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