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