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