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