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