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