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.
25 #include "BranchList.h"
27 #include "buffer_funcs.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
31 #include "bufferview_funcs.h"
33 #include "CutAndPaste.h"
35 #include "DispatchResult.h"
37 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
44 #include "InsetIterator.h"
52 #include "LyXAction.h"
58 #include "TextClassList.h"
60 #include "Paragraph.h"
61 #include "ParIterator.h"
62 #include "ParagraphParameters.h"
65 #include "insets/InsetBox.h"
66 #include "insets/InsetBranch.h"
67 #include "insets/InsetCommand.h"
68 #include "insets/InsetERT.h"
69 #include "insets/InsetExternal.h"
70 #include "insets/InsetFloat.h"
71 #include "insets/InsetListings.h"
72 #include "insets/InsetGraphics.h"
73 #include "insets/InsetInclude.h"
74 #include "insets/InsetNote.h"
75 #include "insets/InsetTabular.h"
76 #include "insets/InsetVSpace.h"
77 #include "insets/InsetWrap.h"
79 #include "frontends/Application.h"
80 #include "frontends/alert.h"
81 #include "frontends/Dialogs.h"
82 #include "frontends/FileDialog.h"
83 #include "frontends/FontLoader.h"
84 #include "frontends/Gui.h"
85 #include "frontends/KeySymbol.h"
86 #include "frontends/LyXView.h"
87 #include "frontends/Menubar.h"
88 #include "frontends/Toolbars.h"
89 #include "frontends/Selection.h"
91 #include "support/environment.h"
92 #include "support/FileFilterList.h"
93 #include "support/filetools.h"
94 #include "support/ForkedcallsController.h"
95 #include "support/fs_extras.h"
96 #include "support/lstrings.h"
97 #include "support/Path.h"
98 #include "support/Package.h"
99 #include "support/Systemcall.h"
100 #include "support/convert.h"
101 #include "support/os.h"
103 #include <boost/current_function.hpp>
104 #include <boost/filesystem/operations.hpp>
109 using std::make_pair;
112 using std::istringstream;
113 using std::ostringstream;
115 namespace fs = boost::filesystem;
119 using bv_funcs::freefont2string;
121 using frontend::LyXView;
123 using support::absolutePath;
124 using support::addName;
125 using support::addPath;
126 using support::bformat;
127 using support::changeExtension;
128 using support::contains;
129 using support::FileFilterList;
130 using support::FileName;
131 using support::fileSearch;
132 using support::ForkedcallsController;
133 using support::i18nLibFileSearch;
134 using support::isDirWriteable;
135 using support::isFileReadable;
136 using support::isStrInt;
137 using support::makeAbsPath;
138 using support::makeDisplayPath;
139 using support::package;
140 using support::quoteName;
141 using support::rtrim;
142 using support::split;
143 using support::subst;
144 using support::Systemcall;
145 using support::token;
147 using support::prefixIs;
149 namespace Alert = frontend::Alert;
154 bool getLocalStatus(Cursor cursor,
155 FuncRequest const & cmd, FuncStatus & status)
157 // Try to fix cursor in case it is broken.
158 cursor.fixIfBroken();
160 // This is, of course, a mess. Better create a new doc iterator and use
161 // this in Inset::getStatus. This might require an additional
162 // BufferView * arg, though (which should be avoided)
163 //Cursor safe = *this;
165 for ( ; cursor.depth(); cursor.pop()) {
166 //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
167 BOOST_ASSERT(cursor.idx() <= cursor.lastidx());
168 BOOST_ASSERT(cursor.pit() <= cursor.lastpit());
169 BOOST_ASSERT(cursor.pos() <= cursor.lastpos());
171 // The inset's getStatus() will return 'true' if it made
172 // a definitive decision on whether it want to handle the
173 // request or not. The result of this decision is put into
174 // the 'status' parameter.
175 if (cursor.inset().getStatus(cursor, cmd, status)) {
184 /** Return the change status at cursor position, taking in account the
185 * status at each level of the document iterator (a table in a deleted
186 * footnote is deleted).
187 * When \param outer is true, the top slice is not looked at.
189 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
191 size_t const depth = dit.depth() - (outer ? 1 : 0);
193 for (size_t i = 0 ; i < depth ; ++i) {
194 CursorSlice const & slice = dit[i];
195 if (!slice.inset().inMathed()
196 && slice.pos() < slice.paragraph().size()) {
197 Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
198 if (ch != Change::UNCHANGED)
202 return Change::UNCHANGED;
210 meta_fake_bit(key_modifier::none)
215 void LyXFunc::initKeySequences(KeyMap * kb)
217 keyseq.reset(new KeySequence(kb, kb));
218 cancel_meta_seq.reset(new KeySequence(kb, kb));
222 void LyXFunc::setLyXView(LyXView * lv)
224 if (!quitting && lyx_view_ && lyx_view_ != lv)
225 // save current selection to the selection buffer to allow
226 // middle-button paste in another window
227 cap::saveSelection(lyx_view_->view()->cursor());
232 void LyXFunc::handleKeyFunc(kb_action action)
234 char_type c = encoded_last_key;
236 if (keyseq->length())
239 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
240 lyx_view_->view()->getIntl().getTransManager().deadkey(
241 c, get_accent(action).accent, view()->cursor().innerText(), view()->cursor());
242 // Need to clear, in case the minibuffer calls these
245 // copied verbatim from do_accent_char
246 view()->cursor().resetAnchor();
251 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
253 BOOST_ASSERT(lyx_view_);
254 if (!LyX::ref().session().bookmarks().isValid(idx))
256 BookmarksSection::Bookmark const & bm = LyX::ref().session().bookmarks().bookmark(idx);
257 BOOST_ASSERT(!bm.filename.empty());
258 string const file = bm.filename.absFilename();
259 // if the file is not opened, open it.
260 if (!theBufferList().exists(file)) {
262 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
266 // open may fail, so we need to test it again
267 if (theBufferList().exists(file)) {
268 // if the current buffer is not that one, switch to it.
269 if (lyx_view_->buffer()->fileName() != file) {
271 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
275 // moveToPosition use par_id, and par_pit and return new par_id.
279 boost::tie(new_pit, new_pos, new_id) = view()->moveToPosition(bm.bottom_pit, bm.bottom_pos, bm.top_id, bm.top_pos);
280 // if bottom_pit, bottom_pos or top_id has been changed, update bookmark
281 // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
282 if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos || bm.top_id != new_id )
283 const_cast<BookmarksSection::Bookmark &>(bm).updatePos(new_pit, new_pos, new_id);
288 void LyXFunc::processKeySym(KeySymbolPtr keysym, key_modifier::state state)
290 LYXERR(Debug::KEY) << "KeySym is " << keysym->getSymbolName() << endl;
292 // Do nothing if we have nothing (JMarc)
293 if (!keysym->isOK()) {
294 LYXERR(Debug::KEY) << "Empty kbd action (probably composing)"
299 if (keysym->isModifier()) {
300 LYXERR(Debug::KEY) << "isModifier true" << endl;
304 //Encoding const * encoding = view()->cursor().getEncoding();
305 //encoded_last_key = keysym->getISOEncoded(encoding ? encoding->name() : "");
306 // FIXME: encoded_last_key shadows the member variable of the same
307 // name. Is that intended?
308 char_type encoded_last_key = keysym->getUCSEncoded();
310 // Do a one-deep top-level lookup for
311 // cancel and meta-fake keys. RVDK_PATCH_5
312 cancel_meta_seq->reset();
314 FuncRequest func = cancel_meta_seq->addkey(keysym, state);
315 LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
316 << " action first set to [" << func.action << ']'
319 // When not cancel or meta-fake, do the normal lookup.
320 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
321 // Mostly, meta_fake_bit = key_modifier::none. RVDK_PATCH_5.
322 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) {
323 // remove Caps Lock and Mod2 as a modifiers
324 func = keyseq->addkey(keysym, (state | meta_fake_bit));
325 LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
326 << "action now set to ["
327 << func.action << ']' << endl;
330 // Dont remove this unless you know what you are doing.
331 meta_fake_bit = key_modifier::none;
333 // Can this happen now ?
334 if (func.action == LFUN_NOACTION) {
335 func = FuncRequest(LFUN_COMMAND_PREFIX);
338 LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
340 << func.action << "]["
341 << to_utf8(keyseq->print(false)) << ']'
344 // already here we know if it any point in going further
345 // why not return already here if action == -1 and
346 // num_bytes == 0? (Lgb)
348 if (keyseq->length() > 1) {
349 lyx_view_->message(keyseq->print(true));
353 // Maybe user can only reach the key via holding down shift.
354 // Let's see. But only if shift is the only modifier
355 if (func.action == LFUN_UNKNOWN_ACTION &&
356 state == key_modifier::shift) {
357 LYXERR(Debug::KEY) << "Trying without shift" << endl;
358 func = keyseq->addkey(keysym, key_modifier::none);
359 LYXERR(Debug::KEY) << "Action now " << func.action << endl;
362 if (func.action == LFUN_UNKNOWN_ACTION) {
363 // Hmm, we didn't match any of the keysequences. See
364 // if it's normal insertable text not already covered
366 if (keysym->isText() && keyseq->length() == 1) {
367 LYXERR(Debug::KEY) << "isText() is true, inserting." << endl;
368 func = FuncRequest(LFUN_SELF_INSERT,
369 FuncRequest::KEYBOARD);
371 LYXERR(Debug::KEY) << "Unknown, !isText() - giving up" << endl;
372 lyx_view_->message(_("Unknown function."));
377 if (func.action == LFUN_SELF_INSERT) {
378 if (encoded_last_key != 0) {
379 docstring const arg(1, encoded_last_key);
380 dispatch(FuncRequest(LFUN_SELF_INSERT, arg,
381 FuncRequest::KEYBOARD));
383 << "SelfInsert arg[`" << to_utf8(arg) << "']" << endl;
391 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
393 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
396 Cursor & cur = view()->cursor();
398 /* In LyX/Mac, when a dialog is open, the menus of the
399 application can still be accessed without giving focus to
400 the main window. In this case, we want to disable the menu
401 entries that are buffer-related.
403 Note that this code is not perfect, as bug 1941 attests:
404 http://bugzilla.lyx.org/show_bug.cgi?id=1941#c4
406 Buffer * buf = lyx_view_? lyx_view_->buffer() : 0;
407 if (lyx_view_ && cmd.origin == FuncRequest::MENU && !lyx_view_->hasFocus())
410 if (cmd.action == LFUN_NOACTION) {
411 flag.message(from_utf8(N_("Nothing to do")));
416 switch (cmd.action) {
417 case LFUN_UNKNOWN_ACTION:
418 #ifndef HAVE_LIBAIKSAURUS
419 case LFUN_THESAURUS_ENTRY:
429 if (flag.unknown()) {
430 flag.message(from_utf8(N_("Unknown action")));
434 if (!flag.enabled()) {
435 if (flag.message().empty())
436 flag.message(from_utf8(N_("Command disabled")));
440 // Check whether we need a buffer
441 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
443 flag.message(from_utf8(N_("Command not allowed with"
444 "out any document open")));
449 // I would really like to avoid having this switch and rather try to
450 // encode this in the function itself.
451 // -- And I'd rather let an inset decide which LFUNs it is willing
452 // to handle (Andre')
454 switch (cmd.action) {
455 case LFUN_BUFFER_TOGGLE_READ_ONLY:
456 flag.setOnOff(buf->isReadonly());
459 case LFUN_BUFFER_SWITCH:
460 // toggle on the current buffer, but do not toggle off
461 // the other ones (is that a good idea?)
462 if (buf && to_utf8(cmd.argument()) == buf->fileName())
466 case LFUN_BUFFER_EXPORT:
467 enable = cmd.argument() == "custom"
468 || Exporter::isExportable(*buf, to_utf8(cmd.argument()));
471 case LFUN_BUFFER_CHKTEX:
472 enable = buf->isLatex() && !lyxrc.chktex_command.empty();
475 case LFUN_BUILD_PROGRAM:
476 enable = Exporter::isExportable(*buf, "program");
479 case LFUN_LAYOUT_TABULAR:
480 enable = cur.innerInsetOfType(Inset::TABULAR_CODE);
484 case LFUN_LAYOUT_PARAGRAPH:
485 enable = !cur.inset().forceDefaultParagraphs(cur.idx());
488 case LFUN_VC_REGISTER:
489 enable = !buf->lyxvc().inUse();
491 case LFUN_VC_CHECK_IN:
492 enable = buf->lyxvc().inUse() && !buf->isReadonly();
494 case LFUN_VC_CHECK_OUT:
495 enable = buf->lyxvc().inUse() && buf->isReadonly();
498 case LFUN_VC_UNDO_LAST:
499 enable = buf->lyxvc().inUse();
501 case LFUN_BUFFER_RELOAD:
502 enable = !buf->isUnnamed() && fs::exists(buf->fileName())
503 && (!buf->isClean() || buf->isExternallyModified(Buffer::timestamp_method));
506 case LFUN_INSET_SETTINGS: {
510 Inset::Code code = cur.inset().lyxCode();
512 case Inset::TABULAR_CODE:
513 enable = cmd.argument() == "tabular";
515 case Inset::ERT_CODE:
516 enable = cmd.argument() == "ert";
518 case Inset::FLOAT_CODE:
519 enable = cmd.argument() == "float";
521 case Inset::WRAP_CODE:
522 enable = cmd.argument() == "wrap";
524 case Inset::NOTE_CODE:
525 enable = cmd.argument() == "note";
527 case Inset::BRANCH_CODE:
528 enable = cmd.argument() == "branch";
530 case Inset::BOX_CODE:
531 enable = cmd.argument() == "box";
533 case Inset::LISTINGS_CODE:
534 enable = cmd.argument() == "listings";
542 case LFUN_INSET_APPLY: {
543 string const name = cmd.getArg(0);
544 Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
546 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
548 if (!inset->getStatus(cur, fr, fs)) {
549 // Every inset is supposed to handle this
554 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
555 flag |= getStatus(fr);
557 enable = flag.enabled();
561 case LFUN_DIALOG_TOGGLE:
562 flag.setOnOff(lyx_view_->getDialogs().visible(cmd.getArg(0)));
563 // fall through to set "enable"
564 case LFUN_DIALOG_SHOW: {
565 string const name = cmd.getArg(0);
567 enable = name == "aboutlyx"
568 || name == "file" //FIXME: should be removed.
570 || name == "texinfo";
571 else if (name == "print")
572 enable = Exporter::isExportable(*buf, "dvi")
573 && lyxrc.print_command != "none";
574 else if (name == "character")
575 enable = cur.inset().lyxCode() != Inset::ERT_CODE &&
576 cur.inset().lyxCode() != Inset::LISTINGS_CODE;
577 else if (name == "latexlog")
578 enable = isFileReadable(FileName(buf->getLogName().second));
579 else if (name == "spellchecker")
580 #if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
581 enable = !buf->isReadonly();
585 else if (name == "vclog")
586 enable = buf->lyxvc().inUse();
590 case LFUN_DIALOG_SHOW_NEW_INSET:
591 enable = cur.inset().lyxCode() != Inset::ERT_CODE &&
592 cur.inset().lyxCode() != Inset::LISTINGS_CODE;
593 if (cur.inset().lyxCode() == Inset::CAPTION_CODE) {
595 if (cur.inset().getStatus(cur, cmd, flag))
600 case LFUN_DIALOG_UPDATE: {
601 string const name = cmd.getArg(0);
603 enable = name == "prefs";
607 case LFUN_CITATION_INSERT: {
608 FuncRequest fr(LFUN_INSET_INSERT, "citation");
609 enable = getStatus(fr).enabled();
613 case LFUN_BUFFER_WRITE: {
614 enable = lyx_view_->buffer()->isUnnamed()
615 || !lyx_view_->buffer()->isClean();
620 case LFUN_BUFFER_WRITE_ALL: {
621 // We enable the command only if there are some modified buffers
622 Buffer * first = theBufferList().first();
623 bool modified = false;
627 // We cannot use a for loop as the buffer list is a cycle.
633 b = theBufferList().next(b);
634 } while (b != first);
642 case LFUN_BOOKMARK_GOTO: {
643 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
644 enable = LyX::ref().session().bookmarks().isValid(num);
648 case LFUN_BOOKMARK_CLEAR:
649 enable = LyX::ref().session().bookmarks().size() > 0;
652 case LFUN_TOOLBAR_TOGGLE: {
653 bool const current = lyx_view_->getToolbars().visible(cmd.getArg(0));
654 flag.setOnOff(current);
657 case LFUN_WINDOW_CLOSE: {
658 enable = (theApp()->gui().viewIds().size() > 1);
662 // this one is difficult to get right. As a half-baked
663 // solution, we consider only the first action of the sequence
664 case LFUN_COMMAND_SEQUENCE: {
665 // argument contains ';'-terminated commands
666 string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
667 FuncRequest func(lyxaction.lookupFunc(firstcmd));
668 func.origin = cmd.origin;
669 flag = getStatus(func);
672 case LFUN_BUFFER_NEW:
673 case LFUN_BUFFER_NEW_TEMPLATE:
674 case LFUN_WORD_FIND_FORWARD:
675 case LFUN_WORD_FIND_BACKWARD:
676 case LFUN_COMMAND_PREFIX:
677 case LFUN_COMMAND_EXECUTE:
679 case LFUN_META_PREFIX:
680 case LFUN_BUFFER_CLOSE:
681 case LFUN_BUFFER_WRITE_AS:
682 case LFUN_BUFFER_UPDATE:
683 case LFUN_BUFFER_VIEW:
684 case LFUN_BUFFER_IMPORT:
685 case LFUN_BUFFER_AUTO_SAVE:
686 case LFUN_RECONFIGURE:
690 case LFUN_DROP_LAYOUTS_CHOICE:
692 case LFUN_SERVER_GET_NAME:
693 case LFUN_SERVER_NOTIFY:
694 case LFUN_SERVER_GOTO_FILE_ROW:
695 case LFUN_DIALOG_HIDE:
696 case LFUN_DIALOG_DISCONNECT_INSET:
697 case LFUN_BUFFER_CHILD_OPEN:
698 case LFUN_TOGGLE_CURSOR_FOLLOWS_SCROLLBAR:
699 case LFUN_KEYMAP_OFF:
700 case LFUN_KEYMAP_PRIMARY:
701 case LFUN_KEYMAP_SECONDARY:
702 case LFUN_KEYMAP_TOGGLE:
704 case LFUN_BUFFER_EXPORT_CUSTOM:
705 case LFUN_BUFFER_PRINT:
706 case LFUN_PREFERENCES_SAVE:
707 case LFUN_SCREEN_FONT_UPDATE:
710 case LFUN_EXTERNAL_EDIT:
711 case LFUN_GRAPHICS_EDIT:
712 case LFUN_ALL_INSETS_TOGGLE:
713 case LFUN_BUFFER_LANGUAGE:
714 case LFUN_TEXTCLASS_APPLY:
715 case LFUN_TEXTCLASS_LOAD:
716 case LFUN_BUFFER_SAVE_AS_DEFAULT:
717 case LFUN_BUFFER_PARAMS_APPLY:
718 case LFUN_LYXRC_APPLY:
719 case LFUN_BUFFER_NEXT:
720 case LFUN_BUFFER_PREVIOUS:
721 case LFUN_WINDOW_NEW:
723 // these are handled in our dispatch()
727 if (!getLocalStatus(cur, cmd, flag))
728 flag = view()->getStatus(cmd);
734 // Can we use a readonly buffer?
735 if (buf && buf->isReadonly()
736 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
737 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
738 flag.message(from_utf8(N_("Document is read-only")));
742 // Are we in a DELETED change-tracking region?
743 if (buf && lookupChangeType(cur, true) == Change::DELETED
744 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
745 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
746 flag.message(from_utf8(N_("This portion of the document is deleted.")));
750 // the default error message if we disable the command
751 if (!flag.enabled() && flag.message().empty())
752 flag.message(from_utf8(N_("Command disabled")));
758 bool LyXFunc::ensureBufferClean(BufferView * bv)
760 Buffer & buf = *bv->buffer();
764 docstring const file = makeDisplayPath(buf.fileName(), 30);
765 docstring text = bformat(_("The document %1$s has unsaved "
766 "changes.\n\nDo you want to save "
767 "the document?"), file);
768 int const ret = Alert::prompt(_("Save changed document?"),
769 text, 0, 1, _("&Save"),
773 dispatch(FuncRequest(LFUN_BUFFER_WRITE));
775 return buf.isClean();
781 void showPrintError(string const & name)
783 docstring str = bformat(_("Could not print the document %1$s.\n"
784 "Check that your printer is set up correctly."),
785 makeDisplayPath(name, 50));
786 Alert::error(_("Print document failed"), str);
790 void loadTextclass(string const & name)
792 std::pair<bool, textclass_type> const tc_pair =
793 textclasslist.numberOfClass(name);
795 if (!tc_pair.first) {
796 lyxerr << "Document class \"" << name
797 << "\" does not exist."
802 textclass_type const tc = tc_pair.second;
804 if (!textclasslist[tc].load()) {
805 docstring s = bformat(_("The document could not be converted\n"
806 "into the document class %1$s."),
807 from_utf8(textclasslist[tc].name()));
808 Alert::error(_("Could not change class"), s);
813 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
818 void LyXFunc::dispatch(FuncRequest const & cmd)
820 string const argument = to_utf8(cmd.argument());
821 kb_action const action = cmd.action;
823 LYXERR(Debug::ACTION) << endl << "LyXFunc::dispatch: cmd: " << cmd << endl;
824 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
826 // we have not done anything wrong yet.
828 dispatch_buffer.erase();
830 // redraw the screen at the end (first of the two drawing steps).
831 //This is done unless explicitely requested otherwise
832 Update::flags updateFlags = Update::FitCursor;
834 FuncStatus const flag = getStatus(cmd);
835 if (!flag.enabled()) {
836 // We cannot use this function here
837 LYXERR(Debug::ACTION) << "LyXFunc::dispatch: "
838 << lyxaction.getActionName(action)
839 << " [" << action << "] is disabled at this location"
841 setErrorMessage(flag.message());
845 case LFUN_WORD_FIND_FORWARD:
846 case LFUN_WORD_FIND_BACKWARD: {
847 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
848 static docstring last_search;
849 docstring searched_string;
851 if (!cmd.argument().empty()) {
852 last_search = cmd.argument();
853 searched_string = cmd.argument();
855 searched_string = last_search;
858 if (searched_string.empty())
861 bool const fw = action == LFUN_WORD_FIND_FORWARD;
862 docstring const data =
863 find2string(searched_string, true, false, fw);
864 find(view(), FuncRequest(LFUN_WORD_FIND, data));
868 case LFUN_COMMAND_PREFIX:
869 BOOST_ASSERT(lyx_view_);
870 lyx_view_->message(keyseq->printOptions(true));
873 case LFUN_COMMAND_EXECUTE:
874 BOOST_ASSERT(lyx_view_);
875 lyx_view_->getToolbars().display("minibuffer", true);
876 lyx_view_->focus_command_buffer();
880 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
882 meta_fake_bit = key_modifier::none;
883 if (lyx_view_->buffer())
884 // cancel any selection
885 dispatch(FuncRequest(LFUN_MARK_OFF));
886 setMessage(from_ascii(N_("Cancel")));
889 case LFUN_META_PREFIX:
890 meta_fake_bit = key_modifier::alt;
891 setMessage(keyseq->print(true));
894 case LFUN_BUFFER_TOGGLE_READ_ONLY:
895 BOOST_ASSERT(lyx_view_ && lyx_view_->view() && lyx_view_->buffer());
896 if (lyx_view_->buffer()->lyxvc().inUse())
897 lyx_view_->buffer()->lyxvc().toggleReadOnly();
899 lyx_view_->buffer()->setReadonly(
900 !lyx_view_->buffer()->isReadonly());
903 // --- Menus -----------------------------------------------
904 case LFUN_BUFFER_NEW:
905 menuNew(argument, false);
908 case LFUN_BUFFER_NEW_TEMPLATE:
909 menuNew(argument, true);
912 case LFUN_BUFFER_CLOSE:
917 case LFUN_BUFFER_WRITE:
918 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
919 if (!lyx_view_->buffer()->isUnnamed()) {
920 docstring const str = bformat(_("Saving document %1$s..."),
921 makeDisplayPath(lyx_view_->buffer()->fileName()));
922 lyx_view_->message(str);
923 menuWrite(lyx_view_->buffer());
924 lyx_view_->message(str + _(" done."));
926 writeAs(lyx_view_->buffer());
928 updateFlags = Update::None;
931 case LFUN_BUFFER_WRITE_AS:
932 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
933 writeAs(lyx_view_->buffer(), argument);
934 updateFlags = Update::None;
937 case LFUN_BUFFER_WRITE_ALL: {
938 Buffer * first = theBufferList().first();
941 lyx_view_->message(_("Saving all documents..."));
943 // We cannot use a for loop as the buffer list cycles.
946 if (!b->isUnnamed()) {
948 lyxerr[Debug::ACTION] << "Saved " << b->fileName() << endl;
952 b = theBufferList().next(b);
953 } while (b != first);
954 lyx_view_->message(_("All documents saved."));
957 updateFlags = Update::None;
961 case LFUN_BUFFER_RELOAD: {
962 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
963 docstring const file = makeDisplayPath(lyx_view_->buffer()->fileName(), 20);
964 docstring text = bformat(_("Any changes will be lost. Are you sure "
965 "you want to revert to the saved version of the document %1$s?"), file);
966 int const ret = Alert::prompt(_("Revert to saved document?"),
967 text, 1, 1, _("&Revert"), _("&Cancel"));
974 case LFUN_BUFFER_UPDATE:
975 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
976 Exporter::Export(lyx_view_->buffer(), argument, true);
979 case LFUN_BUFFER_VIEW:
980 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
981 Exporter::preview(lyx_view_->buffer(), argument);
984 case LFUN_BUILD_PROGRAM:
985 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
986 Exporter::Export(lyx_view_->buffer(), "program", true);
989 case LFUN_BUFFER_CHKTEX:
990 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
991 lyx_view_->buffer()->runChktex();
994 case LFUN_BUFFER_EXPORT:
995 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
996 if (argument == "custom")
997 lyx_view_->getDialogs().show("sendto");
999 Exporter::Export(lyx_view_->buffer(), argument, false);
1003 case LFUN_BUFFER_EXPORT_CUSTOM: {
1004 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1006 string command = split(argument, format_name, ' ');
1007 Format const * format = formats.getFormat(format_name);
1009 lyxerr << "Format \"" << format_name
1010 << "\" not recognized!"
1015 Buffer * buffer = lyx_view_->buffer();
1017 // The name of the file created by the conversion process
1020 // Output to filename
1021 if (format->name() == "lyx") {
1022 string const latexname =
1023 buffer->getLatexName(false);
1024 filename = changeExtension(latexname,
1025 format->extension());
1026 filename = addName(buffer->temppath(), filename);
1028 if (!buffer->writeFile(FileName(filename)))
1032 Exporter::Export(buffer, format_name, true, filename);
1035 // Substitute $$FName for filename
1036 if (!contains(command, "$$FName"))
1037 command = "( " + command + " ) < $$FName";
1038 command = subst(command, "$$FName", filename);
1040 // Execute the command in the background
1042 call.startscript(Systemcall::DontWait, command);
1046 case LFUN_BUFFER_PRINT: {
1047 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1048 // FIXME: cmd.getArg() might fail if one of the arguments
1049 // contains double quotes
1050 string target = cmd.getArg(0);
1051 string target_name = cmd.getArg(1);
1052 string command = cmd.getArg(2);
1055 || target_name.empty()
1056 || command.empty()) {
1057 lyxerr << "Unable to parse \""
1058 << argument << '"' << endl;
1061 if (target != "printer" && target != "file") {
1062 lyxerr << "Unrecognized target \""
1063 << target << '"' << endl;
1067 Buffer * buffer = lyx_view_->buffer();
1069 if (!Exporter::Export(buffer, "dvi", true)) {
1070 showPrintError(buffer->fileName());
1074 // Push directory path.
1075 string const path(buffer->temppath());
1076 // Prevent the compiler from optimizing away p
1078 support::Path p(pp);
1080 // there are three cases here:
1081 // 1. we print to a file
1082 // 2. we print directly to a printer
1083 // 3. we print using a spool command (print to file first)
1086 string const dviname =
1087 changeExtension(buffer->getLatexName(true),
1090 if (target == "printer") {
1091 if (!lyxrc.print_spool_command.empty()) {
1092 // case 3: print using a spool
1093 string const psname =
1094 changeExtension(dviname,".ps");
1095 command += ' ' + lyxrc.print_to_file
1098 + quoteName(dviname);
1101 lyxrc.print_spool_command + ' ';
1102 if (target_name != "default") {
1103 command2 += lyxrc.print_spool_printerprefix
1107 command2 += quoteName(psname);
1109 // If successful, then spool command
1110 res = one.startscript(
1115 res = one.startscript(
1116 Systemcall::DontWait,
1119 // case 2: print directly to a printer
1120 if (target_name != "default")
1121 command += ' ' + lyxrc.print_to_printer + target_name + ' ';
1122 res = one.startscript(
1123 Systemcall::DontWait,
1124 command + quoteName(dviname));
1128 // case 1: print to a file
1129 FileName const filename(makeAbsPath(target_name,
1130 lyx_view_->buffer()->filePath()));
1131 FileName const dvifile(makeAbsPath(dviname, path));
1132 if (fs::exists(filename.toFilesystemEncoding())) {
1133 docstring text = bformat(
1134 _("The file %1$s already exists.\n\n"
1135 "Do you want to overwrite that file?"),
1136 makeDisplayPath(filename.absFilename()));
1137 if (Alert::prompt(_("Overwrite file?"),
1138 text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
1141 command += ' ' + lyxrc.print_to_file
1142 + quoteName(filename.toFilesystemEncoding())
1144 + quoteName(dvifile.toFilesystemEncoding());
1145 res = one.startscript(Systemcall::DontWait,
1150 showPrintError(buffer->fileName());
1154 case LFUN_BUFFER_IMPORT:
1159 // quitting is triggered by the gui code
1160 // (leaving the event loop).
1161 lyx_view_->message(from_utf8(N_("Exiting.")));
1162 if (theBufferList().quitWriteAll())
1163 theApp()->gui().closeAllViews();
1166 case LFUN_BUFFER_AUTO_SAVE:
1170 case LFUN_RECONFIGURE:
1171 BOOST_ASSERT(lyx_view_);
1172 reconfigure(*lyx_view_);
1175 case LFUN_HELP_OPEN: {
1176 BOOST_ASSERT(lyx_view_);
1177 string const arg = argument;
1179 setErrorMessage(from_ascii(N_("Missing argument")));
1182 FileName const fname = i18nLibFileSearch("doc", arg, "lyx");
1183 if (fname.empty()) {
1184 lyxerr << "LyX: unable to find documentation file `"
1185 << arg << "'. Bad installation?" << endl;
1188 lyx_view_->message(bformat(_("Opening help file %1$s..."),
1189 makeDisplayPath(fname.absFilename())));
1190 lyx_view_->loadLyXFile(fname, false);
1194 // --- version control -------------------------------
1195 case LFUN_VC_REGISTER:
1196 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1197 if (!ensureBufferClean(view()))
1199 if (!lyx_view_->buffer()->lyxvc().inUse()) {
1200 lyx_view_->buffer()->lyxvc().registrer();
1203 updateFlags = Update::Force;
1206 case LFUN_VC_CHECK_IN:
1207 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1208 if (!ensureBufferClean(view()))
1210 if (lyx_view_->buffer()->lyxvc().inUse()
1211 && !lyx_view_->buffer()->isReadonly()) {
1212 lyx_view_->buffer()->lyxvc().checkIn();
1217 case LFUN_VC_CHECK_OUT:
1218 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1219 if (!ensureBufferClean(view()))
1221 if (lyx_view_->buffer()->lyxvc().inUse()
1222 && lyx_view_->buffer()->isReadonly()) {
1223 lyx_view_->buffer()->lyxvc().checkOut();
1228 case LFUN_VC_REVERT:
1229 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1230 lyx_view_->buffer()->lyxvc().revert();
1234 case LFUN_VC_UNDO_LAST:
1235 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1236 lyx_view_->buffer()->lyxvc().undoLast();
1240 // --- buffers ----------------------------------------
1241 case LFUN_BUFFER_SWITCH:
1242 BOOST_ASSERT(lyx_view_);
1243 lyx_view_->setBuffer(theBufferList().getBuffer(argument));
1244 updateFlags = Update::Force;
1247 case LFUN_BUFFER_NEXT:
1248 BOOST_ASSERT(lyx_view_);
1249 lyx_view_->setBuffer(theBufferList().next(lyx_view_->buffer()));
1250 updateFlags = Update::Force;
1253 case LFUN_BUFFER_PREVIOUS:
1254 BOOST_ASSERT(lyx_view_);
1255 lyx_view_->setBuffer(theBufferList().previous(lyx_view_->buffer()));
1256 updateFlags = Update::Force;
1260 BOOST_ASSERT(lyx_view_);
1261 newFile(*lyx_view_, argument);
1264 case LFUN_FILE_OPEN:
1265 BOOST_ASSERT(lyx_view_);
1269 case LFUN_DROP_LAYOUTS_CHOICE:
1270 BOOST_ASSERT(lyx_view_);
1271 lyx_view_->getToolbars().openLayoutList();
1274 case LFUN_MENU_OPEN:
1275 BOOST_ASSERT(lyx_view_);
1276 lyx_view_->getMenubar().openByName(from_utf8(argument));
1279 // --- lyxserver commands ----------------------------
1280 case LFUN_SERVER_GET_NAME:
1281 BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
1282 setMessage(from_utf8(lyx_view_->buffer()->fileName()));
1283 LYXERR(Debug::INFO) << "FNAME["
1284 << lyx_view_->buffer()->fileName()
1288 case LFUN_SERVER_NOTIFY:
1289 dispatch_buffer = keyseq->print(false);
1290 theServer().notifyClient(to_utf8(dispatch_buffer));
1293 case LFUN_SERVER_GOTO_FILE_ROW: {
1294 BOOST_ASSERT(lyx_view_);
1297 istringstream is(argument);
1298 is >> file_name >> row;
1299 if (prefixIs(file_name, package().temp_dir().absFilename())) {
1300 // Needed by inverse dvi search. If it is a file
1301 // in tmpdir, call the apropriated function
1302 lyx_view_->setBuffer(theBufferList().getBufferFromTmp(file_name));
1304 // Must replace extension of the file to be .lyx
1305 // and get full path
1306 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
1307 // Either change buffer or load the file
1308 if (theBufferList().exists(s.absFilename())) {
1309 lyx_view_->setBuffer(theBufferList().getBuffer(s.absFilename()));
1311 lyx_view_->loadLyXFile(s);
1315 view()->setCursorFromRow(row);
1317 updateFlags = Update::FitCursor;
1321 case LFUN_DIALOG_SHOW: {
1322 BOOST_ASSERT(lyx_view_);
1323 string const name = cmd.getArg(0);
1324 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1326 if (name == "character") {
1327 data = freefont2string();
1329 lyx_view_->getDialogs().show("character", data);
1330 } else if (name == "latexlog") {
1331 pair<Buffer::LogType, string> const logfile =
1332 lyx_view_->buffer()->getLogName();
1333 switch (logfile.first) {
1334 case Buffer::latexlog:
1337 case Buffer::buildlog:
1341 data += Lexer::quoteString(logfile.second);
1342 lyx_view_->getDialogs().show("log", data);
1343 } else if (name == "vclog") {
1344 string const data = "vc " +
1345 Lexer::quoteString(lyx_view_->buffer()->lyxvc().getLogFile());
1346 lyx_view_->getDialogs().show("log", data);
1348 lyx_view_->getDialogs().show(name, data);
1352 case LFUN_DIALOG_SHOW_NEW_INSET: {
1353 BOOST_ASSERT(lyx_view_);
1354 string const name = cmd.getArg(0);
1355 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1356 if (name == "bibitem" ||
1360 name == "nomenclature" ||
1364 InsetCommandParams p(name);
1365 data = InsetCommandMailer::params2string(name, p);
1366 } else if (name == "include") {
1367 // data is the include type: one of "include",
1368 // "input", "verbatiminput" or "verbatiminput*"
1370 // default type is requested
1372 InsetCommandParams p(data);
1373 data = InsetIncludeMailer::params2string(p);
1374 } else if (name == "box") {
1375 // \c data == "Boxed" || "Frameless" etc
1376 InsetBoxParams p(data);
1377 data = InsetBoxMailer::params2string(p);
1378 } else if (name == "branch") {
1379 InsetBranchParams p;
1380 data = InsetBranchMailer::params2string(p);
1381 } else if (name == "citation") {
1382 InsetCommandParams p("cite");
1383 data = InsetCommandMailer::params2string(name, p);
1384 } else if (name == "ert") {
1385 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1386 } else if (name == "external") {
1387 InsetExternalParams p;
1388 Buffer const & buffer = *lyx_view_->buffer();
1389 data = InsetExternalMailer::params2string(p, buffer);
1390 } else if (name == "float") {
1392 data = InsetFloatMailer::params2string(p);
1393 } else if (name == "listings") {
1394 InsetListingsParams p;
1395 data = InsetListingsMailer::params2string(p);
1396 } else if (name == "graphics") {
1397 InsetGraphicsParams p;
1398 Buffer const & buffer = *lyx_view_->buffer();
1399 data = InsetGraphicsMailer::params2string(p, buffer);
1400 } else if (name == "note") {
1402 data = InsetNoteMailer::params2string(p);
1403 } else if (name == "vspace") {
1405 data = InsetVSpaceMailer::params2string(space);
1406 } else if (name == "wrap") {
1408 data = InsetWrapMailer::params2string(p);
1410 lyx_view_->getDialogs().show(name, data, 0);
1414 case LFUN_DIALOG_UPDATE: {
1415 BOOST_ASSERT(lyx_view_);
1416 string const & name = argument;
1417 // Can only update a dialog connected to an existing inset
1418 Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
1420 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument());
1421 inset->dispatch(view()->cursor(), fr);
1422 } else if (name == "paragraph") {
1423 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1424 } else if (name == "prefs") {
1425 lyx_view_->getDialogs().update(name, string());
1430 case LFUN_DIALOG_HIDE:
1431 LyX::cref().hideDialogs(argument, 0);
1434 case LFUN_DIALOG_TOGGLE: {
1435 BOOST_ASSERT(lyx_view_);
1436 if (lyx_view_->getDialogs().visible(cmd.getArg(0)))
1437 dispatch(FuncRequest(LFUN_DIALOG_HIDE, argument));
1439 dispatch(FuncRequest(LFUN_DIALOG_SHOW, argument));
1443 case LFUN_DIALOG_DISCONNECT_INSET:
1444 BOOST_ASSERT(lyx_view_);
1445 lyx_view_->getDialogs().disconnect(argument);
1449 case LFUN_CITATION_INSERT: {
1450 BOOST_ASSERT(lyx_view_);
1451 if (!argument.empty()) {
1452 // we can have one optional argument, delimited by '|'
1453 // citation-insert <key>|<text_before>
1454 // this should be enhanced to also support text_after
1455 // and citation style
1456 string arg = argument;
1458 if (contains(argument, "|")) {
1459 arg = token(argument, '|', 0);
1460 opt1 = token(argument, '|', 1);
1462 InsetCommandParams icp("cite");
1463 icp["key"] = from_utf8(arg);
1465 icp["before"] = from_utf8(opt1);
1466 string icstr = InsetCommandMailer::params2string("citation", icp);
1467 FuncRequest fr(LFUN_INSET_INSERT, icstr);
1470 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
1474 case LFUN_BUFFER_CHILD_OPEN: {
1475 // takes an optional argument, "|bool", at the end
1476 // indicating whether this file is being opened automatically
1477 // by LyX itself, in which case we will not want to switch
1478 // buffers after opening. The default is false, so in practice
1479 // it is used only when true.
1480 BOOST_ASSERT(lyx_view_);
1481 int const arglength = argument.length();
1483 bool autoOpen = false;
1484 if (argument.substr(arglength - 5, 5) == "|true") {
1486 filename = makeAbsPath(argument.substr(0, arglength - 5),
1487 lyx_view_->buffer()->filePath());
1488 } else if (argument.substr(arglength - 6, 6) == "|false") {
1489 filename = makeAbsPath(argument.substr(0, arglength - 6),
1490 lyx_view_->buffer()->filePath());
1492 makeAbsPath(argument, lyx_view_->buffer()->filePath());
1493 view()->saveBookmark(false);
1494 if (theBufferList().exists(filename.absFilename())) {
1495 Buffer * buf = theBufferList().getBuffer(filename.absFilename());
1497 lyx_view_->setBuffer(buf, true);
1499 buf->setParentName(lyx_view_->buffer()->fileName());
1501 lyx_view_->loadLyXFile(filename, true, true, autoOpen);
1503 // If a screen update is required (in case where auto_open is false),
1504 // loadLyXFile() would have taken care of it already. Otherwise we shall
1505 // reset the update flag because it can cause a circular problem.
1507 updateFlags = Update::None;
1511 case LFUN_TOGGLE_CURSOR_FOLLOWS_SCROLLBAR:
1512 BOOST_ASSERT(lyx_view_);
1513 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1516 case LFUN_KEYMAP_OFF:
1517 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1518 lyx_view_->view()->getIntl().keyMapOn(false);
1521 case LFUN_KEYMAP_PRIMARY:
1522 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1523 lyx_view_->view()->getIntl().keyMapPrim();
1526 case LFUN_KEYMAP_SECONDARY:
1527 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1528 lyx_view_->view()->getIntl().keyMapSec();
1531 case LFUN_KEYMAP_TOGGLE:
1532 BOOST_ASSERT(lyx_view_ && lyx_view_->view());
1533 lyx_view_->view()->getIntl().toggleKeyMap();
1539 string rest = split(argument, countstr, ' ');
1540 istringstream is(countstr);
1543 lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1544 for (int i = 0; i < count; ++i)
1545 dispatch(lyxaction.lookupFunc(rest));
1549 case LFUN_COMMAND_SEQUENCE: {
1550 // argument contains ';'-terminated commands
1551 string arg = argument;
1552 while (!arg.empty()) {
1554 arg = split(arg, first, ';');
1555 FuncRequest func(lyxaction.lookupFunc(first));
1556 func.origin = cmd.origin;
1562 case LFUN_PREFERENCES_SAVE: {
1563 lyxrc.write(makeAbsPath("preferences",
1564 package().user_support().absFilename()),
1569 case LFUN_SCREEN_FONT_UPDATE:
1570 BOOST_ASSERT(lyx_view_);
1571 // handle the screen font changes.
1572 theFontLoader().update();
1573 /// FIXME: only the current view will be updated. the Gui
1574 /// class is able to furnish the list of views.
1575 updateFlags = Update::Force;
1578 case LFUN_SET_COLOR: {
1580 string const x11_name = split(argument, lyx_name, ' ');
1581 if (lyx_name.empty() || x11_name.empty()) {
1582 setErrorMessage(from_ascii(N_(
1583 "Syntax: set-color <lyx_name>"
1588 bool const graphicsbg_changed =
1589 (lyx_name == lcolor.getLyXName(Color::graphicsbg) &&
1590 x11_name != lcolor.getX11Name(Color::graphicsbg));
1592 if (!lcolor.setColor(lyx_name, x11_name)) {
1594 bformat(_("Set-color \"%1$s\" failed "
1595 "- color is undefined or "
1596 "may not be redefined"),
1597 from_utf8(lyx_name)));
1601 theApp()->updateColor(lcolor.getFromLyXName(lyx_name));
1603 if (graphicsbg_changed) {
1604 // FIXME: The graphics cache no longer has a changeDisplay method.
1606 graphics::GCache::get().changeDisplay(true);
1613 BOOST_ASSERT(lyx_view_);
1614 lyx_view_->message(from_utf8(argument));
1617 case LFUN_EXTERNAL_EDIT: {
1618 BOOST_ASSERT(lyx_view_);
1619 FuncRequest fr(action, argument);
1620 InsetExternal().dispatch(view()->cursor(), fr);
1624 case LFUN_GRAPHICS_EDIT: {
1625 FuncRequest fr(action, argument);
1626 InsetGraphics().dispatch(view()->cursor(), fr);
1630 case LFUN_INSET_APPLY: {
1631 BOOST_ASSERT(lyx_view_);
1632 string const name = cmd.getArg(0);
1633 Inset * inset = lyx_view_->getDialogs().getOpenInset(name);
1635 FuncRequest fr(LFUN_INSET_MODIFY, argument);
1636 inset->dispatch(view()->cursor(), fr);
1638 FuncRequest fr(LFUN_INSET_INSERT, argument);
1641 // ideally, the update flag should be set by the insets,
1642 // but this is not possible currently
1643 updateFlags = Update::Force | Update::FitCursor;
1647 case LFUN_ALL_INSETS_TOGGLE: {
1648 BOOST_ASSERT(lyx_view_);
1650 string const name = split(argument, action, ' ');
1651 Inset::Code const inset_code =
1652 Inset::translate(name);
1654 Cursor & cur = view()->cursor();
1655 FuncRequest fr(LFUN_INSET_TOGGLE, action);
1657 Inset & inset = lyx_view_->buffer()->inset();
1658 InsetIterator it = inset_iterator_begin(inset);
1659 InsetIterator const end = inset_iterator_end(inset);
1660 for (; it != end; ++it) {
1661 if (!it->asInsetMath()
1662 && (inset_code == Inset::NO_CODE
1663 || inset_code == it->lyxCode())) {
1664 Cursor tmpcur = cur;
1665 tmpcur.pushLeft(*it);
1666 it->dispatch(tmpcur, fr);
1669 updateFlags = Update::Force | Update::FitCursor;
1673 case LFUN_BUFFER_LANGUAGE: {
1674 BOOST_ASSERT(lyx_view_);
1675 Buffer & buffer = *lyx_view_->buffer();
1676 Language const * oldL = buffer.params().language;
1677 Language const * newL = languages.getLanguage(argument);
1678 if (!newL || oldL == newL)
1681 if (oldL->rightToLeft() == newL->rightToLeft()
1682 && !buffer.isMultiLingual())
1683 buffer.changeLanguage(oldL, newL);
1687 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1688 string const fname =
1689 addName(addPath(package().user_support().absFilename(), "templates/"),
1691 Buffer defaults(fname);
1693 istringstream ss(argument);
1696 int const unknown_tokens = defaults.readHeader(lex);
1698 if (unknown_tokens != 0) {
1699 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1700 << unknown_tokens << " unknown token"
1701 << (unknown_tokens == 1 ? "" : "s")
1705 if (defaults.writeFile(FileName(defaults.fileName())))
1706 setMessage(bformat(_("Document defaults saved in %1$s"),
1707 makeDisplayPath(fname)));
1709 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1713 case LFUN_BUFFER_PARAMS_APPLY: {
1714 BOOST_ASSERT(lyx_view_);
1715 biblio::CiteEngine const engine =
1716 lyx_view_->buffer()->params().getEngine();
1718 istringstream ss(argument);
1721 int const unknown_tokens =
1722 lyx_view_->buffer()->readHeader(lex);
1724 if (unknown_tokens != 0) {
1725 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1726 << unknown_tokens << " unknown token"
1727 << (unknown_tokens == 1 ? "" : "s")
1730 if (engine == lyx_view_->buffer()->params().getEngine())
1733 Cursor & cur = view()->cursor();
1734 FuncRequest fr(LFUN_INSET_REFRESH);
1736 Inset & inset = lyx_view_->buffer()->inset();
1737 InsetIterator it = inset_iterator_begin(inset);
1738 InsetIterator const end = inset_iterator_end(inset);
1739 for (; it != end; ++it)
1740 if (it->lyxCode() == Inset::CITE_CODE)
1741 it->dispatch(cur, fr);
1745 case LFUN_TEXTCLASS_APPLY: {
1746 BOOST_ASSERT(lyx_view_);
1747 Buffer * buffer = lyx_view_->buffer();
1749 textclass_type const old_class =
1750 buffer->params().textclass;
1752 loadTextclass(argument);
1754 std::pair<bool, textclass_type> const tc_pair =
1755 textclasslist.numberOfClass(argument);
1760 textclass_type const new_class = tc_pair.second;
1761 if (old_class == new_class)
1765 lyx_view_->message(_("Converting document to new document class..."));
1766 recordUndoFullDocument(view());
1767 buffer->params().textclass = new_class;
1768 StableDocIterator backcur(view()->cursor());
1769 ErrorList & el = buffer->errorList("Class Switch");
1770 cap::switchBetweenClasses(
1771 old_class, new_class,
1772 static_cast<InsetText &>(buffer->inset()), el);
1774 view()->setCursor(backcur.asDocIterator(&(buffer->inset())));
1776 buffer->errors("Class Switch");
1777 updateLabels(*buffer);
1778 updateFlags = Update::Force | Update::FitCursor;
1782 case LFUN_TEXTCLASS_LOAD:
1783 loadTextclass(argument);
1786 case LFUN_LYXRC_APPLY: {
1787 LyXRC const lyxrc_orig = lyxrc;
1789 istringstream ss(argument);
1790 bool const success = lyxrc.read(ss) == 0;
1793 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1794 << "Unable to read lyxrc data"
1799 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1801 /// We force the redraw in any case because there might be
1802 /// some screen font changes.
1803 /// FIXME: only the current view will be updated. the Gui
1804 /// class is able to furnish the list of views.
1805 updateFlags = Update::Force;
1809 case LFUN_WINDOW_NEW:
1810 LyX::ref().newLyXView();
1813 case LFUN_WINDOW_CLOSE:
1814 BOOST_ASSERT(lyx_view_);
1815 BOOST_ASSERT(theApp());
1816 // update bookmark pit of the current buffer before window close
1817 for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
1818 gotoBookmark(i+1, false, false);
1819 // ask the user for saving changes or cancel quit
1820 if (!theBufferList().quitWriteAll())
1825 case LFUN_BOOKMARK_GOTO:
1826 // go to bookmark, open unopened file and switch to buffer if necessary
1827 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1830 case LFUN_BOOKMARK_CLEAR:
1831 LyX::ref().session().bookmarks().clear();
1834 case LFUN_TOOLBAR_TOGGLE: {
1835 BOOST_ASSERT(lyx_view_);
1836 string const name = cmd.getArg(0);
1837 bool const allowauto = cmd.getArg(1) == "allowauto";
1838 lyx_view_->toggleToolbarState(name, allowauto);
1839 ToolbarInfo * tbi = lyx_view_->getToolbarInfo(name);
1841 setMessage(bformat(_("Unknown toolbar \"%1$s\""),
1846 if (tbi->flags & ToolbarInfo::ON)
1848 else if (tbi->flags & ToolbarInfo::OFF)
1850 else if (tbi->flags & ToolbarInfo::AUTO)
1853 setMessage(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
1854 _(tbi->gui_name), state));
1859 BOOST_ASSERT(lyx_view_);
1860 view()->cursor().dispatch(cmd);
1861 updateFlags = view()->cursor().result().update();
1862 if (!view()->cursor().result().dispatched())
1863 updateFlags = view()->dispatch(cmd);
1868 if (lyx_view_ && lyx_view_->buffer()) {
1869 // BufferView::update() updates the ViewMetricsInfo and
1870 // also initializes the position cache for all insets in
1871 // (at least partially) visible top-level paragraphs.
1872 // We will redraw the screen only if needed.
1873 if (view()->update(updateFlags)) {
1874 // Buffer::changed() signals that a repaint is needed.
1875 // The frontend (WorkArea) knows which area to repaint
1876 // thanks to the ViewMetricsInfo updated above.
1877 lyx_view_->buffer()->changed();
1880 lyx_view_->updateStatusBar();
1882 // if we executed a mutating lfun, mark the buffer as dirty
1884 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1885 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1886 lyx_view_->buffer()->markDirty();
1888 //Do we have a selection?
1889 theSelection().haveSelection(view()->cursor().selection());
1891 if (view()->cursor().inTexted()) {
1892 lyx_view_->updateLayoutChoice();
1896 if (!quitting && lyx_view_) {
1897 lyx_view_->updateMenubar();
1898 lyx_view_->updateToolbars();
1899 // Some messages may already be translated, so we cannot use _()
1900 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1905 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1907 const bool verbose = (cmd.origin == FuncRequest::MENU
1908 || cmd.origin == FuncRequest::TOOLBAR
1909 || cmd.origin == FuncRequest::COMMANDBUFFER);
1911 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1912 LYXERR(Debug::ACTION) << "dispatch msg is " << to_utf8(msg) << endl;
1914 lyx_view_->message(msg);
1918 docstring dispatch_msg = msg;
1919 if (!dispatch_msg.empty())
1920 dispatch_msg += ' ';
1922 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1924 bool argsadded = false;
1926 if (!cmd.argument().empty()) {
1927 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1928 comname += ' ' + cmd.argument();
1933 docstring const shortcuts = theTopLevelKeymap().printbindings(cmd);
1935 if (!shortcuts.empty())
1936 comname += ": " + shortcuts;
1937 else if (!argsadded && !cmd.argument().empty())
1938 comname += ' ' + cmd.argument();
1940 if (!comname.empty()) {
1941 comname = rtrim(comname);
1942 dispatch_msg += '(' + rtrim(comname) + ')';
1945 LYXERR(Debug::ACTION) << "verbose dispatch msg "
1946 << to_utf8(dispatch_msg) << endl;
1947 if (!dispatch_msg.empty())
1948 lyx_view_->message(dispatch_msg);
1952 void LyXFunc::menuNew(string const & name, bool fromTemplate)
1954 // FIXME: initpath is not used. What to do?
1955 string initpath = lyxrc.document_path;
1956 string filename(name);
1958 if (lyx_view_->buffer()) {
1959 string const trypath = lyx_view_->buffer()->filePath();
1960 // If directory is writeable, use this as default.
1961 if (isDirWriteable(FileName(trypath)))
1965 static int newfile_number;
1967 if (filename.empty()) {
1968 filename = addName(lyxrc.document_path,
1969 "newfile" + convert<string>(++newfile_number) + ".lyx");
1970 while (theBufferList().exists(filename) ||
1971 fs::is_readable(FileName(filename).toFilesystemEncoding())) {
1973 filename = addName(lyxrc.document_path,
1974 "newfile" + convert<string>(newfile_number) +
1979 // The template stuff
1982 FileDialog fileDlg(_("Select template file"),
1983 LFUN_SELECT_FILE_SYNC,
1984 make_pair(_("Documents|#o#O"), from_utf8(lyxrc.document_path)),
1985 make_pair(_("Templates|#T#t"), from_utf8(lyxrc.template_path)));
1987 FileDialog::Result result =
1988 fileDlg.open(from_utf8(lyxrc.template_path),
1989 FileFilterList(_("LyX Documents (*.lyx)")),
1992 if (result.first == FileDialog::Later)
1994 if (result.second.empty())
1996 templname = to_utf8(result.second);
1999 Buffer * const b = newFile(filename, templname, !name.empty());
2002 lyx_view_->setBuffer(b);
2007 void LyXFunc::open(string const & fname)
2009 string initpath = lyxrc.document_path;
2011 if (lyx_view_->buffer()) {
2012 string const trypath = lyx_view_->buffer()->filePath();
2013 // If directory is writeable, use this as default.
2014 if (isDirWriteable(FileName(trypath)))
2020 if (fname.empty()) {
2021 FileDialog fileDlg(_("Select document to open"),
2023 make_pair(_("Documents|#o#O"), from_utf8(lyxrc.document_path)),
2024 make_pair(_("Examples|#E#e"), from_utf8(addPath(package().system_support().absFilename(), "examples"))));
2026 FileDialog::Result result =
2027 fileDlg.open(from_utf8(initpath),
2028 FileFilterList(_("LyX Documents (*.lyx)")),
2031 if (result.first == FileDialog::Later)
2034 filename = to_utf8(result.second);
2036 // check selected filename
2037 if (filename.empty()) {
2038 lyx_view_->message(_("Canceled."));
2044 // get absolute path of file and add ".lyx" to the filename if
2046 FileName const fullname = fileSearch(string(), filename, "lyx");
2047 if (!fullname.empty())
2048 filename = fullname.absFilename();
2050 // if the file doesn't exist, let the user create one
2051 if (!fs::exists(fullname.toFilesystemEncoding())) {
2052 // the user specifically chose this name. Believe him.
2053 Buffer * const b = newFile(filename, string(), true);
2055 lyx_view_->setBuffer(b);
2059 docstring const disp_fn = makeDisplayPath(filename);
2060 lyx_view_->message(bformat(_("Opening document %1$s..."), disp_fn));
2063 if (lyx_view_->loadLyXFile(fullname)) {
2064 str2 = bformat(_("Document %1$s opened."), disp_fn);
2066 str2 = bformat(_("Could not open document %1$s"), disp_fn);
2068 lyx_view_->message(str2);
2072 void LyXFunc::doImport(string const & argument)
2075 string filename = split(argument, format, ' ');
2077 LYXERR(Debug::INFO) << "LyXFunc::doImport: " << format
2078 << " file: " << filename << endl;
2080 // need user interaction
2081 if (filename.empty()) {
2082 string initpath = lyxrc.document_path;
2084 if (lyx_view_->buffer()) {
2085 string const trypath = lyx_view_->buffer()->filePath();
2086 // If directory is writeable, use this as default.
2087 if (isDirWriteable(FileName(trypath)))
2091 docstring const text = bformat(_("Select %1$s file to import"),
2092 formats.prettyName(format));
2094 FileDialog fileDlg(text,
2096 make_pair(_("Documents|#o#O"), from_utf8(lyxrc.document_path)),
2097 make_pair(_("Examples|#E#e"),
2098 from_utf8(addPath(package().system_support().absFilename(), "examples"))));
2100 docstring filter = formats.prettyName(format);
2103 filter += from_utf8(formats.extension(format));
2106 FileDialog::Result result =
2107 fileDlg.open(from_utf8(initpath),
2108 FileFilterList(filter),
2111 if (result.first == FileDialog::Later)
2114 filename = to_utf8(result.second);
2116 // check selected filename
2117 if (filename.empty())
2118 lyx_view_->message(_("Canceled."));
2121 if (filename.empty())
2124 // get absolute path of file
2125 FileName const fullname(makeAbsPath(filename));
2127 FileName const lyxfile(changeExtension(fullname.absFilename(), ".lyx"));
2129 // Check if the document already is open
2130 if (use_gui && theBufferList().exists(lyxfile.absFilename())) {
2131 if (!theBufferList().close(theBufferList().getBuffer(lyxfile.absFilename()), true)) {
2132 lyx_view_->message(_("Canceled."));
2137 // if the file exists already, and we didn't do
2138 // -i lyx thefile.lyx, warn
2139 if (fs::exists(lyxfile.toFilesystemEncoding()) && fullname != lyxfile) {
2140 docstring const file = makeDisplayPath(lyxfile.absFilename(), 30);
2142 docstring text = bformat(_("The document %1$s already exists.\n\n"
2143 "Do you want to overwrite that document?"), file);
2144 int const ret = Alert::prompt(_("Overwrite document?"),
2145 text, 0, 1, _("&Overwrite"), _("&Cancel"));
2148 lyx_view_->message(_("Canceled."));
2153 ErrorList errorList;
2154 Importer::Import(lyx_view_, fullname, format, errorList);
2155 // FIXME (Abdel 12/08/06): Is there a need to display the error list here?
2159 void LyXFunc::closeBuffer()
2161 // goto bookmark to update bookmark pit.
2162 for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i)
2163 gotoBookmark(i+1, false, false);
2165 theBufferList().close(lyx_view_->buffer(), true);
2169 void LyXFunc::reloadBuffer()
2171 FileName filename(lyx_view_->buffer()->fileName());
2173 lyx_view_->loadLyXFile(filename);
2176 // Each "lyx_view_" should have it's own message method. lyxview and
2177 // the minibuffer would use the minibuffer, but lyxserver would
2178 // send an ERROR signal to its client. Alejandro 970603
2179 // This function is bit problematic when it comes to NLS, to make the
2180 // lyx servers client be language indepenent we must not translate
2181 // strings sent to this func.
2182 void LyXFunc::setErrorMessage(docstring const & m) const
2184 dispatch_buffer = m;
2189 void LyXFunc::setMessage(docstring const & m) const
2191 dispatch_buffer = m;
2195 docstring const LyXFunc::viewStatusMessage()
2197 // When meta-fake key is pressed, show the key sequence so far + "M-".
2199 return keyseq->print(true) + "M-";
2201 // Else, when a non-complete key sequence is pressed,
2202 // show the available options.
2203 if (keyseq->length() > 0 && !keyseq->deleted())
2204 return keyseq->printOptions(true);
2206 BOOST_ASSERT(lyx_view_);
2207 if (!lyx_view_->buffer())
2208 return _("Welcome to LyX!");
2210 return view()->cursor().currentState();
2214 BufferView * LyXFunc::view() const
2216 BOOST_ASSERT(lyx_view_);
2217 return lyx_view_->view();
2221 bool LyXFunc::wasMetaKey() const
2223 return (meta_fake_bit != key_modifier::none);
2229 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
2231 // Why the switch you might ask. It is a trick to ensure that all
2232 // the elements in the LyXRCTags enum is handled. As you can see
2233 // there are no breaks at all. So it is just a huge fall-through.
2234 // The nice thing is that we will get a warning from the compiler
2235 // if we forget an element.
2236 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
2238 case LyXRC::RC_ACCEPT_COMPOUND:
2239 case LyXRC::RC_ALT_LANG:
2240 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
2241 case LyXRC::RC_PLAINTEXT_LINELEN:
2242 case LyXRC::RC_AUTOREGIONDELETE:
2243 case LyXRC::RC_AUTORESET_OPTIONS:
2244 case LyXRC::RC_AUTOSAVE:
2245 case LyXRC::RC_AUTO_NUMBER:
2246 case LyXRC::RC_BACKUPDIR_PATH:
2247 case LyXRC::RC_BIBTEX_COMMAND:
2248 case LyXRC::RC_BINDFILE:
2249 case LyXRC::RC_CHECKLASTFILES:
2250 case LyXRC::RC_USELASTFILEPOS:
2251 case LyXRC::RC_LOADSESSION:
2252 case LyXRC::RC_CHKTEX_COMMAND:
2253 case LyXRC::RC_CONVERTER:
2254 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
2255 case LyXRC::RC_COPIER:
2256 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
2257 case LyXRC::RC_CUSTOM_EXPORT_COMMAND:
2258 case LyXRC::RC_CUSTOM_EXPORT_FORMAT:
2259 case LyXRC::RC_DATE_INSERT_FORMAT:
2260 case LyXRC::RC_DEFAULT_LANGUAGE:
2261 case LyXRC::RC_DEFAULT_PAPERSIZE:
2262 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
2263 case LyXRC::RC_DISPLAY_GRAPHICS:
2264 case LyXRC::RC_DOCUMENTPATH:
2265 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
2266 string const encoded = FileName(
2267 lyxrc_new.document_path).toFilesystemEncoding();
2268 if (fs::exists(encoded) && fs::is_directory(encoded))
2269 support::package().document_dir() = FileName(lyxrc.document_path);
2271 case LyXRC::RC_ESC_CHARS:
2272 case LyXRC::RC_FONT_ENCODING:
2273 case LyXRC::RC_FORMAT:
2274 case LyXRC::RC_INDEX_COMMAND:
2275 case LyXRC::RC_INPUT:
2276 case LyXRC::RC_KBMAP:
2277 case LyXRC::RC_KBMAP_PRIMARY:
2278 case LyXRC::RC_KBMAP_SECONDARY:
2279 case LyXRC::RC_LABEL_INIT_LENGTH:
2280 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
2281 case LyXRC::RC_LANGUAGE_AUTO_END:
2282 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
2283 case LyXRC::RC_LANGUAGE_COMMAND_END:
2284 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
2285 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
2286 case LyXRC::RC_LANGUAGE_PACKAGE:
2287 case LyXRC::RC_LANGUAGE_USE_BABEL:
2288 case LyXRC::RC_MAKE_BACKUP:
2289 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
2290 case LyXRC::RC_NUMLASTFILES:
2291 case LyXRC::RC_PATH_PREFIX:
2292 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
2293 support::prependEnvPath("PATH", lyxrc.path_prefix);
2295 case LyXRC::RC_PERS_DICT:
2296 case LyXRC::RC_PREVIEW:
2297 case LyXRC::RC_PREVIEW_HASHED_LABELS:
2298 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
2299 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
2300 case LyXRC::RC_PRINTCOPIESFLAG:
2301 case LyXRC::RC_PRINTER:
2302 case LyXRC::RC_PRINTEVENPAGEFLAG:
2303 case LyXRC::RC_PRINTEXSTRAOPTIONS:
2304 case LyXRC::RC_PRINTFILEEXTENSION:
2305 case LyXRC::RC_PRINTLANDSCAPEFLAG:
2306 case LyXRC::RC_PRINTODDPAGEFLAG:
2307 case LyXRC::RC_PRINTPAGERANGEFLAG:
2308 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
2309 case LyXRC::RC_PRINTPAPERFLAG:
2310 case LyXRC::RC_PRINTREVERSEFLAG:
2311 case LyXRC::RC_PRINTSPOOL_COMMAND:
2312 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
2313 case LyXRC::RC_PRINTTOFILE:
2314 case LyXRC::RC_PRINTTOPRINTER:
2315 case LyXRC::RC_PRINT_ADAPTOUTPUT:
2316 case LyXRC::RC_PRINT_COMMAND:
2317 case LyXRC::RC_RTL_SUPPORT:
2318 case LyXRC::RC_SCREEN_DPI:
2319 case LyXRC::RC_SCREEN_FONT_ROMAN:
2320 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
2321 case LyXRC::RC_SCREEN_FONT_SANS:
2322 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
2323 case LyXRC::RC_SCREEN_FONT_SCALABLE:
2324 case LyXRC::RC_SCREEN_FONT_SIZES:
2325 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
2326 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
2327 case LyXRC::RC_SCREEN_GEOMETRY_HEIGHT:
2328 case LyXRC::RC_SCREEN_GEOMETRY_WIDTH:
2329 case LyXRC::RC_SCREEN_GEOMETRY_XYSAVED:
2330 case LyXRC::RC_SCREEN_ZOOM:
2331 case LyXRC::RC_SERVERPIPE:
2332 case LyXRC::RC_SET_COLOR:
2333 case LyXRC::RC_SHOW_BANNER:
2334 case LyXRC::RC_SPELL_COMMAND:
2335 case LyXRC::RC_TEMPDIRPATH:
2336 case LyXRC::RC_TEMPLATEPATH:
2337 case LyXRC::RC_TEX_ALLOWS_SPACES:
2338 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
2339 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
2340 support::os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
2342 case LyXRC::RC_UIFILE:
2343 case LyXRC::RC_USER_EMAIL:
2344 case LyXRC::RC_USER_NAME:
2345 case LyXRC::RC_USETEMPDIR:
2346 case LyXRC::RC_USE_ALT_LANG:
2347 case LyXRC::RC_USE_CONVERTER_CACHE:
2348 case LyXRC::RC_USE_ESC_CHARS:
2349 case LyXRC::RC_USE_INP_ENC:
2350 case LyXRC::RC_USE_PERS_DICT:
2351 case LyXRC::RC_USE_SPELL_LIB:
2352 case LyXRC::RC_VIEWDVI_PAPEROPTION:
2353 case LyXRC::RC_VIEWER:
2354 case LyXRC::RC_LAST: