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