]> git.lyx.org Git - lyx.git/blob - src/LyXFunc.cpp
Try to dispatch to document BufferView in case dispatch to current BufferView fails...
[lyx.git] / src / LyXFunc.cpp
1 /**
2  * \file LyXFunc.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alfredo Braunstein
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Allan Rae
13  * \author Dekel Tsur
14  * \author Martin Vermeer
15  * \author Jürgen Vigna
16  *
17  * Full author contact details are available in file CREDITS.
18  */
19
20 #include <config.h>
21
22 #include "LyXFunc.h"
23
24 #include "LayoutFile.h"
25 #include "BranchList.h"
26 #include "buffer_funcs.h"
27 #include "Buffer.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "CmdDef.h"
32 #include "Color.h"
33 #include "Converter.h"
34 #include "Cursor.h"
35 #include "CutAndPaste.h"
36 #include "DispatchResult.h"
37 #include "Encoding.h"
38 #include "ErrorList.h"
39 #include "Format.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
42 #include "InsetIterator.h"
43 #include "Intl.h"
44 #include "KeyMap.h"
45 #include "Language.h"
46 #include "Lexer.h"
47 #include "LyXAction.h"
48 #include "lyxfind.h"
49 #include "LyX.h"
50 #include "LyXRC.h"
51 #include "LyXVC.h"
52 #include "Paragraph.h"
53 #include "ParagraphParameters.h"
54 #include "ParIterator.h"
55 #include "Row.h"
56 #include "Server.h"
57 #include "Session.h"
58 #include "SpellChecker.h"
59
60 #include "insets/InsetBox.h"
61 #include "insets/InsetBranch.h"
62 #include "insets/InsetCommand.h"
63 #include "insets/InsetERT.h"
64 #include "insets/InsetExternal.h"
65 #include "insets/InsetFloat.h"
66 #include "insets/InsetGraphics.h"
67 #include "insets/InsetInclude.h"
68 #include "insets/InsetListings.h"
69 #include "insets/InsetNote.h"
70 #include "insets/InsetPhantom.h"
71 #include "insets/InsetSpace.h"
72 #include "insets/InsetTabular.h"
73 #include "insets/InsetVSpace.h"
74 #include "insets/InsetWrap.h"
75
76 #include "frontends/alert.h"
77 #include "frontends/Application.h"
78 #include "frontends/KeySymbol.h"
79 #include "frontends/LyXView.h"
80 #include "frontends/Selection.h"
81
82 #include "support/debug.h"
83 #include "support/environment.h"
84 #include "support/FileName.h"
85 #include "support/filetools.h"
86 #include "support/gettext.h"
87 #include "support/lstrings.h"
88 #include "support/Path.h"
89 #include "support/Package.h"
90 #include "support/Systemcall.h"
91 #include "support/convert.h"
92 #include "support/os.h"
93
94 #include <sstream>
95 #include <vector>
96
97 using namespace std;
98 using namespace lyx::support;
99
100 namespace lyx {
101
102 using frontend::LyXView;
103
104 namespace Alert = frontend::Alert;
105
106 namespace {
107
108
109 // This function runs "configure" and then rereads lyx.defaults to
110 // reconfigure the automatic settings.
111 void reconfigure(LyXView * lv, string const & option)
112 {
113         // emit message signal.
114         if (lv)
115                 lv->message(_("Running configure..."));
116
117         // Run configure in user lyx directory
118         PathChanger p(package().user_support());
119         string configure_command = package().configure_command();
120         configure_command += option;
121         Systemcall one;
122         int ret = one.startscript(Systemcall::Wait, configure_command);
123         p.pop();
124         // emit message signal.
125         if (lv)
126                 lv->message(_("Reloading configuration..."));
127         lyxrc.read(libFileSearch(string(), "lyxrc.defaults"));
128         // Re-read packages.lst
129         LaTeXFeatures::getAvailable();
130
131         if (ret)
132                 Alert::information(_("System reconfiguration failed"),
133                            _("The system reconfiguration has failed.\n"
134                                   "Default textclass is used but LyX may "
135                                   "not be able to work properly.\n"
136                                   "Please reconfigure again if needed."));
137         else
138
139                 Alert::information(_("System reconfigured"),
140                            _("The system has been reconfigured.\n"
141                              "You need to restart LyX to make use of any\n"
142                              "updated document class specifications."));
143 }
144
145
146 bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
147 {
148         // Try to fix cursor in case it is broken.
149         cursor.fixIfBroken();
150
151         // This is, of course, a mess. Better create a new doc iterator and use
152         // this in Inset::getStatus. This might require an additional
153         // BufferView * arg, though (which should be avoided)
154         //Cursor safe = *this;
155         bool res = false;
156         for ( ; cursor.depth(); cursor.pop()) {
157                 //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
158                 LASSERT(cursor.idx() <= cursor.lastidx(), /**/);
159                 LASSERT(cursor.pit() <= cursor.lastpit(), /**/);
160                 LASSERT(cursor.pos() <= cursor.lastpos(), /**/);
161
162                 // The inset's getStatus() will return 'true' if it made
163                 // a definitive decision on whether it want to handle the
164                 // request or not. The result of this decision is put into
165                 // the 'status' parameter.
166                 if (cursor.inset().getStatus(cursor, cmd, status)) {
167                         res = true;
168                         break;
169                 }
170         }
171         return res;
172 }
173
174
175 /** Return the change status at cursor position, taking in account the
176  * status at each level of the document iterator (a table in a deleted
177  * footnote is deleted).
178  * When \param outer is true, the top slice is not looked at.
179  */
180 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
181 {
182         size_t const depth = dit.depth() - (outer ? 1 : 0);
183
184         for (size_t i = 0 ; i < depth ; ++i) {
185                 CursorSlice const & slice = dit[i];
186                 if (!slice.inset().inMathed()
187                     && slice.pos() < slice.paragraph().size()) {
188                         Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
189                         if (ch != Change::UNCHANGED)
190                                 return ch;
191                 }
192         }
193         return Change::UNCHANGED;
194 }
195
196 }
197
198
199 LyXFunc::LyXFunc()
200         : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
201 {
202 }
203
204
205 void LyXFunc::initKeySequences(KeyMap * kb)
206 {
207         keyseq = KeySequence(kb, kb);
208         cancel_meta_seq = KeySequence(kb, kb);
209 }
210
211
212 void LyXFunc::setLyXView(LyXView * lv)
213 {
214         if (lyx_view_ && lyx_view_->currentBufferView() && lyx_view_ != lv)
215                 // save current selection to the selection buffer to allow
216                 // middle-button paste in another window
217                 cap::saveSelection(lyx_view_->currentBufferView()->cursor());
218         lyx_view_ = lv;
219 }
220
221
222 void LyXFunc::handleKeyFunc(FuncCode action)
223 {
224         char_type c = encoded_last_key;
225
226         if (keyseq.length())
227                 c = 0;
228
229         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
230         BufferView * bv = lyx_view_->currentBufferView();
231         bv->getIntl().getTransManager().deadkey(
232                 c, get_accent(action).accent, bv->cursor().innerText(),
233                 bv->cursor());
234         // Need to clear, in case the minibuffer calls these
235         // actions
236         keyseq.clear();
237         // copied verbatim from do_accent_char
238         bv->cursor().resetAnchor();
239         bv->processUpdateFlags(Update::FitCursor);
240 }
241
242 //FIXME: bookmark handling is a frontend issue. This code should be transferred
243 // to GuiView and be GuiView and be window dependent.
244 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
245 {
246         LASSERT(lyx_view_, /**/);
247         if (!theSession().bookmarks().isValid(idx))
248                 return;
249         BookmarksSection::Bookmark const & bm = theSession().bookmarks().bookmark(idx);
250         LASSERT(!bm.filename.empty(), /**/);
251         string const file = bm.filename.absFilename();
252         // if the file is not opened, open it.
253         if (!theBufferList().exists(bm.filename)) {
254                 if (openFile)
255                         dispatch(FuncRequest(LFUN_FILE_OPEN, file));
256                 else
257                         return;
258         }
259         // open may fail, so we need to test it again
260         if (!theBufferList().exists(bm.filename))
261                 return;
262
263         // bm can be changed when saving
264         BookmarksSection::Bookmark tmp = bm;
265
266         // Special case idx == 0 used for back-from-back jump navigation
267         if (idx == 0)
268                 dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
269
270         // if the current buffer is not that one, switch to it.
271         if (!lyx_view_->documentBufferView()
272                 || lyx_view_->documentBufferView()->buffer().fileName() != tmp.filename) {
273                 if (!switchToBuffer)
274                         return;
275                 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
276         }
277
278         // moveToPosition try paragraph id first and then paragraph (pit, pos).
279         if (!lyx_view_->documentBufferView()->moveToPosition(
280                 tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos))
281                 return;
282
283         // bm changed
284         if (idx == 0)
285                 return;
286
287         // Cursor jump succeeded!
288         Cursor const & cur = lyx_view_->documentBufferView()->cursor();
289         pit_type new_pit = cur.pit();
290         pos_type new_pos = cur.pos();
291         int new_id = cur.paragraph().id();
292
293         // if bottom_pit, bottom_pos or top_id has been changed, update bookmark
294         // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
295         if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos 
296                 || bm.top_id != new_id) {
297                 const_cast<BookmarksSection::Bookmark &>(bm).updatePos(
298                         new_pit, new_pos, new_id);
299         }
300 }
301
302
303 void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
304 {
305         LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
306
307         // Do nothing if we have nothing (JMarc)
308         if (!keysym.isOK()) {
309                 LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
310                 lyx_view_->restartCursor();
311                 return;
312         }
313
314         if (keysym.isModifier()) {
315                 LYXERR(Debug::KEY, "isModifier true");
316                 if (lyx_view_)
317                         lyx_view_->restartCursor();
318                 return;
319         }
320
321         //Encoding const * encoding = lyx_view_->documentBufferView()->cursor().getEncoding();
322         //encoded_last_key = keysym.getISOEncoded(encoding ? encoding->name() : "");
323         // FIXME: encoded_last_key shadows the member variable of the same
324         // name. Is that intended?
325         char_type encoded_last_key = keysym.getUCSEncoded();
326
327         // Do a one-deep top-level lookup for
328         // cancel and meta-fake keys. RVDK_PATCH_5
329         cancel_meta_seq.reset();
330
331         FuncRequest func = cancel_meta_seq.addkey(keysym, state);
332         LYXERR(Debug::KEY, "action first set to [" << func.action << ']');
333
334         // When not cancel or meta-fake, do the normal lookup.
335         // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
336         // Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5.
337         if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) {
338                 // remove Caps Lock and Mod2 as a modifiers
339                 func = keyseq.addkey(keysym, (state | meta_fake_bit));
340                 LYXERR(Debug::KEY, "action now set to [" << func.action << ']');
341         }
342
343         // Dont remove this unless you know what you are doing.
344         meta_fake_bit = NoModifier;
345
346         // Can this happen now ?
347         if (func.action == LFUN_NOACTION)
348                 func = FuncRequest(LFUN_COMMAND_PREFIX);
349
350         LYXERR(Debug::KEY, " Key [action=" << func.action << "]["
351                 << keyseq.print(KeySequence::Portable) << ']');
352
353         // already here we know if it any point in going further
354         // why not return already here if action == -1 and
355         // num_bytes == 0? (Lgb)
356
357         if (keyseq.length() > 1)
358                 lyx_view_->message(keyseq.print(KeySequence::ForGui));
359
360
361         // Maybe user can only reach the key via holding down shift.
362         // Let's see. But only if shift is the only modifier
363         if (func.action == LFUN_UNKNOWN_ACTION && state == ShiftModifier) {
364                 LYXERR(Debug::KEY, "Trying without shift");
365                 func = keyseq.addkey(keysym, NoModifier);
366                 LYXERR(Debug::KEY, "Action now " << func.action);
367         }
368
369         if (func.action == LFUN_UNKNOWN_ACTION) {
370                 // Hmm, we didn't match any of the keysequences. See
371                 // if it's normal insertable text not already covered
372                 // by a binding
373                 if (keysym.isText() && keyseq.length() == 1) {
374                         LYXERR(Debug::KEY, "isText() is true, inserting.");
375                         func = FuncRequest(LFUN_SELF_INSERT,
376                                            FuncRequest::KEYBOARD);
377                 } else {
378                         LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
379                         lyx_view_->message(_("Unknown function."));
380                         lyx_view_->restartCursor();
381                         return;
382                 }
383         }
384
385         if (func.action == LFUN_SELF_INSERT) {
386                 if (encoded_last_key != 0) {
387                         docstring const arg(1, encoded_last_key);
388                         dispatch(FuncRequest(LFUN_SELF_INSERT, arg,
389                                              FuncRequest::KEYBOARD));
390                         LYXERR(Debug::KEY, "SelfInsert arg[`" << to_utf8(arg) << "']");
391                 }
392         } else {
393                 dispatch(func);
394                 if (!lyx_view_)
395                         return;
396         }
397 }
398
399
400 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
401 {
402         //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
403         FuncStatus flag;
404
405         /* In LyX/Mac, when a dialog is open, the menus of the
406            application can still be accessed without giving focus to
407            the main window. In this case, we want to disable the menu
408            entries that are buffer or view-related.
409
410            If this code is moved somewhere else (like in
411            GuiView::getStatus), then several functions will not be
412            handled correctly.
413         */
414         frontend::LyXView * lv = 0;
415         Buffer * buf = 0;
416         if (lyx_view_ 
417             && (cmd.origin != FuncRequest::MENU || lyx_view_->hasFocus())) {
418                 lv = lyx_view_;
419                 if (lyx_view_->documentBufferView())
420                         buf = &lyx_view_->documentBufferView()->buffer();
421         }
422
423         if (cmd.action == LFUN_NOACTION) {
424                 flag.message(from_utf8(N_("Nothing to do")));
425                 flag.setEnabled(false);
426                 return flag;
427         }
428
429         switch (cmd.action) {
430         case LFUN_UNKNOWN_ACTION:
431                 flag.unknown(true);
432                 flag.setEnabled(false);
433                 break;
434
435         default:
436                 break;
437         }
438
439         if (flag.unknown()) {
440                 flag.message(from_utf8(N_("Unknown action")));
441                 return flag;
442         }
443
444         if (!flag.enabled()) {
445                 if (flag.message().empty())
446                         flag.message(from_utf8(N_("Command disabled")));
447                 return flag;
448         }
449
450         // Check whether we need a buffer
451         if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
452                 // no, exit directly
453                 flag.message(from_utf8(N_("Command not allowed with"
454                                     "out any document open")));
455                 flag.setEnabled(false);
456                 return flag;
457         }
458
459         // I would really like to avoid having this switch and rather try to
460         // encode this in the function itself.
461         // -- And I'd rather let an inset decide which LFUNs it is willing
462         // to handle (Andre')
463         bool enable = true;
464         switch (cmd.action) {
465
466         case LFUN_CITATION_INSERT: {
467                 FuncRequest fr(LFUN_INSET_INSERT, "citation");
468                 enable = getStatus(fr).enabled();
469                 break;
470         }
471         
472         // This could be used for the no-GUI version. The GUI version is handled in
473         // LyXView::getStatus(). See above.
474         /*
475         case LFUN_BUFFER_WRITE:
476         case LFUN_BUFFER_WRITE_AS: {
477                 Buffer * b = theBufferList().getBuffer(FileName(cmd.getArg(0)));
478                 enable = b && (b->isUnnamed() || !b->isClean());
479                 break;
480         }
481         */
482
483         case LFUN_BUFFER_WRITE_ALL: {
484                 // We enable the command only if there are some modified buffers
485                 Buffer * first = theBufferList().first();
486                 enable = false;
487                 if (!first)
488                         break;
489                 Buffer * b = first;
490                 // We cannot use a for loop as the buffer list is a cycle.
491                 do {
492                         if (!b->isClean()) {
493                                 enable = true;
494                                 break;
495                         }
496                         b = theBufferList().next(b);
497                 } while (b != first); 
498                 break;
499         }
500
501         case LFUN_BOOKMARK_GOTO: {
502                 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
503                 enable = theSession().bookmarks().isValid(num);
504                 break;
505         }
506
507         case LFUN_BOOKMARK_CLEAR:
508                 enable = theSession().bookmarks().hasValid();
509                 break;
510
511         // this one is difficult to get right. As a half-baked
512         // solution, we consider only the first action of the sequence
513         case LFUN_COMMAND_SEQUENCE: {
514                 // argument contains ';'-terminated commands
515                 string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
516                 FuncRequest func(lyxaction.lookupFunc(firstcmd));
517                 func.origin = cmd.origin;
518                 flag = getStatus(func);
519                 break;
520         }
521
522         // we want to check if at least one of these is enabled
523         case LFUN_COMMAND_ALTERNATIVES: {
524                 // argument contains ';'-terminated commands
525                 string arg = to_utf8(cmd.argument());
526                 while (!arg.empty()) {
527                         string first;
528                         arg = split(arg, first, ';');
529                         FuncRequest func(lyxaction.lookupFunc(first));
530                         func.origin = cmd.origin;
531                         flag = getStatus(func);
532                         // if this one is enabled, the whole thing is
533                         if (flag.enabled())
534                                 break;
535                 }
536                 break;
537         }
538
539         case LFUN_CALL: {
540                 FuncRequest func;
541                 string name = to_utf8(cmd.argument());
542                 if (theTopLevelCmdDef().lock(name, func)) {
543                         func.origin = cmd.origin;
544                         flag = getStatus(func);
545                         theTopLevelCmdDef().release(name);
546                 } else {
547                         // catch recursion or unknown command
548                         // definition. all operations until the
549                         // recursion or unknown command definition
550                         // occurs are performed, so set the state to
551                         // enabled
552                         enable = true;
553                 }
554                 break;
555         }
556
557         case LFUN_COMMAND_PREFIX:
558         case LFUN_CANCEL:
559         case LFUN_META_PREFIX:
560         case LFUN_RECONFIGURE:
561         case LFUN_HELP_OPEN:
562         case LFUN_DROP_LAYOUTS_CHOICE:
563         case LFUN_SERVER_GET_FILENAME:
564         case LFUN_SERVER_NOTIFY:
565         case LFUN_SERVER_GOTO_FILE_ROW:
566         case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
567         case LFUN_REPEAT:
568         case LFUN_PREFERENCES_SAVE:
569         case LFUN_INSET_EDIT:
570         case LFUN_BUFFER_SAVE_AS_DEFAULT:
571         case LFUN_LYXRC_APPLY:
572                 // these are handled in our dispatch()
573                 break;
574
575         default:
576                 if (!theApp()) {
577                         enable = false;
578                         break;
579                 }
580                 if (theApp()->getStatus(cmd, flag))
581                         break;
582
583                 // Does the view know something?
584                 if (!lv) {
585                         enable = false;
586                         break;
587                 }
588                 if (lv->getStatus(cmd, flag))
589                         break;
590
591                 BufferView * bv = lv->currentBufferView();
592                 BufferView * doc_bv = lv->documentBufferView();
593                 // If we do not have a BufferView, then other functions are disabled
594                 if (!bv) {
595                         enable = false;
596                         break;
597                 }
598                 // Is this a function that acts on inset at point?
599                 Inset * inset = bv->cursor().nextInset();
600                 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
601                     && inset && inset->getStatus(bv->cursor(), cmd, flag))
602                         break;
603
604                 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
605                 if (!decided)
606                         // try the BufferView
607                         decided = bv->getStatus(cmd, flag);
608                 if (!decided)
609                         // try the Buffer
610                         decided = bv->buffer().getStatus(cmd, flag);
611                 if (!decided && doc_bv)
612                         // try the Document Buffer
613                         decided = doc_bv->buffer().getStatus(cmd, flag);
614         }
615
616         if (!enable)
617                 flag.setEnabled(false);
618
619         // Can we use a readonly buffer?
620         if (buf && buf->isReadonly()
621             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
622             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
623                 flag.message(from_utf8(N_("Document is read-only")));
624                 flag.setEnabled(false);
625         }
626
627         // Are we in a DELETED change-tracking region?
628         if (lyx_view_ && lyx_view_->documentBufferView()
629                 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
630                     == Change::DELETED)
631             && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
632             && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
633                 flag.message(from_utf8(N_("This portion of the document is deleted.")));
634                 flag.setEnabled(false);
635         }
636
637         // the default error message if we disable the command
638         if (!flag.enabled() && flag.message().empty())
639                 flag.message(from_utf8(N_("Command disabled")));
640
641         return flag;
642 }
643
644
645 namespace {
646
647 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
648
649 } //namespace anon
650
651
652 void LyXFunc::dispatch(FuncRequest const & cmd)
653 {
654         string const argument = to_utf8(cmd.argument());
655         FuncCode const action = cmd.action;
656
657         LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
658         //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
659
660         // we have not done anything wrong yet.
661         errorstat = false;
662         dispatch_buffer.erase();
663
664         // redraw the screen at the end (first of the two drawing steps).
665         //This is done unless explicitely requested otherwise
666         Update::flags updateFlags = Update::FitCursor;
667
668         FuncStatus const flag = getStatus(cmd);
669         if (!flag.enabled()) {
670                 // We cannot use this function here
671                 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
672                        << lyxaction.getActionName(action)
673                        << " [" << action << "] is disabled at this location");
674                 setErrorMessage(flag.message());
675                 if (lyx_view_)
676                         lyx_view_->restartCursor();
677         } else {
678                 Buffer * buffer = 0;
679                 if (lyx_view_ && lyx_view_->currentBufferView())
680                         buffer = &lyx_view_->currentBufferView()->buffer();
681                 switch (action) {
682
683                 case LFUN_COMMAND_PREFIX:
684                         LASSERT(lyx_view_, /**/);
685                         lyx_view_->message(keyseq.printOptions(true));
686                         break;
687
688                 case LFUN_CANCEL:
689                         LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
690                         keyseq.reset();
691                         meta_fake_bit = NoModifier;
692                         if (buffer)
693                                 // cancel any selection
694                                 dispatch(FuncRequest(LFUN_MARK_OFF));
695                         setMessage(from_ascii(N_("Cancel")));
696                         break;
697
698                 case LFUN_META_PREFIX:
699                         meta_fake_bit = AltModifier;
700                         setMessage(keyseq.print(KeySequence::ForGui));
701                         break;
702
703                 // --- Menus -----------------------------------------------
704                 case LFUN_RECONFIGURE:
705                         // argument is any additional parameter to the configure.py command
706                         reconfigure(lyx_view_, argument);
707                         break;
708
709                 case LFUN_HELP_OPEN: {
710                         if (lyx_view_ == 0)
711                                 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
712                         string const arg = argument;
713                         if (arg.empty()) {
714                                 setErrorMessage(from_utf8(N_("Missing argument")));
715                                 break;
716                         }
717                         FileName fname = i18nLibFileSearch("doc", arg, "lyx");
718                         if (fname.empty()) 
719                                 fname = i18nLibFileSearch("examples", arg, "lyx");
720
721                         if (fname.empty()) {
722                                 lyxerr << "LyX: unable to find documentation file `"
723                                                          << arg << "'. Bad installation?" << endl;
724                                 break;
725                         }
726                         lyx_view_->message(bformat(_("Opening help file %1$s..."),
727                                 makeDisplayPath(fname.absFilename())));
728                         Buffer * buf = lyx_view_->loadDocument(fname, false);
729                         if (buf) {
730                                 buf->updateLabels();
731                                 lyx_view_->setBuffer(buf);
732                                 buf->errors("Parse");
733                         }
734                         updateFlags = Update::None;
735                         break;
736                 }
737
738                 // --- lyxserver commands ----------------------------
739                 case LFUN_SERVER_GET_FILENAME:
740                         LASSERT(lyx_view_ && buffer, /**/);
741                         setMessage(from_utf8(buffer->absFileName()));
742                         LYXERR(Debug::INFO, "FNAME["
743                                 << buffer->absFileName() << ']');
744                         break;
745
746                 case LFUN_SERVER_NOTIFY:
747                         dispatch_buffer = keyseq.print(KeySequence::Portable);
748                         theServer().notifyClient(to_utf8(dispatch_buffer));
749                         break;
750
751                 case LFUN_SERVER_GOTO_FILE_ROW: {
752                         LASSERT(lyx_view_, /**/);
753                         string file_name;
754                         int row;
755                         istringstream is(argument);
756                         is >> file_name >> row;
757                         file_name = os::internal_path(file_name);
758                         Buffer * buf = 0;
759                         bool loaded = false;
760                         string const abstmp = package().temp_dir().absFilename();
761                         string const realtmp = package().temp_dir().realPath();
762                         // We have to use os::path_prefix_is() here, instead of
763                         // simply prefixIs(), because the file name comes from
764                         // an external application and may need case adjustment.
765                         if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
766                             || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
767                                 // Needed by inverse dvi search. If it is a file
768                                 // in tmpdir, call the apropriated function.
769                                 // If tmpdir is a symlink, we may have the real
770                                 // path passed back, so we correct for that.
771                                 if (!prefixIs(file_name, abstmp))
772                                         file_name = subst(file_name, realtmp, abstmp);
773                                 buf = theBufferList().getBufferFromTmp(file_name);
774                         } else {
775                                 // Must replace extension of the file to be .lyx
776                                 // and get full path
777                                 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
778                                 // Either change buffer or load the file
779                                 if (theBufferList().exists(s))
780                                         buf = theBufferList().getBuffer(s);
781                                 else if (s.exists()) {
782                                         buf = lyx_view_->loadDocument(s);
783                                         loaded = true;
784                                 } else
785                                         lyx_view_->message(bformat(
786                                                 _("File does not exist: %1$s"),
787                                                 makeDisplayPath(file_name)));
788                         }
789
790                         if (!buf) {
791                                 updateFlags = Update::None;
792                                 break;
793                         }
794
795                         buf->updateLabels();
796                         lyx_view_->setBuffer(buf);
797                         lyx_view_->documentBufferView()->setCursorFromRow(row);
798                         if (loaded)
799                                 buf->errors("Parse");
800                         updateFlags = Update::FitCursor;
801                         break;
802                 }
803
804
805                 case LFUN_DIALOG_SHOW_NEW_INSET: {
806                         LASSERT(lyx_view_, /**/);
807                         string const name = cmd.getArg(0);
808                         InsetCode code = insetCode(name);
809                         string data = trim(to_utf8(cmd.argument()).substr(name.size()));
810                         bool insetCodeOK = true;
811                         switch (code) {
812                         case BIBITEM_CODE:
813                         case BIBTEX_CODE:
814                         case INDEX_CODE:
815                         case LABEL_CODE:
816                         case NOMENCL_CODE:
817                         case NOMENCL_PRINT_CODE:
818                         case REF_CODE:
819                         case TOC_CODE:
820                         case HYPERLINK_CODE: {
821                                 InsetCommandParams p(code);
822                                 data = InsetCommand::params2string(name, p);
823                                 break;
824                         }
825                         case INCLUDE_CODE: {
826                                 // data is the include type: one of "include",
827                                 // "input", "verbatiminput" or "verbatiminput*"
828                                 if (data.empty())
829                                         // default type is requested
830                                         data = "include";
831                                 InsetCommandParams p(INCLUDE_CODE, data);
832                                 data = InsetCommand::params2string("include", p);
833                                 break;
834                         }
835                         case BOX_CODE: {
836                                 // \c data == "Boxed" || "Frameless" etc
837                                 InsetBoxParams p(data);
838                                 data = InsetBox::params2string(p);
839                                 break;
840                         }
841                         case BRANCH_CODE: {
842                                 InsetBranchParams p;
843                                 data = InsetBranch::params2string(p);
844                                 break;
845                         }
846                         case CITE_CODE: {
847                                 InsetCommandParams p(CITE_CODE);
848                                 data = InsetCommand::params2string(name, p);
849                                 break;
850                         }
851                         case ERT_CODE: {
852                                 data = InsetERT::params2string(InsetCollapsable::Open);
853                                 break;
854                         }
855                         case EXTERNAL_CODE: {
856                                 InsetExternalParams p;
857                                 data = InsetExternal::params2string(p, *buffer);
858                                 break;
859                         }
860                         case FLOAT_CODE:  {
861                                 InsetFloatParams p;
862                                 data = InsetFloat::params2string(p);
863                                 break;
864                         }
865                         case LISTINGS_CODE: {
866                                 InsetListingsParams p;
867                                 data = InsetListings::params2string(p);
868                                 break;
869                         }
870                         case GRAPHICS_CODE: {
871                                 InsetGraphicsParams p;
872                                 data = InsetGraphics::params2string(p, *buffer);
873                                 break;
874                         }
875                         case NOTE_CODE: {
876                                 InsetNoteParams p;
877                                 data = InsetNote::params2string(p);
878                                 break;
879                         }
880                         case PHANTOM_CODE: {
881                                 InsetPhantomParams p;
882                                 data = InsetPhantom::params2string(p);
883                                 break;
884                         }
885                         case SPACE_CODE: {
886                                 InsetSpaceParams p;
887                                 data = InsetSpace::params2string(p);
888                                 break;
889                         }
890                         case VSPACE_CODE: {
891                                 VSpace space;
892                                 data = InsetVSpace::params2string(space);
893                                 break;
894                         }
895                         case WRAP_CODE: {
896                                 InsetWrapParams p;
897                                 data = InsetWrap::params2string(p);
898                                 break;
899                         }
900                         default:
901                                 lyxerr << "Inset type '" << name << 
902                                         "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" <<  endl;
903                                 insetCodeOK = false;
904                                 break;
905                         } // end switch(code)
906                         if (insetCodeOK)
907                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
908                         break;
909                 }
910
911                 case LFUN_CITATION_INSERT: {
912                         LASSERT(lyx_view_, /**/);
913                         if (!argument.empty()) {
914                                 // we can have one optional argument, delimited by '|'
915                                 // citation-insert <key>|<text_before>
916                                 // this should be enhanced to also support text_after
917                                 // and citation style
918                                 string arg = argument;
919                                 string opt1;
920                                 if (contains(argument, "|")) {
921                                         arg = token(argument, '|', 0);
922                                         opt1 = token(argument, '|', 1);
923                                 }
924                                 InsetCommandParams icp(CITE_CODE);
925                                 icp["key"] = from_utf8(arg);
926                                 if (!opt1.empty())
927                                         icp["before"] = from_utf8(opt1);
928                                 string icstr = InsetCommand::params2string("citation", icp);
929                                 FuncRequest fr(LFUN_INSET_INSERT, icstr);
930                                 dispatch(fr);
931                         } else
932                                 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
933                         break;
934                 }
935
936                 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
937                         LASSERT(lyx_view_, /**/);
938                         lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
939                         break;
940
941                 case LFUN_REPEAT: {
942                         // repeat command
943                         string countstr;
944                         string rest = split(argument, countstr, ' ');
945                         istringstream is(countstr);
946                         int count = 0;
947                         is >> count;
948                         //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
949                         for (int i = 0; i < count; ++i)
950                                 dispatch(lyxaction.lookupFunc(rest));
951                         break;
952                 }
953
954                 case LFUN_COMMAND_SEQUENCE: {
955                         // argument contains ';'-terminated commands
956                         string arg = argument;
957                         if (theBufferList().isLoaded(buffer))
958                                 buffer->undo().beginUndoGroup();
959                         while (!arg.empty()) {
960                                 string first;
961                                 arg = split(arg, first, ';');
962                                 FuncRequest func(lyxaction.lookupFunc(first));
963                                 func.origin = cmd.origin;
964                                 dispatch(func);
965                         }
966                         if (theBufferList().isLoaded(buffer))
967                                 buffer->undo().endUndoGroup();
968                         break;
969                 }
970
971                 case LFUN_COMMAND_ALTERNATIVES: {
972                         // argument contains ';'-terminated commands
973                         string arg = argument;
974                         while (!arg.empty()) {
975                                 string first;
976                                 arg = split(arg, first, ';');
977                                 FuncRequest func(lyxaction.lookupFunc(first));
978                                 func.origin = cmd.origin;
979                                 FuncStatus stat = getStatus(func);
980                                 if (stat.enabled()) {
981                                         dispatch(func);
982                                         break;
983                                 }
984                         }
985                         break;
986                 }
987
988                 case LFUN_CALL: {
989                         FuncRequest func;
990                         if (theTopLevelCmdDef().lock(argument, func)) {
991                                 func.origin = cmd.origin;
992                                 dispatch(func);
993                                 theTopLevelCmdDef().release(argument);
994                         } else {
995                                 if (func.action == LFUN_UNKNOWN_ACTION) {
996                                         // unknown command definition
997                                         lyxerr << "Warning: unknown command definition `"
998                                                    << argument << "'"
999                                                    << endl;
1000                                 } else {
1001                                         // recursion detected
1002                                         lyxerr << "Warning: Recursion in the command definition `"
1003                                                    << argument << "' detected"
1004                                                    << endl;
1005                                 }
1006                         }
1007                         break;
1008                 }
1009
1010                 case LFUN_PREFERENCES_SAVE: {
1011                         lyxrc.write(makeAbsPath("preferences",
1012                                                 package().user_support().absFilename()),
1013                                     false);
1014                         break;
1015                 }
1016
1017                 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1018                         string const fname =
1019                                 addName(addPath(package().user_support().absFilename(), "templates/"),
1020                                         "defaults.lyx");
1021                         Buffer defaults(fname);
1022
1023                         istringstream ss(argument);
1024                         Lexer lex;
1025                         lex.setStream(ss);
1026                         int const unknown_tokens = defaults.readHeader(lex);
1027
1028                         if (unknown_tokens != 0) {
1029                                 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1030                                        << unknown_tokens << " unknown token"
1031                                        << (unknown_tokens == 1 ? "" : "s")
1032                                        << endl;
1033                         }
1034
1035                         if (defaults.writeFile(FileName(defaults.absFileName())))
1036                                 setMessage(bformat(_("Document defaults saved in %1$s"),
1037                                                    makeDisplayPath(fname)));
1038                         else
1039                                 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1040                         break;
1041                 }
1042
1043                 case LFUN_LYXRC_APPLY: {
1044                         // reset active key sequences, since the bindings
1045                         // are updated (bug 6064)
1046                         keyseq.reset();
1047                         LyXRC const lyxrc_orig = lyxrc;
1048
1049                         istringstream ss(argument);
1050                         bool const success = lyxrc.read(ss) == 0;
1051
1052                         if (!success) {
1053                                 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1054                                        << "Unable to read lyxrc data"
1055                                        << endl;
1056                                 break;
1057                         }
1058
1059                         actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1060
1061                         setSpellChecker();
1062
1063                         theApp()->resetGui();
1064
1065                         /// We force the redraw in any case because there might be
1066                         /// some screen font changes.
1067                         /// FIXME: only the current view will be updated. the Gui
1068                         /// class is able to furnish the list of views.
1069                         updateFlags = Update::Force;
1070                         break;
1071                 }
1072
1073                 case LFUN_BOOKMARK_GOTO:
1074                         // go to bookmark, open unopened file and switch to buffer if necessary
1075                         gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1076                         updateFlags = Update::FitCursor;
1077                         break;
1078
1079                 case LFUN_BOOKMARK_CLEAR:
1080                         theSession().bookmarks().clear();
1081                         break;
1082
1083                 default:
1084                         LASSERT(theApp(), /**/);
1085                         // Let the frontend dispatch its own actions.
1086                         if (theApp()->dispatch(cmd))
1087                                 // Nothing more to do.
1088                                 return;
1089
1090                         // Everything below is only for active lyx_view_
1091                         if (lyx_view_ == 0)
1092                                 break;
1093
1094                         BufferView * bv = lyx_view_->documentBufferView();
1095                         BufferView * doc_bv = lyx_view_->documentBufferView();
1096
1097                         // Start an undo group. This may be needed for
1098                         // some stuff like inset-apply on labels.
1099                         if (theBufferList().isLoaded(buffer))
1100                                 buffer->undo().beginUndoGroup();
1101                                 
1102                         // Let the current LyXView dispatch its own actions.
1103                         if (lyx_view_->dispatch(cmd)) {
1104                                 if (bv) {
1105                                         updateFlags = bv->cursor().result().update();
1106                                         if (theBufferList().isLoaded(buffer))
1107                                                 buffer->undo().endUndoGroup();
1108                                 }
1109                                 break;
1110                         }
1111
1112                         LASSERT(bv, /**/);
1113
1114                         // Let the current BufferView dispatch its own actions.
1115                         if (bv->dispatch(cmd)) {
1116                                 // The BufferView took care of its own updates if needed.
1117                                 updateFlags = Update::None;
1118                                 if (theBufferList().isLoaded(buffer))
1119                                         buffer->undo().endUndoGroup();
1120                                 break;
1121                         }
1122                         // Try with the document BufferView dispatch if any.
1123                         if (doc_bv && doc_bv->dispatch(cmd)) {
1124                                 // The BufferView took care of its own updates if needed.
1125                                 buffer = &(doc_bv->buffer());
1126                                 updateFlags = Update::None;
1127                                 if (theBufferList().isLoaded(buffer))
1128                                         buffer->undo().endUndoGroup();
1129                                 break;
1130                         }
1131
1132                         // OK, so try the current Buffer itself...
1133                         DispatchResult dr;
1134                         bv->buffer().dispatch(cmd, dr);
1135                         if (dr.dispatched()) {
1136                                 updateFlags = dr.update();
1137                                 break;
1138                         }
1139                         // and with the document Buffer.
1140                         if (doc_bv) {
1141                                 doc_bv->buffer().dispatch(cmd, dr);
1142                                 if (dr.dispatched()) {
1143                                         updateFlags = dr.update();
1144                                         break;
1145                                 }
1146                         }
1147
1148                         // Is this a function that acts on inset at point?
1149                         Inset * inset = bv->cursor().nextInset();
1150                         if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1151                             && inset) {
1152                                 bv->cursor().result().dispatched(true);
1153                                 bv->cursor().result().update(Update::FitCursor | Update::Force);
1154                                 FuncRequest tmpcmd = cmd;
1155                                 inset->dispatch(bv->cursor(), tmpcmd);
1156                                 if (bv->cursor().result().dispatched()) {
1157                                         updateFlags = bv->cursor().result().update();
1158                                         break;
1159                                 }
1160                         }
1161
1162                         // Let the current Cursor dispatch its own actions.
1163                         Cursor old = bv->cursor();
1164                         bv->cursor().getPos(cursorPosBeforeDispatchX_,
1165                                                 cursorPosBeforeDispatchY_);
1166                         bv->cursor().dispatch(cmd);
1167
1168                         // notify insets we just left
1169                         if (bv->cursor() != old) {
1170                                 old.fixIfBroken();
1171                                 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1172                                 if (badcursor)
1173                                         bv->cursor().fixIfBroken();
1174                         }
1175
1176                         if (theBufferList().isLoaded(buffer))
1177                                 buffer->undo().endUndoGroup();
1178
1179                         // update completion. We do it here and not in
1180                         // processKeySym to avoid another redraw just for a
1181                         // changed inline completion
1182                         if (cmd.origin == FuncRequest::KEYBOARD) {
1183                                 if (cmd.action == LFUN_SELF_INSERT
1184                                     || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1185                                         lyx_view_->updateCompletion(bv->cursor(), true, true);
1186                                 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1187                                         lyx_view_->updateCompletion(bv->cursor(), false, true);
1188                                 else
1189                                         lyx_view_->updateCompletion(bv->cursor(), false, false);
1190                         }
1191
1192                         updateFlags = bv->cursor().result().update();
1193                 }
1194
1195                 // if we executed a mutating lfun, mark the buffer as dirty
1196                 if (theBufferList().isLoaded(buffer) && flag.enabled()
1197                     && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1198                     && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1199                         buffer->markDirty();                    
1200
1201                 if (lyx_view_ && lyx_view_->currentBufferView()) {
1202                         // BufferView::update() updates the ViewMetricsInfo and
1203                         // also initializes the position cache for all insets in
1204                         // (at least partially) visible top-level paragraphs.
1205                         // We will redraw the screen only if needed.
1206                         lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1207
1208                         // Do we have a selection?
1209                         theSelection().haveSelection(
1210                                 lyx_view_->currentBufferView()->cursor().selection());
1211                         
1212                         // update gui
1213                         lyx_view_->restartCursor();
1214                 }
1215         }
1216         if (lyx_view_) {
1217                 // Some messages may already be translated, so we cannot use _()
1218                 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1219         }
1220 }
1221
1222
1223 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1224 {
1225         const bool verbose = (cmd.origin == FuncRequest::MENU
1226                               || cmd.origin == FuncRequest::TOOLBAR
1227                               || cmd.origin == FuncRequest::COMMANDBUFFER);
1228
1229         if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1230                 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1231                 if (!msg.empty())
1232                         lyx_view_->message(msg);
1233                 return;
1234         }
1235
1236         docstring dispatch_msg = msg;
1237         if (!dispatch_msg.empty())
1238                 dispatch_msg += ' ';
1239
1240         docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1241
1242         bool argsadded = false;
1243
1244         if (!cmd.argument().empty()) {
1245                 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1246                         comname += ' ' + cmd.argument();
1247                         argsadded = true;
1248                 }
1249         }
1250
1251         docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1252
1253         if (!shortcuts.empty())
1254                 comname += ": " + shortcuts;
1255         else if (!argsadded && !cmd.argument().empty())
1256                 comname += ' ' + cmd.argument();
1257
1258         if (!comname.empty()) {
1259                 comname = rtrim(comname);
1260                 dispatch_msg += '(' + rtrim(comname) + ')';
1261         }
1262
1263         LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1264         if (!dispatch_msg.empty())
1265                 lyx_view_->message(dispatch_msg);
1266 }
1267
1268
1269 // Each "lyx_view_" should have it's own message method. lyxview and
1270 // the minibuffer would use the minibuffer, but lyxserver would
1271 // send an ERROR signal to its client.  Alejandro 970603
1272 // This function is bit problematic when it comes to NLS, to make the
1273 // lyx servers client be language indepenent we must not translate
1274 // strings sent to this func.
1275 void LyXFunc::setErrorMessage(docstring const & m) const
1276 {
1277         dispatch_buffer = m;
1278         errorstat = true;
1279 }
1280
1281
1282 void LyXFunc::setMessage(docstring const & m) const
1283 {
1284         dispatch_buffer = m;
1285 }
1286
1287
1288 docstring LyXFunc::viewStatusMessage()
1289 {
1290         // When meta-fake key is pressed, show the key sequence so far + "M-".
1291         if (wasMetaKey())
1292                 return keyseq.print(KeySequence::ForGui) + "M-";
1293
1294         // Else, when a non-complete key sequence is pressed,
1295         // show the available options.
1296         if (keyseq.length() > 0 && !keyseq.deleted())
1297                 return keyseq.printOptions(true);
1298
1299         LASSERT(lyx_view_, /**/);
1300         if (!lyx_view_->currentBufferView())
1301                 return _("Welcome to LyX!");
1302
1303         return lyx_view_->currentBufferView()->cursor().currentState();
1304 }
1305
1306
1307 bool LyXFunc::wasMetaKey() const
1308 {
1309         return (meta_fake_bit != NoModifier);
1310 }
1311
1312
1313 namespace {
1314
1315 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1316 {
1317         // Why the switch you might ask. It is a trick to ensure that all
1318         // the elements in the LyXRCTags enum is handled. As you can see
1319         // there are no breaks at all. So it is just a huge fall-through.
1320         // The nice thing is that we will get a warning from the compiler
1321         // if we forget an element.
1322         LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1323         switch (tag) {
1324         case LyXRC::RC_ACCEPT_COMPOUND:
1325         case LyXRC::RC_ALT_LANG:
1326         case LyXRC::RC_PLAINTEXT_LINELEN:
1327         case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1328         case LyXRC::RC_AUTOCORRECTION_MATH:
1329         case LyXRC::RC_AUTOREGIONDELETE:
1330         case LyXRC::RC_AUTORESET_OPTIONS:
1331         case LyXRC::RC_AUTOSAVE:
1332         case LyXRC::RC_AUTO_NUMBER:
1333         case LyXRC::RC_BACKUPDIR_PATH:
1334         case LyXRC::RC_BIBTEX_ALTERNATIVES:
1335         case LyXRC::RC_BIBTEX_COMMAND:
1336         case LyXRC::RC_BINDFILE:
1337         case LyXRC::RC_CHECKLASTFILES:
1338         case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1339         case LyXRC::RC_COMPLETION_INLINE_DELAY:
1340         case LyXRC::RC_COMPLETION_INLINE_DOTS:
1341         case LyXRC::RC_COMPLETION_INLINE_MATH:
1342         case LyXRC::RC_COMPLETION_INLINE_TEXT:
1343         case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1344         case LyXRC::RC_COMPLETION_POPUP_DELAY:
1345         case LyXRC::RC_COMPLETION_POPUP_MATH:
1346         case LyXRC::RC_COMPLETION_POPUP_TEXT:
1347         case LyXRC::RC_USELASTFILEPOS:
1348         case LyXRC::RC_LOADSESSION:
1349         case LyXRC::RC_CHKTEX_COMMAND:
1350         case LyXRC::RC_CONVERTER:
1351         case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1352         case LyXRC::RC_COPIER:
1353         case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1354         case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1355         case LyXRC::RC_DATE_INSERT_FORMAT:
1356         case LyXRC::RC_DEFAULT_LANGUAGE:
1357         case LyXRC::RC_GUI_LANGUAGE:
1358         case LyXRC::RC_DEFAULT_PAPERSIZE:
1359         case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1360         case LyXRC::RC_DEFFILE:
1361         case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1362         case LyXRC::RC_DISPLAY_GRAPHICS:
1363         case LyXRC::RC_DOCUMENTPATH:
1364                 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1365                         FileName path(lyxrc_new.document_path);
1366                         if (path.exists() && path.isDirectory())
1367                                 package().document_dir() = FileName(lyxrc.document_path);
1368                 }
1369         case LyXRC::RC_EDITOR_ALTERNATIVES:
1370         case LyXRC::RC_ESC_CHARS:
1371         case LyXRC::RC_EXAMPLEPATH:
1372         case LyXRC::RC_FONT_ENCODING:
1373         case LyXRC::RC_FORMAT:
1374         case LyXRC::RC_GROUP_LAYOUTS:
1375         case LyXRC::RC_HUNSPELLDIR_PATH:
1376         case LyXRC::RC_INDEX_ALTERNATIVES:
1377         case LyXRC::RC_INDEX_COMMAND:
1378         case LyXRC::RC_JBIBTEX_COMMAND:
1379         case LyXRC::RC_JINDEX_COMMAND:
1380         case LyXRC::RC_NOMENCL_COMMAND:
1381         case LyXRC::RC_INPUT:
1382         case LyXRC::RC_KBMAP:
1383         case LyXRC::RC_KBMAP_PRIMARY:
1384         case LyXRC::RC_KBMAP_SECONDARY:
1385         case LyXRC::RC_LABEL_INIT_LENGTH:
1386         case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1387         case LyXRC::RC_LANGUAGE_AUTO_END:
1388         case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1389         case LyXRC::RC_LANGUAGE_COMMAND_END:
1390         case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1391         case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1392         case LyXRC::RC_LANGUAGE_PACKAGE:
1393         case LyXRC::RC_LANGUAGE_USE_BABEL:
1394         case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1395         case LyXRC::RC_MACRO_EDIT_STYLE:
1396         case LyXRC::RC_MAKE_BACKUP:
1397         case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1398         case LyXRC::RC_MOUSE_WHEEL_SPEED:
1399         case LyXRC::RC_NUMLASTFILES:
1400         case LyXRC::RC_PARAGRAPH_MARKERS:
1401         case LyXRC::RC_PATH_PREFIX:
1402                 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1403                         prependEnvPath("PATH", lyxrc.path_prefix);
1404                 }
1405         case LyXRC::RC_PERS_DICT:
1406         case LyXRC::RC_PREVIEW:
1407         case LyXRC::RC_PREVIEW_HASHED_LABELS:
1408         case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1409         case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1410         case LyXRC::RC_PRINTCOPIESFLAG:
1411         case LyXRC::RC_PRINTER:
1412         case LyXRC::RC_PRINTEVENPAGEFLAG:
1413         case LyXRC::RC_PRINTEXSTRAOPTIONS:
1414         case LyXRC::RC_PRINTFILEEXTENSION:
1415         case LyXRC::RC_PRINTLANDSCAPEFLAG:
1416         case LyXRC::RC_PRINTODDPAGEFLAG:
1417         case LyXRC::RC_PRINTPAGERANGEFLAG:
1418         case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1419         case LyXRC::RC_PRINTPAPERFLAG:
1420         case LyXRC::RC_PRINTREVERSEFLAG:
1421         case LyXRC::RC_PRINTSPOOL_COMMAND:
1422         case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1423         case LyXRC::RC_PRINTTOFILE:
1424         case LyXRC::RC_PRINTTOPRINTER:
1425         case LyXRC::RC_PRINT_ADAPTOUTPUT:
1426         case LyXRC::RC_PRINT_COMMAND:
1427         case LyXRC::RC_RTL_SUPPORT:
1428         case LyXRC::RC_SCREEN_DPI:
1429         case LyXRC::RC_SCREEN_FONT_ROMAN:
1430         case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1431         case LyXRC::RC_SCREEN_FONT_SANS:
1432         case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1433         case LyXRC::RC_SCREEN_FONT_SCALABLE:
1434         case LyXRC::RC_SCREEN_FONT_SIZES:
1435         case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1436         case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1437         case LyXRC::RC_GEOMETRY_SESSION:
1438         case LyXRC::RC_SCREEN_ZOOM:
1439         case LyXRC::RC_SERVERPIPE:
1440         case LyXRC::RC_SET_COLOR:
1441         case LyXRC::RC_SHOW_BANNER:
1442         case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1443         case LyXRC::RC_SPELL_COMMAND:
1444         case LyXRC::RC_SPELLCHECKER:
1445         case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1446         case LyXRC::RC_SPLITINDEX_COMMAND:
1447         case LyXRC::RC_TEMPDIRPATH:
1448         case LyXRC::RC_TEMPLATEPATH:
1449         case LyXRC::RC_TEX_ALLOWS_SPACES:
1450         case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1451                 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1452                         os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1453                 }
1454         case LyXRC::RC_THESAURUSDIRPATH:
1455         case LyXRC::RC_UIFILE:
1456         case LyXRC::RC_USER_EMAIL:
1457         case LyXRC::RC_USER_NAME:
1458         case LyXRC::RC_USETEMPDIR:
1459         case LyXRC::RC_USE_ALT_LANG:
1460         case LyXRC::RC_USE_CONVERTER_CACHE:
1461         case LyXRC::RC_USE_ESC_CHARS:
1462         case LyXRC::RC_USE_INP_ENC:
1463         case LyXRC::RC_USE_PERS_DICT:
1464         case LyXRC::RC_USE_TOOLTIP:
1465         case LyXRC::RC_USE_PIXMAP_CACHE:
1466         case LyXRC::RC_USE_SPELL_LIB:
1467         case LyXRC::RC_VIEWDVI_PAPEROPTION:
1468         case LyXRC::RC_SORT_LAYOUTS:
1469         case LyXRC::RC_FULL_SCREEN_LIMIT:
1470         case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1471         case LyXRC::RC_FULL_SCREEN_MENUBAR:
1472         case LyXRC::RC_FULL_SCREEN_TABBAR:
1473         case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1474         case LyXRC::RC_FULL_SCREEN_WIDTH:
1475         case LyXRC::RC_VISUAL_CURSOR:
1476         case LyXRC::RC_VIEWER:
1477         case LyXRC::RC_VIEWER_ALTERNATIVES:
1478         case LyXRC::RC_LAST:
1479                 break;
1480         }
1481 }
1482
1483 } // namespace anon
1484 } // namespace lyx