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