]> git.lyx.org Git - lyx.git/blob - src/LyXFunc.cpp
Move LFUN status check to where they belong.
[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
22 #include "LyXFunc.h"
23
24 #include "LayoutFile.h"
25 #include "BranchList.h"
26 #include "buffer_funcs.h"
27 #include "Buffer.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "CmdDef.h"
32 #include "Color.h"
33 #include "Converter.h"
34 #include "Cursor.h"
35 #include "CutAndPaste.h"
36 #include "DispatchResult.h"
37 #include "Encoding.h"
38 #include "ErrorList.h"
39 #include "Format.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
42 #include "InsetIterator.h"
43 #include "Intl.h"
44 #include "KeyMap.h"
45 #include "Language.h"
46 #include "Lexer.h"
47 #include "LyXAction.h"
48 #include "lyxfind.h"
49 #include "LyX.h"
50 #include "LyXRC.h"
51 #include "LyXVC.h"
52 #include "Paragraph.h"
53 #include "ParagraphParameters.h"
54 #include "ParIterator.h"
55 #include "Row.h"
56 #include "Server.h"
57 #include "Session.h"
58 #include "SpellChecker.h"
59
60 #include "insets/InsetBox.h"
61 #include "insets/InsetBranch.h"
62 #include "insets/InsetCommand.h"
63 #include "insets/InsetERT.h"
64 #include "insets/InsetExternal.h"
65 #include "insets/InsetFloat.h"
66 #include "insets/InsetGraphics.h"
67 #include "insets/InsetInclude.h"
68 #include "insets/InsetListings.h"
69 #include "insets/InsetNote.h"
70 #include "insets/InsetPhantom.h"
71 #include "insets/InsetSpace.h"
72 #include "insets/InsetTabular.h"
73 #include "insets/InsetVSpace.h"
74 #include "insets/InsetWrap.h"
75
76 #include "frontends/alert.h"
77 #include "frontends/Application.h"
78 #include "frontends/KeySymbol.h"
79 #include "frontends/LyXView.h"
80 #include "frontends/Selection.h"
81
82 #include "support/debug.h"
83 #include "support/environment.h"
84 #include "support/FileName.h"
85 #include "support/filetools.h"
86 #include "support/gettext.h"
87 #include "support/lstrings.h"
88 #include "support/Path.h"
89 #include "support/Package.h"
90 #include "support/Systemcall.h"
91 #include "support/convert.h"
92 #include "support/os.h"
93
94 #include <sstream>
95 #include <vector>
96
97 using namespace std;
98 using namespace lyx::support;
99
100 namespace lyx {
101
102 using frontend::LyXView;
103
104 namespace Alert = frontend::Alert;
105
106 namespace {
107
108
109 // This function runs "configure" and then rereads lyx.defaults to
110 // reconfigure the automatic settings.
111 void reconfigure(LyXView * lv, string const & option)
112 {
113         // emit message signal.
114         if (lv)
115                 lv->message(_("Running configure..."));
116
117         // Run configure in user lyx directory
118         PathChanger p(package().user_support());
119         string configure_command = package().configure_command();
120         configure_command += option;
121         Systemcall one;
122         int ret = one.startscript(Systemcall::Wait, configure_command);
123         p.pop();
124         // emit message signal.
125         if (lv)
126                 lv->message(_("Reloading configuration..."));
127         lyxrc.read(libFileSearch(string(), "lyxrc.defaults"));
128         // Re-read packages.lst
129         LaTeXFeatures::getAvailable();
130
131         if (ret)
132                 Alert::information(_("System reconfiguration failed"),
133                            _("The system reconfiguration has failed.\n"
134                                   "Default textclass is used but LyX may "
135                                   "not be able to work properly.\n"
136                                   "Please reconfigure again if needed."));
137         else
138
139                 Alert::information(_("System reconfigured"),
140                            _("The system has been reconfigured.\n"
141                              "You need to restart LyX to make use of any\n"
142                              "updated document class specifications."));
143 }
144
145
146 bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
147 {
148         // Try to fix cursor in case it is broken.
149         cursor.fixIfBroken();
150
151         // This is, of course, a mess. Better create a new doc iterator and use
152         // this in Inset::getStatus. This might require an additional
153         // BufferView * arg, though (which should be avoided)
154         //Cursor safe = *this;
155         bool res = false;
156         for ( ; cursor.depth(); cursor.pop()) {
157                 //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
158                 LASSERT(cursor.idx() <= cursor.lastidx(), /**/);
159                 LASSERT(cursor.pit() <= cursor.lastpit(), /**/);
160                 LASSERT(cursor.pos() <= cursor.lastpos(), /**/);
161
162                 // The inset's getStatus() will return 'true' if it made
163                 // a definitive decision on whether it want to handle the
164                 // request or not. The result of this decision is put into
165                 // the 'status' parameter.
166                 if (cursor.inset().getStatus(cursor, cmd, status)) {
167                         res = true;
168                         break;
169                 }
170         }
171         return res;
172 }
173
174
175 /** Return the change status at cursor position, taking in account the
176  * status at each level of the document iterator (a table in a deleted
177  * footnote is deleted).
178  * When \param outer is true, the top slice is not looked at.
179  */
180 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
181 {
182         size_t const depth = dit.depth() - (outer ? 1 : 0);
183
184         for (size_t i = 0 ; i < depth ; ++i) {
185                 CursorSlice const & slice = dit[i];
186                 if (!slice.inset().inMathed()
187                     && slice.pos() < slice.paragraph().size()) {
188                         Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
189                         if (ch != Change::UNCHANGED)
190                                 return ch;
191                 }
192         }
193         return Change::UNCHANGED;
194 }
195
196 }
197
198
199 LyXFunc::LyXFunc()
200         : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
201 {
202 }
203
204
205 void LyXFunc::initKeySequences(KeyMap * kb)
206 {
207         keyseq = KeySequence(kb, kb);
208         cancel_meta_seq = KeySequence(kb, kb);
209 }
210
211
212 void LyXFunc::setLyXView(LyXView * lv)
213 {
214         if (lyx_view_ && lyx_view_->currentBufferView() && lyx_view_ != lv)
215                 // save current selection to the selection buffer to allow
216                 // middle-button paste in another window
217                 cap::saveSelection(lyx_view_->currentBufferView()->cursor());
218         lyx_view_ = lv;
219 }
220
221
222 void LyXFunc::handleKeyFunc(FuncCode action)
223 {
224         char_type c = encoded_last_key;
225
226         if (keyseq.length())
227                 c = 0;
228
229         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
230         BufferView * bv = lyx_view_->currentBufferView();
231         bv->getIntl().getTransManager().deadkey(
232                 c, get_accent(action).accent, bv->cursor().innerText(),
233                 bv->cursor());
234         // Need to clear, in case the minibuffer calls these
235         // actions
236         keyseq.clear();
237         // copied verbatim from do_accent_char
238         bv->cursor().resetAnchor();
239         bv->processUpdateFlags(Update::FitCursor);
240 }
241
242 //FIXME: bookmark handling is a frontend issue. This code should be transferred
243 // to GuiView and be GuiView and be window dependent.
244 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
245 {
246         LASSERT(lyx_view_, /**/);
247         if (!theSession().bookmarks().isValid(idx))
248                 return;
249         BookmarksSection::Bookmark const & bm = theSession().bookmarks().bookmark(idx);
250         LASSERT(!bm.filename.empty(), /**/);
251         string const file = bm.filename.absFilename();
252         // if the file is not opened, open it.
253         if (!theBufferList().exists(bm.filename)) {
254                 if (openFile)
255                         dispatch(FuncRequest(LFUN_FILE_OPEN, file));
256                 else
257                         return;
258         }
259         // open may fail, so we need to test it again
260         if (!theBufferList().exists(bm.filename))
261                 return;
262
263         // bm can be changed when saving
264         BookmarksSection::Bookmark tmp = bm;
265
266         // Special case idx == 0 used for back-from-back jump navigation
267         if (idx == 0)
268                 dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
269
270         // if the current buffer is not that one, switch to it.
271         if (!lyx_view_->documentBufferView()
272                 || lyx_view_->documentBufferView()->buffer().fileName() != tmp.filename) {
273                 if (!switchToBuffer)
274                         return;
275                 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
276         }
277
278         // moveToPosition try paragraph id first and then paragraph (pit, pos).
279         if (!lyx_view_->documentBufferView()->moveToPosition(
280                 tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos))
281                 return;
282
283         // bm changed
284         if (idx == 0)
285                 return;
286
287         // Cursor jump succeeded!
288         Cursor const & cur = lyx_view_->documentBufferView()->cursor();
289         pit_type new_pit = cur.pit();
290         pos_type new_pos = cur.pos();
291         int new_id = cur.paragraph().id();
292
293         // if bottom_pit, bottom_pos or top_id has been changed, update bookmark
294         // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
295         if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos 
296                 || bm.top_id != new_id) {
297                 const_cast<BookmarksSection::Bookmark &>(bm).updatePos(
298                         new_pit, new_pos, new_id);
299         }
300 }
301
302
303 void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
304 {
305         LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
306
307         // Do nothing if we have nothing (JMarc)
308         if (!keysym.isOK()) {
309                 LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
310                 lyx_view_->restartCursor();
311                 return;
312         }
313
314         if (keysym.isModifier()) {
315                 LYXERR(Debug::KEY, "isModifier true");
316                 if (lyx_view_)
317                         lyx_view_->restartCursor();
318                 return;
319         }
320
321         //Encoding const * encoding = lyx_view_->documentBufferView()->cursor().getEncoding();
322         //encoded_last_key = keysym.getISOEncoded(encoding ? encoding->name() : "");
323         // FIXME: encoded_last_key shadows the member variable of the same
324         // name. Is that intended?
325         char_type encoded_last_key = keysym.getUCSEncoded();
326
327         // Do a one-deep top-level lookup for
328         // cancel and meta-fake keys. RVDK_PATCH_5
329         cancel_meta_seq.reset();
330
331         FuncRequest func = cancel_meta_seq.addkey(keysym, state);
332         LYXERR(Debug::KEY, "action first set to [" << func.action << ']');
333
334         // When not cancel or meta-fake, do the normal lookup.
335         // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
336         // Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5.
337         if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) {
338                 // remove Caps Lock and Mod2 as a modifiers
339                 func = keyseq.addkey(keysym, (state | meta_fake_bit));
340                 LYXERR(Debug::KEY, "action now set to [" << func.action << ']');
341         }
342
343         // Dont remove this unless you know what you are doing.
344         meta_fake_bit = NoModifier;
345
346         // Can this happen now ?
347         if (func.action == LFUN_NOACTION)
348                 func = FuncRequest(LFUN_COMMAND_PREFIX);
349
350         LYXERR(Debug::KEY, " Key [action=" << func.action << "]["
351                 << keyseq.print(KeySequence::Portable) << ']');
352
353         // already here we know if it any point in going further
354         // why not return already here if action == -1 and
355         // num_bytes == 0? (Lgb)
356
357         if (keyseq.length() > 1)
358                 lyx_view_->message(keyseq.print(KeySequence::ForGui));
359
360
361         // Maybe user can only reach the key via holding down shift.
362         // Let's see. But only if shift is the only modifier
363         if (func.action == LFUN_UNKNOWN_ACTION && state == ShiftModifier) {
364                 LYXERR(Debug::KEY, "Trying without shift");
365                 func = keyseq.addkey(keysym, NoModifier);
366                 LYXERR(Debug::KEY, "Action now " << func.action);
367         }
368
369         if (func.action == LFUN_UNKNOWN_ACTION) {
370                 // Hmm, we didn't match any of the keysequences. See
371                 // if it's normal insertable text not already covered
372                 // by a binding
373                 if (keysym.isText() && keyseq.length() == 1) {
374                         LYXERR(Debug::KEY, "isText() is true, inserting.");
375                         func = FuncRequest(LFUN_SELF_INSERT,
376                                            FuncRequest::KEYBOARD);
377                 } else {
378                         LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
379                         lyx_view_->message(_("Unknown function."));
380                         lyx_view_->restartCursor();
381                         return;
382                 }
383         }
384
385         if (func.action == LFUN_SELF_INSERT) {
386                 if (encoded_last_key != 0) {
387                         docstring const arg(1, encoded_last_key);
388                         dispatch(FuncRequest(LFUN_SELF_INSERT, arg,
389                                              FuncRequest::KEYBOARD));
390                         LYXERR(Debug::KEY, "SelfInsert arg[`" << to_utf8(arg) << "']");
391                 }
392         } else {
393                 dispatch(func);
394                 if (!lyx_view_)
395                         return;
396         }
397 }
398
399
400 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
401 {
402         //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
403         FuncStatus flag;
404
405         /* In LyX/Mac, when a dialog is open, the menus of the
406            application can still be accessed without giving focus to
407            the main window. In this case, we want to disable the menu
408            entries that are buffer or view-related.
409
410            If this code is moved somewhere else (like in
411            GuiView::getStatus), then several functions will not be
412            handled correctly.
413         */
414         frontend::LyXView * lv = 0;
415         Buffer * buf = 0;
416         if (lyx_view_ 
417             && (cmd.origin != FuncRequest::MENU || lyx_view_->hasFocus())) {
418                 lv = lyx_view_;
419                 if (lyx_view_->documentBufferView())
420                         buf = &lyx_view_->documentBufferView()->buffer();
421         }
422
423         if (cmd.action == LFUN_NOACTION) {
424                 flag.message(from_utf8(N_("Nothing to do")));
425                 flag.setEnabled(false);
426                 return flag;
427         }
428
429         switch (cmd.action) {
430         case LFUN_UNKNOWN_ACTION:
431                 flag.unknown(true);
432                 flag.setEnabled(false);
433                 break;
434
435         default:
436                 break;
437         }
438
439         if (flag.unknown()) {
440                 flag.message(from_utf8(N_("Unknown action")));
441                 return flag;
442         }
443
444         if (!flag.enabled()) {
445                 if (flag.message().empty())
446                         flag.message(from_utf8(N_("Command disabled")));
447                 return flag;
448         }
449
450         // Check whether we need a buffer
451         if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
452                 // no, exit directly
453                 flag.message(from_utf8(N_("Command not allowed with"
454                                     "out any document open")));
455                 flag.setEnabled(false);
456                 return flag;
457         }
458
459         // I would really like to avoid having this switch and rather try to
460         // encode this in the function itself.
461         // -- And I'd rather let an inset decide which LFUNs it is willing
462         // to handle (Andre')
463         bool enable = true;
464         switch (cmd.action) {
465
466         case LFUN_BUFFER_TOGGLE_READ_ONLY:
467                 flag.setOnOff(buf->isReadonly());
468                 break;
469
470         case LFUN_BUFFER_CHKTEX:
471                 enable = buf->isLatex() && !lyxrc.chktex_command.empty();
472                 break;
473
474         case LFUN_BUILD_PROGRAM:
475                 enable = buf->isExportable("program");
476                 break;
477
478         case LFUN_CITATION_INSERT: {
479                 FuncRequest fr(LFUN_INSET_INSERT, "citation");
480                 enable = getStatus(fr).enabled();
481                 break;
482         }
483         
484         // This could be used for the no-GUI version. The GUI version is handled in
485         // LyXView::getStatus(). See above.
486         /*
487         case LFUN_BUFFER_WRITE:
488         case LFUN_BUFFER_WRITE_AS: {
489                 Buffer * b = theBufferList().getBuffer(FileName(cmd.getArg(0)));
490                 enable = b && (b->isUnnamed() || !b->isClean());
491                 break;
492         }
493         */
494
495         case LFUN_BUFFER_WRITE_ALL: {
496                 // We enable the command only if there are some modified buffers
497                 Buffer * first = theBufferList().first();
498                 enable = false;
499                 if (!first)
500                         break;
501                 Buffer * b = first;
502                 // We cannot use a for loop as the buffer list is a cycle.
503                 do {
504                         if (!b->isClean()) {
505                                 enable = true;
506                                 break;
507                         }
508                         b = theBufferList().next(b);
509                 } while (b != first); 
510                 break;
511         }
512
513         case LFUN_BOOKMARK_GOTO: {
514                 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
515                 enable = theSession().bookmarks().isValid(num);
516                 break;
517         }
518
519         case LFUN_BOOKMARK_CLEAR:
520                 enable = theSession().bookmarks().hasValid();
521                 break;
522
523         // this one is difficult to get right. As a half-baked
524         // solution, we consider only the first action of the sequence
525         case LFUN_COMMAND_SEQUENCE: {
526                 // argument contains ';'-terminated commands
527                 string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
528                 FuncRequest func(lyxaction.lookupFunc(firstcmd));
529                 func.origin = cmd.origin;
530                 flag = getStatus(func);
531                 break;
532         }
533
534         // we want to check if at least one of these is enabled
535         case LFUN_COMMAND_ALTERNATIVES: {
536                 // argument contains ';'-terminated commands
537                 string arg = to_utf8(cmd.argument());
538                 while (!arg.empty()) {
539                         string first;
540                         arg = split(arg, first, ';');
541                         FuncRequest func(lyxaction.lookupFunc(first));
542                         func.origin = cmd.origin;
543                         flag = getStatus(func);
544                         // if this one is enabled, the whole thing is
545                         if (flag.enabled())
546                                 break;
547                 }
548                 break;
549         }
550
551         case LFUN_CALL: {
552                 FuncRequest func;
553                 string name = to_utf8(cmd.argument());
554                 if (theTopLevelCmdDef().lock(name, func)) {
555                         func.origin = cmd.origin;
556                         flag = getStatus(func);
557                         theTopLevelCmdDef().release(name);
558                 } else {
559                         // catch recursion or unknown command
560                         // definition. all operations until the
561                         // recursion or unknown command definition
562                         // occurs are performed, so set the state to
563                         // enabled
564                         enable = true;
565                 }
566                 break;
567         }
568
569         case LFUN_MASTER_BUFFER_UPDATE:
570         case LFUN_MASTER_BUFFER_VIEW: 
571                 if (!buf->parent()) {
572                         enable = false;
573                         break;
574                 }
575         case LFUN_BUFFER_UPDATE:
576         case LFUN_BUFFER_VIEW: {
577                 string format = to_utf8(cmd.argument());
578                 if (cmd.argument().empty())
579                         format = buf->getDefaultOutputFormat();
580                 typedef vector<Format const *> Formats;
581                 Formats formats;
582                 formats = buf->exportableFormats(true);
583                 Formats::const_iterator fit = formats.begin();
584                 Formats::const_iterator end = formats.end();
585                 enable = false;
586                 for (; fit != end ; ++fit) {
587                         if ((*fit)->name() == format)
588                                 enable = true;
589                 }
590                 break;
591         }
592
593         case LFUN_COMMAND_PREFIX:
594         case LFUN_COMMAND_EXECUTE:
595         case LFUN_CANCEL:
596         case LFUN_META_PREFIX:
597         case LFUN_BUFFER_CLOSE:
598         case LFUN_BUFFER_IMPORT:
599         case LFUN_BUFFER_AUTO_SAVE:
600         case LFUN_RECONFIGURE:
601         case LFUN_HELP_OPEN:
602         case LFUN_DROP_LAYOUTS_CHOICE:
603         case LFUN_SERVER_GET_FILENAME:
604         case LFUN_SERVER_NOTIFY:
605         case LFUN_SERVER_GOTO_FILE_ROW:
606         case LFUN_BUFFER_CHILD_OPEN:
607         case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
608         case LFUN_KEYMAP_OFF:
609         case LFUN_KEYMAP_PRIMARY:
610         case LFUN_KEYMAP_SECONDARY:
611         case LFUN_KEYMAP_TOGGLE:
612         case LFUN_REPEAT:
613         case LFUN_BUFFER_EXPORT_CUSTOM:
614         case LFUN_PREFERENCES_SAVE:
615         case LFUN_MESSAGE:
616         case LFUN_INSET_EDIT:
617         case LFUN_BUFFER_LANGUAGE:
618         case LFUN_TEXTCLASS_APPLY:
619         case LFUN_TEXTCLASS_LOAD:
620         case LFUN_BUFFER_SAVE_AS_DEFAULT:
621         case LFUN_BUFFER_PARAMS_APPLY:
622         case LFUN_LAYOUT_MODULES_CLEAR:
623         case LFUN_LAYOUT_MODULE_ADD:
624         case LFUN_LAYOUT_RELOAD:
625         case LFUN_LYXRC_APPLY:
626                 // these are handled in our dispatch()
627                 break;
628
629         default:
630                 if (!theApp()) {
631                         enable = false;
632                         break;
633                 }
634                 if (theApp()->getStatus(cmd, flag))
635                         break;
636
637                 // Does the view know something?
638                 if (!lv) {
639                         enable = false;
640                         break;
641                 }
642                 if (lv->getStatus(cmd, flag))
643                         break;
644
645                 BufferView * bv = lv->currentBufferView();
646                 // If we do not have a BufferView, then other functions are disabled
647                 if (!bv) {
648                         enable = false;
649                         break;
650                 }
651                 // Is this a function that acts on inset at point?
652                 Inset * inset = bv->cursor().nextInset();
653                 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
654                     && inset && inset->getStatus(bv->cursor(), cmd, flag))
655                         break;
656
657                 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
658                 if (!decided)
659                         // try the BufferView
660                         decided = bv->getStatus(cmd, flag);
661                 if (!decided)
662                         // try the Buffer
663                         bv->buffer().getStatus(cmd, flag);
664         }
665
666         if (!enable)
667                 flag.setEnabled(false);
668
669         // Can we use a readonly buffer?
670         if (buf && buf->isReadonly()
671             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
672             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
673                 flag.message(from_utf8(N_("Document is read-only")));
674                 flag.setEnabled(false);
675         }
676
677         // Are we in a DELETED change-tracking region?
678         if (lyx_view_ && lyx_view_->documentBufferView()
679                 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
680                     == Change::DELETED)
681             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
682             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
683                 flag.message(from_utf8(N_("This portion of the document is deleted.")));
684                 flag.setEnabled(false);
685         }
686
687         // the default error message if we disable the command
688         if (!flag.enabled() && flag.message().empty())
689                 flag.message(from_utf8(N_("Command disabled")));
690
691         return flag;
692 }
693
694
695 namespace {
696
697 bool loadLayoutFile(string const & name, string const & buf_path)
698 {
699         if (!LayoutFileList::get().haveClass(name)) {
700                 lyxerr << "Document class \"" << name
701                        << "\" does not exist."
702                        << endl;
703                 return false;
704         }
705
706         LayoutFile & tc = LayoutFileList::get()[name];
707         if (!tc.load(buf_path)) {
708                 docstring s = bformat(_("The document class %1$s "
709                                    "could not be loaded."), from_utf8(name));
710                 Alert::error(_("Could not load class"), s);
711                 return false;
712         }
713         return true;
714 }
715
716
717 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
718
719 } //namespace anon
720
721
722 void LyXFunc::dispatch(FuncRequest const & cmd)
723 {
724         string const argument = to_utf8(cmd.argument());
725         FuncCode const action = cmd.action;
726
727         LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
728         //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
729
730         // we have not done anything wrong yet.
731         errorstat = false;
732         dispatch_buffer.erase();
733
734         // redraw the screen at the end (first of the two drawing steps).
735         //This is done unless explicitely requested otherwise
736         Update::flags updateFlags = Update::FitCursor;
737
738         FuncStatus const flag = getStatus(cmd);
739         if (!flag.enabled()) {
740                 // We cannot use this function here
741                 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
742                        << lyxaction.getActionName(action)
743                        << " [" << action << "] is disabled at this location");
744                 setErrorMessage(flag.message());
745                 if (lyx_view_)
746                         lyx_view_->restartCursor();
747         } else {
748                 Buffer * buffer = 0;
749                 if (lyx_view_ && lyx_view_->currentBufferView())
750                         buffer = &lyx_view_->currentBufferView()->buffer();
751                 switch (action) {
752
753                 case LFUN_COMMAND_PREFIX:
754                         LASSERT(lyx_view_, /**/);
755                         lyx_view_->message(keyseq.printOptions(true));
756                         break;
757
758                 case LFUN_CANCEL:
759                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
760                         keyseq.reset();
761                         meta_fake_bit = NoModifier;
762                         if (buffer)
763                                 // cancel any selection
764                                 dispatch(FuncRequest(LFUN_MARK_OFF));
765                         setMessage(from_ascii(N_("Cancel")));
766                         break;
767
768                 case LFUN_META_PREFIX:
769                         meta_fake_bit = AltModifier;
770                         setMessage(keyseq.print(KeySequence::ForGui));
771                         break;
772
773                 case LFUN_BUFFER_TOGGLE_READ_ONLY: {
774                         LASSERT(lyx_view_ && lyx_view_->currentBufferView() && buffer, /**/);
775                         if (buffer->lyxvc().inUse())
776                                 buffer->lyxvc().toggleReadOnly();
777                         else
778                                 buffer->setReadonly(!buffer->isReadonly());
779                         break;
780                 }
781
782                 // --- Menus -----------------------------------------------
783                 case LFUN_BUFFER_CLOSE:
784                         lyx_view_->closeBuffer();
785                         buffer = 0;
786                         updateFlags = Update::None;
787                         break;
788
789                 case LFUN_BUFFER_CLOSE_ALL:
790                         lyx_view_->closeBufferAll();
791                         buffer = 0;
792                         updateFlags = Update::None;
793                         break;
794
795                 case LFUN_BUFFER_UPDATE: {
796                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
797                         Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
798                         string format = argument;
799                         if (argument.empty())
800                                 format = doc_buffer.getDefaultOutputFormat();
801                         doc_buffer.doExport(format, true);
802                         break;
803                 }
804
805                 case LFUN_BUFFER_VIEW: {
806                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
807                         Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
808                         string format = argument;
809                         if (argument.empty())
810                                 format = doc_buffer.getDefaultOutputFormat();
811                         doc_buffer.preview(format);
812                         break;
813                 }
814
815                 case LFUN_MASTER_BUFFER_UPDATE: {
816                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
817                         Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
818                         string format = argument;
819                         if (argument.empty())
820                                 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
821                         doc_buffer.masterBuffer()->doExport(format, true);
822                         break;
823                 }
824
825                 case LFUN_MASTER_BUFFER_VIEW: {
826                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
827                         Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
828                         string format = argument;
829                         if (argument.empty())
830                                 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
831                         doc_buffer.masterBuffer()->preview(format);
832                         break;
833                 }
834
835                 case LFUN_BUILD_PROGRAM:
836                         LASSERT(lyx_view_ && buffer, /**/);
837                         buffer->doExport("program", true);
838                         break;
839
840                 case LFUN_BUFFER_CHKTEX:
841                         LASSERT(lyx_view_ && buffer, /**/);
842                         buffer->runChktex();
843                         break;
844
845                 case LFUN_BUFFER_EXPORT:
846                         LASSERT(lyx_view_ && buffer, /**/);
847                         if (argument == "custom")
848                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
849                         else
850                                 buffer->doExport(argument, false);
851                         break;
852
853                 case LFUN_BUFFER_EXPORT_CUSTOM: {
854                         LASSERT(lyx_view_ && buffer, /**/);
855                         string format_name;
856                         string command = split(argument, format_name, ' ');
857                         Format const * format = formats.getFormat(format_name);
858                         if (!format) {
859                                 lyxerr << "Format \"" << format_name
860                                        << "\" not recognized!"
861                                        << endl;
862                                 break;
863                         }
864
865                         // The name of the file created by the conversion process
866                         string filename;
867
868                         // Output to filename
869                         if (format->name() == "lyx") {
870                                 string const latexname = buffer->latexName(false);
871                                 filename = changeExtension(latexname,
872                                                            format->extension());
873                                 filename = addName(buffer->temppath(), filename);
874
875                                 if (!buffer->writeFile(FileName(filename)))
876                                         break;
877
878                         } else {
879                                 buffer->doExport(format_name, true, filename);
880                         }
881
882                         // Substitute $$FName for filename
883                         if (!contains(command, "$$FName"))
884                                 command = "( " + command + " ) < $$FName";
885                         command = subst(command, "$$FName", filename);
886
887                         // Execute the command in the background
888                         Systemcall call;
889                         call.startscript(Systemcall::DontWait, command);
890                         break;
891                 }
892
893                 // FIXME: There is need for a command-line import.
894                 /*
895                 case LFUN_BUFFER_IMPORT:
896                         doImport(argument);
897                         break;
898                 */
899
900                 case LFUN_BUFFER_AUTO_SAVE:
901                         buffer->autoSave();
902                         break;
903
904                 case LFUN_RECONFIGURE:
905                         // argument is any additional parameter to the configure.py command
906                         reconfigure(lyx_view_, argument);
907                         break;
908
909                 case LFUN_HELP_OPEN: {
910                         if (lyx_view_ == 0)
911                                 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
912                         string const arg = argument;
913                         if (arg.empty()) {
914                                 setErrorMessage(from_utf8(N_("Missing argument")));
915                                 break;
916                         }
917                         FileName fname = i18nLibFileSearch("doc", arg, "lyx");
918                         if (fname.empty()) 
919                                 fname = i18nLibFileSearch("examples", arg, "lyx");
920
921                         if (fname.empty()) {
922                                 lyxerr << "LyX: unable to find documentation file `"
923                                                          << arg << "'. Bad installation?" << endl;
924                                 break;
925                         }
926                         lyx_view_->message(bformat(_("Opening help file %1$s..."),
927                                 makeDisplayPath(fname.absFilename())));
928                         Buffer * buf = lyx_view_->loadDocument(fname, false);
929                         if (buf) {
930                                 buf->updateLabels();
931                                 lyx_view_->setBuffer(buf);
932                                 buf->errors("Parse");
933                         }
934                         updateFlags = Update::None;
935                         break;
936                 }
937
938                 // --- lyxserver commands ----------------------------
939                 case LFUN_SERVER_GET_FILENAME:
940                         LASSERT(lyx_view_ && buffer, /**/);
941                         setMessage(from_utf8(buffer->absFileName()));
942                         LYXERR(Debug::INFO, "FNAME["
943                                 << buffer->absFileName() << ']');
944                         break;
945
946                 case LFUN_SERVER_NOTIFY:
947                         dispatch_buffer = keyseq.print(KeySequence::Portable);
948                         theServer().notifyClient(to_utf8(dispatch_buffer));
949                         break;
950
951                 case LFUN_SERVER_GOTO_FILE_ROW: {
952                         LASSERT(lyx_view_, /**/);
953                         string file_name;
954                         int row;
955                         istringstream is(argument);
956                         is >> file_name >> row;
957                         file_name = os::internal_path(file_name);
958                         Buffer * buf = 0;
959                         bool loaded = false;
960                         string const abstmp = package().temp_dir().absFilename();
961                         string const realtmp = package().temp_dir().realPath();
962                         // We have to use os::path_prefix_is() here, instead of
963                         // simply prefixIs(), because the file name comes from
964                         // an external application and may need case adjustment.
965                         if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
966                             || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
967                                 // Needed by inverse dvi search. If it is a file
968                                 // in tmpdir, call the apropriated function.
969                                 // If tmpdir is a symlink, we may have the real
970                                 // path passed back, so we correct for that.
971                                 if (!prefixIs(file_name, abstmp))
972                                         file_name = subst(file_name, realtmp, abstmp);
973                                 buf = theBufferList().getBufferFromTmp(file_name);
974                         } else {
975                                 // Must replace extension of the file to be .lyx
976                                 // and get full path
977                                 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
978                                 // Either change buffer or load the file
979                                 if (theBufferList().exists(s))
980                                         buf = theBufferList().getBuffer(s);
981                                 else if (s.exists()) {
982                                         buf = lyx_view_->loadDocument(s);
983                                         loaded = true;
984                                 } else
985                                         lyx_view_->message(bformat(
986                                                 _("File does not exist: %1$s"),
987                                                 makeDisplayPath(file_name)));
988                         }
989
990                         if (!buf) {
991                                 updateFlags = Update::None;
992                                 break;
993                         }
994
995                         buf->updateLabels();
996                         lyx_view_->setBuffer(buf);
997                         lyx_view_->documentBufferView()->setCursorFromRow(row);
998                         if (loaded)
999                                 buf->errors("Parse");
1000                         updateFlags = Update::FitCursor;
1001                         break;
1002                 }
1003
1004
1005                 case LFUN_DIALOG_SHOW_NEW_INSET: {
1006                         LASSERT(lyx_view_, /**/);
1007                         string const name = cmd.getArg(0);
1008                         InsetCode code = insetCode(name);
1009                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1010                         bool insetCodeOK = true;
1011                         switch (code) {
1012                         case BIBITEM_CODE:
1013                         case BIBTEX_CODE:
1014                         case INDEX_CODE:
1015                         case LABEL_CODE:
1016                         case NOMENCL_CODE:
1017                         case NOMENCL_PRINT_CODE:
1018                         case REF_CODE:
1019                         case TOC_CODE:
1020                         case HYPERLINK_CODE: {
1021                                 InsetCommandParams p(code);
1022                                 data = InsetCommand::params2string(name, p);
1023                                 break;
1024                         }
1025                         case INCLUDE_CODE: {
1026                                 // data is the include type: one of "include",
1027                                 // "input", "verbatiminput" or "verbatiminput*"
1028                                 if (data.empty())
1029                                         // default type is requested
1030                                         data = "include";
1031                                 InsetCommandParams p(INCLUDE_CODE, data);
1032                                 data = InsetCommand::params2string("include", p);
1033                                 break;
1034                         }
1035                         case BOX_CODE: {
1036                                 // \c data == "Boxed" || "Frameless" etc
1037                                 InsetBoxParams p(data);
1038                                 data = InsetBox::params2string(p);
1039                                 break;
1040                         }
1041                         case BRANCH_CODE: {
1042                                 InsetBranchParams p;
1043                                 data = InsetBranch::params2string(p);
1044                                 break;
1045                         }
1046                         case CITE_CODE: {
1047                                 InsetCommandParams p(CITE_CODE);
1048                                 data = InsetCommand::params2string(name, p);
1049                                 break;
1050                         }
1051                         case ERT_CODE: {
1052                                 data = InsetERT::params2string(InsetCollapsable::Open);
1053                                 break;
1054                         }
1055                         case EXTERNAL_CODE: {
1056                                 InsetExternalParams p;
1057                                 data = InsetExternal::params2string(p, *buffer);
1058                                 break;
1059                         }
1060                         case FLOAT_CODE:  {
1061                                 InsetFloatParams p;
1062                                 data = InsetFloat::params2string(p);
1063                                 break;
1064                         }
1065                         case LISTINGS_CODE: {
1066                                 InsetListingsParams p;
1067                                 data = InsetListings::params2string(p);
1068                                 break;
1069                         }
1070                         case GRAPHICS_CODE: {
1071                                 InsetGraphicsParams p;
1072                                 data = InsetGraphics::params2string(p, *buffer);
1073                                 break;
1074                         }
1075                         case NOTE_CODE: {
1076                                 InsetNoteParams p;
1077                                 data = InsetNote::params2string(p);
1078                                 break;
1079                         }
1080                         case PHANTOM_CODE: {
1081                                 InsetPhantomParams p;
1082                                 data = InsetPhantom::params2string(p);
1083                                 break;
1084                         }
1085                         case SPACE_CODE: {
1086                                 InsetSpaceParams p;
1087                                 data = InsetSpace::params2string(p);
1088                                 break;
1089                         }
1090                         case VSPACE_CODE: {
1091                                 VSpace space;
1092                                 data = InsetVSpace::params2string(space);
1093                                 break;
1094                         }
1095                         case WRAP_CODE: {
1096                                 InsetWrapParams p;
1097                                 data = InsetWrap::params2string(p);
1098                                 break;
1099                         }
1100                         default:
1101                                 lyxerr << "Inset type '" << name << 
1102                                         "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" <<  endl;
1103                                 insetCodeOK = false;
1104                                 break;
1105                         } // end switch(code)
1106                         if (insetCodeOK)
1107                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
1108                         break;
1109                 }
1110
1111                 case LFUN_CITATION_INSERT: {
1112                         LASSERT(lyx_view_, /**/);
1113                         if (!argument.empty()) {
1114                                 // we can have one optional argument, delimited by '|'
1115                                 // citation-insert <key>|<text_before>
1116                                 // this should be enhanced to also support text_after
1117                                 // and citation style
1118                                 string arg = argument;
1119                                 string opt1;
1120                                 if (contains(argument, "|")) {
1121                                         arg = token(argument, '|', 0);
1122                                         opt1 = token(argument, '|', 1);
1123                                 }
1124                                 InsetCommandParams icp(CITE_CODE);
1125                                 icp["key"] = from_utf8(arg);
1126                                 if (!opt1.empty())
1127                                         icp["before"] = from_utf8(opt1);
1128                                 string icstr = InsetCommand::params2string("citation", icp);
1129                                 FuncRequest fr(LFUN_INSET_INSERT, icstr);
1130                                 dispatch(fr);
1131                         } else
1132                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
1133                         break;
1134                 }
1135
1136                 case LFUN_BUFFER_CHILD_OPEN: {
1137                         LASSERT(lyx_view_ && buffer, /**/);
1138                         FileName filename = makeAbsPath(argument, buffer->filePath());
1139                         lyx_view_->documentBufferView()->saveBookmark(false);
1140                         Buffer * child = 0;
1141                         bool parsed = false;
1142                         if (theBufferList().exists(filename)) {
1143                                 child = theBufferList().getBuffer(filename);
1144                         } else {
1145                                 setMessage(bformat(_("Opening child document %1$s..."),
1146                                         makeDisplayPath(filename.absFilename())));
1147                                 child = lyx_view_->loadDocument(filename, false);
1148                                 parsed = true;
1149                         }
1150                         if (child) {
1151                                 // Set the parent name of the child document.
1152                                 // This makes insertion of citations and references in the child work,
1153                                 // when the target is in the parent or another child document.
1154                                 child->setParent(buffer);
1155                                 child->masterBuffer()->updateLabels();
1156                                 lyx_view_->setBuffer(child);
1157                                 if (parsed)
1158                                         child->errors("Parse");
1159                         }
1160
1161                         // If a screen update is required (in case where auto_open is false), 
1162                         // setBuffer() would have taken care of it already. Otherwise we shall 
1163                         // reset the update flag because it can cause a circular problem.
1164                         // See bug 3970.
1165                         updateFlags = Update::None;
1166                         break;
1167                 }
1168
1169                 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
1170                         LASSERT(lyx_view_, /**/);
1171                         lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1172                         break;
1173
1174                 case LFUN_KEYMAP_OFF:
1175                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1176                         lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
1177                         break;
1178
1179                 case LFUN_KEYMAP_PRIMARY:
1180                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1181                         lyx_view_->currentBufferView()->getIntl().keyMapPrim();
1182                         break;
1183
1184                 case LFUN_KEYMAP_SECONDARY:
1185                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1186                         lyx_view_->currentBufferView()->getIntl().keyMapSec();
1187                         break;
1188
1189                 case LFUN_KEYMAP_TOGGLE:
1190                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1191                         lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
1192                         break;
1193
1194                 case LFUN_REPEAT: {
1195                         // repeat command
1196                         string countstr;
1197                         string rest = split(argument, countstr, ' ');
1198                         istringstream is(countstr);
1199                         int count = 0;
1200                         is >> count;
1201                         //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1202                         for (int i = 0; i < count; ++i)
1203                                 dispatch(lyxaction.lookupFunc(rest));
1204                         break;
1205                 }
1206
1207                 case LFUN_COMMAND_SEQUENCE: {
1208                         // argument contains ';'-terminated commands
1209                         string arg = argument;
1210                         if (theBufferList().isLoaded(buffer))
1211                                 buffer->undo().beginUndoGroup();
1212                         while (!arg.empty()) {
1213                                 string first;
1214                                 arg = split(arg, first, ';');
1215                                 FuncRequest func(lyxaction.lookupFunc(first));
1216                                 func.origin = cmd.origin;
1217                                 dispatch(func);
1218                         }
1219                         if (theBufferList().isLoaded(buffer))
1220                                 buffer->undo().endUndoGroup();
1221                         break;
1222                 }
1223
1224                 case LFUN_COMMAND_ALTERNATIVES: {
1225                         // argument contains ';'-terminated commands
1226                         string arg = argument;
1227                         while (!arg.empty()) {
1228                                 string first;
1229                                 arg = split(arg, first, ';');
1230                                 FuncRequest func(lyxaction.lookupFunc(first));
1231                                 func.origin = cmd.origin;
1232                                 FuncStatus stat = getStatus(func);
1233                                 if (stat.enabled()) {
1234                                         dispatch(func);
1235                                         break;
1236                                 }
1237                         }
1238                         break;
1239                 }
1240
1241                 case LFUN_CALL: {
1242                         FuncRequest func;
1243                         if (theTopLevelCmdDef().lock(argument, func)) {
1244                                 func.origin = cmd.origin;
1245                                 dispatch(func);
1246                                 theTopLevelCmdDef().release(argument);
1247                         } else {
1248                                 if (func.action == LFUN_UNKNOWN_ACTION) {
1249                                         // unknown command definition
1250                                         lyxerr << "Warning: unknown command definition `"
1251                                                    << argument << "'"
1252                                                    << endl;
1253                                 } else {
1254                                         // recursion detected
1255                                         lyxerr << "Warning: Recursion in the command definition `"
1256                                                    << argument << "' detected"
1257                                                    << endl;
1258                                 }
1259                         }
1260                         break;
1261                 }
1262
1263                 case LFUN_PREFERENCES_SAVE: {
1264                         lyxrc.write(makeAbsPath("preferences",
1265                                                 package().user_support().absFilename()),
1266                                     false);
1267                         break;
1268                 }
1269
1270                 case LFUN_MESSAGE:
1271                         LASSERT(lyx_view_, /**/);
1272                         lyx_view_->message(from_utf8(argument));
1273                         break;
1274
1275                 case LFUN_BUFFER_LANGUAGE: {
1276                         LASSERT(lyx_view_, /**/);
1277                         Language const * oldL = buffer->params().language;
1278                         Language const * newL = languages.getLanguage(argument);
1279                         if (!newL || oldL == newL)
1280                                 break;
1281
1282                         if (oldL->rightToLeft() == newL->rightToLeft()
1283                             && !buffer->isMultiLingual())
1284                                 buffer->changeLanguage(oldL, newL);
1285                         break;
1286                 }
1287
1288                 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1289                         string const fname =
1290                                 addName(addPath(package().user_support().absFilename(), "templates/"),
1291                                         "defaults.lyx");
1292                         Buffer defaults(fname);
1293
1294                         istringstream ss(argument);
1295                         Lexer lex;
1296                         lex.setStream(ss);
1297                         int const unknown_tokens = defaults.readHeader(lex);
1298
1299                         if (unknown_tokens != 0) {
1300                                 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1301                                        << unknown_tokens << " unknown token"
1302                                        << (unknown_tokens == 1 ? "" : "s")
1303                                        << endl;
1304                         }
1305
1306                         if (defaults.writeFile(FileName(defaults.absFileName())))
1307                                 setMessage(bformat(_("Document defaults saved in %1$s"),
1308                                                    makeDisplayPath(fname)));
1309                         else
1310                                 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1311                         break;
1312                 }
1313
1314                 case LFUN_BUFFER_PARAMS_APPLY: {
1315                         LASSERT(lyx_view_, /**/);
1316                         
1317                         DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1318                         Cursor & cur = lyx_view_->documentBufferView()->cursor();
1319                         cur.recordUndoFullDocument();
1320                         
1321                         istringstream ss(argument);
1322                         Lexer lex;
1323                         lex.setStream(ss);
1324                         int const unknown_tokens = buffer->readHeader(lex);
1325
1326                         if (unknown_tokens != 0) {
1327                                 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1328                                                 << unknown_tokens << " unknown token"
1329                                                 << (unknown_tokens == 1 ? "" : "s")
1330                                                 << endl;
1331                         }
1332                         
1333                         updateLayout(oldClass, buffer);
1334                         
1335                         updateFlags = Update::Force | Update::FitCursor;
1336                         // We are most certainly here because of a change in the document
1337                         // It is then better to make sure that all dialogs are in sync with
1338                         // current document settings. LyXView::restartCursor() achieve this.
1339                         lyx_view_->restartCursor();
1340                         break;
1341                 }
1342                 
1343                 case LFUN_LAYOUT_MODULES_CLEAR: {
1344                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1345                         DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1346                         lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1347                         buffer->params().clearLayoutModules();
1348                         buffer->params().makeDocumentClass();
1349                         updateLayout(oldClass, buffer);
1350                         updateFlags = Update::Force | Update::FitCursor;
1351                         break;
1352                 }
1353                 
1354                 case LFUN_LAYOUT_MODULE_ADD: {
1355                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1356                         BufferParams const & params = buffer->params();
1357                         if (!params.moduleCanBeAdded(argument)) {
1358                                 LYXERR0("Module `" << argument << 
1359                                                 "' cannot be added due to failed requirements or "
1360                                                 "conflicts with installed modules.");
1361                                 break;
1362                         }
1363                         DocumentClass const * const oldClass = params.documentClassPtr();
1364                         lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1365                         buffer->params().addLayoutModule(argument);
1366                         buffer->params().makeDocumentClass();
1367                         updateLayout(oldClass, buffer);
1368                         updateFlags = Update::Force | Update::FitCursor;
1369                         break;
1370                 }
1371
1372                 case LFUN_TEXTCLASS_APPLY: {
1373                         LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1374
1375                         if (!loadLayoutFile(argument, buffer->temppath()) &&
1376                                 !loadLayoutFile(argument, buffer->filePath()))
1377                                 break;
1378
1379                         LayoutFile const * old_layout = buffer->params().baseClass();
1380                         LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1381
1382                         if (old_layout == new_layout)
1383                                 // nothing to do
1384                                 break;
1385
1386                         //Save the old, possibly modular, layout for use in conversion.
1387                         DocumentClass const * const oldDocClass =
1388                                 buffer->params().documentClassPtr();
1389                         lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1390                         buffer->params().setBaseClass(argument);
1391                         buffer->params().makeDocumentClass();
1392                         updateLayout(oldDocClass, buffer);
1393                         updateFlags = Update::Force | Update::FitCursor;
1394                         break;
1395                 }
1396                 
1397                 case LFUN_LAYOUT_RELOAD: {
1398                         LASSERT(lyx_view_, /**/);
1399                         DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1400                         LayoutFileIndex bc = buffer->params().baseClassID();
1401                         LayoutFileList::get().reset(bc);
1402                         buffer->params().setBaseClass(bc);
1403                         buffer->params().makeDocumentClass();
1404                         updateLayout(oldClass, buffer);
1405                         updateFlags = Update::Force | Update::FitCursor;
1406                         break;
1407                 }
1408
1409                 case LFUN_TEXTCLASS_LOAD:
1410                         loadLayoutFile(argument, buffer->temppath()) ||
1411                         loadLayoutFile(argument, buffer->filePath());
1412                         break;
1413
1414                 case LFUN_LYXRC_APPLY: {
1415                         // reset active key sequences, since the bindings
1416                         // are updated (bug 6064)
1417                         keyseq.reset();
1418                         LyXRC const lyxrc_orig = lyxrc;
1419
1420                         istringstream ss(argument);
1421                         bool const success = lyxrc.read(ss) == 0;
1422
1423                         if (!success) {
1424                                 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1425                                        << "Unable to read lyxrc data"
1426                                        << endl;
1427                                 break;
1428                         }
1429
1430                         actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1431
1432                         setSpellChecker();
1433
1434                         theApp()->resetGui();
1435
1436                         /// We force the redraw in any case because there might be
1437                         /// some screen font changes.
1438                         /// FIXME: only the current view will be updated. the Gui
1439                         /// class is able to furnish the list of views.
1440                         updateFlags = Update::Force;
1441                         break;
1442                 }
1443
1444                 case LFUN_BOOKMARK_GOTO:
1445                         // go to bookmark, open unopened file and switch to buffer if necessary
1446                         gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1447                         updateFlags = Update::FitCursor;
1448                         break;
1449
1450                 case LFUN_BOOKMARK_CLEAR:
1451                         theSession().bookmarks().clear();
1452                         break;
1453
1454                 default:
1455                         LASSERT(theApp(), /**/);
1456                         // Let the frontend dispatch its own actions.
1457                         if (theApp()->dispatch(cmd))
1458                                 // Nothing more to do.
1459                                 return;
1460
1461                         // Everything below is only for active lyx_view_
1462                         if (lyx_view_ == 0)
1463                                 break;
1464
1465                         // Start an undo group. This may be needed for
1466                         // some stuff like inset-apply on labels.
1467                         if (theBufferList().isLoaded(buffer))
1468                                 buffer->undo().beginUndoGroup();
1469                                 
1470                         // Let the current LyXView dispatch its own actions.
1471                         if (lyx_view_->dispatch(cmd)) {
1472                                 if (lyx_view_->currentBufferView()) {
1473                                         updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1474                                         if (theBufferList().isLoaded(buffer))
1475                                                 buffer->undo().endUndoGroup();
1476                                 }
1477                                 break;
1478                         }
1479
1480                         LASSERT(lyx_view_->currentBufferView(), /**/);
1481
1482                         // Let the current BufferView dispatch its own actions.
1483                         if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1484                                 // The BufferView took care of its own updates if needed.
1485                                 updateFlags = Update::None;
1486                                 if (theBufferList().isLoaded(buffer))
1487                                         buffer->undo().endUndoGroup();
1488                                 break;
1489                         }
1490
1491                         // OK, so try the Buffer itself
1492                         DispatchResult dr;
1493                         BufferView * bv = lyx_view_->currentBufferView();
1494                         bv->buffer().dispatch(cmd, dr);
1495                         if (dr.dispatched()) {
1496                                 updateFlags = dr.update();
1497                                 break;
1498                         }
1499
1500                         // Is this a function that acts on inset at point?
1501                         Inset * inset = bv->cursor().nextInset();
1502                         if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1503                             && inset) {
1504                                 bv->cursor().result().dispatched(true);
1505                                 bv->cursor().result().update(Update::FitCursor | Update::Force);
1506                                 FuncRequest tmpcmd = cmd;
1507                                 inset->dispatch(bv->cursor(), tmpcmd);
1508                                 if (bv->cursor().result().dispatched()) {
1509                                         updateFlags = bv->cursor().result().update();
1510                                         break;
1511                                 }
1512                         }
1513
1514                         // Let the current Cursor dispatch its own actions.
1515                         Cursor old = bv->cursor();
1516                         bv->cursor().getPos(cursorPosBeforeDispatchX_,
1517                                                 cursorPosBeforeDispatchY_);
1518                         bv->cursor().dispatch(cmd);
1519
1520                         // notify insets we just left
1521                         if (bv->cursor() != old) {
1522                                 old.fixIfBroken();
1523                                 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1524                                 if (badcursor)
1525                                         bv->cursor().fixIfBroken();
1526                         }
1527
1528                         if (theBufferList().isLoaded(buffer))
1529                                 buffer->undo().endUndoGroup();
1530
1531                         // update completion. We do it here and not in
1532                         // processKeySym to avoid another redraw just for a
1533                         // changed inline completion
1534                         if (cmd.origin == FuncRequest::KEYBOARD) {
1535                                 if (cmd.action == LFUN_SELF_INSERT
1536                                     || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1537                                         lyx_view_->updateCompletion(bv->cursor(), true, true);
1538                                 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1539                                         lyx_view_->updateCompletion(bv->cursor(), false, true);
1540                                 else
1541                                         lyx_view_->updateCompletion(bv->cursor(), false, false);
1542                         }
1543
1544                         updateFlags = bv->cursor().result().update();
1545                 }
1546
1547                 // if we executed a mutating lfun, mark the buffer as dirty
1548                 if (theBufferList().isLoaded(buffer) && flag.enabled()
1549                     && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1550                     && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1551                         buffer->markDirty();                    
1552
1553                 if (lyx_view_ && lyx_view_->currentBufferView()) {
1554                         // BufferView::update() updates the ViewMetricsInfo and
1555                         // also initializes the position cache for all insets in
1556                         // (at least partially) visible top-level paragraphs.
1557                         // We will redraw the screen only if needed.
1558                         lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1559
1560                         // Do we have a selection?
1561                         theSelection().haveSelection(
1562                                 lyx_view_->currentBufferView()->cursor().selection());
1563                         
1564                         // update gui
1565                         lyx_view_->restartCursor();
1566                 }
1567         }
1568         if (lyx_view_) {
1569                 // Some messages may already be translated, so we cannot use _()
1570                 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1571         }
1572 }
1573
1574
1575 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1576 {
1577         const bool verbose = (cmd.origin == FuncRequest::MENU
1578                               || cmd.origin == FuncRequest::TOOLBAR
1579                               || cmd.origin == FuncRequest::COMMANDBUFFER);
1580
1581         if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1582                 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1583                 if (!msg.empty())
1584                         lyx_view_->message(msg);
1585                 return;
1586         }
1587
1588         docstring dispatch_msg = msg;
1589         if (!dispatch_msg.empty())
1590                 dispatch_msg += ' ';
1591
1592         docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1593
1594         bool argsadded = false;
1595
1596         if (!cmd.argument().empty()) {
1597                 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1598                         comname += ' ' + cmd.argument();
1599                         argsadded = true;
1600                 }
1601         }
1602
1603         docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1604
1605         if (!shortcuts.empty())
1606                 comname += ": " + shortcuts;
1607         else if (!argsadded && !cmd.argument().empty())
1608                 comname += ' ' + cmd.argument();
1609
1610         if (!comname.empty()) {
1611                 comname = rtrim(comname);
1612                 dispatch_msg += '(' + rtrim(comname) + ')';
1613         }
1614
1615         LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1616         if (!dispatch_msg.empty())
1617                 lyx_view_->message(dispatch_msg);
1618 }
1619
1620
1621 // Each "lyx_view_" should have it's own message method. lyxview and
1622 // the minibuffer would use the minibuffer, but lyxserver would
1623 // send an ERROR signal to its client.  Alejandro 970603
1624 // This function is bit problematic when it comes to NLS, to make the
1625 // lyx servers client be language indepenent we must not translate
1626 // strings sent to this func.
1627 void LyXFunc::setErrorMessage(docstring const & m) const
1628 {
1629         dispatch_buffer = m;
1630         errorstat = true;
1631 }
1632
1633
1634 void LyXFunc::setMessage(docstring const & m) const
1635 {
1636         dispatch_buffer = m;
1637 }
1638
1639
1640 docstring LyXFunc::viewStatusMessage()
1641 {
1642         // When meta-fake key is pressed, show the key sequence so far + "M-".
1643         if (wasMetaKey())
1644                 return keyseq.print(KeySequence::ForGui) + "M-";
1645
1646         // Else, when a non-complete key sequence is pressed,
1647         // show the available options.
1648         if (keyseq.length() > 0 && !keyseq.deleted())
1649                 return keyseq.printOptions(true);
1650
1651         LASSERT(lyx_view_, /**/);
1652         if (!lyx_view_->currentBufferView())
1653                 return _("Welcome to LyX!");
1654
1655         return lyx_view_->currentBufferView()->cursor().currentState();
1656 }
1657
1658
1659 bool LyXFunc::wasMetaKey() const
1660 {
1661         return (meta_fake_bit != NoModifier);
1662 }
1663
1664
1665 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1666 {
1667         lyx_view_->message(_("Converting document to new document class..."));
1668         
1669         StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1670         ErrorList & el = buf->errorList("Class Switch");
1671         cap::switchBetweenClasses(
1672                         oldlayout, buf->params().documentClassPtr(),
1673                         static_cast<InsetText &>(buf->inset()), el);
1674
1675         lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1676
1677         buf->errors("Class Switch");
1678         buf->updateLabels();
1679 }
1680
1681
1682 namespace {
1683
1684 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1685 {
1686         // Why the switch you might ask. It is a trick to ensure that all
1687         // the elements in the LyXRCTags enum is handled. As you can see
1688         // there are no breaks at all. So it is just a huge fall-through.
1689         // The nice thing is that we will get a warning from the compiler
1690         // if we forget an element.
1691         LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1692         switch (tag) {
1693         case LyXRC::RC_ACCEPT_COMPOUND:
1694         case LyXRC::RC_ALT_LANG:
1695         case LyXRC::RC_PLAINTEXT_LINELEN:
1696         case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1697         case LyXRC::RC_AUTOCORRECTION_MATH:
1698         case LyXRC::RC_AUTOREGIONDELETE:
1699         case LyXRC::RC_AUTORESET_OPTIONS:
1700         case LyXRC::RC_AUTOSAVE:
1701         case LyXRC::RC_AUTO_NUMBER:
1702         case LyXRC::RC_BACKUPDIR_PATH:
1703         case LyXRC::RC_BIBTEX_ALTERNATIVES:
1704         case LyXRC::RC_BIBTEX_COMMAND:
1705         case LyXRC::RC_BINDFILE:
1706         case LyXRC::RC_CHECKLASTFILES:
1707         case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1708         case LyXRC::RC_COMPLETION_INLINE_DELAY:
1709         case LyXRC::RC_COMPLETION_INLINE_DOTS:
1710         case LyXRC::RC_COMPLETION_INLINE_MATH:
1711         case LyXRC::RC_COMPLETION_INLINE_TEXT:
1712         case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1713         case LyXRC::RC_COMPLETION_POPUP_DELAY:
1714         case LyXRC::RC_COMPLETION_POPUP_MATH:
1715         case LyXRC::RC_COMPLETION_POPUP_TEXT:
1716         case LyXRC::RC_USELASTFILEPOS:
1717         case LyXRC::RC_LOADSESSION:
1718         case LyXRC::RC_CHKTEX_COMMAND:
1719         case LyXRC::RC_CONVERTER:
1720         case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1721         case LyXRC::RC_COPIER:
1722         case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1723         case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1724         case LyXRC::RC_DATE_INSERT_FORMAT:
1725         case LyXRC::RC_DEFAULT_LANGUAGE:
1726         case LyXRC::RC_GUI_LANGUAGE:
1727         case LyXRC::RC_DEFAULT_PAPERSIZE:
1728         case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1729         case LyXRC::RC_DEFFILE:
1730         case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1731         case LyXRC::RC_DISPLAY_GRAPHICS:
1732         case LyXRC::RC_DOCUMENTPATH:
1733                 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1734                         FileName path(lyxrc_new.document_path);
1735                         if (path.exists() && path.isDirectory())
1736                                 package().document_dir() = FileName(lyxrc.document_path);
1737                 }
1738         case LyXRC::RC_EDITOR_ALTERNATIVES:
1739         case LyXRC::RC_ESC_CHARS:
1740         case LyXRC::RC_EXAMPLEPATH:
1741         case LyXRC::RC_FONT_ENCODING:
1742         case LyXRC::RC_FORMAT:
1743         case LyXRC::RC_GROUP_LAYOUTS:
1744         case LyXRC::RC_HUNSPELLDIR_PATH:
1745         case LyXRC::RC_INDEX_ALTERNATIVES:
1746         case LyXRC::RC_INDEX_COMMAND:
1747         case LyXRC::RC_JBIBTEX_COMMAND:
1748         case LyXRC::RC_JINDEX_COMMAND:
1749         case LyXRC::RC_NOMENCL_COMMAND:
1750         case LyXRC::RC_INPUT:
1751         case LyXRC::RC_KBMAP:
1752         case LyXRC::RC_KBMAP_PRIMARY:
1753         case LyXRC::RC_KBMAP_SECONDARY:
1754         case LyXRC::RC_LABEL_INIT_LENGTH:
1755         case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1756         case LyXRC::RC_LANGUAGE_AUTO_END:
1757         case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1758         case LyXRC::RC_LANGUAGE_COMMAND_END:
1759         case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1760         case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1761         case LyXRC::RC_LANGUAGE_PACKAGE:
1762         case LyXRC::RC_LANGUAGE_USE_BABEL:
1763         case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1764         case LyXRC::RC_MACRO_EDIT_STYLE:
1765         case LyXRC::RC_MAKE_BACKUP:
1766         case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1767         case LyXRC::RC_MOUSE_WHEEL_SPEED:
1768         case LyXRC::RC_NUMLASTFILES:
1769         case LyXRC::RC_PARAGRAPH_MARKERS:
1770         case LyXRC::RC_PATH_PREFIX:
1771                 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1772                         prependEnvPath("PATH", lyxrc.path_prefix);
1773                 }
1774         case LyXRC::RC_PERS_DICT:
1775         case LyXRC::RC_PREVIEW:
1776         case LyXRC::RC_PREVIEW_HASHED_LABELS:
1777         case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1778         case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1779         case LyXRC::RC_PRINTCOPIESFLAG:
1780         case LyXRC::RC_PRINTER:
1781         case LyXRC::RC_PRINTEVENPAGEFLAG:
1782         case LyXRC::RC_PRINTEXSTRAOPTIONS:
1783         case LyXRC::RC_PRINTFILEEXTENSION:
1784         case LyXRC::RC_PRINTLANDSCAPEFLAG:
1785         case LyXRC::RC_PRINTODDPAGEFLAG:
1786         case LyXRC::RC_PRINTPAGERANGEFLAG:
1787         case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1788         case LyXRC::RC_PRINTPAPERFLAG:
1789         case LyXRC::RC_PRINTREVERSEFLAG:
1790         case LyXRC::RC_PRINTSPOOL_COMMAND:
1791         case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1792         case LyXRC::RC_PRINTTOFILE:
1793         case LyXRC::RC_PRINTTOPRINTER:
1794         case LyXRC::RC_PRINT_ADAPTOUTPUT:
1795         case LyXRC::RC_PRINT_COMMAND:
1796         case LyXRC::RC_RTL_SUPPORT:
1797         case LyXRC::RC_SCREEN_DPI:
1798         case LyXRC::RC_SCREEN_FONT_ROMAN:
1799         case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1800         case LyXRC::RC_SCREEN_FONT_SANS:
1801         case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1802         case LyXRC::RC_SCREEN_FONT_SCALABLE:
1803         case LyXRC::RC_SCREEN_FONT_SIZES:
1804         case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1805         case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1806         case LyXRC::RC_GEOMETRY_SESSION:
1807         case LyXRC::RC_SCREEN_ZOOM:
1808         case LyXRC::RC_SERVERPIPE:
1809         case LyXRC::RC_SET_COLOR:
1810         case LyXRC::RC_SHOW_BANNER:
1811         case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1812         case LyXRC::RC_SPELL_COMMAND:
1813         case LyXRC::RC_SPELLCHECKER:
1814         case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1815         case LyXRC::RC_SPLITINDEX_COMMAND:
1816         case LyXRC::RC_TEMPDIRPATH:
1817         case LyXRC::RC_TEMPLATEPATH:
1818         case LyXRC::RC_TEX_ALLOWS_SPACES:
1819         case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1820                 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1821                         os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1822                 }
1823         case LyXRC::RC_THESAURUSDIRPATH:
1824         case LyXRC::RC_UIFILE:
1825         case LyXRC::RC_USER_EMAIL:
1826         case LyXRC::RC_USER_NAME:
1827         case LyXRC::RC_USETEMPDIR:
1828         case LyXRC::RC_USE_ALT_LANG:
1829         case LyXRC::RC_USE_CONVERTER_CACHE:
1830         case LyXRC::RC_USE_ESC_CHARS:
1831         case LyXRC::RC_USE_INP_ENC:
1832         case LyXRC::RC_USE_PERS_DICT:
1833         case LyXRC::RC_USE_TOOLTIP:
1834         case LyXRC::RC_USE_PIXMAP_CACHE:
1835         case LyXRC::RC_USE_SPELL_LIB:
1836         case LyXRC::RC_VIEWDVI_PAPEROPTION:
1837         case LyXRC::RC_SORT_LAYOUTS:
1838         case LyXRC::RC_FULL_SCREEN_LIMIT:
1839         case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1840         case LyXRC::RC_FULL_SCREEN_MENUBAR:
1841         case LyXRC::RC_FULL_SCREEN_TABBAR:
1842         case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1843         case LyXRC::RC_FULL_SCREEN_WIDTH:
1844         case LyXRC::RC_VISUAL_CURSOR:
1845         case LyXRC::RC_VIEWER:
1846         case LyXRC::RC_VIEWER_ALTERNATIVES:
1847         case LyXRC::RC_LAST:
1848                 break;
1849         }
1850 }
1851
1852 } // namespace anon
1853 } // namespace lyx