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