]> git.lyx.org Git - lyx.git/blob - src/LyXFunc.cpp
* gcc does not like missing characters in keywords
[lyx.git] / src / LyXFunc.cpp
1 /**
2  * \file LyXFunc.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Allan Rae
13  * \author Dekel Tsur
14  * \author Martin Vermeer
15  * \author Jürgen Vigna
16  *
17  * Full author contact details are available in file CREDITS.
18  */
19
20 #include <config.h>
21 #include <vector>
22
23 #include "LyXFunc.h"
24
25 #include "BranchList.h"
26 #include "buffer_funcs.h"
27 #include "Buffer.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "CmdDef.h"
32 #include "Converter.h"
33 #include "Cursor.h"
34 #include "CutAndPaste.h"
35 #include "debug.h"
36 #include "DispatchResult.h"
37 #include "Encoding.h"
38 #include "ErrorList.h"
39 #include "Format.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
42 #include "gettext.h"
43 #include "InsetIterator.h"
44 #include "Intl.h"
45 #include "KeyMap.h"
46 #include "Language.h"
47 #include "Lexer.h"
48 #include "LyXAction.h"
49 #include "lyxfind.h"
50 #include "LyX.h"
51 #include "LyXRC.h"
52 #include "LyXVC.h"
53 #include "Paragraph.h"
54 #include "ParagraphParameters.h"
55 #include "ParIterator.h"
56 #include "Row.h"
57 #include "Server.h"
58 #include "Session.h"
59 #include "TextClassList.h"
60 #include "ToolbarBackend.h"
61
62 #include "insets/InsetBox.h"
63 #include "insets/InsetBranch.h"
64 #include "insets/InsetCommand.h"
65 #include "insets/InsetERT.h"
66 #include "insets/InsetExternal.h"
67 #include "insets/InsetFloat.h"
68 #include "insets/InsetListings.h"
69 #include "insets/InsetGraphics.h"
70 #include "insets/InsetInclude.h"
71 #include "insets/InsetNote.h"
72 #include "insets/InsetTabular.h"
73 #include "insets/InsetVSpace.h"
74 #include "insets/InsetWrap.h"
75
76 #include "frontends/Application.h"
77 #include "frontends/alert.h"
78 #include "frontends/Dialogs.h"
79 #include "frontends/FileDialog.h"
80 #include "frontends/FontLoader.h"
81 #include "frontends/Gui.h"
82 #include "frontends/KeySymbol.h"
83 #include "frontends/LyXView.h"
84 #include "frontends/Selection.h"
85 #include "frontends/WorkArea.h"
86
87 #include "support/environment.h"
88 #include "support/FileFilterList.h"
89 #include "support/filetools.h"
90 #include "support/fs_extras.h"
91 #include "support/lstrings.h"
92 #include "support/Path.h"
93 #include "support/Package.h"
94 #include "support/Systemcall.h"
95 #include "support/convert.h"
96 #include "support/os.h"
97
98 #include <boost/current_function.hpp>
99 #include <boost/filesystem/operations.hpp>
100
101 #include <sstream>
102
103 using std::endl;
104 using std::make_pair;
105 using std::pair;
106 using std::string;
107 using std::istringstream;
108 using std::ostringstream;
109 using std::find;
110 using std::vector;
111
112 namespace fs = boost::filesystem;
113
114 namespace lyx {
115
116 using frontend::LyXView;
117
118 using support::absolutePath;
119 using support::addName;
120 using support::addPath;
121 using support::bformat;
122 using support::changeExtension;
123 using support::contains;
124 using support::FileFilterList;
125 using support::FileName;
126 using support::fileSearch;
127 using support::i18nLibFileSearch;
128 using support::makeDisplayPath;
129 using support::makeAbsPath;
130 using support::package;
131 using support::quoteName;
132 using support::rtrim;
133 using support::split;
134 using support::subst;
135 using support::Systemcall;
136 using support::token;
137 using support::trim;
138 using support::prefixIs;
139
140
141 namespace Alert = frontend::Alert;
142
143 extern bool quitting;
144
145 namespace {
146
147
148 bool import(LyXView * lv, FileName const & filename,
149                       string const & format, ErrorList & errorList)
150 {
151         docstring const displaypath = makeDisplayPath(filename.absFilename());
152         lv->message(bformat(_("Importing %1$s..."), displaypath));
153
154         FileName const lyxfile(changeExtension(filename.absFilename(), ".lyx"));
155
156         string loader_format;
157         vector<string> loaders = theConverters().loaders();
158         if (find(loaders.begin(), loaders.end(), format) == loaders.end()) {
159                 for (vector<string>::const_iterator it = loaders.begin();
160                      it != loaders.end(); ++it) {
161                         if (theConverters().isReachable(format, *it)) {
162                                 string const tofile =
163                                         changeExtension(filename.absFilename(),
164                                                 formats.extension(*it));
165                                 if (!theConverters().convert(0, filename, FileName(tofile),
166                                                         filename, format, *it, errorList))
167                                         return false;
168                                 loader_format = *it;
169                                 break;
170                         }
171                 }
172                 if (loader_format.empty()) {
173                         frontend::Alert::error(_("Couldn't import file"),
174                                      bformat(_("No information for importing the format %1$s."),
175                                          formats.prettyName(format)));
176                         return false;
177                 }
178         } else {
179                 loader_format = format;
180         }
181
182
183         if (loader_format == "lyx") {
184                 Buffer * buf = lv->loadLyXFile(lyxfile);
185                 if (!buf) {
186                         // we are done
187                         lv->message(_("file not imported!"));
188                         return false;
189                 }
190                 updateLabels(*buf);
191                 lv->setBuffer(buf);
192                 lv->showErrorList("Parse");
193         } else {
194                 Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
195                 if (b)
196                         lv->setBuffer(b);
197                 else
198                         return false;
199                 bool as_paragraphs = loader_format == "textparagraph";
200                 string filename2 = (loader_format == format) ? filename.absFilename()
201                         : changeExtension(filename.absFilename(),
202                                           formats.extension(loader_format));
203                 lv->view()->insertPlaintextFile(filename2, as_paragraphs);
204                 lv->dispatch(FuncRequest(LFUN_MARK_OFF));
205         }
206
207         // we are done
208         lv->message(_("imported."));
209         return true;
210 }
211
212
213
214 // This function runs "configure" and then rereads lyx.defaults to
215 // reconfigure the automatic settings.
216 void reconfigure(LyXView & lv, string const & option)
217 {
218         // emit message signal.
219         lv.message(_("Running configure..."));
220
221         // Run configure in user lyx directory
222         support::Path p(package().user_support());
223         string configure_command = package().configure_command();
224         configure_command += option;
225         Systemcall one;
226         int ret = one.startscript(Systemcall::Wait, configure_command);
227         p.pop();
228         // emit message signal.
229         lv.message(_("Reloading configuration..."));
230         lyxrc.read(support::libFileSearch(string(), "lyxrc.defaults"));
231         // Re-read packages.lst
232         LaTeXFeatures::getAvailable();
233
234         if (ret)
235                 Alert::information(_("System reconfiguration failed"),
236                            _("The system reconfiguration has failed.\n"
237                                   "Default textclass is used but LyX may "
238                                   "not be able to work properly.\n"
239                                   "Please reconfigure again if needed."));
240         else
241
242                 Alert::information(_("System reconfigured"),
243                            _("The system has been reconfigured.\n"
244                              "You need to restart LyX to make use of any\n"
245                              "updated document class specifications."));
246 }
247
248
249 bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
250 {
251         // Try to fix cursor in case it is broken.
252         cursor.fixIfBroken();
253
254         // This is, of course, a mess. Better create a new doc iterator and use
255         // this in Inset::getStatus. This might require an additional
256         // BufferView * arg, though (which should be avoided)
257         //Cursor safe = *this;
258         bool res = false;
259         for ( ; cursor.depth(); cursor.pop()) {
260                 //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
261                 BOOST_ASSERT(cursor.idx() <= cursor.lastidx());
262                 BOOST_ASSERT(cursor.pit() <= cursor.lastpit());
263                 BOOST_ASSERT(cursor.pos() <= cursor.lastpos());
264
265                 // The inset's getStatus() will return 'true' if it made
266                 // a definitive decision on whether it want to handle the
267                 // request or not. The result of this decision is put into
268                 // the 'status' parameter.
269                 if (cursor.inset().getStatus(cursor, cmd, status)) {
270                         res = true;
271                         break;
272                 }
273         }
274         return res;
275 }
276
277
278 /** Return the change status at cursor position, taking in account the
279  * status at each level of the document iterator (a table in a deleted
280  * footnote is deleted).
281  * When \param outer is true, the top slice is not looked at.
282  */
283 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
284 {
285         size_t const depth = dit.depth() - (outer ? 1 : 0);
286
287         for (size_t i = 0 ; i < depth ; ++i) {
288                 CursorSlice const & slice = dit[i];
289                 if (!slice.inset().inMathed()
290                     && slice.pos() < slice.paragraph().size()) {
291                         Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
292                         if (ch != Change::UNCHANGED)
293                                 return ch;
294                 }
295         }
296         return Change::UNCHANGED;
297 }
298
299 }
300
301
302 LyXFunc::LyXFunc()
303         : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
304 {
305 }
306
307
308 void LyXFunc::initKeySequences(KeyMap * kb)
309 {
310         keyseq = KeySequence(kb, kb);
311         cancel_meta_seq = KeySequence(kb, kb);
312 }
313
314
315 void LyXFunc::setLyXView(LyXView * lv)
316 {
317         if (!quitting && lyx_view_ && lyx_view_->view() && lyx_view_ != lv)
318                 // save current selection to the selection buffer to allow
319                 // middle-button paste in another window
320                 cap::saveSelection(lyx_view_->view()->cursor());
321         lyx_view_ = lv;
322 }
323
324
325 void LyXFunc::handleKeyFunc(kb_action action)
326 {
327         char_type c = encoded_last_key;
328
329         if (keyseq.length())
330                 c = 0;
331
332         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
333         lyx_view_->view()->getIntl().getTransManager().deadkey(
334                 c, get_accent(action).accent, view()->cursor().innerText(), view()->cursor());
335         // Need to clear, in case the minibuffer calls these
336         // actions
337         keyseq.clear();
338         // copied verbatim from do_accent_char
339         view()->cursor().resetAnchor();
340         view()->processUpdateFlags(Update::FitCursor);
341 }
342
343
344 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
345 {
346         BOOST_ASSERT(lyx_view_);
347         if (!LyX::ref().session().bookmarks().isValid(idx))
348                 return;
349         BookmarksSection::Bookmark const & bm = LyX::ref().session().bookmarks().bookmark(idx);
350         BOOST_ASSERT(!bm.filename.empty());
351         string const file = bm.filename.absFilename();
352         // if the file is not opened, open it.
353         if (!theBufferList().exists(file)) {
354                 if (openFile)
355                         dispatch(FuncRequest(LFUN_FILE_OPEN, file));
356                 else
357                         return;
358         }
359         // open may fail, so we need to test it again
360         if (!theBufferList().exists(file))
361                 return;
362
363         // if the current buffer is not that one, switch to it.
364         if (lyx_view_->buffer()->absFileName() != file) {
365                 if (!switchToBuffer)
366                         return;
367                 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
368         }
369         // moveToPosition try paragraph id first and then paragraph (pit, pos).
370         if (!view()->moveToPosition(bm.bottom_pit, bm.bottom_pos,
371                 bm.top_id, bm.top_pos))
372                 return;
373
374         // Cursor jump succeeded!
375         Cursor const & cur = view()->cursor();
376         pit_type new_pit = cur.pit();
377         pos_type new_pos = cur.pos();
378         int new_id = cur.paragraph().id();
379
380         // if bottom_pit, bottom_pos or top_id has been changed, update bookmark
381         // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
382         if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos 
383                 || bm.top_id != new_id) {
384                 const_cast<BookmarksSection::Bookmark &>(bm).updatePos(
385                         new_pit, new_pos, new_id);
386         }
387 }
388
389
390 namespace {
391 void restartCursor(LyXView * lv)
392 {
393         /* When we move around, or type, it's nice to be able to see
394          * the cursor immediately after the keypress.
395          */
396         if (lv && lv->currentWorkArea())
397                 lv->currentWorkArea()->startBlinkingCursor();
398 }
399 }
400
401 void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
402 {
403         LYXERR(Debug::KEY) << "KeySym is " << keysym.getSymbolName() << endl;
404
405         // Do nothing if we have nothing (JMarc)
406         if (!keysym.isOK()) {
407                 LYXERR(Debug::KEY) << "Empty kbd action (probably composing)"
408                                    << endl;
409                 restartCursor(lyx_view_);
410                 return;
411         }
412
413         if (keysym.isModifier()) {
414                 LYXERR(Debug::KEY) << "isModifier true" << endl;
415                 restartCursor(lyx_view_);
416                 return;
417         }
418
419         //Encoding const * encoding = view()->cursor().getEncoding();
420         //encoded_last_key = keysym.getISOEncoded(encoding ? encoding->name() : "");
421         // FIXME: encoded_last_key shadows the member variable of the same
422         // name. Is that intended?
423         char_type encoded_last_key = keysym.getUCSEncoded();
424
425         // Do a one-deep top-level lookup for
426         // cancel and meta-fake keys. RVDK_PATCH_5
427         cancel_meta_seq.reset();
428
429         FuncRequest func = cancel_meta_seq.addkey(keysym, state);
430         LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
431                            << " action first set to [" << func.action << ']'
432                            << endl;
433
434         // When not cancel or meta-fake, do the normal lookup.
435         // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
436         // Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5.
437         if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) {
438                 // remove Caps Lock and Mod2 as a modifiers
439                 func = keyseq.addkey(keysym, (state | meta_fake_bit));
440                 LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
441                                    << "action now set to ["
442                                    << func.action << ']' << endl;
443         }
444
445         // Dont remove this unless you know what you are doing.
446         meta_fake_bit = NoModifier;
447
448         // Can this happen now ?
449         if (func.action == LFUN_NOACTION)
450                 func = FuncRequest(LFUN_COMMAND_PREFIX);
451
452         LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
453                << " Key [action="
454                << func.action << "]["
455                << to_utf8(keyseq.print(KeySequence::Portable)) << ']'
456                << endl;
457
458         // already here we know if it any point in going further
459         // why not return already here if action == -1 and
460         // num_bytes == 0? (Lgb)
461
462         if (keyseq.length() > 1)
463                 lyx_view_->message(keyseq.print(KeySequence::ForGui));
464
465
466         // Maybe user can only reach the key via holding down shift.
467         // Let's see. But only if shift is the only modifier
468         if (func.action == LFUN_UNKNOWN_ACTION && state == ShiftModifier) {
469                 LYXERR(Debug::KEY) << "Trying without shift" << endl;
470                 func = keyseq.addkey(keysym, NoModifier);
471                 LYXERR(Debug::KEY) << "Action now " << func.action << endl;
472         }
473
474         if (func.action == LFUN_UNKNOWN_ACTION) {
475                 // Hmm, we didn't match any of the keysequences. See
476                 // if it's normal insertable text not already covered
477                 // by a binding
478                 if (keysym.isText() && keyseq.length() == 1) {
479                         LYXERR(Debug::KEY) << "isText() is true, inserting." << endl;
480                         func = FuncRequest(LFUN_SELF_INSERT,
481                                            FuncRequest::KEYBOARD);
482                 } else {
483                         LYXERR(Debug::KEY) << "Unknown, !isText() - giving up" << endl;
484                         lyx_view_->message(_("Unknown function."));
485                         restartCursor(lyx_view_);
486                         return;
487                 }
488         }
489
490         if (func.action == LFUN_SELF_INSERT) {
491                 if (encoded_last_key != 0) {
492                         docstring const arg(1, encoded_last_key);
493                         dispatch(FuncRequest(LFUN_SELF_INSERT, arg,
494                                              FuncRequest::KEYBOARD));
495                         LYXERR(Debug::KEY)
496                                 << "SelfInsert arg[`" << to_utf8(arg) << "']" << endl;
497                 }
498         } else {
499                 dispatch(func);
500         }
501
502         restartCursor(lyx_view_);
503 }
504
505
506 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
507 {
508         //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
509         FuncStatus flag;
510
511         /* In LyX/Mac, when a dialog is open, the menus of the
512            application can still be accessed without giving focus to
513            the main window. In this case, we want to disable the menu
514            entries that are buffer-related.
515
516            Note that this code is not perfect, as bug 1941 attests:
517            http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
518         */
519         Buffer * buf = lyx_view_? lyx_view_->buffer() : 0;
520         if (lyx_view_ && cmd.origin == FuncRequest::MENU && !lyx_view_->hasFocus())
521                 buf = 0;
522
523         if (cmd.action == LFUN_NOACTION) {
524                 flag.message(from_utf8(N_("Nothing to do")));
525                 flag.enabled(false);
526                 return flag;
527         }
528
529         switch (cmd.action) {
530         case LFUN_UNKNOWN_ACTION:
531 #ifndef HAVE_LIBAIKSAURUS
532         case LFUN_THESAURUS_ENTRY:
533 #endif
534                 flag.unknown(true);
535                 flag.enabled(false);
536                 break;
537
538         default:
539                 break;
540         }
541
542         if (flag.unknown()) {
543                 flag.message(from_utf8(N_("Unknown action")));
544                 return flag;
545         }
546
547         if (!flag.enabled()) {
548                 if (flag.message().empty())
549                         flag.message(from_utf8(N_("Command disabled")));
550                 return flag;
551         }
552
553         // Check whether we need a buffer
554         if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
555                 // no, exit directly
556                 flag.message(from_utf8(N_("Command not allowed with"
557                                     "out any document open")));
558                 flag.enabled(false);
559                 return flag;
560         }
561
562         // I would really like to avoid having this switch and rather try to
563         // encode this in the function itself.
564         // -- And I'd rather let an inset decide which LFUNs it is willing
565         // to handle (Andre')
566         bool enable = true;
567         switch (cmd.action) {
568         case LFUN_BUFFER_TOGGLE_READ_ONLY:
569                 flag.setOnOff(buf->isReadonly());
570                 break;
571
572         case LFUN_BUFFER_SWITCH:
573                 // toggle on the current buffer, but do not toggle off
574                 // the other ones (is that a good idea?)
575                 if (buf && to_utf8(cmd.argument()) == buf->absFileName())
576                         flag.setOnOff(true);
577                 break;
578
579         case LFUN_BUFFER_EXPORT:
580                 enable = cmd.argument() == "custom"
581                         || buf->isExportable(to_utf8(cmd.argument()));
582                 break;
583
584         case LFUN_BUFFER_CHKTEX:
585                 enable = buf->isLatex() && !lyxrc.chktex_command.empty();
586                 break;
587
588         case LFUN_BUILD_PROGRAM:
589                 enable = buf->isExportable("program");
590                 break;
591
592         case LFUN_VC_REGISTER:
593                 enable = !buf->lyxvc().inUse();
594                 break;
595         case LFUN_VC_CHECK_IN:
596                 enable = buf->lyxvc().inUse() && !buf->isReadonly();
597                 break;
598         case LFUN_VC_CHECK_OUT:
599                 enable = buf->lyxvc().inUse() && buf->isReadonly();
600                 break;
601         case LFUN_VC_REVERT:
602         case LFUN_VC_UNDO_LAST:
603                 enable = buf->lyxvc().inUse();
604                 break;
605         case LFUN_BUFFER_RELOAD:
606                 enable = !buf->isUnnamed() && fs::exists(buf->absFileName())
607                         && (!buf->isClean() || buf->isExternallyModified(Buffer::timestamp_method));
608                 break;
609
610         case LFUN_INSET_APPLY: {
611                 if (!view()) {
612                         enable = false;
613                         break;
614                 }
615                 string const name = cmd.getArg(0);
616                 Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
617                 if (inset) {
618                         FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
619                         FuncStatus fs;
620                         if (!inset->getStatus(view()->cursor(), fr, fs)) {
621                                 // Every inset is supposed to handle this
622                                 BOOST_ASSERT(false);
623                         }
624                         flag |= fs;
625                 } else {
626                         FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
627                         flag |= getStatus(fr);
628                 }
629                 enable = flag.enabled();
630                 break;
631         }
632
633         case LFUN_DIALOG_TOGGLE:
634                 flag.setOnOff(lyx_view_->getDialogs().visible(cmd.getArg(0)));
635                 // fall through to set "enable"
636         case LFUN_DIALOG_SHOW: {
637                 string const name = cmd.getArg(0);
638                 if (!buf)
639                         enable = name == "aboutlyx"
640                                 || name == "file" //FIXME: should be removed.
641                                 || name == "prefs"
642                                 || name == "texinfo";
643                 else if (name == "print")
644                         enable = buf->isExportable("dvi")
645                                 && lyxrc.print_command != "none";
646                 else if (name == "character") {
647                         if (!view())
648                                 enable = false;
649                         else {
650                                 InsetCode ic = view()->cursor().inset().lyxCode();
651                                 enable = ic != ERT_CODE && ic != LISTINGS_CODE;
652                         }
653                 }
654                 else if (name == "latexlog")
655                         enable = FileName(buf->logName().second).isFileReadable();
656                 else if (name == "spellchecker")
657 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
658                         enable = !buf->isReadonly();
659 #else
660                         enable = false;
661 #endif
662                 else if (name == "vclog")
663                         enable = buf->lyxvc().inUse();
664                 break;
665         }
666
667         case LFUN_DIALOG_UPDATE: {
668                 string const name = cmd.getArg(0);
669                 if (!buf)
670                         enable = name == "prefs";
671                 break;
672         }
673
674         case LFUN_CITATION_INSERT: {
675                 FuncRequest fr(LFUN_INSET_INSERT, "citation");
676                 enable = getStatus(fr).enabled();
677                 break;
678         }
679
680         case LFUN_BUFFER_WRITE: {
681                 enable = lyx_view_->buffer()->isUnnamed()
682                         || !lyx_view_->buffer()->isClean();
683                 break;
684         }
685
686
687         case LFUN_BUFFER_WRITE_ALL: {
688         // We enable the command only if there are some modified buffers
689                 Buffer * first = theBufferList().first();
690                 bool modified = false;
691                 if (first) {
692                         Buffer * b = first;
693                 
694                 // We cannot use a for loop as the buffer list is a cycle.
695                         do {
696                                 if (!b->isClean()) {
697                                         modified = true;
698                                         break;
699                                 }
700                                 b = theBufferList().next(b);
701                         } while (b != first); 
702                 }
703         
704                 enable = modified;
705
706                 break;
707         }
708
709         case LFUN_BOOKMARK_GOTO: {
710                 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
711                 enable = LyX::ref().session().bookmarks().isValid(num);
712                 break;
713         }
714
715         case LFUN_BOOKMARK_CLEAR:
716                 enable = LyX::ref().session().bookmarks().size() > 0;
717                 break;
718
719         case LFUN_TOOLBAR_TOGGLE: {
720                 bool const current = lyx_view_->isToolbarVisible(cmd.getArg(0));
721                 flag.setOnOff(current);
722                 break;
723         }
724         case LFUN_WINDOW_CLOSE: {
725                 enable = (theApp()->gui().viewIds().size() > 1);
726                 break;
727         }
728
729         // this one is difficult to get right. As a half-baked
730         // solution, we consider only the first action of the sequence
731         case LFUN_COMMAND_SEQUENCE: {
732                 // argument contains ';'-terminated commands
733                 string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
734                 FuncRequest func(lyxaction.lookupFunc(firstcmd));
735                 func.origin = cmd.origin;
736                 flag = getStatus(func);
737                 break;
738         }
739
740         case LFUN_CALL: {
741                 FuncRequest func;
742                 std::string name(to_utf8(cmd.argument()));
743                 if (LyX::ref().topLevelCmdDef().lock(name, func)) {
744                         func.origin = cmd.origin;
745                         flag = getStatus(func);
746                         LyX::ref().topLevelCmdDef().release(name);
747                 } else {
748                         // catch recursion or unknown command definiton
749                         // all operations until the recursion or unknown command 
750                         // definiton occures are performed, so set the state to enabled
751                         enable = true;
752                 }
753                 break;
754         }
755
756         case LFUN_BUFFER_NEW:
757         case LFUN_BUFFER_NEW_TEMPLATE:
758         case LFUN_WORD_FIND_FORWARD:
759         case LFUN_WORD_FIND_BACKWARD:
760         case LFUN_COMMAND_PREFIX:
761         case LFUN_COMMAND_EXECUTE:
762         case LFUN_CANCEL:
763         case LFUN_META_PREFIX:
764         case LFUN_BUFFER_CLOSE:
765         case LFUN_BUFFER_WRITE_AS:
766         case LFUN_BUFFER_UPDATE:
767         case LFUN_BUFFER_VIEW:
768         case LFUN_MASTER_BUFFER_UPDATE:
769         case LFUN_MASTER_BUFFER_VIEW:
770         case LFUN_BUFFER_IMPORT:
771         case LFUN_BUFFER_AUTO_SAVE:
772         case LFUN_RECONFIGURE:
773         case LFUN_HELP_OPEN:
774         case LFUN_FILE_NEW:
775         case LFUN_FILE_OPEN:
776         case LFUN_DROP_LAYOUTS_CHOICE:
777         case LFUN_MENU_OPEN:
778         case LFUN_SERVER_GET_NAME:
779         case LFUN_SERVER_NOTIFY:
780         case LFUN_SERVER_GOTO_FILE_ROW:
781         case LFUN_DIALOG_HIDE:
782         case LFUN_DIALOG_DISCONNECT_INSET:
783         case LFUN_BUFFER_CHILD_OPEN:
784         case LFUN_TOGGLE_CURSOR_FOLLOWS_SCROLLBAR:
785         case LFUN_KEYMAP_OFF:
786         case LFUN_KEYMAP_PRIMARY:
787         case LFUN_KEYMAP_SECONDARY:
788         case LFUN_KEYMAP_TOGGLE:
789         case LFUN_REPEAT:
790         case LFUN_BUFFER_EXPORT_CUSTOM:
791         case LFUN_BUFFER_PRINT:
792         case LFUN_PREFERENCES_SAVE:
793         case LFUN_SCREEN_FONT_UPDATE:
794         case LFUN_SET_COLOR:
795         case LFUN_MESSAGE:
796         case LFUN_EXTERNAL_EDIT:
797         case LFUN_GRAPHICS_EDIT:
798         case LFUN_ALL_INSETS_TOGGLE:
799         case LFUN_BUFFER_LANGUAGE:
800         case LFUN_TEXTCLASS_APPLY:
801         case LFUN_TEXTCLASS_LOAD:
802         case LFUN_BUFFER_SAVE_AS_DEFAULT:
803         case LFUN_BUFFER_PARAMS_APPLY:
804         case LFUN_LAYOUT_MODULES_CLEAR:
805         case LFUN_LAYOUT_MODULE_ADD:
806         case LFUN_LAYOUT_RELOAD:
807         case LFUN_LYXRC_APPLY:
808         case LFUN_BUFFER_NEXT:
809         case LFUN_BUFFER_PREVIOUS:
810         case LFUN_WINDOW_NEW:
811         case LFUN_LYX_QUIT:
812                 // these are handled in our dispatch()
813                 break;
814
815         default:
816                 if (!view()) {
817                         enable = false;
818                         break;
819                 }
820                 if (!getLocalStatus(view()->cursor(), cmd, flag))
821                         flag = view()->getStatus(cmd);
822         }
823
824         if (!enable)
825                 flag.enabled(false);
826
827         // Can we use a readonly buffer?
828         if (buf && buf->isReadonly()
829             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
830             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
831                 flag.message(from_utf8(N_("Document is read-only")));
832                 flag.enabled(false);
833         }
834
835         // Are we in a DELETED change-tracking region?
836         if (buf && view() 
837                 && lookupChangeType(view()->cursor(), true) == Change::DELETED
838             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
839             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
840                 flag.message(from_utf8(N_("This portion of the document is deleted.")));
841                 flag.enabled(false);
842         }
843
844         // the default error message if we disable the command
845         if (!flag.enabled() && flag.message().empty())
846                 flag.message(from_utf8(N_("Command disabled")));
847
848         return flag;
849 }
850
851
852 bool LyXFunc::ensureBufferClean(BufferView * bv)
853 {
854         Buffer & buf = bv->buffer();
855         if (buf.isClean())
856                 return true;
857
858         docstring const file = makeDisplayPath(buf.absFileName(), 30);
859         docstring text = bformat(_("The document %1$s has unsaved "
860                                              "changes.\n\nDo you want to save "
861                                              "the document?"), file);
862         int const ret = Alert::prompt(_("Save changed document?"),
863                                       text, 0, 1, _("&Save"),
864                                       _("&Cancel"));
865
866         if (ret == 0)
867                 dispatch(FuncRequest(LFUN_BUFFER_WRITE));
868
869         return buf.isClean();
870 }
871
872
873 namespace {
874
875 void showPrintError(string const & name)
876 {
877         docstring str = bformat(_("Could not print the document %1$s.\n"
878                                             "Check that your printer is set up correctly."),
879                              makeDisplayPath(name, 50));
880         Alert::error(_("Print document failed"), str);
881 }
882
883
884 void loadTextClass(string const & name)
885 {
886         std::pair<bool, textclass_type> const tc_pair =
887                 textclasslist.numberOfClass(name);
888
889         if (!tc_pair.first) {
890                 lyxerr << "Document class \"" << name
891                        << "\" does not exist."
892                        << std::endl;
893                 return;
894         }
895
896         textclass_type const tc = tc_pair.second;
897
898         if (!textclasslist[tc].load()) {
899                 docstring s = bformat(_("The document class %1$s."
900                                    "could not be loaded."),
901                                    from_utf8(textclasslist[tc].name()));
902                 Alert::error(_("Could not load class"), s);
903         }
904 }
905
906
907 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
908
909 } //namespace anon
910
911
912 void LyXFunc::dispatch(FuncRequest const & cmd)
913 {
914         string const argument = to_utf8(cmd.argument());
915         kb_action const action = cmd.action;
916
917         LYXERR(Debug::ACTION) << endl << "LyXFunc::dispatch: cmd: " << cmd << endl;
918         //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
919
920         // we have not done anything wrong yet.
921         errorstat = false;
922         dispatch_buffer.erase();
923
924         // redraw the screen at the end (first of the two drawing steps).
925         //This is done unless explicitely requested otherwise
926         Update::flags updateFlags = Update::FitCursor;
927
928         FuncStatus const flag = getStatus(cmd);
929         if (!flag.enabled()) {
930                 // We cannot use this function here
931                 LYXERR(Debug::ACTION) << "LyXFunc::dispatch: "
932                        << lyxaction.getActionName(action)
933                        << " [" << action << "] is disabled at this location"
934                        << endl;
935                 setErrorMessage(flag.message());
936         } else {
937                 switch (action) {
938
939                 case LFUN_WORD_FIND_FORWARD:
940                 case LFUN_WORD_FIND_BACKWARD: {
941                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
942                         static docstring last_search;
943                         docstring searched_string;
944
945                         if (!cmd.argument().empty()) {
946                                 last_search = cmd.argument();
947                                 searched_string = cmd.argument();
948                         } else {
949                                 searched_string = last_search;
950                         }
951
952                         if (searched_string.empty())
953                                 break;
954
955                         bool const fw = action == LFUN_WORD_FIND_FORWARD;
956                         docstring const data =
957                                 find2string(searched_string, true, false, fw);
958                         find(view(), FuncRequest(LFUN_WORD_FIND, data));
959                         break;
960                 }
961
962                 case LFUN_COMMAND_PREFIX:
963                         BOOST_ASSERT(lyx_view_);
964                         lyx_view_->message(keyseq.printOptions(true));
965                         break;
966
967                 case LFUN_COMMAND_EXECUTE:
968                         BOOST_ASSERT(lyx_view_);
969                         lyx_view_->showMiniBuffer(true);
970                         break;
971
972                 case LFUN_CANCEL:
973                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
974                         keyseq.reset();
975                         meta_fake_bit = NoModifier;
976                         if (lyx_view_->buffer())
977                                 // cancel any selection
978                                 dispatch(FuncRequest(LFUN_MARK_OFF));
979                         setMessage(from_ascii(N_("Cancel")));
980                         break;
981
982                 case LFUN_META_PREFIX:
983                         meta_fake_bit = AltModifier;
984                         setMessage(keyseq.print(KeySequence::ForGui));
985                         break;
986
987                 case LFUN_BUFFER_TOGGLE_READ_ONLY: {
988                         BOOST_ASSERT(lyx_view_ && lyx_view_->view() && lyx_view_->buffer());
989                         Buffer * buf = lyx_view_->buffer();
990                         if (buf->lyxvc().inUse())
991                                 buf->lyxvc().toggleReadOnly();
992                         else
993                                 buf->setReadonly(!lyx_view_->buffer()->isReadonly());
994                         break;
995                 }
996
997                 // --- Menus -----------------------------------------------
998                 case LFUN_BUFFER_NEW:
999                         menuNew(argument, false);
1000                         updateFlags = Update::None;
1001                         break;
1002
1003                 case LFUN_BUFFER_NEW_TEMPLATE:
1004                         menuNew(argument, true);
1005                         updateFlags = Update::None;
1006                         break;
1007
1008                 case LFUN_BUFFER_CLOSE:
1009                         closeBuffer();
1010                         updateFlags = Update::None;
1011                         break;
1012
1013                 case LFUN_BUFFER_WRITE:
1014                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1015                         if (!lyx_view_->buffer()->isUnnamed()) {
1016                                 docstring const str = bformat(_("Saving document %1$s..."),
1017                                          makeDisplayPath(lyx_view_->buffer()->absFileName()));
1018                                 lyx_view_->message(str);
1019                                 lyx_view_->buffer()->menuWrite();
1020                                 lyx_view_->message(str + _(" done."));
1021                         } else {
1022                                 lyx_view_->buffer()->writeAs();
1023                         }
1024                         updateFlags = Update::None;
1025                         break;
1026
1027                 case LFUN_BUFFER_WRITE_AS:
1028                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1029                         lyx_view_->buffer()->writeAs(argument);
1030                         updateFlags = Update::None;
1031                         break;
1032
1033                 case LFUN_BUFFER_WRITE_ALL: {
1034                         Buffer * first = theBufferList().first();
1035                         if (first) {
1036                                 Buffer * b = first;
1037                                 lyx_view_->message(_("Saving all documents..."));
1038                 
1039                                 // We cannot use a for loop as the buffer list cycles.
1040                                 do {
1041                                         if (!b->isClean()) {
1042                                                 if (!b->isUnnamed()) {
1043                                                         b->menuWrite();
1044                                                         lyxerr[Debug::ACTION] << "Saved " << b->absFileName() << endl;
1045                                                 } else
1046                                                         b->writeAs();
1047                                         }
1048                                         b = theBufferList().next(b);
1049                                 } while (b != first); 
1050                                 lyx_view_->message(_("All documents saved."));
1051                         } 
1052         
1053                         updateFlags = Update::None;
1054                         break;
1055                 }
1056
1057                 case LFUN_BUFFER_RELOAD: {
1058                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1059                         docstring const file = makeDisplayPath(lyx_view_->buffer()->absFileName(), 20);
1060                         docstring text = bformat(_("Any changes will be lost. Are you sure "
1061                                                              "you want to revert to the saved version of the document %1$s?"), file);
1062                         int const ret = Alert::prompt(_("Revert to saved document?"),
1063                                 text, 1, 1, _("&Revert"), _("&Cancel"));
1064
1065                         if (ret == 0)
1066                                 reloadBuffer();
1067                         break;
1068                 }
1069
1070                 case LFUN_BUFFER_UPDATE:
1071                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1072                         lyx_view_->buffer()->doExport(argument, true);
1073                         break;
1074
1075                 case LFUN_BUFFER_VIEW:
1076                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1077                         lyx_view_->buffer()->preview(argument);
1078                         break;
1079
1080                 case LFUN_MASTER_BUFFER_UPDATE:
1081                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer() && lyx_view_->buffer()->masterBuffer());
1082                         lyx_view_->buffer()->masterBuffer()->doExport(argument, true);
1083                         break;
1084
1085                 case LFUN_MASTER_BUFFER_VIEW:
1086                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer() && lyx_view_->buffer()->masterBuffer());
1087                         lyx_view_->buffer()->masterBuffer()->preview(argument);
1088                         break;
1089
1090                 case LFUN_BUILD_PROGRAM:
1091                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1092                         lyx_view_->buffer()->doExport("program", true);
1093                         break;
1094
1095                 case LFUN_BUFFER_CHKTEX:
1096                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1097                         lyx_view_->buffer()->runChktex();
1098                         break;
1099
1100                 case LFUN_BUFFER_EXPORT:
1101                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1102                         if (argument == "custom")
1103                                 lyx_view_->getDialogs().show("sendto");
1104                         else
1105                                 lyx_view_->buffer()->doExport(argument, false);
1106                         break;
1107
1108                 case LFUN_BUFFER_EXPORT_CUSTOM: {
1109                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1110                         string format_name;
1111                         string command = split(argument, format_name, ' ');
1112                         Format const * format = formats.getFormat(format_name);
1113                         if (!format) {
1114                                 lyxerr << "Format \"" << format_name
1115                                        << "\" not recognized!"
1116                                        << std::endl;
1117                                 break;
1118                         }
1119
1120                         Buffer * buffer = lyx_view_->buffer();
1121
1122                         // The name of the file created by the conversion process
1123                         string filename;
1124
1125                         // Output to filename
1126                         if (format->name() == "lyx") {
1127                                 string const latexname = buffer->latexName(false);
1128                                 filename = changeExtension(latexname,
1129                                                            format->extension());
1130                                 filename = addName(buffer->temppath(), filename);
1131
1132                                 if (!buffer->writeFile(FileName(filename)))
1133                                         break;
1134
1135                         } else {
1136                                 buffer->doExport(format_name, true, filename);
1137                         }
1138
1139                         // Substitute $$FName for filename
1140                         if (!contains(command, "$$FName"))
1141                                 command = "( " + command + " ) < $$FName";
1142                         command = subst(command, "$$FName", filename);
1143
1144                         // Execute the command in the background
1145                         Systemcall call;
1146                         call.startscript(Systemcall::DontWait, command);
1147                         break;
1148                 }
1149
1150                 case LFUN_BUFFER_PRINT: {
1151                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1152                         // FIXME: cmd.getArg() might fail if one of the arguments
1153                         // contains double quotes
1154                         string target = cmd.getArg(0);
1155                         string target_name = cmd.getArg(1);
1156                         string command = cmd.getArg(2);
1157
1158                         if (target.empty()
1159                             || target_name.empty()
1160                             || command.empty()) {
1161                                 lyxerr << "Unable to parse \""
1162                                        << argument << '"' << endl;
1163                                 break;
1164                         }
1165                         if (target != "printer" && target != "file") {
1166                                 lyxerr << "Unrecognized target \""
1167                                        << target << '"' << endl;
1168                                 break;
1169                         }
1170
1171                         Buffer * buffer = lyx_view_->buffer();
1172
1173                         if (!buffer->doExport("dvi", true)) {
1174                                 showPrintError(buffer->absFileName());
1175                                 break;
1176                         }
1177
1178                         // Push directory path.
1179                         string const path = buffer->temppath();
1180                         // Prevent the compiler from optimizing away p
1181                         FileName pp(path);
1182                         support::Path p(pp);
1183
1184                         // there are three cases here:
1185                         // 1. we print to a file
1186                         // 2. we print directly to a printer
1187                         // 3. we print using a spool command (print to file first)
1188                         Systemcall one;
1189                         int res = 0;
1190                         string const dviname =
1191                                 changeExtension(buffer->latexName(true), "dvi");
1192
1193                         if (target == "printer") {
1194                                 if (!lyxrc.print_spool_command.empty()) {
1195                                         // case 3: print using a spool
1196                                         string const psname =
1197                                                 changeExtension(dviname,".ps");
1198                                         command += ' ' + lyxrc.print_to_file
1199                                                 + quoteName(psname)
1200                                                 + ' '
1201                                                 + quoteName(dviname);
1202
1203                                         string command2 =
1204                                                 lyxrc.print_spool_command + ' ';
1205                                         if (target_name != "default") {
1206                                                 command2 += lyxrc.print_spool_printerprefix
1207                                                         + target_name
1208                                                         + ' ';
1209                                         }
1210                                         command2 += quoteName(psname);
1211                                         // First run dvips.
1212                                         // If successful, then spool command
1213                                         res = one.startscript(
1214                                                 Systemcall::Wait,
1215                                                 command);
1216
1217                                         if (res == 0)
1218                                                 res = one.startscript(
1219                                                         Systemcall::DontWait,
1220                                                         command2);
1221                                 } else {
1222                                         // case 2: print directly to a printer
1223                                         if (target_name != "default")
1224                                                 command += ' ' + lyxrc.print_to_printer + target_name + ' ';
1225                                         res = one.startscript(
1226                                                 Systemcall::DontWait,
1227                                                 command + quoteName(dviname));
1228                                 }
1229
1230                         } else {
1231                                 // case 1: print to a file
1232                                 FileName const filename(makeAbsPath(target_name,
1233                                                         lyx_view_->buffer()->filePath()));
1234                                 FileName const dvifile(makeAbsPath(dviname, path));
1235                                 if (filename.exists()) {
1236                                         docstring text = bformat(
1237                                                 _("The file %1$s already exists.\n\n"
1238                                                   "Do you want to overwrite that file?"),
1239                                                 makeDisplayPath(filename.absFilename()));
1240                                         if (Alert::prompt(_("Overwrite file?"),
1241                                             text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
1242                                                 break;
1243                                 }
1244                                 command += ' ' + lyxrc.print_to_file
1245                                         + quoteName(filename.toFilesystemEncoding())
1246                                         + ' '
1247                                         + quoteName(dvifile.toFilesystemEncoding());
1248                                 res = one.startscript(Systemcall::DontWait,
1249                                                       command);
1250                         }
1251
1252                         if (res != 0)
1253                                 showPrintError(buffer->absFileName());
1254                         break;
1255                 }
1256
1257                 case LFUN_BUFFER_IMPORT:
1258                         doImport(argument);
1259                         break;
1260
1261                 case LFUN_LYX_QUIT:
1262                         // quitting is triggered by the gui code
1263                         // (leaving the event loop).
1264                         lyx_view_->message(from_utf8(N_("Exiting.")));
1265                         if (theBufferList().quitWriteAll())
1266                                 theApp()->gui().closeAllViews();
1267                         break;
1268
1269                 case LFUN_BUFFER_AUTO_SAVE:
1270                         lyx_view_->buffer()->autoSave();
1271                         break;
1272
1273                 case LFUN_RECONFIGURE:
1274                         BOOST_ASSERT(lyx_view_);
1275                         // argument is any additional parameter to the configure.py command
1276                         reconfigure(*lyx_view_, argument);
1277                         break;
1278
1279                 case LFUN_HELP_OPEN: {
1280                         BOOST_ASSERT(lyx_view_);
1281                         string const arg = argument;
1282                         if (arg.empty()) {
1283                                 setErrorMessage(from_ascii(N_("Missing argument")));
1284                                 break;
1285                         }
1286                         FileName const fname = i18nLibFileSearch("doc", arg, "lyx");
1287                         if (fname.empty()) {
1288                                 lyxerr << "LyX: unable to find documentation file `"
1289                                                          << arg << "'. Bad installation?" << endl;
1290                                 break;
1291                         }
1292                         lyx_view_->message(bformat(_("Opening help file %1$s..."),
1293                                 makeDisplayPath(fname.absFilename())));
1294                         Buffer * buf = lyx_view_->loadLyXFile(fname, false);
1295                         if (buf) {
1296                                 updateLabels(*buf);
1297                                 lyx_view_->setBuffer(buf);
1298                                 lyx_view_->showErrorList("Parse");
1299                         }
1300                         updateFlags = Update::None;
1301                         break;
1302                 }
1303
1304                 // --- version control -------------------------------
1305                 case LFUN_VC_REGISTER:
1306                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1307                         if (!ensureBufferClean(view()))
1308                                 break;
1309                         if (!lyx_view_->buffer()->lyxvc().inUse()) {
1310                                 lyx_view_->buffer()->lyxvc().registrer();
1311                                 reloadBuffer();
1312                         }
1313                         updateFlags = Update::Force;
1314                         break;
1315
1316                 case LFUN_VC_CHECK_IN:
1317                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1318                         if (!ensureBufferClean(view()))
1319                                 break;
1320                         if (lyx_view_->buffer()->lyxvc().inUse()
1321                                         && !lyx_view_->buffer()->isReadonly()) {
1322                                 lyx_view_->buffer()->lyxvc().checkIn();
1323                                 reloadBuffer();
1324                         }
1325                         break;
1326
1327                 case LFUN_VC_CHECK_OUT:
1328                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1329                         if (!ensureBufferClean(view()))
1330                                 break;
1331                         if (lyx_view_->buffer()->lyxvc().inUse()
1332                                         && lyx_view_->buffer()->isReadonly()) {
1333                                 lyx_view_->buffer()->lyxvc().checkOut();
1334                                 reloadBuffer();
1335                         }
1336                         break;
1337
1338                 case LFUN_VC_REVERT:
1339                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1340                         lyx_view_->buffer()->lyxvc().revert();
1341                         reloadBuffer();
1342                         break;
1343
1344                 case LFUN_VC_UNDO_LAST:
1345                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1346                         lyx_view_->buffer()->lyxvc().undoLast();
1347                         reloadBuffer();
1348                         break;
1349
1350                 // --- buffers ----------------------------------------
1351                 case LFUN_BUFFER_SWITCH:
1352                         BOOST_ASSERT(lyx_view_);
1353                         lyx_view_->setBuffer(theBufferList().getBuffer(argument));
1354                         updateFlags = Update::None;
1355                         break;
1356
1357                 case LFUN_BUFFER_NEXT:
1358                         BOOST_ASSERT(lyx_view_);
1359                         lyx_view_->setBuffer(theBufferList().next(lyx_view_->buffer()));
1360                         updateFlags = Update::None;
1361                         break;
1362
1363                 case LFUN_BUFFER_PREVIOUS:
1364                         BOOST_ASSERT(lyx_view_);
1365                         lyx_view_->setBuffer(theBufferList().previous(lyx_view_->buffer()));
1366                         updateFlags = Update::None;
1367                         break;
1368
1369                 case LFUN_FILE_NEW: {
1370                         BOOST_ASSERT(lyx_view_);
1371                         string name;
1372                         string tmpname = split(argument, name, ':'); // Split filename
1373                         Buffer * const b = newFile(name, tmpname);
1374                         if (b)
1375                                 lyx_view_->setBuffer(b);
1376                         updateFlags = Update::None;
1377                         break;
1378                 }
1379
1380                 case LFUN_FILE_OPEN:
1381                         BOOST_ASSERT(lyx_view_);
1382                         open(argument);
1383                         updateFlags = Update::None;
1384                         break;
1385
1386                 case LFUN_DROP_LAYOUTS_CHOICE:
1387                         BOOST_ASSERT(lyx_view_);
1388                         lyx_view_->openLayoutList();
1389                         break;
1390
1391                 case LFUN_MENU_OPEN:
1392                         BOOST_ASSERT(lyx_view_);
1393                         lyx_view_->openMenu(from_utf8(argument));
1394                         break;
1395
1396                 // --- lyxserver commands ----------------------------
1397                 case LFUN_SERVER_GET_NAME:
1398                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1399                         setMessage(from_utf8(lyx_view_->buffer()->absFileName()));
1400                         LYXERR(Debug::INFO) << "FNAME["
1401                                                          << lyx_view_->buffer()->absFileName()
1402                                                          << "] " << endl;
1403                         break;
1404
1405                 case LFUN_SERVER_NOTIFY:
1406                         dispatch_buffer = keyseq.print(KeySequence::Portable);
1407                         theServer().notifyClient(to_utf8(dispatch_buffer));
1408                         break;
1409
1410                 case LFUN_SERVER_GOTO_FILE_ROW: {
1411                         BOOST_ASSERT(lyx_view_);
1412                         string file_name;
1413                         int row;
1414                         istringstream is(argument);
1415                         is >> file_name >> row;
1416                         Buffer * buf = 0;
1417                         bool loaded = false;
1418                         if (prefixIs(file_name, package().temp_dir().absFilename()))
1419                                 // Needed by inverse dvi search. If it is a file
1420                                 // in tmpdir, call the apropriated function
1421                                 buf = theBufferList().getBufferFromTmp(file_name);
1422                         else {
1423                                 // Must replace extension of the file to be .lyx
1424                                 // and get full path
1425                                 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
1426                                 // Either change buffer or load the file
1427                                 if (theBufferList().exists(s.absFilename()))
1428                                         buf = theBufferList().getBuffer(s.absFilename());
1429                                 else {
1430                                         buf = lyx_view_->loadLyXFile(s);
1431                                         loaded = true;
1432                                 }
1433                         }
1434
1435                         if (!buf) {
1436                                 updateFlags = Update::None;
1437                                 break;
1438                         }
1439
1440                         updateLabels(*buf);
1441                         lyx_view_->setBuffer(buf);
1442                         view()->setCursorFromRow(row);
1443                         if (loaded)
1444                                 lyx_view_->showErrorList("Parse");
1445                         updateFlags = Update::FitCursor;
1446                         break;
1447                 }
1448
1449                 case LFUN_DIALOG_SHOW: {
1450                         BOOST_ASSERT(lyx_view_);
1451                         string const name = cmd.getArg(0);
1452                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1453
1454                         if (name == "character") {
1455                                 data = freefont2string();
1456                                 if (!data.empty())
1457                                         lyx_view_->getDialogs().show("character", data);
1458                         } else if (name == "latexlog") {
1459                                 pair<Buffer::LogType, string> const logfile =
1460                                         lyx_view_->buffer()->logName();
1461                                 switch (logfile.first) {
1462                                 case Buffer::latexlog:
1463                                         data = "latex ";
1464                                         break;
1465                                 case Buffer::buildlog:
1466                                         data = "literate ";
1467                                         break;
1468                                 }
1469                                 data += Lexer::quoteString(logfile.second);
1470                                 lyx_view_->getDialogs().show("log", data);
1471                         } else if (name == "vclog") {
1472                                 string const data = "vc " +
1473                                         Lexer::quoteString(lyx_view_->buffer()->lyxvc().getLogFile());
1474                                 lyx_view_->getDialogs().show("log", data);
1475                         } else
1476                                 lyx_view_->getDialogs().show(name, data);
1477                         break;
1478                 }
1479
1480                 case LFUN_DIALOG_SHOW_NEW_INSET: {
1481                         BOOST_ASSERT(lyx_view_);
1482                         string const name = cmd.getArg(0);
1483                         InsetCode code = insetCode(name);
1484                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1485                         bool insetCodeOK = true;
1486                         switch (code) {
1487                         case BIBITEM_CODE:
1488                         case BIBTEX_CODE:
1489                         case INDEX_CODE:
1490                         case LABEL_CODE:
1491                         case NOMENCL_CODE:
1492                         case REF_CODE:
1493                         case TOC_CODE:
1494                         case HYPERLINK_CODE: {
1495                                 InsetCommandParams p(code);
1496                                 data = InsetCommandMailer::params2string(name, p);
1497                                 break;
1498                         } 
1499                         case INCLUDE_CODE: {
1500                                 // data is the include type: one of "include",
1501                                 // "input", "verbatiminput" or "verbatiminput*"
1502                                 if (data.empty())
1503                                         // default type is requested
1504                                         data = "include";
1505                                 InsetCommandParams p(INCLUDE_CODE, data);
1506                                 data = InsetCommandMailer::params2string("include", p);
1507                                 break;
1508                         } 
1509                         case BOX_CODE: {
1510                                 // \c data == "Boxed" || "Frameless" etc
1511                                 InsetBoxParams p(data);
1512                                 data = InsetBoxMailer::params2string(p);
1513                                 break;
1514                         } 
1515                         case BRANCH_CODE: {
1516                                 InsetBranchParams p;
1517                                 data = InsetBranchMailer::params2string(p);
1518                                 break;
1519                         } 
1520                         case CITE_CODE: {
1521                                 InsetCommandParams p(CITE_CODE);
1522                                 data = InsetCommandMailer::params2string(name, p);
1523                                 break;
1524                         } 
1525                         case ERT_CODE: {
1526                                 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1527                                 break;
1528                         } 
1529                         case EXTERNAL_CODE: {
1530                                 InsetExternalParams p;
1531                                 Buffer const & buffer = *lyx_view_->buffer();
1532                                 data = InsetExternalMailer::params2string(p, buffer);
1533                                 break;
1534                         } 
1535                         case FLOAT_CODE:  {
1536                                 InsetFloatParams p;
1537                                 data = InsetFloatMailer::params2string(p);
1538                                 break;
1539                         } 
1540                         case LISTINGS_CODE: {
1541                                 InsetListingsParams p;
1542                                 data = InsetListingsMailer::params2string(p);
1543                                 break;
1544                         } 
1545                         case GRAPHICS_CODE: {
1546                                 InsetGraphicsParams p;
1547                                 Buffer const & buffer = *lyx_view_->buffer();
1548                                 data = InsetGraphicsMailer::params2string(p, buffer);
1549                                 break;
1550                         } 
1551                         case NOTE_CODE: {
1552                                 InsetNoteParams p;
1553                                 data = InsetNoteMailer::params2string(p);
1554                                 break;
1555                         } 
1556                         case VSPACE_CODE: {
1557                                 VSpace space;
1558                                 data = InsetVSpaceMailer::params2string(space);
1559                                 break;
1560                         } 
1561                         case WRAP_CODE: {
1562                                 InsetWrapParams p;
1563                                 data = InsetWrapMailer::params2string(p);
1564                                 break;
1565                         }
1566                         default:
1567                                 lyxerr << "Inset type '" << name << 
1568                                         "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << std:: endl;
1569                                 insetCodeOK = false;
1570                                 break;
1571                         } // end switch(code)
1572                         if (insetCodeOK)
1573                                 lyx_view_->getDialogs().show(name, data, 0);
1574                         break;
1575                 }
1576
1577                 case LFUN_DIALOG_UPDATE: {
1578                         BOOST_ASSERT(lyx_view_);
1579                         string const & name = argument;
1580                         // Can only update a dialog connected to an existing inset
1581                         Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
1582                         if (inset) {
1583                                 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1584                                 inset->dispatch(view()->cursor(), fr);
1585                         } else if (name == "paragraph") {
1586                                 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1587                         } else if (name == "prefs") {
1588                                 lyx_view_->getDialogs().update(name, string());
1589                         }
1590                         break;
1591                 }
1592
1593                 case LFUN_DIALOG_HIDE:
1594                         LyX::cref().hideDialogs(argument, 0);
1595                         break;
1596
1597                 case LFUN_DIALOG_TOGGLE: {
1598                         BOOST_ASSERT(lyx_view_);
1599                         if (lyx_view_->getDialogs().visible(cmd.getArg(0)))
1600                                 dispatch(FuncRequest(LFUN_DIALOG_HIDE, argument));
1601                         else
1602                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, argument));
1603                         break;
1604                 }
1605
1606                 case LFUN_DIALOG_DISCONNECT_INSET:
1607                         BOOST_ASSERT(lyx_view_);
1608                         lyx_view_->getDialogs().disconnect(argument);
1609                         break;
1610
1611
1612                 case LFUN_CITATION_INSERT: {
1613                         BOOST_ASSERT(lyx_view_);
1614                         if (!argument.empty()) {
1615                                 // we can have one optional argument, delimited by '|'
1616                                 // citation-insert <key>|<text_before>
1617                                 // this should be enhanced to also support text_after
1618                                 // and citation style
1619                                 string arg = argument;
1620                                 string opt1;
1621                                 if (contains(argument, "|")) {
1622                                         arg = token(argument, '|', 0);
1623                                         opt1 = token(argument, '|', 1);
1624                                 }
1625                                 InsetCommandParams icp(CITE_CODE);
1626                                 icp["key"] = from_utf8(arg);
1627                                 if (!opt1.empty())
1628                                         icp["before"] = from_utf8(opt1);
1629                                 string icstr = InsetCommandMailer::params2string("citation", icp);
1630                                 FuncRequest fr(LFUN_INSET_INSERT, icstr);
1631                                 dispatch(fr);
1632                         } else
1633                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
1634                         break;
1635                 }
1636
1637                 case LFUN_BUFFER_CHILD_OPEN: {
1638                         BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1639                         Buffer * parent = lyx_view_->buffer();
1640                         FileName filename = makeAbsPath(argument, parent->filePath());
1641                         view()->saveBookmark(false);
1642                         Buffer * child = 0;
1643                         bool parsed = false;
1644                         if (theBufferList().exists(filename.absFilename())) {
1645                                 child = theBufferList().getBuffer(filename.absFilename());
1646                         } else {
1647                                 setMessage(bformat(_("Opening child document %1$s..."),
1648                                         makeDisplayPath(filename.absFilename())));
1649                                 child = lyx_view_->loadLyXFile(filename, true);
1650                                 parsed = true;
1651                         }
1652                         if (child) {
1653                                 // Set the parent name of the child document.
1654                                 // This makes insertion of citations and references in the child work,
1655                                 // when the target is in the parent or another child document.
1656                                 child->setParentName(parent->absFileName());
1657                                 updateLabels(*child->masterBuffer());
1658                                 lyx_view_->setBuffer(child);
1659                                 if (parsed)
1660                                         lyx_view_->showErrorList("Parse");
1661                         }
1662
1663                         // If a screen update is required (in case where auto_open is false), 
1664                         // setBuffer() would have taken care of it already. Otherwise we shall 
1665                         // reset the update flag because it can cause a circular problem.
1666                         // See bug 3970.
1667                         updateFlags = Update::None;
1668                         break;
1669                 }
1670
1671                 case LFUN_TOGGLE_CURSOR_FOLLOWS_SCROLLBAR:
1672                         BOOST_ASSERT(lyx_view_);
1673                         lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1674                         break;
1675
1676                 case LFUN_KEYMAP_OFF:
1677                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1678                         lyx_view_->view()->getIntl().keyMapOn(false);
1679                         break;
1680
1681                 case LFUN_KEYMAP_PRIMARY:
1682                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1683                         lyx_view_->view()->getIntl().keyMapPrim();
1684                         break;
1685
1686                 case LFUN_KEYMAP_SECONDARY:
1687                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1688                         lyx_view_->view()->getIntl().keyMapSec();
1689                         break;
1690
1691                 case LFUN_KEYMAP_TOGGLE:
1692                         BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1693                         lyx_view_->view()->getIntl().toggleKeyMap();
1694                         break;
1695
1696                 case LFUN_REPEAT: {
1697                         // repeat command
1698                         string countstr;
1699                         string rest = split(argument, countstr, ' ');
1700                         istringstream is(countstr);
1701                         int count = 0;
1702                         is >> count;
1703                         lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1704                         for (int i = 0; i < count; ++i)
1705                                 dispatch(lyxaction.lookupFunc(rest));
1706                         break;
1707                 }
1708
1709                 case LFUN_COMMAND_SEQUENCE: {
1710                         // argument contains ';'-terminated commands
1711                         string arg = argument;
1712                         while (!arg.empty()) {
1713                                 string first;
1714                                 arg = split(arg, first, ';');
1715                                 FuncRequest func(lyxaction.lookupFunc(first));
1716                                 func.origin = cmd.origin;
1717                                 dispatch(func);
1718                         }
1719                         break;
1720                 }
1721
1722                 case LFUN_CALL: {
1723                         FuncRequest func;
1724                         if (LyX::ref().topLevelCmdDef().lock(argument, func)) {
1725                                 func.origin = cmd.origin;
1726                                 dispatch(func);
1727                                 LyX::ref().topLevelCmdDef().release(argument);
1728                         } else {
1729                                 if (func.action == LFUN_UNKNOWN_ACTION) {
1730                                         // unknown command definition
1731                                         lyxerr << "Warning: unknown command definition `"
1732                                                    << argument << "'"
1733                                                    << endl;
1734                                 } else {
1735                                         // recursion detected
1736                                         lyxerr << "Warning: Recursion in the command definition `"
1737                                                    << argument << "' detected"
1738                                                    << endl;
1739                                 }
1740                         }
1741                         break;
1742                 }
1743
1744                 case LFUN_PREFERENCES_SAVE: {
1745                         lyxrc.write(makeAbsPath("preferences",
1746                                                 package().user_support().absFilename()),
1747                                     false);
1748                         break;
1749                 }
1750
1751                 case LFUN_SCREEN_FONT_UPDATE:
1752                         BOOST_ASSERT(lyx_view_);
1753                         // handle the screen font changes.
1754                         theFontLoader().update();
1755                         /// FIXME: only the current view will be updated. the Gui
1756                         /// class is able to furnish the list of views.
1757                         updateFlags = Update::Force;
1758                         break;
1759
1760                 case LFUN_SET_COLOR: {
1761                         string lyx_name;
1762                         string const x11_name = split(argument, lyx_name, ' ');
1763                         if (lyx_name.empty() || x11_name.empty()) {
1764                                 setErrorMessage(from_ascii(N_(
1765                                                 "Syntax: set-color <lyx_name>"
1766                                                 " <x11_name>")));
1767                                 break;
1768                         }
1769
1770                         bool const graphicsbg_changed =
1771                                 (lyx_name == lcolor.getLyXName(Color_graphicsbg) &&
1772                                  x11_name != lcolor.getX11Name(Color_graphicsbg));
1773
1774                         if (!lcolor.setColor(lyx_name, x11_name)) {
1775                                 setErrorMessage(
1776                                                 bformat(_("Set-color \"%1$s\" failed "
1777                                                                        "- color is undefined or "
1778                                                                        "may not be redefined"),
1779                                                                            from_utf8(lyx_name)));
1780                                 break;
1781                         }
1782
1783                         theApp()->updateColor(lcolor.getFromLyXName(lyx_name));
1784
1785                         if (graphicsbg_changed) {
1786                                 // FIXME: The graphics cache no longer has a changeDisplay method.
1787 #if 0
1788                                 graphics::GCache::get().changeDisplay(true);
1789 #endif
1790                         }
1791                         break;
1792                 }
1793
1794                 case LFUN_MESSAGE:
1795                         BOOST_ASSERT(lyx_view_);
1796                         lyx_view_->message(from_utf8(argument));
1797                         break;
1798
1799                 case LFUN_EXTERNAL_EDIT: {
1800                         BOOST_ASSERT(lyx_view_);
1801                         FuncRequest fr(action, argument);
1802                         InsetExternal().dispatch(view()->cursor(), fr);
1803                         break;
1804                 }
1805
1806                 case LFUN_GRAPHICS_EDIT: {
1807                         FuncRequest fr(action, argument);
1808                         InsetGraphics().dispatch(view()->cursor(), fr);
1809                         break;
1810                 }
1811
1812                 case LFUN_INSET_APPLY: {
1813                         BOOST_ASSERT(lyx_view_);
1814                         string const name = cmd.getArg(0);
1815                         Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
1816                         if (inset) {
1817                                 FuncRequest fr(LFUN_INSET_MODIFY, argument);
1818                                 inset->dispatch(view()->cursor(), fr);
1819                         } else {
1820                                 FuncRequest fr(LFUN_INSET_INSERT, argument);
1821                                 dispatch(fr);
1822                         }
1823                         // ideally, the update flag should be set by the insets,
1824                         // but this is not possible currently
1825                         updateFlags = Update::Force | Update::FitCursor;
1826                         break;
1827                 }
1828
1829                 case LFUN_ALL_INSETS_TOGGLE: {
1830                         BOOST_ASSERT(lyx_view_);
1831                         string action;
1832                         string const name = split(argument, action, ' ');
1833                         InsetCode const inset_code = insetCode(name);
1834
1835                         Cursor & cur = view()->cursor();
1836                         FuncRequest fr(LFUN_INSET_TOGGLE, action);
1837
1838                         Inset & inset = lyx_view_->buffer()->inset();
1839                         InsetIterator it  = inset_iterator_begin(inset);
1840                         InsetIterator const end = inset_iterator_end(inset);
1841                         for (; it != end; ++it) {
1842                                 if (!it->asInsetMath()
1843                                     && (inset_code == NO_CODE
1844                                     || inset_code == it->lyxCode())) {
1845                                         Cursor tmpcur = cur;
1846                                         tmpcur.pushLeft(*it);
1847                                         it->dispatch(tmpcur, fr);
1848                                 }
1849                         }
1850                         updateFlags = Update::Force | Update::FitCursor;
1851                         break;
1852                 }
1853
1854                 case LFUN_BUFFER_LANGUAGE: {
1855                         BOOST_ASSERT(lyx_view_);
1856                         Buffer & buffer = *lyx_view_->buffer();
1857                         Language const * oldL = buffer.params().language;
1858                         Language const * newL = languages.getLanguage(argument);
1859                         if (!newL || oldL == newL)
1860                                 break;
1861
1862                         if (oldL->rightToLeft() == newL->rightToLeft()
1863                             && !buffer.isMultiLingual())
1864                                 buffer.changeLanguage(oldL, newL);
1865                         break;
1866                 }
1867
1868                 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1869                         string const fname =
1870                                 addName(addPath(package().user_support().absFilename(), "templates/"),
1871                                         "defaults.lyx");
1872                         Buffer defaults(fname);
1873
1874                         istringstream ss(argument);
1875                         Lexer lex(0,0);
1876                         lex.setStream(ss);
1877                         int const unknown_tokens = defaults.readHeader(lex);
1878
1879                         if (unknown_tokens != 0) {
1880                                 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1881                                        << unknown_tokens << " unknown token"
1882                                        << (unknown_tokens == 1 ? "" : "s")
1883                                        << endl;
1884                         }
1885
1886                         if (defaults.writeFile(FileName(defaults.absFileName())))
1887                                 setMessage(bformat(_("Document defaults saved in %1$s"),
1888                                                    makeDisplayPath(fname)));
1889                         else
1890                                 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1891                         break;
1892                 }
1893
1894                 case LFUN_BUFFER_PARAMS_APPLY: {
1895                         BOOST_ASSERT(lyx_view_);
1896                         biblio::CiteEngine const oldEngine =
1897                                         lyx_view_->buffer()->params().getEngine();
1898                         
1899                         Buffer * buffer = lyx_view_->buffer();
1900
1901                         TextClassPtr oldClass = buffer->params().getTextClassPtr();
1902
1903                         Cursor & cur = view()->cursor();
1904                         cur.recordUndoFullDocument();
1905                         
1906                         istringstream ss(argument);
1907                         Lexer lex(0,0);
1908                         lex.setStream(ss);
1909                         int const unknown_tokens = buffer->readHeader(lex);
1910
1911                         if (unknown_tokens != 0) {
1912                                 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1913                                                 << unknown_tokens << " unknown token"
1914                                                 << (unknown_tokens == 1 ? "" : "s")
1915                                                 << endl;
1916                         }
1917                         
1918                         updateLayout(oldClass, buffer);
1919                         
1920                         biblio::CiteEngine const newEngine =
1921                                         lyx_view_->buffer()->params().getEngine();
1922                         
1923                         if (oldEngine != newEngine) {
1924                                 FuncRequest fr(LFUN_INSET_REFRESH);
1925         
1926                                 Inset & inset = lyx_view_->buffer()->inset();
1927                                 InsetIterator it  = inset_iterator_begin(inset);
1928                                 InsetIterator const end = inset_iterator_end(inset);
1929                                 for (; it != end; ++it)
1930                                         if (it->lyxCode() == CITE_CODE)
1931                                                 it->dispatch(cur, fr);
1932                         }
1933                         
1934                         updateFlags = Update::Force | Update::FitCursor;
1935                         break;
1936                 }
1937                 
1938                 case LFUN_LAYOUT_MODULES_CLEAR: {
1939                         BOOST_ASSERT(lyx_view_);
1940                         Buffer * buffer = lyx_view_->buffer();
1941                         TextClassPtr oldClass = buffer->params().getTextClassPtr();
1942                         view()->cursor().recordUndoFullDocument();
1943                         buffer->params().clearLayoutModules();
1944                         updateLayout(oldClass, buffer);
1945                         updateFlags = Update::Force | Update::FitCursor;
1946                         break;
1947                 }
1948                 
1949                 case LFUN_LAYOUT_MODULE_ADD: {
1950                         BOOST_ASSERT(lyx_view_);
1951                         Buffer * buffer = lyx_view_->buffer();
1952                         TextClassPtr oldClass = buffer->params().getTextClassPtr();
1953                         view()->cursor().recordUndoFullDocument();
1954                         buffer->params().addLayoutModule(argument);
1955                         updateLayout(oldClass, buffer);
1956                         updateFlags = Update::Force | Update::FitCursor;
1957                         break;
1958                 }
1959
1960                 case LFUN_TEXTCLASS_APPLY: {
1961                         BOOST_ASSERT(lyx_view_);
1962                         Buffer * buffer = lyx_view_->buffer();
1963
1964                         loadTextClass(argument);
1965
1966                         std::pair<bool, textclass_type> const tc_pair =
1967                                 textclasslist.numberOfClass(argument);
1968
1969                         if (!tc_pair.first)
1970                                 break;
1971
1972                         textclass_type const old_class = buffer->params().getBaseClass();
1973                         textclass_type const new_class = tc_pair.second;
1974
1975                         if (old_class == new_class)
1976                                 // nothing to do
1977                                 break;
1978
1979                         //Save the old, possibly modular, layout for use in conversion.
1980                         TextClassPtr oldClass = buffer->params().getTextClassPtr();
1981                         view()->cursor().recordUndoFullDocument();
1982                         buffer->params().setBaseClass(new_class);
1983                         updateLayout(oldClass, buffer);
1984                         updateFlags = Update::Force | Update::FitCursor;
1985                         break;
1986                 }
1987                 
1988                 case LFUN_LAYOUT_RELOAD: {
1989                         BOOST_ASSERT(lyx_view_);
1990                         Buffer * buffer = lyx_view_->buffer();
1991                         TextClassPtr oldClass = buffer->params().getTextClassPtr();
1992                         textclass_type const tc = buffer->params().getBaseClass();
1993                         textclasslist.reset(tc);
1994                         buffer->params().setBaseClass(tc);
1995                         updateLayout(oldClass, buffer);
1996                         updateFlags = Update::Force | Update::FitCursor;
1997                         break;
1998                 }
1999
2000                 case LFUN_TEXTCLASS_LOAD:
2001                         loadTextClass(argument);
2002                         break;
2003
2004                 case LFUN_LYXRC_APPLY: {
2005                         LyXRC const lyxrc_orig = lyxrc;
2006
2007                         istringstream ss(argument);
2008                         bool const success = lyxrc.read(ss) == 0;
2009
2010                         if (!success) {
2011                                 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
2012                                        << "Unable to read lyxrc data"
2013                                        << endl;
2014                                 break;
2015                         }
2016
2017                         actOnUpdatedPrefs(lyxrc_orig, lyxrc);
2018
2019                         /// We force the redraw in any case because there might be
2020                         /// some screen font changes.
2021                         /// FIXME: only the current view will be updated. the Gui
2022                         /// class is able to furnish the list of views.
2023                         updateFlags = Update::Force;
2024                         break;
2025                 }
2026
2027                 case LFUN_WINDOW_NEW:
2028                         LyX::ref().newLyXView();
2029                         break;
2030
2031                 case LFUN_WINDOW_CLOSE:
2032                         BOOST_ASSERT(lyx_view_);
2033                         BOOST_ASSERT(theApp());
2034                         // update bookmark pit of the current buffer before window close
2035                         for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
2036                                 gotoBookmark(i+1, false, false);
2037                         // ask the user for saving changes or cancel quit
2038                         if (!theBufferList().quitWriteAll())
2039                                 break;
2040                         lyx_view_->close();
2041                         return;
2042
2043                 case LFUN_BOOKMARK_GOTO:
2044                         // go to bookmark, open unopened file and switch to buffer if necessary
2045                         gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
2046                         break;
2047
2048                 case LFUN_BOOKMARK_CLEAR:
2049                         LyX::ref().session().bookmarks().clear();
2050                         break;
2051
2052                 case LFUN_TOOLBAR_TOGGLE: {
2053                         BOOST_ASSERT(lyx_view_);
2054                         string const name = cmd.getArg(0);
2055                         bool const allowauto = cmd.getArg(1) == "allowauto";
2056                         lyx_view_->toggleToolbarState(name, allowauto);
2057                         ToolbarInfo * tbi = lyx_view_->getToolbarInfo(name);
2058                         if (!tbi) {
2059                                 setMessage(bformat(_("Unknown toolbar \"%1$s\""),
2060                                                    from_utf8(name)));
2061                                 break;
2062                         }
2063                         docstring state;
2064                         if (tbi->flags & ToolbarInfo::ON)
2065                                 state = _("on");
2066                         else if (tbi->flags & ToolbarInfo::OFF)
2067                                 state = _("off");
2068                         else if (tbi->flags & ToolbarInfo::AUTO)
2069                                 state = _("auto");
2070
2071                         setMessage(bformat(_("Toolbar \"%1$s\" state set to %2$s"), 
2072                                            _(tbi->gui_name), state));
2073                         break;
2074                 }
2075
2076                 default: {
2077                         BOOST_ASSERT(lyx_view_);
2078                         view()->cursor().dispatch(cmd);
2079                         updateFlags = view()->cursor().result().update();
2080                         if (!view()->cursor().result().dispatched())
2081                                 updateFlags = view()->dispatch(cmd);
2082                         break;
2083                 }
2084                 }
2085
2086                 if (lyx_view_ && lyx_view_->buffer()) {
2087                         // BufferView::update() updates the ViewMetricsInfo and
2088                         // also initializes the position cache for all insets in
2089                         // (at least partially) visible top-level paragraphs.
2090                         // We will redraw the screen only if needed.
2091                         view()->processUpdateFlags(updateFlags);
2092                         lyx_view_->updateStatusBar();
2093
2094                         // if we executed a mutating lfun, mark the buffer as dirty
2095                         if (flag.enabled()
2096                             && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
2097                             && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
2098                                 lyx_view_->buffer()->markDirty();
2099
2100                         //Do we have a selection?
2101                         theSelection().haveSelection(view()->cursor().selection());
2102
2103                         if (view()->cursor().inTexted()) {
2104                                 lyx_view_->updateLayoutChoice();
2105                         }
2106                 }
2107         }
2108         if (!quitting && lyx_view_) {
2109                 lyx_view_->updateToolbars();
2110                 // Some messages may already be translated, so we cannot use _()
2111                 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
2112         }
2113 }
2114
2115
2116 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
2117 {
2118         const bool verbose = (cmd.origin == FuncRequest::MENU
2119                               || cmd.origin == FuncRequest::TOOLBAR
2120                               || cmd.origin == FuncRequest::COMMANDBUFFER);
2121
2122         if (cmd.action == LFUN_SELF_INSERT || !verbose) {
2123                 LYXERR(Debug::ACTION) << "dispatch msg is " << to_utf8(msg) << endl;
2124                 if (!msg.empty())
2125                         lyx_view_->message(msg);
2126                 return;
2127         }
2128
2129         docstring dispatch_msg = msg;
2130         if (!dispatch_msg.empty())
2131                 dispatch_msg += ' ';
2132
2133         docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
2134
2135         bool argsadded = false;
2136
2137         if (!cmd.argument().empty()) {
2138                 if (cmd.action != LFUN_UNKNOWN_ACTION) {
2139                         comname += ' ' + cmd.argument();
2140                         argsadded = true;
2141                 }
2142         }
2143
2144         docstring const shortcuts = theTopLevelKeymap().printbindings(cmd);
2145
2146         if (!shortcuts.empty())
2147                 comname += ": " + shortcuts;
2148         else if (!argsadded && !cmd.argument().empty())
2149                 comname += ' ' + cmd.argument();
2150
2151         if (!comname.empty()) {
2152                 comname = rtrim(comname);
2153                 dispatch_msg += '(' + rtrim(comname) + ')';
2154         }
2155
2156         LYXERR(Debug::ACTION) << "verbose dispatch msg "
2157                 << to_utf8(dispatch_msg) << endl;
2158         if (!dispatch_msg.empty())
2159                 lyx_view_->message(dispatch_msg);
2160 }
2161
2162
2163 void LyXFunc::menuNew(string const & name, bool fromTemplate)
2164 {
2165         // FIXME: initpath is not used. What to do?
2166         string initpath = lyxrc.document_path;
2167         string filename(name);
2168
2169         if (lyx_view_->buffer()) {
2170                 string const trypath = lyx_view_->buffer()->filePath();
2171                 // If directory is writeable, use this as default.
2172                 if (FileName(trypath).isDirWritable())
2173                         initpath = trypath;
2174         }
2175
2176         static int newfile_number;
2177
2178         if (filename.empty()) {
2179                 filename = addName(lyxrc.document_path,
2180                             "newfile" + convert<string>(++newfile_number) + ".lyx");
2181                 while (theBufferList().exists(filename) ||
2182                        FileName(filename).isReadable()) {
2183                         ++newfile_number;
2184                         filename = addName(lyxrc.document_path,
2185                                            "newfile" +  convert<string>(newfile_number) +
2186                                     ".lyx");
2187                 }
2188         }
2189
2190         // The template stuff
2191         string templname;
2192         if (fromTemplate) {
2193                 FileDialog dlg(_("Select template file"));
2194                 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
2195                 dlg.setButton1(_("Templates|#T#t"), from_utf8(lyxrc.template_path));
2196
2197                 FileDialog::Result result =
2198                         dlg.open(from_utf8(lyxrc.template_path),
2199                                      FileFilterList(_("LyX Documents (*.lyx)")),
2200                                      docstring());
2201
2202                 if (result.first == FileDialog::Later)
2203                         return;
2204                 if (result.second.empty())
2205                         return;
2206                 templname = to_utf8(result.second);
2207         }
2208
2209         Buffer * const b = newFile(filename, templname, !name.empty());
2210         if (b)
2211                 lyx_view_->setBuffer(b);
2212 }
2213
2214
2215 void LyXFunc::open(string const & fname)
2216 {
2217         string initpath = lyxrc.document_path;
2218
2219         if (lyx_view_->buffer()) {
2220                 string const trypath = lyx_view_->buffer()->filePath();
2221                 // If directory is writeable, use this as default.
2222                 if (FileName(trypath).isDirWritable())
2223                         initpath = trypath;
2224         }
2225
2226         string filename;
2227
2228         if (fname.empty()) {
2229                 FileDialog dlg(_("Select document to open"), LFUN_FILE_OPEN);
2230                 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
2231                 dlg.setButton2(_("Examples|#E#e"),
2232                                 from_utf8(addPath(package().system_support().absFilename(), "examples")));
2233
2234                 FileDialog::Result result =
2235                         dlg.open(from_utf8(initpath),
2236                                      FileFilterList(_("LyX Documents (*.lyx)")),
2237                                      docstring());
2238
2239                 if (result.first == FileDialog::Later)
2240                         return;
2241
2242                 filename = to_utf8(result.second);
2243
2244                 // check selected filename
2245                 if (filename.empty()) {
2246                         lyx_view_->message(_("Canceled."));
2247                         return;
2248                 }
2249         } else
2250                 filename = fname;
2251
2252         // get absolute path of file and add ".lyx" to the filename if
2253         // necessary
2254         FileName const fullname = fileSearch(string(), filename, "lyx");
2255         if (!fullname.empty())
2256                 filename = fullname.absFilename();
2257
2258         // if the file doesn't exist, let the user create one
2259         if (!fullname.exists()) {
2260                 // the user specifically chose this name. Believe him.
2261                 Buffer * const b = newFile(filename, string(), true);
2262                 if (b)
2263                         lyx_view_->setBuffer(b);
2264                 return;
2265         }
2266
2267         docstring const disp_fn = makeDisplayPath(filename);
2268         lyx_view_->message(bformat(_("Opening document %1$s..."), disp_fn));
2269
2270         docstring str2;
2271         Buffer * buf = lyx_view_->loadLyXFile(fullname);
2272         if (buf) {
2273                 updateLabels(*buf);
2274                 lyx_view_->setBuffer(buf);
2275                 lyx_view_->showErrorList("Parse");
2276                 str2 = bformat(_("Document %1$s opened."), disp_fn);
2277         } else {
2278                 str2 = bformat(_("Could not open document %1$s"), disp_fn);
2279         }
2280         lyx_view_->message(str2);
2281 }
2282
2283
2284 void LyXFunc::doImport(string const & argument)
2285 {
2286         string format;
2287         string filename = split(argument, format, ' ');
2288
2289         LYXERR(Debug::INFO) << "LyXFunc::doImport: " << format
2290                             << " file: " << filename << endl;
2291
2292         // need user interaction
2293         if (filename.empty()) {
2294                 string initpath = lyxrc.document_path;
2295
2296                 if (lyx_view_->buffer()) {
2297                         string const trypath = lyx_view_->buffer()->filePath();
2298                         // If directory is writeable, use this as default.
2299                         if (FileName(trypath).isDirWritable())
2300                                 initpath = trypath;
2301                 }
2302
2303                 docstring const text = bformat(_("Select %1$s file to import"),
2304                         formats.prettyName(format));
2305
2306                 FileDialog dlg(text, LFUN_BUFFER_IMPORT);
2307                 dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path));
2308                 dlg.setButton2(_("Examples|#E#e"),
2309                         from_utf8(addPath(package().system_support().absFilename(), "examples")));
2310
2311                 docstring filter = formats.prettyName(format);
2312                 filter += " (*.";
2313                 // FIXME UNICODE
2314                 filter += from_utf8(formats.extension(format));
2315                 filter += ')';
2316
2317                 FileDialog::Result result =
2318                         dlg.open(from_utf8(initpath),
2319                                      FileFilterList(filter),
2320                                      docstring());
2321
2322                 if (result.first == FileDialog::Later)
2323                         return;
2324
2325                 filename = to_utf8(result.second);
2326
2327                 // check selected filename
2328                 if (filename.empty())
2329                         lyx_view_->message(_("Canceled."));
2330         }
2331
2332         if (filename.empty())
2333                 return;
2334
2335         // get absolute path of file
2336         FileName const fullname(makeAbsPath(filename));
2337
2338         FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
2339
2340         // Check if the document already is open
2341         if (use_gui && theBufferList().exists(lyxfile.absFilename())) {
2342                 if (!theBufferList().close(theBufferList().getBuffer(lyxfile.absFilename()), true)) {
2343                         lyx_view_->message(_("Canceled."));
2344                         return;
2345                 }
2346         }
2347
2348         // if the file exists already, and we didn't do
2349         // -i lyx thefile.lyx, warn
2350         if (lyxfile.exists() && fullname != lyxfile) {
2351                 docstring const file = makeDisplayPath(lyxfile.absFilename(), 30);
2352
2353                 docstring text = bformat(_("The document %1$s already exists.\n\n"
2354                                                      "Do you want to overwrite that document?"), file);
2355                 int const ret = Alert::prompt(_("Overwrite document?"),
2356                         text, 0, 1, _("&Overwrite"), _("&Cancel"));
2357
2358                 if (ret == 1) {
2359                         lyx_view_->message(_("Canceled."));
2360                         return;
2361                 }
2362         }
2363
2364         ErrorList errorList;
2365         import(lyx_view_, fullname, format, errorList);
2366         // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
2367 }
2368
2369
2370 void LyXFunc::closeBuffer()
2371 {
2372         // goto bookmark to update bookmark pit.
2373         for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
2374                 gotoBookmark(i+1, false, false);
2375         
2376         theBufferList().close(lyx_view_->buffer(), true);
2377 }
2378
2379
2380 void LyXFunc::reloadBuffer()
2381 {
2382         FileName filename(lyx_view_->buffer()->absFileName());
2383         docstring const disp_fn = makeDisplayPath(filename.absFilename());
2384         docstring str;
2385         closeBuffer();
2386         Buffer * buf = lyx_view_->loadLyXFile(filename);
2387         if (buf) {
2388                 updateLabels(*buf);
2389                 lyx_view_->setBuffer(buf);
2390                 lyx_view_->showErrorList("Parse");
2391                 str = bformat(_("Document %1$s reloaded."), disp_fn);
2392         } else {
2393                 str = bformat(_("Could not reload document %1$s"), disp_fn);
2394         }
2395         lyx_view_->message(str);
2396 }
2397
2398 // Each "lyx_view_" should have it's own message method. lyxview and
2399 // the minibuffer would use the minibuffer, but lyxserver would
2400 // send an ERROR signal to its client.  Alejandro 970603
2401 // This function is bit problematic when it comes to NLS, to make the
2402 // lyx servers client be language indepenent we must not translate
2403 // strings sent to this func.
2404 void LyXFunc::setErrorMessage(docstring const & m) const
2405 {
2406         dispatch_buffer = m;
2407         errorstat = true;
2408 }
2409
2410
2411 void LyXFunc::setMessage(docstring const & m) const
2412 {
2413         dispatch_buffer = m;
2414 }
2415
2416
2417 docstring const LyXFunc::viewStatusMessage()
2418 {
2419         // When meta-fake key is pressed, show the key sequence so far + "M-".
2420         if (wasMetaKey())
2421                 return keyseq.print(KeySequence::ForGui) + "M-";
2422
2423         // Else, when a non-complete key sequence is pressed,
2424         // show the available options.
2425         if (keyseq.length() > 0 && !keyseq.deleted())
2426                 return keyseq.printOptions(true);
2427
2428         BOOST_ASSERT(lyx_view_);
2429         if (!lyx_view_->buffer())
2430                 return _("Welcome to LyX!");
2431
2432         return view()->cursor().currentState();
2433 }
2434
2435
2436 BufferView * LyXFunc::view() const
2437 {
2438         BOOST_ASSERT(lyx_view_);
2439         return lyx_view_->view();
2440 }
2441
2442
2443 bool LyXFunc::wasMetaKey() const
2444 {
2445         return (meta_fake_bit != NoModifier);
2446 }
2447
2448
2449 void LyXFunc::updateLayout(TextClassPtr const & oldlayout,
2450                            Buffer * buffer)
2451 {
2452         lyx_view_->message(_("Converting document to new document class..."));
2453         
2454         StableDocIterator backcur(view()->cursor());
2455         ErrorList & el = buffer->errorList("Class Switch");
2456         cap::switchBetweenClasses(
2457                         oldlayout, buffer->params().getTextClassPtr(),
2458                         static_cast<InsetText &>(buffer->inset()), el);
2459
2460         view()->setCursor(backcur.asDocIterator(&(buffer->inset())));
2461
2462         buffer->errors("Class Switch");
2463         updateLabels(*buffer);
2464 }
2465
2466
2467 namespace {
2468
2469 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
2470 {
2471         // Why the switch you might ask. It is a trick to ensure that all
2472         // the elements in the LyXRCTags enum is handled. As you can see
2473         // there are no breaks at all. So it is just a huge fall-through.
2474         // The nice thing is that we will get a warning from the compiler
2475         // if we forget an element.
2476         LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
2477         switch (tag) {
2478         case LyXRC::RC_ACCEPT_COMPOUND:
2479         case LyXRC::RC_ALT_LANG:
2480         case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
2481         case LyXRC::RC_PLAINTEXT_LINELEN:
2482         case LyXRC::RC_AUTOREGIONDELETE:
2483         case LyXRC::RC_AUTORESET_OPTIONS:
2484         case LyXRC::RC_AUTOSAVE:
2485         case LyXRC::RC_AUTO_NUMBER:
2486         case LyXRC::RC_BACKUPDIR_PATH:
2487         case LyXRC::RC_BIBTEX_COMMAND:
2488         case LyXRC::RC_BINDFILE:
2489         case LyXRC::RC_CHECKLASTFILES:
2490         case LyXRC::RC_USELASTFILEPOS:
2491         case LyXRC::RC_LOADSESSION:
2492         case LyXRC::RC_CHKTEX_COMMAND:
2493         case LyXRC::RC_CONVERTER:
2494         case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
2495         case LyXRC::RC_COPIER:
2496         case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
2497         case LyXRC::RC_CUSTOM_EXPORT_COMMAND:
2498         case LyXRC::RC_CUSTOM_EXPORT_FORMAT:
2499         case LyXRC::RC_DATE_INSERT_FORMAT:
2500         case LyXRC::RC_DEFAULT_LANGUAGE:
2501         case LyXRC::RC_DEFAULT_PAPERSIZE:
2502         case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
2503         case LyXRC::RC_DISPLAY_GRAPHICS:
2504         case LyXRC::RC_DOCUMENTPATH:
2505                 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
2506                         FileName path(lyxrc_new.document_path);
2507                         if (path.exists() && path.isDirectory())
2508                                 support::package().document_dir() = FileName(lyxrc.document_path);
2509                 }
2510         case LyXRC::RC_ESC_CHARS:
2511         case LyXRC::RC_FONT_ENCODING:
2512         case LyXRC::RC_FORMAT:
2513         case LyXRC::RC_INDEX_COMMAND:
2514         case LyXRC::RC_INPUT:
2515         case LyXRC::RC_KBMAP:
2516         case LyXRC::RC_KBMAP_PRIMARY:
2517         case LyXRC::RC_KBMAP_SECONDARY:
2518         case LyXRC::RC_LABEL_INIT_LENGTH:
2519         case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
2520         case LyXRC::RC_LANGUAGE_AUTO_END:
2521         case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
2522         case LyXRC::RC_LANGUAGE_COMMAND_END:
2523         case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
2524         case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
2525         case LyXRC::RC_LANGUAGE_PACKAGE:
2526         case LyXRC::RC_LANGUAGE_USE_BABEL:
2527         case LyXRC::RC_MAKE_BACKUP:
2528         case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
2529         case LyXRC::RC_NUMLASTFILES:
2530         case LyXRC::RC_PATH_PREFIX:
2531                 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
2532                         support::prependEnvPath("PATH", lyxrc.path_prefix);
2533                 }
2534         case LyXRC::RC_PERS_DICT:
2535         case LyXRC::RC_PREVIEW:
2536         case LyXRC::RC_PREVIEW_HASHED_LABELS:
2537         case LyXRC::RC_PREVIEW_SCALE_FACTOR:
2538         case LyXRC::RC_PRINTCOLLCOPIESFLAG:
2539         case LyXRC::RC_PRINTCOPIESFLAG:
2540         case LyXRC::RC_PRINTER:
2541         case LyXRC::RC_PRINTEVENPAGEFLAG:
2542         case LyXRC::RC_PRINTEXSTRAOPTIONS:
2543         case LyXRC::RC_PRINTFILEEXTENSION:
2544         case LyXRC::RC_PRINTLANDSCAPEFLAG:
2545         case LyXRC::RC_PRINTODDPAGEFLAG:
2546         case LyXRC::RC_PRINTPAGERANGEFLAG:
2547         case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
2548         case LyXRC::RC_PRINTPAPERFLAG:
2549         case LyXRC::RC_PRINTREVERSEFLAG:
2550         case LyXRC::RC_PRINTSPOOL_COMMAND:
2551         case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
2552         case LyXRC::RC_PRINTTOFILE:
2553         case LyXRC::RC_PRINTTOPRINTER:
2554         case LyXRC::RC_PRINT_ADAPTOUTPUT:
2555         case LyXRC::RC_PRINT_COMMAND:
2556         case LyXRC::RC_RTL_SUPPORT:
2557         case LyXRC::RC_SCREEN_DPI:
2558         case LyXRC::RC_SCREEN_FONT_ROMAN:
2559         case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
2560         case LyXRC::RC_SCREEN_FONT_SANS:
2561         case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
2562         case LyXRC::RC_SCREEN_FONT_SCALABLE:
2563         case LyXRC::RC_SCREEN_FONT_SIZES:
2564         case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
2565         case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
2566         case LyXRC::RC_SCREEN_GEOMETRY_HEIGHT:
2567         case LyXRC::RC_SCREEN_GEOMETRY_WIDTH:
2568         case LyXRC::RC_SCREEN_GEOMETRY_XYSAVED:
2569         case LyXRC::RC_SCREEN_ZOOM:
2570         case LyXRC::RC_SERVERPIPE:
2571         case LyXRC::RC_SET_COLOR:
2572         case LyXRC::RC_SHOW_BANNER:
2573         case LyXRC::RC_SPELL_COMMAND:
2574         case LyXRC::RC_TEMPDIRPATH:
2575         case LyXRC::RC_TEMPLATEPATH:
2576         case LyXRC::RC_TEX_ALLOWS_SPACES:
2577         case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
2578                 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
2579                         support::os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
2580                 }
2581         case LyXRC::RC_UIFILE:
2582         case LyXRC::RC_USER_EMAIL:
2583         case LyXRC::RC_USER_NAME:
2584         case LyXRC::RC_USETEMPDIR:
2585         case LyXRC::RC_USE_ALT_LANG:
2586         case LyXRC::RC_USE_CONVERTER_CACHE:
2587         case LyXRC::RC_USE_ESC_CHARS:
2588         case LyXRC::RC_USE_INP_ENC:
2589         case LyXRC::RC_USE_PERS_DICT:
2590         case LyXRC::RC_USE_SPELL_LIB:
2591         case LyXRC::RC_VIEWDVI_PAPEROPTION:
2592         case LyXRC::RC_VIEWER:
2593         case LyXRC::RC_LAST:
2594                 break;
2595         }
2596 }
2597
2598 } // namespace anon
2599
2600
2601 } // namespace lyx