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