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