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