]> git.lyx.org Git - lyx.git/blob - src/lyx_cb.C
ecdf613ac1836fd5bc34dc1985d76936c551626c
[lyx.git] / src / lyx_cb.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1995 Matthias Ettrich,
7  *          Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include <fstream>
14 #include <algorithm>
15 #include <iostream>
16
17 #include FORMS_H_LOCATION
18 #include "lyx.h"
19 #include "layout_forms.h"
20 //#include "form1.h"
21 #include "lyx_main.h"
22 #include "lyx_cb.h"
23 //#include "insets/insetref.h"
24 #include "insets/insetlabel.h"
25 #include "insets/figinset.h"
26 #include "lyxfunc.h"
27 #include "minibuffer.h"
28 #include "combox.h"
29 #include "bufferlist.h"
30 #include "filedlg.h"
31 #include "lyx_gui_misc.h"
32 #include "LyXView.h"
33 //#include "BufferView.h"
34 #include "lastfiles.h"
35 #include "bufferview_funcs.h"
36 #include "support/FileInfo.h"
37 #include "support/syscall.h"
38 #include "support/filetools.h"
39 #include "support/path.h"
40 //#include "support/lyxlib.h"
41 //#include "lyxserver.h"
42 #include "lyxrc.h"
43 #include "lyxtext.h"
44 //#include "CutAndPaste.h"
45 //#include "exporter.h"
46
47 using std::ifstream;
48 using std::copy;
49 using std::back_inserter;
50 using std::endl;
51 using std::cout;
52 using std::ios;
53 using std::istream_iterator;
54 using std::pair;
55 using std::vector;
56 using std::sort;
57 using std::equal;
58
59 extern Combox * combo_language;
60 extern Combox * combo_language2;
61 extern BufferList bufferlist;
62 extern void show_symbols_form();
63 extern FD_form_title * fd_form_title;
64 extern FD_form_character * fd_form_character;
65 extern FD_form_preamble * fd_form_preamble;
66 extern FD_form_figure * fd_form_figure;
67
68 extern BufferView * current_view; // called too many times in this file...
69
70 extern void DeleteSimpleCutBuffer(); /* for the cleanup when exiting */
71
72 #if 0
73 extern bool send_fax(string const & fname, string const & sendcmd);
74 #endif
75
76 extern void MenuSendto();
77
78 //extern LyXServer * lyxserver;
79
80 // this should be static, but I need it in buffer.C
81 bool quitting;  // flag, that we are quitting the program
82 extern bool finished; // all cleanup done just let it run through now.
83
84 char ascii_type; /* for selection notify callbacks */
85
86 bool scrolling = false;
87
88 // This is used to make the dreaded font toggle problem hopefully go
89 // away. Definitely not the best solution, but I think it sorta works.
90 bool toggleall = true;
91
92 /* 
93    This is the inset locking stuff needed for mathed --------------------
94
95    an inset can simple call LockInset in it's edit call and *ONLY* in it's
96    edit call.
97    Inset::Edit() can only be called by the main lyx module.
98
99    Then the inset may modify the menu's and/or iconbars. 
100
101    Unlocking is either done by LyX or the inset itself with a UnlockInset-call
102
103    During the lock, all button and keyboard events will be modified
104    and send to the inset through the following inset-features. Note that
105    Inset::InsetUnlock will be called from inside UnlockInset. It is meant
106    to contain the code for restoring the menus and things like this.
107
108    
109    virtual void InsetButtonPress(int x, int y, int button);
110    virtual void InsetButtonRelease(int x, int y, int button);
111    virtual void InsetKeyPress(XKeyEvent *ev);
112    virtual void InsetMotionNotify(int x, int y, int state);
113    virtual void InsetUnlock();
114
115    If a inset wishes any redraw and/or update it just has to call
116    UpdateInset(this).
117    It's is completly irrelevant, where the inset is. UpdateInset will
118    find it in any paragraph in any buffer. 
119    Of course the_locking_inset and the insets in the current paragraph/buffer
120    are checked first, so no performance problem should occur.
121    
122    Hope that's ok for the beginning, Alejandro,
123    sorry that I needed so much time,
124
125                   Matthias
126    */
127
128 //void UpdateInset(BufferView * bv, Inset * inset, bool mark_dirty = true);
129
130 /* these functions return 1 if an error occured, 
131    otherwise 0 */
132 // Now they work only for updatable insets. [Alejandro 080596]
133 //int LockInset(UpdatableInset * inset);
134 void ToggleLockedInsetCursor(int x, int y, int asc, int desc);
135 //void FitLockedInsetCursor(long x, long y, int asc, int desc);
136 //int UnlockInset(UpdatableInset * inset);
137 //void LockedInsetStoreUndo(Undo::undo_kind kind);
138
139 /* this is for asyncron updating. UpdateInsetUpdateList will be called
140    automatically from LyX. Just insert the Inset into the Updatelist */
141 //void UpdateInsetUpdateList();
142 //void PutInsetIntoInsetUpdateList(Inset * inset);
143
144 //InsetUpdateStruct * InsetUpdateList = 0;
145
146
147 /*
148   -----------------------------------------------------------------------
149  */
150
151 /* some function prototypes */
152
153 int RunLinuxDoc(BufferView *, int, string const &);
154 int RunDocBook(int, string const &);
155 bool MenuWrite(Buffer * buf);
156 bool MenuWriteAs(Buffer * buffer);
157 void MenuReload(Buffer * buf);
158 void MenuLayoutSave();
159
160
161 void ShowMessage(Buffer const * buf,
162                  string const & msg1,
163                  string const & msg2,
164                  string const & msg3, int delay)
165 {
166         if (lyxrc.use_gui)
167                 buf->getUser()->owner()->getMiniBuffer()->Set(msg1, msg2,
168                                                               msg3, delay);
169         else
170                 lyxerr << msg1 << msg2 << msg3 << endl;
171 }
172
173
174 //
175 // Menu callbacks
176 //
177
178 //
179 // File menu
180 //
181
182 // should be moved to lyxfunc.C
183 bool MenuWrite(Buffer * buffer)
184 {
185         XFlush(fl_get_display());
186         if (!buffer->save()) {
187                 string fname = buffer->fileName();
188                 string s = MakeAbsPath(fname);
189                 if (AskQuestion(_("Save failed. Rename and try again?"),
190                                 MakeDisplayPath(s, 50),
191                                 _("(If not, document is not saved.)"))) {
192                         return MenuWriteAs(buffer);
193                 }
194                 return false;
195         } else {
196                 lastfiles->newFile(buffer->fileName());
197         }
198         return true;
199 }
200
201
202 // should be moved to BufferView.C
203 // Half of this func should be in LyXView, the rest in BufferView.
204 bool MenuWriteAs(Buffer * buffer)
205 {
206         // Why do we require BufferView::text to be able to write a
207         // document? I see no point in that. (Lgb)
208         //if (!bv->text) return;
209
210         string fname = buffer->fileName();
211         string oldname = fname;
212         LyXFileDlg fileDlg;
213
214         ProhibitInput(current_view);
215         fileDlg.SetButton(0, _("Documents"), lyxrc.document_path);
216         fileDlg.SetButton(1, _("Templates"), lyxrc.template_path);
217
218         if (!IsLyXFilename(fname))
219                 fname += ".lyx";
220
221         if (buffer->isUnnamed()) {
222                 fname = fileDlg.Select(_("Enter Filename to Save Document as"), 
223                                        "",
224                                        "*.lyx", 
225                                        "");
226         } else {
227                 fname = fileDlg.Select(_("Enter Filename to Save Document as"), 
228                                        OnlyPath(fname),
229                                        "*.lyx", 
230                                        OnlyFilename(fname));
231         }
232         AllowInput(current_view);
233
234         if (fname.empty()) {
235                 return false;
236         }
237         // Make sure the absolute filename ends with appropriate suffix
238         string s = MakeAbsPath(fname);
239         if (!IsLyXFilename(s))
240                 s += ".lyx";
241
242         // Same name as we have already?
243         if (s == oldname) {
244                 if (!AskQuestion(_("Same name as document already has:"),
245                                  MakeDisplayPath(s, 50),
246                                  _("Save anyway?")))
247                         return false;
248                 // Falls through to name change and save
249         } 
250         // No, but do we have another file with this name open?
251         else if (bufferlist.exists(s)) {
252                 if (AskQuestion(_("Another document with same name open!"),
253                                 MakeDisplayPath(s, 50),
254                                 _("Replace with current document?")))
255                         {
256                                 bufferlist.close(bufferlist.getBuffer(s));
257
258                                 // Ok, change the name of the buffer, but don't save!
259                                 buffer->setFileName(s);
260                                 buffer->markDirty();
261
262                                 ShowMessage(buffer, _("Document renamed to '"),
263                                                 MakeDisplayPath(s), _("', but not saved..."));
264                         }
265                 return false;
266         } // Check whether the file exists
267         else {
268                 FileInfo myfile(s);
269                 if (myfile.isOK() && !AskQuestion(_("Document already exists:"), 
270                                                   MakeDisplayPath(s, 50),
271                                                   _("Replace file?")))
272                         return false;
273         }
274
275         // Ok, change the name of the buffer
276         buffer->setFileName(s);
277         buffer->markDirty();
278         bool unnamed = buffer->isUnnamed();
279         buffer->setUnnamed(false);
280         // And save
281         // Small bug: If the save fails, we have irreversible changed the name
282         // of the document.
283         // Hope this is fixed this way! (Jug)
284         if (!MenuWrite(buffer)) {
285             buffer->setFileName(oldname);
286             buffer->setUnnamed(unnamed);
287             ShowMessage(buffer, _("Document could not be saved!"),
288                         _("Holding the old name."), MakeDisplayPath(oldname));
289             return false;
290         }
291         // now remove the oldname autosave file if existant!
292         removeAutosaveFile(oldname);
293         return true;
294 }
295
296
297 int MenuRunChktex(Buffer * buffer)
298 {
299         int ret;
300
301         if (buffer->isSGML()) {
302                 WriteAlert(_("Chktex does not work with SGML derived documents."));
303                 return 0;
304         } else 
305                 ret = buffer->runChktex();
306    
307         if (ret >= 0) {
308                 string s;
309                 string t;
310                 if (ret == 0) {
311                         s = _("No warnings found.");
312                 } else if (ret == 1) {
313                         s = _("One warning found.");
314                         t = _("Use 'Edit->Go to Error' to find it.");
315                 } else {
316                         s += tostr(ret);
317                         s += _(" warnings found.");
318                         t = _("Use 'Edit->Go to Error' to find them.");
319                 }
320                 WriteAlert(_("Chktex run successfully"), s, t);
321         } else {
322                 WriteAlert(_("Error!"), _("It seems chktex does not work."));
323         }
324         return ret;
325 }
326
327 #if 0
328 void MenuFax(Buffer * buffer)
329 {
330         // Generate postscript file
331         if (!Exporter::Export(buffer, "ps", true))
332                 return;
333
334         // Send fax
335         string const ps = OnlyFilename(ChangeExtension(buffer->fileName(), 
336                                                        ".ps"));
337
338         string path = OnlyPath (buffer->fileName());
339         if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) {
340                 path = buffer->tmppath;
341         }
342         Path p(path);
343         if (!lyxrc.fax_program.empty()) {
344                 string help2 = subst(lyxrc.fax_program, "$$FName", ps);
345                 help2 += " &";
346                 Systemcalls one(Systemcalls::System, help2);
347         } else
348                 send_fax(ps, lyxrc.fax_command);
349 }
350 #endif
351
352
353 void QuitLyX()
354 {
355         lyxerr.debug() << "Running QuitLyX." << endl;
356
357         if (!bufferlist.QwriteAll())
358                 return;
359
360         lastfiles->writeFile(lyxrc.lastfiles);
361
362         // Set a flag that we do quitting from the program,
363         // so no refreshes are necessary.
364         quitting = true;
365
366         // close buffers first
367         bufferlist.closeAll();
368
369         // do any other cleanup procedures now
370         lyxerr.debug() << "Deleting tmp dir " << system_tempdir << endl;
371
372         DestroyLyXTmpDir(system_tempdir);
373
374         finished = true;
375 }
376
377
378
379 void AutoSave(BufferView * bv)
380         // should probably be moved into BufferList (Lgb)
381         // Perfect target for a thread...
382 {
383         if (!bv->available())
384                 return;
385
386         if (bv->buffer()->isBakClean() || bv->buffer()->isReadonly()) {
387                 // We don't save now, but we'll try again later
388                 bv->owner()->resetAutosaveTimer();
389                 return;
390         }
391
392         bv->owner()->getMiniBuffer()->Set(_("Autosaving current document..."));
393         
394         // create autosave filename
395         string fname =  OnlyPath(bv->buffer()->fileName());
396         fname += "#";
397         fname += OnlyFilename(bv->buffer()->fileName());
398         fname += "#";
399         
400         // tmp_ret will be located (usually) in /tmp
401         // will that be a problem?
402         pid_t pid = fork(); // If you want to debug the autosave
403         // you should set pid to -1, and comment out the
404         // fork.
405         if (pid == 0 || pid == -1) {
406                 // pid = -1 signifies that lyx was unable
407                 // to fork. But we will do the save
408                 // anyway.
409                 bool failed = false;
410                 
411                 string tmp_ret = lyx::tempName();
412                 if (!tmp_ret.empty()) {
413                         bv->buffer()->writeFile(tmp_ret, 1);
414                         // assume successful write of tmp_ret
415                         if (lyx::rename(tmp_ret, fname)) {
416                                 failed = true;
417                                 // most likely couldn't move between filesystems
418                                 // unless write of tmp_ret failed
419                                 // so remove tmp file (if it exists)
420                                 lyx::unlink(tmp_ret);
421                         }
422                 } else {
423                         failed = true;
424                 }
425                 
426                 if (failed) {
427                         // failed to write/rename tmp_ret so try writing direct
428                         if (!bv->buffer()->writeFile(fname, 1)) {
429                                 // It is dangerous to do this in the child,
430                                 // but safe in the parent, so...
431                                 if (pid == -1)
432                                         bv->owner()->getMiniBuffer()->Set(_("Autosave Failed!"));
433                         }
434                 }
435                 if (pid == 0) { // we are the child so...
436                         _exit(0);
437                 }
438         }
439         
440         bv->buffer()->markBakClean();
441         bv->owner()->resetAutosaveTimer();
442 }
443
444
445 //
446 // Copyright CHT Software Service GmbH
447 // Uwe C. Schroeder
448 //
449 // create new file with template
450 // SERVERCMD !
451 //
452 Buffer * NewLyxFile(string const & filename)
453 {
454         // Split argument by :
455         string name;
456         string tmpname = split(filename, name, ':');
457 #ifdef __EMX__ // Fix me! lyx_cb.C may not be low level enough to allow this.
458         if (name.length() == 1
459             && isalpha(static_cast<unsigned char>(name[0]))
460             && (prefixIs(tmpname, "/") || prefixIs(tmpname, "\\"))) {
461                 name += ':';
462                 name += token(tmpname, ':', 0);
463                 tmpname = split(tmpname, ':');
464         }
465 #endif
466         lyxerr.debug() << "Arg is " << filename
467                        << "\nName is " << name
468                        << "\nTemplate is " << tmpname << endl;
469
470         // find a free buffer 
471         Buffer * tmpbuf = bufferlist.newFile(name, tmpname);
472         if (tmpbuf)
473                 lastfiles->newFile(tmpbuf->fileName());
474         return tmpbuf;
475 }
476
477
478 // Insert ascii file (if filename is empty, prompt for one)
479 void InsertAsciiFile(BufferView * bv, string const & f, bool asParagraph)
480 {
481         string fname = f;
482         LyXFileDlg fileDlg;
483  
484         if (!bv->available()) return;
485      
486         if (fname.empty()) {
487                 ProhibitInput(bv);
488                 fname = fileDlg.Select(_("File to Insert"), 
489                                        bv->owner()->buffer()->filepath,
490                                        "*");
491                 AllowInput(bv);
492                 if (fname.empty()) return;
493         }
494
495         FileInfo fi(fname);
496
497         if (!fi.readable()) {
498                 WriteFSAlert(_("Error! Specified file is unreadable: "),
499                              MakeDisplayPath(fname, 50));
500                 return;
501         }
502
503         ifstream ifs(fname.c_str());
504         if (!ifs) {
505                 WriteFSAlert(_("Error! Cannot open specified file: "),
506                              MakeDisplayPath(fname, 50));
507                 return;
508         }
509
510         ifs.unsetf(ios::skipws);
511         istream_iterator<char> ii(ifs);
512         istream_iterator<char> end;
513 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
514         // We use this until the compilers get better...
515         vector<char> tmp;
516         copy(ii, end, back_inserter(tmp));
517         string tmpstr(tmp.begin(), tmp.end());
518 #else
519         // This is what we want to use and what we will use once the
520         // compilers get good enough. 
521         //string tmpstr(ii, end); // yet a reason for using std::string
522         // alternate approach to get the file into a string:
523         string tmpstr;
524         copy(ii, end, back_inserter(tmpstr));
525 #endif
526         // insert the string
527         bv->hideCursor();
528         
529         // clear the selection
530         bv->beforeChange();
531         if (!asParagraph)
532                 bv->text->InsertStringA(bv, tmpstr);
533         else
534                 bv->text->InsertStringB(bv, tmpstr);
535         bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
536 }
537
538
539 void MenuInsertLabel(string const & arg)
540 {
541         string label(arg);
542         ProhibitInput(current_view);
543         if (label.empty()) {
544                 pair<bool, string>
545                         result = askForText(_("Enter new label to insert:"));
546                 if (result.first) {
547                         label = frontStrip(strip(result.second));
548                 }
549         }
550         if (!label.empty()) {
551                 InsetCommandParams p( "label", label );
552                 InsetLabel * inset = new InsetLabel( p );
553                 current_view->insertInset( inset );
554         }
555         AllowInput(current_view);
556 }
557
558
559 // This is _only_ used in Toolbar_pimpl.C, move it there and get rid of
560 // current_view. (Lgb)
561 void LayoutsCB(int sel, void *, Combox *)
562 {
563         string tmp = tostr(sel);
564         current_view->owner()->getLyXFunc()->Dispatch(LFUN_LAYOUTNO,
565                                                       tmp);
566 }
567
568
569 void MenuLayoutCharacter()
570 {
571         static int ow = -1, oh;
572
573         if (fd_form_character->form_character->visible) {
574                 fl_raise_form(fd_form_character->form_character);
575         } else {
576                 fl_show_form(fd_form_character->form_character,
577                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
578                              _("Character Style"));
579                 if (ow < 0) {
580                         ow = fd_form_character->form_character->w;
581                         oh = fd_form_character->form_character->h;
582                 }
583                 fl_set_form_minsize(fd_form_character->form_character, ow, oh);
584         }
585 }
586
587
588 bool UpdateLayoutPreamble()
589 {
590         bool update = true;
591         if (!current_view->available())
592                 update = false;
593
594         if (update) {
595                 fl_set_input(fd_form_preamble->input_preamble,
596                              current_view->buffer()->params.preamble.c_str());
597
598                 if (current_view->buffer()->isReadonly()) {
599                         fl_deactivate_object(fd_form_preamble->input_preamble);
600                         fl_deactivate_object(fd_form_preamble->button_ok);
601                         fl_deactivate_object(fd_form_preamble->button_apply);
602                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_INACTIVE);
603                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_INACTIVE);
604                 }
605                 else {
606                         fl_activate_object(fd_form_preamble->input_preamble);
607                         fl_activate_object(fd_form_preamble->button_ok);
608                         fl_activate_object(fd_form_preamble->button_apply);
609                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_BLACK);
610                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_BLACK);
611                 }
612         } else if (fd_form_preamble->form_preamble->visible) {
613                 fl_hide_form(fd_form_preamble->form_preamble);
614         }
615         return update;
616 }
617
618
619 void MenuLayoutPreamble()
620 {
621         static int ow = -1, oh;
622
623         if (UpdateLayoutPreamble()) {
624                 if (fd_form_preamble->form_preamble->visible) {
625                         fl_raise_form(fd_form_preamble->form_preamble);
626                 } else {
627                         fl_show_form(fd_form_preamble->form_preamble,
628                                      FL_PLACE_MOUSE | FL_FREE_SIZE,
629                                      FL_TRANSIENT,
630                                      _("LaTeX Preamble"));
631                         if (ow < 0) {
632                                 ow = fd_form_preamble->form_preamble->w;
633                                 oh = fd_form_preamble->form_preamble->h;
634                         }
635                         fl_set_form_minsize(fd_form_preamble->form_preamble,
636                                             ow, oh);
637                 }
638         }
639 }
640
641
642 void MenuLayoutSave()
643 {
644         if (!current_view->available())
645                 return;
646
647         if (AskQuestion(_("Do you want to save the current settings"),
648                         _("for Character, Document, Paper and Quotes"),
649                         _("as default for new documents?")))
650                 current_view->buffer()->saveParamsAsDefaults();
651 }
652
653
654 // This is both GUI and LyXFont dependent. Don't know where to put it. (Asger)
655 // Well, it's mostly GUI dependent, so I guess it will stay here. (Asger)
656 LyXFont const UserFreeFont(BufferParams const & params)
657 {
658         LyXFont font(LyXFont::ALL_IGNORE);
659
660         int pos = fl_get_choice(fd_form_character->choice_family);
661         switch (pos) {
662         case 1: font.setFamily(LyXFont::IGNORE_FAMILY); break;
663         case 2: font.setFamily(LyXFont::ROMAN_FAMILY); break;
664         case 3: font.setFamily(LyXFont::SANS_FAMILY); break;
665         case 4: font.setFamily(LyXFont::TYPEWRITER_FAMILY); break;
666         case 5: font.setFamily(LyXFont::INHERIT_FAMILY); break;
667         }
668
669         pos = fl_get_choice(fd_form_character->choice_series);
670         switch (pos) {
671         case 1: font.setSeries(LyXFont::IGNORE_SERIES); break;
672         case 2: font.setSeries(LyXFont::MEDIUM_SERIES); break;
673         case 3: font.setSeries(LyXFont::BOLD_SERIES); break;
674         case 4: font.setSeries(LyXFont::INHERIT_SERIES); break;
675         }
676
677         pos = fl_get_choice(fd_form_character->choice_shape);
678         switch (pos) {
679         case 1: font.setShape(LyXFont::IGNORE_SHAPE); break;
680         case 2: font.setShape(LyXFont::UP_SHAPE); break;
681         case 3: font.setShape(LyXFont::ITALIC_SHAPE); break;
682         case 4: font.setShape(LyXFont::SLANTED_SHAPE); break;
683         case 5: font.setShape(LyXFont::SMALLCAPS_SHAPE); break;
684         case 6: font.setShape(LyXFont::INHERIT_SHAPE); break;
685         }
686
687         pos = fl_get_choice(fd_form_character->choice_size);
688         switch (pos) {
689         case 1: font.setSize(LyXFont::IGNORE_SIZE); break;
690         case 2: font.setSize(LyXFont::SIZE_TINY); break;
691         case 3: font.setSize(LyXFont::SIZE_SCRIPT); break;
692         case 4: font.setSize(LyXFont::SIZE_FOOTNOTE); break;
693         case 5: font.setSize(LyXFont::SIZE_SMALL); break;
694         case 6: font.setSize(LyXFont::SIZE_NORMAL); break;
695         case 7: font.setSize(LyXFont::SIZE_LARGE); break;
696         case 8: font.setSize(LyXFont::SIZE_LARGER); break;
697         case 9: font.setSize(LyXFont::SIZE_LARGEST); break;
698         case 10: font.setSize(LyXFont::SIZE_HUGE); break;
699         case 11: font.setSize(LyXFont::SIZE_HUGER); break;
700         case 12: font.setSize(LyXFont::INCREASE_SIZE); break;
701         case 13: font.setSize(LyXFont::DECREASE_SIZE); break;
702         case 14: font.setSize(LyXFont::INHERIT_SIZE); break;
703         }
704
705         pos = fl_get_choice(fd_form_character->choice_bar);
706         switch (pos) {
707         case 1: font.setEmph(LyXFont::IGNORE);
708                 font.setUnderbar(LyXFont::IGNORE);
709                 font.setNoun(LyXFont::IGNORE);
710                 font.setLatex(LyXFont::IGNORE);
711                 break;
712         case 2: font.setEmph(LyXFont::TOGGLE); break;
713         case 3: font.setUnderbar(LyXFont::TOGGLE); break;
714         case 4: font.setNoun(LyXFont::TOGGLE); break;
715         case 5: font.setLatex(LyXFont::TOGGLE); break;
716         case 6: font.setEmph(LyXFont::INHERIT);
717                 font.setUnderbar(LyXFont::INHERIT);
718                 font.setNoun(LyXFont::INHERIT);
719                 font.setLatex(LyXFont::INHERIT);
720                 break;
721         }
722
723         pos = fl_get_choice(fd_form_character->choice_color);
724         switch (pos) {
725         case 1: font.setColor(LColor::ignore); break;
726         case 2: font.setColor(LColor::none); break;
727         case 3: font.setColor(LColor::black); break;
728         case 4: font.setColor(LColor::white); break;
729         case 5: font.setColor(LColor::red); break;
730         case 6: font.setColor(LColor::green); break;
731         case 7: font.setColor(LColor::blue); break;
732         case 8: font.setColor(LColor::cyan); break;
733         case 9: font.setColor(LColor::magenta); break;
734         case 10: font.setColor(LColor::yellow); break;
735         case 11: font.setColor(LColor::inherit); break;
736         }
737
738         int const choice = combo_language2->get();
739         if (choice == 1)
740                 font.setLanguage(ignore_language);
741         else if (choice == 2)
742                 font.setLanguage(params.language);
743         else
744                 font.setLanguage(languages.getLanguage(combo_language2->getline()));
745
746         return font; 
747 }
748
749
750 /* callbacks for form form_title */
751 extern "C" void TimerCB(FL_OBJECT *, long)
752 {
753         // only if the form still exists
754         if (lyxrc.show_banner
755             && fd_form_title
756             && fd_form_title->form_title) {
757                 if (fd_form_title->form_title->visible) {
758                         fl_hide_form(fd_form_title->form_title);
759                 }
760                 fl_free_form(fd_form_title->form_title);
761                 fd_form_title->form_title = 0;
762         }
763 }
764
765
766 /* callbacks for form form_character */
767
768 extern "C" void CharacterApplyCB(FL_OBJECT *, long)
769 {
770         // we set toggleall locally here, since it should be true for
771         // all other uses of ToggleAndShow() (JMarc)
772         toggleall = fl_get_button(fd_form_character->check_toggle_all);
773         ToggleAndShow(current_view, UserFreeFont(current_view->buffer()->params));
774         current_view->setState();
775         toggleall = true;
776 }
777
778
779 extern "C" void CharacterCloseCB(FL_OBJECT *, long)
780 {
781         fl_hide_form(fd_form_character->form_character);
782 }
783
784
785 extern "C" void CharacterOKCB(FL_OBJECT *ob, long data)
786 {
787         CharacterApplyCB(ob, data);
788         CharacterCloseCB(ob, data);
789 }
790
791
792 /* callbacks for form form_preamble */
793
794 extern "C" void PreambleCancelCB(FL_OBJECT *, long)
795 {
796         fl_hide_form(fd_form_preamble->form_preamble);
797 }
798
799
800 extern "C" void PreambleApplyCB(FL_OBJECT *, long)
801 {
802         if (!current_view->available())
803                 return;
804         
805         current_view->buffer()->params.preamble = 
806                 fl_get_input(fd_form_preamble->input_preamble);
807         current_view->buffer()->markDirty();
808         current_view->owner()->getMiniBuffer()->Set(_("LaTeX preamble set"));
809 }
810
811    
812 extern "C" void PreambleOKCB(FL_OBJECT * ob, long data)
813 {
814         PreambleApplyCB(ob, data);
815         PreambleCancelCB(ob, data);
816 }
817
818
819 void Figure()
820 {
821         if (fd_form_figure->form_figure->visible) {
822                 fl_raise_form(fd_form_figure->form_figure);
823         } else {
824                 fl_show_form(fd_form_figure->form_figure,
825                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
826                              _("Insert Figure"));
827         }
828 }
829
830
831 /* callbacks for form form_figure */
832 extern "C"
833 void FigureApplyCB(FL_OBJECT *, long)
834 {
835         if (!current_view->available())
836                 return;
837
838         Buffer * buffer = current_view->buffer();
839         if (buffer->isReadonly()) // paranoia
840                 return;
841         
842         current_view->owner()->getMiniBuffer()->Set(_("Inserting figure..."));
843         if (fl_get_button(fd_form_figure->radio_inline)) {
844                 InsetFig * new_inset = new InsetFig(100, 20, *buffer);
845                 current_view->insertInset(new_inset);
846                 current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
847                 new_inset->Edit(current_view, 0, 0, 0);
848                 return;
849         }
850         
851         current_view->hideCursor();
852         current_view->update(BufferView::SELECT|BufferView::FITCUR);
853         current_view->beforeChange();
854       
855         current_view->text->SetCursorParUndo(current_view->buffer()); 
856         current_view->text->FreezeUndo();
857
858         current_view->text->BreakParagraph(current_view);
859         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
860       
861         if (current_view->text->cursor.par()->Last()) {
862                 current_view->text->CursorLeft(current_view);
863          
864                 current_view->text->BreakParagraph(current_view);
865                 current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
866         }
867
868         // The standard layout should always be numer 0;
869         current_view->text->SetLayout(current_view, 0);
870
871 #ifndef NEW_INSETS
872         if (current_view->text->cursor.par()->footnoteflag == 
873             LyXParagraph::NO_FOOTNOTE) {
874 #endif
875                 current_view->text->
876                         SetParagraph(current_view, 0, 0,
877                                      0, 0,
878                                      VSpace (0.3 * buffer->params.spacing.getValue(),
879                                              LyXLength::CM),
880                                      VSpace (0.3 *
881                                              buffer->params.spacing.getValue(),
882                                              LyXLength::CM),
883                                      LYX_ALIGN_CENTER, string(), 0);
884 #ifndef NEW_INSETS
885         } else {
886                 current_view->text->SetParagraph(current_view, 0, 0,
887                                                  0, 0,
888                                                  VSpace(VSpace::NONE),
889                                                  VSpace(VSpace::NONE),
890                                                  LYX_ALIGN_CENTER, 
891                                                  string(),
892                                                  0);
893         }
894 #endif
895         
896         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
897       
898         Inset * new_inset = new InsetFig(100, 100, *buffer);
899         current_view->insertInset(new_inset);
900         new_inset->Edit(current_view, 0, 0, 0);
901         current_view->update(BufferView::SELECT|BufferView::FITCUR);
902         current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
903         current_view->text->UnFreezeUndo();
904         current_view->setState();
905 }
906
907
908 extern "C" void FigureCancelCB(FL_OBJECT *, long)
909 {
910         fl_hide_form(fd_form_figure->form_figure);
911 }
912
913
914 extern "C" void FigureOKCB(FL_OBJECT * ob, long data)
915 {
916         FigureApplyCB(ob, data);
917         FigureCancelCB(ob, data);
918 }
919
920
921 // This function runs "configure" and then rereads lyx.defaults to
922 // reconfigure the automatic settings.
923 void Reconfigure(BufferView * bv)
924 {
925         bv->owner()->getMiniBuffer()->Set(_("Running configure..."));
926
927         // Run configure in user lyx directory
928         Path p(user_lyxdir);
929         Systemcalls one(Systemcalls::System, 
930                         AddName(system_lyxdir, "configure"));
931         p.pop();
932         bv->owner()->getMiniBuffer()->Set(_("Reloading configuration..."));
933         lyxrc.read(LibFileSearch(string(), "lyxrc.defaults"));
934         WriteAlert(_("The system has been reconfigured."), 
935                    _("You need to restart LyX to make use of any"),
936                    _("updated document class specifications."));
937 }