]> git.lyx.org Git - lyx.git/blob - src/lyx_cb.C
doubleClick, trippleClick, new UpdateInsetList some other small stuff
[lyx.git] / src / lyx_cb.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich,
7  *          Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include <cctype>
14 #include <unistd.h>
15 #include <csignal>
16 #include <cstring>
17 #include <cstdlib>
18
19 #include <fstream>
20 using std::ifstream;
21
22 #include "LString.h"
23 #include "support/lstrings.h"
24 #include "lyx_main.h"
25 #include FORMS_H_LOCATION
26 #include "lyx.h"
27 #include "layout_forms.h"
28 #include "bullet_forms.h"
29 #include "print_form.h"
30 #include "form1.h"
31 #include "spellchecker.h"
32 #include "version.h"
33 #include "lyx_cb.h"
34 #include "credits.h"
35 #include "insets/insetref.h"
36 #include "insets/insetquotes.h"
37 #include "insets/insetlabel.h"
38 #include "insets/figinset.h"
39 #include "lyxfunc.h"
40 #include "latexoptions.h"
41 #include "lyxfont.h"
42 #include "minibuffer.h"
43 #include "combox.h"
44 #include "bufferlist.h"
45 #include "support/filetools.h"
46 #include "support/path.h"
47 #include "filedlg.h"
48 #include "lyx_gui_misc.h"
49 #include "LyXView.h"
50 #include "lastfiles.h"
51 #include "support/FileInfo.h"
52 #include "debug.h"
53 #include "support/syscall.h"
54 #include "support/lyxlib.h"
55 #include "lyxserver.h"
56 #include "FontLoader.h"
57 #include "lyxrc.h"
58 #include "lyxtext.h"
59 #include "gettext.h"
60 #include "layout.h"
61
62 extern Combox * combo_language;
63 extern BufferList bufferlist;
64 extern void show_symbols_form();
65 extern FD_form_title * fd_form_title;
66 extern FD_form_paragraph * fd_form_paragraph;
67 extern FD_form_character * fd_form_character;
68 extern FD_form_document * fd_form_document;
69 extern FD_form_quotes * fd_form_quotes;
70 extern FD_form_preamble * fd_form_preamble;
71 extern FD_form_table * fd_form_table;
72 extern FD_form_print * fd_form_print;
73 extern FD_form_figure * fd_form_figure;
74 extern FD_form_screen * fd_form_screen;
75 extern FD_form_toc * fd_form_toc;
76 extern FD_form_ref * fd_form_ref;
77 extern FD_LaTeXOptions * fd_latex_options;
78 extern FD_form_bullet * fd_form_bullet;
79
80 extern BufferView * current_view; // called too many times in this file...
81
82 extern void DeleteSimpleCutBuffer(); /* for the cleanup when exiting */
83
84 extern bool send_fax(string const & fname, string const & sendcmd);
85 extern void MenuSendto();
86
87 extern LyXServer * lyxserver;
88 extern FontLoader fontloader;
89
90 // this should be static, but I need it in buffer.C
91 bool quitting;  // flag, that we are quitting the program
92 extern bool finished; // all cleanup done just let it run through now.
93
94 char ascii_type; /* for selection notify callbacks */
95
96 bool scrolling = false;
97
98 char updatetimer = 0;
99
100 /* whether the work area should get callbacks */ 
101 bool input_prohibited = false;
102
103 /* the selection possible is needed, that only motion events are 
104 * used, where the bottom press event was on the drawing area too */
105 bool selection_possible = false;
106
107 // This is used to make the dreaded font toggle problem hopefully go
108 // away. Definitely not the best solution, but I think it sorta works.
109 bool toggleall = true;
110
111 /* 
112    This is the inset locking stuff needed for mathed --------------------
113
114    an inset can simple call LockInset in it's edit call and *ONLY* in it's
115    edit call.
116    Inset::Edit() can only be called by the main lyx module.
117
118    Then the inset may modify the menu's and/or iconbars. 
119
120    Unlocking is either done by LyX or the inset itself with a UnlockInset-call
121
122    During the lock, all button and keyboard events will be modified
123    and send to the inset through the following inset-features. Note that
124    Inset::InsetUnlock will be called from inside UnlockInset. It is meant
125    to contain the code for restoring the menus and things like this.
126
127    
128    virtual void InsetButtonPress(int x, int y, int button);
129    virtual void InsetButtonRelease(int x, int y, int button);
130    virtual void InsetKeyPress(XKeyEvent *ev);
131    virtual void InsetMotionNotify(int x, int y, int state);
132    virtual void InsetUnlock();
133
134    If a inset wishes any redraw and/or update it just has to call
135    UpdateInset(this).
136    It's is completly irrelevant, where the inset is. UpdateInset will
137    find it in any paragraph in any buffer. 
138    Of course the_locking_inset and the insets in the current paragraph/buffer
139    are checked first, so no performance problem should occur.
140    
141    Hope that's ok for the beginning, Alejandro,
142    sorry that I needed so much time,
143
144                   Matthias
145    */
146
147 //void UpdateInset(BufferView * bv, Inset * inset, bool mark_dirty = true);
148
149 /* these functions return 1 if an error occured, 
150    otherwise 0 */
151 // Now they work only for updatable insets. [Alejandro 080596]
152 //int LockInset(UpdatableInset * inset);
153 void ToggleLockedInsetCursor(long x, long y, int asc, int desc);
154 //void FitLockedInsetCursor(long x, long y, int asc, int desc);
155 //int UnlockInset(UpdatableInset * inset);
156 //void LockedInsetStoreUndo(Undo::undo_kind kind);
157
158 /* this is for asyncron updating. UpdateInsetUpdateList will be called
159    automatically from LyX. Just insert the Inset into the Updatelist */
160 //void UpdateInsetUpdateList();
161 //void PutInsetIntoInsetUpdateList(Inset * inset);
162
163 //InsetUpdateStruct * InsetUpdateList = 0;
164
165
166 /*
167   -----------------------------------------------------------------------
168  */
169
170 /* some function prototypes */
171
172 int RunLinuxDoc(int, string const &);
173 int RunDocBook(int, string const &);
174 void MenuWrite(Buffer * buf);
175 void MenuWriteAs(Buffer * buffer);
176 void MenuReload(Buffer * buf);
177 void MenuLayoutSave();
178
179
180 // How should this actually work? Should it prohibit input in all BufferViews,
181 // or just in the current one? If "just the current one", then it should be
182 // placed in BufferView. If "all BufferViews" then LyXGUI (I think) should
183 // run "ProhibitInput" on all LyXViews which will run prohibitInput on all
184 // BufferViews. Or is it perhaps just the (input in) BufferViews in the
185 // current LyxView that should be prohibited (Lgb) (This applies to
186 // "AllowInput" as well.)
187 void ProhibitInput()
188 {
189         input_prohibited = true;
190         current_view->hideCursor();
191
192         static Cursor cursor;
193         static bool cursor_undefined = true;
194    
195         if (cursor_undefined){
196                 cursor = XCreateFontCursor(fl_display, XC_watch);
197                 XFlush(fl_display);
198                 cursor_undefined = false;
199         }
200    
201         /* set the cursor to the watch for all forms and the canvas */ 
202         XDefineCursor(fl_display, current_view->owner()->getForm()->window, 
203                       cursor);
204         if (fd_form_paragraph->form_paragraph->visible)
205                 XDefineCursor(fl_display,
206                               fd_form_paragraph->form_paragraph->window,
207                               cursor);
208         if (fd_form_character->form_character->visible)
209                 XDefineCursor(fl_display,
210                               fd_form_character->form_character->window,
211                               cursor);
212
213         XFlush(fl_display);
214         fl_deactivate_all_forms();
215 }
216
217
218 // Should find a way to move this into BufferView.C
219 void SetXtermCursor(Window win)
220 {
221         static Cursor cursor;
222         static bool cursor_undefined = true;
223         if (cursor_undefined){
224                 cursor = XCreateFontCursor(fl_display, XC_xterm);
225                 XFlush(fl_display);
226                 cursor_undefined = false;
227         }
228         XDefineCursor(fl_display, win, cursor);
229         XFlush(fl_display);
230 }
231
232
233 void AllowInput()
234 {
235         input_prohibited = false;
236
237         /* reset the cursor from the watch for all forms and the canvas */
238    
239         XUndefineCursor(fl_display, current_view->owner()->getForm()->window);
240         if (fd_form_paragraph->form_paragraph->visible)
241                 XUndefineCursor(fl_display,
242                                 fd_form_paragraph->form_paragraph->window);
243         if (fd_form_character->form_character->visible)
244                 XUndefineCursor(fl_display,
245                                 fd_form_character->form_character->window);
246
247         // What to do about this? (Lgb)
248         if (current_view->belowMouse())
249                 SetXtermCursor(current_view->owner()->getForm()->window);
250
251         XFlush(fl_display);
252         fl_activate_all_forms();
253 }
254
255
256 void FreeUpdateTimer()
257 {
258         /* a real free timer would be better but I don't know 
259          * how to do this with xforms */
260         updatetimer = 0;
261 }
262
263
264 void SetUpdateTimer(float time)
265 {
266         fl_set_timer(current_view->owner()->getMainForm()->timer_update, time);
267         updatetimer = 1;
268 }
269
270
271 //
272 // Menu callbacks
273 //
274
275 //
276 // File menu
277 //
278
279 // should be moved to lyxfunc.C
280 void MenuWrite(Buffer * buffer)
281 {
282         XFlush(fl_display);
283         if (!buffer->save(lyxrc->make_backup)) {
284                 string fname = buffer->fileName();
285                 string s = MakeAbsPath(fname);
286                 if (AskQuestion(_("Save failed. Rename and try again?"),
287                                 MakeDisplayPath(s, 50),
288                                 _("(If not, document is not saved.)"))) {
289                         MenuWriteAs(buffer);
290                 }
291         } else {
292                 lastfiles->newFile(buffer->fileName());
293         }
294 }
295
296
297 // should be moved to BufferView.C
298 // Half of this func should be in LyXView, the rest in BufferView.
299 void MenuWriteAs(Buffer * buffer)
300 {
301         // Why do we require BufferView::text to be able to write a
302         // document? I see no point in that. (Lgb)
303         //if (!bv->text) return;
304
305         string fname = buffer->fileName();
306         string oldname = fname;
307         LyXFileDlg fileDlg;
308
309         ProhibitInput();
310         fileDlg.SetButton(0, _("Documents"), lyxrc->document_path);
311         fileDlg.SetButton(1, _("Templates"), lyxrc->template_path);
312
313         if (!IsLyXFilename(fname))
314                 fname += ".lyx";
315
316         fname = fileDlg.Select(_("Enter Filename to Save Document as"), 
317                                OnlyPath(fname),
318                                "*.lyx", 
319                                OnlyFilename(fname));
320         AllowInput();
321
322         if (fname.empty()) {
323                 return;
324         }
325         // Make sure the absolute filename ends with appropriate suffix
326         string s = MakeAbsPath(fname);
327         if (!IsLyXFilename(s))
328                 s += ".lyx";
329
330         // Same name as we have already?
331         if (s == oldname) {
332                 if (!AskQuestion(_("Same name as document already has:"),
333                                  MakeDisplayPath(s, 50),
334                                  _("Save anyway?")))
335                         return;
336                 // Falls through to name change and save
337         } 
338         // No, but do we have another file with this name open?
339         else if (bufferlist.exists(s)) {
340                 if (AskQuestion(_("Another document with same name open!"),
341                                 MakeDisplayPath(s, 50),
342                                 _("Replace with current document?")))
343                         {
344                                 bufferlist.close(bufferlist.getBuffer(s));
345
346                                 // Ok, change the name of the buffer, but don't save!
347                                 buffer->fileName(s);
348                                 buffer->markDirty();
349
350                                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Document renamed to '"),
351                                                 MakeDisplayPath(s),
352                                                 _("', but not saved..."));
353                         }
354                 return;
355         } // Check whether the file exists
356         else {
357                 FileInfo myfile(s);
358                 if (myfile.isOK() && !AskQuestion(_("Document already exists:"), 
359                                                   MakeDisplayPath(s, 50),
360                                                   _("Replace file?")))
361                         return;
362         }
363
364         // Ok, change the name of the buffer
365         buffer->fileName(s);
366         buffer->markDirty();
367         // And save
368         // Small bug: If the save fails, we have irreversible changed the name
369         // of the document.
370         MenuWrite(buffer);
371 }    
372
373
374 int MenuRunLaTeX(Buffer * buffer)
375 {
376         int ret = 0;
377
378         if (buffer->isLinuxDoc())
379                 ret = RunLinuxDoc(1, buffer->fileName());
380         else if (buffer->isLiterate())
381                 ret = buffer->runLiterate();
382         else if (buffer->isDocBook())
383                 ret = RunDocBook(1, buffer->fileName());
384         else
385                 ret = buffer->runLaTeX();
386    
387         if (ret > 0) {
388                 string s;
389                 string t;
390                 if (ret == 1) {
391                         s = _("One error detected");
392                         t = _("You should try to fix it.");
393                 } else {
394                         s += tostr(ret);
395                         s += _(" errors detected.");
396                         t = _("You should try to fix them.");
397                 }
398                 WriteAlert(_("There were errors during the LaTeX run."), s, t);
399         }
400         return ret;
401 }
402
403
404 int MenuBuildProg(Buffer * buffer)
405 {
406         int ret = 0;
407         
408         if (buffer->isLiterate())
409                 ret = buffer->buildProgram();
410         else {
411                 string s = _("Wrong type of document");
412                 string t = _("The Build operation is not allowed in this document");
413                 WriteAlert(_("There were errors during the Build process."), s, t);
414                 return 1;
415         }
416         
417         if (ret > 0) {
418                 string s;
419                 string t;
420                 if (ret == 1) {
421                         s = _("One error detected");
422                         t = _("You should try to fix it.");
423                 } else {
424                         s += tostr(ret);
425                         s += _(" errors detected.");
426                         t = _("You should try to fix them.");
427                 }
428                 WriteAlert(_("There were errors during the Build process."), s, t);
429         }
430         return ret;
431 }
432
433
434 int MenuRunChktex(Buffer * buffer)
435 {
436         int ret;
437
438         if (buffer->isSGML()) {
439                 WriteAlert(_("Chktex does not work with SGML derived documents."));
440                 return 0;
441         } else 
442                 ret = buffer->runChktex();
443    
444         if (ret >= 0) {
445                 string s;
446                 string t;
447                 if (ret == 0) {
448                         s = _("No warnings found.");
449                 } else if (ret == 1) {
450                         s = _("One warning found.");
451                         t = _("Use 'Edit->Go to Error' to find it.");
452                 } else {
453                         s += tostr(ret);
454                         s += _(" warnings found.");
455                         t = _("Use 'Edit->Go to Error' to find them.");
456                 }
457                 WriteAlert(_("Chktex run successfully"), s, t);
458         } else {
459                 WriteAlert(_("Error!"), _("It seems chktex does not work."));
460         }
461         return ret;
462 }
463
464  
465 int MakeLaTeXOutput(Buffer * buffer)
466 {
467         // Who cares?
468         //if (!bv->text)
469         //      return 1;
470         int ret = 0;
471         string path = OnlyPath(buffer->fileName());
472         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
473                 path = buffer->tmppath;
474         }
475         if (!buffer->isDviClean()) {
476                 Path p(path);
477                 ret = MenuRunLaTeX(buffer);
478         }
479         return ret;
480 }
481
482
483 /* wait == false means don't wait for termination */
484 /* wait == true means wait for termination       */
485 // The bool should be placed last on the argument line. (Lgb)
486 // Returns false if we fail.
487 bool RunScript(Buffer * buffer, bool wait,
488                string const & command,
489                string const & orgname = string(),
490                bool need_shell = true)
491 {
492         string path;
493         string cmd;
494         string name = orgname;
495         int result = 0;
496         
497         if (MakeLaTeXOutput(buffer) > 0)
498                 return false;
499         /* get DVI-Filename */
500         if (name.empty())
501                 name = ChangeExtension(buffer->getLatexName(),
502                                        ".dvi", true);
503
504         path = OnlyPath(name);
505         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
506                 path = buffer->tmppath;
507         }
508         Path p(path);
509         // At this point we check whether the command contains the
510         // filename parameter $$FName and if that's the case we
511         // substitute the real file name otherwise the filename is
512         // simply appended. rokrau 1/12/00
513         cmd = command;
514         std::string::size_type i;
515         if ( (i=command.find("$$FName")) != std::string::npos)
516         {
517                 cmd.replace(i,7,QuoteName(name));
518         }
519         else
520                 cmd = command + ' ' + QuoteName(name);
521
522         Systemcalls one;
523
524         if (need_shell) {
525 #ifndef __EMX__
526                 if (!wait)
527                         cmd += " &";
528 #else
529                 // OS/2 cmd.exe has another use for '&'
530                 if (!wait) {
531                         // This is not NLS safe, but it's OK, I think.
532                         string sh = OnlyFilename(GetEnvPath("EMXSHELL"));
533                         if (sh.empty()) {
534                                 // COMSPEC is set, unless user unsets 
535                                 sh = OnlyFilename(GetEnvPath("COMSPEC"));
536                                 if (sh.empty())
537                                         sh = "cmd.exe";
538                         }
539                         sh = lowercase(sh);
540                         if (contains(sh, "cmd.exe")
541                             || contains(sh, "4os2.exe"))
542                                 cmd = "start /min/n " + cmd;
543                         else
544                                 cmd += " &";
545                 }
546 #endif
547                 // It seems that, if wait is false, we never get back
548                 // the return code of the command. This means that all
549                 // the code I added in PrintApplyCB is currently
550                 // useless...
551 #ifdef WITH_WARNINGS
552 #warning What should we do here?
553 #endif          
554                 buffer->getUser()->owner()->getMiniBuffer()->Set(
555                         _("Executing command:"), cmd);
556                 result = one.startscript(Systemcalls::System, cmd);
557         } else {
558                 buffer->getUser()->owner()->getMiniBuffer()->Set(
559                         _("Executing command:"), cmd);
560                 result = one.startscript(wait ? Systemcalls::Wait
561                                          : Systemcalls::DontWait, cmd);
562         }
563         return result == 0;
564 }
565
566
567 // Returns false if we fail
568 bool CreatePostscript(Buffer * buffer, bool wait = false)
569 {
570         // Who cares?
571         //if (!bv->text)
572         //      return false;
573
574         ProhibitInput();
575
576         // Generate dvi file
577         if (MakeLaTeXOutput(buffer) > 0) {
578                 AllowInput();
579                 return false;
580         }
581         // Generate postscript file
582         string psname = ChangeExtension (buffer->fileName(),
583                                          ".ps_tmp", true);
584
585         string paper;
586
587         // Wrong type
588         char real_papersize = buffer->params.papersize;
589         if (real_papersize == BufferParams::PAPER_DEFAULT)
590                 real_papersize = lyxrc->default_papersize;
591
592         switch (real_papersize) {
593         case BufferParams::PAPER_USLETTER:
594                 paper = "letter";
595                 break;
596         case BufferParams::PAPER_A3PAPER:
597                 paper = "a3";
598                 break;
599         case BufferParams::PAPER_A4PAPER:
600                 paper = "a4";
601                 break;
602         case BufferParams::PAPER_A5PAPER:
603                 paper = "a5";
604                 break;
605         case BufferParams::PAPER_B5PAPER:
606                 paper = "b5";
607                 break;
608         case BufferParams::PAPER_EXECUTIVEPAPER:
609                 paper = "foolscap";
610                 break;
611         case BufferParams::PAPER_LEGALPAPER:
612                 paper = "legal";
613                 break;
614         default: /* If nothing else fits, keep an empty value... */
615                 break;
616         }
617
618         // Make postscript file.
619         string command = lyxrc->dvi_to_ps_command + ' ' + lyxrc->print_to_file + ' ';
620         command += QuoteName(psname);
621         if (buffer->params.use_geometry
622             && buffer->params.papersize2 == BufferParams::VM_PAPER_CUSTOM
623             && !lyxrc->print_paper_dimension_flag.empty()
624             && !buffer->params.paperwidth.empty()
625             && !buffer->params.paperheight.empty()) {
626                 // using a custom papersize
627                 command += ' ';
628                 command += lyxrc->print_paper_dimension_flag + ' ';
629                 command += buffer->params.paperwidth + ',';
630                 command += buffer->params.paperheight;
631         } else if (!paper.empty()
632                    && (real_papersize != BufferParams::PAPER_USLETTER ||
633                        buffer->params.orientation == BufferParams::ORIENTATION_PORTRAIT)) {
634                 // dvips won't accept -t letter -t landscape.  In all other
635                 // cases, include the paper size explicitly.
636                 command += ' ';
637                 command += lyxrc->print_paper_flag + ' ' + paper;
638         }
639         if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE) {
640                 command += ' ';
641                 command += lyxrc->print_landscape_flag;
642         }
643         // push directorypath, if necessary 
644         string path = OnlyPath(buffer->fileName());
645         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)){
646                 path = buffer->tmppath;
647         }
648         Path p(path);
649         bool ret = RunScript(buffer, wait, command);
650         AllowInput();
651         return ret;
652 }
653
654
655 // Returns false if we fail
656 //bool MenuPreviewPS(Buffer * buffer)
657 bool PreviewPostscript(Buffer * buffer)
658 {
659         // Who cares?
660         //if (!bv->text)
661         //      return false;
662
663         // Generate postscript file
664         if (!CreatePostscript(buffer, true)) {
665                 return false;
666         }
667
668         // Start postscript viewer
669         ProhibitInput();
670         string ps = ChangeExtension (buffer->fileName(),
671                                      ".ps_tmp", true);
672         // push directorypath, if necessary 
673         string path = OnlyPath(buffer->fileName());
674         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)){
675                 path = buffer->tmppath;
676         }
677         Path p(path);
678         bool ret = RunScript(buffer, false, lyxrc->view_ps_command, ps);
679         AllowInput();
680         return ret;
681 }
682
683
684 void MenuFax(Buffer * buffer)
685 {
686         // Who cares?
687         //if (!bv->text)
688         //      return;
689
690         // Generate postscript file
691         if (!CreatePostscript(buffer, true)) {
692                 return;
693         }
694
695         // Send fax
696         string ps = ChangeExtension (buffer->fileName(), ".ps_tmp", true);
697         string path = OnlyPath (buffer->fileName());
698         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
699                 path = buffer->tmppath;
700         }
701         Path p(path);
702         if (!lyxrc->fax_program.empty()) {
703                 string help2 = subst(lyxrc->fax_program, "$$FName", ps);
704                 help2 += " &";
705                 Systemcalls one(Systemcalls::System, help2);
706         } else
707                 send_fax(ps, lyxrc->fax_command);
708 }
709
710
711 // Returns false if we fail
712 bool PreviewDVI(Buffer * buffer)
713 {
714         // Who cares?
715         //if (!bv->text)
716         //      return false;
717
718         string paper = lyxrc->view_dvi_paper_option;
719         if (!paper.empty()) {
720                 // wrong type
721                 char real_papersize = buffer->params.papersize;
722                 if (real_papersize == BufferParams::PAPER_DEFAULT)
723                         real_papersize = lyxrc->default_papersize;
724   
725                 switch (real_papersize) {
726                 case BufferParams::PAPER_USLETTER:
727                         paper += " us";
728                         break;
729                 case BufferParams::PAPER_A3PAPER:
730                         paper += " a3";
731                         break;
732                 case BufferParams::PAPER_A4PAPER:
733                         paper += " a4";
734                         break;
735                 case BufferParams::PAPER_A5PAPER:
736                         paper += " a5";
737                         break;
738                 case BufferParams::PAPER_B5PAPER:
739                         paper += " b5";
740                         break;
741                 case BufferParams::PAPER_EXECUTIVEPAPER:
742                         paper += " foolscap";
743                         break;
744                 case BufferParams::PAPER_LEGALPAPER:
745                         paper += " legal";
746                         break;
747                 default: /* If nothing else fits, keep the empty value */
748                         break;
749                 }
750                 if (real_papersize==' ') {
751                         //      if (paper.empty()) {
752                         if (buffer->params.orientation 
753                             == BufferParams::ORIENTATION_LANDSCAPE)
754                           // we HAVE to give a size when the page is in
755                           // landscape, so use USletter.          
756                                 paper = " -paper usr";
757                 } else {
758                         // paper = " -paper " + paper;
759                         if (buffer->params.orientation 
760                             == BufferParams::ORIENTATION_LANDSCAPE)
761                                paper+= 'r';
762                 }
763         }
764         // push directorypath, if necessary 
765         string path = OnlyPath(buffer->fileName());
766         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
767                 path = buffer->tmppath;
768         }
769         Path p(path);
770         // Run dvi-viewer
771         string command = lyxrc->view_dvi_command + " " + paper;
772         bool ret = RunScript(buffer, false, command);
773         return ret;
774 }
775
776
777 void MenuMakeLaTeX(Buffer * buffer)
778 {
779         // Why care about this?
780         //if (!bv->text)
781         //      return;
782         
783         // Get LaTeX-Filename
784         string s = buffer->getLatexName(false);
785         
786         FileInfo fi(s);
787         if (fi.readable() &&
788             !AskQuestion(_("File already exists:"), 
789                          MakeDisplayPath(s, 50),
790                          _("Do you want to overwrite the file?"))) {
791                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Canceled"));
792                 return;
793         }
794         
795         if (buffer->isDocBook())
796                 buffer->getUser()->owner()->getMiniBuffer()->Set(
797                         _("DocBook does not have a latex backend"));
798         else {
799                 if (buffer->isLinuxDoc())
800                         RunLinuxDoc(0, buffer->fileName());
801                 else
802                         buffer->makeLaTeXFile(s, string(), true);
803                 buffer->getUser()->owner()->getMiniBuffer()->Set(
804                         _("Nice LaTeX file saved as"), MakeDisplayPath(s));
805                 buffer->markDviDirty();
806         }
807 }
808
809
810 void MenuMakeLinuxDoc(Buffer * buffer)
811 {
812         // Who cares?
813         //if (!bv->text) return;
814         
815         if (!buffer->isLinuxDoc()) {
816                 WriteAlert(_("Error!"), _("Document class must be linuxdoc."));
817                 return;
818         }
819         
820         // Get LinuxDoc-Filename
821         string s = ChangeExtension(buffer->fileName(), 
822                                    ".sgml", false);
823         
824         FileInfo fi(s);
825         if (fi.readable() &&
826             !AskQuestion(_("File already exists:"), 
827                          MakeDisplayPath(s, 50),
828                          _("Do you want to overwrite the file?"))) {
829                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Canceled"));
830                 return;
831         }
832         
833         buffer->getUser()->owner()->getMiniBuffer()->Set(_("Building LinuxDoc SGML file `"),
834                                           MakeDisplayPath(s),"'...");
835         
836         buffer->makeLinuxDocFile(s, 65);
837         buffer->redraw();
838         buffer->getUser()->owner()->getMiniBuffer()->Set(_("LinuxDoc SGML file save as"),
839                                           MakeDisplayPath(s)); 
840 }
841
842
843 void MenuMakeDocBook(Buffer * buffer)
844 {
845         // Who cares?
846         //if (!bv->text) return;
847         
848         if (!buffer->isDocBook()) {
849                 WriteAlert(_("Error!"),
850                            _("Document class must be docbook."));
851                 return;
852         }
853         
854         // Get DocBook-Filename
855         string s = ChangeExtension(buffer->fileName(), 
856                                    ".sgml", false);
857         
858         FileInfo fi(s);
859         if (fi.readable() &&
860             !AskQuestion(_("File already exists:"), 
861                          MakeDisplayPath(s, 50),
862                          _("Do you want to overwrite the file?"))) {
863                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Canceled"));
864                 return;
865         }
866         
867         buffer->getUser()->owner()->getMiniBuffer()->Set(_("Building DocBook SGML file `"),
868                                           MakeDisplayPath(s), "'..."); 
869         
870         buffer->makeDocBookFile(s, 65);
871         buffer->redraw();
872         buffer->getUser()->owner()->getMiniBuffer()->Set(_("DocBook SGML file save as"),
873                                           MakeDisplayPath(s)); 
874 }
875
876
877 void MenuMakeAscii(Buffer * buffer)
878 {
879         // Who cares?
880         //if (!bv->text) return;
881         
882         /* get LaTeX-Filename */
883         string s = ChangeExtension (buffer->fileName(),
884                                     ".txt", false);
885         
886         FileInfo fi(s);
887         if (fi.readable() &&
888             !AskQuestion(_("File already exists:"), 
889                          MakeDisplayPath(s, 50),
890                          _("Do you want to overwrite the file?"))) {
891                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Canceled"));
892                 return;
893         }
894         
895         buffer->writeFileAscii(s, lyxrc->ascii_linelen);
896         
897         buffer->getUser()->owner()->getMiniBuffer()->Set(_("Ascii file saved as"), MakeDisplayPath(s));
898 }
899
900
901 void MenuPrint(Buffer * buffer)
902 {
903         // Who cares?
904         //if (!bv->text)
905         //      return;
906
907         string input_file = ChangeExtension(buffer->fileName(),
908                                             lyxrc->print_file_extension,
909                                             true);
910         fl_set_input(fd_form_print->input_file, input_file.c_str());
911         
912         if (fd_form_print->form_print->visible) {
913                 fl_raise_form(fd_form_print->form_print);
914         } 
915         else {
916                 fl_show_form(fd_form_print->form_print,
917                              FL_PLACE_MOUSE, FL_FULLBORDER,
918                              _("Print"));
919         }
920 }
921
922 void MenuMakeHTML(Buffer * buffer)
923 {
924         // First, create LaTeX file
925         MenuMakeLaTeX(buffer);
926
927         // And now, run the converter
928         string file = buffer->fileName();
929         Path path(OnlyPath(file));
930         // the tex file name has to be correct for
931         // latex, but the html file name can be
932         // anything.
933         string result = ChangeExtension(file, ".html", false);
934         string infile = buffer->getLatexName(false);
935         string tmp = lyxrc->html_command;
936         tmp = subst(tmp, "$$FName", infile);
937         tmp = subst(tmp, "$$OutName", result);
938         Systemcalls one;
939         int res = one.startscript(Systemcalls::System, tmp);
940         if (res == 0) {
941                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Document exported as HTML to file `")
942                                                   + MakeDisplayPath(result) +'\'');
943         } else {
944                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Unable to convert to HTML the file `")
945                                                   + MakeDisplayPath(infile) 
946                                                   + '\'');
947         }
948
949 }
950
951 void MenuExport(Buffer * buffer, string const & extyp) 
952 {
953         // latex
954         if (extyp == "latex") {
955                 // make sure that this buffer is not linuxdoc
956                 MenuMakeLaTeX(buffer);
957         }
958         // linuxdoc
959         else if (extyp == "linuxdoc") {
960                 // make sure that this buffer is not latex
961                 MenuMakeLinuxDoc(buffer);
962         }
963         // docbook
964         else if (extyp == "docbook") {
965                 // make sure that this buffer is not latex or linuxdoc
966                 MenuMakeDocBook(buffer);
967         }
968         // dvi
969         else if (extyp == "dvi") {
970                 // Run LaTeX as "Update dvi..." Bernhard.
971                 // We want the dvi in the current directory. This
972                 // is achieved by temporarily disabling use of
973                 // temp directory. As a side-effect, we get
974                 // *.log and *.aux files also. (Asger)
975                 bool flag = lyxrc->use_tempdir;
976                 lyxrc->use_tempdir = false;
977                 MenuRunLaTeX(buffer);
978                 lyxrc->use_tempdir = flag;
979         }
980         // postscript
981         else if (extyp == "postscript") {
982                 // Start Print-dialog. Not as good as dvi... Bernhard.
983                 MenuPrint(buffer);
984                 // Since the MenuPrint is a pop-up, we can't use
985                 // the same trick as above. (Asger)
986                 // MISSING: Move of ps-file :-(
987                 // And MenuPrint should not be used for this at all...
988         }
989         // ascii
990         else if (extyp == "ascii") {
991                 MenuMakeAscii(buffer);
992         }
993         else if (extyp == "custom") {
994                 MenuSendto();
995         }
996         // HTML
997         else if (extyp == "html") {
998                 MenuMakeHTML(buffer);
999         }
1000         else {
1001                 buffer->getUser()->owner()->getMiniBuffer()->Set(_("Unknown export type: ") + extyp);
1002         }
1003 }
1004
1005
1006 void QuitLyX()
1007 {
1008         lyxerr.debug() << "Running QuitLyX." << endl;
1009
1010         if (!bufferlist.QwriteAll())
1011                 return;
1012
1013         lastfiles->writeFile(lyxrc->lastfiles);
1014
1015         // Set a flag that we do quitting from the program,
1016         // so no refreshes are necessary.
1017         quitting = true;
1018
1019         // close buffers first
1020         bufferlist.closeAll();
1021
1022         // do any other cleanup procedures now
1023         lyxerr.debug() << "Deleting tmp dir " << system_tempdir << endl;
1024
1025         DestroyLyXTmpDir(system_tempdir);
1026
1027         finished = true;
1028 }
1029
1030
1031
1032 void AutoSave()
1033         // should probably be moved into BufferList (Lgb)
1034         // Perfect target for a thread...
1035 {
1036         if (!current_view->available())
1037                 return;
1038
1039         if (current_view->buffer()->isBakClean()
1040             || current_view->buffer()->isReadonly()) {
1041                 // We don't save now, but we'll try again later
1042                 current_view->owner()->resetAutosaveTimer();
1043                 return;
1044         }
1045
1046         current_view->owner()->getMiniBuffer()->Set(_("Autosaving current document..."));
1047         
1048         // create autosave filename
1049         string fname =  OnlyPath(current_view->buffer()->fileName());
1050         fname += "#";
1051         fname += OnlyFilename(current_view->buffer()->fileName());
1052         fname += "#";
1053         
1054         // tmp_ret will be located (usually) in /tmp
1055         // will that be a problem?
1056         string tmp_ret = tmpnam(0);
1057         
1058         pid_t pid = fork(); // If you want to debug the autosave
1059         // you should set pid to -1, and comment out the
1060         // fork.
1061         if (pid == 0 || pid == -1) {
1062                 // pid = -1 signifies that lyx was unable
1063                 // to fork. But we will do the save
1064                 // anyway.
1065                 bool failed = false;
1066                 if (!tmp_ret.empty()) {
1067                         current_view->buffer()->writeFile(tmp_ret, 1);
1068                         // assume successful write of tmp_ret
1069                         if (rename(tmp_ret.c_str(), fname.c_str()) == -1) {
1070                                 failed = true;
1071                                 // most likely couldn't move between filesystems
1072                                 // unless write of tmp_ret failed
1073                                 // so remove tmp file (if it exists)
1074                                 remove(tmp_ret.c_str());
1075                         }
1076                 } else {
1077                         failed = true;
1078                 }
1079                 
1080                 if (failed) {
1081                         // failed to write/rename tmp_ret so try writing direct
1082                         if (!current_view->buffer()->writeFile(fname, 1)) {
1083                                 // It is dangerous to do this in the child,
1084                                 // but safe in the parent, so...
1085                                 if (pid == -1)
1086                                         current_view->owner()->getMiniBuffer()->Set(_("Autosave Failed!"));
1087                         }
1088                 }
1089                 if (pid == 0) { // we are the child so...
1090                         _exit(0);
1091                 }
1092         }
1093         
1094         current_view->buffer()->markBakClean();
1095         current_view->owner()->resetAutosaveTimer();
1096 }
1097
1098
1099 //
1100 // (c) CHT Software Service GmbH
1101 // Uwe C. Schroeder
1102 //
1103 // create new file with template
1104 // SERVERCMD !
1105 //
1106 Buffer * NewLyxFile(string const & filename)
1107 {
1108         // Split argument by :
1109         string name;
1110         string tmpname = split(filename, name, ':');
1111 #ifdef __EMX__ // Fix me! lyx_cb.C may not be low level enough to allow this.
1112         if (name.length() == 1
1113             && isalpha(static_cast<unsigned char>(name[0]))
1114             && (prefixIs(tmpname, "/") || prefixIs(tmpname, "\\"))) {
1115                 name += ':';
1116                 name += token(tmpname, ':', 0);
1117                 tmpname = split(tmpname, ':');
1118         }
1119 #endif
1120         lyxerr.debug() << "Arg is " << filename
1121                        << "\nName is " << name
1122                        << "\nTemplate is " << tmpname << endl;
1123
1124         // find a free buffer 
1125         Buffer * tmpbuf = bufferlist.newFile(name, tmpname);
1126         if (tmpbuf)
1127                 lastfiles->newFile(tmpbuf->fileName());
1128         return tmpbuf;
1129 }
1130
1131
1132 // Insert ascii file (if filename is empty, prompt for one)
1133 void InsertAsciiFile(string const & f, bool asParagraph)
1134 {
1135         string fname = f;
1136         LyXFileDlg fileDlg;
1137  
1138         if (!current_view->available()) return;
1139      
1140         if (fname.empty()) {
1141                 ProhibitInput();
1142                 fname = fileDlg.Select(_("File to Insert"), 
1143                                        current_view->owner()->buffer()->filepath,
1144                                        "*");
1145                 AllowInput();
1146                 if (fname.empty()) return;
1147         }
1148
1149         FileInfo fi(fname);
1150
1151         if (!fi.readable()) {
1152                 WriteFSAlert(_("Error! Specified file is unreadable: "),
1153                              MakeDisplayPath(fname, 50));
1154                 return;
1155         }
1156
1157         ifstream ifs(fname.c_str());
1158         if (!ifs) {
1159                 WriteFSAlert(_("Error! Cannot open specified file: "),
1160                              MakeDisplayPath(fname, 50));
1161                 return;
1162         }
1163         LyXParagraph * tmppar = new LyXParagraph;
1164         tmppar->readSimpleWholeFile(ifs);
1165         
1166         // set the end of the string
1167 #ifdef WITH_WARNINGS
1168 #warning why do we do this?
1169 #endif
1170         // I don't think this is needed. Actually it might be plain wrong.
1171         tmppar->InsertChar(tmppar->text.size() - 1, '\0');
1172
1173         // insert the string
1174         current_view->hideCursor();
1175         
1176         // clear the selection
1177         current_view->beforeChange();
1178         if (!asParagraph)
1179                 current_view->text->InsertStringA(tmppar->text);
1180         else
1181                 current_view->text->InsertStringB(tmppar->text);
1182         delete tmppar;
1183         current_view->update(1);
1184 }
1185
1186
1187 void MenuShowTableOfContents()
1188 {
1189         static int ow = -1, oh;
1190
1191         TocUpdateCB(0, 0);
1192         if (fd_form_toc->form_toc->visible) {
1193                 fl_raise_form(fd_form_toc->form_toc);
1194         } else {
1195                 fl_show_form(fd_form_toc->form_toc,
1196                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
1197                              _("Table Of Contents"));
1198                 if (ow < 0) {
1199                         ow = fd_form_toc->form_toc->w;
1200                         oh = fd_form_toc->form_toc->h;
1201                 }
1202                 fl_set_form_minsize(fd_form_toc->form_toc, ow, oh);
1203         }
1204 }
1205
1206
1207 void MenuInsertLabel(char const * arg)
1208 {
1209         string label = arg;
1210         ProhibitInput();
1211         if (label.empty()) {
1212                 pair<bool, string>
1213                         result = askForText(_("Enter new label to insert:"));
1214                 if (result.first) {
1215                         label = frontStrip(strip(result.second));
1216                 }
1217         }
1218         if (!label.empty()) {
1219                 InsetLabel * new_inset = new InsetLabel;
1220                 new_inset->setContents(label);
1221                 current_view->insertInset(new_inset);
1222         }
1223         AllowInput();
1224 }
1225
1226
1227 void MenuInsertRef()
1228 {
1229         static int ow = -1, oh;
1230
1231         RefUpdateCB(0, 0);
1232         if (fd_form_ref->form_ref->visible) {
1233                 fl_raise_form(fd_form_ref->form_ref);
1234         } else {
1235                 fl_show_form(fd_form_ref->form_ref,
1236                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
1237                              _("Insert Reference"));
1238                 if (ow < 0) {
1239                         ow = fd_form_ref->form_ref->w;
1240                         oh = fd_form_ref->form_ref->h;
1241                 }
1242                 fl_set_form_minsize(fd_form_ref->form_ref, ow, oh);
1243         }
1244 }
1245
1246
1247 void MenuPasteSelection(char at)
1248 {
1249         if (!current_view->available())
1250                 return;
1251
1252         ascii_type = at;
1253   
1254         Atom data_prop = XInternAtom(fl_display, 
1255                                      "LyX_Primary",
1256                                      false);
1257         if (data_prop == None) 
1258                 return;
1259         XConvertSelection(fl_display,
1260                           XA_PRIMARY, XA_STRING, data_prop, 
1261                           current_view->owner()->getForm()->window, 0);
1262         XFlush(fl_display);
1263 }
1264
1265
1266 // candidate for move to BufferView
1267 void Foot(BufferView * bv)
1268 {
1269         if (!bv->available()) 
1270                 return;
1271         
1272         bv->owner()->getMiniBuffer()
1273                 ->Set(_("Inserting Footnote..."));
1274         bv->hideCursor();
1275         bv->update(-2);
1276         bv->text->InsertFootnoteEnvironment(LyXParagraph::FOOTNOTE);
1277         bv->update(1);
1278 }
1279
1280
1281 // candidate for move to LyXView
1282 // This is only used in toolbar.C
1283 void LayoutsCB(int sel, void *)
1284 {
1285         string tmp = tostr(sel);
1286         current_view->owner()->getLyXFunc()->Dispatch(LFUN_LAYOUTNO,
1287                                                       tmp.c_str());
1288 }
1289
1290
1291 /*
1292  * SGML Linuxdoc support:
1293  * (flag == -1) import SGML file
1294  * (flag == 0) make TeX output
1295  * (flag == 1) make dvi output
1296  */
1297 int RunLinuxDoc(int flag, string const & filename)
1298 {
1299         string name;
1300         string s2;
1301         string path;
1302         string add_flags;
1303
1304         int errorcode = 0;
1305
1306         /* generate a path-less extension name */
1307         name = ChangeExtension (filename, ".sgml", true);
1308         path = OnlyPath (filename);
1309         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
1310                 path = current_view->buffer()->tmppath;
1311         }
1312         Path p(path);
1313         
1314         if (flag != -1) {
1315                 if (!current_view->available())
1316                         return 0;
1317                 current_view->buffer()->makeLinuxDocFile(name, 0);
1318 #ifdef WITH_WARNINGS
1319 #warning remove this once we have a proper geometry class
1320 #endif
1321                 BufferParams::PAPER_SIZE ps = static_cast<BufferParams::PAPER_SIZE>(current_view->buffer()->params.papersize);
1322                 switch (ps) {
1323                 case BufferParams::PAPER_A4PAPER:
1324                         add_flags = "-p a4";
1325                         break;
1326                 case BufferParams::PAPER_USLETTER:
1327                         add_flags = "-p letter";
1328                         break;
1329                 default: /* nothing to be done yet ;-) */     break; 
1330                 }
1331         }
1332         
1333         ProhibitInput();
1334         
1335         Systemcalls one;
1336         switch (flag) {
1337         case -1: /* Import file */
1338                 current_view->owner()->getMiniBuffer()->Set(_("Importing LinuxDoc SGML file `"), 
1339                                 MakeDisplayPath(filename), "'...");
1340                 s2 = "sgml2lyx " + lyxrc->sgml_extra_options + ' ' 
1341                         + name;
1342                 if (one.startscript(Systemcalls::System, s2)) 
1343                         errorcode = 1;
1344                 break;
1345         case 0: /* TeX output asked */
1346                 current_view->owner()->getMiniBuffer()->Set(_("Converting LinuxDoc SGML to TeX file..."));
1347                 s2 = "sgml2latex " + add_flags + " -o tex "
1348                         + lyxrc->sgml_extra_options + ' ' + name;
1349                 if (one.startscript(Systemcalls::System, s2)) 
1350                         errorcode = 1;
1351                 break;
1352         case 1: /* dvi output asked */
1353                 current_view->owner()->getMiniBuffer()->Set(_("Converting LinuxDoc SGML to dvi file..."));
1354                 s2 = "sgml2latex " + add_flags + " -o dvi "
1355                         + lyxrc->sgml_extra_options + ' ' + name;
1356                 if (one.startscript(Systemcalls::System, s2)) {
1357                         errorcode = 1;
1358                 } else
1359                         current_view->buffer()->markDviClean();
1360                 break;
1361         default: /* unknown output */
1362                 break;
1363         }
1364         
1365         AllowInput();
1366
1367         current_view->buffer()->redraw();
1368         return errorcode;
1369 }
1370
1371
1372 /*
1373  * SGML DocBook support:
1374  * (flag == 1) make dvi output
1375  */
1376 int RunDocBook(int flag, string const & filename)
1377 {
1378         /* generate a path-less extension name */
1379         string name = ChangeExtension (filename, ".sgml", true);
1380         string path = OnlyPath (filename);
1381         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
1382                 path = current_view->buffer()->tmppath;
1383         }
1384         Path p(path);
1385
1386         if (!current_view->available())
1387                 return 0;
1388         
1389         current_view->buffer()->makeDocBookFile(name, 0);
1390
1391         // Shall this code go or should it stay? (Lgb)
1392 //      string add_flags;
1393 //      LYX_PAPER_SIZE ps = (LYX_PAPER_SIZE) current_view->buffer()->params.papersize;
1394 //      switch (ps) {
1395 //      case BufferParams::PAPER_A4PAPER:  add_flags = "-p a4";     break;
1396 //      case BufferParams::PAPER_USLETTER: add_flags = "-p letter"; break;
1397 //      default: /* nothing to be done yet ;-) */     break; 
1398 //      }
1399         ProhibitInput();
1400         
1401         int errorcode = 0;
1402         Systemcalls one;
1403         switch (flag) {
1404         case 1: /* dvi output asked */
1405         {
1406                 current_view->owner()->getMiniBuffer()->Set(_("Converting DocBook SGML to dvi file..."));
1407                 string s2 = "sgmltools --backend dvi " + name;
1408                 if (one.startscript(Systemcalls::System, s2)) {
1409                         errorcode = 1;
1410                 } else
1411                         current_view->buffer()->markDviClean();
1412         }
1413         break;
1414         default: /* unknown output */
1415                 break;
1416         }
1417         
1418         AllowInput();
1419
1420         current_view->buffer()->redraw();
1421         return errorcode;
1422 }
1423
1424
1425 void MenuLayoutCharacter()
1426 {
1427         static int ow = -1, oh;
1428
1429         if (fd_form_character->form_character->visible) {
1430                 fl_raise_form(fd_form_character->form_character);
1431         } else {
1432                 fl_show_form(fd_form_character->form_character,
1433                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
1434                              _("Character Style"));
1435                 if (ow < 0) {
1436                         ow = fd_form_character->form_character->w;
1437                         oh = fd_form_character->form_character->h;
1438                 }
1439                 fl_set_form_minsize(fd_form_character->form_character, ow, oh);
1440         }
1441 }
1442
1443
1444 inline void DeactivateParagraphButtons ()
1445 {
1446         fl_deactivate_object (fd_form_paragraph->button_ok);
1447         fl_deactivate_object (fd_form_paragraph->button_apply);
1448         fl_set_object_lcol (fd_form_paragraph->button_ok, FL_INACTIVE);
1449         fl_set_object_lcol (fd_form_paragraph->button_apply, FL_INACTIVE);
1450 }
1451
1452
1453 inline void ActivateParagraphButtons ()
1454 {
1455         fl_activate_object (fd_form_paragraph->button_ok);
1456         fl_activate_object (fd_form_paragraph->button_apply);
1457         fl_set_object_lcol (fd_form_paragraph->button_ok, FL_BLACK);
1458         fl_set_object_lcol (fd_form_paragraph->button_apply, FL_BLACK);
1459 }
1460
1461
1462 inline void DisableParagraphLayout ()
1463 {
1464         DeactivateParagraphButtons();
1465         fl_deactivate_object (fd_form_paragraph->input_labelwidth);
1466         fl_deactivate_object (fd_form_paragraph->check_lines_top);
1467         fl_deactivate_object (fd_form_paragraph->check_lines_bottom);
1468         fl_deactivate_object (fd_form_paragraph->check_pagebreaks_top);
1469         fl_deactivate_object (fd_form_paragraph->check_pagebreaks_bottom);
1470         fl_deactivate_object (fd_form_paragraph->check_noindent);
1471         fl_deactivate_object (fd_form_paragraph->group_radio_alignment);
1472         fl_deactivate_object (fd_form_paragraph->radio_align_right);
1473         fl_deactivate_object (fd_form_paragraph->radio_align_left);
1474         fl_deactivate_object (fd_form_paragraph->radio_align_block);
1475         fl_deactivate_object (fd_form_paragraph->radio_align_center);
1476         fl_deactivate_object (fd_form_paragraph->input_space_above);
1477         fl_deactivate_object (fd_form_paragraph->input_space_below);
1478         fl_deactivate_object (fd_form_paragraph->choice_space_above);
1479         fl_deactivate_object (fd_form_paragraph->choice_space_below);
1480         fl_deactivate_object (fd_form_paragraph->check_space_above);
1481         fl_deactivate_object (fd_form_paragraph->check_space_below);
1482 }
1483
1484
1485 inline void EnableParagraphLayout ()
1486 {
1487         ActivateParagraphButtons();
1488         fl_activate_object (fd_form_paragraph->input_labelwidth);
1489         fl_activate_object (fd_form_paragraph->check_lines_top);
1490         fl_activate_object (fd_form_paragraph->check_lines_bottom);
1491         fl_activate_object (fd_form_paragraph->check_pagebreaks_top);
1492         fl_activate_object (fd_form_paragraph->check_pagebreaks_bottom);
1493         fl_activate_object (fd_form_paragraph->check_noindent);
1494         fl_activate_object (fd_form_paragraph->group_radio_alignment);
1495         fl_activate_object (fd_form_paragraph->radio_align_right);
1496         fl_activate_object (fd_form_paragraph->radio_align_left);
1497         fl_activate_object (fd_form_paragraph->radio_align_block);
1498         fl_activate_object (fd_form_paragraph->radio_align_center);
1499         fl_activate_object (fd_form_paragraph->input_space_above);
1500         fl_activate_object (fd_form_paragraph->input_space_below);
1501         fl_activate_object (fd_form_paragraph->choice_space_above);
1502         fl_activate_object (fd_form_paragraph->choice_space_below);
1503         fl_activate_object (fd_form_paragraph->check_space_above);
1504         fl_activate_object (fd_form_paragraph->check_space_below);
1505 }
1506
1507
1508 bool UpdateLayoutParagraph()
1509 {
1510         if (!current_view->available()) {
1511                 if (fd_form_paragraph->form_paragraph->visible) 
1512                         fl_hide_form(fd_form_paragraph->form_paragraph);
1513                 return false;
1514         }
1515
1516         Buffer * buf = current_view->buffer();
1517
1518         fl_set_input(fd_form_paragraph->input_labelwidth,
1519                      current_view->text->cursor.par->GetLabelWidthString().c_str());
1520         fl_set_button(fd_form_paragraph->radio_align_right, 0);
1521         fl_set_button(fd_form_paragraph->radio_align_left, 0);
1522         fl_set_button(fd_form_paragraph->radio_align_center, 0);
1523         fl_set_button(fd_form_paragraph->radio_align_block, 0);
1524
1525         int align = current_view->text->cursor.par->GetAlign();
1526         if (align == LYX_ALIGN_LAYOUT)
1527                 align = textclasslist.Style(buf->params.textclass,
1528                                             current_view->text->cursor.par->GetLayout()).align;
1529          
1530         switch (align) {
1531         case LYX_ALIGN_RIGHT:
1532                 fl_set_button(fd_form_paragraph->radio_align_right, 1);
1533                 break;
1534         case LYX_ALIGN_LEFT:
1535                 fl_set_button(fd_form_paragraph->radio_align_left, 1);
1536                 break;
1537         case LYX_ALIGN_CENTER:
1538                 fl_set_button(fd_form_paragraph->radio_align_center, 1);
1539                 break;
1540         default:
1541                 fl_set_button(fd_form_paragraph->radio_align_block, 1);
1542                 break;
1543         }
1544          
1545         fl_set_button(fd_form_paragraph->check_lines_top,
1546                       current_view->text->cursor.par->FirstPhysicalPar()->line_top);
1547         fl_set_button(fd_form_paragraph->check_lines_bottom,
1548                       current_view->text->cursor.par->FirstPhysicalPar()->line_bottom);
1549         fl_set_button(fd_form_paragraph->check_pagebreaks_top,
1550                       current_view->text->cursor.par->FirstPhysicalPar()->pagebreak_top);
1551         fl_set_button(fd_form_paragraph->check_pagebreaks_bottom,
1552                       current_view->text->cursor.par->FirstPhysicalPar()->pagebreak_bottom);
1553         fl_set_button(fd_form_paragraph->check_noindent,
1554                       current_view->text->cursor.par->FirstPhysicalPar()->noindent);
1555         fl_set_input (fd_form_paragraph->input_space_above, "");
1556         
1557         switch (current_view->text->cursor.par->FirstPhysicalPar()->added_space_top.kind()) {
1558         case VSpace::NONE:
1559                 fl_set_choice (fd_form_paragraph->choice_space_above, 1);
1560                 break;
1561         case VSpace::DEFSKIP:
1562                 fl_set_choice (fd_form_paragraph->choice_space_above, 2);
1563                 break;
1564         case VSpace::SMALLSKIP:
1565                 fl_set_choice (fd_form_paragraph->choice_space_above, 3);
1566                 break;
1567         case VSpace::MEDSKIP:
1568                 fl_set_choice (fd_form_paragraph->choice_space_above, 4);
1569                 break;
1570         case VSpace::BIGSKIP:
1571                 fl_set_choice (fd_form_paragraph->choice_space_above, 5);
1572                 break;
1573         case VSpace::VFILL:
1574                 fl_set_choice (fd_form_paragraph->choice_space_above, 6);
1575                 break;
1576         case VSpace::LENGTH:
1577                 fl_set_choice (fd_form_paragraph->choice_space_above, 7); 
1578                 fl_set_input  (fd_form_paragraph->input_space_above, 
1579                                current_view->text->cursor.par->FirstPhysicalPar()->added_space_top.length().asString().c_str());
1580                 break;
1581         }
1582         fl_set_button (fd_form_paragraph->check_space_above,
1583                        current_view->text->cursor.par->FirstPhysicalPar()->added_space_top.keep());
1584         fl_set_input (fd_form_paragraph->input_space_below, "");
1585         switch (current_view->text->cursor.par->FirstPhysicalPar()->added_space_bottom.kind()) {
1586         case VSpace::NONE:
1587                 fl_set_choice (fd_form_paragraph->choice_space_below,
1588                                1);
1589                 break;
1590         case VSpace::DEFSKIP:
1591                 fl_set_choice (fd_form_paragraph->choice_space_below,
1592                                2);
1593                 break;
1594         case VSpace::SMALLSKIP:
1595                 fl_set_choice (fd_form_paragraph->choice_space_below,
1596                                3);
1597                 break;
1598         case VSpace::MEDSKIP:
1599                 fl_set_choice (fd_form_paragraph->choice_space_below,
1600                                4);
1601                 break;
1602         case VSpace::BIGSKIP:
1603                 fl_set_choice (fd_form_paragraph->choice_space_below,
1604                                5);
1605                 break;
1606         case VSpace::VFILL:
1607                 fl_set_choice (fd_form_paragraph->choice_space_below,
1608                                6);
1609                 break;
1610         case VSpace::LENGTH:
1611                 fl_set_choice (fd_form_paragraph->choice_space_below,
1612                                7); 
1613                 fl_set_input  (fd_form_paragraph->input_space_below, 
1614                                current_view->text->cursor.par->FirstPhysicalPar()->added_space_bottom.length().asString().c_str());
1615                 break;
1616         }
1617         fl_set_button (fd_form_paragraph->check_space_below,
1618                        current_view->text->cursor.par->FirstPhysicalPar()->added_space_bottom.keep());
1619
1620         fl_set_button(fd_form_paragraph->check_noindent,
1621                       current_view->text->cursor.par->FirstPhysicalPar()->noindent);
1622
1623         if (current_view->buffer()->isReadonly()) {
1624                 DisableParagraphLayout();
1625         } else {
1626                 EnableParagraphLayout();
1627         }
1628         return true;
1629 }
1630
1631
1632 void MenuLayoutParagraph()
1633 {
1634         if (UpdateLayoutParagraph()) {
1635                 if (fd_form_paragraph->form_paragraph->visible) {
1636                         fl_raise_form(fd_form_paragraph->form_paragraph);
1637                 } else {
1638                         fl_show_form(fd_form_paragraph->form_paragraph,
1639                                      FL_PLACE_MOUSE, FL_FULLBORDER,
1640                                      _("Paragraph Environment"));
1641                 }
1642         }
1643 }
1644
1645
1646 inline
1647 void DeactivateDocumentButtons ()
1648 {
1649         fl_deactivate_object (fd_form_document->button_ok);
1650         fl_deactivate_object (fd_form_document->button_apply);
1651         fl_set_object_lcol (fd_form_document->button_ok, FL_INACTIVE);
1652         fl_set_object_lcol (fd_form_document->button_apply, FL_INACTIVE);
1653 }
1654
1655
1656 inline
1657 void ActivateDocumentButtons ()
1658 {
1659         fl_activate_object (fd_form_document->button_ok);
1660         fl_activate_object (fd_form_document->button_apply);
1661         fl_set_object_lcol (fd_form_document->button_ok, FL_BLACK);
1662         fl_set_object_lcol (fd_form_document->button_apply, FL_BLACK);
1663 }
1664
1665
1666 inline
1667 void DisableDocumentLayout ()
1668 {
1669         DeactivateDocumentButtons ();
1670         fl_deactivate_object (fd_form_document->group_radio_separation);
1671         fl_deactivate_object (fd_form_document->radio_indent);
1672         fl_deactivate_object (fd_form_document->radio_skip);
1673         fl_deactivate_object (fd_form_document->choice_class);
1674         fl_deactivate_object (fd_form_document->choice_pagestyle);
1675         fl_deactivate_object (fd_form_document->choice_fonts);
1676         fl_deactivate_object (fd_form_document->choice_fontsize);
1677         fl_deactivate_object (fd_form_document->input_float_placement);
1678         fl_deactivate_object (fd_form_document->choice_postscript_driver);
1679         fl_deactivate_object (fd_form_document->choice_inputenc);
1680         fl_deactivate_object (fd_form_document->group_radio_sides);
1681         fl_deactivate_object (fd_form_document->radio_sides_one);
1682         fl_deactivate_object (fd_form_document->radio_sides_two);
1683         fl_deactivate_object (fd_form_document->group_radio_columns);
1684         fl_deactivate_object (fd_form_document->radio_columns_one);
1685         fl_deactivate_object (fd_form_document->radio_columns_two);
1686         fl_deactivate_object (fd_form_document->input_extra);
1687         fl_deactivate_object (fd_form_document->choice_language);
1688         combo_language->deactivate();
1689         fl_deactivate_object (fd_form_document->input_default_skip);
1690         fl_deactivate_object (fd_form_document->choice_default_skip);
1691         fl_deactivate_object (fd_form_document->slider_secnumdepth);
1692         fl_deactivate_object (fd_form_document->slider_tocdepth);
1693         fl_deactivate_object (fd_form_document->choice_spacing);
1694         fl_deactivate_object (fd_form_document->input_spacing);
1695         fl_deactivate_object (fd_form_document->check_use_amsmath);
1696 }
1697
1698
1699 inline
1700 void EnableDocumentLayout ()
1701 {
1702         ActivateDocumentButtons ();
1703         fl_activate_object (fd_form_document->group_radio_separation);
1704         fl_activate_object (fd_form_document->radio_indent);
1705         fl_activate_object (fd_form_document->radio_skip);
1706         fl_activate_object (fd_form_document->choice_class);
1707         fl_activate_object (fd_form_document->choice_pagestyle);
1708         fl_activate_object (fd_form_document->choice_fonts);
1709         fl_activate_object (fd_form_document->choice_fontsize);
1710         fl_activate_object (fd_form_document->input_float_placement);
1711         fl_activate_object (fd_form_document->choice_postscript_driver);
1712         fl_activate_object (fd_form_document->choice_inputenc);
1713         fl_activate_object (fd_form_document->group_radio_sides);
1714         fl_activate_object (fd_form_document->radio_sides_one);
1715         fl_activate_object (fd_form_document->radio_sides_two);
1716         fl_activate_object (fd_form_document->group_radio_columns);
1717         fl_activate_object (fd_form_document->radio_columns_one);
1718         fl_activate_object (fd_form_document->radio_columns_two);
1719         fl_activate_object (fd_form_document->input_extra);
1720         fl_activate_object (fd_form_document->choice_language);
1721         combo_language->activate();
1722         fl_activate_object (fd_form_document->input_default_skip);
1723         fl_activate_object (fd_form_document->choice_default_skip);
1724         fl_activate_object (fd_form_document->slider_secnumdepth);
1725         fl_activate_object (fd_form_document->slider_tocdepth);
1726         fl_activate_object (fd_form_document->choice_spacing);
1727         fl_activate_object (fd_form_document->input_spacing);
1728         fl_activate_object (fd_form_document->check_use_amsmath);
1729 }
1730
1731
1732 bool UpdateLayoutDocument(BufferParams * params)
1733 {
1734         if (!current_view->available()) {
1735                 if (fd_form_document->form_document->visible) 
1736                         fl_hide_form(fd_form_document->form_document);
1737                 return false;
1738         }               
1739
1740         if (params == 0)
1741                 params = &current_view->buffer()->params;
1742         LyXTextClass const & tclass = textclasslist.TextClass(params->textclass);
1743         
1744         fl_set_choice_text(fd_form_document->choice_class, 
1745                            textclasslist.DescOfClass(params->textclass).c_str());
1746         combo_language->select_text(params->language.c_str());
1747         
1748         fl_set_choice_text(fd_form_document->choice_fonts, 
1749                            params->fonts.c_str());
1750         fl_set_choice_text(fd_form_document->choice_inputenc, 
1751                            params->inputenc.c_str());
1752         fl_set_choice_text(fd_form_document->choice_postscript_driver, 
1753                            params->graphicsDriver.c_str());
1754
1755         // ale970405+lasgoutt970513
1756         fl_clear_choice(fd_form_document->choice_fontsize);
1757         fl_addto_choice(fd_form_document->choice_fontsize, "default");
1758         fl_addto_choice(fd_form_document->choice_fontsize, 
1759                         tclass.opt_fontsize().c_str());
1760         fl_set_choice(fd_form_document->choice_fontsize, 
1761                       tokenPos(tclass.opt_fontsize(), '|', params->fontsize) + 2);
1762
1763         // ale970405+lasgoutt970513
1764         fl_clear_choice(fd_form_document->choice_pagestyle);
1765         fl_addto_choice(fd_form_document->choice_pagestyle, "default");
1766         fl_addto_choice(fd_form_document->choice_pagestyle, 
1767                         tclass.opt_pagestyle().c_str());
1768     
1769         fl_set_choice(fd_form_document->choice_pagestyle,
1770                       tokenPos(tclass.opt_pagestyle(), '|', params->pagestyle) + 2);
1771
1772         fl_set_button(fd_form_document->radio_indent, 0);
1773         fl_set_button(fd_form_document->radio_skip, 0);
1774     
1775         
1776         fl_set_button(fd_form_document->check_use_amsmath, params->use_amsmath);
1777
1778         if (params->paragraph_separation == BufferParams::PARSEP_INDENT)
1779                 fl_set_button(fd_form_document->radio_indent, 1);
1780         else
1781                 fl_set_button(fd_form_document->radio_skip, 1);
1782
1783         switch (params->getDefSkip().kind()) {
1784         case VSpace::SMALLSKIP: 
1785                 fl_set_choice (fd_form_document->choice_default_skip, 1);
1786                 break;
1787         case VSpace::MEDSKIP: 
1788                 fl_set_choice (fd_form_document->choice_default_skip, 2);
1789                 break;
1790         case VSpace::BIGSKIP: 
1791                 fl_set_choice (fd_form_document->choice_default_skip, 3);
1792                 break;
1793         case VSpace::LENGTH: 
1794                 fl_set_choice (fd_form_document->choice_default_skip, 4);
1795                 fl_set_input (fd_form_document->input_default_skip,
1796                               params->getDefSkip().asLyXCommand().c_str());
1797                 break;
1798         default:
1799                 fl_set_choice (fd_form_document->choice_default_skip, 2);
1800                 break;
1801         }
1802    
1803         fl_set_button(fd_form_document->radio_sides_one, 0);
1804         fl_set_button(fd_form_document->radio_sides_two, 0);
1805    
1806         switch (params->sides) {
1807         case LyXTextClass::OneSide:
1808                 fl_set_button(fd_form_document->radio_sides_one, 1);
1809                 break;
1810         case LyXTextClass::TwoSides:
1811                 fl_set_button(fd_form_document->radio_sides_two, 1);
1812                 break;
1813         }
1814    
1815         fl_set_button(fd_form_document->radio_columns_one, 0);
1816         fl_set_button(fd_form_document->radio_columns_two, 0);
1817    
1818         if (params->columns == 2)
1819                 fl_set_button(fd_form_document->radio_columns_two, 1);
1820         else
1821                 fl_set_button(fd_form_document->radio_columns_one, 1);
1822    
1823         fl_set_input(fd_form_document->input_spacing, "");
1824         switch (params->spacing.getSpace()) {
1825         case Spacing::Single:
1826         {
1827                 // \singlespacing
1828                 fl_set_choice(fd_form_document->choice_spacing, 1);
1829                 break;
1830         }
1831         case Spacing::Onehalf:
1832         {
1833                 // \onehalfspacing
1834                 fl_set_choice(fd_form_document->choice_spacing, 2);
1835                 break;
1836         }
1837         case Spacing::Double:
1838         {
1839                 // \ doublespacing
1840                 fl_set_choice(fd_form_document->choice_spacing, 3);
1841                 break;
1842         }
1843         case Spacing::Other:
1844         {
1845                 fl_set_choice(fd_form_document->choice_spacing, 4);
1846                 char sval[20];
1847                 sprintf(sval, "%g", params->spacing.getValue()); 
1848                 fl_set_input(fd_form_document->input_spacing, sval);
1849                 break;
1850         }
1851         }
1852
1853
1854         fl_set_counter_value(fd_form_document->slider_secnumdepth, 
1855                              params->secnumdepth);
1856         fl_set_counter_value(fd_form_document->slider_tocdepth, 
1857                              params->tocdepth);
1858         if (!params->float_placement.empty()) { // buffer local (Lgb)
1859                 fl_set_input(fd_form_document->input_float_placement,
1860                              params->float_placement.c_str());
1861         } else {
1862                 fl_set_input(fd_form_document->input_float_placement, "");
1863         }
1864         if (!params->options.empty())
1865                 fl_set_input(fd_form_document->input_extra,
1866                              params->options.c_str());
1867         else
1868                 fl_set_input(fd_form_document->input_extra, "");
1869
1870         if (current_view->buffer()->isSGML()) {
1871                 // bullets not used in SGML derived documents
1872                 fl_deactivate_object(fd_form_document->button_bullets);
1873                 fl_set_object_lcol(fd_form_document->button_bullets,
1874                                    FL_INACTIVE);
1875         } else {
1876                 fl_activate_object(fd_form_document->button_bullets);
1877                 fl_set_object_lcol(fd_form_document->button_bullets,
1878                                    FL_BLACK);
1879         }
1880
1881         if (current_view->buffer()->isReadonly()) {
1882                 DisableDocumentLayout();
1883         } else {
1884                 EnableDocumentLayout();
1885         }
1886
1887         return true;
1888 }
1889
1890
1891 void MenuLayoutDocument()
1892 {
1893         if (UpdateLayoutDocument()) {
1894                 if (fd_form_document->form_document->visible) {
1895                         fl_raise_form(fd_form_document->form_document);
1896                 } else {
1897                         fl_show_form(fd_form_document->form_document,
1898                                      FL_PLACE_MOUSE, FL_FULLBORDER,
1899                                      _("Document Layout"));
1900                 }
1901         }
1902 }
1903
1904
1905 bool UpdateLayoutQuotes()
1906 {
1907         bool update = true;
1908         if (!current_view->available()
1909             || current_view->buffer()->isReadonly())
1910                 update = false;
1911         
1912         if (update) {
1913                 fl_set_choice(fd_form_quotes->choice_quotes_language,
1914                               current_view->buffer()->params.quotes_language + 1);
1915                 fl_set_button(fd_form_quotes->radio_single, 0);
1916                 fl_set_button(fd_form_quotes->radio_double, 0);
1917         
1918                 if (current_view->buffer()->params.quotes_times == InsetQuotes::SingleQ)
1919                         fl_set_button(fd_form_quotes->radio_single, 1);
1920                 else
1921                         fl_set_button(fd_form_quotes->radio_double, 1);
1922         } else if (fd_form_quotes->form_quotes->visible) {
1923                 fl_hide_form(fd_form_quotes->form_quotes);
1924         }
1925         return update;
1926 }
1927
1928
1929 void MenuLayoutQuotes()
1930 {
1931         if (UpdateLayoutQuotes()) {
1932                 if (fd_form_quotes->form_quotes->visible) {
1933                         fl_raise_form(fd_form_quotes->form_quotes);
1934                 } else {
1935                         fl_show_form(fd_form_quotes->form_quotes,
1936                                      FL_PLACE_MOUSE, FL_FULLBORDER,
1937                                      _("Quotes"));
1938                 }
1939         }
1940 }
1941
1942
1943 bool UpdateLayoutPreamble()
1944 {
1945         bool update = true;
1946         if (!current_view->available())
1947                 update = false;
1948
1949         if (update) {
1950                 fl_set_input(fd_form_preamble->input_preamble,
1951                              current_view->buffer()->params.preamble.c_str());
1952
1953                 if (current_view->buffer()->isReadonly()) {
1954                         fl_deactivate_object(fd_form_preamble->input_preamble);
1955                         fl_deactivate_object(fd_form_preamble->button_ok);
1956                         fl_deactivate_object(fd_form_preamble->button_apply);
1957                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_INACTIVE);
1958                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_INACTIVE);
1959                 }
1960                 else {
1961                         fl_activate_object(fd_form_preamble->input_preamble);
1962                         fl_activate_object(fd_form_preamble->button_ok);
1963                         fl_activate_object(fd_form_preamble->button_apply);
1964                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_BLACK);
1965                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_BLACK);
1966                 }
1967         } else if (fd_form_preamble->form_preamble->visible) {
1968                 fl_hide_form(fd_form_preamble->form_preamble);
1969         }
1970         return update;
1971 }
1972
1973
1974 void MenuLayoutPreamble()
1975 {
1976         static int ow = -1, oh;
1977
1978         if (UpdateLayoutPreamble()) {
1979                 if (fd_form_preamble->form_preamble->visible) {
1980                         fl_raise_form(fd_form_preamble->form_preamble);
1981                 } else {
1982                         fl_show_form(fd_form_preamble->form_preamble,
1983                                      FL_PLACE_MOUSE | FL_FREE_SIZE,
1984                                      FL_FULLBORDER,
1985                                      _("LaTeX Preamble"));
1986                         if (ow < 0) {
1987                                 ow = fd_form_preamble->form_preamble->w;
1988                                 oh = fd_form_preamble->form_preamble->h;
1989                         }
1990                         fl_set_form_minsize(fd_form_preamble->form_preamble,
1991                                             ow, oh);
1992                 }
1993         }
1994 }
1995
1996
1997 void MenuLayoutSave()
1998 {
1999         if (!current_view->available())
2000                 return;
2001
2002         if (AskQuestion(_("Do you want to save the current settings"),
2003                         _("for Character, Document, Paper and Quotes"),
2004                         _("as default for new documents?")))
2005                 current_view->buffer()->saveParamsAsDefaults();
2006 }
2007
2008
2009 /* -------> These CB's use ToggleFree() as the (one and only?) font-changer. 
2010                         They also show the current font state. */
2011
2012 static
2013 void ToggleAndShow(BufferView *, LyXFont const &);
2014
2015
2016 void FontSize(string const & size)
2017 {
2018         LyXFont font(LyXFont::ALL_IGNORE);
2019         font.setGUISize(size);
2020         ToggleAndShow(current_view, font);
2021 }
2022
2023
2024 void Emph()
2025 {
2026         LyXFont font(LyXFont::ALL_IGNORE);
2027         font.setEmph(LyXFont::TOGGLE);
2028         ToggleAndShow(current_view, font);
2029 }
2030
2031
2032 void Noun()
2033 {
2034         LyXFont font(LyXFont::ALL_IGNORE);
2035         font.setNoun(LyXFont::TOGGLE);
2036         ToggleAndShow(current_view, font);
2037 }
2038
2039
2040 void Bold()
2041 {
2042         LyXFont font(LyXFont::ALL_IGNORE);
2043         font.setSeries(LyXFont::BOLD_SERIES);
2044         ToggleAndShow(current_view, font);
2045 }
2046
2047
2048 void Underline()
2049 {
2050         LyXFont font(LyXFont::ALL_IGNORE);
2051         font.setUnderbar(LyXFont::TOGGLE);
2052         ToggleAndShow(current_view, font);
2053 }
2054
2055
2056 void Code()
2057 {
2058         LyXFont font(LyXFont::ALL_IGNORE);
2059         font.setFamily(LyXFont::TYPEWRITER_FAMILY); // no good
2060         ToggleAndShow(current_view, font);
2061 }
2062
2063
2064 void Sans()
2065 {
2066         LyXFont font(LyXFont::ALL_IGNORE);
2067         font.setFamily(LyXFont::SANS_FAMILY);
2068         ToggleAndShow(current_view, font);
2069 }
2070
2071
2072 void Roman()
2073 {
2074         LyXFont font(LyXFont::ALL_IGNORE);
2075         font.setFamily(LyXFont::ROMAN_FAMILY);
2076         ToggleAndShow(current_view, font);
2077 }
2078
2079
2080 void Tex()
2081 {
2082         LyXFont font(LyXFont::ALL_IGNORE);
2083         font.setLatex (LyXFont::TOGGLE);
2084         ToggleAndShow(current_view, font);
2085 }
2086
2087 void RTLCB()
2088 {
2089         LyXFont font(LyXFont::ALL_IGNORE);
2090         font.setDirection (LyXFont::TOGGLE_DIR);
2091         ToggleAndShow(current_view, font);
2092 }
2093
2094
2095 void StyleReset()
2096 {
2097         LyXFont font(LyXFont::ALL_INHERIT);
2098         ToggleAndShow(current_view, font);
2099 }
2100
2101
2102 /* -------> Returns the current font and depth by printing a message. In the
2103  * future perhaps we could try to implement a callback to the button-bar.
2104  * That is, `light' the bold button when the font is currently bold, etc.
2105  */
2106 string CurrentState()
2107 {
2108         string state;
2109         if (current_view->available()) { 
2110                 // I think we should only show changes from the default
2111                 // font. (Asger)
2112                 Buffer * buffer = current_view->buffer();
2113                 LyXFont font = current_view->text->real_current_font;
2114                 LyXFont defaultfont = textclasslist.TextClass(buffer->
2115                                                               params.textclass).defaultfont();
2116                 font.reduce(defaultfont);
2117                 state = _("Font: ") + font.stateText();
2118
2119                 int depth = current_view->text->GetDepth();
2120                 if (depth > 0) 
2121                         state += string(_(", Depth: ")) + tostr(depth);
2122         }
2123         return state;
2124 }
2125
2126
2127 // candidate for move to BufferView
2128 /* -------> Does the actual toggle job of the XxxCB() calls above.
2129  * Also shows the current font state.
2130  */
2131 static
2132 void ToggleAndShow(BufferView * bv, LyXFont const & font)
2133 {
2134         if (bv->available()) { 
2135                 bv->hideCursor();
2136                 bv->update(-2);
2137                 bv->text->ToggleFree(font, toggleall);
2138                 bv->update(1);
2139         }
2140 }
2141
2142
2143 // candidate for move to BufferView
2144 void Margin(BufferView * bv)
2145 {
2146         if (bv->available()) {
2147                 bv->owner()->getMiniBuffer()->Set(_("Inserting margin note..."));
2148                 bv->hideCursor();
2149                 bv->update(-2);
2150                 bv->text->InsertFootnoteEnvironment(LyXParagraph::MARGIN);
2151                 bv->update(1);
2152         }
2153 }
2154
2155
2156 void Figure()
2157 {
2158         if (fd_form_figure->form_figure->visible) {
2159                 fl_raise_form(fd_form_figure->form_figure);
2160         } else {
2161                 fl_show_form(fd_form_figure->form_figure,
2162                              FL_PLACE_MOUSE, FL_FULLBORDER,
2163                              _("Insert Figure"));
2164         }
2165 }
2166
2167
2168 void Table()
2169 {
2170         if (fd_form_table->form_table->visible) {
2171                 fl_raise_form(fd_form_table->form_table);
2172         } else {
2173                 fl_show_form(fd_form_table->form_table,
2174                              FL_PLACE_MOUSE, FL_FULLBORDER,
2175                              _("Insert Table"));
2176         }
2177 }
2178
2179
2180 // candidate for move to BufferView
2181 void Melt(BufferView * bv)
2182 {
2183         if (!bv->available()) return;
2184         
2185         bv->owner()->getMiniBuffer()->Set(_("Melt"));
2186         bv->hideCursor();
2187         bv->beforeChange();
2188         bv->update(-2);
2189         bv->text->MeltFootnoteEnvironment();
2190         bv->update(1);
2191 }
2192
2193
2194 // candidate for move to BufferView
2195 // Change environment depth.
2196 // if decInc >= 0, increment depth
2197 // if decInc <  0, decrement depth
2198 void changeDepth(BufferView * bv, int decInc)
2199 {
2200         if (!bv->available()) return;
2201         
2202         bv->hideCursor();
2203         bv->update(-2);
2204         if (decInc >= 0)
2205                 bv->text->IncDepth();
2206         else
2207                 bv->text->DecDepth();
2208         bv->update(1);
2209         bv->owner()->getMiniBuffer()
2210                 ->Set(_("Changed environment depth"
2211                         " (in possible range, maybe not)"));
2212 }
2213
2214
2215 // This is both GUI and LyXFont dependent. Don't know where to put it. (Asger)
2216 // Well, it's mostly GUI dependent, so I guess it will stay here. (Asger)
2217 LyXFont UserFreeFont()
2218 {
2219         LyXFont font(LyXFont::ALL_IGNORE);
2220
2221         int pos = fl_get_choice(fd_form_character->choice_family);
2222         switch(pos) {
2223         case 1: font.setFamily(LyXFont::IGNORE_FAMILY); break;
2224         case 2: font.setFamily(LyXFont::ROMAN_FAMILY); break;
2225         case 3: font.setFamily(LyXFont::SANS_FAMILY); break;
2226         case 4: font.setFamily(LyXFont::TYPEWRITER_FAMILY); break;
2227         case 5: font.setFamily(LyXFont::INHERIT_FAMILY); break;
2228         }
2229
2230         pos = fl_get_choice(fd_form_character->choice_series);
2231         switch(pos) {
2232         case 1: font.setSeries(LyXFont::IGNORE_SERIES); break;
2233         case 2: font.setSeries(LyXFont::MEDIUM_SERIES); break;
2234         case 3: font.setSeries(LyXFont::BOLD_SERIES); break;
2235         case 4: font.setSeries(LyXFont::INHERIT_SERIES); break;
2236         }
2237
2238         pos = fl_get_choice(fd_form_character->choice_shape);
2239         switch(pos) {
2240         case 1: font.setShape(LyXFont::IGNORE_SHAPE); break;
2241         case 2: font.setShape(LyXFont::UP_SHAPE); break;
2242         case 3: font.setShape(LyXFont::ITALIC_SHAPE); break;
2243         case 4: font.setShape(LyXFont::SLANTED_SHAPE); break;
2244         case 5: font.setShape(LyXFont::SMALLCAPS_SHAPE); break;
2245         case 6: font.setShape(LyXFont::INHERIT_SHAPE); break;
2246         }
2247
2248         pos = fl_get_choice(fd_form_character->choice_size);
2249         switch(pos) {
2250         case 1: font.setSize(LyXFont::IGNORE_SIZE); break;
2251         case 2: font.setSize(LyXFont::SIZE_TINY); break;
2252         case 3: font.setSize(LyXFont::SIZE_SCRIPT); break;
2253         case 4: font.setSize(LyXFont::SIZE_FOOTNOTE); break;
2254         case 5: font.setSize(LyXFont::SIZE_SMALL); break;
2255         case 6: font.setSize(LyXFont::SIZE_NORMAL); break;
2256         case 7: font.setSize(LyXFont::SIZE_LARGE); break;
2257         case 8: font.setSize(LyXFont::SIZE_LARGER); break;
2258         case 9: font.setSize(LyXFont::SIZE_LARGEST); break;
2259         case 10: font.setSize(LyXFont::SIZE_HUGE); break;
2260         case 11: font.setSize(LyXFont::SIZE_HUGER); break;
2261         case 12: font.setSize(LyXFont::INCREASE_SIZE); break;
2262         case 13: font.setSize(LyXFont::DECREASE_SIZE); break;
2263         case 14: font.setSize(LyXFont::INHERIT_SIZE); break;
2264         }
2265
2266         pos = fl_get_choice(fd_form_character->choice_bar);
2267         switch(pos) {
2268         case 1: font.setEmph(LyXFont::IGNORE);
2269                 font.setUnderbar(LyXFont::IGNORE);
2270                 font.setNoun(LyXFont::IGNORE);
2271                 font.setLatex(LyXFont::IGNORE);
2272                 break;
2273         case 2: font.setEmph(LyXFont::TOGGLE); break;
2274         case 3: font.setUnderbar(LyXFont::TOGGLE); break;
2275         case 4: font.setNoun(LyXFont::TOGGLE); break;
2276         case 5: font.setLatex(LyXFont::TOGGLE); break;
2277         case 6: font.setEmph(LyXFont::INHERIT);
2278                 font.setUnderbar(LyXFont::INHERIT);
2279                 font.setNoun(LyXFont::INHERIT);
2280                 font.setLatex(LyXFont::INHERIT);
2281                 break;
2282         }
2283
2284         pos = fl_get_choice(fd_form_character->choice_color);
2285         switch(pos) {
2286         case 1: font.setColor(LColor::ignore); break;
2287         case 2: font.setColor(LColor::none); break;
2288         case 3: font.setColor(LColor::black); break;
2289         case 4: font.setColor(LColor::white); break;
2290         case 5: font.setColor(LColor::red); break;
2291         case 6: font.setColor(LColor::green); break;
2292         case 7: font.setColor(LColor::blue); break;
2293         case 8: font.setColor(LColor::cyan); break;
2294         case 9: font.setColor(LColor::magenta); break;
2295         case 10: font.setColor(LColor::yellow); break;
2296         case 11: font.setColor(LColor::inherit); break;
2297         }
2298
2299         return font; 
2300 }
2301
2302
2303 void Free()
2304 {
2305         ToggleAndShow(current_view, UserFreeFont());
2306 }
2307
2308
2309 /* callbacks for form form_title */
2310 extern "C" void TimerCB(FL_OBJECT *, long)
2311 {
2312         // only if the form still exists
2313         if (fd_form_title->form_title != 0) {
2314                 if (fd_form_title->form_title->visible) {
2315                         fl_hide_form(fd_form_title->form_title);
2316                 }
2317                 fl_free_form(fd_form_title->form_title);
2318                 fd_form_title->form_title = 0;
2319         }
2320 }
2321
2322
2323 /* callbacks for form form_paragraph */
2324
2325 extern "C" void ParagraphVSpaceCB(FL_OBJECT * obj, long )
2326 {
2327         // "Synchronize" the choices and input fields, making it
2328         // impossible to commit senseless data.
2329
2330         FD_form_paragraph const * fp = fd_form_paragraph;
2331
2332         if (obj == fp->choice_space_above) {
2333                 if (fl_get_choice (fp->choice_space_above) != 7) {
2334                         fl_set_input (fp->input_space_above, "");
2335                         ActivateParagraphButtons();
2336                 }
2337         } else if (obj == fp->choice_space_below) {
2338                 if (fl_get_choice (fp->choice_space_below) != 7) {
2339                         fl_set_input (fp->input_space_below, "");
2340                         ActivateParagraphButtons();
2341                 }
2342         } else if (obj == fp->input_space_above) {
2343                 string input = fl_get_input (fp->input_space_above);
2344
2345                 if (input.empty()) {
2346                         fl_set_choice (fp->choice_space_above, 1);
2347                         ActivateParagraphButtons();
2348                 }
2349                 else if (isValidGlueLength (input)) {
2350                         fl_set_choice (fp->choice_space_above, 7);
2351                         ActivateParagraphButtons();
2352                 }
2353                 else {
2354                         fl_set_choice (fp->choice_space_above, 7);
2355                         DeactivateParagraphButtons();
2356                 }
2357         } else if (obj == fp->input_space_below) {
2358                 string input = fl_get_input (fp->input_space_below);
2359
2360                 if (input.empty()) {
2361                         fl_set_choice (fp->choice_space_below, 1);
2362                         ActivateParagraphButtons();
2363                 }
2364                 else if (isValidGlueLength (input)) {
2365                         fl_set_choice (fp->choice_space_below, 7);
2366                         ActivateParagraphButtons();
2367                 }
2368                 else {
2369                         fl_set_choice (fp->choice_space_below, 7);
2370                         DeactivateParagraphButtons();
2371                 }
2372         }
2373 }
2374
2375
2376 extern "C" void ParagraphApplyCB(FL_OBJECT *, long)
2377 {
2378         if (!current_view->available())
2379                 return;
2380         
2381         VSpace space_top, space_bottom;
2382         LyXAlignment align;
2383         string labelwidthstring;
2384         bool noindent;
2385
2386         // If a vspace kind is "Length" but there's no text in
2387         // the input field, reset the kind to "None". 
2388         if (fl_get_choice (fd_form_paragraph->choice_space_above) == 7
2389             && !*(fl_get_input (fd_form_paragraph->input_space_above))) {
2390                 fl_set_choice (fd_form_paragraph->choice_space_above, 1);
2391         }
2392         if (fl_get_choice (fd_form_paragraph->choice_space_below) == 7
2393             && !*(fl_get_input (fd_form_paragraph->input_space_below))) {
2394                 fl_set_choice (fd_form_paragraph->choice_space_below, 1);
2395         }
2396    
2397         bool line_top = fl_get_button(fd_form_paragraph->check_lines_top);
2398         bool line_bottom = fl_get_button(fd_form_paragraph->check_lines_bottom);
2399         bool pagebreak_top = fl_get_button(fd_form_paragraph->check_pagebreaks_top);
2400         bool pagebreak_bottom = fl_get_button(fd_form_paragraph->check_pagebreaks_bottom);
2401         switch (fl_get_choice (fd_form_paragraph->choice_space_above)) {
2402         case 1: space_top = VSpace(VSpace::NONE); break;
2403         case 2: space_top = VSpace(VSpace::DEFSKIP); break;
2404         case 3: space_top = VSpace(VSpace::SMALLSKIP); break;
2405         case 4: space_top = VSpace(VSpace::MEDSKIP); break;
2406         case 5: space_top = VSpace(VSpace::BIGSKIP); break;
2407         case 6: space_top = VSpace(VSpace::VFILL); break;
2408         case 7: space_top = VSpace(LyXGlueLength (fl_get_input (fd_form_paragraph->input_space_above))); break;
2409         }
2410         if (fl_get_button (fd_form_paragraph->check_space_above))
2411                 space_top.setKeep (true);
2412         switch (fl_get_choice (fd_form_paragraph->choice_space_below)) {
2413         case 1: space_bottom = VSpace(VSpace::NONE); break;
2414         case 2: space_bottom = VSpace(VSpace::DEFSKIP); break;
2415         case 3: space_bottom = VSpace(VSpace::SMALLSKIP); break;
2416         case 4: space_bottom = VSpace(VSpace::MEDSKIP); break;
2417         case 5: space_bottom = VSpace(VSpace::BIGSKIP); break;
2418         case 6: space_bottom = VSpace(VSpace::VFILL); break;
2419         case 7: space_bottom = VSpace(LyXGlueLength (fl_get_input (fd_form_paragraph->input_space_below))); break;
2420         }
2421         if (fl_get_button (fd_form_paragraph->check_space_below))
2422                 space_bottom.setKeep (true);
2423
2424         if (fl_get_button(fd_form_paragraph->radio_align_left))
2425                 align = LYX_ALIGN_LEFT;
2426         else if (fl_get_button(fd_form_paragraph->radio_align_right))
2427                 align = LYX_ALIGN_RIGHT;
2428         else if (fl_get_button(fd_form_paragraph->radio_align_center))
2429                 align = LYX_ALIGN_CENTER;
2430         else 
2431                 align = LYX_ALIGN_BLOCK;
2432    
2433         labelwidthstring = fl_get_input(fd_form_paragraph->input_labelwidth);
2434         noindent = fl_get_button(fd_form_paragraph->check_noindent);
2435
2436         current_view->text->SetParagraph(line_top,
2437                                          line_bottom,
2438                                          pagebreak_top,
2439                                          pagebreak_bottom,
2440                                          space_top,
2441                                          space_bottom,
2442                                          align, 
2443                                          labelwidthstring,
2444                                          noindent);
2445         current_view->update(1);
2446         current_view->owner()->getMiniBuffer()->Set(_("Paragraph layout set"));
2447 }
2448
2449
2450 extern "C" void ParagraphCancelCB(FL_OBJECT *, long)
2451 {
2452         fl_hide_form(fd_form_paragraph->form_paragraph);
2453 }
2454
2455
2456 extern "C" void ParagraphOKCB(FL_OBJECT *ob, long data)
2457 {
2458         ParagraphApplyCB(ob, data);
2459         ParagraphCancelCB(ob, data);
2460 }
2461
2462
2463 /* callbacks for form form_character */
2464
2465 extern "C" void CharacterApplyCB(FL_OBJECT *, long)
2466 {
2467         // we set toggleall locally here, since it should be true for
2468         // all other uses of ToggleAndShow() (JMarc)
2469         toggleall = fl_get_button(fd_form_character->check_toggle_all);
2470         ToggleAndShow(current_view, UserFreeFont());
2471         toggleall = true;
2472 }
2473
2474
2475 extern "C" void CharacterCloseCB(FL_OBJECT *, long)
2476 {
2477         fl_hide_form(fd_form_character->form_character);
2478 }
2479
2480
2481 extern "C" void CharacterOKCB(FL_OBJECT *ob, long data)
2482 {
2483         CharacterApplyCB(ob, data);
2484         CharacterCloseCB(ob, data);
2485 }
2486
2487
2488 /* callbacks for form form_document */
2489
2490 void UpdateDocumentButtons(BufferParams const & params) 
2491 {
2492         fl_set_choice(fd_form_document->choice_pagestyle, 1);
2493
2494         switch (params.sides) {
2495         case LyXTextClass::OneSide:
2496                 fl_set_button(fd_form_document->radio_sides_one, 1);
2497                 break;
2498         case LyXTextClass::TwoSides:
2499                 fl_set_button(fd_form_document->radio_sides_two, 1);
2500                 break;
2501         }
2502    
2503         if (params.columns == 2)
2504                 fl_set_button(fd_form_document->radio_columns_two, 1);
2505         else
2506                 fl_set_button(fd_form_document->radio_columns_one, 1);
2507         
2508         fl_set_input(fd_form_document->input_extra, params.options.c_str());
2509         fl_set_counter_value(fd_form_document->slider_secnumdepth, 
2510                              params.secnumdepth);
2511         fl_set_counter_value(fd_form_document->slider_tocdepth, 
2512                              params.tocdepth);
2513         
2514 }
2515
2516 extern "C" void ChoiceClassCB(FL_OBJECT * ob, long)
2517 {
2518         ProhibitInput();
2519         if (textclasslist.Load(fl_get_choice(ob)-1)) {
2520                 if (AskQuestion(_("Should I set some parameters to"),
2521                                 fl_get_choice_text(ob),
2522                                 _("the defaults of this document class?"))) {
2523                         BufferParams params = BufferParams();
2524                         params.textclass = fl_get_choice(ob)-1;
2525                         params.useClassDefaults();
2526                         UpdateLayoutDocument(&params);
2527                         UpdateDocumentButtons(params);
2528                 }
2529         } else {
2530                 // unable to load new style
2531                 WriteAlert(_("Conversion Errors!"),
2532                            _("Unable to switch to new document class."),
2533                            _("Reverting to original document class."));
2534                 fl_set_choice(fd_form_document->choice_class, 
2535                               current_view->buffer()->params.textclass + 1);
2536         }
2537         AllowInput();
2538 }
2539
2540
2541 extern "C" void DocumentDefskipCB(FL_OBJECT * obj, long)
2542 {
2543         // "Synchronize" the choice and the input field, so that it
2544         // is impossible to commit senseless data.
2545         FD_form_document const * fd = fd_form_document;
2546
2547         if (obj == fd->choice_default_skip) {
2548                 if (fl_get_choice (fd->choice_default_skip) != 4) {
2549                         fl_set_input (fd->input_default_skip, "");
2550                         ActivateDocumentButtons();
2551                 }
2552         } else if (obj == fd->input_default_skip) {
2553
2554                 char const * input = fl_get_input (fd->input_default_skip);
2555
2556                 if (!*input) {
2557                         fl_set_choice (fd->choice_default_skip, 2);
2558                         ActivateDocumentButtons();
2559                 } else if (isValidGlueLength (input)) {
2560                         fl_set_choice (fd->choice_default_skip, 4);
2561                         ActivateDocumentButtons();
2562                 } else {
2563                         fl_set_choice (fd->choice_default_skip, 4);
2564                         DeactivateDocumentButtons();
2565                 }
2566         }
2567 }
2568
2569
2570 extern "C" void DocumentSpacingCB(FL_OBJECT * obj, long)
2571 {
2572         // "Synchronize" the choice and the input field, so that it
2573         // is impossible to commit senseless data.
2574         FD_form_document const * fd = fd_form_document;
2575
2576         if (obj == fd->choice_spacing
2577             && fl_get_choice (fd->choice_spacing) != 4) {
2578                 fl_set_input(fd->input_spacing, "");
2579         } else if (obj == fd->input_spacing) {
2580
2581                 const char* input = fl_get_input (fd->input_spacing);
2582
2583                 if (!*input) {
2584                         fl_set_choice (fd->choice_spacing, 1);
2585                 } else {
2586                         fl_set_choice (fd->choice_spacing, 4);
2587                 }
2588         }
2589 }
2590
2591
2592 extern "C" void DocumentApplyCB(FL_OBJECT *, long)
2593 {
2594         bool redo = false;
2595         BufferParams * params = &(current_view->buffer()->params);
2596         current_view->buffer()->params.language = 
2597                 combo_language->getline();
2598
2599         // If default skip is a "Length" but there's no text in the
2600         // input field, reset the kind to "Medskip", which is the default.
2601         if (fl_get_choice (fd_form_document->choice_default_skip) == 4
2602             && !*(fl_get_input (fd_form_document->input_default_skip))) {
2603                 fl_set_choice (fd_form_document->choice_default_skip, 2);
2604         }
2605
2606         /* this shouldn't be done automatically IMO. For example I write german
2607          * documents with an american keyboard very often. Matthias */
2608    
2609         /* ChangeKeymap(buffer->parameters.language, TRUE, false,
2610            fl_get_choice(fd_form_document->choice_language)); */
2611         params->fonts = 
2612                 fl_get_choice_text(fd_form_document->choice_fonts);
2613         params->inputenc = 
2614                 fl_get_choice_text(fd_form_document->choice_inputenc);
2615         params->fontsize = 
2616                 fl_get_choice_text(fd_form_document->choice_fontsize);
2617         params->pagestyle = 
2618                 fl_get_choice_text(fd_form_document->choice_pagestyle);
2619         params->graphicsDriver = 
2620                 fl_get_choice_text(fd_form_document->choice_postscript_driver);
2621         params->use_amsmath = 
2622                 fl_get_button(fd_form_document->check_use_amsmath);
2623    
2624         if (!current_view->available())
2625                 return;
2626         if (lyxrc->rtl_support) {
2627                 current_view->text->SetCursor(current_view->text->cursor.par,
2628                                               current_view->text->cursor.pos);
2629                 current_view->setState();
2630         }
2631
2632         LyXTextClassList::ClassList::size_type new_class =
2633                 fl_get_choice(fd_form_document->choice_class) - 1;
2634
2635         if (params->textclass != new_class) {
2636                 // try to load new_class
2637                 if (textclasslist.Load(new_class)) {
2638                         // successfully loaded
2639                         redo = true;
2640                         current_view->owner()->getMiniBuffer()->Set(_("Converting document to new document class..."));
2641                         int ret = current_view->text->
2642                                 SwitchLayoutsBetweenClasses(current_view->buffer()->
2643                                                             params.textclass,
2644                                                             new_class,
2645                                                             current_view->buffer()->
2646                                                             paragraph);
2647
2648                         if (ret) {
2649                                 string s;
2650                                 if (ret == 1)
2651                                         s = _("One paragraph couldn't be converted");
2652                                 else {
2653                                         s += tostr(ret);
2654                                         s += _(" paragraphs couldn't be converted");
2655                                 }
2656                                 WriteAlert(_("Conversion Errors!"), s,
2657                                            _("into chosen document class"));
2658                         }
2659
2660                         params->textclass = new_class;
2661                 } else {
2662                         // problem changing class -- warn user and retain old style
2663                         WriteAlert(_("Conversion Errors!"),
2664                                    _("Unable to switch to new document class."),
2665                                    _("Reverting to original document class."));
2666                         fl_set_choice(fd_form_document->choice_class, params->textclass + 1);
2667                 }
2668         }
2669
2670         char tmpsep = params->paragraph_separation;
2671         if (fl_get_button(fd_form_document->radio_indent))
2672                 params->paragraph_separation = BufferParams::PARSEP_INDENT;
2673         else
2674                 params->paragraph_separation = BufferParams::PARSEP_SKIP;
2675         if (tmpsep != params->paragraph_separation)
2676                 redo = true;
2677    
2678         VSpace tmpdefskip = params->getDefSkip();
2679         switch (fl_get_choice (fd_form_document->choice_default_skip)) {
2680         case 1: params->setDefSkip(VSpace(VSpace::SMALLSKIP)); break;
2681         case 2: params->setDefSkip(VSpace(VSpace::MEDSKIP)); break;
2682         case 3: params->setDefSkip(VSpace(VSpace::BIGSKIP)); break;
2683         case 4: params->setDefSkip( 
2684                 VSpace (LyXGlueLength (fl_get_input 
2685                                        (fd_form_document->input_default_skip))));
2686         break;
2687         // DocumentDefskipCB assures that this never happens
2688         default: params->setDefSkip(VSpace(VSpace::MEDSKIP)); break;
2689         }
2690         if (!(tmpdefskip == params->getDefSkip()))
2691                 redo = true;
2692
2693         if (fl_get_button(fd_form_document->radio_columns_two))
2694                 params->columns = 2;
2695         else
2696                 params->columns = 1;
2697         if (fl_get_button(fd_form_document->radio_sides_two))
2698                 params->sides = LyXTextClass::TwoSides;
2699         else
2700                 params->sides = LyXTextClass::OneSide;
2701
2702         Spacing tmpSpacing = params->spacing;
2703         switch(fl_get_choice(fd_form_document->choice_spacing)) {
2704         case 1:
2705                 lyxerr.debug() << "Spacing: SINGLE" << endl;
2706                 params->spacing.set(Spacing::Single);
2707                 break;
2708         case 2:
2709                 lyxerr.debug() << "Spacing: ONEHALF" << endl;
2710                 params->spacing.set(Spacing::Onehalf);
2711                 break;
2712         case 3:
2713                 lyxerr.debug() << "Spacing: DOUBLE" << endl;
2714                 params->spacing.set(Spacing::Double);
2715                 break;
2716         case 4:
2717                 lyxerr.debug() << "Spacing: OTHER" << endl;
2718                 params->spacing.set(Spacing::Other, 
2719                                     fl_get_input(fd_form_document->input_spacing));
2720                 break;
2721         }
2722         if (tmpSpacing != params->spacing)
2723                 redo = true;
2724         
2725         signed char tmpchar =  
2726                 static_cast<signed char>(fl_get_counter_value(fd_form_document->slider_secnumdepth));
2727         if (params->secnumdepth != tmpchar)
2728                 redo = true;
2729         params->secnumdepth = tmpchar;
2730    
2731         params->tocdepth =  
2732                 static_cast<int>(fl_get_counter_value(fd_form_document->slider_tocdepth));
2733
2734         params->float_placement = 
2735                 fl_get_input(fd_form_document->input_float_placement);
2736
2737         // More checking should be done to ensure the string doesn't have
2738         // spaces or illegal placement characters in it. (thornley)
2739
2740         if (redo)
2741                 current_view->redoCurrentBuffer();
2742    
2743         current_view->owner()->getMiniBuffer()->Set(_("Document layout set"));
2744         current_view->buffer()->markDirty();
2745
2746         params->options = 
2747                 fl_get_input(fd_form_document->input_extra);
2748    
2749 }
2750
2751
2752 extern "C" void DocumentCancelCB(FL_OBJECT *, long)
2753 {
2754         fl_hide_form(fd_form_document->form_document);
2755 }
2756
2757
2758 extern "C" void DocumentOKCB(FL_OBJECT * ob, long data)
2759 {
2760         DocumentCancelCB(ob, data);
2761         DocumentApplyCB(ob, data);
2762 }
2763
2764
2765 extern "C" void DocumentBulletsCB(FL_OBJECT *, long)
2766 {
2767         bulletForm();
2768         // bullet callbacks etc. in bullet_panel.C -- ARRae
2769 }
2770
2771
2772 /* callbacks for form form_quotes */
2773
2774 extern "C" void QuotesApplyCB(FL_OBJECT *, long)
2775 {
2776         if (!current_view->available())
2777                 return;
2778         
2779         current_view->owner()->getMiniBuffer()->Set(_("Quotes type set"));
2780         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
2781         switch(fl_get_choice(fd_form_quotes->choice_quotes_language) - 1) {
2782         case 0:
2783                 lga = InsetQuotes::EnglishQ;
2784                 break;
2785         case 1:
2786                 lga = InsetQuotes::SwedishQ;
2787                 break;
2788         case 2:
2789                 lga = InsetQuotes::GermanQ;
2790                 break;
2791         case 3:
2792                 lga = InsetQuotes::PolishQ;
2793                 break;
2794         case 4:
2795                 lga = InsetQuotes::FrenchQ;
2796                 break;
2797         case 5:
2798                 lga = InsetQuotes::DanishQ;
2799                 break;
2800         }
2801         current_view->buffer()->params.quotes_language = lga;
2802         if (fl_get_button(fd_form_quotes->radio_single))   
2803                 current_view->buffer()->
2804                         params.quotes_times = InsetQuotes::SingleQ;
2805         else
2806                 current_view->buffer()->
2807                         params.quotes_times = InsetQuotes::DoubleQ;
2808 }
2809
2810
2811 extern "C" void QuotesCancelCB(FL_OBJECT *, long)
2812 {
2813         fl_hide_form(fd_form_quotes->form_quotes);
2814 }
2815
2816
2817 extern "C" void QuotesOKCB(FL_OBJECT * ob, long data)
2818 {
2819         QuotesApplyCB(ob, data);
2820         QuotesCancelCB(ob, data);
2821 }
2822
2823
2824
2825 /* callbacks for form form_preamble */
2826
2827 extern "C" void PreambleCancelCB(FL_OBJECT *, long)
2828 {
2829         fl_hide_form(fd_form_preamble->form_preamble);
2830 }
2831
2832
2833 extern "C" void PreambleApplyCB(FL_OBJECT *, long)
2834 {
2835         if (!current_view->available())
2836                 return;
2837         
2838         current_view->buffer()->params.preamble = 
2839                 fl_get_input(fd_form_preamble->input_preamble);
2840         current_view->buffer()->markDirty();
2841         current_view->owner()->getMiniBuffer()->Set(_("LaTeX preamble set"));
2842 }
2843
2844    
2845 extern "C" void PreambleOKCB(FL_OBJECT * ob, long data)
2846 {
2847         PreambleApplyCB(ob, data);
2848         PreambleCancelCB(ob, data);
2849 }
2850
2851
2852 /* callbacks for form form_table */
2853
2854 extern "C" void TableApplyCB(FL_OBJECT *, long)
2855 {
2856         if (!current_view->available())
2857                 return;
2858    
2859         // check for tables in tables
2860         if (current_view->text->cursor.par->table){
2861                 WriteAlert(_("Impossible Operation!"),
2862                            _("Cannot insert table in table."),
2863                            _("Sorry."));
2864                 return;
2865         }
2866  
2867         current_view->owner()->getMiniBuffer()->Set(_("Inserting table..."));
2868
2869         int ysize = int(fl_get_slider_value(fd_form_table->slider_columns) + 0.5);
2870         int xsize = int(fl_get_slider_value(fd_form_table->slider_rows) + 0.5);
2871    
2872    
2873         current_view->hideCursor();
2874         current_view->beforeChange();
2875         current_view->update(-2);
2876    
2877         current_view->text->SetCursorParUndo(); 
2878         current_view->text->FreezeUndo();
2879
2880         current_view->text->BreakParagraph();
2881         current_view->update(-1);
2882    
2883         if (current_view->text->cursor.par->Last()) {
2884                 current_view->text->CursorLeft();
2885       
2886                 current_view->text->BreakParagraph();
2887                 current_view->update(-1);
2888         }
2889
2890         current_view->text->current_font.setLatex(LyXFont::OFF);
2891         //if (!fl_get_button(fd_form_table->check_latex)){
2892         // insert the new wysiwy table
2893         current_view->text->SetLayout(0); // standard layout
2894         if (current_view->text->cursor.par->footnoteflag == 
2895             LyXParagraph::NO_FOOTNOTE) {
2896                 current_view->text
2897                         ->SetParagraph(0, 0,
2898                                        0, 0,
2899                                        VSpace (0.3 * current_view->buffer()->
2900                                                params.spacing.getValue(),
2901                                                LyXLength::CM),
2902                                        VSpace (0.3 * current_view->buffer()->
2903                                                params.spacing.getValue(),
2904                                                LyXLength::CM),
2905                                        LYX_ALIGN_CENTER,
2906                                        string(),
2907                                        0);
2908         } else {
2909                 current_view->text
2910                         ->SetParagraph(0, 0,
2911                                        0, 0,
2912                                        VSpace(VSpace::NONE),
2913                                        VSpace(VSpace::NONE),
2914                                        LYX_ALIGN_CENTER, 
2915                                        string(),
2916                                        0);
2917         }
2918         
2919         current_view->text->cursor.par->table =
2920                 new LyXTable(xsize, ysize);
2921
2922         for (int i = 0; i < xsize * ysize - 1; ++i)
2923                 current_view->text->cursor.par->InsertChar(0, LyXParagraph::META_NEWLINE);
2924         current_view->text->RedoParagraph();
2925    
2926         current_view->text->UnFreezeUndo();
2927      
2928         current_view->update(1);
2929         current_view->owner()->getMiniBuffer()->Set(_("Table inserted"));
2930         current_view->setState();
2931 }
2932
2933
2934 extern "C" void TableCancelCB(FL_OBJECT *, long)
2935 {
2936         fl_hide_form(fd_form_table->form_table);
2937 }
2938
2939
2940 extern "C" void TableOKCB(FL_OBJECT * ob, long data)
2941 {
2942         TableApplyCB(ob, data);
2943         TableCancelCB(ob, data);
2944 }
2945
2946
2947 /* callbacks for form form_print */
2948
2949 extern "C" void PrintCancelCB(FL_OBJECT *, long)
2950 {
2951         fl_hide_form(fd_form_print->form_print);
2952 }
2953
2954
2955 static
2956 bool stringOnlyContains (string const & LStr, char const * cset)
2957 {
2958         char const * cstr = LStr.c_str() ;
2959
2960         return strspn(cstr, cset) == strlen(cstr) ;
2961 }
2962
2963
2964 extern "C" void PrintApplyCB(FL_OBJECT *, long)
2965 {
2966         if (!current_view->available())
2967                 return;
2968         Buffer * buffer = current_view->buffer();
2969         string path = OnlyPath(buffer->fileName());
2970
2971         string pageflag;
2972         if (fl_get_button(fd_form_print->radio_even_pages))
2973                 pageflag = lyxrc->print_evenpage_flag + ' ';
2974         else if (fl_get_button(fd_form_print->radio_odd_pages))
2975                 pageflag = lyxrc->print_oddpage_flag + ' ';
2976
2977 // Changes by Stephan Witt (stephan.witt@beusen.de), 19-Jan-99
2978 // User may give a page (range) list
2979 // User may print multiple (unsorted) copies
2980         string pages = subst(fl_get_input(fd_form_print->input_pages), ';',',');
2981         pages = subst(pages, '+',',');
2982         pages = frontStrip(strip(pages)) ;
2983         while (!pages.empty()) { // a page range was given
2984                 string piece ;
2985                 pages = split (pages, piece, ',') ;
2986                 piece = strip(piece) ;
2987                 piece = frontStrip(piece) ;
2988                 if ( !stringOnlyContains (piece, "0123456789-") ) {
2989                         WriteAlert(_("ERROR!  Unable to print!"),
2990                                    _("Check 'range of pages'!"));
2991                         return;
2992                 }
2993                 if (piece.find('-') == string::npos) { // not found
2994                         pageflag += lyxrc->print_pagerange_flag + piece + '-' + piece + ' ' ;
2995                 } else if (suffixIs(piece, "-") ) { // missing last page
2996                         pageflag += lyxrc->print_pagerange_flag + piece + "1000 ";
2997                 } else if (prefixIs(piece, "-") ) { // missing first page
2998                         pageflag += lyxrc->print_pagerange_flag + '1' + piece + ' ' ;
2999                 } else {
3000                         pageflag += lyxrc->print_pagerange_flag + piece + ' ' ;
3001                 }
3002         }
3003    
3004         string copies = frontStrip(strip(fl_get_input(fd_form_print->input_copies)));
3005         if (!copies.empty()) { // a number of copies was given
3006                 if ( !stringOnlyContains (copies, "0123456789") ) {
3007                         WriteAlert(_("ERROR!  Unable to print!"),
3008                                    _("Check 'number of copies'!"));
3009                         return;
3010                 }
3011                 if (fl_get_button(fd_form_print->do_unsorted))
3012                         pageflag += lyxrc->print_copies_flag;
3013                 else
3014                         pageflag += lyxrc->print_collcopies_flag;
3015                 pageflag += " " + copies + ' ' ;
3016         }
3017
3018         string reverseflag;
3019         if (fl_get_button(fd_form_print->radio_order_reverse))
3020                 reverseflag = lyxrc->print_reverse_flag + ' ';
3021    
3022         string orientationflag;
3023         if (buffer->params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
3024                 orientationflag = lyxrc->print_landscape_flag + ' ';
3025    
3026         string ps_file = fl_get_input(fd_form_print->input_file);
3027         string printer = strip(fl_get_input(fd_form_print->input_printer));
3028
3029         string printerflag;
3030         if (lyxrc->print_adapt_output // printer name should be passed to dvips
3031             && ! printer.empty()) // a printer name has been given
3032                 printerflag = lyxrc->print_to_printer + printer + ' ';
3033      
3034         string extraflags;
3035         if (!lyxrc->print_extra_options.empty())
3036                 extraflags = lyxrc->print_extra_options + ' ';
3037
3038         string command = lyxrc->print_command + ' ' 
3039                 + printerflag + pageflag + reverseflag 
3040                 + orientationflag + extraflags;
3041  
3042         char real_papersize = buffer->params.papersize;
3043         if (real_papersize == BufferParams::PAPER_DEFAULT)
3044                 real_papersize = lyxrc->default_papersize;
3045         
3046         string paper;
3047         switch (real_papersize) {
3048         case BufferParams::PAPER_USLETTER:
3049                 paper = "letter";
3050                 break;
3051         case BufferParams::PAPER_A3PAPER:
3052                 paper = "a3";
3053                 break;
3054         case BufferParams::PAPER_A4PAPER:
3055                 paper = "a4";
3056                 break;
3057         case BufferParams::PAPER_A5PAPER:
3058                 paper = "a5";
3059                 break;
3060         case BufferParams::PAPER_B5PAPER:
3061                 paper = "b5";
3062                 break;
3063         case BufferParams::PAPER_EXECUTIVEPAPER:
3064                 paper = "foolscap";
3065                 break;
3066         case BufferParams::PAPER_LEGALPAPER:
3067                 paper = "legal";
3068                 break;
3069         default: /* If nothing else fits, keep an empty value... */
3070                 break;
3071         }
3072
3073         if (buffer->params.use_geometry
3074             && buffer->params.papersize2 == BufferParams::VM_PAPER_CUSTOM
3075             && !lyxrc->print_paper_dimension_flag.empty()
3076             && !buffer->params.paperwidth.empty()
3077             && !buffer->params.paperheight.empty()) {
3078                 // using a custom papersize
3079                 command += ' ';
3080                 command += lyxrc->print_paper_dimension_flag + ' ';
3081                 command += buffer->params.paperwidth + ',';
3082                 command += buffer->params.paperheight + ' ';
3083         } else if (!lyxrc->print_paper_flag.empty()
3084                    && !paper.empty()
3085                    && (real_papersize != BufferParams::PAPER_USLETTER ||
3086                        buffer->params.orientation == BufferParams::ORIENTATION_PORTRAIT)) {
3087                 command += " " + lyxrc->print_paper_flag + " " + paper + " ";
3088         }
3089         if (fl_get_button(fd_form_print->radio_file))
3090                 command += lyxrc->print_to_file 
3091                         + QuoteName(MakeAbsPath(ps_file, path));
3092         else if (!lyxrc->print_spool_command.empty())
3093                 command += lyxrc->print_to_file 
3094                         + QuoteName(ps_file);
3095         
3096         // push directorypath, if necessary 
3097         if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)){
3098                 path = buffer->tmppath;
3099         }
3100         Path p(path);
3101
3102         bool result;
3103         if (!lyxrc->print_spool_command.empty() && 
3104             !fl_get_button(fd_form_print->radio_file)) {
3105                 string command2 = lyxrc->print_spool_command + ' ';
3106                 if (!printer.empty())
3107                         command2 += lyxrc->print_spool_printerprefix 
3108                                 + printer;
3109                 // First run dvips and, if succesful, then spool command
3110                 if ((result = RunScript(buffer, true, command))) {
3111                         result = RunScript(buffer, false, command2, ps_file);
3112                 }
3113         } else
3114                 result = RunScript(buffer, false, command);
3115
3116         if (!result)
3117                 WriteAlert(_("Error:"),
3118                            _("Unable to print"),
3119                            _("Check that your parameters are correct"));
3120 }
3121
3122
3123 extern "C" void PrintOKCB(FL_OBJECT * ob, long data)
3124 {
3125         PrintCancelCB(ob, data);  
3126         PrintApplyCB(ob, data);
3127 }
3128
3129
3130 /* callbacks for form form_figure */
3131 extern "C" void FigureApplyCB(FL_OBJECT *, long)
3132 {
3133         if (!current_view->available())
3134                 return;
3135
3136         Buffer * buffer = current_view->buffer();
3137         if(buffer->isReadonly()) // paranoia
3138                 return;
3139         
3140         current_view->owner()->getMiniBuffer()->Set(_("Inserting figure..."));
3141         if (fl_get_button(fd_form_figure->radio_inline)
3142             || current_view->text->cursor.par->table) {
3143                 InsetFig * new_inset = new InsetFig(100, 20, buffer);
3144                 current_view->insertInset(new_inset);
3145                 current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
3146                 new_inset->Edit(current_view, 0, 0);
3147                 return;
3148         }
3149         
3150         current_view->hideCursor();
3151         current_view->update(-2);
3152         current_view->beforeChange();
3153       
3154         current_view->text->SetCursorParUndo(); 
3155         current_view->text->FreezeUndo();
3156
3157         current_view->text->BreakParagraph();
3158         current_view->update(-1);
3159       
3160         if (current_view->text->cursor.par->Last()) {
3161                 current_view->text->CursorLeft();
3162          
3163                 current_view->text->BreakParagraph();
3164                 current_view->update(-1);
3165         }
3166
3167         // The standard layout should always be numer 0;
3168         current_view->text->SetLayout(0);
3169         
3170         if (current_view->text->cursor.par->footnoteflag == 
3171             LyXParagraph::NO_FOOTNOTE) {
3172                 current_view->text->
3173                         SetParagraph(0, 0,
3174                                      0, 0,
3175                                      VSpace (0.3 * buffer->params.spacing.getValue(),
3176                                              LyXLength::CM),
3177                                      VSpace (0.3 *
3178                                              buffer->params.spacing.getValue(),
3179                                              LyXLength::CM),
3180                                      LYX_ALIGN_CENTER, string(), 0);
3181         } else {
3182                 current_view->text->SetParagraph(0, 0,
3183                                                  0, 0,
3184                                                  VSpace(VSpace::NONE),
3185                                                  VSpace(VSpace::NONE),
3186                                                  LYX_ALIGN_CENTER, 
3187                                                  string(),
3188                                                  0);
3189         }
3190         
3191         current_view->update(-1);
3192       
3193         Inset * new_inset = new InsetFig(100, 100, buffer);
3194         current_view->insertInset(new_inset);
3195         new_inset->Edit(current_view, 0, 0);
3196         current_view->update(0);
3197         current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
3198         current_view->text->UnFreezeUndo();
3199         current_view->setState();
3200 }
3201
3202
3203 extern "C" void FigureCancelCB(FL_OBJECT *, long)
3204 {
3205         fl_hide_form(fd_form_figure->form_figure);
3206 }
3207
3208
3209 extern "C" void FigureOKCB(FL_OBJECT * ob, long data)
3210 {
3211         FigureApplyCB(ob, data);
3212         FigureCancelCB(ob, data);
3213 }
3214
3215
3216 extern "C" void ScreenApplyCB(FL_OBJECT *, long)
3217 {
3218         lyxrc->roman_font_name = fl_get_input(fd_form_screen->input_roman);
3219         lyxrc->sans_font_name = fl_get_input(fd_form_screen->input_sans);
3220         lyxrc->typewriter_font_name = fl_get_input(fd_form_screen->input_typewriter);
3221         lyxrc->font_norm = fl_get_input(fd_form_screen->input_font_norm);
3222         lyxrc->zoom = atoi(fl_get_input(fd_form_screen->intinput_size));
3223         fontloader.update();
3224    
3225         // All buffers will need resize
3226         bufferlist.resize();
3227
3228         current_view->owner()->getMiniBuffer()->Set(_("Screen options set"));
3229 }
3230
3231
3232 extern "C" void ScreenCancelCB(FL_OBJECT *, long)
3233 {
3234         fl_hide_form(fd_form_screen->form_screen);
3235 }
3236
3237
3238 extern "C" void ScreenOKCB(FL_OBJECT * ob, long data)
3239 {
3240         ScreenCancelCB(ob, data);
3241         ScreenApplyCB(ob, data);
3242 }
3243
3244
3245 void LaTeXOptions(BufferView * bv)
3246 {
3247         if (!bv->available())
3248                 return;
3249
3250         fl_set_button(fd_latex_options->accents,
3251                       int(bv->buffer()->params.allowAccents));
3252         
3253         if (fd_latex_options->LaTeXOptions->visible) {
3254                 fl_raise_form(fd_latex_options->LaTeXOptions);
3255         } else {
3256                 fl_show_form(fd_latex_options->LaTeXOptions,
3257                              FL_PLACE_MOUSE, FL_FULLBORDER,
3258                              _("LaTeX Options"));
3259         }
3260 }
3261
3262
3263 // This function runs "configure" and then rereads lyx.defaults to
3264 // reconfigure the automatic settings.
3265 void Reconfigure(BufferView * bv)
3266 {
3267         bv->owner()->getMiniBuffer()->Set(_("Running configure..."));
3268
3269         // Run configure in user lyx directory
3270         Path p(user_lyxdir);
3271         Systemcalls one(Systemcalls::System, 
3272                         AddName(system_lyxdir, "configure"));
3273         p.pop();
3274         bv->owner()->getMiniBuffer()->Set(_("Reloading configuration..."));
3275         lyxrc->read(LibFileSearch(string(), "lyxrc.defaults"));
3276         WriteAlert(_("The system has been reconfigured."), 
3277                    _("You need to restart LyX to make use of any"),
3278                    _("updated document class specifications."));
3279 }
3280
3281
3282 //
3283 // Table of Contents
3284 //
3285
3286 struct TocList {
3287         int counter[6];
3288         bool appendix;
3289         TocList * next;
3290 };
3291
3292
3293 static TocList * toclist = 0;
3294
3295
3296 extern "C" void TocSelectCB(FL_OBJECT * ob, long)
3297 {
3298         if (!current_view->available())
3299                 return;
3300    
3301         TocList * tmptoclist = toclist;
3302         int i = fl_get_browser(ob);
3303         for (int a = 1; a < i && tmptoclist->next; ++a) {
3304                 tmptoclist = tmptoclist->next;
3305         }
3306
3307         if (!tmptoclist)
3308                 return;
3309      
3310
3311         LyXParagraph * par = current_view->buffer()->paragraph;
3312         while (par && (par->GetFirstCounter(0) != tmptoclist->counter[0] ||
3313                        par->GetFirstCounter(1) != tmptoclist->counter[1] ||
3314                        par->GetFirstCounter(2) != tmptoclist->counter[2] ||
3315                        par->GetFirstCounter(3) != tmptoclist->counter[3] ||
3316                        par->GetFirstCounter(4) != tmptoclist->counter[4] ||
3317                        par->GetFirstCounter(5) != tmptoclist->counter[5] ||
3318                        par->appendix != tmptoclist->appendix)) {
3319                 par = par->LastPhysicalPar()->Next();
3320         }
3321    
3322         if (par) {
3323                 current_view->beforeChange();
3324                 current_view->text->SetCursor(par, 0);
3325                 current_view->text->sel_cursor = 
3326                         current_view->text->cursor;
3327                 current_view->update(0);
3328         }
3329         else {
3330                 WriteAlert(_("Error"), 
3331                            _("Couldn't find this label"), 
3332                            _("in current document."));
3333         }
3334           
3335 }
3336
3337
3338 extern "C" void TocCancelCB(FL_OBJECT *, long)
3339 {
3340         fl_hide_form(fd_form_toc->form_toc);
3341 }
3342
3343
3344 extern "C" void TocUpdateCB(FL_OBJECT *, long)
3345 {
3346         static LyXParagraph * stapar = 0;
3347         TocList * tmptoclist = 0;
3348    
3349         /* deleted the toclist */ 
3350         if (toclist){
3351                 while (toclist){
3352                         tmptoclist = toclist->next;
3353                         delete toclist;
3354                         toclist = tmptoclist;
3355                 }
3356         }
3357         toclist = 0;
3358         tmptoclist = toclist;
3359
3360
3361         fl_clear_browser(fd_form_toc->browser_toc);
3362         if (!current_view->available()) {
3363                 fl_add_browser_line(fd_form_toc->browser_toc,
3364                                     _("*** No Document ***"));
3365                 return;
3366         }
3367         fl_hide_object(fd_form_toc->browser_toc);
3368         /* get the table of contents */ 
3369         LyXParagraph * par = current_view->buffer()->paragraph;
3370         char labeltype;
3371         char * line = new char[200];
3372         int pos = 0;
3373         unsigned char c;
3374         int topline = 0;
3375    
3376         if (stapar == par)
3377                 topline = fl_get_browser_topline(fd_form_toc->browser_toc);
3378         stapar = par;
3379    
3380         while (par) {
3381                 labeltype = textclasslist.Style(current_view->buffer()->params.textclass, 
3382                                                 par->GetLayout()).labeltype;
3383       
3384                 if (labeltype >= LABEL_COUNTER_CHAPTER
3385                     && labeltype <= LABEL_COUNTER_CHAPTER +
3386                     current_view->buffer()->params.tocdepth) {
3387                         /* insert this into the table of contents */ 
3388                         /* first indent a little bit */ 
3389                         
3390                         for (pos = 0; 
3391                              pos < (labeltype - 
3392                                     textclasslist.TextClass(current_view->buffer()->
3393                                                             params.textclass).maxcounter()) * 4 + 2;
3394                              ++pos)
3395                                 line[pos] = ' ';
3396                         
3397                         // Then the labestring
3398                         if (!par->labelstring.empty()) {
3399                                 string::size_type i = 0;
3400                                 while (pos < 199 && i < par->labelstring.length()) {
3401                                         line[pos] = par->labelstring[i];
3402                                         ++i;
3403                                         ++pos;
3404                                 }
3405                         }
3406          
3407                         line[pos] = ' ';
3408                         ++pos;
3409                         
3410                         /* now the contents */
3411                         LyXParagraph::size_type i = 0;
3412                         while (pos < 199 && i < par->size()) {
3413                                 c = par->GetChar(i);
3414                                 if (isprint(c) || c >= 128) {
3415                                         line[pos] = c;
3416                                         ++pos;
3417                                 }
3418                                 ++i;
3419                         }
3420                         line[pos] = '\0';
3421                         fl_add_browser_line(fd_form_toc->browser_toc, line);
3422                         
3423                         /* make a toclist entry */
3424                         if (!tmptoclist){
3425                                 tmptoclist = new TocList;
3426                                 toclist = tmptoclist;
3427                         } else {
3428                                 tmptoclist->next = new TocList;
3429                                 tmptoclist = tmptoclist->next;
3430                         }
3431                         
3432                         tmptoclist->next = 0;
3433                         int a = 0;
3434                         for (a = 0; a < 6; ++a) {
3435                                 tmptoclist->counter[a] = par->GetFirstCounter(a);
3436                         }
3437                         tmptoclist->appendix = par->appendix;
3438                 }
3439                 par = par->LastPhysicalPar()->Next();
3440                 
3441         }
3442         delete[] line;
3443         fl_set_browser_topline(fd_form_toc->browser_toc, topline);
3444         fl_show_object(fd_form_toc->browser_toc);
3445 }
3446
3447
3448 /* callbacks for form form_ref */
3449 extern "C" void RefSelectCB(FL_OBJECT *, long data)
3450 {
3451         if (!current_view->available())
3452                 return;
3453
3454         string s = 
3455                 fl_get_browser_line(fd_form_ref->browser_ref,
3456                                     fl_get_browser(fd_form_ref->browser_ref));
3457         string u = frontStrip(strip(fl_get_input(fd_form_ref->ref_name)));
3458
3459         if (s.empty())
3460                 return;
3461
3462         if (data == 2) {
3463                 current_view->owner()->getLyXFunc()->Dispatch(LFUN_REFGOTO, s.c_str());
3464                 return;
3465         }
3466             
3467         string t;
3468         if (data == 0)
3469                 t += "\\ref";
3470         else
3471                 t += "\\pageref";
3472
3473         if(current_view->buffer()->isSGML())
3474                 t += "[" + u + "]" + "{" + s + "}";
3475         else
3476                 t += "{" + s + "}";
3477
3478         Inset * new_inset = 
3479                 new InsetRef(t, current_view->buffer());
3480         current_view->insertInset(new_inset);
3481 }
3482
3483
3484 extern "C" void RefUpdateCB(FL_OBJECT *, long)
3485 {
3486         if (!current_view->available()) {
3487                 fl_clear_browser(fd_form_ref->browser_ref);
3488                 return;
3489         }
3490
3491         FL_OBJECT * brow = fd_form_ref->browser_ref;
3492
3493         // Get the current line, in order to restore it later
3494         char const * const btmp = fl_get_browser_line(brow,
3495                                                       fl_get_browser(brow));
3496         string currentstr = btmp ? btmp : "";
3497
3498         fl_clear_browser(brow);
3499
3500         string refs = current_view->buffer()->getReferenceList('\n');
3501         int topline = 1;
3502
3503         fl_addto_browser_chars(brow, refs.c_str());
3504         int total_lines = fl_get_browser_maxline(brow);
3505         for (int i = 1; i <= total_lines ; ++i) {
3506                 if (fl_get_browser_line(brow, i) == currentstr) {
3507                         topline = i;
3508                         break;
3509                 }
3510         }
3511         fl_set_browser_topline(brow, topline);
3512
3513         if (!fl_get_browser_maxline(brow)) {
3514                 fl_add_browser_line(brow, 
3515                                     _("*** No labels found in document ***"));
3516                 fl_deactivate_object(brow);
3517         } else {
3518                 fl_select_browser_line(brow, topline);
3519                 fl_activate_object(brow);
3520         }
3521         if (current_view->buffer()->isReadonly()) {
3522                 // would be better to de/activate insert buttons
3523                 // but that's more work... besides this works. ARRae
3524                 fl_hide_form(fd_form_ref->form_ref);
3525         }
3526         if (!current_view->buffer()->isSGML()) {
3527                 fl_deactivate_object(fd_form_ref->ref_name);
3528                 fl_set_object_lcol(fd_form_ref->ref_name, FL_INACTIVE);
3529         }
3530         else {
3531                 fl_activate_object(fd_form_ref->ref_name);
3532                 fl_set_object_lcol(fd_form_ref->ref_name, FL_BLACK);
3533         }
3534 }
3535
3536
3537 extern "C" void RefHideCB(FL_OBJECT *, long)
3538 {
3539         fl_hide_form(fd_form_ref->form_ref);
3540 }
3541
3542 #ifdef WITH_WARNINGS
3543 #warning UGLY!!
3544 #endif
3545 // I know we shouldn't put anything in here but this seems the fastest
3546 // way to do this (and the cleanest for now). This function just inserts
3547 // a newline in the string and the inserts 'depth'-spaces so that the
3548 // code is indented in the right way!!!
3549 void addNewlineAndDepth(string & file, int const depth)
3550 {
3551         file += '\n';
3552         file.append(depth, ' ');
3553 }