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/FileInfo.h"
83 #include "support/filetools.h"
84 #include "support/forkedcontr.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"
94 using bv_funcs::freefont2string;
96 using lyx::support::AddName;
97 using lyx::support::AddPath;
98 using lyx::support::bformat;
99 using lyx::support::ChangeExtension;
100 using lyx::support::contains;
101 using lyx::support::FileFilterList;
102 using lyx::support::FileInfo;
103 using lyx::support::FileSearch;
104 using lyx::support::ForkedcallsController;
105 using lyx::support::i18nLibFileSearch;
106 using lyx::support::IsDirWriteable;
107 using lyx::support::IsFileReadable;
108 using lyx::support::isStrInt;
109 using lyx::support::MakeAbsPath;
110 using lyx::support::MakeDisplayPath;
111 using lyx::support::package;
112 using lyx::support::Path;
113 using lyx::support::QuoteName;
114 using lyx::support::rtrim;
115 using lyx::support::split;
116 using lyx::support::subst;
117 using lyx::support::Systemcall;
118 using lyx::support::token;
119 using lyx::support::trim;
120 using lyx::support::prefixIs;
123 using std::make_pair;
126 using std::istringstream;
128 namespace biblio = lyx::biblio;
131 extern BufferList bufferlist;
132 extern LyXServer * lyxserver;
134 extern boost::scoped_ptr<kb_keymap> toplevel_keymap;
137 extern tex_accent_struct get_accent(kb_action action);
142 bool getStatus(LCursor cursor,
143 FuncRequest const & cmd, FuncStatus & status)
145 // This is, of course, a mess. Better create a new doc iterator and use
146 // this in Inset::getStatus. This might require an additional
147 // BufferView * arg, though (which should be avoided)
148 //LCursor safe = *this;
150 for ( ; cursor.size(); cursor.pop()) {
151 //lyxerr << "\nLCursor::getStatus: cmd: " << cmd << endl << *this << endl;
152 DocIterator::idx_type & idx = cursor.idx();
153 DocIterator::idx_type const lastidx = cursor.lastidx();
156 lyxerr << "wrong idx " << idx << ", max is " << lastidx
157 << ". Trying to correct this." << endl;
161 DocIterator::pit_type & pit = cursor.pit();
162 DocIterator::pit_type const lastpit = cursor.lastpit();
165 lyxerr << "wrong par " << pit << ", max is " << lastpit
166 << ". Trying to correct this." << endl;
170 DocIterator::pos_type & pos = cursor.pos();
171 DocIterator::pos_type const lastpos = cursor.lastpos();
174 lyxerr << "wrong pos " << pos << ", max is " << lastpos
175 << ". Trying to correct this." << endl;
179 // The inset's getStatus() will return 'true' if it made
180 // a definitive decision on whether it want to handle the
181 // request or not. The result of this decision is put into
182 // the 'status' parameter.
183 if (cursor.inset().getStatus(cursor, cmd, status)) {
193 LyXFunc::LyXFunc(LyXView * lv)
196 keyseq(toplevel_keymap.get(), toplevel_keymap.get()),
197 cancel_meta_seq(toplevel_keymap.get(), toplevel_keymap.get()),
198 meta_fake_bit(key_modifier::none)
203 void LyXFunc::handleKeyFunc(kb_action action)
205 char c = encoded_last_key;
207 if (keyseq.length()) {
211 owner->getIntl().getTransManager()
212 .deadkey(c, get_accent(action).accent, view()->getLyXText());
213 // Need to clear, in case the minibuffer calls these
216 // copied verbatim from do_accent_char
217 view()->cursor().resetAnchor();
222 void LyXFunc::processKeySym(LyXKeySymPtr keysym, key_modifier::state state)
224 lyxerr[Debug::KEY] << "KeySym is " << keysym->getSymbolName() << endl;
226 // Do nothing if we have nothing (JMarc)
227 if (!keysym->isOK()) {
228 lyxerr[Debug::KEY] << "Empty kbd action (probably composing)"
233 if (keysym->isModifier()) {
234 lyxerr[Debug::KEY] << "isModifier true" << endl;
238 Encoding const * encoding = view()->cursor().getEncoding();
240 encoded_last_key = keysym->getISOEncoded(encoding ? encoding->Name() : "");
242 // Do a one-deep top-level lookup for
243 // cancel and meta-fake keys. RVDK_PATCH_5
244 cancel_meta_seq.reset();
246 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
247 lyxerr[Debug::KEY] << "action first set to [" << func.action << ']' << endl;
249 // When not cancel or meta-fake, do the normal lookup.
250 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
251 // Mostly, meta_fake_bit = key_modifier::none. RVDK_PATCH_5.
252 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_FAKE)) {
253 // remove Caps Lock and Mod2 as a modifiers
254 func = keyseq.addkey(keysym, (state | meta_fake_bit));
255 lyxerr[Debug::KEY] << "action now set to ["
256 << func.action << ']' << endl;
259 // Dont remove this unless you know what you are doing.
260 meta_fake_bit = key_modifier::none;
262 // can this happen now ?
263 if (func.action == LFUN_NOACTION) {
264 func = FuncRequest(LFUN_PREFIX);
267 if (lyxerr.debugging(Debug::KEY)) {
268 lyxerr << "Key [action="
269 << func.action << "]["
270 << keyseq.print() << ']'
274 // already here we know if it any point in going further
275 // why not return already here if action == -1 and
276 // num_bytes == 0? (Lgb)
278 if (keyseq.length() > 1) {
279 owner->message(keyseq.print());
283 // Maybe user can only reach the key via holding down shift.
284 // Let's see. But only if shift is the only modifier
285 if (func.action == LFUN_UNKNOWN_ACTION &&
286 state == key_modifier::shift) {
287 lyxerr[Debug::KEY] << "Trying without shift" << endl;
288 func = keyseq.addkey(keysym, key_modifier::none);
289 lyxerr[Debug::KEY] << "Action now " << func.action << endl;
292 if (func.action == LFUN_UNKNOWN_ACTION) {
293 // Hmm, we didn't match any of the keysequences. See
294 // if it's normal insertable text not already covered
296 if (keysym->isText() && keyseq.length() == 1) {
297 lyxerr[Debug::KEY] << "isText() is true, inserting." << endl;
298 func = FuncRequest(LFUN_SELFINSERT);
300 lyxerr[Debug::KEY] << "Unknown, !isText() - giving up" << endl;
301 owner->message(_("Unknown function."));
306 if (func.action == LFUN_SELFINSERT) {
307 if (encoded_last_key != 0) {
308 string arg(1, encoded_last_key);
309 dispatch(FuncRequest(LFUN_SELFINSERT, arg));
311 << "SelfInsert arg[`" << arg << "']" << endl;
319 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
321 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
323 LCursor & cur = view()->cursor();
325 /* In LyX/Mac, when a dialog is open, the menus of the
326 application can still be accessed without giving focus to
327 the main window. In this case, we want to disable the menu
328 entries that are buffer-related.
331 if (cmd.origin == FuncRequest::UI && !owner->hasFocus())
334 buf = owner->buffer();
336 if (cmd.action == LFUN_NOACTION) {
337 flag.message(N_("Nothing to do"));
342 switch (cmd.action) {
343 case LFUN_UNKNOWN_ACTION:
344 #ifndef HAVE_LIBAIKSAURUS
345 case LFUN_THESAURUS_ENTRY:
351 flag |= lyx_gui::getStatus(cmd);
354 if (flag.unknown()) {
355 flag.message(N_("Unknown action"));
359 if (!flag.enabled()) {
360 if (flag.message().empty())
361 flag.message(N_("Command disabled"));
365 // Check whether we need a buffer
366 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
368 flag.message(N_("Command not allowed with"
369 "out any document open"));
374 // I would really like to avoid having this switch and rather try to
375 // encode this in the function itself.
376 // -- And I'd rather let an inset decide which LFUNs it is willing
377 // to handle (Andre')
379 switch (cmd.action) {
380 case LFUN_TOOLTIPS_TOGGLE:
381 flag.setOnOff(owner->getDialogs().tooltipsEnabled());
384 case LFUN_READ_ONLY_TOGGLE:
385 flag.setOnOff(buf->isReadonly());
388 case LFUN_SWITCHBUFFER:
389 // toggle on the current buffer, but do not toggle off
390 // the other ones (is that a good idea?)
391 if (cmd.argument == buf->fileName())
396 enable = cmd.argument == "custom"
397 || Exporter::IsExportable(*buf, cmd.argument);
401 enable = cur.selection();
405 enable = buf->isLatex() && lyxrc.chktex_command != "none";
409 enable = Exporter::IsExportable(*buf, "program");
412 case LFUN_LAYOUT_TABULAR:
413 enable = cur.innerInsetOfType(InsetBase::TABULAR_CODE);
417 case LFUN_LAYOUT_PARAGRAPH:
418 enable = !cur.inset().forceDefaultParagraphs(&cur.inset());
421 case LFUN_VC_REGISTER:
422 enable = !buf->lyxvc().inUse();
424 case LFUN_VC_CHECKIN:
425 enable = buf->lyxvc().inUse() && !buf->isReadonly();
427 case LFUN_VC_CHECKOUT:
428 enable = buf->lyxvc().inUse() && buf->isReadonly();
432 enable = buf->lyxvc().inUse();
434 case LFUN_MENURELOAD:
435 enable = !buf->isUnnamed() && !buf->isClean();
439 case LFUN_INSET_SETTINGS: {
443 UpdatableInset * inset = cur.inset().asUpdatableInset();
444 lyxerr << "inset: " << inset << endl;
448 InsetBase::Code code = inset->lyxCode();
450 case InsetBase::TABULAR_CODE:
451 enable = cmd.argument == "tabular";
453 case InsetBase::ERT_CODE:
454 enable = cmd.argument == "ert";
456 case InsetBase::FLOAT_CODE:
457 enable = cmd.argument == "float";
459 case InsetBase::WRAP_CODE:
460 enable = cmd.argument == "wrap";
462 case InsetBase::NOTE_CODE:
463 enable = cmd.argument == "note";
465 case InsetBase::BRANCH_CODE:
466 enable = cmd.argument == "branch";
468 case InsetBase::BOX_CODE:
469 enable = cmd.argument == "box";
477 case LFUN_DIALOG_SHOW: {
478 string const name = cmd.getArg(0);
480 enable = name == "aboutlyx"
484 || name == "texinfo";
485 else if (name == "print")
486 enable = Exporter::IsExportable(*buf, "dvi")
487 && lyxrc.print_command != "none";
488 else if (name == "character")
489 enable = cur.inset().lyxCode() != InsetBase::ERT_CODE;
490 else if (name == "vclog")
491 enable = buf->lyxvc().inUse();
492 else if (name == "latexlog")
493 enable = IsFileReadable(buf->getLogName().second);
497 case LFUN_DIALOG_UPDATE: {
498 string const name = cmd.getArg(0);
500 enable = name == "prefs";
504 // this one is difficult to get right. As a half-baked
505 // solution, we consider only the first action of the sequence
506 case LFUN_SEQUENCE: {
507 // argument contains ';'-terminated commands
508 string const firstcmd = token(cmd.argument, ';', 0);
509 FuncRequest func(lyxaction.lookupFunc(firstcmd));
510 func.origin = cmd.origin;
511 flag = getStatus(func);
515 case LFUN_MENUNEWTMPLT:
516 case LFUN_WORDFINDFORWARD:
517 case LFUN_WORDFINDBACKWARD:
519 case LFUN_EXEC_COMMAND:
522 case LFUN_CLOSEBUFFER:
531 case LFUN_RECONFIGURE:
535 case LFUN_DROP_LAYOUTS_CHOICE:
536 case LFUN_MENU_OPEN_BY_NAME:
539 case LFUN_GOTOFILEROW:
540 case LFUN_GOTO_PARAGRAPH:
541 case LFUN_DIALOG_SHOW_NEW_INSET:
542 case LFUN_DIALOG_SHOW_NEXT_INSET:
543 case LFUN_DIALOG_HIDE:
544 case LFUN_DIALOG_DISCONNECT_INSET:
546 case LFUN_TOGGLECURSORFOLLOW:
550 case LFUN_KMAP_TOGGLE:
552 case LFUN_EXPORT_CUSTOM:
554 case LFUN_SAVEPREFERENCES:
555 case LFUN_SCREEN_FONT_UPDATE:
558 case LFUN_EXTERNAL_EDIT:
559 case LFUN_GRAPHICS_EDIT:
560 case LFUN_ALL_INSETS_TOGGLE:
561 case LFUN_LANGUAGE_BUFFER:
562 case LFUN_TEXTCLASS_APPLY:
563 case LFUN_TEXTCLASS_LOAD:
564 case LFUN_SAVE_AS_DEFAULT:
565 case LFUN_BUFFERPARAMS_APPLY:
566 case LFUN_LYXRC_APPLY:
567 case LFUN_NEXTBUFFER:
568 case LFUN_PREVIOUSBUFFER:
569 // these are handled in our dispatch()
574 if (!::getStatus(cur, cmd, flag))
575 flag = view()->getStatus(cmd);
581 // Can we use a readonly buffer?
582 if (buf && buf->isReadonly()
583 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
584 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
585 flag.message(N_("Document is read-only"));
589 // the default error message if we disable the command
590 if (!flag.enabled() && flag.message().empty())
591 flag.message(N_("Command disabled"));
599 bool ensureBufferClean(BufferView * bv)
601 Buffer & buf = *bv->buffer();
605 string const file = MakeDisplayPath(buf.fileName(), 30);
606 string text = bformat(_("The document %1$s has unsaved "
607 "changes.\n\nDo you want to save "
608 "the document?"), file);
609 int const ret = Alert::prompt(_("Save changed document?"),
610 text, 0, 1, _("&Save"),
614 bv->owner()->dispatch(FuncRequest(LFUN_MENUWRITE));
616 return buf.isClean();
620 void showPrintError(string const & name)
622 string str = bformat(_("Could not print the document %1$s.\n"
623 "Check that your printer is set up correctly."),
624 MakeDisplayPath(name, 50));
625 Alert::error(_("Print document failed"), str);
629 void loadTextclass(string const & name)
631 std::pair<bool, lyx::textclass_type> const tc_pair =
632 textclasslist.NumberOfClass(name);
634 if (!tc_pair.first) {
635 lyxerr << "Document class \"" << name
636 << "\" does not exist."
641 lyx::textclass_type const tc = tc_pair.second;
643 if (!textclasslist[tc].load()) {
644 string s = bformat(_("The document could not be converted\n"
645 "into the document class %1$s."),
646 textclasslist[tc].name());
647 Alert::error(_("Could not change class"), s);
652 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
657 void LyXFunc::dispatch(FuncRequest const & cmd)
659 BOOST_ASSERT(view());
660 string const argument = cmd.argument;
661 kb_action const action = cmd.action;
663 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl;
664 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
666 // we have not done anything wrong yet.
668 dispatch_buffer.erase();
672 FuncStatus const flag = getStatus(cmd);
673 if (!flag.enabled()) {
674 // We cannot use this function here
675 lyxerr[Debug::ACTION] << "LyXFunc::dispatch: "
676 << lyxaction.getActionName(action)
677 << " [" << action << "] is disabled at this location"
679 setErrorMessage(flag.message());
682 if (view()->available())
683 view()->hideCursor();
687 case LFUN_WORDFINDFORWARD:
688 case LFUN_WORDFINDBACKWARD: {
689 static string last_search;
690 string searched_string;
692 if (!argument.empty()) {
693 last_search = argument;
694 searched_string = argument;
696 searched_string = last_search;
699 if (searched_string.empty())
702 bool const fw = action == LFUN_WORDFINDFORWARD;
704 lyx::find::find2string(searched_string, true, false, fw);
705 lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data));
710 owner->message(keyseq.printOptions());
713 case LFUN_EXEC_COMMAND:
714 owner->getToolbars().display("minibuffer", true);
715 owner->focus_command_buffer();
720 meta_fake_bit = key_modifier::none;
721 if (view()->available())
722 // cancel any selection
723 dispatch(FuncRequest(LFUN_MARK_OFF));
724 setMessage(N_("Cancel"));
728 meta_fake_bit = key_modifier::alt;
729 setMessage(keyseq.print());
732 case LFUN_READ_ONLY_TOGGLE:
733 if (owner->buffer()->lyxvc().inUse())
734 owner->buffer()->lyxvc().toggleReadOnly();
736 owner->buffer()->setReadonly(
737 !owner->buffer()->isReadonly());
740 // --- Menus -----------------------------------------------
742 menuNew(argument, false);
745 case LFUN_MENUNEWTMPLT:
746 menuNew(argument, true);
749 case LFUN_CLOSEBUFFER:
754 if (!owner->buffer()->isUnnamed()) {
755 string const str = bformat(_("Saving document %1$s..."),
756 MakeDisplayPath(owner->buffer()->fileName()));
758 MenuWrite(owner->buffer());
759 owner->message(str + _(" done."));
761 WriteAs(owner->buffer());
765 WriteAs(owner->buffer(), argument);
768 case LFUN_MENURELOAD: {
769 string const file = MakeDisplayPath(view()->buffer()->fileName(), 20);
770 string text = bformat(_("Any changes will be lost. Are you sure "
771 "you want to revert to the saved version of the document %1$s?"), file);
772 int const ret = Alert::prompt(_("Revert to saved document?"),
773 text, 0, 1, _("&Revert"), _("&Cancel"));
781 Exporter::Export(owner->buffer(), argument, true);
782 view()->showErrorList(BufferFormat(*owner->buffer()));
786 Exporter::Preview(owner->buffer(), argument);
787 view()->showErrorList(BufferFormat(*owner->buffer()));
791 Exporter::Export(owner->buffer(), "program", true);
792 view()->showErrorList(_("Build"));
796 owner->buffer()->runChktex();
797 view()->showErrorList(_("ChkTeX"));
801 if (argument == "custom")
802 owner->getDialogs().show("sendto");
804 Exporter::Export(owner->buffer(), argument, false);
805 view()->showErrorList(BufferFormat(*owner->buffer()));
809 case LFUN_EXPORT_CUSTOM: {
811 string command = split(argument, format_name, ' ');
812 Format const * format = formats.getFormat(format_name);
814 lyxerr << "Format \"" << format_name
815 << "\" not recognized!"
820 Buffer * buffer = owner->buffer();
822 // The name of the file created by the conversion process
825 // Output to filename
826 if (format->name() == "lyx") {
827 string const latexname =
828 buffer->getLatexName(false);
829 filename = ChangeExtension(latexname,
830 format->extension());
831 filename = AddName(buffer->temppath(), filename);
833 if (!buffer->writeFile(filename))
837 Exporter::Export(buffer, format_name, true,
841 // Substitute $$FName for filename
842 if (!contains(command, "$$FName"))
843 command = "( " + command + " ) < $$FName";
844 command = subst(command, "$$FName", filename);
846 // Execute the command in the background
848 call.startscript(Systemcall::DontWait, command);
855 string command = split(split(argument, target, ' '),
859 || target_name.empty()
860 || command.empty()) {
861 lyxerr << "Unable to parse \""
862 << argument << '"' << std::endl;
865 if (target != "printer" && target != "file") {
866 lyxerr << "Unrecognized target \""
867 << target << '"' << std::endl;
871 Buffer * buffer = owner->buffer();
873 if (!Exporter::Export(buffer, "dvi", true)) {
874 showPrintError(buffer->fileName());
878 // Push directory path.
879 string const path = buffer->temppath();
882 // there are three cases here:
883 // 1. we print to a file
884 // 2. we print directly to a printer
885 // 3. we print using a spool command (print to file first)
888 string const dviname =
889 ChangeExtension(buffer->getLatexName(true),
892 if (target == "printer") {
893 if (!lyxrc.print_spool_command.empty()) {
894 // case 3: print using a spool
895 string const psname =
896 ChangeExtension(dviname,".ps");
897 command += lyxrc.print_to_file
900 + QuoteName(dviname);
903 lyxrc.print_spool_command +' ';
904 if (target_name != "default") {
905 command2 += lyxrc.print_spool_printerprefix
909 command2 += QuoteName(psname);
911 // If successful, then spool command
912 res = one.startscript(
917 res = one.startscript(
918 Systemcall::DontWait,
921 // case 2: print directly to a printer
922 res = one.startscript(
923 Systemcall::DontWait,
924 command + QuoteName(dviname));
928 // case 1: print to a file
929 command += lyxrc.print_to_file
930 + QuoteName(MakeAbsPath(target_name,
933 + QuoteName(dviname);
934 res = one.startscript(Systemcall::DontWait,
939 showPrintError(buffer->fileName());
952 InsetCommandParams p("tableofcontents");
953 string const data = InsetCommandMailer::params2string("toc", p);
954 owner->getDialogs().show("toc", data, 0);
962 case LFUN_RECONFIGURE:
966 case LFUN_HELP_OPEN: {
967 string const arg = argument;
969 setErrorMessage(N_("Missing argument"));
972 string const fname = i18nLibFileSearch("doc", arg, "lyx");
974 lyxerr << "LyX: unable to find documentation file `"
975 << arg << "'. Bad installation?" << endl;
978 owner->message(bformat(_("Opening help file %1$s..."),
979 MakeDisplayPath(fname)));
980 view()->loadLyXFile(fname, false);
984 // --- version control -------------------------------
985 case LFUN_VC_REGISTER:
986 if (!ensureBufferClean(view()))
988 if (!owner->buffer()->lyxvc().inUse()) {
989 owner->buffer()->lyxvc().registrer();
994 case LFUN_VC_CHECKIN:
995 if (!ensureBufferClean(view()))
997 if (owner->buffer()->lyxvc().inUse()
998 && !owner->buffer()->isReadonly()) {
999 owner->buffer()->lyxvc().checkIn();
1004 case LFUN_VC_CHECKOUT:
1005 if (!ensureBufferClean(view()))
1007 if (owner->buffer()->lyxvc().inUse()
1008 && owner->buffer()->isReadonly()) {
1009 owner->buffer()->lyxvc().checkOut();
1014 case LFUN_VC_REVERT:
1015 owner->buffer()->lyxvc().revert();
1020 owner->buffer()->lyxvc().undoLast();
1024 // --- buffers ----------------------------------------
1025 case LFUN_SWITCHBUFFER:
1026 view()->setBuffer(bufferlist.getBuffer(argument));
1029 case LFUN_NEXTBUFFER:
1030 view()->setBuffer(bufferlist.next(view()->buffer()));
1033 case LFUN_PREVIOUSBUFFER:
1034 view()->setBuffer(bufferlist.previous(view()->buffer()));
1038 NewFile(view(), argument);
1041 case LFUN_FILE_OPEN:
1045 case LFUN_DROP_LAYOUTS_CHOICE:
1046 owner->getToolbars().openLayoutList();
1049 case LFUN_MENU_OPEN_BY_NAME:
1050 owner->getMenubar().openByName(argument);
1053 // --- lyxserver commands ----------------------------
1055 setMessage(owner->buffer()->fileName());
1056 lyxerr[Debug::INFO] << "FNAME["
1057 << owner->buffer()->fileName()
1062 dispatch_buffer = keyseq.print();
1063 lyxserver->notifyClient(dispatch_buffer);
1066 case LFUN_GOTOFILEROW: {
1069 istringstream is(argument);
1070 is >> file_name >> row;
1071 if (prefixIs(file_name, package().temp_dir())) {
1072 // Needed by inverse dvi search. If it is a file
1073 // in tmpdir, call the apropriated function
1074 view()->setBuffer(bufferlist.getBufferFromTmp(file_name));
1076 // Must replace extension of the file to be .lyx
1077 // and get full path
1078 string const s = ChangeExtension(file_name, ".lyx");
1079 // Either change buffer or load the file
1080 if (bufferlist.exists(s)) {
1081 view()->setBuffer(bufferlist.getBuffer(s));
1083 view()->loadLyXFile(s);
1087 view()->setCursorFromRow(row);
1090 // see BufferView_pimpl::center()
1091 view()->updateScrollbar();
1095 case LFUN_GOTO_PARAGRAPH: {
1096 istringstream is(argument);
1099 ParIterator par = owner->buffer()->getParFromID(id);
1100 if (par == owner->buffer()->par_iterator_end()) {
1101 lyxerr[Debug::INFO] << "No matching paragraph found! ["
1102 << id << ']' << endl;
1105 lyxerr[Debug::INFO] << "Paragraph " << par->id()
1106 << " found." << endl;
1110 view()->setCursor(par, 0);
1112 view()->switchKeyMap();
1113 owner->view_state_changed();
1116 // see BufferView_pimpl::center()
1117 view()->updateScrollbar();
1121 case LFUN_DIALOG_SHOW: {
1122 string const name = cmd.getArg(0);
1123 string data = trim(cmd.argument.substr(name.size()));
1125 if (name == "character") {
1126 data = freefont2string();
1128 owner->getDialogs().show("character", data);
1131 else if (name == "latexlog") {
1132 pair<Buffer::LogType, string> const logfile =
1133 owner->buffer()->getLogName();
1134 switch (logfile.first) {
1135 case Buffer::latexlog:
1138 case Buffer::buildlog:
1142 data += logfile.second;
1143 owner->getDialogs().show("log", data);
1145 else if (name == "vclog") {
1146 string const data = "vc " +
1147 owner->buffer()->lyxvc().getLogFile();
1148 owner->getDialogs().show("log", data);
1151 owner->getDialogs().show(name, data);
1155 case LFUN_DIALOG_SHOW_NEW_INSET: {
1156 string const name = cmd.getArg(0);
1157 string data = trim(cmd.argument.substr(name.size()));
1158 if (name == "bibitem" ||
1160 name == "include" ||
1166 InsetCommandParams p(name);
1167 data = InsetCommandMailer::params2string(name, p);
1168 } else if (name == "box") {
1169 // \c data == "Boxed" || "Frameless" etc
1170 InsetBoxParams p(data);
1171 data = InsetBoxMailer::params2string(p);
1172 } else if (name == "branch") {
1173 InsetBranchParams p;
1174 data = InsetBranchMailer::params2string(p);
1175 } else if (name == "citation") {
1176 InsetCommandParams p("cite");
1177 data = InsetCommandMailer::params2string(name, p);
1178 } else if (name == "ert") {
1179 data = InsetERTMailer::params2string(InsetCollapsable::Open);
1180 } else if (name == "external") {
1181 InsetExternalParams p;
1182 Buffer const & buffer = *owner->buffer();
1183 data = InsetExternalMailer::params2string(p, buffer);
1184 } else if (name == "float") {
1186 data = InsetFloatMailer::params2string(p);
1187 } else if (name == "graphics") {
1188 InsetGraphicsParams p;
1189 Buffer const & buffer = *owner->buffer();
1190 data = InsetGraphicsMailer::params2string(p, buffer);
1191 } else if (name == "note") {
1193 data = InsetNoteMailer::params2string(p);
1194 } else if (name == "vspace") {
1196 data = InsetVSpaceMailer::params2string(space);
1197 } else if (name == "wrap") {
1199 data = InsetWrapMailer::params2string(p);
1201 owner->getDialogs().show(name, data, 0);
1205 case LFUN_DIALOG_SHOW_NEXT_INSET:
1208 case LFUN_DIALOG_UPDATE: {
1209 string const & name = argument;
1210 // Can only update a dialog connected to an existing inset
1211 InsetBase * inset = owner->getDialogs().getOpenInset(name);
1213 FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument);
1214 inset->dispatch(view()->cursor(), fr);
1215 } else if (name == "paragraph") {
1216 dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE));
1217 } else if (name == "prefs") {
1218 owner->getDialogs().update(name, string());
1223 case LFUN_DIALOG_HIDE:
1224 Dialogs::hide(argument, 0);
1227 case LFUN_DIALOG_DISCONNECT_INSET:
1228 owner->getDialogs().disconnect(argument);
1231 case LFUN_CHILDOPEN: {
1232 string const filename =
1233 MakeAbsPath(argument, owner->buffer()->filePath());
1234 setMessage(N_("Opening child document ") +
1235 MakeDisplayPath(filename) + "...");
1236 view()->savePosition(0);
1237 string const parentfilename = owner->buffer()->fileName();
1238 if (bufferlist.exists(filename))
1239 view()->setBuffer(bufferlist.getBuffer(filename));
1241 view()->loadLyXFile(filename);
1242 // Set the parent name of the child document.
1243 // This makes insertion of citations and references in the child work,
1244 // when the target is in the parent or another child document.
1245 owner->buffer()->setParentName(parentfilename);
1249 case LFUN_TOGGLECURSORFOLLOW:
1250 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1254 owner->getIntl().KeyMapOn(false);
1257 case LFUN_KMAP_PRIM:
1258 owner->getIntl().KeyMapPrim();
1262 owner->getIntl().KeyMapSec();
1265 case LFUN_KMAP_TOGGLE:
1266 owner->getIntl().ToggleKeyMap();
1272 string rest = split(argument, countstr, ' ');
1273 istringstream is(countstr);
1276 lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1277 for (int i = 0; i < count; ++i)
1278 dispatch(lyxaction.lookupFunc(rest));
1282 case LFUN_SEQUENCE: {
1283 // argument contains ';'-terminated commands
1284 string arg = argument;
1285 while (!arg.empty()) {
1287 arg = split(arg, first, ';');
1288 FuncRequest func(lyxaction.lookupFunc(first));
1289 func.origin = cmd.origin;
1295 case LFUN_SAVEPREFERENCES: {
1296 Path p(package().user_support());
1297 lyxrc.write("preferences", false);
1301 case LFUN_SCREEN_FONT_UPDATE:
1302 // handle the screen font changes.
1303 lyxrc.set_font_norm_type();
1304 lyx_gui::update_fonts();
1305 // All visible buffers will need resize
1309 case LFUN_SET_COLOR: {
1311 string const x11_name = split(argument, lyx_name, ' ');
1312 if (lyx_name.empty() || x11_name.empty()) {
1313 setErrorMessage(N_("Syntax: set-color <lyx_name>"
1318 bool const graphicsbg_changed =
1319 (lyx_name == lcolor.getLyXName(LColor::graphicsbg) &&
1320 x11_name != lcolor.getX11Name(LColor::graphicsbg));
1322 if (!lcolor.setColor(lyx_name, x11_name)) {
1324 bformat(_("Set-color \"%1$s\" failed "
1325 "- color is undefined or "
1326 "may not be redefined"), lyx_name));
1330 lyx_gui::update_color(lcolor.getFromLyXName(lyx_name));
1332 if (graphicsbg_changed) {
1333 #ifdef WITH_WARNINGS
1334 #warning FIXME!! The graphics cache no longer has a changeDisplay method.
1337 lyx::graphics::GCache::get().changeDisplay(true);
1344 owner->message(argument);
1347 case LFUN_TOOLTIPS_TOGGLE:
1348 owner->getDialogs().toggleTooltips();
1351 case LFUN_EXTERNAL_EDIT: {
1352 FuncRequest fr(action, argument);
1353 InsetExternal().dispatch(view()->cursor(), fr);
1357 case LFUN_GRAPHICS_EDIT: {
1358 FuncRequest fr(action, argument);
1359 InsetGraphics().dispatch(view()->cursor(), fr);
1363 case LFUN_ALL_INSETS_TOGGLE: {
1365 string const name = split(argument, action, ' ');
1366 InsetBase::Code const inset_code =
1367 InsetBase::translate(name);
1369 LCursor & cur = view()->cursor();
1370 FuncRequest fr(LFUN_INSET_TOGGLE, action);
1372 InsetBase & inset = owner->buffer()->inset();
1373 InsetIterator it = inset_iterator_begin(inset);
1374 InsetIterator const end = inset_iterator_end(inset);
1375 for (; it != end; ++it) {
1376 if (inset_code == InsetBase::NO_CODE
1377 || inset_code == it->lyxCode())
1378 it->dispatch(cur, fr);
1383 case LFUN_LANGUAGE_BUFFER: {
1384 Buffer & buffer = *owner->buffer();
1385 Language const * oldL = buffer.params().language;
1386 Language const * newL = languages.getLanguage(argument);
1387 if (!newL || oldL == newL)
1390 if (oldL->RightToLeft() == newL->RightToLeft()
1391 && !buffer.isMultiLingual())
1392 buffer.changeLanguage(oldL, newL);
1394 buffer.updateDocLang(newL);
1398 case LFUN_SAVE_AS_DEFAULT: {
1399 string const fname =
1400 AddName(AddPath(package().user_support(), "templates/"),
1402 Buffer defaults(fname);
1404 istringstream ss(argument);
1407 int const unknown_tokens = defaults.readHeader(lex);
1409 if (unknown_tokens != 0) {
1410 lyxerr << "Warning in LFUN_SAVE_AS_DEFAULT!\n"
1411 << unknown_tokens << " unknown token"
1412 << (unknown_tokens == 1 ? "" : "s")
1416 if (defaults.writeFile(defaults.fileName()))
1417 setMessage(_("Document defaults saved in ")
1418 + MakeDisplayPath(fname));
1420 setErrorMessage(_("Unable to save document defaults"));
1424 case LFUN_BUFFERPARAMS_APPLY: {
1425 biblio::CiteEngine const engine =
1426 owner->buffer()->params().cite_engine;
1428 istringstream ss(argument);
1431 int const unknown_tokens =
1432 owner->buffer()->readHeader(lex);
1434 if (unknown_tokens != 0) {
1435 lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n"
1436 << unknown_tokens << " unknown token"
1437 << (unknown_tokens == 1 ? "" : "s")
1440 if (engine == owner->buffer()->params().cite_engine)
1443 LCursor & cur = view()->cursor();
1444 FuncRequest fr(LFUN_INSET_REFRESH);
1446 InsetBase & inset = owner->buffer()->inset();
1447 InsetIterator it = inset_iterator_begin(inset);
1448 InsetIterator const end = inset_iterator_end(inset);
1449 for (; it != end; ++it)
1450 if (it->lyxCode() == InsetBase::CITE_CODE)
1451 it->dispatch(cur, fr);
1455 case LFUN_TEXTCLASS_APPLY: {
1456 Buffer * buffer = owner->buffer();
1458 lyx::textclass_type const old_class =
1459 buffer->params().textclass;
1461 loadTextclass(argument);
1463 std::pair<bool, lyx::textclass_type> const tc_pair =
1464 textclasslist.NumberOfClass(argument);
1469 lyx::textclass_type const new_class = tc_pair.second;
1470 if (old_class == new_class)
1474 owner->message(_("Converting document to new document class..."));
1476 lyx::cap::SwitchLayoutsBetweenClasses(
1477 old_class, new_class,
1478 buffer->paragraphs(), el);
1480 bufferErrors(*buffer, el);
1481 view()->showErrorList(_("Class switch"));
1485 case LFUN_TEXTCLASS_LOAD:
1486 loadTextclass(argument);
1489 case LFUN_LYXRC_APPLY: {
1490 LyXRC const lyxrc_orig = lyxrc;
1492 istringstream ss(argument);
1493 bool const success = lyxrc.read(ss) == 0;
1496 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1497 << "Unable to read lyxrc data"
1502 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1508 view()->cursor().dispatch(cmd);
1509 if (view()->cursor().result().dispatched())
1510 update |= view()->cursor().result().update();
1512 update |= view()->dispatch(cmd);
1517 if (view()->available()) {
1518 // Redraw screen unless explicitly told otherwise.
1519 // This also initializes the position cache for all insets
1520 // in (at least partially) visible top-level paragraphs.
1521 view()->update(true, update);
1523 // if we executed a mutating lfun, mark the buffer as dirty
1524 if (getStatus(cmd).enabled()
1525 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)
1526 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly))
1527 view()->buffer()->markDirty();
1530 if (view()->cursor().inTexted()) {
1531 view()->owner()->updateLayoutChoice();
1534 sendDispatchMessage(getMessage(), cmd);
1538 void LyXFunc::sendDispatchMessage(string const & msg, FuncRequest const & cmd)
1540 owner->updateMenubar();
1541 owner->updateToolbars();
1543 const bool verbose = (cmd.origin == FuncRequest::UI
1544 || cmd.origin == FuncRequest::COMMANDBUFFER);
1546 if (cmd.action == LFUN_SELFINSERT || !verbose) {
1547 lyxerr[Debug::ACTION] << "dispatch msg is " << msg << endl;
1549 owner->message(msg);
1553 string dispatch_msg = msg;
1554 if (!dispatch_msg.empty())
1555 dispatch_msg += ' ';
1557 string comname = lyxaction.getActionName(cmd.action);
1559 bool argsadded = false;
1561 if (!cmd.argument.empty()) {
1562 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1563 comname += ' ' + cmd.argument;
1568 string const shortcuts = toplevel_keymap->printbindings(cmd);
1570 if (!shortcuts.empty()) {
1571 comname += ": " + shortcuts;
1572 } else if (!argsadded && !cmd.argument.empty()) {
1573 comname += ' ' + cmd.argument;
1576 if (!comname.empty()) {
1577 comname = rtrim(comname);
1578 dispatch_msg += '(' + comname + ')';
1581 lyxerr[Debug::ACTION] << "verbose dispatch msg " << dispatch_msg << endl;
1582 if (!dispatch_msg.empty())
1583 owner->message(dispatch_msg);
1587 void LyXFunc::setupLocalKeymap()
1589 keyseq.stdmap = toplevel_keymap.get();
1590 keyseq.curmap = toplevel_keymap.get();
1591 cancel_meta_seq.stdmap = toplevel_keymap.get();
1592 cancel_meta_seq.curmap = toplevel_keymap.get();
1596 void LyXFunc::menuNew(string const & name, bool fromTemplate)
1598 string initpath = lyxrc.document_path;
1599 string filename(name);
1601 if (view()->available()) {
1602 string const trypath = owner->buffer()->filePath();
1603 // If directory is writeable, use this as default.
1604 if (IsDirWriteable(trypath))
1608 static int newfile_number;
1610 if (filename.empty()) {
1611 filename = AddName(lyxrc.document_path,
1612 "newfile" + convert<string>(++newfile_number) + ".lyx");
1613 FileInfo fi(filename);
1614 while (bufferlist.exists(filename) || fi.readable()) {
1616 filename = AddName(lyxrc.document_path,
1617 "newfile" + convert<string>(newfile_number) +
1619 fi.newFile(filename);
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 FileInfo const f(filename, true);
1700 // the user specifically chose this name. Believe them.
1701 view()->newFile(filename, "", true);
1705 owner->message(bformat(_("Opening document %1$s..."), disp_fn));
1708 if (view()->loadLyXFile(filename)) {
1709 str2 = bformat(_("Document %1$s opened."), disp_fn);
1711 str2 = bformat(_("Could not open document %1$s"), disp_fn);
1713 owner->message(str2);
1717 void LyXFunc::doImport(string const & argument)
1720 string filename = split(argument, format, ' ');
1722 lyxerr[Debug::INFO] << "LyXFunc::doImport: " << format
1723 << " file: " << filename << endl;
1725 // need user interaction
1726 if (filename.empty()) {
1727 string initpath = lyxrc.document_path;
1729 if (view()->available()) {
1730 string const trypath = owner->buffer()->filePath();
1731 // If directory is writeable, use this as default.
1732 if (IsDirWriteable(trypath))
1736 string const text = bformat(_("Select %1$s file to import"),
1737 formats.prettyName(format));
1739 FileDialog fileDlg(text,
1741 make_pair(string(_("Documents|#o#O")),
1742 string(lyxrc.document_path)),
1743 make_pair(string(_("Examples|#E#e")),
1744 string(AddPath(package().system_support(), "examples"))));
1746 string const filter = formats.prettyName(format)
1747 + " (*." + formats.extension(format) + ')';
1749 FileDialog::Result result =
1750 fileDlg.open(initpath,
1751 FileFilterList(filter),
1754 if (result.first == FileDialog::Later)
1757 filename = result.second;
1759 // check selected filename
1760 if (filename.empty())
1761 owner->message(_("Canceled."));
1764 if (filename.empty())
1767 // get absolute path of file
1768 filename = MakeAbsPath(filename);
1770 string const lyxfile = ChangeExtension(filename, ".lyx");
1772 // Check if the document already is open
1773 if (lyx_gui::use_gui && bufferlist.exists(lyxfile)) {
1774 if (!bufferlist.close(bufferlist.getBuffer(lyxfile), true)) {
1775 owner->message(_("Canceled."));
1780 // if the file exists already, and we didn't do
1781 // -i lyx thefile.lyx, warn
1782 if (FileInfo(lyxfile, true).exist() && filename != lyxfile) {
1783 string const file = MakeDisplayPath(lyxfile, 30);
1785 string text = bformat(_("The document %1$s already exists.\n\n"
1786 "Do you want to over-write that document?"), file);
1787 int const ret = Alert::prompt(_("Over-write document?"),
1788 text, 0, 1, _("&Over-write"), _("&Cancel"));
1791 owner->message(_("Canceled."));
1796 Importer::Import(owner, filename, format);
1800 void LyXFunc::closeBuffer()
1802 if (bufferlist.close(owner->buffer(), true) && !quitting) {
1803 if (bufferlist.empty()) {
1804 // need this otherwise SEGV may occur while
1805 // trying to set variables that don't exist
1806 // since there's no current buffer
1807 owner->getDialogs().hideBufferDependent();
1809 view()->setBuffer(bufferlist.first());
1815 // Each "owner" should have it's own message method. lyxview and
1816 // the minibuffer would use the minibuffer, but lyxserver would
1817 // send an ERROR signal to its client. Alejandro 970603
1818 // This function is bit problematic when it comes to NLS, to make the
1819 // lyx servers client be language indepenent we must not translate
1820 // strings sent to this func.
1821 void LyXFunc::setErrorMessage(string const & m) const
1823 dispatch_buffer = m;
1828 void LyXFunc::setMessage(string const & m) const
1830 dispatch_buffer = m;
1834 string const LyXFunc::viewStatusMessage()
1836 // When meta-fake key is pressed, show the key sequence so far + "M-".
1838 return keyseq.print() + "M-";
1840 // Else, when a non-complete key sequence is pressed,
1841 // show the available options.
1842 if (keyseq.length() > 0 && !keyseq.deleted())
1843 return keyseq.printOptions();
1845 if (!view()->available())
1846 return _("Welcome to LyX!");
1848 return view()->cursor().currentState();
1852 BufferView * LyXFunc::view() const
1854 BOOST_ASSERT(owner);
1855 return owner->view().get();
1859 bool LyXFunc::wasMetaKey() const
1861 return (meta_fake_bit != key_modifier::none);
1867 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1869 // Why the switch you might ask. It is a trick to ensure that all
1870 // the elements in the LyXRCTags enum is handled. As you can see
1871 // there are no breaks at all. So it is just a huge fall-through.
1872 // The nice thing is that we will get a warning from the compiler
1873 // if we forget an element.
1874 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1876 case LyXRC::RC_ACCEPT_COMPOUND:
1877 case LyXRC::RC_ALT_LANG:
1878 case LyXRC::RC_ASCIIROFF_COMMAND:
1879 case LyXRC::RC_ASCII_LINELEN:
1880 case LyXRC::RC_AUTOREGIONDELETE:
1881 case LyXRC::RC_AUTORESET_OPTIONS:
1882 case LyXRC::RC_AUTOSAVE:
1883 case LyXRC::RC_AUTO_NUMBER:
1884 case LyXRC::RC_BACKUPDIR_PATH:
1885 case LyXRC::RC_BIBTEX_COMMAND:
1886 case LyXRC::RC_BINDFILE:
1887 case LyXRC::RC_CHECKLASTFILES:
1888 case LyXRC::RC_CHKTEX_COMMAND:
1889 case LyXRC::RC_CONVERTER:
1890 case LyXRC::RC_COPIER:
1891 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1892 case LyXRC::RC_CUSTOM_EXPORT_COMMAND:
1893 case LyXRC::RC_CUSTOM_EXPORT_FORMAT:
1894 case LyXRC::RC_CYGWIN_PATH_FIX:
1895 if (lyxrc_orig.cygwin_path_fix != lyxrc_new.cygwin_path_fix) {
1896 namespace os = lyx::support::os;
1897 os::cygwin_path_fix(lyxrc_new.cygwin_path_fix);
1899 case LyXRC::RC_DATE_INSERT_FORMAT:
1900 case LyXRC::RC_DEFAULT_LANGUAGE:
1901 case LyXRC::RC_DEFAULT_PAPERSIZE:
1902 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1903 case LyXRC::RC_DISPLAY_GRAPHICS:
1904 case LyXRC::RC_DOCUMENTPATH:
1905 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1906 FileInfo fi(lyxrc_new.document_path);
1907 if (fi.isOK() && fi.isDir()) {
1908 using lyx::support::package;
1909 package().document_dir() = lyxrc.document_path;
1912 case LyXRC::RC_ESC_CHARS:
1913 case LyXRC::RC_FONT_ENCODING:
1914 case LyXRC::RC_FORMAT:
1915 case LyXRC::RC_INDEX_COMMAND:
1916 case LyXRC::RC_INPUT:
1917 case LyXRC::RC_KBMAP:
1918 case LyXRC::RC_KBMAP_PRIMARY:
1919 case LyXRC::RC_KBMAP_SECONDARY:
1920 case LyXRC::RC_LABEL_INIT_LENGTH:
1921 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1922 case LyXRC::RC_LANGUAGE_AUTO_END:
1923 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1924 case LyXRC::RC_LANGUAGE_COMMAND_END:
1925 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1926 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1927 case LyXRC::RC_LANGUAGE_PACKAGE:
1928 case LyXRC::RC_LANGUAGE_USE_BABEL:
1929 case LyXRC::RC_LASTFILES:
1930 case LyXRC::RC_MAKE_BACKUP:
1931 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1932 case LyXRC::RC_NUMLASTFILES:
1933 case LyXRC::RC_PATH_PREFIX:
1934 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1935 using lyx::support::prependEnvPath;
1936 prependEnvPath("PATH", lyxrc.path_prefix);
1938 case LyXRC::RC_PERS_DICT:
1939 case LyXRC::RC_POPUP_BOLD_FONT:
1940 case LyXRC::RC_POPUP_FONT_ENCODING:
1941 case LyXRC::RC_POPUP_NORMAL_FONT:
1942 case LyXRC::RC_PREVIEW:
1943 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1944 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1945 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1946 case LyXRC::RC_PRINTCOPIESFLAG:
1947 case LyXRC::RC_PRINTER:
1948 case LyXRC::RC_PRINTEVENPAGEFLAG:
1949 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1950 case LyXRC::RC_PRINTFILEEXTENSION:
1951 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1952 case LyXRC::RC_PRINTODDPAGEFLAG:
1953 case LyXRC::RC_PRINTPAGERANGEFLAG:
1954 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1955 case LyXRC::RC_PRINTPAPERFLAG:
1956 case LyXRC::RC_PRINTREVERSEFLAG:
1957 case LyXRC::RC_PRINTSPOOL_COMMAND:
1958 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1959 case LyXRC::RC_PRINTTOFILE:
1960 case LyXRC::RC_PRINTTOPRINTER:
1961 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1962 case LyXRC::RC_PRINT_COMMAND:
1963 case LyXRC::RC_RTL_SUPPORT:
1964 case LyXRC::RC_SCREEN_DPI:
1965 case LyXRC::RC_SCREEN_FONT_ENCODING:
1966 case LyXRC::RC_SCREEN_FONT_ROMAN:
1967 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1968 case LyXRC::RC_SCREEN_FONT_SANS:
1969 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1970 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1971 case LyXRC::RC_SCREEN_FONT_SIZES:
1972 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1973 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1974 case LyXRC::RC_SCREEN_ZOOM:
1975 case LyXRC::RC_SERVERPIPE:
1976 case LyXRC::RC_SET_COLOR:
1977 case LyXRC::RC_SHOW_BANNER:
1978 case LyXRC::RC_SPELL_COMMAND:
1979 case LyXRC::RC_TEMPDIRPATH:
1980 case LyXRC::RC_TEMPLATEPATH:
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: