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