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/filefilterlist.h"
82 #include "support/filetools.h"
83 #include "support/forkedcontr.h"
84 #include "support/fs_extras.h"
85 #include "support/lstrings.h"
86 #include "support/path.h"
87 #include "support/package.h"
88 #include "support/systemcall.h"
89 #include "support/convert.h"
90 #include "support/os.h"
92 #include <boost/filesystem/operations.hpp>
96 using bv_funcs::freefont2string;
98 using lyx::support::AddName;
99 using lyx::support::AddPath;
100 using lyx::support::bformat;
101 using lyx::support::ChangeExtension;
102 using lyx::support::contains;
103 using lyx::support::FileFilterList;
104 using lyx::support::FileSearch;
105 using lyx::support::ForkedcallsController;
106 using lyx::support::i18nLibFileSearch;
107 using lyx::support::IsDirWriteable;
108 using lyx::support::IsFileReadable;
109 using lyx::support::isStrInt;
110 using lyx::support::MakeAbsPath;
111 using lyx::support::MakeDisplayPath;
112 using lyx::support::package;
113 using lyx::support::Path;
114 using lyx::support::QuoteName;
115 using lyx::support::rtrim;
116 using lyx::support::split;
117 using lyx::support::subst;
118 using lyx::support::Systemcall;
119 using lyx::support::token;
120 using lyx::support::trim;
121 using lyx::support::prefixIs;
124 using std::make_pair;
127 using std::istringstream;
129 namespace biblio = lyx::biblio;
130 namespace fs = boost::filesystem;
133 extern BufferList bufferlist;
134 extern LyXServer * lyxserver;
136 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
139 extern tex_accent_struct get_accent(kb_action action);
144 bool getStatus(LCursor cursor,
145 FuncRequest const & cmd, FuncStatus & status)
147 // This is, of course, a mess. Better create a new doc iterator and use
148 // this in Inset::getStatus. This might require an additional
149 // BufferView * arg, though (which should be avoided)
150 //LCursor safe = *this;
152 for ( ; cursor.size(); cursor.pop()) {
153 //lyxerr << "\nLCursor::getStatus: cmd: " << cmd << endl << *this << endl;
154 DocIterator::idx_type & idx = cursor.idx();
155 DocIterator::idx_type const lastidx = cursor.lastidx();
158 lyxerr << "wrong idx " << idx << ", max is " << lastidx
159 << ". Trying to correct this." << endl;
163 DocIterator::pit_type & pit = cursor.pit();
164 DocIterator::pit_type const lastpit = cursor.lastpit();
167 lyxerr << "wrong par " << pit << ", max is " << lastpit
168 << ". Trying to correct this." << endl;
172 DocIterator::pos_type & pos = cursor.pos();
173 DocIterator::pos_type const lastpos = cursor.lastpos();
176 lyxerr << "wrong pos " << pos << ", max is " << lastpos
177 << ". Trying to correct this." << endl;
181 // The inset's getStatus() will return 'true' if it made
182 // a definitive decision on whether it want to handle the
183 // request or not. The result of this decision is put into
184 // the 'status' parameter.
185 if (cursor.inset().getStatus(cursor, cmd, status)) {
195 LyXFunc::LyXFunc(LyXView * lv)
198 keyseq(toplevel_keymap.get(), toplevel_keymap.get()),
199 cancel_meta_seq(toplevel_keymap.get(), toplevel_keymap.get()),
200 meta_fake_bit(key_modifier::none)
205 void LyXFunc::handleKeyFunc(kb_action action)
207 char c = encoded_last_key;
209 if (keyseq.length()) {
213 owner->getIntl().getTransManager()
214 .deadkey(c, get_accent(action).accent, view()->getLyXText());
215 // Need to clear, in case the minibuffer calls these
218 // copied verbatim from do_accent_char
219 view()->cursor().resetAnchor();
224 void LyXFunc::processKeySym(LyXKeySymPtr keysym, key_modifier::state state)
226 lyxerr[Debug::KEY] << "KeySym is " << keysym->getSymbolName() << endl;
228 // Do nothing if we have nothing (JMarc)
229 if (!keysym->isOK()) {
230 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
235 if (keysym->isModifier()) {
236 lyxerr[Debug::KEY] << "isModifier true" << endl;
240 Encoding const * encoding = view()->cursor().getEncoding();
242 encoded_last_key = keysym->getISOEncoded(encoding ? encoding->Name() : "");
244 // Do a one-deep top-level lookup for
245 // cancel and meta-fake keys. RVDK_PATCH_5
246 cancel_meta_seq.reset();
248 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
249 lyxerr[Debug::KEY] << "action first set to [" << func.action << ']' << endl;
251 // When not cancel or meta-fake, do the normal lookup.
252 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
253 // Mostly, meta_fake_bit = key_modifier::none. RVDK_PATCH_5.
254 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_FAKE)) {
255 // remove Caps Lock and Mod2 as a modifiers
256 func = keyseq.addkey(keysym, (state | meta_fake_bit));
257 lyxerr[Debug::KEY] << "action now set to ["
258 << func.action << ']' << endl;
261 // Dont remove this unless you know what you are doing.
262 meta_fake_bit = key_modifier::none;
264 // can this happen now ?
265 if (func.action == LFUN_NOACTION) {
266 func = FuncRequest(LFUN_PREFIX);
269 if (lyxerr.debugging(Debug::KEY)) {
270 lyxerr << "Key [action="
271 << func.action << "]["
272 << keyseq.print() << ']'
276 // already here we know if it any point in going further
277 // why not return already here if action == -1 and
278 // num_bytes == 0? (Lgb)
280 if (keyseq.length() > 1) {
281 owner->message(keyseq.print());
285 // Maybe user can only reach the key via holding down shift.
286 // Let's see. But only if shift is the only modifier
287 if (func.action == LFUN_UNKNOWN_ACTION &&
288 state == key_modifier::shift) {
289 lyxerr[Debug::KEY] << "Trying without shift" << endl;
290 func = keyseq.addkey(keysym, key_modifier::none);
291 lyxerr[Debug::KEY] << "Action now " << func.action << endl;
294 if (func.action == LFUN_UNKNOWN_ACTION) {
295 // Hmm, we didn't match any of the keysequences. See
296 // if it's normal insertable text not already covered
298 if (keysym->isText() && keyseq.length() == 1) {
299 lyxerr[Debug::KEY] << "isText() is true, inserting." << endl;
300 func = FuncRequest(LFUN_SELFINSERT);
302 lyxerr[Debug::KEY] << "Unknown, !isText() - giving up" << endl;
303 owner->message(_("Unknown function."));
308 if (func.action == LFUN_SELFINSERT) {
309 if (encoded_last_key != 0) {
310 string arg(1, encoded_last_key);
311 dispatch(FuncRequest(LFUN_SELFINSERT, arg));
313 << "SelfInsert arg[`" << arg << "']" << endl;
321 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
323 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
325 LCursor & cur = view()->cursor();
327 /* In LyX/Mac, when a dialog is open, the menus of the
328 application can still be accessed without giving focus to
329 the main window. In this case, we want to disable the menu
330 entries that are buffer-related.
333 if (cmd.origin == FuncRequest::UI && !owner->hasFocus())
336 buf = owner->buffer();
338 if (cmd.action == LFUN_NOACTION) {
339 flag.message(N_("Nothing to do"));
344 switch (cmd.action) {
345 case LFUN_UNKNOWN_ACTION:
346 #ifndef HAVE_LIBAIKSAURUS
347 case LFUN_THESAURUS_ENTRY:
353 flag |= lyx_gui::getStatus(cmd);
356 if (flag.unknown()) {
357 flag.message(N_("Unknown action"));
361 if (!flag.enabled()) {
362 if (flag.message().empty())
363 flag.message(N_("Command disabled"));
367 // Check whether we need a buffer
368 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
370 flag.message(N_("Command not allowed with"
371 "out any document open"));
376 // I would really like to avoid having this switch and rather try to
377 // encode this in the function itself.
378 // -- And I'd rather let an inset decide which LFUNs it is willing
379 // to handle (Andre')
381 switch (cmd.action) {
382 case LFUN_TOOLTIPS_TOGGLE:
383 flag.setOnOff(owner->getDialogs().tooltipsEnabled());
386 case LFUN_READ_ONLY_TOGGLE:
387 flag.setOnOff(buf->isReadonly());
390 case LFUN_SWITCHBUFFER:
391 // toggle on the current buffer, but do not toggle off
392 // the other ones (is that a good idea?)
393 if (cmd.argument == buf->fileName())
398 enable = cmd.argument == "custom"
399 || Exporter::IsExportable(*buf, cmd.argument);
403 enable = cur.selection();
407 enable = buf->isLatex() && lyxrc.chktex_command != "none";
411 enable = Exporter::IsExportable(*buf, "program");
414 case LFUN_LAYOUT_TABULAR:
415 enable = cur.innerInsetOfType(InsetBase::TABULAR_CODE);
419 case LFUN_LAYOUT_PARAGRAPH:
420 enable = !cur.inset().forceDefaultParagraphs(&cur.inset());
423 case LFUN_VC_REGISTER:
424 enable = !buf->lyxvc().inUse();
426 case LFUN_VC_CHECKIN:
427 enable = buf->lyxvc().inUse() && !buf->isReadonly();
429 case LFUN_VC_CHECKOUT:
430 enable = buf->lyxvc().inUse() && buf->isReadonly();
434 enable = buf->lyxvc().inUse();
436 case LFUN_MENURELOAD:
437 enable = !buf->isUnnamed() && !buf->isClean();
441 case LFUN_INSET_SETTINGS: {
445 UpdatableInset * inset = cur.inset().asUpdatableInset();
446 lyxerr << "inset: " << inset << endl;
450 InsetBase::Code code = inset->lyxCode();
452 case InsetBase::TABULAR_CODE:
453 enable = cmd.argument == "tabular";
455 case InsetBase::ERT_CODE:
456 enable = cmd.argument == "ert";
458 case InsetBase::FLOAT_CODE:
459 enable = cmd.argument == "float";
461 case InsetBase::WRAP_CODE:
462 enable = cmd.argument == "wrap";
464 case InsetBase::NOTE_CODE:
465 enable = cmd.argument == "note";
467 case InsetBase::BRANCH_CODE:
468 enable = cmd.argument == "branch";
470 case InsetBase::BOX_CODE:
471 enable = cmd.argument == "box";
479 case LFUN_DIALOG_SHOW: {
480 string const name = cmd.getArg(0);
482 enable = name == "aboutlyx"
486 || name == "texinfo";
487 else if (name == "print")
488 enable = Exporter::IsExportable(*buf, "dvi")
489 && lyxrc.print_command != "none";
490 else if (name == "character")
491 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
492 else if (name == "vclog")
493 enable = buf->lyxvc().inUse();
494 else if (name == "latexlog")
495 enable = IsFileReadable(buf->getLogName().second);
499 case LFUN_DIALOG_UPDATE: {
500 string const name = cmd.getArg(0);
502 enable = name == "prefs";
506 // this one is difficult to get right. As a half-baked
507 // solution, we consider only the first action of the sequence
508 case LFUN_SEQUENCE: {
509 // argument contains ';'-terminated commands
510 string const firstcmd = token(cmd.argument, ';', 0);
511 FuncRequest func(lyxaction.lookupFunc(firstcmd));
512 func.origin = cmd.origin;
513 flag = getStatus(func);
517 case LFUN_MENUNEWTMPLT:
518 case LFUN_WORDFINDFORWARD:
519 case LFUN_WORDFINDBACKWARD:
521 case LFUN_EXEC_COMMAND:
524 case LFUN_CLOSEBUFFER:
533 case LFUN_RECONFIGURE:
537 case LFUN_DROP_LAYOUTS_CHOICE:
538 case LFUN_MENU_OPEN_BY_NAME:
541 case LFUN_GOTOFILEROW:
542 case LFUN_GOTO_PARAGRAPH:
543 case LFUN_DIALOG_SHOW_NEW_INSET:
544 case LFUN_DIALOG_SHOW_NEXT_INSET:
545 case LFUN_DIALOG_HIDE:
546 case LFUN_DIALOG_DISCONNECT_INSET:
548 case LFUN_TOGGLECURSORFOLLOW:
552 case LFUN_KMAP_TOGGLE:
554 case LFUN_EXPORT_CUSTOM:
556 case LFUN_SAVEPREFERENCES:
557 case LFUN_SCREEN_FONT_UPDATE:
560 case LFUN_EXTERNAL_EDIT:
561 case LFUN_GRAPHICS_EDIT:
562 case LFUN_ALL_INSETS_TOGGLE:
563 case LFUN_LANGUAGE_BUFFER:
564 case LFUN_TEXTCLASS_APPLY:
565 case LFUN_TEXTCLASS_LOAD:
566 case LFUN_SAVE_AS_DEFAULT:
567 case LFUN_BUFFERPARAMS_APPLY:
568 case LFUN_LYXRC_APPLY:
569 case LFUN_NEXTBUFFER:
570 case LFUN_PREVIOUSBUFFER:
571 // these are handled in our dispatch()
576 if (!::getStatus(cur, cmd, flag))
577 flag = view()->getStatus(cmd);
583 // Can we use a readonly buffer?
584 if (buf && buf->isReadonly()
585 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
586 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
587 flag.message(N_("Document is read-only"));
591 // the default error message if we disable the command
592 if (!flag.enabled() && flag.message().empty())
593 flag.message(N_("Command disabled"));
601 bool ensureBufferClean(BufferView * bv)
603 Buffer & buf = *bv->buffer();
607 string const file = MakeDisplayPath(buf.fileName(), 30);
608 string text = bformat(_("The document %1$s has unsaved "
609 "changes.\n\nDo you want to save "
610 "the document?"), file);
611 int const ret = Alert::prompt(_("Save changed document?"),
612 text, 0, 1, _("&Save"),
616 bv->owner()->dispatch(FuncRequest(LFUN_MENUWRITE));
618 return buf.isClean();
622 void showPrintError(string const & name)
624 string str = bformat(_("Could not print the document %1$s.\n"
625 "Check that your printer is set up correctly."),
626 MakeDisplayPath(name, 50));
627 Alert::error(_("Print document failed"), str);
631 void loadTextclass(string const & name)
633 std::pair<bool, lyx::textclass_type> const tc_pair =
634 textclasslist.NumberOfClass(name);
636 if (!tc_pair.first) {
637 lyxerr << "Document class \"" << name
638 << "\" does not exist."
643 lyx::textclass_type const tc = tc_pair.second;
645 if (!textclasslist[tc].load()) {
646 string s = bformat(_("The document could not be converted\n"
647 "into the document class %1$s."),
648 textclasslist[tc].name());
649 Alert::error(_("Could not change class"), s);
654 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
659 void LyXFunc::dispatch(FuncRequest const & cmd)
661 BOOST_ASSERT(view());
662 string const argument = cmd.argument;
663 kb_action const action = cmd.action;
665 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl;
666 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
668 // we have not done anything wrong yet.
670 dispatch_buffer.erase();
674 FuncStatus const flag = getStatus(cmd);
675 if (!flag.enabled()) {
676 // We cannot use this function here
677 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: "
678 << lyxaction.getActionName(action)
679 << " [" << action << "] is disabled at this location"
681 setErrorMessage(flag.message());
684 if (view()->available())
685 view()->hideCursor();
689 case LFUN_WORDFINDFORWARD:
690 case LFUN_WORDFINDBACKWARD: {
691 static string last_search;
692 string searched_string;
694 if (!argument.empty()) {
695 last_search = argument;
696 searched_string = argument;
698 searched_string = last_search;
701 if (searched_string.empty())
704 bool const fw = action == LFUN_WORDFINDFORWARD;
706 lyx::find::find2string(searched_string, true, false, fw);
707 lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data));
712 owner->message(keyseq.printOptions());
715 case LFUN_EXEC_COMMAND:
716 owner->getToolbars().display("minibuffer", true);
717 owner->focus_command_buffer();
722 meta_fake_bit = key_modifier::none;
723 if (view()->available())
724 // cancel any selection
725 dispatch(FuncRequest(LFUN_MARK_OFF));
726 setMessage(N_("Cancel"));
730 meta_fake_bit = key_modifier::alt;
731 setMessage(keyseq.print());
734 case LFUN_READ_ONLY_TOGGLE:
735 if (owner->buffer()->lyxvc().inUse())
736 owner->buffer()->lyxvc().toggleReadOnly();
738 owner->buffer()->setReadonly(
739 !owner->buffer()->isReadonly());
742 // --- Menus -----------------------------------------------
744 menuNew(argument, false);
747 case LFUN_MENUNEWTMPLT:
748 menuNew(argument, true);
751 case LFUN_CLOSEBUFFER:
756 if (!owner->buffer()->isUnnamed()) {
757 string const str = bformat(_("Saving document %1$s..."),
758 MakeDisplayPath(owner->buffer()->fileName()));
760 MenuWrite(owner->buffer());
761 owner->message(str + _(" done."));
763 WriteAs(owner->buffer());
767 WriteAs(owner->buffer(), argument);
770 case LFUN_MENURELOAD: {
771 string const file = MakeDisplayPath(view()->buffer()->fileName(), 20);
772 string text = bformat(_("Any changes will be lost. Are you sure "
773 "you want to revert to the saved version of the document %1$s?"), file);
774 int const ret = Alert::prompt(_("Revert to saved document?"),
775 text, 0, 1, _("&Revert"), _("&Cancel"));
783 Exporter::Export(owner->buffer(), argument, true);
784 view()->showErrorList(BufferFormat(*owner->buffer()));
788 Exporter::Preview(owner->buffer(), argument);
789 view()->showErrorList(BufferFormat(*owner->buffer()));
793 Exporter::Export(owner->buffer(), "program", true);
794 view()->showErrorList(_("Build"));
798 owner->buffer()->runChktex();
799 view()->showErrorList(_("ChkTeX"));
803 if (argument == "custom")
804 owner->getDialogs().show("sendto");
806 Exporter::Export(owner->buffer(), argument, false);
807 view()->showErrorList(BufferFormat(*owner->buffer()));
811 case LFUN_EXPORT_CUSTOM: {
813 string command = split(argument, format_name, ' ');
814 Format const * format = formats.getFormat(format_name);
816 lyxerr << "Format \"" << format_name
817 << "\" not recognized!"
822 Buffer * buffer = owner->buffer();
824 // The name of the file created by the conversion process
827 // Output to filename
828 if (format->name() == "lyx") {
829 string const latexname =
830 buffer->getLatexName(false);
831 filename = ChangeExtension(latexname,
832 format->extension());
833 filename = AddName(buffer->temppath(), filename);
835 if (!buffer->writeFile(filename))
839 Exporter::Export(buffer, format_name, true,
843 // Substitute $$FName for filename
844 if (!contains(command, "$$FName"))
845 command = "( " + command + " ) < $$FName";
846 command = subst(command, "$$FName", filename);
848 // Execute the command in the background
850 call.startscript(Systemcall::DontWait, command);
857 string command = split(split(argument, target, ' '),
861 || target_name.empty()
862 || command.empty()) {
863 lyxerr << "Unable to parse \""
864 << argument << '"' << std::endl;
867 if (target != "printer" && target != "file") {
868 lyxerr << "Unrecognized target \""
869 << target << '"' << std::endl;
873 Buffer * buffer = owner->buffer();
875 if (!Exporter::Export(buffer, "dvi", true)) {
876 showPrintError(buffer->fileName());
880 // Push directory path.
881 string const path = buffer->temppath();
884 // there are three cases here:
885 // 1. we print to a file
886 // 2. we print directly to a printer
887 // 3. we print using a spool command (print to file first)
890 string const dviname =
891 ChangeExtension(buffer->getLatexName(true),
894 if (target == "printer") {
895 if (!lyxrc.print_spool_command.empty()) {
896 // case 3: print using a spool
897 string const psname =
898 ChangeExtension(dviname,".ps");
899 command += lyxrc.print_to_file
902 + QuoteName(dviname);
905 lyxrc.print_spool_command +' ';
906 if (target_name != "default") {
907 command2 += lyxrc.print_spool_printerprefix
911 command2 += QuoteName(psname);
913 // If successful, then spool command
914 res = one.startscript(
919 res = one.startscript(
920 Systemcall::DontWait,
923 // case 2: print directly to a printer
924 res = one.startscript(
925 Systemcall::DontWait,
926 command + QuoteName(dviname));
930 // case 1: print to a file
931 command += lyxrc.print_to_file
932 + QuoteName(MakeAbsPath(target_name,
935 + QuoteName(dviname);
936 res = one.startscript(Systemcall::DontWait,
941 showPrintError(buffer->fileName());
954 InsetCommandParams p("tableofcontents");
955 string const data = InsetCommandMailer::params2string("toc", p);
956 owner->getDialogs().show("toc", data, 0);
964 case LFUN_RECONFIGURE:
968 case LFUN_HELP_OPEN: {
969 string const arg = argument;
971 setErrorMessage(N_("Missing argument"));
974 string const fname = i18nLibFileSearch("doc", arg, "lyx");
976 lyxerr << "LyX: unable to find documentation file `"
977 << arg << "'. Bad installation?" << endl;
980 owner->message(bformat(_("Opening help file %1$s..."),
981 MakeDisplayPath(fname)));
982 view()->loadLyXFile(fname, false);
986 // --- version control -------------------------------
987 case LFUN_VC_REGISTER:
988 if (!ensureBufferClean(view()))
990 if (!owner->buffer()->lyxvc().inUse()) {
991 owner->buffer()->lyxvc().registrer();
996 case LFUN_VC_CHECKIN:
997 if (!ensureBufferClean(view()))
999 if (owner->buffer()->lyxvc().inUse()
1000 && !owner->buffer()->isReadonly()) {
1001 owner->buffer()->lyxvc().checkIn();
1006 case LFUN_VC_CHECKOUT:
1007 if (!ensureBufferClean(view()))
1009 if (owner->buffer()->lyxvc().inUse()
1010 && owner->buffer()->isReadonly()) {
1011 owner->buffer()->lyxvc().checkOut();
1016 case LFUN_VC_REVERT:
1017 owner->buffer()->lyxvc().revert();
1022 owner->buffer()->lyxvc().undoLast();
1026 // --- buffers ----------------------------------------
1027 case LFUN_SWITCHBUFFER:
1028 view()->setBuffer(bufferlist.getBuffer(argument));
1031 case LFUN_NEXTBUFFER:
1032 view()->setBuffer(bufferlist.next(view()->buffer()));
1035 case LFUN_PREVIOUSBUFFER:
1036 view()->setBuffer(bufferlist.previous(view()->buffer()));
1040 NewFile(view(), argument);
1043 case LFUN_FILE_OPEN:
1047 case LFUN_DROP_LAYOUTS_CHOICE:
1048 owner->getToolbars().openLayoutList();
1051 case LFUN_MENU_OPEN_BY_NAME:
1052 owner->getMenubar().openByName(argument);
1055 // --- lyxserver commands ----------------------------
1057 setMessage(owner->buffer()->fileName());
1058 lyxerr[Debug::INFO] << "FNAME["
1059 << owner->buffer()->fileName()
1064 dispatch_buffer = keyseq.print();
1065 lyxserver->notifyClient(dispatch_buffer);
1068 case LFUN_GOTOFILEROW: {
1071 istringstream is(argument);
1072 is >> file_name >> row;
1073 if (prefixIs(file_name, package().temp_dir())) {
1074 // Needed by inverse dvi search. If it is a file
1075 // in tmpdir, call the apropriated function
1076 view()->setBuffer(bufferlist.getBufferFromTmp(file_name));
1078 // Must replace extension of the file to be .lyx
1079 // and get full path
1080 string const s = ChangeExtension(file_name, ".lyx");
1081 // Either change buffer or load the file
1082 if (bufferlist.exists(s)) {
1083 view()->setBuffer(bufferlist.getBuffer(s));
1085 view()->loadLyXFile(s);
1089 view()->setCursorFromRow(row);
1092 // see BufferView_pimpl::center()
1093 view()->updateScrollbar();
1097 case LFUN_GOTO_PARAGRAPH: {
1098 istringstream is(argument);
1101 ParIterator par = owner->buffer()->getParFromID(id);
1102 if (par == owner->buffer()->par_iterator_end()) {
1103 lyxerr[Debug::INFO] << "No matching paragraph found! ["
1104 << id << ']' << endl;
1107 lyxerr[Debug::INFO] << "Paragraph " << par->id()
1108 << " found." << endl;
1112 view()->setCursor(par, 0);
1114 view()->switchKeyMap();
1115 owner->view_state_changed();
1118 // see BufferView_pimpl::center()
1119 view()->updateScrollbar();
1123 case LFUN_DIALOG_SHOW: {
1124 string const name = cmd.getArg(0);
1125 string data = trim(cmd.argument.substr(name.size()));
1127 if (name == "character") {
1128 data = freefont2string();
1130 owner->getDialogs().show("character", data);
1133 else if (name == "latexlog") {
1134 pair<Buffer::LogType, string> const logfile =
1135 owner->buffer()->getLogName();
1136 switch (logfile.first) {
1137 case Buffer::latexlog:
1140 case Buffer::buildlog:
1144 data += logfile.second;
1145 owner->getDialogs().show("log", data);
1147 else if (name == "vclog") {
1148 string const data = "vc " +
1149 owner->buffer()->lyxvc().getLogFile();
1150 owner->getDialogs().show("log", data);
1153 owner->getDialogs().show(name, data);
1157 case LFUN_DIALOG_SHOW_NEW_INSET: {
1158 string const name = cmd.getArg(0);
1159 string data = trim(cmd.argument.substr(name.size()));
1160 if (name == "bibitem" ||
1162 name == "include" ||
1168 InsetCommandParams p(name);
1169 data = InsetCommandMailer::params2string(name, p);
1170 } else if (name == "box") {
1171 // \c data == "Boxed" || "Frameless" etc
1172 InsetBoxParams p(data);
1173 data = InsetBoxMailer::params2string(p);
1174 } else if (name == "branch") {
1175 InsetBranchParams p;
1176 data = InsetBranchMailer::params2string(p);
1177 } else if (name == "citation") {
1178 InsetCommandParams p("cite");
1179 data = InsetCommandMailer::params2string(name, p);
1180 } else if (name == "ert") {
1181 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1182 } else if (name == "external") {
1183 InsetExternalParams p;
1184 Buffer const & buffer = *owner->buffer();
1185 data = InsetExternalMailer::params2string(p, buffer);
1186 } else if (name == "float") {
1188 data = InsetFloatMailer::params2string(p);
1189 } else if (name == "graphics") {
1190 InsetGraphicsParams p;
1191 Buffer const & buffer = *owner->buffer();
1192 data = InsetGraphicsMailer::params2string(p, buffer);
1193 } else if (name == "note") {
1195 data = InsetNoteMailer::params2string(p);
1196 } else if (name == "vspace") {
1198 data = InsetVSpaceMailer::params2string(space);
1199 } else if (name == "wrap") {
1201 data = InsetWrapMailer::params2string(p);
1203 owner->getDialogs().show(name, data, 0);
1207 case LFUN_DIALOG_SHOW_NEXT_INSET:
1210 case LFUN_DIALOG_UPDATE: {
1211 string const & name = argument;
1212 // Can only update a dialog connected to an existing inset
1213 InsetBase * inset = owner->getDialogs().getOpenInset(name);
1215 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument);
1216 inset->dispatch(view()->cursor(), fr);
1217 } else if (name == "paragraph") {
1218 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1219 } else if (name == "prefs") {
1220 owner->getDialogs().update(name, string());
1225 case LFUN_DIALOG_HIDE:
1226 Dialogs::hide(argument, 0);
1229 case LFUN_DIALOG_DISCONNECT_INSET:
1230 owner->getDialogs().disconnect(argument);
1233 case LFUN_CHILDOPEN: {
1234 string const filename =
1235 MakeAbsPath(argument, owner->buffer()->filePath());
1236 setMessage(N_("Opening child document ") +
1237 MakeDisplayPath(filename) + "...");
1238 view()->savePosition(0);
1239 string const parentfilename = owner->buffer()->fileName();
1240 if (bufferlist.exists(filename))
1241 view()->setBuffer(bufferlist.getBuffer(filename));
1243 view()->loadLyXFile(filename);
1244 // Set the parent name of the child document.
1245 // This makes insertion of citations and references in the child work,
1246 // when the target is in the parent or another child document.
1247 owner->buffer()->setParentName(parentfilename);
1251 case LFUN_TOGGLECURSORFOLLOW:
1252 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1256 owner->getIntl().KeyMapOn(false);
1259 case LFUN_KMAP_PRIM:
1260 owner->getIntl().KeyMapPrim();
1264 owner->getIntl().KeyMapSec();
1267 case LFUN_KMAP_TOGGLE:
1268 owner->getIntl().ToggleKeyMap();
1274 string rest = split(argument, countstr, ' ');
1275 istringstream is(countstr);
1278 lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1279 for (int i = 0; i < count; ++i)
1280 dispatch(lyxaction.lookupFunc(rest));
1284 case LFUN_SEQUENCE: {
1285 // argument contains ';'-terminated commands
1286 string arg = argument;
1287 while (!arg.empty()) {
1289 arg = split(arg, first, ';');
1290 FuncRequest func(lyxaction.lookupFunc(first));
1291 func.origin = cmd.origin;
1297 case LFUN_SAVEPREFERENCES: {
1298 Path p(package().user_support());
1299 lyxrc.write("preferences", false);
1303 case LFUN_SCREEN_FONT_UPDATE:
1304 // handle the screen font changes.
1305 lyxrc.set_font_norm_type();
1306 lyx_gui::update_fonts();
1307 // All visible buffers will need resize
1311 case LFUN_SET_COLOR: {
1313 string const x11_name = split(argument, lyx_name, ' ');
1314 if (lyx_name.empty() || x11_name.empty()) {
1315 setErrorMessage(N_("Syntax: set-color <lyx_name>"
1320 bool const graphicsbg_changed =
1321 (lyx_name == lcolor.getLyXName(LColor::graphicsbg) &&
1322 x11_name != lcolor.getX11Name(LColor::graphicsbg));
1324 if (!lcolor.setColor(lyx_name, x11_name)) {
1326 bformat(_("Set-color \"%1$s\" failed "
1327 "- color is undefined or "
1328 "may not be redefined"), lyx_name));
1332 lyx_gui::update_color(lcolor.getFromLyXName(lyx_name));
1334 if (graphicsbg_changed) {
1335 #ifdef WITH_WARNINGS
1336 #warning FIXME!! The graphics cache no longer has a changeDisplay method.
1339 lyx::graphics::GCache::get().changeDisplay(true);
1346 owner->message(argument);
1349 case LFUN_TOOLTIPS_TOGGLE:
1350 owner->getDialogs().toggleTooltips();
1353 case LFUN_EXTERNAL_EDIT: {
1354 FuncRequest fr(action, argument);
1355 InsetExternal().dispatch(view()->cursor(), fr);
1359 case LFUN_GRAPHICS_EDIT: {
1360 FuncRequest fr(action, argument);
1361 InsetGraphics().dispatch(view()->cursor(), fr);
1365 case LFUN_ALL_INSETS_TOGGLE: {
1367 string const name = split(argument, action, ' ');
1368 InsetBase::Code const inset_code =
1369 InsetBase::translate(name);
1371 LCursor & cur = view()->cursor();
1372 FuncRequest fr(LFUN_INSET_TOGGLE, action);
1374 InsetBase & inset = owner->buffer()->inset();
1375 InsetIterator it = inset_iterator_begin(inset);
1376 InsetIterator const end = inset_iterator_end(inset);
1377 for (; it != end; ++it) {
1378 if (inset_code == InsetBase::NO_CODE
1379 || inset_code == it->lyxCode())
1380 it->dispatch(cur, fr);
1385 case LFUN_LANGUAGE_BUFFER: {
1386 Buffer & buffer = *owner->buffer();
1387 Language const * oldL = buffer.params().language;
1388 Language const * newL = languages.getLanguage(argument);
1389 if (!newL || oldL == newL)
1392 if (oldL->RightToLeft() == newL->RightToLeft()
1393 && !buffer.isMultiLingual())
1394 buffer.changeLanguage(oldL, newL);
1396 buffer.updateDocLang(newL);
1400 case LFUN_SAVE_AS_DEFAULT: {
1401 string const fname =
1402 AddName(AddPath(package().user_support(), "templates/"),
1404 Buffer defaults(fname);
1406 istringstream ss(argument);
1409 int const unknown_tokens = defaults.readHeader(lex);
1411 if (unknown_tokens != 0) {
1412 lyxerr << "Warning in LFUN_SAVE_AS_DEFAULT!\n"
1413 << unknown_tokens << " unknown token"
1414 << (unknown_tokens == 1 ? "" : "s")
1418 if (defaults.writeFile(defaults.fileName()))
1419 setMessage(_("Document defaults saved in ")
1420 + MakeDisplayPath(fname));
1422 setErrorMessage(_("Unable to save document defaults"));
1426 case LFUN_BUFFERPARAMS_APPLY: {
1427 biblio::CiteEngine const engine =
1428 owner->buffer()->params().cite_engine;
1430 istringstream ss(argument);
1433 int const unknown_tokens =
1434 owner->buffer()->readHeader(lex);
1436 if (unknown_tokens != 0) {
1437 lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n"
1438 << unknown_tokens << " unknown token"
1439 << (unknown_tokens == 1 ? "" : "s")
1442 if (engine == owner->buffer()->params().cite_engine)
1445 LCursor & cur = view()->cursor();
1446 FuncRequest fr(LFUN_INSET_REFRESH);
1448 InsetBase & inset = owner->buffer()->inset();
1449 InsetIterator it = inset_iterator_begin(inset);
1450 InsetIterator const end = inset_iterator_end(inset);
1451 for (; it != end; ++it)
1452 if (it->lyxCode() == InsetBase::CITE_CODE)
1453 it->dispatch(cur, fr);
1457 case LFUN_TEXTCLASS_APPLY: {
1458 Buffer * buffer = owner->buffer();
1460 lyx::textclass_type const old_class =
1461 buffer->params().textclass;
1463 loadTextclass(argument);
1465 std::pair<bool, lyx::textclass_type> const tc_pair =
1466 textclasslist.NumberOfClass(argument);
1471 lyx::textclass_type const new_class = tc_pair.second;
1472 if (old_class == new_class)
1476 owner->message(_("Converting document to new document class..."));
1478 lyx::cap::SwitchLayoutsBetweenClasses(
1479 old_class, new_class,
1480 buffer->paragraphs(), el);
1482 bufferErrors(*buffer, el);
1483 view()->showErrorList(_("Class switch"));
1487 case LFUN_TEXTCLASS_LOAD:
1488 loadTextclass(argument);
1491 case LFUN_LYXRC_APPLY: {
1492 LyXRC const lyxrc_orig = lyxrc;
1494 istringstream ss(argument);
1495 bool const success = lyxrc.read(ss) == 0;
1498 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1499 << "Unable to read lyxrc data"
1504 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1510 view()->cursor().dispatch(cmd);
1511 if (view()->cursor().result().dispatched())
1512 update |= view()->cursor().result().update();
1514 update |= view()->dispatch(cmd);
1519 if (view()->available()) {
1520 // Redraw screen unless explicitly told otherwise.
1521 // This also initializes the position cache for all insets
1522 // in (at least partially) visible top-level paragraphs.
1523 view()->update(true, update);
1525 // if we executed a mutating lfun, mark the buffer as dirty
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_UIFILE:
1981 case LyXRC::RC_USER_EMAIL:
1982 case LyXRC::RC_USER_NAME:
1983 case LyXRC::RC_USETEMPDIR:
1984 case LyXRC::RC_USE_ALT_LANG:
1985 case LyXRC::RC_USE_ESC_CHARS:
1986 case LyXRC::RC_USE_INP_ENC:
1987 case LyXRC::RC_USE_PERS_DICT:
1988 case LyXRC::RC_USE_SPELL_LIB:
1989 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1990 case LyXRC::RC_VIEWER:
1991 case LyXRC::RC_WHEEL_JUMP:
1992 case LyXRC::RC_LAST: