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_BUFFER_LANGUAGE:
577 case LFUN_TEXTCLASS_APPLY:
578 case LFUN_TEXTCLASS_LOAD:
579 case LFUN_BUFFER_SAVE_AS_DEFAULT:
580 case LFUN_BUFFER_PARAMS_APPLY:
581 case LFUN_LAYOUT_MODULES_CLEAR:
582 case LFUN_LAYOUT_MODULE_ADD:
583 case LFUN_LAYOUT_RELOAD:
584 case LFUN_LYXRC_APPLY:
585 // these are handled in our dispatch()
593 if (theApp()->getStatus(cmd, flag))
596 // Does the view know something?
601 if (lv->getStatus(cmd, flag))
604 BufferView * bv = lv->currentBufferView();
605 BufferView * doc_bv = lv->documentBufferView();
606 // If we do not have a BufferView, then other functions are disabled
611 // Is this a function that acts on inset at point?
612 Inset * inset = bv->cursor().nextInset();
613 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
614 && inset && inset->getStatus(bv->cursor(), cmd, flag))
617 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
619 // try the BufferView
620 decided = bv->getStatus(cmd, flag);
623 decided = bv->buffer().getStatus(cmd, flag);
624 if (!decided && doc_bv)
625 // try the Document Buffer
626 decided = doc_bv->buffer().getStatus(cmd, flag);
630 flag.setEnabled(false);
632 // Can we use a readonly buffer?
633 if (buf && buf->isReadonly()
634 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
635 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
636 flag.message(from_utf8(N_("Document is read-only")));
637 flag.setEnabled(false);
640 // Are we in a DELETED change-tracking region?
641 if (lyx_view_ && lyx_view_->documentBufferView()
642 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
644 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
645 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
646 flag.message(from_utf8(N_("This portion of the document is deleted.")));
647 flag.setEnabled(false);
650 // the default error message if we disable the command
651 if (!flag.enabled() && flag.message().empty())
652 flag.message(from_utf8(N_("Command disabled")));
660 bool loadLayoutFile(string const & name, string const & buf_path)
662 if (!LayoutFileList::get().haveClass(name)) {
663 lyxerr << "Document class \"" << name
664 << "\" does not exist."
669 LayoutFile & tc = LayoutFileList::get()[name];
670 if (!tc.load(buf_path)) {
671 docstring s = bformat(_("The document class %1$s "
672 "could not be loaded."), from_utf8(name));
673 Alert::error(_("Could not load class"), s);
680 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
685 void LyXFunc::dispatch(FuncRequest const & cmd)
687 string const argument = to_utf8(cmd.argument());
688 FuncCode const action = cmd.action;
690 LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
691 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
693 // we have not done anything wrong yet.
695 dispatch_buffer.erase();
697 // redraw the screen at the end (first of the two drawing steps).
698 //This is done unless explicitely requested otherwise
699 Update::flags updateFlags = Update::FitCursor;
701 FuncStatus const flag = getStatus(cmd);
702 if (!flag.enabled()) {
703 // We cannot use this function here
704 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
705 << lyxaction.getActionName(action)
706 << " [" << action << "] is disabled at this location");
707 setErrorMessage(flag.message());
709 lyx_view_->restartCursor();
712 if (lyx_view_ && lyx_view_->currentBufferView())
713 buffer = &lyx_view_->currentBufferView()->buffer();
716 case LFUN_COMMAND_PREFIX:
717 LASSERT(lyx_view_, /**/);
718 lyx_view_->message(keyseq.printOptions(true));
722 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
724 meta_fake_bit = NoModifier;
726 // cancel any selection
727 dispatch(FuncRequest(LFUN_MARK_OFF));
728 setMessage(from_ascii(N_("Cancel")));
731 case LFUN_META_PREFIX:
732 meta_fake_bit = AltModifier;
733 setMessage(keyseq.print(KeySequence::ForGui));
736 // --- Menus -----------------------------------------------
737 case LFUN_BUFFER_CLOSE:
738 lyx_view_->closeBuffer();
740 updateFlags = Update::None;
743 case LFUN_BUFFER_CLOSE_ALL:
744 lyx_view_->closeBufferAll();
746 updateFlags = Update::None;
749 case LFUN_RECONFIGURE:
750 // argument is any additional parameter to the configure.py command
751 reconfigure(lyx_view_, argument);
754 case LFUN_HELP_OPEN: {
756 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
757 string const arg = argument;
759 setErrorMessage(from_utf8(N_("Missing argument")));
762 FileName fname = i18nLibFileSearch("doc", arg, "lyx");
764 fname = i18nLibFileSearch("examples", arg, "lyx");
767 lyxerr << "LyX: unable to find documentation file `"
768 << arg << "'. Bad installation?" << endl;
771 lyx_view_->message(bformat(_("Opening help file %1$s..."),
772 makeDisplayPath(fname.absFilename())));
773 Buffer * buf = lyx_view_->loadDocument(fname, false);
776 lyx_view_->setBuffer(buf);
777 buf->errors("Parse");
779 updateFlags = Update::None;
783 // --- lyxserver commands ----------------------------
784 case LFUN_SERVER_GET_FILENAME:
785 LASSERT(lyx_view_ && buffer, /**/);
786 setMessage(from_utf8(buffer->absFileName()));
787 LYXERR(Debug::INFO, "FNAME["
788 << buffer->absFileName() << ']');
791 case LFUN_SERVER_NOTIFY:
792 dispatch_buffer = keyseq.print(KeySequence::Portable);
793 theServer().notifyClient(to_utf8(dispatch_buffer));
796 case LFUN_SERVER_GOTO_FILE_ROW: {
797 LASSERT(lyx_view_, /**/);
800 istringstream is(argument);
801 is >> file_name >> row;
802 file_name = os::internal_path(file_name);
805 string const abstmp = package().temp_dir().absFilename();
806 string const realtmp = package().temp_dir().realPath();
807 // We have to use os::path_prefix_is() here, instead of
808 // simply prefixIs(), because the file name comes from
809 // an external application and may need case adjustment.
810 if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
811 || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
812 // Needed by inverse dvi search. If it is a file
813 // in tmpdir, call the apropriated function.
814 // If tmpdir is a symlink, we may have the real
815 // path passed back, so we correct for that.
816 if (!prefixIs(file_name, abstmp))
817 file_name = subst(file_name, realtmp, abstmp);
818 buf = theBufferList().getBufferFromTmp(file_name);
820 // Must replace extension of the file to be .lyx
822 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
823 // Either change buffer or load the file
824 if (theBufferList().exists(s))
825 buf = theBufferList().getBuffer(s);
826 else if (s.exists()) {
827 buf = lyx_view_->loadDocument(s);
830 lyx_view_->message(bformat(
831 _("File does not exist: %1$s"),
832 makeDisplayPath(file_name)));
836 updateFlags = Update::None;
841 lyx_view_->setBuffer(buf);
842 lyx_view_->documentBufferView()->setCursorFromRow(row);
844 buf->errors("Parse");
845 updateFlags = Update::FitCursor;
850 case LFUN_DIALOG_SHOW_NEW_INSET: {
851 LASSERT(lyx_view_, /**/);
852 string const name = cmd.getArg(0);
853 InsetCode code = insetCode(name);
854 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
855 bool insetCodeOK = true;
862 case NOMENCL_PRINT_CODE:
865 case HYPERLINK_CODE: {
866 InsetCommandParams p(code);
867 data = InsetCommand::params2string(name, p);
871 // data is the include type: one of "include",
872 // "input", "verbatiminput" or "verbatiminput*"
874 // default type is requested
876 InsetCommandParams p(INCLUDE_CODE, data);
877 data = InsetCommand::params2string("include", p);
881 // \c data == "Boxed" || "Frameless" etc
882 InsetBoxParams p(data);
883 data = InsetBox::params2string(p);
888 data = InsetBranch::params2string(p);
892 InsetCommandParams p(CITE_CODE);
893 data = InsetCommand::params2string(name, p);
897 data = InsetERT::params2string(InsetCollapsable::Open);
900 case EXTERNAL_CODE: {
901 InsetExternalParams p;
902 data = InsetExternal::params2string(p, *buffer);
907 data = InsetFloat::params2string(p);
910 case LISTINGS_CODE: {
911 InsetListingsParams p;
912 data = InsetListings::params2string(p);
915 case GRAPHICS_CODE: {
916 InsetGraphicsParams p;
917 data = InsetGraphics::params2string(p, *buffer);
922 data = InsetNote::params2string(p);
926 InsetPhantomParams p;
927 data = InsetPhantom::params2string(p);
932 data = InsetSpace::params2string(p);
937 data = InsetVSpace::params2string(space);
942 data = InsetWrap::params2string(p);
946 lyxerr << "Inset type '" << name <<
947 "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << endl;
950 } // end switch(code)
952 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
956 case LFUN_CITATION_INSERT: {
957 LASSERT(lyx_view_, /**/);
958 if (!argument.empty()) {
959 // we can have one optional argument, delimited by '|'
960 // citation-insert <key>|<text_before>
961 // this should be enhanced to also support text_after
962 // and citation style
963 string arg = argument;
965 if (contains(argument, "|")) {
966 arg = token(argument, '|', 0);
967 opt1 = token(argument, '|', 1);
969 InsetCommandParams icp(CITE_CODE);
970 icp["key"] = from_utf8(arg);
972 icp["before"] = from_utf8(opt1);
973 string icstr = InsetCommand::params2string("citation", icp);
974 FuncRequest fr(LFUN_INSET_INSERT, icstr);
977 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
981 case LFUN_BUFFER_CHILD_OPEN: {
982 LASSERT(lyx_view_ && buffer, /**/);
983 FileName filename = makeAbsPath(argument, buffer->filePath());
984 lyx_view_->documentBufferView()->saveBookmark(false);
987 if (theBufferList().exists(filename)) {
988 child = theBufferList().getBuffer(filename);
990 setMessage(bformat(_("Opening child document %1$s..."),
991 makeDisplayPath(filename.absFilename())));
992 child = lyx_view_->loadDocument(filename, false);
996 // Set the parent name of the child document.
997 // This makes insertion of citations and references in the child work,
998 // when the target is in the parent or another child document.
999 child->setParent(buffer);
1000 child->masterBuffer()->updateLabels();
1001 lyx_view_->setBuffer(child);
1003 child->errors("Parse");
1006 // If a screen update is required (in case where auto_open is false),
1007 // setBuffer() would have taken care of it already. Otherwise we shall
1008 // reset the update flag because it can cause a circular problem.
1010 updateFlags = Update::None;
1014 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
1015 LASSERT(lyx_view_, /**/);
1016 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1019 case LFUN_KEYMAP_OFF:
1020 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1021 lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
1024 case LFUN_KEYMAP_PRIMARY:
1025 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1026 lyx_view_->currentBufferView()->getIntl().keyMapPrim();
1029 case LFUN_KEYMAP_SECONDARY:
1030 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1031 lyx_view_->currentBufferView()->getIntl().keyMapSec();
1034 case LFUN_KEYMAP_TOGGLE:
1035 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1036 lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
1042 string rest = split(argument, countstr, ' ');
1043 istringstream is(countstr);
1046 //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1047 for (int i = 0; i < count; ++i)
1048 dispatch(lyxaction.lookupFunc(rest));
1052 case LFUN_COMMAND_SEQUENCE: {
1053 // argument contains ';'-terminated commands
1054 string arg = argument;
1055 if (theBufferList().isLoaded(buffer))
1056 buffer->undo().beginUndoGroup();
1057 while (!arg.empty()) {
1059 arg = split(arg, first, ';');
1060 FuncRequest func(lyxaction.lookupFunc(first));
1061 func.origin = cmd.origin;
1064 if (theBufferList().isLoaded(buffer))
1065 buffer->undo().endUndoGroup();
1069 case LFUN_COMMAND_ALTERNATIVES: {
1070 // argument contains ';'-terminated commands
1071 string arg = argument;
1072 while (!arg.empty()) {
1074 arg = split(arg, first, ';');
1075 FuncRequest func(lyxaction.lookupFunc(first));
1076 func.origin = cmd.origin;
1077 FuncStatus stat = getStatus(func);
1078 if (stat.enabled()) {
1088 if (theTopLevelCmdDef().lock(argument, func)) {
1089 func.origin = cmd.origin;
1091 theTopLevelCmdDef().release(argument);
1093 if (func.action == LFUN_UNKNOWN_ACTION) {
1094 // unknown command definition
1095 lyxerr << "Warning: unknown command definition `"
1099 // recursion detected
1100 lyxerr << "Warning: Recursion in the command definition `"
1101 << argument << "' detected"
1108 case LFUN_PREFERENCES_SAVE: {
1109 lyxrc.write(makeAbsPath("preferences",
1110 package().user_support().absFilename()),
1115 case LFUN_BUFFER_LANGUAGE: {
1116 LASSERT(lyx_view_, /**/);
1117 Language const * oldL = buffer->params().language;
1118 Language const * newL = languages.getLanguage(argument);
1119 if (!newL || oldL == newL)
1122 if (oldL->rightToLeft() == newL->rightToLeft()
1123 && !buffer->isMultiLingual())
1124 buffer->changeLanguage(oldL, newL);
1128 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1129 string const fname =
1130 addName(addPath(package().user_support().absFilename(), "templates/"),
1132 Buffer defaults(fname);
1134 istringstream ss(argument);
1137 int const unknown_tokens = defaults.readHeader(lex);
1139 if (unknown_tokens != 0) {
1140 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1141 << unknown_tokens << " unknown token"
1142 << (unknown_tokens == 1 ? "" : "s")
1146 if (defaults.writeFile(FileName(defaults.absFileName())))
1147 setMessage(bformat(_("Document defaults saved in %1$s"),
1148 makeDisplayPath(fname)));
1150 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1154 case LFUN_BUFFER_PARAMS_APPLY: {
1155 LASSERT(lyx_view_, /**/);
1157 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1158 Cursor & cur = lyx_view_->documentBufferView()->cursor();
1159 cur.recordUndoFullDocument();
1161 istringstream ss(argument);
1164 int const unknown_tokens = buffer->readHeader(lex);
1166 if (unknown_tokens != 0) {
1167 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1168 << unknown_tokens << " unknown token"
1169 << (unknown_tokens == 1 ? "" : "s")
1173 updateLayout(oldClass, buffer);
1175 updateFlags = Update::Force | Update::FitCursor;
1176 // We are most certainly here because of a change in the document
1177 // It is then better to make sure that all dialogs are in sync with
1178 // current document settings. LyXView::restartCursor() achieve this.
1179 lyx_view_->restartCursor();
1183 case LFUN_LAYOUT_MODULES_CLEAR: {
1184 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1185 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1186 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1187 buffer->params().clearLayoutModules();
1188 buffer->params().makeDocumentClass();
1189 updateLayout(oldClass, buffer);
1190 updateFlags = Update::Force | Update::FitCursor;
1194 case LFUN_LAYOUT_MODULE_ADD: {
1195 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1196 BufferParams const & params = buffer->params();
1197 if (!params.moduleCanBeAdded(argument)) {
1198 LYXERR0("Module `" << argument <<
1199 "' cannot be added due to failed requirements or "
1200 "conflicts with installed modules.");
1203 DocumentClass const * const oldClass = params.documentClassPtr();
1204 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1205 buffer->params().addLayoutModule(argument);
1206 buffer->params().makeDocumentClass();
1207 updateLayout(oldClass, buffer);
1208 updateFlags = Update::Force | Update::FitCursor;
1212 case LFUN_TEXTCLASS_APPLY: {
1213 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1215 if (!loadLayoutFile(argument, buffer->temppath()) &&
1216 !loadLayoutFile(argument, buffer->filePath()))
1219 LayoutFile const * old_layout = buffer->params().baseClass();
1220 LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1222 if (old_layout == new_layout)
1226 //Save the old, possibly modular, layout for use in conversion.
1227 DocumentClass const * const oldDocClass =
1228 buffer->params().documentClassPtr();
1229 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1230 buffer->params().setBaseClass(argument);
1231 buffer->params().makeDocumentClass();
1232 updateLayout(oldDocClass, buffer);
1233 updateFlags = Update::Force | Update::FitCursor;
1237 case LFUN_LAYOUT_RELOAD: {
1238 LASSERT(lyx_view_, /**/);
1239 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1240 LayoutFileIndex bc = buffer->params().baseClassID();
1241 LayoutFileList::get().reset(bc);
1242 buffer->params().setBaseClass(bc);
1243 buffer->params().makeDocumentClass();
1244 updateLayout(oldClass, buffer);
1245 updateFlags = Update::Force | Update::FitCursor;
1249 case LFUN_TEXTCLASS_LOAD:
1250 loadLayoutFile(argument, buffer->temppath()) ||
1251 loadLayoutFile(argument, buffer->filePath());
1254 case LFUN_LYXRC_APPLY: {
1255 // reset active key sequences, since the bindings
1256 // are updated (bug 6064)
1258 LyXRC const lyxrc_orig = lyxrc;
1260 istringstream ss(argument);
1261 bool const success = lyxrc.read(ss) == 0;
1264 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1265 << "Unable to read lyxrc data"
1270 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1274 theApp()->resetGui();
1276 /// We force the redraw in any case because there might be
1277 /// some screen font changes.
1278 /// FIXME: only the current view will be updated. the Gui
1279 /// class is able to furnish the list of views.
1280 updateFlags = Update::Force;
1284 case LFUN_BOOKMARK_GOTO:
1285 // go to bookmark, open unopened file and switch to buffer if necessary
1286 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1287 updateFlags = Update::FitCursor;
1290 case LFUN_BOOKMARK_CLEAR:
1291 theSession().bookmarks().clear();
1295 LASSERT(theApp(), /**/);
1296 // Let the frontend dispatch its own actions.
1297 if (theApp()->dispatch(cmd))
1298 // Nothing more to do.
1301 // Everything below is only for active lyx_view_
1305 // Start an undo group. This may be needed for
1306 // some stuff like inset-apply on labels.
1307 if (theBufferList().isLoaded(buffer))
1308 buffer->undo().beginUndoGroup();
1310 // Let the current LyXView dispatch its own actions.
1311 if (lyx_view_->dispatch(cmd)) {
1312 if (lyx_view_->currentBufferView()) {
1313 updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1314 if (theBufferList().isLoaded(buffer))
1315 buffer->undo().endUndoGroup();
1320 LASSERT(lyx_view_->currentBufferView(), /**/);
1322 // Let the current BufferView dispatch its own actions.
1323 if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1324 // The BufferView took care of its own updates if needed.
1325 updateFlags = Update::None;
1326 if (theBufferList().isLoaded(buffer))
1327 buffer->undo().endUndoGroup();
1331 // OK, so try the Buffer itself
1333 BufferView * bv = lyx_view_->currentBufferView();
1334 bv->buffer().dispatch(cmd, dr);
1335 if (dr.dispatched()) {
1336 updateFlags = dr.update();
1339 // OK, so try with the document Buffer.
1340 BufferView * doc_bv = lyx_view_->documentBufferView();
1342 buffer = &(doc_bv->buffer());
1343 buffer->dispatch(cmd, dr);
1344 if (dr.dispatched()) {
1345 updateFlags = dr.update();
1350 // Is this a function that acts on inset at point?
1351 Inset * inset = bv->cursor().nextInset();
1352 if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1354 bv->cursor().result().dispatched(true);
1355 bv->cursor().result().update(Update::FitCursor | Update::Force);
1356 FuncRequest tmpcmd = cmd;
1357 inset->dispatch(bv->cursor(), tmpcmd);
1358 if (bv->cursor().result().dispatched()) {
1359 updateFlags = bv->cursor().result().update();
1364 // Let the current Cursor dispatch its own actions.
1365 Cursor old = bv->cursor();
1366 bv->cursor().getPos(cursorPosBeforeDispatchX_,
1367 cursorPosBeforeDispatchY_);
1368 bv->cursor().dispatch(cmd);
1370 // notify insets we just left
1371 if (bv->cursor() != old) {
1373 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1375 bv->cursor().fixIfBroken();
1378 if (theBufferList().isLoaded(buffer))
1379 buffer->undo().endUndoGroup();
1381 // update completion. We do it here and not in
1382 // processKeySym to avoid another redraw just for a
1383 // changed inline completion
1384 if (cmd.origin == FuncRequest::KEYBOARD) {
1385 if (cmd.action == LFUN_SELF_INSERT
1386 || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1387 lyx_view_->updateCompletion(bv->cursor(), true, true);
1388 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1389 lyx_view_->updateCompletion(bv->cursor(), false, true);
1391 lyx_view_->updateCompletion(bv->cursor(), false, false);
1394 updateFlags = bv->cursor().result().update();
1397 // if we executed a mutating lfun, mark the buffer as dirty
1398 if (theBufferList().isLoaded(buffer) && flag.enabled()
1399 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1400 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1401 buffer->markDirty();
1403 if (lyx_view_ && lyx_view_->currentBufferView()) {
1404 // BufferView::update() updates the ViewMetricsInfo and
1405 // also initializes the position cache for all insets in
1406 // (at least partially) visible top-level paragraphs.
1407 // We will redraw the screen only if needed.
1408 lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1410 // Do we have a selection?
1411 theSelection().haveSelection(
1412 lyx_view_->currentBufferView()->cursor().selection());
1415 lyx_view_->restartCursor();
1419 // Some messages may already be translated, so we cannot use _()
1420 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1425 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1427 const bool verbose = (cmd.origin == FuncRequest::MENU
1428 || cmd.origin == FuncRequest::TOOLBAR
1429 || cmd.origin == FuncRequest::COMMANDBUFFER);
1431 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1432 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1434 lyx_view_->message(msg);
1438 docstring dispatch_msg = msg;
1439 if (!dispatch_msg.empty())
1440 dispatch_msg += ' ';
1442 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1444 bool argsadded = false;
1446 if (!cmd.argument().empty()) {
1447 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1448 comname += ' ' + cmd.argument();
1453 docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1455 if (!shortcuts.empty())
1456 comname += ": " + shortcuts;
1457 else if (!argsadded && !cmd.argument().empty())
1458 comname += ' ' + cmd.argument();
1460 if (!comname.empty()) {
1461 comname = rtrim(comname);
1462 dispatch_msg += '(' + rtrim(comname) + ')';
1465 LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1466 if (!dispatch_msg.empty())
1467 lyx_view_->message(dispatch_msg);
1471 // Each "lyx_view_" should have it's own message method. lyxview and
1472 // the minibuffer would use the minibuffer, but lyxserver would
1473 // send an ERROR signal to its client. Alejandro 970603
1474 // This function is bit problematic when it comes to NLS, to make the
1475 // lyx servers client be language indepenent we must not translate
1476 // strings sent to this func.
1477 void LyXFunc::setErrorMessage(docstring const & m) const
1479 dispatch_buffer = m;
1484 void LyXFunc::setMessage(docstring const & m) const
1486 dispatch_buffer = m;
1490 docstring LyXFunc::viewStatusMessage()
1492 // When meta-fake key is pressed, show the key sequence so far + "M-".
1494 return keyseq.print(KeySequence::ForGui) + "M-";
1496 // Else, when a non-complete key sequence is pressed,
1497 // show the available options.
1498 if (keyseq.length() > 0 && !keyseq.deleted())
1499 return keyseq.printOptions(true);
1501 LASSERT(lyx_view_, /**/);
1502 if (!lyx_view_->currentBufferView())
1503 return _("Welcome to LyX!");
1505 return lyx_view_->currentBufferView()->cursor().currentState();
1509 bool LyXFunc::wasMetaKey() const
1511 return (meta_fake_bit != NoModifier);
1515 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1517 lyx_view_->message(_("Converting document to new document class..."));
1519 StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1520 ErrorList & el = buf->errorList("Class Switch");
1521 cap::switchBetweenClasses(
1522 oldlayout, buf->params().documentClassPtr(),
1523 static_cast<InsetText &>(buf->inset()), el);
1525 lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1527 buf->errors("Class Switch");
1528 buf->updateLabels();
1534 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1536 // Why the switch you might ask. It is a trick to ensure that all
1537 // the elements in the LyXRCTags enum is handled. As you can see
1538 // there are no breaks at all. So it is just a huge fall-through.
1539 // The nice thing is that we will get a warning from the compiler
1540 // if we forget an element.
1541 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1543 case LyXRC::RC_ACCEPT_COMPOUND:
1544 case LyXRC::RC_ALT_LANG:
1545 case LyXRC::RC_PLAINTEXT_LINELEN:
1546 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1547 case LyXRC::RC_AUTOCORRECTION_MATH:
1548 case LyXRC::RC_AUTOREGIONDELETE:
1549 case LyXRC::RC_AUTORESET_OPTIONS:
1550 case LyXRC::RC_AUTOSAVE:
1551 case LyXRC::RC_AUTO_NUMBER:
1552 case LyXRC::RC_BACKUPDIR_PATH:
1553 case LyXRC::RC_BIBTEX_ALTERNATIVES:
1554 case LyXRC::RC_BIBTEX_COMMAND:
1555 case LyXRC::RC_BINDFILE:
1556 case LyXRC::RC_CHECKLASTFILES:
1557 case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1558 case LyXRC::RC_COMPLETION_INLINE_DELAY:
1559 case LyXRC::RC_COMPLETION_INLINE_DOTS:
1560 case LyXRC::RC_COMPLETION_INLINE_MATH:
1561 case LyXRC::RC_COMPLETION_INLINE_TEXT:
1562 case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1563 case LyXRC::RC_COMPLETION_POPUP_DELAY:
1564 case LyXRC::RC_COMPLETION_POPUP_MATH:
1565 case LyXRC::RC_COMPLETION_POPUP_TEXT:
1566 case LyXRC::RC_USELASTFILEPOS:
1567 case LyXRC::RC_LOADSESSION:
1568 case LyXRC::RC_CHKTEX_COMMAND:
1569 case LyXRC::RC_CONVERTER:
1570 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1571 case LyXRC::RC_COPIER:
1572 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1573 case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1574 case LyXRC::RC_DATE_INSERT_FORMAT:
1575 case LyXRC::RC_DEFAULT_LANGUAGE:
1576 case LyXRC::RC_GUI_LANGUAGE:
1577 case LyXRC::RC_DEFAULT_PAPERSIZE:
1578 case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1579 case LyXRC::RC_DEFFILE:
1580 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1581 case LyXRC::RC_DISPLAY_GRAPHICS:
1582 case LyXRC::RC_DOCUMENTPATH:
1583 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1584 FileName path(lyxrc_new.document_path);
1585 if (path.exists() && path.isDirectory())
1586 package().document_dir() = FileName(lyxrc.document_path);
1588 case LyXRC::RC_EDITOR_ALTERNATIVES:
1589 case LyXRC::RC_ESC_CHARS:
1590 case LyXRC::RC_EXAMPLEPATH:
1591 case LyXRC::RC_FONT_ENCODING:
1592 case LyXRC::RC_FORMAT:
1593 case LyXRC::RC_GROUP_LAYOUTS:
1594 case LyXRC::RC_HUNSPELLDIR_PATH:
1595 case LyXRC::RC_INDEX_ALTERNATIVES:
1596 case LyXRC::RC_INDEX_COMMAND:
1597 case LyXRC::RC_JBIBTEX_COMMAND:
1598 case LyXRC::RC_JINDEX_COMMAND:
1599 case LyXRC::RC_NOMENCL_COMMAND:
1600 case LyXRC::RC_INPUT:
1601 case LyXRC::RC_KBMAP:
1602 case LyXRC::RC_KBMAP_PRIMARY:
1603 case LyXRC::RC_KBMAP_SECONDARY:
1604 case LyXRC::RC_LABEL_INIT_LENGTH:
1605 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1606 case LyXRC::RC_LANGUAGE_AUTO_END:
1607 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1608 case LyXRC::RC_LANGUAGE_COMMAND_END:
1609 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1610 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1611 case LyXRC::RC_LANGUAGE_PACKAGE:
1612 case LyXRC::RC_LANGUAGE_USE_BABEL:
1613 case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1614 case LyXRC::RC_MACRO_EDIT_STYLE:
1615 case LyXRC::RC_MAKE_BACKUP:
1616 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1617 case LyXRC::RC_MOUSE_WHEEL_SPEED:
1618 case LyXRC::RC_NUMLASTFILES:
1619 case LyXRC::RC_PARAGRAPH_MARKERS:
1620 case LyXRC::RC_PATH_PREFIX:
1621 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1622 prependEnvPath("PATH", lyxrc.path_prefix);
1624 case LyXRC::RC_PERS_DICT:
1625 case LyXRC::RC_PREVIEW:
1626 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1627 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1628 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1629 case LyXRC::RC_PRINTCOPIESFLAG:
1630 case LyXRC::RC_PRINTER:
1631 case LyXRC::RC_PRINTEVENPAGEFLAG:
1632 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1633 case LyXRC::RC_PRINTFILEEXTENSION:
1634 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1635 case LyXRC::RC_PRINTODDPAGEFLAG:
1636 case LyXRC::RC_PRINTPAGERANGEFLAG:
1637 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1638 case LyXRC::RC_PRINTPAPERFLAG:
1639 case LyXRC::RC_PRINTREVERSEFLAG:
1640 case LyXRC::RC_PRINTSPOOL_COMMAND:
1641 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1642 case LyXRC::RC_PRINTTOFILE:
1643 case LyXRC::RC_PRINTTOPRINTER:
1644 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1645 case LyXRC::RC_PRINT_COMMAND:
1646 case LyXRC::RC_RTL_SUPPORT:
1647 case LyXRC::RC_SCREEN_DPI:
1648 case LyXRC::RC_SCREEN_FONT_ROMAN:
1649 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1650 case LyXRC::RC_SCREEN_FONT_SANS:
1651 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1652 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1653 case LyXRC::RC_SCREEN_FONT_SIZES:
1654 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1655 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1656 case LyXRC::RC_GEOMETRY_SESSION:
1657 case LyXRC::RC_SCREEN_ZOOM:
1658 case LyXRC::RC_SERVERPIPE:
1659 case LyXRC::RC_SET_COLOR:
1660 case LyXRC::RC_SHOW_BANNER:
1661 case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1662 case LyXRC::RC_SPELL_COMMAND:
1663 case LyXRC::RC_SPELLCHECKER:
1664 case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1665 case LyXRC::RC_SPLITINDEX_COMMAND:
1666 case LyXRC::RC_TEMPDIRPATH:
1667 case LyXRC::RC_TEMPLATEPATH:
1668 case LyXRC::RC_TEX_ALLOWS_SPACES:
1669 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1670 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1671 os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1673 case LyXRC::RC_THESAURUSDIRPATH:
1674 case LyXRC::RC_UIFILE:
1675 case LyXRC::RC_USER_EMAIL:
1676 case LyXRC::RC_USER_NAME:
1677 case LyXRC::RC_USETEMPDIR:
1678 case LyXRC::RC_USE_ALT_LANG:
1679 case LyXRC::RC_USE_CONVERTER_CACHE:
1680 case LyXRC::RC_USE_ESC_CHARS:
1681 case LyXRC::RC_USE_INP_ENC:
1682 case LyXRC::RC_USE_PERS_DICT:
1683 case LyXRC::RC_USE_TOOLTIP:
1684 case LyXRC::RC_USE_PIXMAP_CACHE:
1685 case LyXRC::RC_USE_SPELL_LIB:
1686 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1687 case LyXRC::RC_SORT_LAYOUTS:
1688 case LyXRC::RC_FULL_SCREEN_LIMIT:
1689 case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1690 case LyXRC::RC_FULL_SCREEN_MENUBAR:
1691 case LyXRC::RC_FULL_SCREEN_TABBAR:
1692 case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1693 case LyXRC::RC_FULL_SCREEN_WIDTH:
1694 case LyXRC::RC_VISUAL_CURSOR:
1695 case LyXRC::RC_VIEWER:
1696 case LyXRC::RC_VIEWER_ALTERNATIVES:
1697 case LyXRC::RC_LAST: