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/current_function.hpp>
94 #include <boost/filesystem/operations.hpp>
98 using bv_funcs::freefont2string;
100 using lyx::support::AbsolutePath;
101 using lyx::support::AddName;
102 using lyx::support::AddPath;
103 using lyx::support::bformat;
104 using lyx::support::ChangeExtension;
105 using lyx::support::contains;
106 using lyx::support::FileFilterList;
107 using lyx::support::FileSearch;
108 using lyx::support::ForkedcallsController;
109 using lyx::support::i18nLibFileSearch;
110 using lyx::support::IsDirWriteable;
111 using lyx::support::IsFileReadable;
112 using lyx::support::isStrInt;
113 using lyx::support::MakeAbsPath;
114 using lyx::support::MakeDisplayPath;
115 using lyx::support::package;
116 using lyx::support::Path;
117 using lyx::support::QuoteName;
118 using lyx::support::rtrim;
119 using lyx::support::split;
120 using lyx::support::subst;
121 using lyx::support::Systemcall;
122 using lyx::support::token;
123 using lyx::support::trim;
124 using lyx::support::prefixIs;
127 using std::make_pair;
130 using std::istringstream;
132 namespace biblio = lyx::biblio;
133 namespace fs = boost::filesystem;
136 extern BufferList bufferlist;
137 extern LyXServer * lyxserver;
139 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
142 extern tex_accent_struct get_accent(kb_action action);
147 bool getStatus(LCursor cursor,
148 FuncRequest const & cmd, FuncStatus & status)
150 // Try to fix cursor in case it is broken.
151 cursor.fixIfBroken();
153 // This is, of course, a mess. Better create a new doc iterator and use
154 // this in Inset::getStatus. This might require an additional
155 // BufferView * arg, though (which should be avoided)
156 //LCursor safe = *this;
158 for ( ; cursor.depth(); cursor.pop()) {
159 //lyxerr << "\nLCursor::getStatus: cmd: " << cmd << endl << *this << endl;
160 BOOST_ASSERT(cursor.idx() <= cursor.lastidx());
161 BOOST_ASSERT(cursor.pit() <= cursor.lastpit());
162 BOOST_ASSERT(cursor.pos() <= cursor.lastpos());
164 // The inset's getStatus() will return 'true' if it made
165 // a definitive decision on whether it want to handle the
166 // request or not. The result of this decision is put into
167 // the 'status' parameter.
168 if (cursor.inset().getStatus(cursor, cmd, status)) {
178 LyXFunc::LyXFunc(LyXView * lv)
181 keyseq(toplevel_keymap.get(), toplevel_keymap.get()),
182 cancel_meta_seq(toplevel_keymap.get(), toplevel_keymap.get()),
183 meta_fake_bit(key_modifier::none)
188 void LyXFunc::handleKeyFunc(kb_action action)
190 char c = encoded_last_key;
192 if (keyseq.length()) {
196 owner->getIntl().getTransManager()
197 .deadkey(c, get_accent(action).accent, view()->getLyXText());
198 // Need to clear, in case the minibuffer calls these
201 // copied verbatim from do_accent_char
202 view()->cursor().resetAnchor();
207 void LyXFunc::processKeySym(LyXKeySymPtr keysym, key_modifier::state state)
209 lyxerr[Debug::KEY] << "KeySym is " << keysym->getSymbolName() << endl;
211 // Do nothing if we have nothing (JMarc)
212 if (!keysym->isOK()) {
213 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
218 if (keysym->isModifier()) {
219 lyxerr[Debug::KEY] << "isModifier true" << endl;
223 Encoding const * encoding = view()->cursor().getEncoding();
225 encoded_last_key = keysym->getISOEncoded(encoding ? encoding->Name() : "");
227 // Do a one-deep top-level lookup for
228 // cancel and meta-fake keys. RVDK_PATCH_5
229 cancel_meta_seq.reset();
231 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
232 lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
233 << " action first set to [" << func.action << ']'
236 // When not cancel or meta-fake, do the normal lookup.
237 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
238 // Mostly, meta_fake_bit = key_modifier::none. RVDK_PATCH_5.
239 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_FAKE)) {
240 // remove Caps Lock and Mod2 as a modifiers
241 func = keyseq.addkey(keysym, (state | meta_fake_bit));
242 lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION
243 << "action now set to ["
244 << func.action << ']' << endl;
247 // Dont remove this unless you know what you are doing.
248 meta_fake_bit = key_modifier::none;
250 // Can this happen now ?
251 if (func.action == LFUN_NOACTION) {
252 func = FuncRequest(LFUN_PREFIX);
255 if (lyxerr.debugging(Debug::KEY)) {
256 lyxerr << BOOST_CURRENT_FUNCTION
258 << func.action << "]["
259 << keyseq.print() << ']'
263 // already here we know if it any point in going further
264 // why not return already here if action == -1 and
265 // num_bytes == 0? (Lgb)
267 if (keyseq.length() > 1) {
268 owner->message(keyseq.print());
272 // Maybe user can only reach the key via holding down shift.
273 // Let's see. But only if shift is the only modifier
274 if (func.action == LFUN_UNKNOWN_ACTION &&
275 state == key_modifier::shift) {
276 lyxerr[Debug::KEY] << "Trying without shift" << endl;
277 func = keyseq.addkey(keysym, key_modifier::none);
278 lyxerr[Debug::KEY] << "Action now " << func.action << endl;
281 if (func.action == LFUN_UNKNOWN_ACTION) {
282 // Hmm, we didn't match any of the keysequences. See
283 // if it's normal insertable text not already covered
285 if (keysym->isText() && keyseq.length() == 1) {
286 lyxerr[Debug::KEY] << "isText() is true, inserting." << endl;
287 func = FuncRequest(LFUN_SELFINSERT);
289 lyxerr[Debug::KEY] << "Unknown, !isText() - giving up" << endl;
290 owner->message(_("Unknown function."));
295 if (func.action == LFUN_SELFINSERT) {
296 if (encoded_last_key != 0) {
297 string const arg(1, encoded_last_key);
298 dispatch(FuncRequest(LFUN_SELFINSERT, arg));
300 << "SelfInsert arg[`" << arg << "']" << endl;
308 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
310 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
312 LCursor & cur = view()->cursor();
314 /* In LyX/Mac, when a dialog is open, the menus of the
315 application can still be accessed without giving focus to
316 the main window. In this case, we want to disable the menu
317 entries that are buffer-related.
320 if (cmd.origin == FuncRequest::UI && !owner->hasFocus())
323 buf = owner->buffer();
325 if (cmd.action == LFUN_NOACTION) {
326 flag.message(N_("Nothing to do"));
331 switch (cmd.action) {
332 case LFUN_UNKNOWN_ACTION:
333 #ifndef HAVE_LIBAIKSAURUS
334 case LFUN_THESAURUS_ENTRY:
340 flag |= lyx_gui::getStatus(cmd);
343 if (flag.unknown()) {
344 flag.message(N_("Unknown action"));
348 if (!flag.enabled()) {
349 if (flag.message().empty())
350 flag.message(N_("Command disabled"));
354 // Check whether we need a buffer
355 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
357 flag.message(N_("Command not allowed with"
358 "out any document open"));
363 // I would really like to avoid having this switch and rather try to
364 // encode this in the function itself.
365 // -- And I'd rather let an inset decide which LFUNs it is willing
366 // to handle (Andre')
368 switch (cmd.action) {
369 case LFUN_TOOLTIPS_TOGGLE:
370 flag.setOnOff(owner->getDialogs().tooltipsEnabled());
373 case LFUN_READ_ONLY_TOGGLE:
374 flag.setOnOff(buf->isReadonly());
377 case LFUN_SWITCHBUFFER:
378 // toggle on the current buffer, but do not toggle off
379 // the other ones (is that a good idea?)
380 if (cmd.argument == buf->fileName())
385 enable = cmd.argument == "custom"
386 || Exporter::IsExportable(*buf, cmd.argument);
390 enable = cur.selection();
394 enable = buf->isLatex() && lyxrc.chktex_command != "none";
398 enable = Exporter::IsExportable(*buf, "program");
401 case LFUN_LAYOUT_TABULAR:
402 enable = cur.innerInsetOfType(InsetBase::TABULAR_CODE);
406 case LFUN_LAYOUT_PARAGRAPH:
407 enable = !cur.inset().forceDefaultParagraphs(&cur.inset());
410 case LFUN_VC_REGISTER:
411 enable = !buf->lyxvc().inUse();
413 case LFUN_VC_CHECKIN:
414 enable = buf->lyxvc().inUse() && !buf->isReadonly();
416 case LFUN_VC_CHECKOUT:
417 enable = buf->lyxvc().inUse() && buf->isReadonly();
421 enable = buf->lyxvc().inUse();
423 case LFUN_MENURELOAD:
424 enable = !buf->isUnnamed() && !buf->isClean();
427 case LFUN_INSET_SETTINGS: {
431 UpdatableInset * inset = cur.inset().asUpdatableInset();
432 lyxerr << "inset: " << inset << endl;
436 InsetBase::Code code = inset->lyxCode();
438 case InsetBase::TABULAR_CODE:
439 enable = cmd.argument == "tabular";
441 case InsetBase::ERT_CODE:
442 enable = cmd.argument == "ert";
444 case InsetBase::FLOAT_CODE:
445 enable = cmd.argument == "float";
447 case InsetBase::WRAP_CODE:
448 enable = cmd.argument == "wrap";
450 case InsetBase::NOTE_CODE:
451 enable = cmd.argument == "note";
453 case InsetBase::BRANCH_CODE:
454 enable = cmd.argument == "branch";
456 case InsetBase::BOX_CODE:
457 enable = cmd.argument == "box";
465 case LFUN_INSET_APPLY: {
466 string const name = cmd.getArg(0);
467 InsetBase * inset = owner->getDialogs().getOpenInset(name);
469 FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument);
471 bool const success = inset->getStatus(cur, fr, fs);
472 // Every inset is supposed to handle this
473 BOOST_ASSERT(success);
476 FuncRequest fr(LFUN_INSET_INSERT, cmd.argument);
477 flag |= getStatus(fr);
479 enable = flag.enabled();
483 case LFUN_DIALOG_SHOW: {
484 string const name = cmd.getArg(0);
486 enable = name == "aboutlyx"
490 || name == "texinfo";
491 else if (name == "print")
492 enable = Exporter::IsExportable(*buf, "dvi")
493 && lyxrc.print_command != "none";
494 else if (name == "character" || name == "mathpanel")
495 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
496 else if (name == "latexlog")
497 enable = IsFileReadable(buf->getLogName().second);
498 #if !defined (USE_ASPELL) && !defined (USE_ISPELL) && !defined (USE_PSPELL)
499 else if (name == "spellchecker")
502 else if (name == "vclog")
503 enable = buf->lyxvc().inUse();
507 case LFUN_DIALOG_SHOW_NEW_INSET:
508 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
511 case LFUN_DIALOG_UPDATE: {
512 string const name = cmd.getArg(0);
514 enable = name == "prefs";
518 // this one is difficult to get right. As a half-baked
519 // solution, we consider only the first action of the sequence
520 case LFUN_SEQUENCE: {
521 // argument contains ';'-terminated commands
522 string const firstcmd = token(cmd.argument, ';', 0);
523 FuncRequest func(lyxaction.lookupFunc(firstcmd));
524 func.origin = cmd.origin;
525 flag = getStatus(func);
529 case LFUN_MENUNEWTMPLT:
530 case LFUN_WORDFINDFORWARD:
531 case LFUN_WORDFINDBACKWARD:
533 case LFUN_EXEC_COMMAND:
536 case LFUN_CLOSEBUFFER:
545 case LFUN_RECONFIGURE:
549 case LFUN_DROP_LAYOUTS_CHOICE:
550 case LFUN_MENU_OPEN_BY_NAME:
553 case LFUN_GOTOFILEROW:
554 case LFUN_DIALOG_SHOW_NEXT_INSET:
555 case LFUN_DIALOG_HIDE:
556 case LFUN_DIALOG_DISCONNECT_INSET:
558 case LFUN_TOGGLECURSORFOLLOW:
562 case LFUN_KMAP_TOGGLE:
564 case LFUN_EXPORT_CUSTOM:
566 case LFUN_SAVEPREFERENCES:
567 case LFUN_SCREEN_FONT_UPDATE:
570 case LFUN_EXTERNAL_EDIT:
571 case LFUN_GRAPHICS_EDIT:
572 case LFUN_ALL_INSETS_TOGGLE:
573 case LFUN_LANGUAGE_BUFFER:
574 case LFUN_TEXTCLASS_APPLY:
575 case LFUN_TEXTCLASS_LOAD:
576 case LFUN_SAVE_AS_DEFAULT:
577 case LFUN_BUFFERPARAMS_APPLY:
578 case LFUN_LYXRC_APPLY:
579 case LFUN_NEXTBUFFER:
580 case LFUN_PREVIOUSBUFFER:
581 // these are handled in our dispatch()
586 if (!::getStatus(cur, cmd, flag))
587 flag = view()->getStatus(cmd);
593 // Can we use a readonly buffer?
594 if (buf && buf->isReadonly()
595 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
596 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
597 flag.message(N_("Document is read-only"));
601 // the default error message if we disable the command
602 if (!flag.enabled() && flag.message().empty())
603 flag.message(N_("Command disabled"));
611 bool ensureBufferClean(BufferView * bv)
613 Buffer & buf = *bv->buffer();
617 string const file = MakeDisplayPath(buf.fileName(), 30);
618 string text = bformat(_("The document %1$s has unsaved "
619 "changes.\n\nDo you want to save "
620 "the document?"), file);
621 int const ret = Alert::prompt(_("Save changed document?"),
622 text, 0, 1, _("&Save"),
626 bv->owner()->dispatch(FuncRequest(LFUN_MENUWRITE));
628 return buf.isClean();
632 void showPrintError(string const & name)
634 string str = bformat(_("Could not print the document %1$s.\n"
635 "Check that your printer is set up correctly."),
636 MakeDisplayPath(name, 50));
637 Alert::error(_("Print document failed"), str);
641 void loadTextclass(string const & name)
643 std::pair<bool, lyx::textclass_type> const tc_pair =
644 textclasslist.NumberOfClass(name);
646 if (!tc_pair.first) {
647 lyxerr << "Document class \"" << name
648 << "\" does not exist."
653 lyx::textclass_type const tc = tc_pair.second;
655 if (!textclasslist[tc].load()) {
656 string s = bformat(_("The document could not be converted\n"
657 "into the document class %1$s."),
658 textclasslist[tc].name());
659 Alert::error(_("Could not change class"), s);
664 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
669 void LyXFunc::dispatch(FuncRequest const & cmd)
671 BOOST_ASSERT(view());
672 string const argument = cmd.argument;
673 kb_action const action = cmd.action;
675 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl;
676 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
678 // we have not done anything wrong yet.
680 dispatch_buffer.erase();
684 FuncStatus const flag = getStatus(cmd);
685 if (!flag.enabled()) {
686 // We cannot use this function here
687 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: "
688 << lyxaction.getActionName(action)
689 << " [" << action << "] is disabled at this location"
691 setErrorMessage(flag.message());
694 if (view()->available())
695 view()->hideCursor();
699 case LFUN_WORDFINDFORWARD:
700 case LFUN_WORDFINDBACKWARD: {
701 static string last_search;
702 string searched_string;
704 if (!argument.empty()) {
705 last_search = argument;
706 searched_string = argument;
708 searched_string = last_search;
711 if (searched_string.empty())
714 bool const fw = action == LFUN_WORDFINDFORWARD;
716 lyx::find::find2string(searched_string, true, false, fw);
717 lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data));
722 owner->message(keyseq.printOptions());
725 case LFUN_EXEC_COMMAND:
726 owner->getToolbars().display("minibuffer", true);
727 owner->focus_command_buffer();
732 meta_fake_bit = key_modifier::none;
733 if (view()->available())
734 // cancel any selection
735 dispatch(FuncRequest(LFUN_MARK_OFF));
736 setMessage(N_("Cancel"));
740 meta_fake_bit = key_modifier::alt;
741 setMessage(keyseq.print());
744 case LFUN_READ_ONLY_TOGGLE:
745 if (owner->buffer()->lyxvc().inUse())
746 owner->buffer()->lyxvc().toggleReadOnly();
748 owner->buffer()->setReadonly(
749 !owner->buffer()->isReadonly());
752 // --- Menus -----------------------------------------------
754 menuNew(argument, false);
757 case LFUN_MENUNEWTMPLT:
758 menuNew(argument, true);
761 case LFUN_CLOSEBUFFER:
766 if (!owner->buffer()->isUnnamed()) {
767 string const str = bformat(_("Saving document %1$s..."),
768 MakeDisplayPath(owner->buffer()->fileName()));
770 MenuWrite(owner->buffer());
771 owner->message(str + _(" done."));
773 WriteAs(owner->buffer());
777 WriteAs(owner->buffer(), argument);
780 case LFUN_MENURELOAD: {
781 string const file = MakeDisplayPath(view()->buffer()->fileName(), 20);
782 string text = bformat(_("Any changes will be lost. Are you sure "
783 "you want to revert to the saved version of the document %1$s?"), file);
784 int const ret = Alert::prompt(_("Revert to saved document?"),
785 text, 0, 1, _("&Revert"), _("&Cancel"));
793 Exporter::Export(owner->buffer(), argument, true);
794 view()->showErrorList(BufferFormat(*owner->buffer()));
798 Exporter::Preview(owner->buffer(), argument);
799 view()->showErrorList(BufferFormat(*owner->buffer()));
803 Exporter::Export(owner->buffer(), "program", true);
804 view()->showErrorList(_("Build"));
808 owner->buffer()->runChktex();
809 view()->showErrorList(_("ChkTeX"));
813 if (argument == "custom")
814 owner->getDialogs().show("sendto");
816 Exporter::Export(owner->buffer(), argument, false);
817 view()->showErrorList(BufferFormat(*owner->buffer()));
821 case LFUN_EXPORT_CUSTOM: {
823 string command = split(argument, format_name, ' ');
824 Format const * format = formats.getFormat(format_name);
826 lyxerr << "Format \"" << format_name
827 << "\" not recognized!"
832 Buffer * buffer = owner->buffer();
834 // The name of the file created by the conversion process
837 // Output to filename
838 if (format->name() == "lyx") {
839 string const latexname =
840 buffer->getLatexName(false);
841 filename = ChangeExtension(latexname,
842 format->extension());
843 filename = AddName(buffer->temppath(), filename);
845 if (!buffer->writeFile(filename))
849 Exporter::Export(buffer, format_name, true,
853 // Substitute $$FName for filename
854 if (!contains(command, "$$FName"))
855 command = "( " + command + " ) < $$FName";
856 command = subst(command, "$$FName", filename);
858 // Execute the command in the background
860 call.startscript(Systemcall::DontWait, command);
867 string command = split(split(argument, target, ' '),
871 || target_name.empty()
872 || command.empty()) {
873 lyxerr << "Unable to parse \""
874 << argument << '"' << std::endl;
877 if (target != "printer" && target != "file") {
878 lyxerr << "Unrecognized target \""
879 << target << '"' << std::endl;
883 Buffer * buffer = owner->buffer();
885 if (!Exporter::Export(buffer, "dvi", true)) {
886 showPrintError(buffer->fileName());
890 // Push directory path.
891 string const path = buffer->temppath();
894 // there are three cases here:
895 // 1. we print to a file
896 // 2. we print directly to a printer
897 // 3. we print using a spool command (print to file first)
900 string const dviname =
901 ChangeExtension(buffer->getLatexName(true),
904 if (target == "printer") {
905 if (!lyxrc.print_spool_command.empty()) {
906 // case 3: print using a spool
907 string const psname =
908 ChangeExtension(dviname,".ps");
909 command += lyxrc.print_to_file
912 + QuoteName(dviname);
915 lyxrc.print_spool_command +' ';
916 if (target_name != "default") {
917 command2 += lyxrc.print_spool_printerprefix
921 command2 += QuoteName(psname);
923 // If successful, then spool command
924 res = one.startscript(
929 res = one.startscript(
930 Systemcall::DontWait,
933 // case 2: print directly to a printer
934 res = one.startscript(
935 Systemcall::DontWait,
936 command + QuoteName(dviname));
940 // case 1: print to a file
941 command += lyxrc.print_to_file
942 + QuoteName(MakeAbsPath(target_name,
945 + QuoteName(dviname);
946 res = one.startscript(Systemcall::DontWait,
951 showPrintError(buffer->fileName());
964 InsetCommandParams p("tableofcontents");
965 string const data = InsetCommandMailer::params2string("toc", p);
966 owner->getDialogs().show("toc", data, 0);
974 case LFUN_RECONFIGURE:
978 case LFUN_HELP_OPEN: {
979 string const arg = argument;
981 setErrorMessage(N_("Missing argument"));
984 string const fname = i18nLibFileSearch("doc", arg, "lyx");
986 lyxerr << "LyX: unable to find documentation file `"
987 << arg << "'. Bad installation?" << endl;
990 owner->message(bformat(_("Opening help file %1$s..."),
991 MakeDisplayPath(fname)));
992 view()->loadLyXFile(fname, false);
996 // --- version control -------------------------------
997 case LFUN_VC_REGISTER:
998 if (!ensureBufferClean(view()))
1000 if (!owner->buffer()->lyxvc().inUse()) {
1001 owner->buffer()->lyxvc().registrer();
1006 case LFUN_VC_CHECKIN:
1007 if (!ensureBufferClean(view()))
1009 if (owner->buffer()->lyxvc().inUse()
1010 && !owner->buffer()->isReadonly()) {
1011 owner->buffer()->lyxvc().checkIn();
1016 case LFUN_VC_CHECKOUT:
1017 if (!ensureBufferClean(view()))
1019 if (owner->buffer()->lyxvc().inUse()
1020 && owner->buffer()->isReadonly()) {
1021 owner->buffer()->lyxvc().checkOut();
1026 case LFUN_VC_REVERT:
1027 owner->buffer()->lyxvc().revert();
1032 owner->buffer()->lyxvc().undoLast();
1036 // --- buffers ----------------------------------------
1037 case LFUN_SWITCHBUFFER:
1038 view()->setBuffer(bufferlist.getBuffer(argument));
1041 case LFUN_NEXTBUFFER:
1042 view()->setBuffer(bufferlist.next(view()->buffer()));
1045 case LFUN_PREVIOUSBUFFER:
1046 view()->setBuffer(bufferlist.previous(view()->buffer()));
1050 NewFile(view(), argument);
1053 case LFUN_FILE_OPEN:
1057 case LFUN_DROP_LAYOUTS_CHOICE:
1058 owner->getToolbars().openLayoutList();
1061 case LFUN_MENU_OPEN_BY_NAME:
1062 owner->getMenubar().openByName(argument);
1065 // --- lyxserver commands ----------------------------
1067 setMessage(owner->buffer()->fileName());
1068 lyxerr[Debug::INFO] << "FNAME["
1069 << owner->buffer()->fileName()
1074 dispatch_buffer = keyseq.print();
1075 lyxserver->notifyClient(dispatch_buffer);
1078 case LFUN_GOTOFILEROW: {
1081 istringstream is(argument);
1082 is >> file_name >> row;
1083 if (prefixIs(file_name, package().temp_dir())) {
1084 // Needed by inverse dvi search. If it is a file
1085 // in tmpdir, call the apropriated function
1086 view()->setBuffer(bufferlist.getBufferFromTmp(file_name));
1088 // Must replace extension of the file to be .lyx
1089 // and get full path
1090 string const s = ChangeExtension(file_name, ".lyx");
1091 // Either change buffer or load the file
1092 if (bufferlist.exists(s)) {
1093 view()->setBuffer(bufferlist.getBuffer(s));
1095 view()->loadLyXFile(s);
1099 view()->setCursorFromRow(row);
1102 // see BufferView_pimpl::center()
1103 view()->updateScrollbar();
1107 case LFUN_DIALOG_SHOW: {
1108 string const name = cmd.getArg(0);
1109 string data = trim(cmd.argument.substr(name.size()));
1111 if (name == "character") {
1112 data = freefont2string();
1114 owner->getDialogs().show("character", data);
1117 else if (name == "latexlog") {
1118 pair<Buffer::LogType, string> const logfile =
1119 owner->buffer()->getLogName();
1120 switch (logfile.first) {
1121 case Buffer::latexlog:
1124 case Buffer::buildlog:
1128 data += logfile.second;
1129 owner->getDialogs().show("log", data);
1131 else if (name == "vclog") {
1132 string const data = "vc " +
1133 owner->buffer()->lyxvc().getLogFile();
1134 owner->getDialogs().show("log", data);
1137 owner->getDialogs().show(name, data);
1141 case LFUN_DIALOG_SHOW_NEW_INSET: {
1142 string const name = cmd.getArg(0);
1143 string data = trim(cmd.argument.substr(name.size()));
1144 if (name == "bibitem" ||
1146 name == "include" ||
1152 InsetCommandParams p(name);
1153 data = InsetCommandMailer::params2string(name, p);
1154 } else if (name == "box") {
1155 // \c data == "Boxed" || "Frameless" etc
1156 InsetBoxParams p(data);
1157 data = InsetBoxMailer::params2string(p);
1158 } else if (name == "branch") {
1159 InsetBranchParams p;
1160 data = InsetBranchMailer::params2string(p);
1161 } else if (name == "citation") {
1162 InsetCommandParams p("cite");
1163 data = InsetCommandMailer::params2string(name, p);
1164 } else if (name == "ert") {
1165 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1166 } else if (name == "external") {
1167 InsetExternalParams p;
1168 Buffer const & buffer = *owner->buffer();
1169 data = InsetExternalMailer::params2string(p, buffer);
1170 } else if (name == "float") {
1172 data = InsetFloatMailer::params2string(p);
1173 } else if (name == "graphics") {
1174 InsetGraphicsParams p;
1175 Buffer const & buffer = *owner->buffer();
1176 data = InsetGraphicsMailer::params2string(p, buffer);
1177 } else if (name == "note") {
1179 data = InsetNoteMailer::params2string(p);
1180 } else if (name == "vspace") {
1182 data = InsetVSpaceMailer::params2string(space);
1183 } else if (name == "wrap") {
1185 data = InsetWrapMailer::params2string(p);
1187 owner->getDialogs().show(name, data, 0);
1191 case LFUN_DIALOG_SHOW_NEXT_INSET:
1194 case LFUN_DIALOG_UPDATE: {
1195 string const & name = argument;
1196 // Can only update a dialog connected to an existing inset
1197 InsetBase * inset = owner->getDialogs().getOpenInset(name);
1199 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument);
1200 inset->dispatch(view()->cursor(), fr);
1201 } else if (name == "paragraph") {
1202 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1203 } else if (name == "prefs") {
1204 owner->getDialogs().update(name, string());
1209 case LFUN_DIALOG_HIDE:
1210 Dialogs::hide(argument, 0);
1213 case LFUN_DIALOG_DISCONNECT_INSET:
1214 owner->getDialogs().disconnect(argument);
1217 case LFUN_CHILDOPEN: {
1218 string const filename =
1219 MakeAbsPath(argument, owner->buffer()->filePath());
1220 setMessage(N_("Opening child document ") +
1221 MakeDisplayPath(filename) + "...");
1222 view()->savePosition(0);
1223 string const parentfilename = owner->buffer()->fileName();
1224 if (bufferlist.exists(filename))
1225 view()->setBuffer(bufferlist.getBuffer(filename));
1227 view()->loadLyXFile(filename);
1228 // Set the parent name of the child document.
1229 // This makes insertion of citations and references in the child work,
1230 // when the target is in the parent or another child document.
1231 owner->buffer()->setParentName(parentfilename);
1235 case LFUN_TOGGLECURSORFOLLOW:
1236 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1240 owner->getIntl().KeyMapOn(false);
1243 case LFUN_KMAP_PRIM:
1244 owner->getIntl().KeyMapPrim();
1248 owner->getIntl().KeyMapSec();
1251 case LFUN_KMAP_TOGGLE:
1252 owner->getIntl().ToggleKeyMap();
1258 string rest = split(argument, countstr, ' ');
1259 istringstream is(countstr);
1262 lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1263 for (int i = 0; i < count; ++i)
1264 dispatch(lyxaction.lookupFunc(rest));
1268 case LFUN_SEQUENCE: {
1269 // argument contains ';'-terminated commands
1270 string arg = argument;
1271 while (!arg.empty()) {
1273 arg = split(arg, first, ';');
1274 FuncRequest func(lyxaction.lookupFunc(first));
1275 func.origin = cmd.origin;
1281 case LFUN_SAVEPREFERENCES: {
1282 Path p(package().user_support());
1283 lyxrc.write("preferences", false);
1287 case LFUN_SCREEN_FONT_UPDATE:
1288 // handle the screen font changes.
1289 lyxrc.set_font_norm_type();
1290 lyx_gui::update_fonts();
1291 // All visible buffers will need resize
1295 case LFUN_SET_COLOR: {
1297 string const x11_name = split(argument, lyx_name, ' ');
1298 if (lyx_name.empty() || x11_name.empty()) {
1299 setErrorMessage(N_("Syntax: set-color <lyx_name>"
1304 bool const graphicsbg_changed =
1305 (lyx_name == lcolor.getLyXName(LColor::graphicsbg) &&
1306 x11_name != lcolor.getX11Name(LColor::graphicsbg));
1308 if (!lcolor.setColor(lyx_name, x11_name)) {
1310 bformat(_("Set-color \"%1$s\" failed "
1311 "- color is undefined or "
1312 "may not be redefined"), lyx_name));
1316 lyx_gui::update_color(lcolor.getFromLyXName(lyx_name));
1318 if (graphicsbg_changed) {
1319 #ifdef WITH_WARNINGS
1320 #warning FIXME!! The graphics cache no longer has a changeDisplay method.
1323 lyx::graphics::GCache::get().changeDisplay(true);
1330 owner->message(argument);
1333 case LFUN_TOOLTIPS_TOGGLE:
1334 owner->getDialogs().toggleTooltips();
1337 case LFUN_EXTERNAL_EDIT: {
1338 FuncRequest fr(action, argument);
1339 InsetExternal().dispatch(view()->cursor(), fr);
1343 case LFUN_GRAPHICS_EDIT: {
1344 FuncRequest fr(action, argument);
1345 InsetGraphics().dispatch(view()->cursor(), fr);
1349 case LFUN_INSET_APPLY: {
1350 string const name = cmd.getArg(0);
1351 InsetBase * inset = owner->getDialogs().getOpenInset(name);
1353 FuncRequest fr(LFUN_INSET_MODIFY, argument);
1354 inset->dispatch(view()->cursor(), fr);
1356 FuncRequest fr(LFUN_INSET_INSERT, argument);
1362 case LFUN_ALL_INSETS_TOGGLE: {
1364 string const name = split(argument, action, ' ');
1365 InsetBase::Code const inset_code =
1366 InsetBase::translate(name);
1368 LCursor & cur = view()->cursor();
1369 FuncRequest fr(LFUN_INSET_TOGGLE, action);
1371 InsetBase & inset = owner->buffer()->inset();
1372 InsetIterator it = inset_iterator_begin(inset);
1373 InsetIterator const end = inset_iterator_end(inset);
1374 for (; it != end; ++it) {
1375 if (inset_code == InsetBase::NO_CODE
1376 || inset_code == it->lyxCode())
1377 it->dispatch(cur, fr);
1382 case LFUN_LANGUAGE_BUFFER: {
1383 Buffer & buffer = *owner->buffer();
1384 Language const * oldL = buffer.params().language;
1385 Language const * newL = languages.getLanguage(argument);
1386 if (!newL || oldL == newL)
1389 if (oldL->RightToLeft() == newL->RightToLeft()
1390 && !buffer.isMultiLingual())
1391 buffer.changeLanguage(oldL, newL);
1393 buffer.updateDocLang(newL);
1397 case LFUN_SAVE_AS_DEFAULT: {
1398 string const fname =
1399 AddName(AddPath(package().user_support(), "templates/"),
1401 Buffer defaults(fname);
1403 istringstream ss(argument);
1406 int const unknown_tokens = defaults.readHeader(lex);
1408 if (unknown_tokens != 0) {
1409 lyxerr << "Warning in LFUN_SAVE_AS_DEFAULT!\n"
1410 << unknown_tokens << " unknown token"
1411 << (unknown_tokens == 1 ? "" : "s")
1415 if (defaults.writeFile(defaults.fileName()))
1416 setMessage(_("Document defaults saved in ")
1417 + MakeDisplayPath(fname));
1419 setErrorMessage(_("Unable to save document defaults"));
1423 case LFUN_BUFFERPARAMS_APPLY: {
1424 biblio::CiteEngine const engine =
1425 owner->buffer()->params().cite_engine;
1427 istringstream ss(argument);
1430 int const unknown_tokens =
1431 owner->buffer()->readHeader(lex);
1433 if (unknown_tokens != 0) {
1434 lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n"
1435 << unknown_tokens << " unknown token"
1436 << (unknown_tokens == 1 ? "" : "s")
1439 if (engine == owner->buffer()->params().cite_engine)
1442 LCursor & cur = view()->cursor();
1443 FuncRequest fr(LFUN_INSET_REFRESH);
1445 InsetBase & inset = owner->buffer()->inset();
1446 InsetIterator it = inset_iterator_begin(inset);
1447 InsetIterator const end = inset_iterator_end(inset);
1448 for (; it != end; ++it)
1449 if (it->lyxCode() == InsetBase::CITE_CODE)
1450 it->dispatch(cur, fr);
1454 case LFUN_TEXTCLASS_APPLY: {
1455 Buffer * buffer = owner->buffer();
1457 lyx::textclass_type const old_class =
1458 buffer->params().textclass;
1460 loadTextclass(argument);
1462 std::pair<bool, lyx::textclass_type> const tc_pair =
1463 textclasslist.NumberOfClass(argument);
1468 lyx::textclass_type const new_class = tc_pair.second;
1469 if (old_class == new_class)
1473 owner->message(_("Converting document to new document class..."));
1475 lyx::cap::SwitchBetweenClasses(
1476 old_class, new_class,
1477 buffer->paragraphs(), el);
1479 bufferErrors(*buffer, el);
1480 view()->showErrorList(_("Class switch"));
1481 updateCounters(*buffer);
1486 case LFUN_TEXTCLASS_LOAD:
1487 loadTextclass(argument);
1490 case LFUN_LYXRC_APPLY: {
1491 LyXRC const lyxrc_orig = lyxrc;
1493 istringstream ss(argument);
1494 bool const success = lyxrc.read(ss) == 0;
1497 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1498 << "Unable to read lyxrc data"
1503 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1508 view()->cursor().dispatch(cmd);
1509 update |= view()->cursor().result().update();
1510 if (!view()->cursor().result().dispatched()) {
1511 update |= view()->dispatch(cmd);
1518 if (view()->available()) {
1519 // Redraw screen unless explicitly told otherwise.
1520 // This also initializes the position cache for all insets
1521 // in (at least partially) visible top-level paragraphs.
1522 view()->update(true, update);
1524 // if we executed a mutating lfun, mark the buffer as dirty
1525 // FIXME: Why not use flag.enabled() but call getStatus again?
1526 if (getStatus(cmd).enabled()
1527 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)
1528 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly))
1529 view()->buffer()->markDirty();
1532 if (view()->cursor().inTexted()) {
1533 view()->owner()->updateLayoutChoice();
1536 sendDispatchMessage(_(getMessage()), cmd);
1540 void LyXFunc::sendDispatchMessage(string const & msg, FuncRequest const & cmd)
1542 owner->updateMenubar();
1543 owner->updateToolbars();
1545 const bool verbose = (cmd.origin == FuncRequest::UI
1546 || cmd.origin == FuncRequest::COMMANDBUFFER);
1548 if (cmd.action == LFUN_SELFINSERT || !verbose) {
1549 lyxerr[Debug::ACTION] << "dispatch msg is " << msg << endl;
1551 owner->message(msg);
1555 string dispatch_msg = msg;
1556 if (!dispatch_msg.empty())
1557 dispatch_msg += ' ';
1559 string comname = lyxaction.getActionName(cmd.action);
1561 bool argsadded = false;
1563 if (!cmd.argument.empty()) {
1564 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1565 comname += ' ' + cmd.argument;
1570 string const shortcuts = toplevel_keymap->printbindings(cmd);
1572 if (!shortcuts.empty()) {
1573 comname += ": " + shortcuts;
1574 } else if (!argsadded && !cmd.argument.empty()) {
1575 comname += ' ' + cmd.argument;
1578 if (!comname.empty()) {
1579 comname = rtrim(comname);
1580 dispatch_msg += '(' + comname + ')';
1583 lyxerr[Debug::ACTION] << "verbose dispatch msg " << dispatch_msg << endl;
1584 if (!dispatch_msg.empty())
1585 owner->message(dispatch_msg);
1589 void LyXFunc::setupLocalKeymap()
1591 keyseq.stdmap = toplevel_keymap.get();
1592 keyseq.curmap = toplevel_keymap.get();
1593 cancel_meta_seq.stdmap = toplevel_keymap.get();
1594 cancel_meta_seq.curmap = toplevel_keymap.get();
1598 void LyXFunc::menuNew(string const & name, bool fromTemplate)
1600 string initpath = lyxrc.document_path;
1601 string filename(name);
1603 if (view()->available()) {
1604 string const trypath = owner->buffer()->filePath();
1605 // If directory is writeable, use this as default.
1606 if (IsDirWriteable(trypath))
1610 static int newfile_number;
1612 if (filename.empty()) {
1613 filename = AddName(lyxrc.document_path,
1614 "newfile" + convert<string>(++newfile_number) + ".lyx");
1615 while (bufferlist.exists(filename) || fs::is_readable(filename)) {
1617 filename = AddName(lyxrc.document_path,
1618 "newfile" + convert<string>(newfile_number) +
1623 // The template stuff
1626 FileDialog fileDlg(_("Select template file"),
1627 LFUN_SELECT_FILE_SYNC,
1628 make_pair(string(_("Documents|#o#O")),
1629 string(lyxrc.document_path)),
1630 make_pair(string(_("Templates|#T#t")),
1631 string(lyxrc.template_path)));
1633 FileDialog::Result result =
1634 fileDlg.open(lyxrc.template_path,
1635 FileFilterList(_("LyX Documents (*.lyx)")),
1638 if (result.first == FileDialog::Later)
1640 if (result.second.empty())
1642 templname = result.second;
1645 view()->newFile(filename, templname, !name.empty());
1649 void LyXFunc::open(string const & fname)
1651 string initpath = lyxrc.document_path;
1653 if (view()->available()) {
1654 string const trypath = owner->buffer()->filePath();
1655 // If directory is writeable, use this as default.
1656 if (IsDirWriteable(trypath))
1662 if (fname.empty()) {
1663 FileDialog fileDlg(_("Select document to open"),
1665 make_pair(string(_("Documents|#o#O")),
1666 string(lyxrc.document_path)),
1667 make_pair(string(_("Examples|#E#e")),
1668 string(AddPath(package().system_support(), "examples"))));
1670 FileDialog::Result result =
1671 fileDlg.open(initpath,
1672 FileFilterList(_("LyX Documents (*.lyx)")),
1675 if (result.first == FileDialog::Later)
1678 filename = result.second;
1680 // check selected filename
1681 if (filename.empty()) {
1682 owner->message(_("Canceled."));
1688 // get absolute path of file and add ".lyx" to the filename if
1690 string const fullpath = FileSearch(string(), filename, "lyx");
1691 if (!fullpath.empty()) {
1692 filename = fullpath;
1695 string const disp_fn(MakeDisplayPath(filename));
1697 // if the file doesn't exist, let the user create one
1698 if (!fs::exists(filename)) {
1699 // the user specifically chose this name. Believe them.
1700 view()->newFile(filename, "", true);
1704 owner->message(bformat(_("Opening document %1$s..."), disp_fn));
1707 if (view()->loadLyXFile(filename)) {
1708 str2 = bformat(_("Document %1$s opened."), disp_fn);
1710 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1712 owner->message(str2);
1716 void LyXFunc::doImport(string const & argument)
1719 string filename = split(argument, format, ' ');
1721 lyxerr[Debug::INFO] << "LyXFunc::doImport: " << format
1722 << " file: " << filename << endl;
1724 // need user interaction
1725 if (filename.empty()) {
1726 string initpath = lyxrc.document_path;
1728 if (view()->available()) {
1729 string const trypath = owner->buffer()->filePath();
1730 // If directory is writeable, use this as default.
1731 if (IsDirWriteable(trypath))
1735 string const text = bformat(_("Select %1$s file to import"),
1736 formats.prettyName(format));
1738 FileDialog fileDlg(text,
1740 make_pair(string(_("Documents|#o#O")),
1741 string(lyxrc.document_path)),
1742 make_pair(string(_("Examples|#E#e")),
1743 string(AddPath(package().system_support(), "examples"))));
1745 string const filter = formats.prettyName(format)
1746 + " (*." + formats.extension(format) + ')';
1748 FileDialog::Result result =
1749 fileDlg.open(initpath,
1750 FileFilterList(filter),
1753 if (result.first == FileDialog::Later)
1756 filename = result.second;
1758 // check selected filename
1759 if (filename.empty())
1760 owner->message(_("Canceled."));
1763 if (filename.empty())
1766 // get absolute path of file
1767 filename = MakeAbsPath(filename);
1769 string const lyxfile = ChangeExtension(filename, ".lyx");
1771 // Check if the document already is open
1772 if (lyx_gui::use_gui && bufferlist.exists(lyxfile)) {
1773 if (!bufferlist.close(bufferlist.getBuffer(lyxfile), true)) {
1774 owner->message(_("Canceled."));
1779 // if the file exists already, and we didn't do
1780 // -i lyx thefile.lyx, warn
1781 if (fs::exists(lyxfile) && filename != lyxfile) {
1782 string const file = MakeDisplayPath(lyxfile, 30);
1784 string text = bformat(_("The document %1$s already exists.\n\n"
1785 "Do you want to over-write that document?"), file);
1786 int const ret = Alert::prompt(_("Over-write document?"),
1787 text, 0, 1, _("&Over-write"), _("&Cancel"));
1790 owner->message(_("Canceled."));
1795 Importer::Import(owner, filename, format);
1799 void LyXFunc::closeBuffer()
1801 if (bufferlist.close(owner->buffer(), true) && !quitting) {
1802 if (bufferlist.empty()) {
1803 // need this otherwise SEGV may occur while
1804 // trying to set variables that don't exist
1805 // since there's no current buffer
1806 owner->getDialogs().hideBufferDependent();
1808 view()->setBuffer(bufferlist.first());
1814 // Each "owner" should have it's own message method. lyxview and
1815 // the minibuffer would use the minibuffer, but lyxserver would
1816 // send an ERROR signal to its client. Alejandro 970603
1817 // This function is bit problematic when it comes to NLS, to make the
1818 // lyx servers client be language indepenent we must not translate
1819 // strings sent to this func.
1820 void LyXFunc::setErrorMessage(string const & m) const
1822 dispatch_buffer = m;
1827 void LyXFunc::setMessage(string const & m) const
1829 dispatch_buffer = m;
1833 string const LyXFunc::viewStatusMessage()
1835 // When meta-fake key is pressed, show the key sequence so far + "M-".
1837 return keyseq.print() + "M-";
1839 // Else, when a non-complete key sequence is pressed,
1840 // show the available options.
1841 if (keyseq.length() > 0 && !keyseq.deleted())
1842 return keyseq.printOptions();
1844 if (!view()->available())
1845 return _("Welcome to LyX!");
1847 return view()->cursor().currentState();
1851 BufferView * LyXFunc::view() const
1853 BOOST_ASSERT(owner);
1854 return owner->view().get();
1858 bool LyXFunc::wasMetaKey() const
1860 return (meta_fake_bit != key_modifier::none);
1866 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1868 // Why the switch you might ask. It is a trick to ensure that all
1869 // the elements in the LyXRCTags enum is handled. As you can see
1870 // there are no breaks at all. So it is just a huge fall-through.
1871 // The nice thing is that we will get a warning from the compiler
1872 // if we forget an element.
1873 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1875 case LyXRC::RC_ACCEPT_COMPOUND:
1876 case LyXRC::RC_ALT_LANG:
1877 case LyXRC::RC_ASCIIROFF_COMMAND:
1878 case LyXRC::RC_ASCII_LINELEN:
1879 case LyXRC::RC_AUTOREGIONDELETE:
1880 case LyXRC::RC_AUTORESET_OPTIONS:
1881 case LyXRC::RC_AUTOSAVE:
1882 case LyXRC::RC_AUTO_NUMBER:
1883 case LyXRC::RC_BACKUPDIR_PATH:
1884 case LyXRC::RC_BIBTEX_COMMAND:
1885 case LyXRC::RC_BINDFILE:
1886 case LyXRC::RC_CHECKLASTFILES:
1887 case LyXRC::RC_CHKTEX_COMMAND:
1888 case LyXRC::RC_CONVERTER:
1889 case LyXRC::RC_COPIER:
1890 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1891 case LyXRC::RC_CUSTOM_EXPORT_COMMAND:
1892 case LyXRC::RC_CUSTOM_EXPORT_FORMAT:
1893 case LyXRC::RC_CYGWIN_PATH_FIX:
1894 if (lyxrc_orig.cygwin_path_fix != lyxrc_new.cygwin_path_fix) {
1895 namespace os = lyx::support::os;
1896 os::cygwin_path_fix(lyxrc_new.cygwin_path_fix);
1898 case LyXRC::RC_DATE_INSERT_FORMAT:
1899 case LyXRC::RC_DEFAULT_LANGUAGE:
1900 case LyXRC::RC_DEFAULT_PAPERSIZE:
1901 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1902 case LyXRC::RC_DISPLAY_GRAPHICS:
1903 case LyXRC::RC_DOCUMENTPATH:
1904 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1905 if (fs::exists(lyxrc_new.document_path) &&
1906 fs::is_directory(lyxrc_new.document_path)) {
1907 using lyx::support::package;
1908 package().document_dir() = lyxrc.document_path;
1911 case LyXRC::RC_ESC_CHARS:
1912 case LyXRC::RC_FONT_ENCODING:
1913 case LyXRC::RC_FORMAT:
1914 case LyXRC::RC_INDEX_COMMAND:
1915 case LyXRC::RC_INPUT:
1916 case LyXRC::RC_KBMAP:
1917 case LyXRC::RC_KBMAP_PRIMARY:
1918 case LyXRC::RC_KBMAP_SECONDARY:
1919 case LyXRC::RC_LABEL_INIT_LENGTH:
1920 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1921 case LyXRC::RC_LANGUAGE_AUTO_END:
1922 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1923 case LyXRC::RC_LANGUAGE_COMMAND_END:
1924 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1925 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1926 case LyXRC::RC_LANGUAGE_PACKAGE:
1927 case LyXRC::RC_LANGUAGE_USE_BABEL:
1928 case LyXRC::RC_LASTFILES:
1929 case LyXRC::RC_MAKE_BACKUP:
1930 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1931 case LyXRC::RC_NUMLASTFILES:
1932 case LyXRC::RC_PATH_PREFIX:
1933 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1934 using lyx::support::prependEnvPath;
1935 prependEnvPath("PATH", lyxrc.path_prefix);
1937 case LyXRC::RC_PERS_DICT:
1938 case LyXRC::RC_POPUP_BOLD_FONT:
1939 case LyXRC::RC_POPUP_FONT_ENCODING:
1940 case LyXRC::RC_POPUP_NORMAL_FONT:
1941 case LyXRC::RC_PREVIEW:
1942 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1943 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1944 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1945 case LyXRC::RC_PRINTCOPIESFLAG:
1946 case LyXRC::RC_PRINTER:
1947 case LyXRC::RC_PRINTEVENPAGEFLAG:
1948 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1949 case LyXRC::RC_PRINTFILEEXTENSION:
1950 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1951 case LyXRC::RC_PRINTODDPAGEFLAG:
1952 case LyXRC::RC_PRINTPAGERANGEFLAG:
1953 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1954 case LyXRC::RC_PRINTPAPERFLAG:
1955 case LyXRC::RC_PRINTREVERSEFLAG:
1956 case LyXRC::RC_PRINTSPOOL_COMMAND:
1957 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1958 case LyXRC::RC_PRINTTOFILE:
1959 case LyXRC::RC_PRINTTOPRINTER:
1960 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1961 case LyXRC::RC_PRINT_COMMAND:
1962 case LyXRC::RC_RTL_SUPPORT:
1963 case LyXRC::RC_SCREEN_DPI:
1964 case LyXRC::RC_SCREEN_FONT_ENCODING:
1965 case LyXRC::RC_SCREEN_FONT_ROMAN:
1966 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1967 case LyXRC::RC_SCREEN_FONT_SANS:
1968 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1969 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1970 case LyXRC::RC_SCREEN_FONT_SIZES:
1971 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1972 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1973 case LyXRC::RC_SCREEN_ZOOM:
1974 case LyXRC::RC_SERVERPIPE:
1975 case LyXRC::RC_SET_COLOR:
1976 case LyXRC::RC_SHOW_BANNER:
1977 case LyXRC::RC_SPELL_COMMAND:
1978 case LyXRC::RC_TEMPDIRPATH:
1979 case LyXRC::RC_TEMPLATEPATH:
1980 case LyXRC::RC_TEX_ALLOWS_SPACES:
1981 case LyXRC::RC_UIFILE:
1982 case LyXRC::RC_USER_EMAIL:
1983 case LyXRC::RC_USER_NAME:
1984 case LyXRC::RC_USETEMPDIR:
1985 case LyXRC::RC_USE_ALT_LANG:
1986 case LyXRC::RC_USE_ESC_CHARS:
1987 case LyXRC::RC_USE_INP_ENC:
1988 case LyXRC::RC_USE_PERS_DICT:
1989 case LyXRC::RC_USE_SPELL_LIB:
1990 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1991 case LyXRC::RC_VIEWER:
1992 case LyXRC::RC_WHEEL_JUMP:
1993 case LyXRC::RC_LAST: