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