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