3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alfredo Braunstein
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
9 * \author Angus Leeming
11 * \author André Pönitz
14 * \author Martin Vermeer
15 * \author Jürgen Vigna
17 * Full author contact details are available in file CREDITS.
24 #include "LayoutFile.h"
25 #include "BranchList.h"
26 #include "buffer_funcs.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
33 #include "Converter.h"
35 #include "CutAndPaste.h"
36 #include "DispatchResult.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
42 #include "InsetIterator.h"
47 #include "LyXAction.h"
52 #include "Paragraph.h"
53 #include "ParagraphParameters.h"
54 #include "ParIterator.h"
58 #include "SpellChecker.h"
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"
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"
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"
98 using namespace lyx::support;
102 using frontend::LyXView;
104 namespace Alert = frontend::Alert;
109 // This function runs "configure" and then rereads lyx.defaults to
110 // reconfigure the automatic settings.
111 void reconfigure(LyXView * lv, string const & option)
113 // emit message signal.
115 lv->message(_("Running configure..."));
117 // Run configure in user lyx directory
118 PathChanger p(package().user_support());
119 string configure_command = package().configure_command();
120 configure_command += option;
122 int ret = one.startscript(Systemcall::Wait, configure_command);
124 // emit message signal.
126 lv->message(_("Reloading configuration..."));
127 lyxrc.read(libFileSearch(string(), "lyxrc.defaults"));
128 // Re-read packages.lst
129 LaTeXFeatures::getAvailable();
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."));
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."));
146 bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
148 // Try to fix cursor in case it is broken.
149 cursor.fixIfBroken();
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;
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(), /**/);
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)) {
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.
180 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
182 size_t const depth = dit.depth() - (outer ? 1 : 0);
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)
193 return Change::UNCHANGED;
200 : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
205 void LyXFunc::initKeySequences(KeyMap * kb)
207 keyseq = KeySequence(kb, kb);
208 cancel_meta_seq = KeySequence(kb, kb);
212 void LyXFunc::setLyXView(LyXView * lv)
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());
222 void LyXFunc::handleKeyFunc(FuncCode action)
224 char_type c = encoded_last_key;
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(),
234 // Need to clear, in case the minibuffer calls these
237 // copied verbatim from do_accent_char
238 bv->cursor().resetAnchor();
239 bv->processUpdateFlags(Update::FitCursor);
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)
246 LASSERT(lyx_view_, /**/);
247 if (!theSession().bookmarks().isValid(idx))
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)) {
255 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
259 // open may fail, so we need to test it again
260 if (!theBufferList().exists(bm.filename))
263 // bm can be changed when saving
264 BookmarksSection::Bookmark tmp = bm;
266 // Special case idx == 0 used for back-from-back jump navigation
268 dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
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) {
275 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
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))
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();
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);
303 void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
305 LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
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();
314 if (keysym.isModifier()) {
315 LYXERR(Debug::KEY, "isModifier true");
317 lyx_view_->restartCursor();
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();
327 // Do a one-deep top-level lookup for
328 // cancel and meta-fake keys. RVDK_PATCH_5
329 cancel_meta_seq.reset();
331 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
332 LYXERR(Debug::KEY, "action first set to [" << func.action << ']');
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 << ']');
343 // Dont remove this unless you know what you are doing.
344 meta_fake_bit = NoModifier;
346 // Can this happen now ?
347 if (func.action == LFUN_NOACTION)
348 func = FuncRequest(LFUN_COMMAND_PREFIX);
350 LYXERR(Debug::KEY, " Key [action=" << func.action << "]["
351 << keyseq.print(KeySequence::Portable) << ']');
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)
357 if (keyseq.length() > 1)
358 lyx_view_->message(keyseq.print(KeySequence::ForGui));
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);
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
373 if (keysym.isText() && keyseq.length() == 1) {
374 LYXERR(Debug::KEY, "isText() is true, inserting.");
375 func = FuncRequest(LFUN_SELF_INSERT,
376 FuncRequest::KEYBOARD);
378 LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
379 lyx_view_->message(_("Unknown function."));
380 lyx_view_->restartCursor();
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) << "']");
400 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
402 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
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.
410 If this code is moved somewhere else (like in
411 GuiView::getStatus), then several functions will not be
414 frontend::LyXView * lv = 0;
417 && (cmd.origin != FuncRequest::MENU || lyx_view_->hasFocus())) {
419 if (lyx_view_->documentBufferView())
420 buf = &lyx_view_->documentBufferView()->buffer();
423 if (cmd.action == LFUN_NOACTION) {
424 flag.message(from_utf8(N_("Nothing to do")));
425 flag.setEnabled(false);
429 switch (cmd.action) {
430 case LFUN_UNKNOWN_ACTION:
432 flag.setEnabled(false);
439 if (flag.unknown()) {
440 flag.message(from_utf8(N_("Unknown action")));
444 if (!flag.enabled()) {
445 if (flag.message().empty())
446 flag.message(from_utf8(N_("Command disabled")));
450 // Check whether we need a buffer
451 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
453 flag.message(from_utf8(N_("Command not allowed with"
454 "out any document open")));
455 flag.setEnabled(false);
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')
464 switch (cmd.action) {
466 case LFUN_CITATION_INSERT: {
467 FuncRequest fr(LFUN_INSET_INSERT, "citation");
468 enable = getStatus(fr).enabled();
472 // This could be used for the no-GUI version. The GUI version is handled in
473 // LyXView::getStatus(). See above.
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());
483 case LFUN_BUFFER_WRITE_ALL: {
484 // We enable the command only if there are some modified buffers
485 Buffer * first = theBufferList().first();
490 // We cannot use a for loop as the buffer list is a cycle.
496 b = theBufferList().next(b);
497 } while (b != first);
501 case LFUN_BOOKMARK_GOTO: {
502 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
503 enable = theSession().bookmarks().isValid(num);
507 case LFUN_BOOKMARK_CLEAR:
508 enable = theSession().bookmarks().hasValid();
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);
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()) {
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
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);
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
557 case LFUN_COMMAND_PREFIX:
559 case LFUN_META_PREFIX:
560 case LFUN_BUFFER_CLOSE:
561 case LFUN_RECONFIGURE:
563 case LFUN_DROP_LAYOUTS_CHOICE:
564 case LFUN_SERVER_GET_FILENAME:
565 case LFUN_SERVER_NOTIFY:
566 case LFUN_SERVER_GOTO_FILE_ROW:
567 case LFUN_BUFFER_CHILD_OPEN:
568 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
569 case LFUN_KEYMAP_OFF:
570 case LFUN_KEYMAP_PRIMARY:
571 case LFUN_KEYMAP_SECONDARY:
572 case LFUN_KEYMAP_TOGGLE:
574 case LFUN_PREFERENCES_SAVE:
575 case LFUN_INSET_EDIT:
576 case LFUN_TEXTCLASS_APPLY:
577 case LFUN_TEXTCLASS_LOAD:
578 case LFUN_BUFFER_SAVE_AS_DEFAULT:
579 case LFUN_BUFFER_PARAMS_APPLY:
580 case LFUN_LAYOUT_MODULES_CLEAR:
581 case LFUN_LAYOUT_MODULE_ADD:
582 case LFUN_LAYOUT_RELOAD:
583 case LFUN_LYXRC_APPLY:
584 // these are handled in our dispatch()
592 if (theApp()->getStatus(cmd, flag))
595 // Does the view know something?
600 if (lv->getStatus(cmd, flag))
603 BufferView * bv = lv->currentBufferView();
604 BufferView * doc_bv = lv->documentBufferView();
605 // If we do not have a BufferView, then other functions are disabled
610 // Is this a function that acts on inset at point?
611 Inset * inset = bv->cursor().nextInset();
612 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
613 && inset && inset->getStatus(bv->cursor(), cmd, flag))
616 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
618 // try the BufferView
619 decided = bv->getStatus(cmd, flag);
622 decided = bv->buffer().getStatus(cmd, flag);
623 if (!decided && doc_bv)
624 // try the Document Buffer
625 decided = doc_bv->buffer().getStatus(cmd, flag);
629 flag.setEnabled(false);
631 // Can we use a readonly buffer?
632 if (buf && buf->isReadonly()
633 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
634 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
635 flag.message(from_utf8(N_("Document is read-only")));
636 flag.setEnabled(false);
639 // Are we in a DELETED change-tracking region?
640 if (lyx_view_ && lyx_view_->documentBufferView()
641 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
643 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
644 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
645 flag.message(from_utf8(N_("This portion of the document is deleted.")));
646 flag.setEnabled(false);
649 // the default error message if we disable the command
650 if (!flag.enabled() && flag.message().empty())
651 flag.message(from_utf8(N_("Command disabled")));
659 bool loadLayoutFile(string const & name, string const & buf_path)
661 if (!LayoutFileList::get().haveClass(name)) {
662 lyxerr << "Document class \"" << name
663 << "\" does not exist."
668 LayoutFile & tc = LayoutFileList::get()[name];
669 if (!tc.load(buf_path)) {
670 docstring s = bformat(_("The document class %1$s "
671 "could not be loaded."), from_utf8(name));
672 Alert::error(_("Could not load class"), s);
679 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
684 void LyXFunc::dispatch(FuncRequest const & cmd)
686 string const argument = to_utf8(cmd.argument());
687 FuncCode const action = cmd.action;
689 LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
690 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
692 // we have not done anything wrong yet.
694 dispatch_buffer.erase();
696 // redraw the screen at the end (first of the two drawing steps).
697 //This is done unless explicitely requested otherwise
698 Update::flags updateFlags = Update::FitCursor;
700 FuncStatus const flag = getStatus(cmd);
701 if (!flag.enabled()) {
702 // We cannot use this function here
703 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
704 << lyxaction.getActionName(action)
705 << " [" << action << "] is disabled at this location");
706 setErrorMessage(flag.message());
708 lyx_view_->restartCursor();
711 if (lyx_view_ && lyx_view_->currentBufferView())
712 buffer = &lyx_view_->currentBufferView()->buffer();
715 case LFUN_COMMAND_PREFIX:
716 LASSERT(lyx_view_, /**/);
717 lyx_view_->message(keyseq.printOptions(true));
721 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
723 meta_fake_bit = NoModifier;
725 // cancel any selection
726 dispatch(FuncRequest(LFUN_MARK_OFF));
727 setMessage(from_ascii(N_("Cancel")));
730 case LFUN_META_PREFIX:
731 meta_fake_bit = AltModifier;
732 setMessage(keyseq.print(KeySequence::ForGui));
735 // --- Menus -----------------------------------------------
736 case LFUN_BUFFER_CLOSE:
737 lyx_view_->closeBuffer();
739 updateFlags = Update::None;
742 case LFUN_BUFFER_CLOSE_ALL:
743 lyx_view_->closeBufferAll();
745 updateFlags = Update::None;
748 case LFUN_RECONFIGURE:
749 // argument is any additional parameter to the configure.py command
750 reconfigure(lyx_view_, argument);
753 case LFUN_HELP_OPEN: {
755 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
756 string const arg = argument;
758 setErrorMessage(from_utf8(N_("Missing argument")));
761 FileName fname = i18nLibFileSearch("doc", arg, "lyx");
763 fname = i18nLibFileSearch("examples", arg, "lyx");
766 lyxerr << "LyX: unable to find documentation file `"
767 << arg << "'. Bad installation?" << endl;
770 lyx_view_->message(bformat(_("Opening help file %1$s..."),
771 makeDisplayPath(fname.absFilename())));
772 Buffer * buf = lyx_view_->loadDocument(fname, false);
775 lyx_view_->setBuffer(buf);
776 buf->errors("Parse");
778 updateFlags = Update::None;
782 // --- lyxserver commands ----------------------------
783 case LFUN_SERVER_GET_FILENAME:
784 LASSERT(lyx_view_ && buffer, /**/);
785 setMessage(from_utf8(buffer->absFileName()));
786 LYXERR(Debug::INFO, "FNAME["
787 << buffer->absFileName() << ']');
790 case LFUN_SERVER_NOTIFY:
791 dispatch_buffer = keyseq.print(KeySequence::Portable);
792 theServer().notifyClient(to_utf8(dispatch_buffer));
795 case LFUN_SERVER_GOTO_FILE_ROW: {
796 LASSERT(lyx_view_, /**/);
799 istringstream is(argument);
800 is >> file_name >> row;
801 file_name = os::internal_path(file_name);
804 string const abstmp = package().temp_dir().absFilename();
805 string const realtmp = package().temp_dir().realPath();
806 // We have to use os::path_prefix_is() here, instead of
807 // simply prefixIs(), because the file name comes from
808 // an external application and may need case adjustment.
809 if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
810 || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
811 // Needed by inverse dvi search. If it is a file
812 // in tmpdir, call the apropriated function.
813 // If tmpdir is a symlink, we may have the real
814 // path passed back, so we correct for that.
815 if (!prefixIs(file_name, abstmp))
816 file_name = subst(file_name, realtmp, abstmp);
817 buf = theBufferList().getBufferFromTmp(file_name);
819 // Must replace extension of the file to be .lyx
821 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
822 // Either change buffer or load the file
823 if (theBufferList().exists(s))
824 buf = theBufferList().getBuffer(s);
825 else if (s.exists()) {
826 buf = lyx_view_->loadDocument(s);
829 lyx_view_->message(bformat(
830 _("File does not exist: %1$s"),
831 makeDisplayPath(file_name)));
835 updateFlags = Update::None;
840 lyx_view_->setBuffer(buf);
841 lyx_view_->documentBufferView()->setCursorFromRow(row);
843 buf->errors("Parse");
844 updateFlags = Update::FitCursor;
849 case LFUN_DIALOG_SHOW_NEW_INSET: {
850 LASSERT(lyx_view_, /**/);
851 string const name = cmd.getArg(0);
852 InsetCode code = insetCode(name);
853 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
854 bool insetCodeOK = true;
861 case NOMENCL_PRINT_CODE:
864 case HYPERLINK_CODE: {
865 InsetCommandParams p(code);
866 data = InsetCommand::params2string(name, p);
870 // data is the include type: one of "include",
871 // "input", "verbatiminput" or "verbatiminput*"
873 // default type is requested
875 InsetCommandParams p(INCLUDE_CODE, data);
876 data = InsetCommand::params2string("include", p);
880 // \c data == "Boxed" || "Frameless" etc
881 InsetBoxParams p(data);
882 data = InsetBox::params2string(p);
887 data = InsetBranch::params2string(p);
891 InsetCommandParams p(CITE_CODE);
892 data = InsetCommand::params2string(name, p);
896 data = InsetERT::params2string(InsetCollapsable::Open);
899 case EXTERNAL_CODE: {
900 InsetExternalParams p;
901 data = InsetExternal::params2string(p, *buffer);
906 data = InsetFloat::params2string(p);
909 case LISTINGS_CODE: {
910 InsetListingsParams p;
911 data = InsetListings::params2string(p);
914 case GRAPHICS_CODE: {
915 InsetGraphicsParams p;
916 data = InsetGraphics::params2string(p, *buffer);
921 data = InsetNote::params2string(p);
925 InsetPhantomParams p;
926 data = InsetPhantom::params2string(p);
931 data = InsetSpace::params2string(p);
936 data = InsetVSpace::params2string(space);
941 data = InsetWrap::params2string(p);
945 lyxerr << "Inset type '" << name <<
946 "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << endl;
949 } // end switch(code)
951 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
955 case LFUN_CITATION_INSERT: {
956 LASSERT(lyx_view_, /**/);
957 if (!argument.empty()) {
958 // we can have one optional argument, delimited by '|'
959 // citation-insert <key>|<text_before>
960 // this should be enhanced to also support text_after
961 // and citation style
962 string arg = argument;
964 if (contains(argument, "|")) {
965 arg = token(argument, '|', 0);
966 opt1 = token(argument, '|', 1);
968 InsetCommandParams icp(CITE_CODE);
969 icp["key"] = from_utf8(arg);
971 icp["before"] = from_utf8(opt1);
972 string icstr = InsetCommand::params2string("citation", icp);
973 FuncRequest fr(LFUN_INSET_INSERT, icstr);
976 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
980 case LFUN_BUFFER_CHILD_OPEN: {
981 LASSERT(lyx_view_ && buffer, /**/);
982 FileName filename = makeAbsPath(argument, buffer->filePath());
983 lyx_view_->documentBufferView()->saveBookmark(false);
986 if (theBufferList().exists(filename)) {
987 child = theBufferList().getBuffer(filename);
989 setMessage(bformat(_("Opening child document %1$s..."),
990 makeDisplayPath(filename.absFilename())));
991 child = lyx_view_->loadDocument(filename, false);
995 // Set the parent name of the child document.
996 // This makes insertion of citations and references in the child work,
997 // when the target is in the parent or another child document.
998 child->setParent(buffer);
999 child->masterBuffer()->updateLabels();
1000 lyx_view_->setBuffer(child);
1002 child->errors("Parse");
1005 // If a screen update is required (in case where auto_open is false),
1006 // setBuffer() would have taken care of it already. Otherwise we shall
1007 // reset the update flag because it can cause a circular problem.
1009 updateFlags = Update::None;
1013 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
1014 LASSERT(lyx_view_, /**/);
1015 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1018 case LFUN_KEYMAP_OFF:
1019 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1020 lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
1023 case LFUN_KEYMAP_PRIMARY:
1024 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1025 lyx_view_->currentBufferView()->getIntl().keyMapPrim();
1028 case LFUN_KEYMAP_SECONDARY:
1029 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1030 lyx_view_->currentBufferView()->getIntl().keyMapSec();
1033 case LFUN_KEYMAP_TOGGLE:
1034 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1035 lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
1041 string rest = split(argument, countstr, ' ');
1042 istringstream is(countstr);
1045 //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1046 for (int i = 0; i < count; ++i)
1047 dispatch(lyxaction.lookupFunc(rest));
1051 case LFUN_COMMAND_SEQUENCE: {
1052 // argument contains ';'-terminated commands
1053 string arg = argument;
1054 if (theBufferList().isLoaded(buffer))
1055 buffer->undo().beginUndoGroup();
1056 while (!arg.empty()) {
1058 arg = split(arg, first, ';');
1059 FuncRequest func(lyxaction.lookupFunc(first));
1060 func.origin = cmd.origin;
1063 if (theBufferList().isLoaded(buffer))
1064 buffer->undo().endUndoGroup();
1068 case LFUN_COMMAND_ALTERNATIVES: {
1069 // argument contains ';'-terminated commands
1070 string arg = argument;
1071 while (!arg.empty()) {
1073 arg = split(arg, first, ';');
1074 FuncRequest func(lyxaction.lookupFunc(first));
1075 func.origin = cmd.origin;
1076 FuncStatus stat = getStatus(func);
1077 if (stat.enabled()) {
1087 if (theTopLevelCmdDef().lock(argument, func)) {
1088 func.origin = cmd.origin;
1090 theTopLevelCmdDef().release(argument);
1092 if (func.action == LFUN_UNKNOWN_ACTION) {
1093 // unknown command definition
1094 lyxerr << "Warning: unknown command definition `"
1098 // recursion detected
1099 lyxerr << "Warning: Recursion in the command definition `"
1100 << argument << "' detected"
1107 case LFUN_PREFERENCES_SAVE: {
1108 lyxrc.write(makeAbsPath("preferences",
1109 package().user_support().absFilename()),
1114 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1115 string const fname =
1116 addName(addPath(package().user_support().absFilename(), "templates/"),
1118 Buffer defaults(fname);
1120 istringstream ss(argument);
1123 int const unknown_tokens = defaults.readHeader(lex);
1125 if (unknown_tokens != 0) {
1126 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1127 << unknown_tokens << " unknown token"
1128 << (unknown_tokens == 1 ? "" : "s")
1132 if (defaults.writeFile(FileName(defaults.absFileName())))
1133 setMessage(bformat(_("Document defaults saved in %1$s"),
1134 makeDisplayPath(fname)));
1136 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1140 case LFUN_BUFFER_PARAMS_APPLY: {
1141 LASSERT(lyx_view_, /**/);
1143 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1144 Cursor & cur = lyx_view_->documentBufferView()->cursor();
1145 cur.recordUndoFullDocument();
1147 istringstream ss(argument);
1150 int const unknown_tokens = buffer->readHeader(lex);
1152 if (unknown_tokens != 0) {
1153 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1154 << unknown_tokens << " unknown token"
1155 << (unknown_tokens == 1 ? "" : "s")
1159 updateLayout(oldClass, buffer);
1161 updateFlags = Update::Force | Update::FitCursor;
1162 // We are most certainly here because of a change in the document
1163 // It is then better to make sure that all dialogs are in sync with
1164 // current document settings. LyXView::restartCursor() achieve this.
1165 lyx_view_->restartCursor();
1169 case LFUN_LAYOUT_MODULES_CLEAR: {
1170 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1171 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1172 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1173 buffer->params().clearLayoutModules();
1174 buffer->params().makeDocumentClass();
1175 updateLayout(oldClass, buffer);
1176 updateFlags = Update::Force | Update::FitCursor;
1180 case LFUN_LAYOUT_MODULE_ADD: {
1181 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1182 BufferParams const & params = buffer->params();
1183 if (!params.moduleCanBeAdded(argument)) {
1184 LYXERR0("Module `" << argument <<
1185 "' cannot be added due to failed requirements or "
1186 "conflicts with installed modules.");
1189 DocumentClass const * const oldClass = params.documentClassPtr();
1190 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1191 buffer->params().addLayoutModule(argument);
1192 buffer->params().makeDocumentClass();
1193 updateLayout(oldClass, buffer);
1194 updateFlags = Update::Force | Update::FitCursor;
1198 case LFUN_TEXTCLASS_APPLY: {
1199 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1201 if (!loadLayoutFile(argument, buffer->temppath()) &&
1202 !loadLayoutFile(argument, buffer->filePath()))
1205 LayoutFile const * old_layout = buffer->params().baseClass();
1206 LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1208 if (old_layout == new_layout)
1212 //Save the old, possibly modular, layout for use in conversion.
1213 DocumentClass const * const oldDocClass =
1214 buffer->params().documentClassPtr();
1215 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1216 buffer->params().setBaseClass(argument);
1217 buffer->params().makeDocumentClass();
1218 updateLayout(oldDocClass, buffer);
1219 updateFlags = Update::Force | Update::FitCursor;
1223 case LFUN_LAYOUT_RELOAD: {
1224 LASSERT(lyx_view_, /**/);
1225 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1226 LayoutFileIndex bc = buffer->params().baseClassID();
1227 LayoutFileList::get().reset(bc);
1228 buffer->params().setBaseClass(bc);
1229 buffer->params().makeDocumentClass();
1230 updateLayout(oldClass, buffer);
1231 updateFlags = Update::Force | Update::FitCursor;
1235 case LFUN_TEXTCLASS_LOAD:
1236 loadLayoutFile(argument, buffer->temppath()) ||
1237 loadLayoutFile(argument, buffer->filePath());
1240 case LFUN_LYXRC_APPLY: {
1241 // reset active key sequences, since the bindings
1242 // are updated (bug 6064)
1244 LyXRC const lyxrc_orig = lyxrc;
1246 istringstream ss(argument);
1247 bool const success = lyxrc.read(ss) == 0;
1250 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1251 << "Unable to read lyxrc data"
1256 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1260 theApp()->resetGui();
1262 /// We force the redraw in any case because there might be
1263 /// some screen font changes.
1264 /// FIXME: only the current view will be updated. the Gui
1265 /// class is able to furnish the list of views.
1266 updateFlags = Update::Force;
1270 case LFUN_BOOKMARK_GOTO:
1271 // go to bookmark, open unopened file and switch to buffer if necessary
1272 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1273 updateFlags = Update::FitCursor;
1276 case LFUN_BOOKMARK_CLEAR:
1277 theSession().bookmarks().clear();
1281 LASSERT(theApp(), /**/);
1282 // Let the frontend dispatch its own actions.
1283 if (theApp()->dispatch(cmd))
1284 // Nothing more to do.
1287 // Everything below is only for active lyx_view_
1291 // Start an undo group. This may be needed for
1292 // some stuff like inset-apply on labels.
1293 if (theBufferList().isLoaded(buffer))
1294 buffer->undo().beginUndoGroup();
1296 // Let the current LyXView dispatch its own actions.
1297 if (lyx_view_->dispatch(cmd)) {
1298 if (lyx_view_->currentBufferView()) {
1299 updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1300 if (theBufferList().isLoaded(buffer))
1301 buffer->undo().endUndoGroup();
1306 LASSERT(lyx_view_->currentBufferView(), /**/);
1308 // Let the current BufferView dispatch its own actions.
1309 if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1310 // The BufferView took care of its own updates if needed.
1311 updateFlags = Update::None;
1312 if (theBufferList().isLoaded(buffer))
1313 buffer->undo().endUndoGroup();
1317 // OK, so try the Buffer itself
1319 BufferView * bv = lyx_view_->currentBufferView();
1320 bv->buffer().dispatch(cmd, dr);
1321 if (dr.dispatched()) {
1322 updateFlags = dr.update();
1325 // OK, so try with the document Buffer.
1326 BufferView * doc_bv = lyx_view_->documentBufferView();
1328 buffer = &(doc_bv->buffer());
1329 buffer->dispatch(cmd, dr);
1330 if (dr.dispatched()) {
1331 updateFlags = dr.update();
1336 // Is this a function that acts on inset at point?
1337 Inset * inset = bv->cursor().nextInset();
1338 if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1340 bv->cursor().result().dispatched(true);
1341 bv->cursor().result().update(Update::FitCursor | Update::Force);
1342 FuncRequest tmpcmd = cmd;
1343 inset->dispatch(bv->cursor(), tmpcmd);
1344 if (bv->cursor().result().dispatched()) {
1345 updateFlags = bv->cursor().result().update();
1350 // Let the current Cursor dispatch its own actions.
1351 Cursor old = bv->cursor();
1352 bv->cursor().getPos(cursorPosBeforeDispatchX_,
1353 cursorPosBeforeDispatchY_);
1354 bv->cursor().dispatch(cmd);
1356 // notify insets we just left
1357 if (bv->cursor() != old) {
1359 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1361 bv->cursor().fixIfBroken();
1364 if (theBufferList().isLoaded(buffer))
1365 buffer->undo().endUndoGroup();
1367 // update completion. We do it here and not in
1368 // processKeySym to avoid another redraw just for a
1369 // changed inline completion
1370 if (cmd.origin == FuncRequest::KEYBOARD) {
1371 if (cmd.action == LFUN_SELF_INSERT
1372 || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1373 lyx_view_->updateCompletion(bv->cursor(), true, true);
1374 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1375 lyx_view_->updateCompletion(bv->cursor(), false, true);
1377 lyx_view_->updateCompletion(bv->cursor(), false, false);
1380 updateFlags = bv->cursor().result().update();
1383 // if we executed a mutating lfun, mark the buffer as dirty
1384 if (theBufferList().isLoaded(buffer) && flag.enabled()
1385 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1386 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1387 buffer->markDirty();
1389 if (lyx_view_ && lyx_view_->currentBufferView()) {
1390 // BufferView::update() updates the ViewMetricsInfo and
1391 // also initializes the position cache for all insets in
1392 // (at least partially) visible top-level paragraphs.
1393 // We will redraw the screen only if needed.
1394 lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1396 // Do we have a selection?
1397 theSelection().haveSelection(
1398 lyx_view_->currentBufferView()->cursor().selection());
1401 lyx_view_->restartCursor();
1405 // Some messages may already be translated, so we cannot use _()
1406 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1411 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1413 const bool verbose = (cmd.origin == FuncRequest::MENU
1414 || cmd.origin == FuncRequest::TOOLBAR
1415 || cmd.origin == FuncRequest::COMMANDBUFFER);
1417 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1418 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1420 lyx_view_->message(msg);
1424 docstring dispatch_msg = msg;
1425 if (!dispatch_msg.empty())
1426 dispatch_msg += ' ';
1428 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1430 bool argsadded = false;
1432 if (!cmd.argument().empty()) {
1433 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1434 comname += ' ' + cmd.argument();
1439 docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1441 if (!shortcuts.empty())
1442 comname += ": " + shortcuts;
1443 else if (!argsadded && !cmd.argument().empty())
1444 comname += ' ' + cmd.argument();
1446 if (!comname.empty()) {
1447 comname = rtrim(comname);
1448 dispatch_msg += '(' + rtrim(comname) + ')';
1451 LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1452 if (!dispatch_msg.empty())
1453 lyx_view_->message(dispatch_msg);
1457 // Each "lyx_view_" should have it's own message method. lyxview and
1458 // the minibuffer would use the minibuffer, but lyxserver would
1459 // send an ERROR signal to its client. Alejandro 970603
1460 // This function is bit problematic when it comes to NLS, to make the
1461 // lyx servers client be language indepenent we must not translate
1462 // strings sent to this func.
1463 void LyXFunc::setErrorMessage(docstring const & m) const
1465 dispatch_buffer = m;
1470 void LyXFunc::setMessage(docstring const & m) const
1472 dispatch_buffer = m;
1476 docstring LyXFunc::viewStatusMessage()
1478 // When meta-fake key is pressed, show the key sequence so far + "M-".
1480 return keyseq.print(KeySequence::ForGui) + "M-";
1482 // Else, when a non-complete key sequence is pressed,
1483 // show the available options.
1484 if (keyseq.length() > 0 && !keyseq.deleted())
1485 return keyseq.printOptions(true);
1487 LASSERT(lyx_view_, /**/);
1488 if (!lyx_view_->currentBufferView())
1489 return _("Welcome to LyX!");
1491 return lyx_view_->currentBufferView()->cursor().currentState();
1495 bool LyXFunc::wasMetaKey() const
1497 return (meta_fake_bit != NoModifier);
1501 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1503 lyx_view_->message(_("Converting document to new document class..."));
1505 StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1506 ErrorList & el = buf->errorList("Class Switch");
1507 cap::switchBetweenClasses(
1508 oldlayout, buf->params().documentClassPtr(),
1509 static_cast<InsetText &>(buf->inset()), el);
1511 lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1513 buf->errors("Class Switch");
1514 buf->updateLabels();
1520 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1522 // Why the switch you might ask. It is a trick to ensure that all
1523 // the elements in the LyXRCTags enum is handled. As you can see
1524 // there are no breaks at all. So it is just a huge fall-through.
1525 // The nice thing is that we will get a warning from the compiler
1526 // if we forget an element.
1527 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1529 case LyXRC::RC_ACCEPT_COMPOUND:
1530 case LyXRC::RC_ALT_LANG:
1531 case LyXRC::RC_PLAINTEXT_LINELEN:
1532 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1533 case LyXRC::RC_AUTOCORRECTION_MATH:
1534 case LyXRC::RC_AUTOREGIONDELETE:
1535 case LyXRC::RC_AUTORESET_OPTIONS:
1536 case LyXRC::RC_AUTOSAVE:
1537 case LyXRC::RC_AUTO_NUMBER:
1538 case LyXRC::RC_BACKUPDIR_PATH:
1539 case LyXRC::RC_BIBTEX_ALTERNATIVES:
1540 case LyXRC::RC_BIBTEX_COMMAND:
1541 case LyXRC::RC_BINDFILE:
1542 case LyXRC::RC_CHECKLASTFILES:
1543 case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1544 case LyXRC::RC_COMPLETION_INLINE_DELAY:
1545 case LyXRC::RC_COMPLETION_INLINE_DOTS:
1546 case LyXRC::RC_COMPLETION_INLINE_MATH:
1547 case LyXRC::RC_COMPLETION_INLINE_TEXT:
1548 case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1549 case LyXRC::RC_COMPLETION_POPUP_DELAY:
1550 case LyXRC::RC_COMPLETION_POPUP_MATH:
1551 case LyXRC::RC_COMPLETION_POPUP_TEXT:
1552 case LyXRC::RC_USELASTFILEPOS:
1553 case LyXRC::RC_LOADSESSION:
1554 case LyXRC::RC_CHKTEX_COMMAND:
1555 case LyXRC::RC_CONVERTER:
1556 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1557 case LyXRC::RC_COPIER:
1558 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1559 case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1560 case LyXRC::RC_DATE_INSERT_FORMAT:
1561 case LyXRC::RC_DEFAULT_LANGUAGE:
1562 case LyXRC::RC_GUI_LANGUAGE:
1563 case LyXRC::RC_DEFAULT_PAPERSIZE:
1564 case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1565 case LyXRC::RC_DEFFILE:
1566 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1567 case LyXRC::RC_DISPLAY_GRAPHICS:
1568 case LyXRC::RC_DOCUMENTPATH:
1569 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1570 FileName path(lyxrc_new.document_path);
1571 if (path.exists() && path.isDirectory())
1572 package().document_dir() = FileName(lyxrc.document_path);
1574 case LyXRC::RC_EDITOR_ALTERNATIVES:
1575 case LyXRC::RC_ESC_CHARS:
1576 case LyXRC::RC_EXAMPLEPATH:
1577 case LyXRC::RC_FONT_ENCODING:
1578 case LyXRC::RC_FORMAT:
1579 case LyXRC::RC_GROUP_LAYOUTS:
1580 case LyXRC::RC_HUNSPELLDIR_PATH:
1581 case LyXRC::RC_INDEX_ALTERNATIVES:
1582 case LyXRC::RC_INDEX_COMMAND:
1583 case LyXRC::RC_JBIBTEX_COMMAND:
1584 case LyXRC::RC_JINDEX_COMMAND:
1585 case LyXRC::RC_NOMENCL_COMMAND:
1586 case LyXRC::RC_INPUT:
1587 case LyXRC::RC_KBMAP:
1588 case LyXRC::RC_KBMAP_PRIMARY:
1589 case LyXRC::RC_KBMAP_SECONDARY:
1590 case LyXRC::RC_LABEL_INIT_LENGTH:
1591 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1592 case LyXRC::RC_LANGUAGE_AUTO_END:
1593 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1594 case LyXRC::RC_LANGUAGE_COMMAND_END:
1595 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1596 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1597 case LyXRC::RC_LANGUAGE_PACKAGE:
1598 case LyXRC::RC_LANGUAGE_USE_BABEL:
1599 case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1600 case LyXRC::RC_MACRO_EDIT_STYLE:
1601 case LyXRC::RC_MAKE_BACKUP:
1602 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1603 case LyXRC::RC_MOUSE_WHEEL_SPEED:
1604 case LyXRC::RC_NUMLASTFILES:
1605 case LyXRC::RC_PARAGRAPH_MARKERS:
1606 case LyXRC::RC_PATH_PREFIX:
1607 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1608 prependEnvPath("PATH", lyxrc.path_prefix);
1610 case LyXRC::RC_PERS_DICT:
1611 case LyXRC::RC_PREVIEW:
1612 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1613 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1614 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1615 case LyXRC::RC_PRINTCOPIESFLAG:
1616 case LyXRC::RC_PRINTER:
1617 case LyXRC::RC_PRINTEVENPAGEFLAG:
1618 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1619 case LyXRC::RC_PRINTFILEEXTENSION:
1620 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1621 case LyXRC::RC_PRINTODDPAGEFLAG:
1622 case LyXRC::RC_PRINTPAGERANGEFLAG:
1623 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1624 case LyXRC::RC_PRINTPAPERFLAG:
1625 case LyXRC::RC_PRINTREVERSEFLAG:
1626 case LyXRC::RC_PRINTSPOOL_COMMAND:
1627 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1628 case LyXRC::RC_PRINTTOFILE:
1629 case LyXRC::RC_PRINTTOPRINTER:
1630 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1631 case LyXRC::RC_PRINT_COMMAND:
1632 case LyXRC::RC_RTL_SUPPORT:
1633 case LyXRC::RC_SCREEN_DPI:
1634 case LyXRC::RC_SCREEN_FONT_ROMAN:
1635 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1636 case LyXRC::RC_SCREEN_FONT_SANS:
1637 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1638 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1639 case LyXRC::RC_SCREEN_FONT_SIZES:
1640 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1641 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1642 case LyXRC::RC_GEOMETRY_SESSION:
1643 case LyXRC::RC_SCREEN_ZOOM:
1644 case LyXRC::RC_SERVERPIPE:
1645 case LyXRC::RC_SET_COLOR:
1646 case LyXRC::RC_SHOW_BANNER:
1647 case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1648 case LyXRC::RC_SPELL_COMMAND:
1649 case LyXRC::RC_SPELLCHECKER:
1650 case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1651 case LyXRC::RC_SPLITINDEX_COMMAND:
1652 case LyXRC::RC_TEMPDIRPATH:
1653 case LyXRC::RC_TEMPLATEPATH:
1654 case LyXRC::RC_TEX_ALLOWS_SPACES:
1655 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1656 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1657 os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1659 case LyXRC::RC_THESAURUSDIRPATH:
1660 case LyXRC::RC_UIFILE:
1661 case LyXRC::RC_USER_EMAIL:
1662 case LyXRC::RC_USER_NAME:
1663 case LyXRC::RC_USETEMPDIR:
1664 case LyXRC::RC_USE_ALT_LANG:
1665 case LyXRC::RC_USE_CONVERTER_CACHE:
1666 case LyXRC::RC_USE_ESC_CHARS:
1667 case LyXRC::RC_USE_INP_ENC:
1668 case LyXRC::RC_USE_PERS_DICT:
1669 case LyXRC::RC_USE_TOOLTIP:
1670 case LyXRC::RC_USE_PIXMAP_CACHE:
1671 case LyXRC::RC_USE_SPELL_LIB:
1672 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1673 case LyXRC::RC_SORT_LAYOUTS:
1674 case LyXRC::RC_FULL_SCREEN_LIMIT:
1675 case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1676 case LyXRC::RC_FULL_SCREEN_MENUBAR:
1677 case LyXRC::RC_FULL_SCREEN_TABBAR:
1678 case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1679 case LyXRC::RC_FULL_SCREEN_WIDTH:
1680 case LyXRC::RC_VISUAL_CURSOR:
1681 case LyXRC::RC_VIEWER:
1682 case LyXRC::RC_VIEWER_ALTERNATIVES:
1683 case LyXRC::RC_LAST: