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