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