]> git.lyx.org Git - lyx.git/blob - src/lyx_cb.C
678998711963b3456ab5cdb8001749a671c86827
[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 (lyxrc.use_gui) {
335                 if (!bufferlist.QwriteAll())
336                         return;
337
338                 lastfiles->writeFile(lyxrc.lastfiles);
339         }
340
341         // Set a flag that we do quitting from the program,
342         // so no refreshes are necessary.
343         quitting = true;
344
345         // close buffers first
346         bufferlist.closeAll();
347
348         // do any other cleanup procedures now
349         lyxerr.debug() << "Deleting tmp dir " << system_tempdir << endl;
350
351         DestroyLyXTmpDir(system_tempdir);
352
353         finished = true;
354 }
355
356
357
358 void AutoSave(BufferView * bv)
359         // should probably be moved into BufferList (Lgb)
360         // Perfect target for a thread...
361 {
362         if (!bv->available())
363                 return;
364
365         if (bv->buffer()->isBakClean() || bv->buffer()->isReadonly()) {
366                 // We don't save now, but we'll try again later
367                 bv->owner()->resetAutosaveTimer();
368                 return;
369         }
370
371         bv->owner()->getMiniBuffer()->Set(_("Autosaving current document..."));
372         
373         // create autosave filename
374         string fname =  OnlyPath(bv->buffer()->fileName());
375         fname += "#";
376         fname += OnlyFilename(bv->buffer()->fileName());
377         fname += "#";
378         
379         // tmp_ret will be located (usually) in /tmp
380         // will that be a problem?
381         pid_t const pid = fork(); // If you want to debug the autosave
382         // you should set pid to -1, and comment out the
383         // fork.
384         if (pid == 0 || pid == -1) {
385                 // pid = -1 signifies that lyx was unable
386                 // to fork. But we will do the save
387                 // anyway.
388                 bool failed = false;
389                 
390                 string const tmp_ret = lyx::tempName(string(), "lyxauto");
391                 if (!tmp_ret.empty()) {
392                         bv->buffer()->writeFile(tmp_ret, 1);
393                         // assume successful write of tmp_ret
394                         if (!lyx::rename(tmp_ret, fname)) {
395                                 failed = true;
396                                 // most likely couldn't move between filesystems
397                                 // unless write of tmp_ret failed
398                                 // so remove tmp file (if it exists)
399                                 lyx::unlink(tmp_ret);
400                         }
401                 } else {
402                         failed = true;
403                 }
404                 
405                 if (failed) {
406                         // failed to write/rename tmp_ret so try writing direct
407                         if (!bv->buffer()->writeFile(fname, 1)) {
408                                 // It is dangerous to do this in the child,
409                                 // but safe in the parent, so...
410                                 if (pid == -1)
411                                         bv->owner()->getMiniBuffer()->Set(_("Autosave Failed!"));
412                         }
413                 }
414                 if (pid == 0) { // we are the child so...
415                         _exit(0);
416                 }
417         }
418         
419         bv->buffer()->markBakClean();
420         bv->owner()->resetAutosaveTimer();
421 }
422
423
424 //
425 // Copyright CHT Software Service GmbH
426 // Uwe C. Schroeder
427 //
428 // create new file with template
429 // SERVERCMD !
430 //
431 Buffer * NewLyxFile(string const & filename)
432 {
433         // Split argument by :
434         string name;
435         string tmpname = split(filename, name, ':');
436 #ifdef __EMX__ // Fix me! lyx_cb.C may not be low level enough to allow this.
437         if (name.length() == 1
438             && isalpha(static_cast<unsigned char>(name[0]))
439             && (prefixIs(tmpname, "/") || prefixIs(tmpname, "\\"))) {
440                 name += ':';
441                 name += token(tmpname, ':', 0);
442                 tmpname = split(tmpname, ':');
443         }
444 #endif
445         lyxerr.debug() << "Arg is " << filename
446                        << "\nName is " << name
447                        << "\nTemplate is " << tmpname << endl;
448
449         // find a free buffer 
450         Buffer * tmpbuf = bufferlist.newFile(name, tmpname);
451         if (tmpbuf)
452                 lastfiles->newFile(tmpbuf->fileName());
453         return tmpbuf;
454 }
455
456
457 // Insert ascii file (if filename is empty, prompt for one)
458 void InsertAsciiFile(BufferView * bv, string const & f, bool asParagraph)
459 {
460         string fname = f;
461         LyXFileDlg fileDlg;
462  
463         if (!bv->available()) return;
464      
465         if (fname.empty()) {
466                 ProhibitInput(bv);
467                 fname = fileDlg.Select(_("File to Insert"), 
468                                        bv->owner()->buffer()->filepath,
469                                        "*");
470                 AllowInput(bv);
471                 if (fname.empty()) return;
472         }
473
474         FileInfo fi(fname);
475
476         if (!fi.readable()) {
477                 WriteFSAlert(_("Error! Specified file is unreadable: "),
478                              MakeDisplayPath(fname, 50));
479                 return;
480         }
481
482         ifstream ifs(fname.c_str());
483         if (!ifs) {
484                 WriteFSAlert(_("Error! Cannot open specified file: "),
485                              MakeDisplayPath(fname, 50));
486                 return;
487         }
488
489         ifs.unsetf(ios::skipws);
490         istream_iterator<char> ii(ifs);
491         istream_iterator<char> end;
492 #if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD)
493         // We use this until the compilers get better...
494         vector<char> tmp;
495         copy(ii, end, back_inserter(tmp));
496         string const tmpstr(tmp.begin(), tmp.end());
497 #else
498         // This is what we want to use and what we will use once the
499         // compilers get good enough. 
500         //string tmpstr(ii, end); // yet a reason for using std::string
501         // alternate approach to get the file into a string:
502         string tmpstr;
503         copy(ii, end, back_inserter(tmpstr));
504 #endif
505         // insert the string
506         bv->hideCursor();
507         
508         // clear the selection
509         bv->beforeChange();
510         if (!asParagraph)
511                 bv->text->InsertStringA(bv, tmpstr);
512         else
513                 bv->text->InsertStringB(bv, tmpstr);
514         bv->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
515 }
516
517
518 void MenuInsertLabel(BufferView * bv, string const & arg)
519 {
520         string label(arg);
521         ProhibitInput(bv);
522         if (label.empty()) {
523 #ifndef NEW_INSETS
524                 LyXParagraph * par =
525                         bv->text->cursor.par()->FirstPhysicalPar();
526 #else
527                 LyXParagraph * par = bv->text->cursor.par();
528 #endif
529                 LyXLayout const * layout =
530                         &textclasslist.Style(bv->buffer()->params.textclass,
531                                              par->GetLayout());
532
533                 if (layout->latextype == LATEX_PARAGRAPH && par->previous) {
534 #ifndef NEW_INSETS
535                         LyXParagraph * par2 = par->previous->FirstPhysicalPar();
536 #else
537                         LyXParagraph * par2 = par->previous;
538 #endif
539                         LyXLayout const * layout2 =
540                                 &textclasslist.Style(bv->buffer()->params.textclass,
541                                                      par2->GetLayout());
542                         if (layout2->latextype != LATEX_PARAGRAPH) {
543                                 par = par2;
544                                 layout = layout2;
545                         }
546                 }
547                 string text = layout->latexname().substr(0, 3);
548                 if (layout->latexname() == "theorem")
549                         text = "thm"; // Create a correct prefix for prettyref
550 #ifndef NEW_INSETS
551                 if (par->footnoteflag==LyXParagraph::OPEN_FOOTNOTE)
552                         switch (par->footnotekind) {
553                         case LyXParagraph::FIG:
554                         case LyXParagraph::WIDE_FIG:
555                                 text = "fig";
556                                 break;
557                         case LyXParagraph::TAB:
558                         case LyXParagraph::WIDE_TAB:
559                                 text = "tab";
560                                 break;
561                         case LyXParagraph::ALGORITHM:
562                                 text = "alg";
563                                 break;
564                         case LyXParagraph::FOOTNOTE:    
565                         case LyXParagraph::MARGIN:
566                                 break;
567                         }
568 #endif
569                 text += ":";
570                 if (layout->latextype == LATEX_PARAGRAPH ||
571                     lyxrc.label_init_length < 0)
572                         text.erase();
573                 string par_text = par->String(bv->buffer(), false);
574                 for (int i = 0; i < lyxrc.label_init_length; ++i) {
575                         if (par_text.empty())
576                                 break;
577                         string head;
578                         par_text = split(par_text, head, ' ');
579                         if (i > 0)
580                                 text += '-'; // Is it legal to use spaces in
581                                              // labels ?
582                         text += head;
583                 }
584
585                 pair<bool, string> result =
586                         askForText(_("Enter new label to insert:"), text);
587                 if (result.first) {
588                         label = frontStrip(strip(result.second));
589                 }
590         }
591         if (!label.empty()) {
592                 InsetCommandParams p( "label", label );
593                 InsetLabel * inset = new InsetLabel( p );
594                 bv->insertInset( inset );
595         }
596         AllowInput(bv);
597 }
598
599
600 // This is _only_ used in Toolbar_pimpl.C, move it there and get rid of
601 // current_view. (Lgb)
602 void LayoutsCB(int sel, void *, Combox *)
603 {
604         string const tmp = tostr(sel);
605         current_view->owner()->getLyXFunc()->Dispatch(LFUN_LAYOUTNO,
606                                                       tmp);
607 }
608
609
610 void MenuLayoutCharacter()
611 {
612         static int ow = -1, oh;
613
614         if (fd_form_character->form_character->visible) {
615                 fl_raise_form(fd_form_character->form_character);
616         } else {
617                 fl_show_form(fd_form_character->form_character,
618                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
619                              _("Character Style"));
620                 if (ow < 0) {
621                         ow = fd_form_character->form_character->w;
622                         oh = fd_form_character->form_character->h;
623                 }
624                 fl_set_form_minsize(fd_form_character->form_character, ow, oh);
625         }
626 }
627
628
629 bool UpdateLayoutPreamble(BufferView * bv)
630 {
631         bool update = true;
632         if (!bv->available())
633                 update = false;
634
635         if (update) {
636                 fl_set_input(fd_form_preamble->input_preamble,
637                              bv->buffer()->params.preamble.c_str());
638
639                 if (bv->buffer()->isReadonly()) {
640                         fl_deactivate_object(fd_form_preamble->input_preamble);
641                         fl_deactivate_object(fd_form_preamble->button_ok);
642                         fl_deactivate_object(fd_form_preamble->button_apply);
643                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_INACTIVE);
644                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_INACTIVE);
645                 } else {
646                         fl_activate_object(fd_form_preamble->input_preamble);
647                         fl_activate_object(fd_form_preamble->button_ok);
648                         fl_activate_object(fd_form_preamble->button_apply);
649                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_BLACK);
650                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_BLACK);
651                 }
652         } else if (fd_form_preamble->form_preamble->visible) {
653                 fl_hide_form(fd_form_preamble->form_preamble);
654         }
655         return update;
656 }
657
658
659 void MenuLayoutPreamble()
660 {
661         static int ow = -1, oh;
662
663         if (UpdateLayoutPreamble(current_view)) {
664                 if (fd_form_preamble->form_preamble->visible) {
665                         fl_raise_form(fd_form_preamble->form_preamble);
666                 } else {
667                         fl_show_form(fd_form_preamble->form_preamble,
668                                      FL_PLACE_MOUSE | FL_FREE_SIZE,
669                                      FL_TRANSIENT,
670                                      _("LaTeX Preamble"));
671                         if (ow < 0) {
672                                 ow = fd_form_preamble->form_preamble->w;
673                                 oh = fd_form_preamble->form_preamble->h;
674                         }
675                         fl_set_form_minsize(fd_form_preamble->form_preamble,
676                                             ow, oh);
677                 }
678         }
679 }
680
681
682 void MenuLayoutSave(BufferView * bv)
683 {
684         if (!bv->available())
685                 return;
686
687         if (AskQuestion(_("Do you want to save the current settings"),
688                         _("for Character, Document, Paper and Quotes"),
689                         _("as default for new documents?")))
690                 bv->buffer()->saveParamsAsDefaults();
691 }
692
693
694 // This is both GUI and LyXFont dependent. Don't know where to put it. (Asger)
695 // Well, it's mostly GUI dependent, so I guess it will stay here. (Asger)
696 LyXFont const UserFreeFont(BufferParams const & params)
697 {
698         LyXFont font(LyXFont::ALL_IGNORE);
699
700         int pos = fl_get_choice(fd_form_character->choice_family);
701         switch (pos) {
702         case 1: font.setFamily(LyXFont::IGNORE_FAMILY); break;
703         case 2: font.setFamily(LyXFont::ROMAN_FAMILY); break;
704         case 3: font.setFamily(LyXFont::SANS_FAMILY); break;
705         case 4: font.setFamily(LyXFont::TYPEWRITER_FAMILY); break;
706         case 5: font.setFamily(LyXFont::INHERIT_FAMILY); break;
707         }
708
709         pos = fl_get_choice(fd_form_character->choice_series);
710         switch (pos) {
711         case 1: font.setSeries(LyXFont::IGNORE_SERIES); break;
712         case 2: font.setSeries(LyXFont::MEDIUM_SERIES); break;
713         case 3: font.setSeries(LyXFont::BOLD_SERIES); break;
714         case 4: font.setSeries(LyXFont::INHERIT_SERIES); break;
715         }
716
717         pos = fl_get_choice(fd_form_character->choice_shape);
718         switch (pos) {
719         case 1: font.setShape(LyXFont::IGNORE_SHAPE); break;
720         case 2: font.setShape(LyXFont::UP_SHAPE); break;
721         case 3: font.setShape(LyXFont::ITALIC_SHAPE); break;
722         case 4: font.setShape(LyXFont::SLANTED_SHAPE); break;
723         case 5: font.setShape(LyXFont::SMALLCAPS_SHAPE); break;
724         case 6: font.setShape(LyXFont::INHERIT_SHAPE); break;
725         }
726
727         pos = fl_get_choice(fd_form_character->choice_size);
728         switch (pos) {
729         case 1: font.setSize(LyXFont::IGNORE_SIZE); break;
730         case 2: font.setSize(LyXFont::SIZE_TINY); break;
731         case 3: font.setSize(LyXFont::SIZE_SCRIPT); break;
732         case 4: font.setSize(LyXFont::SIZE_FOOTNOTE); break;
733         case 5: font.setSize(LyXFont::SIZE_SMALL); break;
734         case 6: font.setSize(LyXFont::SIZE_NORMAL); break;
735         case 7: font.setSize(LyXFont::SIZE_LARGE); break;
736         case 8: font.setSize(LyXFont::SIZE_LARGER); break;
737         case 9: font.setSize(LyXFont::SIZE_LARGEST); break;
738         case 10: font.setSize(LyXFont::SIZE_HUGE); break;
739         case 11: font.setSize(LyXFont::SIZE_HUGER); break;
740         case 12: font.setSize(LyXFont::INCREASE_SIZE); break;
741         case 13: font.setSize(LyXFont::DECREASE_SIZE); break;
742         case 14: font.setSize(LyXFont::INHERIT_SIZE); break;
743         }
744
745         pos = fl_get_choice(fd_form_character->choice_bar);
746         switch (pos) {
747         case 1: font.setEmph(LyXFont::IGNORE);
748                 font.setUnderbar(LyXFont::IGNORE);
749                 font.setNoun(LyXFont::IGNORE);
750                 font.setLatex(LyXFont::IGNORE);
751                 break;
752         case 2: font.setEmph(LyXFont::TOGGLE); break;
753         case 3: font.setUnderbar(LyXFont::TOGGLE); break;
754         case 4: font.setNoun(LyXFont::TOGGLE); break;
755         case 5: font.setLatex(LyXFont::TOGGLE); break;
756         case 6: font.setEmph(LyXFont::INHERIT);
757                 font.setUnderbar(LyXFont::INHERIT);
758                 font.setNoun(LyXFont::INHERIT);
759                 font.setLatex(LyXFont::INHERIT);
760                 break;
761         }
762
763         pos = fl_get_choice(fd_form_character->choice_color);
764         switch (pos) {
765         case 1: font.setColor(LColor::ignore); break;
766         case 2: font.setColor(LColor::none); break;
767         case 3: font.setColor(LColor::black); break;
768         case 4: font.setColor(LColor::white); break;
769         case 5: font.setColor(LColor::red); break;
770         case 6: font.setColor(LColor::green); break;
771         case 7: font.setColor(LColor::blue); break;
772         case 8: font.setColor(LColor::cyan); break;
773         case 9: font.setColor(LColor::magenta); break;
774         case 10: font.setColor(LColor::yellow); break;
775         case 11: font.setColor(LColor::inherit); break;
776         }
777
778         int const choice = combo_language2->get();
779         if (choice == 1)
780                 font.setLanguage(ignore_language);
781         else if (choice == 2)
782                 font.setLanguage(params.language);
783         else
784                 font.setLanguage(languages.getLanguage(combo_language2->getline()));
785
786         return font; 
787 }
788
789
790 /* callbacks for form form_title */
791 extern "C"
792 void TimerCB(FL_OBJECT *, long)
793 {
794         // only if the form still exists
795         if (lyxrc.show_banner
796             && fd_form_title
797             && fd_form_title->form_title) {
798                 if (fd_form_title->form_title->visible) {
799                         fl_hide_form(fd_form_title->form_title);
800                 }
801                 fl_free_form(fd_form_title->form_title);
802                 fd_form_title->form_title = 0;
803         }
804 }
805
806
807 /* callbacks for form form_character */
808
809 extern "C"
810 void CharacterApplyCB(FL_OBJECT *, long)
811 {
812         // we set toggleall locally here, since it should be true for
813         // all other uses of ToggleAndShow() (JMarc)
814         toggleall = fl_get_button(fd_form_character->check_toggle_all);
815         ToggleAndShow(current_view, UserFreeFont(current_view->buffer()->params));
816         current_view->setState();
817         toggleall = true;
818 }
819
820
821 extern "C"
822 void CharacterCloseCB(FL_OBJECT *, long)
823 {
824         fl_hide_form(fd_form_character->form_character);
825 }
826
827
828 extern "C"
829 void CharacterOKCB(FL_OBJECT * ob, long data)
830 {
831         CharacterApplyCB(ob, data);
832         CharacterCloseCB(ob, data);
833 }
834
835
836 /* callbacks for form form_preamble */
837
838 extern "C"
839 void PreambleCancelCB(FL_OBJECT *, long)
840 {
841         fl_hide_form(fd_form_preamble->form_preamble);
842 }
843
844
845 extern "C"
846 void PreambleApplyCB(FL_OBJECT *, long)
847 {
848         if (!current_view->available())
849                 return;
850         
851         current_view->buffer()->params.preamble = 
852                 fl_get_input(fd_form_preamble->input_preamble);
853         current_view->buffer()->markDirty();
854         current_view->owner()->getMiniBuffer()->Set(_("LaTeX preamble set"));
855 }
856
857    
858 extern "C"
859 void PreambleOKCB(FL_OBJECT * ob, long data)
860 {
861         PreambleApplyCB(ob, data);
862         PreambleCancelCB(ob, data);
863 }
864
865
866 void Figure()
867 {
868         if (fd_form_figure->form_figure->visible) {
869                 fl_raise_form(fd_form_figure->form_figure);
870         } else {
871                 fl_show_form(fd_form_figure->form_figure,
872                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
873                              _("Insert Figure"));
874         }
875 }
876
877
878 /* callbacks for form form_figure */
879 extern "C"
880 void FigureApplyCB(FL_OBJECT *, long)
881 {
882         if (!current_view->available())
883                 return;
884
885         Buffer * buffer = current_view->buffer();
886         if (buffer->isReadonly()) // paranoia
887                 return;
888         
889         current_view->owner()->getMiniBuffer()->Set(_("Inserting figure..."));
890         if (fl_get_button(fd_form_figure->radio_inline)) {
891                 InsetFig * new_inset = new InsetFig(100, 20, *buffer);
892                 current_view->insertInset(new_inset);
893                 current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
894                 new_inset->Edit(current_view, 0, 0, 0);
895                 return;
896         }
897         
898         current_view->hideCursor();
899         current_view->update(BufferView::SELECT|BufferView::FITCUR);
900         current_view->beforeChange();
901       
902         current_view->text->SetCursorParUndo(current_view->buffer()); 
903         current_view->text->FreezeUndo();
904
905         current_view->text->BreakParagraph(current_view);
906         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
907       
908         if (current_view->text->cursor.par()->Last()) {
909                 current_view->text->CursorLeft(current_view);
910          
911                 current_view->text->BreakParagraph(current_view);
912                 current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
913         }
914
915         // The standard layout should always be numer 0;
916         current_view->text->SetLayout(current_view, 0);
917
918 #ifndef NEW_INSETS
919         if (current_view->text->cursor.par()->footnoteflag == 
920             LyXParagraph::NO_FOOTNOTE) {
921 #endif
922                 current_view->text->
923                         SetParagraph(current_view, 0, 0,
924                                      0, 0,
925                                      VSpace (0.3 * buffer->params.spacing.getValue(),
926                                              LyXLength::CM),
927                                      VSpace (0.3 *
928                                              buffer->params.spacing.getValue(),
929                                              LyXLength::CM),
930                                      LYX_ALIGN_CENTER, string(), 0);
931 #ifndef NEW_INSETS
932         } else {
933                 current_view->text->SetParagraph(current_view, 0, 0,
934                                                  0, 0,
935                                                  VSpace(VSpace::NONE),
936                                                  VSpace(VSpace::NONE),
937                                                  LYX_ALIGN_CENTER, 
938                                                  string(),
939                                                  0);
940         }
941 #endif
942         
943         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
944       
945         Inset * new_inset = new InsetFig(100, 100, *buffer);
946         current_view->insertInset(new_inset);
947         new_inset->Edit(current_view, 0, 0, 0);
948         current_view->update(BufferView::SELECT|BufferView::FITCUR);
949         current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
950         current_view->text->UnFreezeUndo();
951         current_view->setState();
952 }
953
954
955 extern "C" void FigureCancelCB(FL_OBJECT *, long)
956 {
957         fl_hide_form(fd_form_figure->form_figure);
958 }
959
960
961 extern "C" void FigureOKCB(FL_OBJECT * ob, long data)
962 {
963         FigureApplyCB(ob, data);
964         FigureCancelCB(ob, data);
965 }
966
967
968 // This function runs "configure" and then rereads lyx.defaults to
969 // reconfigure the automatic settings.
970 void Reconfigure(BufferView * bv)
971 {
972         bv->owner()->getMiniBuffer()->Set(_("Running configure..."));
973
974         // Run configure in user lyx directory
975         Path p(user_lyxdir);
976         Systemcalls one(Systemcalls::System, 
977                         AddName(system_lyxdir, "configure"));
978         p.pop();
979         bv->owner()->getMiniBuffer()->Set(_("Reloading configuration..."));
980         lyxrc.read(LibFileSearch(string(), "lyxrc.defaults"));
981         WriteAlert(_("The system has been reconfigured."), 
982                    _("You need to restart LyX to make use of any"),
983                    _("updated document class specifications."));
984 }