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