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_RECONFIGURE:
562 case LFUN_DROP_LAYOUTS_CHOICE:
563 case LFUN_SERVER_GET_FILENAME:
564 case LFUN_SERVER_NOTIFY:
565 case LFUN_SERVER_GOTO_FILE_ROW:
566 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
567 case LFUN_KEYMAP_OFF:
568 case LFUN_KEYMAP_PRIMARY:
569 case LFUN_KEYMAP_SECONDARY:
570 case LFUN_KEYMAP_TOGGLE:
572 case LFUN_PREFERENCES_SAVE:
573 case LFUN_INSET_EDIT:
574 case LFUN_TEXTCLASS_APPLY:
575 case LFUN_TEXTCLASS_LOAD:
576 case LFUN_BUFFER_SAVE_AS_DEFAULT:
577 case LFUN_BUFFER_PARAMS_APPLY:
578 case LFUN_LAYOUT_MODULES_CLEAR:
579 case LFUN_LAYOUT_MODULE_ADD:
580 case LFUN_LAYOUT_RELOAD:
581 case LFUN_LYXRC_APPLY:
582 // these are handled in our dispatch()
590 if (theApp()->getStatus(cmd, flag))
593 // Does the view know something?
598 if (lv->getStatus(cmd, flag))
601 BufferView * bv = lv->currentBufferView();
602 BufferView * doc_bv = lv->documentBufferView();
603 // If we do not have a BufferView, then other functions are disabled
608 // Is this a function that acts on inset at point?
609 Inset * inset = bv->cursor().nextInset();
610 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
611 && inset && inset->getStatus(bv->cursor(), cmd, flag))
614 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
616 // try the BufferView
617 decided = bv->getStatus(cmd, flag);
620 decided = bv->buffer().getStatus(cmd, flag);
621 if (!decided && doc_bv)
622 // try the Document Buffer
623 decided = doc_bv->buffer().getStatus(cmd, flag);
627 flag.setEnabled(false);
629 // Can we use a readonly buffer?
630 if (buf && buf->isReadonly()
631 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
632 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
633 flag.message(from_utf8(N_("Document is read-only")));
634 flag.setEnabled(false);
637 // Are we in a DELETED change-tracking region?
638 if (lyx_view_ && lyx_view_->documentBufferView()
639 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
641 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
642 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
643 flag.message(from_utf8(N_("This portion of the document is deleted.")));
644 flag.setEnabled(false);
647 // the default error message if we disable the command
648 if (!flag.enabled() && flag.message().empty())
649 flag.message(from_utf8(N_("Command disabled")));
657 bool loadLayoutFile(string const & name, string const & buf_path)
659 if (!LayoutFileList::get().haveClass(name)) {
660 lyxerr << "Document class \"" << name
661 << "\" does not exist."
666 LayoutFile & tc = LayoutFileList::get()[name];
667 if (!tc.load(buf_path)) {
668 docstring s = bformat(_("The document class %1$s "
669 "could not be loaded."), from_utf8(name));
670 Alert::error(_("Could not load class"), s);
677 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
682 void LyXFunc::dispatch(FuncRequest const & cmd)
684 string const argument = to_utf8(cmd.argument());
685 FuncCode const action = cmd.action;
687 LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
688 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
690 // we have not done anything wrong yet.
692 dispatch_buffer.erase();
694 // redraw the screen at the end (first of the two drawing steps).
695 //This is done unless explicitely requested otherwise
696 Update::flags updateFlags = Update::FitCursor;
698 FuncStatus const flag = getStatus(cmd);
699 if (!flag.enabled()) {
700 // We cannot use this function here
701 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
702 << lyxaction.getActionName(action)
703 << " [" << action << "] is disabled at this location");
704 setErrorMessage(flag.message());
706 lyx_view_->restartCursor();
709 if (lyx_view_ && lyx_view_->currentBufferView())
710 buffer = &lyx_view_->currentBufferView()->buffer();
713 case LFUN_COMMAND_PREFIX:
714 LASSERT(lyx_view_, /**/);
715 lyx_view_->message(keyseq.printOptions(true));
719 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
721 meta_fake_bit = NoModifier;
723 // cancel any selection
724 dispatch(FuncRequest(LFUN_MARK_OFF));
725 setMessage(from_ascii(N_("Cancel")));
728 case LFUN_META_PREFIX:
729 meta_fake_bit = AltModifier;
730 setMessage(keyseq.print(KeySequence::ForGui));
733 // --- Menus -----------------------------------------------
734 case LFUN_RECONFIGURE:
735 // argument is any additional parameter to the configure.py command
736 reconfigure(lyx_view_, argument);
739 case LFUN_HELP_OPEN: {
741 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
742 string const arg = argument;
744 setErrorMessage(from_utf8(N_("Missing argument")));
747 FileName fname = i18nLibFileSearch("doc", arg, "lyx");
749 fname = i18nLibFileSearch("examples", arg, "lyx");
752 lyxerr << "LyX: unable to find documentation file `"
753 << arg << "'. Bad installation?" << endl;
756 lyx_view_->message(bformat(_("Opening help file %1$s..."),
757 makeDisplayPath(fname.absFilename())));
758 Buffer * buf = lyx_view_->loadDocument(fname, false);
761 lyx_view_->setBuffer(buf);
762 buf->errors("Parse");
764 updateFlags = Update::None;
768 // --- lyxserver commands ----------------------------
769 case LFUN_SERVER_GET_FILENAME:
770 LASSERT(lyx_view_ && buffer, /**/);
771 setMessage(from_utf8(buffer->absFileName()));
772 LYXERR(Debug::INFO, "FNAME["
773 << buffer->absFileName() << ']');
776 case LFUN_SERVER_NOTIFY:
777 dispatch_buffer = keyseq.print(KeySequence::Portable);
778 theServer().notifyClient(to_utf8(dispatch_buffer));
781 case LFUN_SERVER_GOTO_FILE_ROW: {
782 LASSERT(lyx_view_, /**/);
785 istringstream is(argument);
786 is >> file_name >> row;
787 file_name = os::internal_path(file_name);
790 string const abstmp = package().temp_dir().absFilename();
791 string const realtmp = package().temp_dir().realPath();
792 // We have to use os::path_prefix_is() here, instead of
793 // simply prefixIs(), because the file name comes from
794 // an external application and may need case adjustment.
795 if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
796 || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
797 // Needed by inverse dvi search. If it is a file
798 // in tmpdir, call the apropriated function.
799 // If tmpdir is a symlink, we may have the real
800 // path passed back, so we correct for that.
801 if (!prefixIs(file_name, abstmp))
802 file_name = subst(file_name, realtmp, abstmp);
803 buf = theBufferList().getBufferFromTmp(file_name);
805 // Must replace extension of the file to be .lyx
807 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
808 // Either change buffer or load the file
809 if (theBufferList().exists(s))
810 buf = theBufferList().getBuffer(s);
811 else if (s.exists()) {
812 buf = lyx_view_->loadDocument(s);
815 lyx_view_->message(bformat(
816 _("File does not exist: %1$s"),
817 makeDisplayPath(file_name)));
821 updateFlags = Update::None;
826 lyx_view_->setBuffer(buf);
827 lyx_view_->documentBufferView()->setCursorFromRow(row);
829 buf->errors("Parse");
830 updateFlags = Update::FitCursor;
835 case LFUN_DIALOG_SHOW_NEW_INSET: {
836 LASSERT(lyx_view_, /**/);
837 string const name = cmd.getArg(0);
838 InsetCode code = insetCode(name);
839 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
840 bool insetCodeOK = true;
847 case NOMENCL_PRINT_CODE:
850 case HYPERLINK_CODE: {
851 InsetCommandParams p(code);
852 data = InsetCommand::params2string(name, p);
856 // data is the include type: one of "include",
857 // "input", "verbatiminput" or "verbatiminput*"
859 // default type is requested
861 InsetCommandParams p(INCLUDE_CODE, data);
862 data = InsetCommand::params2string("include", p);
866 // \c data == "Boxed" || "Frameless" etc
867 InsetBoxParams p(data);
868 data = InsetBox::params2string(p);
873 data = InsetBranch::params2string(p);
877 InsetCommandParams p(CITE_CODE);
878 data = InsetCommand::params2string(name, p);
882 data = InsetERT::params2string(InsetCollapsable::Open);
885 case EXTERNAL_CODE: {
886 InsetExternalParams p;
887 data = InsetExternal::params2string(p, *buffer);
892 data = InsetFloat::params2string(p);
895 case LISTINGS_CODE: {
896 InsetListingsParams p;
897 data = InsetListings::params2string(p);
900 case GRAPHICS_CODE: {
901 InsetGraphicsParams p;
902 data = InsetGraphics::params2string(p, *buffer);
907 data = InsetNote::params2string(p);
911 InsetPhantomParams p;
912 data = InsetPhantom::params2string(p);
917 data = InsetSpace::params2string(p);
922 data = InsetVSpace::params2string(space);
927 data = InsetWrap::params2string(p);
931 lyxerr << "Inset type '" << name <<
932 "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << endl;
935 } // end switch(code)
937 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
941 case LFUN_CITATION_INSERT: {
942 LASSERT(lyx_view_, /**/);
943 if (!argument.empty()) {
944 // we can have one optional argument, delimited by '|'
945 // citation-insert <key>|<text_before>
946 // this should be enhanced to also support text_after
947 // and citation style
948 string arg = argument;
950 if (contains(argument, "|")) {
951 arg = token(argument, '|', 0);
952 opt1 = token(argument, '|', 1);
954 InsetCommandParams icp(CITE_CODE);
955 icp["key"] = from_utf8(arg);
957 icp["before"] = from_utf8(opt1);
958 string icstr = InsetCommand::params2string("citation", icp);
959 FuncRequest fr(LFUN_INSET_INSERT, icstr);
962 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
966 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
967 LASSERT(lyx_view_, /**/);
968 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
971 case LFUN_KEYMAP_OFF:
972 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
973 lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
976 case LFUN_KEYMAP_PRIMARY:
977 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
978 lyx_view_->currentBufferView()->getIntl().keyMapPrim();
981 case LFUN_KEYMAP_SECONDARY:
982 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
983 lyx_view_->currentBufferView()->getIntl().keyMapSec();
986 case LFUN_KEYMAP_TOGGLE:
987 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
988 lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
994 string rest = split(argument, countstr, ' ');
995 istringstream is(countstr);
998 //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
999 for (int i = 0; i < count; ++i)
1000 dispatch(lyxaction.lookupFunc(rest));
1004 case LFUN_COMMAND_SEQUENCE: {
1005 // argument contains ';'-terminated commands
1006 string arg = argument;
1007 if (theBufferList().isLoaded(buffer))
1008 buffer->undo().beginUndoGroup();
1009 while (!arg.empty()) {
1011 arg = split(arg, first, ';');
1012 FuncRequest func(lyxaction.lookupFunc(first));
1013 func.origin = cmd.origin;
1016 if (theBufferList().isLoaded(buffer))
1017 buffer->undo().endUndoGroup();
1021 case LFUN_COMMAND_ALTERNATIVES: {
1022 // argument contains ';'-terminated commands
1023 string arg = argument;
1024 while (!arg.empty()) {
1026 arg = split(arg, first, ';');
1027 FuncRequest func(lyxaction.lookupFunc(first));
1028 func.origin = cmd.origin;
1029 FuncStatus stat = getStatus(func);
1030 if (stat.enabled()) {
1040 if (theTopLevelCmdDef().lock(argument, func)) {
1041 func.origin = cmd.origin;
1043 theTopLevelCmdDef().release(argument);
1045 if (func.action == LFUN_UNKNOWN_ACTION) {
1046 // unknown command definition
1047 lyxerr << "Warning: unknown command definition `"
1051 // recursion detected
1052 lyxerr << "Warning: Recursion in the command definition `"
1053 << argument << "' detected"
1060 case LFUN_PREFERENCES_SAVE: {
1061 lyxrc.write(makeAbsPath("preferences",
1062 package().user_support().absFilename()),
1067 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1068 string const fname =
1069 addName(addPath(package().user_support().absFilename(), "templates/"),
1071 Buffer defaults(fname);
1073 istringstream ss(argument);
1076 int const unknown_tokens = defaults.readHeader(lex);
1078 if (unknown_tokens != 0) {
1079 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1080 << unknown_tokens << " unknown token"
1081 << (unknown_tokens == 1 ? "" : "s")
1085 if (defaults.writeFile(FileName(defaults.absFileName())))
1086 setMessage(bformat(_("Document defaults saved in %1$s"),
1087 makeDisplayPath(fname)));
1089 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1093 case LFUN_BUFFER_PARAMS_APPLY: {
1094 LASSERT(lyx_view_, /**/);
1096 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1097 Cursor & cur = lyx_view_->documentBufferView()->cursor();
1098 cur.recordUndoFullDocument();
1100 istringstream ss(argument);
1103 int const unknown_tokens = buffer->readHeader(lex);
1105 if (unknown_tokens != 0) {
1106 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1107 << unknown_tokens << " unknown token"
1108 << (unknown_tokens == 1 ? "" : "s")
1112 updateLayout(oldClass, buffer);
1114 updateFlags = Update::Force | Update::FitCursor;
1115 // We are most certainly here because of a change in the document
1116 // It is then better to make sure that all dialogs are in sync with
1117 // current document settings. LyXView::restartCursor() achieve this.
1118 lyx_view_->restartCursor();
1122 case LFUN_LAYOUT_MODULES_CLEAR: {
1123 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1124 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1125 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1126 buffer->params().clearLayoutModules();
1127 buffer->params().makeDocumentClass();
1128 updateLayout(oldClass, buffer);
1129 updateFlags = Update::Force | Update::FitCursor;
1133 case LFUN_LAYOUT_MODULE_ADD: {
1134 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1135 BufferParams const & params = buffer->params();
1136 if (!params.moduleCanBeAdded(argument)) {
1137 LYXERR0("Module `" << argument <<
1138 "' cannot be added due to failed requirements or "
1139 "conflicts with installed modules.");
1142 DocumentClass const * const oldClass = params.documentClassPtr();
1143 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1144 buffer->params().addLayoutModule(argument);
1145 buffer->params().makeDocumentClass();
1146 updateLayout(oldClass, buffer);
1147 updateFlags = Update::Force | Update::FitCursor;
1151 case LFUN_TEXTCLASS_APPLY: {
1152 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1154 if (!loadLayoutFile(argument, buffer->temppath()) &&
1155 !loadLayoutFile(argument, buffer->filePath()))
1158 LayoutFile const * old_layout = buffer->params().baseClass();
1159 LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1161 if (old_layout == new_layout)
1165 //Save the old, possibly modular, layout for use in conversion.
1166 DocumentClass const * const oldDocClass =
1167 buffer->params().documentClassPtr();
1168 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1169 buffer->params().setBaseClass(argument);
1170 buffer->params().makeDocumentClass();
1171 updateLayout(oldDocClass, buffer);
1172 updateFlags = Update::Force | Update::FitCursor;
1176 case LFUN_LAYOUT_RELOAD: {
1177 LASSERT(lyx_view_, /**/);
1178 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1179 LayoutFileIndex bc = buffer->params().baseClassID();
1180 LayoutFileList::get().reset(bc);
1181 buffer->params().setBaseClass(bc);
1182 buffer->params().makeDocumentClass();
1183 updateLayout(oldClass, buffer);
1184 updateFlags = Update::Force | Update::FitCursor;
1188 case LFUN_TEXTCLASS_LOAD:
1189 loadLayoutFile(argument, buffer->temppath()) ||
1190 loadLayoutFile(argument, buffer->filePath());
1193 case LFUN_LYXRC_APPLY: {
1194 // reset active key sequences, since the bindings
1195 // are updated (bug 6064)
1197 LyXRC const lyxrc_orig = lyxrc;
1199 istringstream ss(argument);
1200 bool const success = lyxrc.read(ss) == 0;
1203 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1204 << "Unable to read lyxrc data"
1209 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1213 theApp()->resetGui();
1215 /// We force the redraw in any case because there might be
1216 /// some screen font changes.
1217 /// FIXME: only the current view will be updated. the Gui
1218 /// class is able to furnish the list of views.
1219 updateFlags = Update::Force;
1223 case LFUN_BOOKMARK_GOTO:
1224 // go to bookmark, open unopened file and switch to buffer if necessary
1225 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1226 updateFlags = Update::FitCursor;
1229 case LFUN_BOOKMARK_CLEAR:
1230 theSession().bookmarks().clear();
1234 LASSERT(theApp(), /**/);
1235 // Let the frontend dispatch its own actions.
1236 if (theApp()->dispatch(cmd))
1237 // Nothing more to do.
1240 // Everything below is only for active lyx_view_
1244 // Start an undo group. This may be needed for
1245 // some stuff like inset-apply on labels.
1246 if (theBufferList().isLoaded(buffer))
1247 buffer->undo().beginUndoGroup();
1249 // Let the current LyXView dispatch its own actions.
1250 if (lyx_view_->dispatch(cmd)) {
1251 if (lyx_view_->currentBufferView()) {
1252 updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1253 if (theBufferList().isLoaded(buffer))
1254 buffer->undo().endUndoGroup();
1259 LASSERT(lyx_view_->currentBufferView(), /**/);
1261 // Let the current BufferView dispatch its own actions.
1262 if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1263 // The BufferView took care of its own updates if needed.
1264 updateFlags = Update::None;
1265 if (theBufferList().isLoaded(buffer))
1266 buffer->undo().endUndoGroup();
1270 // OK, so try the Buffer itself
1272 BufferView * bv = lyx_view_->currentBufferView();
1273 bv->buffer().dispatch(cmd, dr);
1274 if (dr.dispatched()) {
1275 updateFlags = dr.update();
1278 // OK, so try with the document Buffer.
1279 BufferView * doc_bv = lyx_view_->documentBufferView();
1281 buffer = &(doc_bv->buffer());
1282 buffer->dispatch(cmd, dr);
1283 if (dr.dispatched()) {
1284 updateFlags = dr.update();
1289 // Is this a function that acts on inset at point?
1290 Inset * inset = bv->cursor().nextInset();
1291 if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1293 bv->cursor().result().dispatched(true);
1294 bv->cursor().result().update(Update::FitCursor | Update::Force);
1295 FuncRequest tmpcmd = cmd;
1296 inset->dispatch(bv->cursor(), tmpcmd);
1297 if (bv->cursor().result().dispatched()) {
1298 updateFlags = bv->cursor().result().update();
1303 // Let the current Cursor dispatch its own actions.
1304 Cursor old = bv->cursor();
1305 bv->cursor().getPos(cursorPosBeforeDispatchX_,
1306 cursorPosBeforeDispatchY_);
1307 bv->cursor().dispatch(cmd);
1309 // notify insets we just left
1310 if (bv->cursor() != old) {
1312 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1314 bv->cursor().fixIfBroken();
1317 if (theBufferList().isLoaded(buffer))
1318 buffer->undo().endUndoGroup();
1320 // update completion. We do it here and not in
1321 // processKeySym to avoid another redraw just for a
1322 // changed inline completion
1323 if (cmd.origin == FuncRequest::KEYBOARD) {
1324 if (cmd.action == LFUN_SELF_INSERT
1325 || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1326 lyx_view_->updateCompletion(bv->cursor(), true, true);
1327 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1328 lyx_view_->updateCompletion(bv->cursor(), false, true);
1330 lyx_view_->updateCompletion(bv->cursor(), false, false);
1333 updateFlags = bv->cursor().result().update();
1336 // if we executed a mutating lfun, mark the buffer as dirty
1337 if (theBufferList().isLoaded(buffer) && flag.enabled()
1338 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1339 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1340 buffer->markDirty();
1342 if (lyx_view_ && lyx_view_->currentBufferView()) {
1343 // BufferView::update() updates the ViewMetricsInfo and
1344 // also initializes the position cache for all insets in
1345 // (at least partially) visible top-level paragraphs.
1346 // We will redraw the screen only if needed.
1347 lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1349 // Do we have a selection?
1350 theSelection().haveSelection(
1351 lyx_view_->currentBufferView()->cursor().selection());
1354 lyx_view_->restartCursor();
1358 // Some messages may already be translated, so we cannot use _()
1359 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1364 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1366 const bool verbose = (cmd.origin == FuncRequest::MENU
1367 || cmd.origin == FuncRequest::TOOLBAR
1368 || cmd.origin == FuncRequest::COMMANDBUFFER);
1370 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1371 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1373 lyx_view_->message(msg);
1377 docstring dispatch_msg = msg;
1378 if (!dispatch_msg.empty())
1379 dispatch_msg += ' ';
1381 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1383 bool argsadded = false;
1385 if (!cmd.argument().empty()) {
1386 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1387 comname += ' ' + cmd.argument();
1392 docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1394 if (!shortcuts.empty())
1395 comname += ": " + shortcuts;
1396 else if (!argsadded && !cmd.argument().empty())
1397 comname += ' ' + cmd.argument();
1399 if (!comname.empty()) {
1400 comname = rtrim(comname);
1401 dispatch_msg += '(' + rtrim(comname) + ')';
1404 LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1405 if (!dispatch_msg.empty())
1406 lyx_view_->message(dispatch_msg);
1410 // Each "lyx_view_" should have it's own message method. lyxview and
1411 // the minibuffer would use the minibuffer, but lyxserver would
1412 // send an ERROR signal to its client. Alejandro 970603
1413 // This function is bit problematic when it comes to NLS, to make the
1414 // lyx servers client be language indepenent we must not translate
1415 // strings sent to this func.
1416 void LyXFunc::setErrorMessage(docstring const & m) const
1418 dispatch_buffer = m;
1423 void LyXFunc::setMessage(docstring const & m) const
1425 dispatch_buffer = m;
1429 docstring LyXFunc::viewStatusMessage()
1431 // When meta-fake key is pressed, show the key sequence so far + "M-".
1433 return keyseq.print(KeySequence::ForGui) + "M-";
1435 // Else, when a non-complete key sequence is pressed,
1436 // show the available options.
1437 if (keyseq.length() > 0 && !keyseq.deleted())
1438 return keyseq.printOptions(true);
1440 LASSERT(lyx_view_, /**/);
1441 if (!lyx_view_->currentBufferView())
1442 return _("Welcome to LyX!");
1444 return lyx_view_->currentBufferView()->cursor().currentState();
1448 bool LyXFunc::wasMetaKey() const
1450 return (meta_fake_bit != NoModifier);
1454 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1456 lyx_view_->message(_("Converting document to new document class..."));
1458 StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1459 ErrorList & el = buf->errorList("Class Switch");
1460 cap::switchBetweenClasses(
1461 oldlayout, buf->params().documentClassPtr(),
1462 static_cast<InsetText &>(buf->inset()), el);
1464 lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1466 buf->errors("Class Switch");
1467 buf->updateLabels();
1473 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1475 // Why the switch you might ask. It is a trick to ensure that all
1476 // the elements in the LyXRCTags enum is handled. As you can see
1477 // there are no breaks at all. So it is just a huge fall-through.
1478 // The nice thing is that we will get a warning from the compiler
1479 // if we forget an element.
1480 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1482 case LyXRC::RC_ACCEPT_COMPOUND:
1483 case LyXRC::RC_ALT_LANG:
1484 case LyXRC::RC_PLAINTEXT_LINELEN:
1485 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1486 case LyXRC::RC_AUTOCORRECTION_MATH:
1487 case LyXRC::RC_AUTOREGIONDELETE:
1488 case LyXRC::RC_AUTORESET_OPTIONS:
1489 case LyXRC::RC_AUTOSAVE:
1490 case LyXRC::RC_AUTO_NUMBER:
1491 case LyXRC::RC_BACKUPDIR_PATH:
1492 case LyXRC::RC_BIBTEX_ALTERNATIVES:
1493 case LyXRC::RC_BIBTEX_COMMAND:
1494 case LyXRC::RC_BINDFILE:
1495 case LyXRC::RC_CHECKLASTFILES:
1496 case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1497 case LyXRC::RC_COMPLETION_INLINE_DELAY:
1498 case LyXRC::RC_COMPLETION_INLINE_DOTS:
1499 case LyXRC::RC_COMPLETION_INLINE_MATH:
1500 case LyXRC::RC_COMPLETION_INLINE_TEXT:
1501 case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1502 case LyXRC::RC_COMPLETION_POPUP_DELAY:
1503 case LyXRC::RC_COMPLETION_POPUP_MATH:
1504 case LyXRC::RC_COMPLETION_POPUP_TEXT:
1505 case LyXRC::RC_USELASTFILEPOS:
1506 case LyXRC::RC_LOADSESSION:
1507 case LyXRC::RC_CHKTEX_COMMAND:
1508 case LyXRC::RC_CONVERTER:
1509 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1510 case LyXRC::RC_COPIER:
1511 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1512 case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1513 case LyXRC::RC_DATE_INSERT_FORMAT:
1514 case LyXRC::RC_DEFAULT_LANGUAGE:
1515 case LyXRC::RC_GUI_LANGUAGE:
1516 case LyXRC::RC_DEFAULT_PAPERSIZE:
1517 case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1518 case LyXRC::RC_DEFFILE:
1519 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1520 case LyXRC::RC_DISPLAY_GRAPHICS:
1521 case LyXRC::RC_DOCUMENTPATH:
1522 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1523 FileName path(lyxrc_new.document_path);
1524 if (path.exists() && path.isDirectory())
1525 package().document_dir() = FileName(lyxrc.document_path);
1527 case LyXRC::RC_EDITOR_ALTERNATIVES:
1528 case LyXRC::RC_ESC_CHARS:
1529 case LyXRC::RC_EXAMPLEPATH:
1530 case LyXRC::RC_FONT_ENCODING:
1531 case LyXRC::RC_FORMAT:
1532 case LyXRC::RC_GROUP_LAYOUTS:
1533 case LyXRC::RC_HUNSPELLDIR_PATH:
1534 case LyXRC::RC_INDEX_ALTERNATIVES:
1535 case LyXRC::RC_INDEX_COMMAND:
1536 case LyXRC::RC_JBIBTEX_COMMAND:
1537 case LyXRC::RC_JINDEX_COMMAND:
1538 case LyXRC::RC_NOMENCL_COMMAND:
1539 case LyXRC::RC_INPUT:
1540 case LyXRC::RC_KBMAP:
1541 case LyXRC::RC_KBMAP_PRIMARY:
1542 case LyXRC::RC_KBMAP_SECONDARY:
1543 case LyXRC::RC_LABEL_INIT_LENGTH:
1544 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1545 case LyXRC::RC_LANGUAGE_AUTO_END:
1546 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1547 case LyXRC::RC_LANGUAGE_COMMAND_END:
1548 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1549 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1550 case LyXRC::RC_LANGUAGE_PACKAGE:
1551 case LyXRC::RC_LANGUAGE_USE_BABEL:
1552 case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1553 case LyXRC::RC_MACRO_EDIT_STYLE:
1554 case LyXRC::RC_MAKE_BACKUP:
1555 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1556 case LyXRC::RC_MOUSE_WHEEL_SPEED:
1557 case LyXRC::RC_NUMLASTFILES:
1558 case LyXRC::RC_PARAGRAPH_MARKERS:
1559 case LyXRC::RC_PATH_PREFIX:
1560 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1561 prependEnvPath("PATH", lyxrc.path_prefix);
1563 case LyXRC::RC_PERS_DICT:
1564 case LyXRC::RC_PREVIEW:
1565 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1566 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1567 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1568 case LyXRC::RC_PRINTCOPIESFLAG:
1569 case LyXRC::RC_PRINTER:
1570 case LyXRC::RC_PRINTEVENPAGEFLAG:
1571 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1572 case LyXRC::RC_PRINTFILEEXTENSION:
1573 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1574 case LyXRC::RC_PRINTODDPAGEFLAG:
1575 case LyXRC::RC_PRINTPAGERANGEFLAG:
1576 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1577 case LyXRC::RC_PRINTPAPERFLAG:
1578 case LyXRC::RC_PRINTREVERSEFLAG:
1579 case LyXRC::RC_PRINTSPOOL_COMMAND:
1580 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1581 case LyXRC::RC_PRINTTOFILE:
1582 case LyXRC::RC_PRINTTOPRINTER:
1583 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1584 case LyXRC::RC_PRINT_COMMAND:
1585 case LyXRC::RC_RTL_SUPPORT:
1586 case LyXRC::RC_SCREEN_DPI:
1587 case LyXRC::RC_SCREEN_FONT_ROMAN:
1588 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1589 case LyXRC::RC_SCREEN_FONT_SANS:
1590 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1591 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1592 case LyXRC::RC_SCREEN_FONT_SIZES:
1593 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1594 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1595 case LyXRC::RC_GEOMETRY_SESSION:
1596 case LyXRC::RC_SCREEN_ZOOM:
1597 case LyXRC::RC_SERVERPIPE:
1598 case LyXRC::RC_SET_COLOR:
1599 case LyXRC::RC_SHOW_BANNER:
1600 case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1601 case LyXRC::RC_SPELL_COMMAND:
1602 case LyXRC::RC_SPELLCHECKER:
1603 case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1604 case LyXRC::RC_SPLITINDEX_COMMAND:
1605 case LyXRC::RC_TEMPDIRPATH:
1606 case LyXRC::RC_TEMPLATEPATH:
1607 case LyXRC::RC_TEX_ALLOWS_SPACES:
1608 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1609 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1610 os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1612 case LyXRC::RC_THESAURUSDIRPATH:
1613 case LyXRC::RC_UIFILE:
1614 case LyXRC::RC_USER_EMAIL:
1615 case LyXRC::RC_USER_NAME:
1616 case LyXRC::RC_USETEMPDIR:
1617 case LyXRC::RC_USE_ALT_LANG:
1618 case LyXRC::RC_USE_CONVERTER_CACHE:
1619 case LyXRC::RC_USE_ESC_CHARS:
1620 case LyXRC::RC_USE_INP_ENC:
1621 case LyXRC::RC_USE_PERS_DICT:
1622 case LyXRC::RC_USE_TOOLTIP:
1623 case LyXRC::RC_USE_PIXMAP_CACHE:
1624 case LyXRC::RC_USE_SPELL_LIB:
1625 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1626 case LyXRC::RC_SORT_LAYOUTS:
1627 case LyXRC::RC_FULL_SCREEN_LIMIT:
1628 case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1629 case LyXRC::RC_FULL_SCREEN_MENUBAR:
1630 case LyXRC::RC_FULL_SCREEN_TABBAR:
1631 case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1632 case LyXRC::RC_FULL_SCREEN_WIDTH:
1633 case LyXRC::RC_VISUAL_CURSOR:
1634 case LyXRC::RC_VIEWER:
1635 case LyXRC::RC_VIEWER_ALTERNATIVES:
1636 case LyXRC::RC_LAST: