]> git.lyx.org Git - lyx.git/blob - src/lyx_cb.C
ea272c971624056f5d2e2f903a6e61286d9af8f5
[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();
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 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                 pair<bool, string>
522                         result = askForText(_("Enter new label to insert:"));
523                 if (result.first) {
524                         label = frontStrip(strip(result.second));
525                 }
526         }
527         if (!label.empty()) {
528                 InsetCommandParams p( "label", label );
529                 InsetLabel * inset = new InsetLabel( p );
530                 bv->insertInset( inset );
531         }
532         AllowInput(bv);
533 }
534
535
536 // This is _only_ used in Toolbar_pimpl.C, move it there and get rid of
537 // current_view. (Lgb)
538 void LayoutsCB(int sel, void *, Combox *)
539 {
540         string const tmp = tostr(sel);
541         current_view->owner()->getLyXFunc()->Dispatch(LFUN_LAYOUTNO,
542                                                       tmp);
543 }
544
545
546 void MenuLayoutCharacter()
547 {
548         static int ow = -1, oh;
549
550         if (fd_form_character->form_character->visible) {
551                 fl_raise_form(fd_form_character->form_character);
552         } else {
553                 fl_show_form(fd_form_character->form_character,
554                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
555                              _("Character Style"));
556                 if (ow < 0) {
557                         ow = fd_form_character->form_character->w;
558                         oh = fd_form_character->form_character->h;
559                 }
560                 fl_set_form_minsize(fd_form_character->form_character, ow, oh);
561         }
562 }
563
564
565 bool UpdateLayoutPreamble(BufferView * bv)
566 {
567         bool update = true;
568         if (!bv->available())
569                 update = false;
570
571         if (update) {
572                 fl_set_input(fd_form_preamble->input_preamble,
573                              bv->buffer()->params.preamble.c_str());
574
575                 if (bv->buffer()->isReadonly()) {
576                         fl_deactivate_object(fd_form_preamble->input_preamble);
577                         fl_deactivate_object(fd_form_preamble->button_ok);
578                         fl_deactivate_object(fd_form_preamble->button_apply);
579                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_INACTIVE);
580                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_INACTIVE);
581                 } else {
582                         fl_activate_object(fd_form_preamble->input_preamble);
583                         fl_activate_object(fd_form_preamble->button_ok);
584                         fl_activate_object(fd_form_preamble->button_apply);
585                         fl_set_object_lcol(fd_form_preamble->button_ok, FL_BLACK);
586                         fl_set_object_lcol(fd_form_preamble->button_apply, FL_BLACK);
587                 }
588         } else if (fd_form_preamble->form_preamble->visible) {
589                 fl_hide_form(fd_form_preamble->form_preamble);
590         }
591         return update;
592 }
593
594
595 void MenuLayoutPreamble()
596 {
597         static int ow = -1, oh;
598
599         if (UpdateLayoutPreamble(current_view)) {
600                 if (fd_form_preamble->form_preamble->visible) {
601                         fl_raise_form(fd_form_preamble->form_preamble);
602                 } else {
603                         fl_show_form(fd_form_preamble->form_preamble,
604                                      FL_PLACE_MOUSE | FL_FREE_SIZE,
605                                      FL_TRANSIENT,
606                                      _("LaTeX Preamble"));
607                         if (ow < 0) {
608                                 ow = fd_form_preamble->form_preamble->w;
609                                 oh = fd_form_preamble->form_preamble->h;
610                         }
611                         fl_set_form_minsize(fd_form_preamble->form_preamble,
612                                             ow, oh);
613                 }
614         }
615 }
616
617
618 void MenuLayoutSave(BufferView * bv)
619 {
620         if (!bv->available())
621                 return;
622
623         if (AskQuestion(_("Do you want to save the current settings"),
624                         _("for Character, Document, Paper and Quotes"),
625                         _("as default for new documents?")))
626                 bv->buffer()->saveParamsAsDefaults();
627 }
628
629
630 // This is both GUI and LyXFont dependent. Don't know where to put it. (Asger)
631 // Well, it's mostly GUI dependent, so I guess it will stay here. (Asger)
632 LyXFont const UserFreeFont(BufferParams const & params)
633 {
634         LyXFont font(LyXFont::ALL_IGNORE);
635
636         int pos = fl_get_choice(fd_form_character->choice_family);
637         switch (pos) {
638         case 1: font.setFamily(LyXFont::IGNORE_FAMILY); break;
639         case 2: font.setFamily(LyXFont::ROMAN_FAMILY); break;
640         case 3: font.setFamily(LyXFont::SANS_FAMILY); break;
641         case 4: font.setFamily(LyXFont::TYPEWRITER_FAMILY); break;
642         case 5: font.setFamily(LyXFont::INHERIT_FAMILY); break;
643         }
644
645         pos = fl_get_choice(fd_form_character->choice_series);
646         switch (pos) {
647         case 1: font.setSeries(LyXFont::IGNORE_SERIES); break;
648         case 2: font.setSeries(LyXFont::MEDIUM_SERIES); break;
649         case 3: font.setSeries(LyXFont::BOLD_SERIES); break;
650         case 4: font.setSeries(LyXFont::INHERIT_SERIES); break;
651         }
652
653         pos = fl_get_choice(fd_form_character->choice_shape);
654         switch (pos) {
655         case 1: font.setShape(LyXFont::IGNORE_SHAPE); break;
656         case 2: font.setShape(LyXFont::UP_SHAPE); break;
657         case 3: font.setShape(LyXFont::ITALIC_SHAPE); break;
658         case 4: font.setShape(LyXFont::SLANTED_SHAPE); break;
659         case 5: font.setShape(LyXFont::SMALLCAPS_SHAPE); break;
660         case 6: font.setShape(LyXFont::INHERIT_SHAPE); break;
661         }
662
663         pos = fl_get_choice(fd_form_character->choice_size);
664         switch (pos) {
665         case 1: font.setSize(LyXFont::IGNORE_SIZE); break;
666         case 2: font.setSize(LyXFont::SIZE_TINY); break;
667         case 3: font.setSize(LyXFont::SIZE_SCRIPT); break;
668         case 4: font.setSize(LyXFont::SIZE_FOOTNOTE); break;
669         case 5: font.setSize(LyXFont::SIZE_SMALL); break;
670         case 6: font.setSize(LyXFont::SIZE_NORMAL); break;
671         case 7: font.setSize(LyXFont::SIZE_LARGE); break;
672         case 8: font.setSize(LyXFont::SIZE_LARGER); break;
673         case 9: font.setSize(LyXFont::SIZE_LARGEST); break;
674         case 10: font.setSize(LyXFont::SIZE_HUGE); break;
675         case 11: font.setSize(LyXFont::SIZE_HUGER); break;
676         case 12: font.setSize(LyXFont::INCREASE_SIZE); break;
677         case 13: font.setSize(LyXFont::DECREASE_SIZE); break;
678         case 14: font.setSize(LyXFont::INHERIT_SIZE); break;
679         }
680
681         pos = fl_get_choice(fd_form_character->choice_bar);
682         switch (pos) {
683         case 1: font.setEmph(LyXFont::IGNORE);
684                 font.setUnderbar(LyXFont::IGNORE);
685                 font.setNoun(LyXFont::IGNORE);
686                 font.setLatex(LyXFont::IGNORE);
687                 break;
688         case 2: font.setEmph(LyXFont::TOGGLE); break;
689         case 3: font.setUnderbar(LyXFont::TOGGLE); break;
690         case 4: font.setNoun(LyXFont::TOGGLE); break;
691         case 5: font.setLatex(LyXFont::TOGGLE); break;
692         case 6: font.setEmph(LyXFont::INHERIT);
693                 font.setUnderbar(LyXFont::INHERIT);
694                 font.setNoun(LyXFont::INHERIT);
695                 font.setLatex(LyXFont::INHERIT);
696                 break;
697         }
698
699         pos = fl_get_choice(fd_form_character->choice_color);
700         switch (pos) {
701         case 1: font.setColor(LColor::ignore); break;
702         case 2: font.setColor(LColor::none); break;
703         case 3: font.setColor(LColor::black); break;
704         case 4: font.setColor(LColor::white); break;
705         case 5: font.setColor(LColor::red); break;
706         case 6: font.setColor(LColor::green); break;
707         case 7: font.setColor(LColor::blue); break;
708         case 8: font.setColor(LColor::cyan); break;
709         case 9: font.setColor(LColor::magenta); break;
710         case 10: font.setColor(LColor::yellow); break;
711         case 11: font.setColor(LColor::inherit); break;
712         }
713
714         int const choice = combo_language2->get();
715         if (choice == 1)
716                 font.setLanguage(ignore_language);
717         else if (choice == 2)
718                 font.setLanguage(params.language);
719         else
720                 font.setLanguage(languages.getLanguage(combo_language2->getline()));
721
722         return font; 
723 }
724
725
726 /* callbacks for form form_title */
727 extern "C"
728 void TimerCB(FL_OBJECT *, long)
729 {
730         // only if the form still exists
731         if (lyxrc.show_banner
732             && fd_form_title
733             && fd_form_title->form_title) {
734                 if (fd_form_title->form_title->visible) {
735                         fl_hide_form(fd_form_title->form_title);
736                 }
737                 fl_free_form(fd_form_title->form_title);
738                 fd_form_title->form_title = 0;
739         }
740 }
741
742
743 /* callbacks for form form_character */
744
745 extern "C"
746 void CharacterApplyCB(FL_OBJECT *, long)
747 {
748         // we set toggleall locally here, since it should be true for
749         // all other uses of ToggleAndShow() (JMarc)
750         toggleall = fl_get_button(fd_form_character->check_toggle_all);
751         ToggleAndShow(current_view, UserFreeFont(current_view->buffer()->params));
752         current_view->setState();
753         toggleall = true;
754 }
755
756
757 extern "C"
758 void CharacterCloseCB(FL_OBJECT *, long)
759 {
760         fl_hide_form(fd_form_character->form_character);
761 }
762
763
764 extern "C"
765 void CharacterOKCB(FL_OBJECT * ob, long data)
766 {
767         CharacterApplyCB(ob, data);
768         CharacterCloseCB(ob, data);
769 }
770
771
772 /* callbacks for form form_preamble */
773
774 extern "C"
775 void PreambleCancelCB(FL_OBJECT *, long)
776 {
777         fl_hide_form(fd_form_preamble->form_preamble);
778 }
779
780
781 extern "C"
782 void PreambleApplyCB(FL_OBJECT *, long)
783 {
784         if (!current_view->available())
785                 return;
786         
787         current_view->buffer()->params.preamble = 
788                 fl_get_input(fd_form_preamble->input_preamble);
789         current_view->buffer()->markDirty();
790         current_view->owner()->getMiniBuffer()->Set(_("LaTeX preamble set"));
791 }
792
793    
794 extern "C"
795 void PreambleOKCB(FL_OBJECT * ob, long data)
796 {
797         PreambleApplyCB(ob, data);
798         PreambleCancelCB(ob, data);
799 }
800
801
802 void Figure()
803 {
804         if (fd_form_figure->form_figure->visible) {
805                 fl_raise_form(fd_form_figure->form_figure);
806         } else {
807                 fl_show_form(fd_form_figure->form_figure,
808                              FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
809                              _("Insert Figure"));
810         }
811 }
812
813
814 /* callbacks for form form_figure */
815 extern "C"
816 void FigureApplyCB(FL_OBJECT *, long)
817 {
818         if (!current_view->available())
819                 return;
820
821         Buffer * buffer = current_view->buffer();
822         if (buffer->isReadonly()) // paranoia
823                 return;
824         
825         current_view->owner()->getMiniBuffer()->Set(_("Inserting figure..."));
826         if (fl_get_button(fd_form_figure->radio_inline)) {
827                 InsetFig * new_inset = new InsetFig(100, 20, *buffer);
828                 current_view->insertInset(new_inset);
829                 current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
830                 new_inset->Edit(current_view, 0, 0, 0);
831                 return;
832         }
833         
834         current_view->hideCursor();
835         current_view->update(BufferView::SELECT|BufferView::FITCUR);
836         current_view->beforeChange();
837       
838         current_view->text->SetCursorParUndo(current_view->buffer()); 
839         current_view->text->FreezeUndo();
840
841         current_view->text->BreakParagraph(current_view);
842         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
843       
844         if (current_view->text->cursor.par()->Last()) {
845                 current_view->text->CursorLeft(current_view);
846          
847                 current_view->text->BreakParagraph(current_view);
848                 current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
849         }
850
851         // The standard layout should always be numer 0;
852         current_view->text->SetLayout(current_view, 0);
853
854 #ifndef NEW_INSETS
855         if (current_view->text->cursor.par()->footnoteflag == 
856             LyXParagraph::NO_FOOTNOTE) {
857 #endif
858                 current_view->text->
859                         SetParagraph(current_view, 0, 0,
860                                      0, 0,
861                                      VSpace (0.3 * buffer->params.spacing.getValue(),
862                                              LyXLength::CM),
863                                      VSpace (0.3 *
864                                              buffer->params.spacing.getValue(),
865                                              LyXLength::CM),
866                                      LYX_ALIGN_CENTER, string(), 0);
867 #ifndef NEW_INSETS
868         } else {
869                 current_view->text->SetParagraph(current_view, 0, 0,
870                                                  0, 0,
871                                                  VSpace(VSpace::NONE),
872                                                  VSpace(VSpace::NONE),
873                                                  LYX_ALIGN_CENTER, 
874                                                  string(),
875                                                  0);
876         }
877 #endif
878         
879         current_view->update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE);
880       
881         Inset * new_inset = new InsetFig(100, 100, *buffer);
882         current_view->insertInset(new_inset);
883         new_inset->Edit(current_view, 0, 0, 0);
884         current_view->update(BufferView::SELECT|BufferView::FITCUR);
885         current_view->owner()->getMiniBuffer()->Set(_("Figure inserted"));
886         current_view->text->UnFreezeUndo();
887         current_view->setState();
888 }
889
890
891 extern "C" void FigureCancelCB(FL_OBJECT *, long)
892 {
893         fl_hide_form(fd_form_figure->form_figure);
894 }
895
896
897 extern "C" void FigureOKCB(FL_OBJECT * ob, long data)
898 {
899         FigureApplyCB(ob, data);
900         FigureCancelCB(ob, data);
901 }
902
903
904 // This function runs "configure" and then rereads lyx.defaults to
905 // reconfigure the automatic settings.
906 void Reconfigure(BufferView * bv)
907 {
908         bv->owner()->getMiniBuffer()->Set(_("Running configure..."));
909
910         // Run configure in user lyx directory
911         Path p(user_lyxdir);
912         Systemcalls one(Systemcalls::System, 
913                         AddName(system_lyxdir, "configure"));
914         p.pop();
915         bv->owner()->getMiniBuffer()->Set(_("Reloading configuration..."));
916         lyxrc.read(LibFileSearch(string(), "lyxrc.defaults"));
917         WriteAlert(_("The system has been reconfigured."), 
918                    _("You need to restart LyX to make use of any"),
919                    _("updated document class specifications."));
920 }