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 "BranchList.h"
26 #include "buffer_funcs.h"
27 #include "bufferlist.h"
28 #include "bufferparams.h"
29 #include "BufferView.h"
31 #include "CutAndPaste.h"
33 #include "dispatchresult.h"
35 #include "errorlist.h"
38 #include "funcrequest.h"
41 #include "insetiterator.h"
47 #include "LyXAction.h"
52 #include "lyxserver.h"
53 #include "lyxtextclasslist.h"
55 #include "paragraph.h"
56 #include "pariterator.h"
57 #include "ParagraphParameters.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/insetnote.h"
68 #include "insets/insettabular.h"
69 #include "insets/insetvspace.h"
70 #include "insets/insetwrap.h"
72 #include "frontends/Alert.h"
73 #include "frontends/Dialogs.h"
74 #include "frontends/FileDialog.h"
75 #include "frontends/lyx_gui.h"
76 #include "frontends/LyXKeySym.h"
77 #include "frontends/LyXView.h"
78 #include "frontends/Menubar.h"
79 #include "frontends/Toolbars.h"
81 #include "support/environment.h"
82 #include "support/filefilterlist.h"
83 #include "support/filetools.h"
84 #include "support/forkedcontr.h"
85 #include "support/fs_extras.h"
86 #include "support/lstrings.h"
87 #include "support/path.h"
88 #include "support/package.h"
89 #include "support/systemcall.h"
90 #include "support/convert.h"
91 #include "support/os.h"
93 #include <boost/filesystem/operations.hpp>
97 using bv_funcs::freefont2string;
99 using lyx::support::AbsolutePath;
100 using lyx::support::AddName;
101 using lyx::support::AddPath;
102 using lyx::support::bformat;
103 using lyx::support::ChangeExtension;
104 using lyx::support::contains;
105 using lyx::support::FileFilterList;
106 using lyx::support::FileSearch;
107 using lyx::support::ForkedcallsController;
108 using lyx::support::i18nLibFileSearch;
109 using lyx::support::IsDirWriteable;
110 using lyx::support::IsFileReadable;
111 using lyx::support::isStrInt;
112 using lyx::support::MakeAbsPath;
113 using lyx::support::MakeDisplayPath;
114 using lyx::support::package;
115 using lyx::support::Path;
116 using lyx::support::QuoteName;
117 using lyx::support::rtrim;
118 using lyx::support::split;
119 using lyx::support::subst;
120 using lyx::support::Systemcall;
121 using lyx::support::token;
122 using lyx::support::trim;
123 using lyx::support::prefixIs;
126 using std::make_pair;
129 using std::istringstream;
131 namespace biblio = lyx::biblio;
132 namespace fs = boost::filesystem;
135 extern BufferList bufferlist;
136 extern LyXServer * lyxserver;
138 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
141 extern tex_accent_struct get_accent(kb_action action);
146 bool getStatus(LCursor cursor,
147 FuncRequest const & cmd, FuncStatus & status)
149 // This is, of course, a mess. Better create a new doc iterator and use
150 // this in Inset::getStatus. This might require an additional
151 // BufferView * arg, though (which should be avoided)
152 //LCursor safe = *this;
154 for ( ; cursor.depth(); cursor.pop()) {
155 //lyxerr << "\nLCursor::getStatus: cmd: " << cmd << endl << *this << endl;
156 DocIterator::idx_type & idx = cursor.idx();
157 DocIterator::idx_type const lastidx = cursor.lastidx();
160 lyxerr << "wrong idx " << idx << ", max is " << lastidx
161 << ". Trying to correct this." << endl;
165 DocIterator::pit_type & pit = cursor.pit();
166 DocIterator::pit_type const lastpit = cursor.lastpit();
169 lyxerr << "wrong par " << pit << ", max is " << lastpit
170 << ". Trying to correct this." << endl;
174 DocIterator::pos_type & pos = cursor.pos();
175 DocIterator::pos_type const lastpos = cursor.lastpos();
178 lyxerr << "wrong pos " << pos << ", max is " << lastpos
179 << ". Trying to correct this." << endl;
183 // The inset's getStatus() will return 'true' if it made
184 // a definitive decision on whether it want to handle the
185 // request or not. The result of this decision is put into
186 // the 'status' parameter.
187 if (cursor.inset().getStatus(cursor, cmd, status)) {
197 LyXFunc::LyXFunc(LyXView * lv)
200 keyseq(toplevel_keymap.get(), toplevel_keymap.get()),
201 cancel_meta_seq(toplevel_keymap.get(), toplevel_keymap.get()),
202 meta_fake_bit(key_modifier::none)
207 void LyXFunc::handleKeyFunc(kb_action action)
209 char c = encoded_last_key;
211 if (keyseq.length()) {
215 owner->getIntl().getTransManager()
216 .deadkey(c, get_accent(action).accent, view()->getLyXText());
217 // Need to clear, in case the minibuffer calls these
220 // copied verbatim from do_accent_char
221 view()->cursor().resetAnchor();
226 void LyXFunc::processKeySym(LyXKeySymPtr keysym, key_modifier::state state)
228 lyxerr[Debug::KEY] << "KeySym is " << keysym->getSymbolName() << endl;
230 // Do nothing if we have nothing (JMarc)
231 if (!keysym->isOK()) {
232 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
237 if (keysym->isModifier()) {
238 lyxerr[Debug::KEY] << "isModifier true" << endl;
242 Encoding const * encoding = view()->cursor().getEncoding();
244 encoded_last_key = keysym->getISOEncoded(encoding ? encoding->Name() : "");
246 // Do a one-deep top-level lookup for
247 // cancel and meta-fake keys. RVDK_PATCH_5
248 cancel_meta_seq.reset();
250 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
251 lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
252 << " action first set to [" << func.action << ']'
255 // When not cancel or meta-fake, do the normal lookup.
256 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
257 // Mostly, meta_fake_bit = key_modifier::none. RVDK_PATCH_5.
258 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_FAKE)) {
259 // remove Caps Lock and Mod2 as a modifiers
260 func = keyseq.addkey(keysym, (state | meta_fake_bit));
261 lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
262 << "action now set to ["
263 << func.action << ']' << endl;
266 // Dont remove this unless you know what you are doing.
267 meta_fake_bit = key_modifier::none;
269 // Can this happen now ?
270 if (func.action == LFUN_NOACTION) {
271 func = FuncRequest(LFUN_PREFIX);
274 if (lyxerr.debugging(Debug::KEY)) {
275 lyxerr << BOOST_CURRENT_FUNCTION
277 << func.action << "]["
278 << keyseq.print() << ']'
282 // already here we know if it any point in going further
283 // why not return already here if action == -1 and
284 // num_bytes == 0? (Lgb)
286 if (keyseq.length() > 1) {
287 owner->message(keyseq.print());
291 // Maybe user can only reach the key via holding down shift.
292 // Let's see. But only if shift is the only modifier
293 if (func.action == LFUN_UNKNOWN_ACTION &&
294 state == key_modifier::shift) {
295 lyxerr[Debug::KEY] << "Trying without shift" << endl;
296 func = keyseq.addkey(keysym, key_modifier::none);
297 lyxerr[Debug::KEY] << "Action now " << func.action << endl;
300 if (func.action == LFUN_UNKNOWN_ACTION) {
301 // Hmm, we didn't match any of the keysequences. See
302 // if it's normal insertable text not already covered
304 if (keysym->isText() && keyseq.length() == 1) {
305 lyxerr[Debug::KEY] << "isText() is true, inserting." << endl;
306 func = FuncRequest(LFUN_SELFINSERT);
308 lyxerr[Debug::KEY] << "Unknown, !isText() - giving up" << endl;
309 owner->message(_("Unknown function."));
314 if (func.action == LFUN_SELFINSERT) {
315 if (encoded_last_key != 0) {
316 string const arg(1, encoded_last_key);
317 dispatch(FuncRequest(LFUN_SELFINSERT, arg));
319 << "SelfInsert arg[`" << arg << "']" << endl;
327 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
329 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
331 LCursor & cur = view()->cursor();
333 /* In LyX/Mac, when a dialog is open, the menus of the
334 application can still be accessed without giving focus to
335 the main window. In this case, we want to disable the menu
336 entries that are buffer-related.
339 if (cmd.origin == FuncRequest::UI && !owner->hasFocus())
342 buf = owner->buffer();
344 if (cmd.action == LFUN_NOACTION) {
345 flag.message(N_("Nothing to do"));
350 switch (cmd.action) {
351 case LFUN_UNKNOWN_ACTION:
352 #ifndef HAVE_LIBAIKSAURUS
353 case LFUN_THESAURUS_ENTRY:
359 flag |= lyx_gui::getStatus(cmd);
362 if (flag.unknown()) {
363 flag.message(N_("Unknown action"));
367 if (!flag.enabled()) {
368 if (flag.message().empty())
369 flag.message(N_("Command disabled"));
373 // Check whether we need a buffer
374 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
376 flag.message(N_("Command not allowed with"
377 "out any document open"));
382 // I would really like to avoid having this switch and rather try to
383 // encode this in the function itself.
384 // -- And I'd rather let an inset decide which LFUNs it is willing
385 // to handle (Andre')
387 switch (cmd.action) {
388 case LFUN_TOOLTIPS_TOGGLE:
389 flag.setOnOff(owner->getDialogs().tooltipsEnabled());
392 case LFUN_READ_ONLY_TOGGLE:
393 flag.setOnOff(buf->isReadonly());
396 case LFUN_SWITCHBUFFER:
397 // toggle on the current buffer, but do not toggle off
398 // the other ones (is that a good idea?)
399 if (cmd.argument == buf->fileName())
404 enable = cmd.argument == "custom"
405 || Exporter::IsExportable(*buf, cmd.argument);
409 enable = cur.selection();
413 enable = buf->isLatex() && lyxrc.chktex_command != "none";
417 enable = Exporter::IsExportable(*buf, "program");
420 case LFUN_LAYOUT_TABULAR:
421 enable = cur.innerInsetOfType(InsetBase::TABULAR_CODE);
425 case LFUN_LAYOUT_PARAGRAPH:
426 enable = !cur.inset().forceDefaultParagraphs(&cur.inset());
429 case LFUN_VC_REGISTER:
430 enable = !buf->lyxvc().inUse();
432 case LFUN_VC_CHECKIN:
433 enable = buf->lyxvc().inUse() && !buf->isReadonly();
435 case LFUN_VC_CHECKOUT:
436 enable = buf->lyxvc().inUse() && buf->isReadonly();
440 enable = buf->lyxvc().inUse();
442 case LFUN_MENURELOAD:
443 enable = !buf->isUnnamed() && !buf->isClean();
446 case LFUN_INSET_SETTINGS: {
450 UpdatableInset * inset = cur.inset().asUpdatableInset();
451 lyxerr << "inset: " << inset << endl;
455 InsetBase::Code code = inset->lyxCode();
457 case InsetBase::TABULAR_CODE:
458 enable = cmd.argument == "tabular";
460 case InsetBase::ERT_CODE:
461 enable = cmd.argument == "ert";
463 case InsetBase::FLOAT_CODE:
464 enable = cmd.argument == "float";
466 case InsetBase::WRAP_CODE:
467 enable = cmd.argument == "wrap";
469 case InsetBase::NOTE_CODE:
470 enable = cmd.argument == "note";
472 case InsetBase::BRANCH_CODE:
473 enable = cmd.argument == "branch";
475 case InsetBase::BOX_CODE:
476 enable = cmd.argument == "box";
484 case LFUN_DIALOG_SHOW: {
485 string const name = cmd.getArg(0);
487 enable = name == "aboutlyx"
491 || name == "texinfo";
492 else if (name == "print")
493 enable = Exporter::IsExportable(*buf, "dvi")
494 && lyxrc.print_command != "none";
495 else if (name == "character" || name == "mathpanel")
496 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
497 else if (name == "vclog")
498 enable = buf->lyxvc().inUse();
499 else if (name == "latexlog")
500 enable = IsFileReadable(buf->getLogName().second);
504 case LFUN_DIALOG_SHOW_NEW_INSET:
505 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
508 case LFUN_DIALOG_UPDATE: {
509 string const name = cmd.getArg(0);
511 enable = name == "prefs";
515 // this one is difficult to get right. As a half-baked
516 // solution, we consider only the first action of the sequence
517 case LFUN_SEQUENCE: {
518 // argument contains ';'-terminated commands
519 string const firstcmd = token(cmd.argument, ';', 0);
520 FuncRequest func(lyxaction.lookupFunc(firstcmd));
521 func.origin = cmd.origin;
522 flag = getStatus(func);
526 case LFUN_MENUNEWTMPLT:
527 case LFUN_WORDFINDFORWARD:
528 case LFUN_WORDFINDBACKWARD:
530 case LFUN_EXEC_COMMAND:
533 case LFUN_CLOSEBUFFER:
542 case LFUN_RECONFIGURE:
546 case LFUN_DROP_LAYOUTS_CHOICE:
547 case LFUN_MENU_OPEN_BY_NAME:
550 case LFUN_GOTOFILEROW:
551 case LFUN_DIALOG_SHOW_NEXT_INSET:
552 case LFUN_DIALOG_HIDE:
553 case LFUN_DIALOG_DISCONNECT_INSET:
555 case LFUN_TOGGLECURSORFOLLOW:
559 case LFUN_KMAP_TOGGLE:
561 case LFUN_EXPORT_CUSTOM:
563 case LFUN_SAVEPREFERENCES:
564 case LFUN_SCREEN_FONT_UPDATE:
567 case LFUN_EXTERNAL_EDIT:
568 case LFUN_GRAPHICS_EDIT:
569 case LFUN_ALL_INSETS_TOGGLE:
570 case LFUN_LANGUAGE_BUFFER:
571 case LFUN_TEXTCLASS_APPLY:
572 case LFUN_TEXTCLASS_LOAD:
573 case LFUN_SAVE_AS_DEFAULT:
574 case LFUN_BUFFERPARAMS_APPLY:
575 case LFUN_LYXRC_APPLY:
576 case LFUN_NEXTBUFFER:
577 case LFUN_PREVIOUSBUFFER:
578 // these are handled in our dispatch()
583 if (!::getStatus(cur, cmd, flag))
584 flag = view()->getStatus(cmd);
590 // Can we use a readonly buffer?
591 if (buf && buf->isReadonly()
592 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
593 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
594 flag.message(N_("Document is read-only"));
598 // the default error message if we disable the command
599 if (!flag.enabled() && flag.message().empty())
600 flag.message(N_("Command disabled"));
608 bool ensureBufferClean(BufferView * bv)
610 Buffer & buf = *bv->buffer();
614 string const file = MakeDisplayPath(buf.fileName(), 30);
615 string text = bformat(_("The document %1$s has unsaved "
616 "changes.\n\nDo you want to save "
617 "the document?"), file);
618 int const ret = Alert::prompt(_("Save changed document?"),
619 text, 0, 1, _("&Save"),
623 bv->owner()->dispatch(FuncRequest(LFUN_MENUWRITE));
625 return buf.isClean();
629 void showPrintError(string const & name)
631 string str = bformat(_("Could not print the document %1$s.\n"
632 "Check that your printer is set up correctly."),
633 MakeDisplayPath(name, 50));
634 Alert::error(_("Print document failed"), str);
638 void loadTextclass(string const & name)
640 std::pair<bool, lyx::textclass_type> const tc_pair =
641 textclasslist.NumberOfClass(name);
643 if (!tc_pair.first) {
644 lyxerr << "Document class \"" << name
645 << "\" does not exist."
650 lyx::textclass_type const tc = tc_pair.second;
652 if (!textclasslist[tc].load()) {
653 string s = bformat(_("The document could not be converted\n"
654 "into the document class %1$s."),
655 textclasslist[tc].name());
656 Alert::error(_("Could not change class"), s);
661 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
666 void LyXFunc::dispatch(FuncRequest const & cmd)
668 BOOST_ASSERT(view());
669 string const argument = cmd.argument;
670 kb_action const action = cmd.action;
672 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl;
673 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
675 // we have not done anything wrong yet.
677 dispatch_buffer.erase();
681 FuncStatus const flag = getStatus(cmd);
682 if (!flag.enabled()) {
683 // We cannot use this function here
684 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: "
685 << lyxaction.getActionName(action)
686 << " [" << action << "] is disabled at this location"
688 setErrorMessage(flag.message());
691 if (view()->available())
692 view()->hideCursor();
696 case LFUN_WORDFINDFORWARD:
697 case LFUN_WORDFINDBACKWARD: {
698 static string last_search;
699 string searched_string;
701 if (!argument.empty()) {
702 last_search = argument;
703 searched_string = argument;
705 searched_string = last_search;
708 if (searched_string.empty())
711 bool const fw = action == LFUN_WORDFINDFORWARD;
713 lyx::find::find2string(searched_string, true, false, fw);
714 lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data));
719 owner->message(keyseq.printOptions());
722 case LFUN_EXEC_COMMAND:
723 owner->getToolbars().display("minibuffer", true);
724 owner->focus_command_buffer();
729 meta_fake_bit = key_modifier::none;
730 if (view()->available())
731 // cancel any selection
732 dispatch(FuncRequest(LFUN_MARK_OFF));
733 setMessage(N_("Cancel"));
737 meta_fake_bit = key_modifier::alt;
738 setMessage(keyseq.print());
741 case LFUN_READ_ONLY_TOGGLE:
742 if (owner->buffer()->lyxvc().inUse())
743 owner->buffer()->lyxvc().toggleReadOnly();
745 owner->buffer()->setReadonly(
746 !owner->buffer()->isReadonly());
749 // --- Menus -----------------------------------------------
751 menuNew(argument, false);
754 case LFUN_MENUNEWTMPLT:
755 menuNew(argument, true);
758 case LFUN_CLOSEBUFFER:
763 if (!owner->buffer()->isUnnamed()) {
764 string const str = bformat(_("Saving document %1$s..."),
765 MakeDisplayPath(owner->buffer()->fileName()));
767 MenuWrite(owner->buffer());
768 owner->message(str + _(" done."));
770 WriteAs(owner->buffer());
774 WriteAs(owner->buffer(), argument);
777 case LFUN_MENURELOAD: {
778 string const file = MakeDisplayPath(view()->buffer()->fileName(), 20);
779 string text = bformat(_("Any changes will be lost. Are you sure "
780 "you want to revert to the saved version of the document %1$s?"), file);
781 int const ret = Alert::prompt(_("Revert to saved document?"),
782 text, 0, 1, _("&Revert"), _("&Cancel"));
790 Exporter::Export(owner->buffer(), argument, true);
791 view()->showErrorList(BufferFormat(*owner->buffer()));
795 Exporter::Preview(owner->buffer(), argument);
796 view()->showErrorList(BufferFormat(*owner->buffer()));
800 Exporter::Export(owner->buffer(), "program", true);
801 view()->showErrorList(_("Build"));
805 owner->buffer()->runChktex();
806 view()->showErrorList(_("ChkTeX"));
810 if (argument == "custom")
811 owner->getDialogs().show("sendto");
813 Exporter::Export(owner->buffer(), argument, false);
814 view()->showErrorList(BufferFormat(*owner->buffer()));
818 case LFUN_EXPORT_CUSTOM: {
820 string command = split(argument, format_name, ' ');
821 Format const * format = formats.getFormat(format_name);
823 lyxerr << "Format \"" << format_name
824 << "\" not recognized!"
829 Buffer * buffer = owner->buffer();
831 // The name of the file created by the conversion process
834 // Output to filename
835 if (format->name() == "lyx") {
836 string const latexname =
837 buffer->getLatexName(false);
838 filename = ChangeExtension(latexname,
839 format->extension());
840 filename = AddName(buffer->temppath(), filename);
842 if (!buffer->writeFile(filename))
846 Exporter::Export(buffer, format_name, true,
850 // Substitute $$FName for filename
851 if (!contains(command, "$$FName"))
852 command = "( " + command + " ) < $$FName";
853 command = subst(command, "$$FName", filename);
855 // Execute the command in the background
857 call.startscript(Systemcall::DontWait, command);
864 string command = split(split(argument, target, ' '),
868 || target_name.empty()
869 || command.empty()) {
870 lyxerr << "Unable to parse \""
871 << argument << '"' << std::endl;
874 if (target != "printer" && target != "file") {
875 lyxerr << "Unrecognized target \""
876 << target << '"' << std::endl;
880 Buffer * buffer = owner->buffer();
882 if (!Exporter::Export(buffer, "dvi", true)) {
883 showPrintError(buffer->fileName());
887 // Push directory path.
888 string const path = buffer->temppath();
891 // there are three cases here:
892 // 1. we print to a file
893 // 2. we print directly to a printer
894 // 3. we print using a spool command (print to file first)
897 string const dviname =
898 ChangeExtension(buffer->getLatexName(true),
901 if (target == "printer") {
902 if (!lyxrc.print_spool_command.empty()) {
903 // case 3: print using a spool
904 string const psname =
905 ChangeExtension(dviname,".ps");
906 command += lyxrc.print_to_file
909 + QuoteName(dviname);
912 lyxrc.print_spool_command +' ';
913 if (target_name != "default") {
914 command2 += lyxrc.print_spool_printerprefix
918 command2 += QuoteName(psname);
920 // If successful, then spool command
921 res = one.startscript(
926 res = one.startscript(
927 Systemcall::DontWait,
930 // case 2: print directly to a printer
931 res = one.startscript(
932 Systemcall::DontWait,
933 command + QuoteName(dviname));
937 // case 1: print to a file
938 command += lyxrc.print_to_file
939 + QuoteName(MakeAbsPath(target_name,
942 + QuoteName(dviname);
943 res = one.startscript(Systemcall::DontWait,
948 showPrintError(buffer->fileName());
961 InsetCommandParams p("tableofcontents");
962 string const data = InsetCommandMailer::params2string("toc", p);
963 owner->getDialogs().show("toc", data, 0);
971 case LFUN_RECONFIGURE:
975 case LFUN_HELP_OPEN: {
976 string const arg = argument;
978 setErrorMessage(N_("Missing argument"));
981 string const fname = i18nLibFileSearch("doc", arg, "lyx");
983 lyxerr << "LyX: unable to find documentation file `"
984 << arg << "'. Bad installation?" << endl;
987 owner->message(bformat(_("Opening help file %1$s..."),
988 MakeDisplayPath(fname)));
989 view()->loadLyXFile(fname, false);
993 // --- version control -------------------------------
994 case LFUN_VC_REGISTER:
995 if (!ensureBufferClean(view()))
997 if (!owner->buffer()->lyxvc().inUse()) {
998 owner->buffer()->lyxvc().registrer();
1003 case LFUN_VC_CHECKIN:
1004 if (!ensureBufferClean(view()))
1006 if (owner->buffer()->lyxvc().inUse()
1007 && !owner->buffer()->isReadonly()) {
1008 owner->buffer()->lyxvc().checkIn();
1013 case LFUN_VC_CHECKOUT:
1014 if (!ensureBufferClean(view()))
1016 if (owner->buffer()->lyxvc().inUse()
1017 && owner->buffer()->isReadonly()) {
1018 owner->buffer()->lyxvc().checkOut();
1023 case LFUN_VC_REVERT:
1024 owner->buffer()->lyxvc().revert();
1029 owner->buffer()->lyxvc().undoLast();
1033 // --- buffers ----------------------------------------
1034 case LFUN_SWITCHBUFFER:
1035 view()->setBuffer(bufferlist.getBuffer(argument));
1038 case LFUN_NEXTBUFFER:
1039 view()->setBuffer(bufferlist.next(view()->buffer()));
1042 case LFUN_PREVIOUSBUFFER:
1043 view()->setBuffer(bufferlist.previous(view()->buffer()));
1047 NewFile(view(), argument);
1050 case LFUN_FILE_OPEN:
1054 case LFUN_DROP_LAYOUTS_CHOICE:
1055 owner->getToolbars().openLayoutList();
1058 case LFUN_MENU_OPEN_BY_NAME:
1059 owner->getMenubar().openByName(argument);
1062 // --- lyxserver commands ----------------------------
1064 setMessage(owner->buffer()->fileName());
1065 lyxerr[Debug::INFO] << "FNAME["
1066 << owner->buffer()->fileName()
1071 dispatch_buffer = keyseq.print();
1072 lyxserver->notifyClient(dispatch_buffer);
1075 case LFUN_GOTOFILEROW: {
1078 istringstream is(argument);
1079 is >> file_name >> row;
1080 if (prefixIs(file_name, package().temp_dir())) {
1081 // Needed by inverse dvi search. If it is a file
1082 // in tmpdir, call the apropriated function
1083 view()->setBuffer(bufferlist.getBufferFromTmp(file_name));
1085 // Must replace extension of the file to be .lyx
1086 // and get full path
1087 string const s = ChangeExtension(file_name, ".lyx");
1088 // Either change buffer or load the file
1089 if (bufferlist.exists(s)) {
1090 view()->setBuffer(bufferlist.getBuffer(s));
1092 view()->loadLyXFile(s);
1096 view()->setCursorFromRow(row);
1099 // see BufferView_pimpl::center()
1100 view()->updateScrollbar();
1104 case LFUN_DIALOG_SHOW: {
1105 string const name = cmd.getArg(0);
1106 string data = trim(cmd.argument.substr(name.size()));
1108 if (name == "character") {
1109 data = freefont2string();
1111 owner->getDialogs().show("character", data);
1114 else if (name == "latexlog") {
1115 pair<Buffer::LogType, string> const logfile =
1116 owner->buffer()->getLogName();
1117 switch (logfile.first) {
1118 case Buffer::latexlog:
1121 case Buffer::buildlog:
1125 data += logfile.second;
1126 owner->getDialogs().show("log", data);
1128 else if (name == "vclog") {
1129 string const data = "vc " +
1130 owner->buffer()->lyxvc().getLogFile();
1131 owner->getDialogs().show("log", data);
1134 owner->getDialogs().show(name, data);
1138 case LFUN_DIALOG_SHOW_NEW_INSET: {
1139 string const name = cmd.getArg(0);
1140 string data = trim(cmd.argument.substr(name.size()));
1141 if (name == "bibitem" ||
1143 name == "include" ||
1149 InsetCommandParams p(name);
1150 data = InsetCommandMailer::params2string(name, p);
1151 } else if (name == "box") {
1152 // \c data == "Boxed" || "Frameless" etc
1153 InsetBoxParams p(data);
1154 data = InsetBoxMailer::params2string(p);
1155 } else if (name == "branch") {
1156 InsetBranchParams p;
1157 data = InsetBranchMailer::params2string(p);
1158 } else if (name == "citation") {
1159 InsetCommandParams p("cite");
1160 data = InsetCommandMailer::params2string(name, p);
1161 } else if (name == "ert") {
1162 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1163 } else if (name == "external") {
1164 InsetExternalParams p;
1165 Buffer const & buffer = *owner->buffer();
1166 data = InsetExternalMailer::params2string(p, buffer);
1167 } else if (name == "float") {
1169 data = InsetFloatMailer::params2string(p);
1170 } else if (name == "graphics") {
1171 InsetGraphicsParams p;
1172 Buffer const & buffer = *owner->buffer();
1173 data = InsetGraphicsMailer::params2string(p, buffer);
1174 } else if (name == "note") {
1176 data = InsetNoteMailer::params2string(p);
1177 } else if (name == "vspace") {
1179 data = InsetVSpaceMailer::params2string(space);
1180 } else if (name == "wrap") {
1182 data = InsetWrapMailer::params2string(p);
1184 owner->getDialogs().show(name, data, 0);
1188 case LFUN_DIALOG_SHOW_NEXT_INSET:
1191 case LFUN_DIALOG_UPDATE: {
1192 string const & name = argument;
1193 // Can only update a dialog connected to an existing inset
1194 InsetBase * inset = owner->getDialogs().getOpenInset(name);
1196 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument);
1197 inset->dispatch(view()->cursor(), fr);
1198 } else if (name == "paragraph") {
1199 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1200 } else if (name == "prefs") {
1201 owner->getDialogs().update(name, string());
1206 case LFUN_DIALOG_HIDE:
1207 Dialogs::hide(argument, 0);
1210 case LFUN_DIALOG_DISCONNECT_INSET:
1211 owner->getDialogs().disconnect(argument);
1214 case LFUN_CHILDOPEN: {
1215 string const filename =
1216 MakeAbsPath(argument, owner->buffer()->filePath());
1217 setMessage(N_("Opening child document ") +
1218 MakeDisplayPath(filename) + "...");
1219 view()->savePosition(0);
1220 string const parentfilename = owner->buffer()->fileName();
1221 if (bufferlist.exists(filename))
1222 view()->setBuffer(bufferlist.getBuffer(filename));
1224 view()->loadLyXFile(filename);
1225 // Set the parent name of the child document.
1226 // This makes insertion of citations and references in the child work,
1227 // when the target is in the parent or another child document.
1228 owner->buffer()->setParentName(parentfilename);
1232 case LFUN_TOGGLECURSORFOLLOW:
1233 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1237 owner->getIntl().KeyMapOn(false);
1240 case LFUN_KMAP_PRIM:
1241 owner->getIntl().KeyMapPrim();
1245 owner->getIntl().KeyMapSec();
1248 case LFUN_KMAP_TOGGLE:
1249 owner->getIntl().ToggleKeyMap();
1255 string rest = split(argument, countstr, ' ');
1256 istringstream is(countstr);
1259 lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1260 for (int i = 0; i < count; ++i)
1261 dispatch(lyxaction.lookupFunc(rest));
1265 case LFUN_SEQUENCE: {
1266 // argument contains ';'-terminated commands
1267 string arg = argument;
1268 while (!arg.empty()) {
1270 arg = split(arg, first, ';');
1271 FuncRequest func(lyxaction.lookupFunc(first));
1272 func.origin = cmd.origin;
1278 case LFUN_SAVEPREFERENCES: {
1279 Path p(package().user_support());
1280 lyxrc.write("preferences", false);
1284 case LFUN_SCREEN_FONT_UPDATE:
1285 // handle the screen font changes.
1286 lyxrc.set_font_norm_type();
1287 lyx_gui::update_fonts();
1288 // All visible buffers will need resize
1292 case LFUN_SET_COLOR: {
1294 string const x11_name = split(argument, lyx_name, ' ');
1295 if (lyx_name.empty() || x11_name.empty()) {
1296 setErrorMessage(N_("Syntax: set-color <lyx_name>"
1301 bool const graphicsbg_changed =
1302 (lyx_name == lcolor.getLyXName(LColor::graphicsbg) &&
1303 x11_name != lcolor.getX11Name(LColor::graphicsbg));
1305 if (!lcolor.setColor(lyx_name, x11_name)) {
1307 bformat(_("Set-color \"%1$s\" failed "
1308 "- color is undefined or "
1309 "may not be redefined"), lyx_name));
1313 lyx_gui::update_color(lcolor.getFromLyXName(lyx_name));
1315 if (graphicsbg_changed) {
1316 #ifdef WITH_WARNINGS
1317 #warning FIXME!! The graphics cache no longer has a changeDisplay method.
1320 lyx::graphics::GCache::get().changeDisplay(true);
1327 owner->message(argument);
1330 case LFUN_TOOLTIPS_TOGGLE:
1331 owner->getDialogs().toggleTooltips();
1334 case LFUN_EXTERNAL_EDIT: {
1335 FuncRequest fr(action, argument);
1336 InsetExternal().dispatch(view()->cursor(), fr);
1340 case LFUN_GRAPHICS_EDIT: {
1341 FuncRequest fr(action, argument);
1342 InsetGraphics().dispatch(view()->cursor(), fr);
1346 case LFUN_ALL_INSETS_TOGGLE: {
1348 string const name = split(argument, action, ' ');
1349 InsetBase::Code const inset_code =
1350 InsetBase::translate(name);
1352 LCursor & cur = view()->cursor();
1353 FuncRequest fr(LFUN_INSET_TOGGLE, action);
1355 InsetBase & inset = owner->buffer()->inset();
1356 InsetIterator it = inset_iterator_begin(inset);
1357 InsetIterator const end = inset_iterator_end(inset);
1358 for (; it != end; ++it) {
1359 if (inset_code == InsetBase::NO_CODE
1360 || inset_code == it->lyxCode())
1361 it->dispatch(cur, fr);
1366 case LFUN_LANGUAGE_BUFFER: {
1367 Buffer & buffer = *owner->buffer();
1368 Language const * oldL = buffer.params().language;
1369 Language const * newL = languages.getLanguage(argument);
1370 if (!newL || oldL == newL)
1373 if (oldL->RightToLeft() == newL->RightToLeft()
1374 && !buffer.isMultiLingual())
1375 buffer.changeLanguage(oldL, newL);
1377 buffer.updateDocLang(newL);
1381 case LFUN_SAVE_AS_DEFAULT: {
1382 string const fname =
1383 AddName(AddPath(package().user_support(), "templates/"),
1385 Buffer defaults(fname);
1387 istringstream ss(argument);
1390 int const unknown_tokens = defaults.readHeader(lex);
1392 if (unknown_tokens != 0) {
1393 lyxerr << "Warning in LFUN_SAVE_AS_DEFAULT!\n"
1394 << unknown_tokens << " unknown token"
1395 << (unknown_tokens == 1 ? "" : "s")
1399 if (defaults.writeFile(defaults.fileName()))
1400 setMessage(_("Document defaults saved in ")
1401 + MakeDisplayPath(fname));
1403 setErrorMessage(_("Unable to save document defaults"));
1407 case LFUN_BUFFERPARAMS_APPLY: {
1408 biblio::CiteEngine const engine =
1409 owner->buffer()->params().cite_engine;
1411 istringstream ss(argument);
1414 int const unknown_tokens =
1415 owner->buffer()->readHeader(lex);
1417 if (unknown_tokens != 0) {
1418 lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n"
1419 << unknown_tokens << " unknown token"
1420 << (unknown_tokens == 1 ? "" : "s")
1423 if (engine == owner->buffer()->params().cite_engine)
1426 LCursor & cur = view()->cursor();
1427 FuncRequest fr(LFUN_INSET_REFRESH);
1429 InsetBase & inset = owner->buffer()->inset();
1430 InsetIterator it = inset_iterator_begin(inset);
1431 InsetIterator const end = inset_iterator_end(inset);
1432 for (; it != end; ++it)
1433 if (it->lyxCode() == InsetBase::CITE_CODE)
1434 it->dispatch(cur, fr);
1438 case LFUN_TEXTCLASS_APPLY: {
1439 Buffer * buffer = owner->buffer();
1441 lyx::textclass_type const old_class =
1442 buffer->params().textclass;
1444 loadTextclass(argument);
1446 std::pair<bool, lyx::textclass_type> const tc_pair =
1447 textclasslist.NumberOfClass(argument);
1452 lyx::textclass_type const new_class = tc_pair.second;
1453 if (old_class == new_class)
1457 owner->message(_("Converting document to new document class..."));
1459 lyx::cap::SwitchLayoutsBetweenClasses(
1460 old_class, new_class,
1461 buffer->paragraphs(), el);
1463 bufferErrors(*buffer, el);
1464 view()->showErrorList(_("Class switch"));
1468 case LFUN_TEXTCLASS_LOAD:
1469 loadTextclass(argument);
1472 case LFUN_LYXRC_APPLY: {
1473 LyXRC const lyxrc_orig = lyxrc;
1475 istringstream ss(argument);
1476 bool const success = lyxrc.read(ss) == 0;
1479 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1480 << "Unable to read lyxrc data"
1485 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1490 view()->cursor().dispatch(cmd);
1491 update |= view()->cursor().result().update();
1492 if (!view()->cursor().result().dispatched()) {
1493 update |= view()->dispatch(cmd);
1500 if (view()->available()) {
1501 // Redraw screen unless explicitly told otherwise.
1502 // This also initializes the position cache for all insets
1503 // in (at least partially) visible top-level paragraphs.
1504 view()->update(true, update);
1506 // if we executed a mutating lfun, mark the buffer as dirty
1507 if (getStatus(cmd).enabled()
1508 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)
1509 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly))
1510 view()->buffer()->markDirty();
1513 if (view()->cursor().inTexted()) {
1514 view()->owner()->updateLayoutChoice();
1517 sendDispatchMessage(getMessage(), cmd);
1521 void LyXFunc::sendDispatchMessage(string const & msg, FuncRequest const & cmd)
1523 owner->updateMenubar();
1524 owner->updateToolbars();
1526 const bool verbose = (cmd.origin == FuncRequest::UI
1527 || cmd.origin == FuncRequest::COMMANDBUFFER);
1529 if (cmd.action == LFUN_SELFINSERT || !verbose) {
1530 lyxerr[Debug::ACTION] << "dispatch msg is " << msg << endl;
1532 owner->message(msg);
1536 string dispatch_msg = msg;
1537 if (!dispatch_msg.empty())
1538 dispatch_msg += ' ';
1540 string comname = lyxaction.getActionName(cmd.action);
1542 bool argsadded = false;
1544 if (!cmd.argument.empty()) {
1545 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1546 comname += ' ' + cmd.argument;
1551 string const shortcuts = toplevel_keymap->printbindings(cmd);
1553 if (!shortcuts.empty()) {
1554 comname += ": " + shortcuts;
1555 } else if (!argsadded && !cmd.argument.empty()) {
1556 comname += ' ' + cmd.argument;
1559 if (!comname.empty()) {
1560 comname = rtrim(comname);
1561 dispatch_msg += '(' + comname + ')';
1564 lyxerr[Debug::ACTION] << "verbose dispatch msg " << dispatch_msg << endl;
1565 if (!dispatch_msg.empty())
1566 owner->message(dispatch_msg);
1570 void LyXFunc::setupLocalKeymap()
1572 keyseq.stdmap = toplevel_keymap.get();
1573 keyseq.curmap = toplevel_keymap.get();
1574 cancel_meta_seq.stdmap = toplevel_keymap.get();
1575 cancel_meta_seq.curmap = toplevel_keymap.get();
1579 void LyXFunc::menuNew(string const & name, bool fromTemplate)
1581 string initpath = lyxrc.document_path;
1582 string filename(name);
1584 if (view()->available()) {
1585 string const trypath = owner->buffer()->filePath();
1586 // If directory is writeable, use this as default.
1587 if (IsDirWriteable(trypath))
1591 static int newfile_number;
1593 if (filename.empty()) {
1594 filename = AddName(lyxrc.document_path,
1595 "newfile" + convert<string>(++newfile_number) + ".lyx");
1596 while (bufferlist.exists(filename) || fs::is_readable(filename)) {
1598 filename = AddName(lyxrc.document_path,
1599 "newfile" + convert<string>(newfile_number) +
1604 // The template stuff
1607 FileDialog fileDlg(_("Select template file"),
1608 LFUN_SELECT_FILE_SYNC,
1609 make_pair(string(_("Documents|#o#O")),
1610 string(lyxrc.document_path)),
1611 make_pair(string(_("Templates|#T#t")),
1612 string(lyxrc.template_path)));
1614 FileDialog::Result result =
1615 fileDlg.open(lyxrc.template_path,
1616 FileFilterList(_("LyX Documents (*.lyx)")),
1619 if (result.first == FileDialog::Later)
1621 if (result.second.empty())
1623 templname = result.second;
1626 view()->newFile(filename, templname, !name.empty());
1630 void LyXFunc::open(string const & fname)
1632 string initpath = lyxrc.document_path;
1634 if (view()->available()) {
1635 string const trypath = owner->buffer()->filePath();
1636 // If directory is writeable, use this as default.
1637 if (IsDirWriteable(trypath))
1643 if (fname.empty()) {
1644 FileDialog fileDlg(_("Select document to open"),
1646 make_pair(string(_("Documents|#o#O")),
1647 string(lyxrc.document_path)),
1648 make_pair(string(_("Examples|#E#e")),
1649 string(AddPath(package().system_support(), "examples"))));
1651 FileDialog::Result result =
1652 fileDlg.open(initpath,
1653 FileFilterList(_("LyX Documents (*.lyx)")),
1656 if (result.first == FileDialog::Later)
1659 filename = result.second;
1661 // check selected filename
1662 if (filename.empty()) {
1663 owner->message(_("Canceled."));
1669 // get absolute path of file and add ".lyx" to the filename if
1671 string const fullpath = FileSearch(string(), filename, "lyx");
1672 if (!fullpath.empty()) {
1673 filename = fullpath;
1676 string const disp_fn(MakeDisplayPath(filename));
1678 // if the file doesn't exist, let the user create one
1679 if (!fs::exists(filename)) {
1680 // the user specifically chose this name. Believe them.
1681 view()->newFile(filename, "", true);
1685 owner->message(bformat(_("Opening document %1$s..."), disp_fn));
1688 if (view()->loadLyXFile(filename)) {
1689 str2 = bformat(_("Document %1$s opened."), disp_fn);
1691 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1693 owner->message(str2);
1697 void LyXFunc::doImport(string const & argument)
1700 string filename = split(argument, format, ' ');
1702 lyxerr[Debug::INFO] << "LyXFunc::doImport: " << format
1703 << " file: " << filename << endl;
1705 // need user interaction
1706 if (filename.empty()) {
1707 string initpath = lyxrc.document_path;
1709 if (view()->available()) {
1710 string const trypath = owner->buffer()->filePath();
1711 // If directory is writeable, use this as default.
1712 if (IsDirWriteable(trypath))
1716 string const text = bformat(_("Select %1$s file to import"),
1717 formats.prettyName(format));
1719 FileDialog fileDlg(text,
1721 make_pair(string(_("Documents|#o#O")),
1722 string(lyxrc.document_path)),
1723 make_pair(string(_("Examples|#E#e")),
1724 string(AddPath(package().system_support(), "examples"))));
1726 string const filter = formats.prettyName(format)
1727 + " (*." + formats.extension(format) + ')';
1729 FileDialog::Result result =
1730 fileDlg.open(initpath,
1731 FileFilterList(filter),
1734 if (result.first == FileDialog::Later)
1737 filename = result.second;
1739 // check selected filename
1740 if (filename.empty())
1741 owner->message(_("Canceled."));
1744 if (filename.empty())
1747 // get absolute path of file
1748 filename = MakeAbsPath(filename);
1750 string const lyxfile = ChangeExtension(filename, ".lyx");
1752 // Check if the document already is open
1753 if (lyx_gui::use_gui && bufferlist.exists(lyxfile)) {
1754 if (!bufferlist.close(bufferlist.getBuffer(lyxfile), true)) {
1755 owner->message(_("Canceled."));
1760 // if the file exists already, and we didn't do
1761 // -i lyx thefile.lyx, warn
1762 if (fs::exists(lyxfile) && filename != lyxfile) {
1763 string const file = MakeDisplayPath(lyxfile, 30);
1765 string text = bformat(_("The document %1$s already exists.\n\n"
1766 "Do you want to over-write that document?"), file);
1767 int const ret = Alert::prompt(_("Over-write document?"),
1768 text, 0, 1, _("&Over-write"), _("&Cancel"));
1771 owner->message(_("Canceled."));
1776 Importer::Import(owner, filename, format);
1780 void LyXFunc::closeBuffer()
1782 if (bufferlist.close(owner->buffer(), true) && !quitting) {
1783 if (bufferlist.empty()) {
1784 // need this otherwise SEGV may occur while
1785 // trying to set variables that don't exist
1786 // since there's no current buffer
1787 owner->getDialogs().hideBufferDependent();
1789 view()->setBuffer(bufferlist.first());
1795 // Each "owner" should have it's own message method. lyxview and
1796 // the minibuffer would use the minibuffer, but lyxserver would
1797 // send an ERROR signal to its client. Alejandro 970603
1798 // This function is bit problematic when it comes to NLS, to make the
1799 // lyx servers client be language indepenent we must not translate
1800 // strings sent to this func.
1801 void LyXFunc::setErrorMessage(string const & m) const
1803 dispatch_buffer = m;
1808 void LyXFunc::setMessage(string const & m) const
1810 dispatch_buffer = m;
1814 string const LyXFunc::viewStatusMessage()
1816 // When meta-fake key is pressed, show the key sequence so far + "M-".
1818 return keyseq.print() + "M-";
1820 // Else, when a non-complete key sequence is pressed,
1821 // show the available options.
1822 if (keyseq.length() > 0 && !keyseq.deleted())
1823 return keyseq.printOptions();
1825 if (!view()->available())
1826 return _("Welcome to LyX!");
1828 return view()->cursor().currentState();
1832 BufferView * LyXFunc::view() const
1834 BOOST_ASSERT(owner);
1835 return owner->view().get();
1839 bool LyXFunc::wasMetaKey() const
1841 return (meta_fake_bit != key_modifier::none);
1847 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1849 // Why the switch you might ask. It is a trick to ensure that all
1850 // the elements in the LyXRCTags enum is handled. As you can see
1851 // there are no breaks at all. So it is just a huge fall-through.
1852 // The nice thing is that we will get a warning from the compiler
1853 // if we forget an element.
1854 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1856 case LyXRC::RC_ACCEPT_COMPOUND:
1857 case LyXRC::RC_ALT_LANG:
1858 case LyXRC::RC_ASCIIROFF_COMMAND:
1859 case LyXRC::RC_ASCII_LINELEN:
1860 case LyXRC::RC_AUTOREGIONDELETE:
1861 case LyXRC::RC_AUTORESET_OPTIONS:
1862 case LyXRC::RC_AUTOSAVE:
1863 case LyXRC::RC_AUTO_NUMBER:
1864 case LyXRC::RC_BACKUPDIR_PATH:
1865 case LyXRC::RC_BIBTEX_COMMAND:
1866 case LyXRC::RC_BINDFILE:
1867 case LyXRC::RC_CHECKLASTFILES:
1868 case LyXRC::RC_CHKTEX_COMMAND:
1869 case LyXRC::RC_CONVERTER:
1870 case LyXRC::RC_COPIER:
1871 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1872 case LyXRC::RC_CUSTOM_EXPORT_COMMAND:
1873 case LyXRC::RC_CUSTOM_EXPORT_FORMAT:
1874 case LyXRC::RC_CYGWIN_PATH_FIX:
1875 if (lyxrc_orig.cygwin_path_fix != lyxrc_new.cygwin_path_fix) {
1876 namespace os = lyx::support::os;
1877 os::cygwin_path_fix(lyxrc_new.cygwin_path_fix);
1879 case LyXRC::RC_DATE_INSERT_FORMAT:
1880 case LyXRC::RC_DEFAULT_LANGUAGE:
1881 case LyXRC::RC_DEFAULT_PAPERSIZE:
1882 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1883 case LyXRC::RC_DISPLAY_GRAPHICS:
1884 case LyXRC::RC_DOCUMENTPATH:
1885 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1886 if (fs::exists(lyxrc_new.document_path) &&
1887 fs::is_directory(lyxrc_new.document_path)) {
1888 using lyx::support::package;
1889 package().document_dir() = lyxrc.document_path;
1892 case LyXRC::RC_ESC_CHARS:
1893 case LyXRC::RC_FONT_ENCODING:
1894 case LyXRC::RC_FORMAT:
1895 case LyXRC::RC_INDEX_COMMAND:
1896 case LyXRC::RC_INPUT:
1897 case LyXRC::RC_KBMAP:
1898 case LyXRC::RC_KBMAP_PRIMARY:
1899 case LyXRC::RC_KBMAP_SECONDARY:
1900 case LyXRC::RC_LABEL_INIT_LENGTH:
1901 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1902 case LyXRC::RC_LANGUAGE_AUTO_END:
1903 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1904 case LyXRC::RC_LANGUAGE_COMMAND_END:
1905 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1906 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1907 case LyXRC::RC_LANGUAGE_PACKAGE:
1908 case LyXRC::RC_LANGUAGE_USE_BABEL:
1909 case LyXRC::RC_LASTFILES:
1910 case LyXRC::RC_MAKE_BACKUP:
1911 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1912 case LyXRC::RC_NUMLASTFILES:
1913 case LyXRC::RC_PATH_PREFIX:
1914 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1915 using lyx::support::prependEnvPath;
1916 prependEnvPath("PATH", lyxrc.path_prefix);
1918 case LyXRC::RC_PERS_DICT:
1919 case LyXRC::RC_POPUP_BOLD_FONT:
1920 case LyXRC::RC_POPUP_FONT_ENCODING:
1921 case LyXRC::RC_POPUP_NORMAL_FONT:
1922 case LyXRC::RC_PREVIEW:
1923 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1924 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1925 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1926 case LyXRC::RC_PRINTCOPIESFLAG:
1927 case LyXRC::RC_PRINTER:
1928 case LyXRC::RC_PRINTEVENPAGEFLAG:
1929 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1930 case LyXRC::RC_PRINTFILEEXTENSION:
1931 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1932 case LyXRC::RC_PRINTODDPAGEFLAG:
1933 case LyXRC::RC_PRINTPAGERANGEFLAG:
1934 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1935 case LyXRC::RC_PRINTPAPERFLAG:
1936 case LyXRC::RC_PRINTREVERSEFLAG:
1937 case LyXRC::RC_PRINTSPOOL_COMMAND:
1938 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1939 case LyXRC::RC_PRINTTOFILE:
1940 case LyXRC::RC_PRINTTOPRINTER:
1941 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1942 case LyXRC::RC_PRINT_COMMAND:
1943 case LyXRC::RC_RTL_SUPPORT:
1944 case LyXRC::RC_SCREEN_DPI:
1945 case LyXRC::RC_SCREEN_FONT_ENCODING:
1946 case LyXRC::RC_SCREEN_FONT_ROMAN:
1947 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1948 case LyXRC::RC_SCREEN_FONT_SANS:
1949 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1950 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1951 case LyXRC::RC_SCREEN_FONT_SIZES:
1952 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1953 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1954 case LyXRC::RC_SCREEN_ZOOM:
1955 case LyXRC::RC_SERVERPIPE:
1956 case LyXRC::RC_SET_COLOR:
1957 case LyXRC::RC_SHOW_BANNER:
1958 case LyXRC::RC_SPELL_COMMAND:
1959 case LyXRC::RC_TEMPDIRPATH:
1960 case LyXRC::RC_TEMPLATEPATH:
1961 case LyXRC::RC_UIFILE:
1962 case LyXRC::RC_USER_EMAIL:
1963 case LyXRC::RC_USER_NAME:
1964 case LyXRC::RC_USETEMPDIR:
1965 case LyXRC::RC_USE_ALT_LANG:
1966 case LyXRC::RC_USE_ESC_CHARS:
1967 case LyXRC::RC_USE_INP_ENC:
1968 case LyXRC::RC_USE_PERS_DICT:
1969 case LyXRC::RC_USE_SPELL_LIB:
1970 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1971 case LyXRC::RC_VIEWER:
1972 case LyXRC::RC_WHEEL_JUMP:
1973 case LyXRC::RC_LAST: