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