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