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