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