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