]> git.lyx.org Git - features.git/blob - src/lyx_cb.C
Color patch from Angus, KDE patch from Johnm menu patch from Rob, and the usual unint...
[features.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         fname = fileDlg.Select(_("Enter Filename to Save Document as"), 
222                                OnlyPath(fname),
223                                "*.lyx", 
224                                OnlyFilename(fname));
225
226         AllowInput(current_view);
227
228         if (fname.empty())
229                 return false;
230
231         // Make sure the absolute filename ends with appropriate suffix
232         string s = MakeAbsPath(fname);
233         if (!IsLyXFilename(s))
234                 s += ".lyx";
235
236         // Same name as we have already?
237         if (!buffer->isUnnamed() && s == oldname) {
238                 if (!AskQuestion(_("Same name as document already has:"),
239                                  MakeDisplayPath(s, 50),
240                                  _("Save anyway?")))
241                         return false;
242                 // Falls through to name change and save
243         } 
244         // No, but do we have another file with this name open?
245         else if (!buffer->isUnnamed() && bufferlist.exists(s)) {
246                 if (AskQuestion(_("Another document with same name open!"),
247                                 MakeDisplayPath(s, 50),
248                                 _("Replace with current document?")))
249                         {
250                                 bufferlist.close(bufferlist.getBuffer(s));
251
252                                 // Ok, change the name of the buffer, but don't save!
253                                 buffer->setFileName(s);
254                                 buffer->markDirty();
255
256                                 ShowMessage(buffer, _("Document renamed to '"),
257                                                 MakeDisplayPath(s), _("', but not saved..."));
258                         }
259                 return false;
260         } // Check whether the file exists
261         else {
262                 FileInfo myfile(s);
263                 if (myfile.isOK() && !AskQuestion(_("Document already exists:"), 
264                                                   MakeDisplayPath(s, 50),
265                                                   _("Replace file?")))
266                         return false;
267         }
268
269         // Ok, change the name of the buffer
270         buffer->setFileName(s);
271         buffer->markDirty();
272         bool unnamed = buffer->isUnnamed();
273         buffer->setUnnamed(false);
274         // And save
275         // Small bug: If the save fails, we have irreversible changed the name
276         // of the document.
277         // Hope this is fixed this way! (Jug)
278         if (!MenuWrite(buffer)) {
279             buffer->setFileName(oldname);
280             buffer->setUnnamed(unnamed);
281             ShowMessage(buffer, _("Document could not be saved!"),
282                         _("Holding the old name."), MakeDisplayPath(oldname));
283             return false;
284         }
285         // now remove the oldname autosave file if existant!
286         removeAutosaveFile(oldname);
287         return true;
288 }
289
290
291 int MenuRunChktex(Buffer * buffer)
292 {
293         int ret;
294
295         if (buffer->isSGML()) {
296                 WriteAlert(_("Chktex does not work with SGML derived documents."));
297                 return 0;
298         } else 
299                 ret = buffer->runChktex();
300    
301         if (ret >= 0) {
302                 string s;
303                 string t;
304                 if (ret == 0) {
305                         s = _("No warnings found.");
306                 } else if (ret == 1) {
307                         s = _("One warning found.");
308                         t = _("Use 'Edit->Go to Error' to find it.");
309                 } else {
310                         s += tostr(ret);
311                         s += _(" warnings found.");
312                         t = _("Use 'Edit->Go to Error' to find them.");
313                 }
314                 WriteAlert(_("Chktex run successfully"), s, t);
315         } else {
316                 WriteAlert(_("Error!"), _("It seems chktex does not work."));
317         }
318         return ret;
319 }
320
321 #if 0
322 void MenuFax(Buffer * buffer)
323 {
324         // Generate postscript file
325         if (!Exporter::Export(buffer, "ps", true))
326                 return;
327
328         // Send fax
329         string const ps = OnlyFilename(ChangeExtension(buffer->fileName(), 
330                                                        ".ps"));
331
332         string path = OnlyPath (buffer->fileName());
333         if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) {
334                 path = buffer->tmppath;
335         }
336         Path p(path);
337         if (!lyxrc.fax_program.empty()) {
338                 string help2 = subst(lyxrc.fax_program, "$$FName", ps);
339                 help2 += " &";
340                 Systemcalls one(Systemcalls::System, help2);
341         } else
342                 send_fax(ps, lyxrc.fax_command);
343 }
344 #endif
345
346
347 void QuitLyX()
348 {
349         lyxerr.debug() << "Running QuitLyX." << endl;
350
351         if (!bufferlist.QwriteAll())
352                 return;
353
354         lastfiles->writeFile(lyxrc.lastfiles);
355
356         // Set a flag that we do quitting from the program,
357         // so no refreshes are necessary.
358         quitting = true;
359
360         // close buffers first
361         bufferlist.closeAll();
362
363         // do any other cleanup procedures now
364         lyxerr.debug() << "Deleting tmp dir " << system_tempdir << endl;
365
366         DestroyLyXTmpDir(system_tempdir);
367
368         finished = true;
369 }
370
371
372
373 void AutoSave(BufferView * bv)
374         // should probably be moved into BufferList (Lgb)
375         // Perfect target for a thread...
376 {
377         if (!bv->available())
378                 return;
379
380         if (bv->buffer()->isBakClean() || bv->buffer()->isReadonly()) {
381                 // We don't save now, but we'll try again later
382                 bv->owner()->resetAutosaveTimer();
383                 return;
384         }
385
386         bv->owner()->getMiniBuffer()->Set(_("Autosaving current document..."));
387         
388         // create autosave filename
389         string fname =  OnlyPath(bv->buffer()->fileName());
390         fname += "#";
391         fname += OnlyFilename(bv->buffer()->fileName());
392         fname += "#";
393         
394         // tmp_ret will be located (usually) in /tmp
395         // will that be a problem?
396         pid_t pid = fork(); // If you want to debug the autosave
397         // you should set pid to -1, and comment out the
398         // fork.
399         if (pid == 0 || pid == -1) {
400                 // pid = -1 signifies that lyx was unable
401                 // to fork. But we will do the save
402                 // anyway.
403                 bool failed = false;
404                 
405                 string tmp_ret = lyx::tempName();
406                 if (!tmp_ret.empty()) {
407                         bv->buffer()->writeFile(tmp_ret, 1);
408                         // assume successful write of tmp_ret
409                         if (lyx::rename(tmp_ret, fname)) {
410                                 failed = true;
411                                 // most likely couldn't move between filesystems
412                                 // unless write of tmp_ret failed
413                                 // so remove tmp file (if it exists)
414                                 lyx::unlink(tmp_ret);
415                         }
416                 } else {
417                         failed = true;
418                 }
419                 
420                 if (failed) {
421                         // failed to write/rename tmp_ret so try writing direct
422                         if (!bv->buffer()->writeFile(fname, 1)) {
423                                 // It is dangerous to do this in the child,
424                                 // but safe in the parent, so...
425                                 if (pid == -1)
426                                         bv->owner()->getMiniBuffer()->Set(_("Autosave Failed!"));
427                         }
428                 }
429                 if (pid == 0) { // we are the child so...
430                         _exit(0);
431                 }
432         }
433         
434         bv->buffer()->markBakClean();
435         bv->owner()->resetAutosaveTimer();
436 }
437
438
439 //
440 // Copyright CHT Software Service GmbH
441 // Uwe C. Schroeder
442 //
443 // create new file with template
444 // SERVERCMD !
445 //
446 Buffer * NewLyxFile(string const & filename)
447 {
448         // Split argument by :
449         string name;
450         string tmpname = split(filename, name, ':');
451 #ifdef __EMX__ // Fix me! lyx_cb.C may not be low level enough to allow this.
452         if (name.length() == 1
453             && isalpha(static_cast<unsigned char>(name[0]))
454             && (prefixIs(tmpname, "/") || prefixIs(tmpname, "\\"))) {
455                 name += ':';
456                 name += token(tmpname, ':', 0);
457                 tmpname = split(tmpname, ':');
458         }
459 #endif
460         lyxerr.debug() << "Arg is " << filename
461                        << "\nName is " << name
462                        << "\nTemplate is " << tmpname << endl;
463
464         // find a free buffer 
465         Buffer * tmpbuf = bufferlist.newFile(name, tmpname);
466         if (tmpbuf)
467                 lastfiles->newFile(tmpbuf->fileName());
468         return tmpbuf;
469 }
470
471
472 // Insert ascii file (if filename is empty, prompt for one)
473 void InsertAsciiFile(BufferView * bv, string const & f, bool asParagraph)
474 {
475         string fname = f;
476         LyXFileDlg fileDlg;
477  
478         if (!bv->available()) return;
479      
480         if (fname.empty()) {
481                 ProhibitInput(bv);
482                 fname = fileDlg.Select(_("File to Insert"), 
483                                        bv->owner()->buffer()->filepath,
484                                        "*");
485                 AllowInput(bv);
486                 if (fname.empty()) return;
487         }
488
489         FileInfo fi(fname);
490
491         if (!fi.readable()) {
492                 WriteFSAlert(_("Error! Specified file is unreadable: "),
493                              MakeDisplayPath(fname, 50));
494                 return;
495         }
496
497         ifstream ifs(fname.c_str());
498         if (!ifs) {
499                 WriteFSAlert(_("Error! Cannot open specified file: "),
500                              MakeDisplayPath(fname, 50));
501                 return;
502         }
503
504         ifs.unsetf(ios::skipws);
505         istream_iterator<char> ii(ifs);
506         istream_iterator<char> end;
507 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
508         // We use this until the compilers get better...
509         vector<char> tmp;
510         copy(ii, end, back_inserter(tmp));
511         string tmpstr(tmp.begin(), tmp.end());
512 #else
513         // This is what we want to use and what we will use once the
514         // compilers get good enough. 
515         //string tmpstr(ii, end); // yet a reason for using std::string
516         // alternate approach to get the file into a string:
517         string tmpstr;
518         copy(ii, end, back_inserter(tmpstr));
519 #endif
520         // insert the string
521         bv->hideCursor();
522         
523         // clear the selection
524         bv->beforeChange();
525         if (!asParagraph)
526                 bv->text->InsertStringA(bv, tmpstr);
527         else
528                 bv->text->InsertStringB(bv, tmpstr);
529         bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
530 }
531
532
533 void MenuInsertLabel(string const & arg)
534 {
535         string label(arg);
536         ProhibitInput(current_view);
537         if (label.empty()) {
538                 pair<bool, string>
539                         result = askForText(_("Enter new label to insert:"));
540                 if (result.first) {
541                         label = frontStrip(strip(result.second));
542                 }
543         }
544         if (!label.empty()) {
545                 InsetCommandParams p( "label", label );
546                 InsetLabel * inset = new InsetLabel( p );
547                 current_view->insertInset( inset );
548         }
549         AllowInput(current_view);
550 }
551
552
553 // This is _only_ used in Toolbar_pimpl.C, move it there and get rid of
554 // current_view. (Lgb)
555 void LayoutsCB(int sel, void *, Combox *)
556 {
557         string tmp = tostr(sel);
558         current_view->owner()->getLyXFunc()->Dispatch(LFUN_LAYOUTNO,
559                                                       tmp);
560 }
561
562
563 void MenuLayoutCharacter()
564 {
565         static int ow = -1, oh;
566
567         if (fd_form_character->form_character->visible) {
568                 fl_raise_form(fd_form_character->form_character);
569         } else {
570                 fl_show_form(fd_form_character->form_character,
571                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
572                              _("Character Style"));
573                 if (ow < 0) {
574                         ow = fd_form_character->form_character->w;
575                         oh = fd_form_character->form_character->h;
576                 }
577                 fl_set_form_minsize(fd_form_character->form_character, ow, oh);
578         }
579 }
580
581
582 bool UpdateLayoutPreamble()
583 {
584         bool update = true;
585         if (!current_view->available())
586                 update = false;
587
588         if (update) {
589                 fl_set_input(fd_form_preamble->input_preamble,
590                              current_view->buffer()->params.preamble.c_str());
591
592                 if (current_view->buffer()->isReadonly()) {
593                         fl_deactivate_object(fd_form_preamble->input_preamble);
594                         fl_deactivate_object(fd_form_preamble->button_ok);
595                         fl_deactivate_object(fd_form_preamble->button_apply);
596                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_INACTIVE);
597                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_INACTIVE);
598                 }
599                 else {
600                         fl_activate_object(fd_form_preamble->input_preamble);
601                         fl_activate_object(fd_form_preamble->button_ok);
602                         fl_activate_object(fd_form_preamble->button_apply);
603                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_BLACK);
604                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_BLACK);
605                 }
606         } else if (fd_form_preamble->form_preamble->visible) {
607                 fl_hide_form(fd_form_preamble->form_preamble);
608         }
609         return update;
610 }
611
612
613 void MenuLayoutPreamble()
614 {
615         static int ow = -1, oh;
616
617         if (UpdateLayoutPreamble()) {
618                 if (fd_form_preamble->form_preamble->visible) {
619                         fl_raise_form(fd_form_preamble->form_preamble);
620                 } else {
621                         fl_show_form(fd_form_preamble->form_preamble,
622                                      FL_PLACE_MOUSE | FL_FREE_SIZE,
623                                      FL_TRANSIENT,
624                                      _("LaTeX Preamble"));
625                         if (ow < 0) {
626                                 ow = fd_form_preamble->form_preamble->w;
627                                 oh = fd_form_preamble->form_preamble->h;
628                         }
629                         fl_set_form_minsize(fd_form_preamble->form_preamble,
630                                             ow, oh);
631                 }
632         }
633 }
634
635
636 void MenuLayoutSave()
637 {
638         if (!current_view->available())
639                 return;
640
641         if (AskQuestion(_("Do you want to save the current settings"),
642                         _("for Character, Document, Paper and Quotes"),
643                         _("as default for new documents?")))
644                 current_view->buffer()->saveParamsAsDefaults();
645 }
646
647
648 // This is both GUI and LyXFont dependent. Don't know where to put it. (Asger)
649 // Well, it's mostly GUI dependent, so I guess it will stay here. (Asger)
650 LyXFont const UserFreeFont(BufferParams const & params)
651 {
652         LyXFont font(LyXFont::ALL_IGNORE);
653
654         int pos = fl_get_choice(fd_form_character->choice_family);
655         switch (pos) {
656         case 1: font.setFamily(LyXFont::IGNORE_FAMILY); break;
657         case 2: font.setFamily(LyXFont::ROMAN_FAMILY); break;
658         case 3: font.setFamily(LyXFont::SANS_FAMILY); break;
659         case 4: font.setFamily(LyXFont::TYPEWRITER_FAMILY); break;
660         case 5: font.setFamily(LyXFont::INHERIT_FAMILY); break;
661         }
662
663         pos = fl_get_choice(fd_form_character->choice_series);
664         switch (pos) {
665         case 1: font.setSeries(LyXFont::IGNORE_SERIES); break;
666         case 2: font.setSeries(LyXFont::MEDIUM_SERIES); break;
667         case 3: font.setSeries(LyXFont::BOLD_SERIES); break;
668         case 4: font.setSeries(LyXFont::INHERIT_SERIES); break;
669         }
670
671         pos = fl_get_choice(fd_form_character->choice_shape);
672         switch (pos) {
673         case 1: font.setShape(LyXFont::IGNORE_SHAPE); break;
674         case 2: font.setShape(LyXFont::UP_SHAPE); break;
675         case 3: font.setShape(LyXFont::ITALIC_SHAPE); break;
676         case 4: font.setShape(LyXFont::SLANTED_SHAPE); break;
677         case 5: font.setShape(LyXFont::SMALLCAPS_SHAPE); break;
678         case 6: font.setShape(LyXFont::INHERIT_SHAPE); break;
679         }
680
681         pos = fl_get_choice(fd_form_character->choice_size);
682         switch (pos) {
683         case 1: font.setSize(LyXFont::IGNORE_SIZE); break;
684         case 2: font.setSize(LyXFont::SIZE_TINY); break;
685         case 3: font.setSize(LyXFont::SIZE_SCRIPT); break;
686         case 4: font.setSize(LyXFont::SIZE_FOOTNOTE); break;
687         case 5: font.setSize(LyXFont::SIZE_SMALL); break;
688         case 6: font.setSize(LyXFont::SIZE_NORMAL); break;
689         case 7: font.setSize(LyXFont::SIZE_LARGE); break;
690         case 8: font.setSize(LyXFont::SIZE_LARGER); break;
691         case 9: font.setSize(LyXFont::SIZE_LARGEST); break;
692         case 10: font.setSize(LyXFont::SIZE_HUGE); break;
693         case 11: font.setSize(LyXFont::SIZE_HUGER); break;
694         case 12: font.setSize(LyXFont::INCREASE_SIZE); break;
695         case 13: font.setSize(LyXFont::DECREASE_SIZE); break;
696         case 14: font.setSize(LyXFont::INHERIT_SIZE); break;
697         }
698
699         pos = fl_get_choice(fd_form_character->choice_bar);
700         switch (pos) {
701         case 1: font.setEmph(LyXFont::IGNORE);
702                 font.setUnderbar(LyXFont::IGNORE);
703                 font.setNoun(LyXFont::IGNORE);
704                 font.setLatex(LyXFont::IGNORE);
705                 break;
706         case 2: font.setEmph(LyXFont::TOGGLE); break;
707         case 3: font.setUnderbar(LyXFont::TOGGLE); break;
708         case 4: font.setNoun(LyXFont::TOGGLE); break;
709         case 5: font.setLatex(LyXFont::TOGGLE); break;
710         case 6: font.setEmph(LyXFont::INHERIT);
711                 font.setUnderbar(LyXFont::INHERIT);
712                 font.setNoun(LyXFont::INHERIT);
713                 font.setLatex(LyXFont::INHERIT);
714                 break;
715         }
716
717         pos = fl_get_choice(fd_form_character->choice_color);
718         switch (pos) {
719         case 1: font.setColor(LColor::ignore); break;
720         case 2: font.setColor(LColor::none); break;
721         case 3: font.setColor(LColor::black); break;
722         case 4: font.setColor(LColor::white); break;
723         case 5: font.setColor(LColor::red); break;
724         case 6: font.setColor(LColor::green); break;
725         case 7: font.setColor(LColor::blue); break;
726         case 8: font.setColor(LColor::cyan); break;
727         case 9: font.setColor(LColor::magenta); break;
728         case 10: font.setColor(LColor::yellow); break;
729         case 11: font.setColor(LColor::inherit); break;
730         }
731
732         int const choice = combo_language2->get();
733         if (choice == 1)
734                 font.setLanguage(ignore_language);
735         else if (choice == 2)
736                 font.setLanguage(params.language);
737         else
738                 font.setLanguage(languages.getLanguage(combo_language2->getline()));
739
740         return font; 
741 }
742
743
744 /* callbacks for form form_title */
745 extern "C" void TimerCB(FL_OBJECT *, long)
746 {
747         // only if the form still exists
748         if (lyxrc.show_banner
749             && fd_form_title
750             && fd_form_title->form_title) {
751                 if (fd_form_title->form_title->visible) {
752                         fl_hide_form(fd_form_title->form_title);
753                 }
754                 fl_free_form(fd_form_title->form_title);
755                 fd_form_title->form_title = 0;
756         }
757 }
758
759
760 /* callbacks for form form_character */
761
762 extern "C" void CharacterApplyCB(FL_OBJECT *, long)
763 {
764         // we set toggleall locally here, since it should be true for
765         // all other uses of ToggleAndShow() (JMarc)
766         toggleall = fl_get_button(fd_form_character->check_toggle_all);
767         ToggleAndShow(current_view, UserFreeFont(current_view->buffer()->params));
768         current_view->setState();
769         toggleall = true;
770 }
771
772
773 extern "C" void CharacterCloseCB(FL_OBJECT *, long)
774 {
775         fl_hide_form(fd_form_character->form_character);
776 }
777
778
779 extern "C" void CharacterOKCB(FL_OBJECT *ob, long data)
780 {
781         CharacterApplyCB(ob, data);
782         CharacterCloseCB(ob, data);
783 }
784
785
786 /* callbacks for form form_preamble */
787
788 extern "C" void PreambleCancelCB(FL_OBJECT *, long)
789 {
790         fl_hide_form(fd_form_preamble->form_preamble);
791 }
792
793
794 extern "C" void PreambleApplyCB(FL_OBJECT *, long)
795 {
796         if (!current_view->available())
797                 return;
798         
799         current_view->buffer()->params.preamble = 
800                 fl_get_input(fd_form_preamble->input_preamble);
801         current_view->buffer()->markDirty();
802         current_view->owner()->getMiniBuffer()->Set(_("LaTeX preamble set"));
803 }
804
805    
806 extern "C" void PreambleOKCB(FL_OBJECT * ob, long data)
807 {
808         PreambleApplyCB(ob, data);
809         PreambleCancelCB(ob, data);
810 }
811
812
813 void Figure()
814 {
815         if (fd_form_figure->form_figure->visible) {
816                 fl_raise_form(fd_form_figure->form_figure);
817         } else {
818                 fl_show_form(fd_form_figure->form_figure,
819                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
820                              _("Insert Figure"));
821         }
822 }
823
824
825 /* callbacks for form form_figure */
826 extern "C"
827 void FigureApplyCB(FL_OBJECT *, long)
828 {
829         if (!current_view->available())
830                 return;
831
832         Buffer * buffer = current_view->buffer();
833         if (buffer->isReadonly()) // paranoia
834                 return;
835         
836         current_view->owner()->getMiniBuffer()->Set(_("Inserting figure..."));
837         if (fl_get_button(fd_form_figure->radio_inline)) {
838                 InsetFig * new_inset = new InsetFig(100, 20, *buffer);
839                 current_view->insertInset(new_inset);
840                 current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
841                 new_inset->Edit(current_view, 0, 0, 0);
842                 return;
843         }
844         
845         current_view->hideCursor();
846         current_view->update(BufferView::SELECT|BufferView::FITCUR);
847         current_view->beforeChange();
848       
849         current_view->text->SetCursorParUndo(current_view->buffer()); 
850         current_view->text->FreezeUndo();
851
852         current_view->text->BreakParagraph(current_view);
853         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
854       
855         if (current_view->text->cursor.par()->Last()) {
856                 current_view->text->CursorLeft(current_view);
857          
858                 current_view->text->BreakParagraph(current_view);
859                 current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
860         }
861
862         // The standard layout should always be numer 0;
863         current_view->text->SetLayout(current_view, 0);
864
865 #ifndef NEW_INSETS
866         if (current_view->text->cursor.par()->footnoteflag == 
867             LyXParagraph::NO_FOOTNOTE) {
868 #endif
869                 current_view->text->
870                         SetParagraph(current_view, 0, 0,
871                                      0, 0,
872                                      VSpace (0.3 * buffer->params.spacing.getValue(),
873                                              LyXLength::CM),
874                                      VSpace (0.3 *
875                                              buffer->params.spacing.getValue(),
876                                              LyXLength::CM),
877                                      LYX_ALIGN_CENTER, string(), 0);
878 #ifndef NEW_INSETS
879         } else {
880                 current_view->text->SetParagraph(current_view, 0, 0,
881                                                  0, 0,
882                                                  VSpace(VSpace::NONE),
883                                                  VSpace(VSpace::NONE),
884                                                  LYX_ALIGN_CENTER, 
885                                                  string(),
886                                                  0);
887         }
888 #endif
889         
890         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
891       
892         Inset * new_inset = new InsetFig(100, 100, *buffer);
893         current_view->insertInset(new_inset);
894         new_inset->Edit(current_view, 0, 0, 0);
895         current_view->update(BufferView::SELECT|BufferView::FITCUR);
896         current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
897         current_view->text->UnFreezeUndo();
898         current_view->setState();
899 }
900
901
902 extern "C" void FigureCancelCB(FL_OBJECT *, long)
903 {
904         fl_hide_form(fd_form_figure->form_figure);
905 }
906
907
908 extern "C" void FigureOKCB(FL_OBJECT * ob, long data)
909 {
910         FigureApplyCB(ob, data);
911         FigureCancelCB(ob, data);
912 }
913
914
915 // This function runs "configure" and then rereads lyx.defaults to
916 // reconfigure the automatic settings.
917 void Reconfigure(BufferView * bv)
918 {
919         bv->owner()->getMiniBuffer()->Set(_("Running configure..."));
920
921         // Run configure in user lyx directory
922         Path p(user_lyxdir);
923         Systemcalls one(Systemcalls::System, 
924                         AddName(system_lyxdir, "configure"));
925         p.pop();
926         bv->owner()->getMiniBuffer()->Set(_("Reloading configuration..."));
927         lyxrc.read(LibFileSearch(string(), "lyxrc.defaults"));
928         WriteAlert(_("The system has been reconfigured."), 
929                    _("You need to restart LyX to make use of any"),
930                    _("updated document class specifications."));
931 }