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 "LayoutFile.h"
25 #include "BranchList.h"
26 #include "buffer_funcs.h"
28 #include "BufferList.h"
29 #include "BufferParams.h"
30 #include "BufferView.h"
33 #include "Converter.h"
35 #include "CutAndPaste.h"
36 #include "DispatchResult.h"
38 #include "ErrorList.h"
40 #include "FuncRequest.h"
41 #include "FuncStatus.h"
42 #include "InsetIterator.h"
47 #include "LyXAction.h"
52 #include "Paragraph.h"
53 #include "ParagraphParameters.h"
54 #include "ParIterator.h"
58 #include "SpellChecker.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/InsetInclude.h"
68 #include "insets/InsetListings.h"
69 #include "insets/InsetNote.h"
70 #include "insets/InsetPhantom.h"
71 #include "insets/InsetSpace.h"
72 #include "insets/InsetTabular.h"
73 #include "insets/InsetVSpace.h"
74 #include "insets/InsetWrap.h"
76 #include "frontends/alert.h"
77 #include "frontends/Application.h"
78 #include "frontends/KeySymbol.h"
79 #include "frontends/LyXView.h"
80 #include "frontends/Selection.h"
82 #include "support/debug.h"
83 #include "support/environment.h"
84 #include "support/FileName.h"
85 #include "support/filetools.h"
86 #include "support/gettext.h"
87 #include "support/lstrings.h"
88 #include "support/Path.h"
89 #include "support/Package.h"
90 #include "support/Systemcall.h"
91 #include "support/convert.h"
92 #include "support/os.h"
98 using namespace lyx::support;
102 using frontend::LyXView;
104 namespace Alert = frontend::Alert;
109 // This function runs "configure" and then rereads lyx.defaults to
110 // reconfigure the automatic settings.
111 void reconfigure(LyXView * lv, string const & option)
113 // emit message signal.
115 lv->message(_("Running configure..."));
117 // Run configure in user lyx directory
118 PathChanger p(package().user_support());
119 string configure_command = package().configure_command();
120 configure_command += option;
122 int ret = one.startscript(Systemcall::Wait, configure_command);
124 // emit message signal.
126 lv->message(_("Reloading configuration..."));
127 lyxrc.read(libFileSearch(string(), "lyxrc.defaults"));
128 // Re-read packages.lst
129 LaTeXFeatures::getAvailable();
132 Alert::information(_("System reconfiguration failed"),
133 _("The system reconfiguration has failed.\n"
134 "Default textclass is used but LyX may "
135 "not be able to work properly.\n"
136 "Please reconfigure again if needed."));
139 Alert::information(_("System reconfigured"),
140 _("The system has been reconfigured.\n"
141 "You need to restart LyX to make use of any\n"
142 "updated document class specifications."));
146 bool getLocalStatus(Cursor cursor, FuncRequest const & cmd, FuncStatus & status)
148 // Try to fix cursor in case it is broken.
149 cursor.fixIfBroken();
151 // This is, of course, a mess. Better create a new doc iterator and use
152 // this in Inset::getStatus. This might require an additional
153 // BufferView * arg, though (which should be avoided)
154 //Cursor safe = *this;
156 for ( ; cursor.depth(); cursor.pop()) {
157 //lyxerr << "\nCursor::getStatus: cmd: " << cmd << endl << *this << endl;
158 LASSERT(cursor.idx() <= cursor.lastidx(), /**/);
159 LASSERT(cursor.pit() <= cursor.lastpit(), /**/);
160 LASSERT(cursor.pos() <= cursor.lastpos(), /**/);
162 // The inset's getStatus() will return 'true' if it made
163 // a definitive decision on whether it want to handle the
164 // request or not. The result of this decision is put into
165 // the 'status' parameter.
166 if (cursor.inset().getStatus(cursor, cmd, status)) {
175 /** Return the change status at cursor position, taking in account the
176 * status at each level of the document iterator (a table in a deleted
177 * footnote is deleted).
178 * When \param outer is true, the top slice is not looked at.
180 Change::Type lookupChangeType(DocIterator const & dit, bool outer = false)
182 size_t const depth = dit.depth() - (outer ? 1 : 0);
184 for (size_t i = 0 ; i < depth ; ++i) {
185 CursorSlice const & slice = dit[i];
186 if (!slice.inset().inMathed()
187 && slice.pos() < slice.paragraph().size()) {
188 Change::Type const ch = slice.paragraph().lookupChange(slice.pos()).type;
189 if (ch != Change::UNCHANGED)
193 return Change::UNCHANGED;
200 : lyx_view_(0), encoded_last_key(0), meta_fake_bit(NoModifier)
205 void LyXFunc::initKeySequences(KeyMap * kb)
207 keyseq = KeySequence(kb, kb);
208 cancel_meta_seq = KeySequence(kb, kb);
212 void LyXFunc::setLyXView(LyXView * lv)
214 if (lyx_view_ && lyx_view_->currentBufferView() && lyx_view_ != lv)
215 // save current selection to the selection buffer to allow
216 // middle-button paste in another window
217 cap::saveSelection(lyx_view_->currentBufferView()->cursor());
222 void LyXFunc::handleKeyFunc(FuncCode action)
224 char_type c = encoded_last_key;
229 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
230 BufferView * bv = lyx_view_->currentBufferView();
231 bv->getIntl().getTransManager().deadkey(
232 c, get_accent(action).accent, bv->cursor().innerText(),
234 // Need to clear, in case the minibuffer calls these
237 // copied verbatim from do_accent_char
238 bv->cursor().resetAnchor();
239 bv->processUpdateFlags(Update::FitCursor);
242 //FIXME: bookmark handling is a frontend issue. This code should be transferred
243 // to GuiView and be GuiView and be window dependent.
244 void LyXFunc::gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer)
246 LASSERT(lyx_view_, /**/);
247 if (!theSession().bookmarks().isValid(idx))
249 BookmarksSection::Bookmark const & bm = theSession().bookmarks().bookmark(idx);
250 LASSERT(!bm.filename.empty(), /**/);
251 string const file = bm.filename.absFilename();
252 // if the file is not opened, open it.
253 if (!theBufferList().exists(bm.filename)) {
255 dispatch(FuncRequest(LFUN_FILE_OPEN, file));
259 // open may fail, so we need to test it again
260 if (!theBufferList().exists(bm.filename))
263 // bm can be changed when saving
264 BookmarksSection::Bookmark tmp = bm;
266 // Special case idx == 0 used for back-from-back jump navigation
268 dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
270 // if the current buffer is not that one, switch to it.
271 if (!lyx_view_->documentBufferView()
272 || lyx_view_->documentBufferView()->buffer().fileName() != tmp.filename) {
275 dispatch(FuncRequest(LFUN_BUFFER_SWITCH, file));
278 // moveToPosition try paragraph id first and then paragraph (pit, pos).
279 if (!lyx_view_->documentBufferView()->moveToPosition(
280 tmp.bottom_pit, tmp.bottom_pos, tmp.top_id, tmp.top_pos))
287 // Cursor jump succeeded!
288 Cursor const & cur = lyx_view_->documentBufferView()->cursor();
289 pit_type new_pit = cur.pit();
290 pos_type new_pos = cur.pos();
291 int new_id = cur.paragraph().id();
293 // if bottom_pit, bottom_pos or top_id has been changed, update bookmark
294 // see http://bugzilla.lyx.org/show_bug.cgi?id=3092
295 if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos
296 || bm.top_id != new_id) {
297 const_cast<BookmarksSection::Bookmark &>(bm).updatePos(
298 new_pit, new_pos, new_id);
303 void LyXFunc::processKeySym(KeySymbol const & keysym, KeyModifier state)
305 LYXERR(Debug::KEY, "KeySym is " << keysym.getSymbolName());
307 // Do nothing if we have nothing (JMarc)
308 if (!keysym.isOK()) {
309 LYXERR(Debug::KEY, "Empty kbd action (probably composing)");
310 lyx_view_->restartCursor();
314 if (keysym.isModifier()) {
315 LYXERR(Debug::KEY, "isModifier true");
317 lyx_view_->restartCursor();
321 //Encoding const * encoding = lyx_view_->documentBufferView()->cursor().getEncoding();
322 //encoded_last_key = keysym.getISOEncoded(encoding ? encoding->name() : "");
323 // FIXME: encoded_last_key shadows the member variable of the same
324 // name. Is that intended?
325 char_type encoded_last_key = keysym.getUCSEncoded();
327 // Do a one-deep top-level lookup for
328 // cancel and meta-fake keys. RVDK_PATCH_5
329 cancel_meta_seq.reset();
331 FuncRequest func = cancel_meta_seq.addkey(keysym, state);
332 LYXERR(Debug::KEY, "action first set to [" << func.action << ']');
334 // When not cancel or meta-fake, do the normal lookup.
335 // Note how the meta_fake Mod1 bit is OR-ed in and reset afterwards.
336 // Mostly, meta_fake_bit = NoModifier. RVDK_PATCH_5.
337 if ((func.action != LFUN_CANCEL) && (func.action != LFUN_META_PREFIX)) {
338 // remove Caps Lock and Mod2 as a modifiers
339 func = keyseq.addkey(keysym, (state | meta_fake_bit));
340 LYXERR(Debug::KEY, "action now set to [" << func.action << ']');
343 // Dont remove this unless you know what you are doing.
344 meta_fake_bit = NoModifier;
346 // Can this happen now ?
347 if (func.action == LFUN_NOACTION)
348 func = FuncRequest(LFUN_COMMAND_PREFIX);
350 LYXERR(Debug::KEY, " Key [action=" << func.action << "]["
351 << keyseq.print(KeySequence::Portable) << ']');
353 // already here we know if it any point in going further
354 // why not return already here if action == -1 and
355 // num_bytes == 0? (Lgb)
357 if (keyseq.length() > 1)
358 lyx_view_->message(keyseq.print(KeySequence::ForGui));
361 // Maybe user can only reach the key via holding down shift.
362 // Let's see. But only if shift is the only modifier
363 if (func.action == LFUN_UNKNOWN_ACTION && state == ShiftModifier) {
364 LYXERR(Debug::KEY, "Trying without shift");
365 func = keyseq.addkey(keysym, NoModifier);
366 LYXERR(Debug::KEY, "Action now " << func.action);
369 if (func.action == LFUN_UNKNOWN_ACTION) {
370 // Hmm, we didn't match any of the keysequences. See
371 // if it's normal insertable text not already covered
373 if (keysym.isText() && keyseq.length() == 1) {
374 LYXERR(Debug::KEY, "isText() is true, inserting.");
375 func = FuncRequest(LFUN_SELF_INSERT,
376 FuncRequest::KEYBOARD);
378 LYXERR(Debug::KEY, "Unknown, !isText() - giving up");
379 lyx_view_->message(_("Unknown function."));
380 lyx_view_->restartCursor();
385 if (func.action == LFUN_SELF_INSERT) {
386 if (encoded_last_key != 0) {
387 docstring const arg(1, encoded_last_key);
388 dispatch(FuncRequest(LFUN_SELF_INSERT, arg,
389 FuncRequest::KEYBOARD));
390 LYXERR(Debug::KEY, "SelfInsert arg[`" << to_utf8(arg) << "']");
400 FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const
402 //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl;
405 /* In LyX/Mac, when a dialog is open, the menus of the
406 application can still be accessed without giving focus to
407 the main window. In this case, we want to disable the menu
408 entries that are buffer or view-related.
410 If this code is moved somewhere else (like in
411 GuiView::getStatus), then several functions will not be
414 frontend::LyXView * lv = 0;
417 && (cmd.origin != FuncRequest::MENU || lyx_view_->hasFocus())) {
419 if (lyx_view_->documentBufferView())
420 buf = &lyx_view_->documentBufferView()->buffer();
423 if (cmd.action == LFUN_NOACTION) {
424 flag.message(from_utf8(N_("Nothing to do")));
425 flag.setEnabled(false);
429 switch (cmd.action) {
430 case LFUN_UNKNOWN_ACTION:
432 flag.setEnabled(false);
439 if (flag.unknown()) {
440 flag.message(from_utf8(N_("Unknown action")));
444 if (!flag.enabled()) {
445 if (flag.message().empty())
446 flag.message(from_utf8(N_("Command disabled")));
450 // Check whether we need a buffer
451 if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) {
453 flag.message(from_utf8(N_("Command not allowed with"
454 "out any document open")));
455 flag.setEnabled(false);
459 // I would really like to avoid having this switch and rather try to
460 // encode this in the function itself.
461 // -- And I'd rather let an inset decide which LFUNs it is willing
462 // to handle (Andre')
464 switch (cmd.action) {
466 case LFUN_BUFFER_TOGGLE_READ_ONLY:
467 flag.setOnOff(buf->isReadonly());
470 case LFUN_BUFFER_CHKTEX:
471 enable = buf->isLatex() && !lyxrc.chktex_command.empty();
474 case LFUN_BUILD_PROGRAM:
475 enable = buf->isExportable("program");
478 case LFUN_CITATION_INSERT: {
479 FuncRequest fr(LFUN_INSET_INSERT, "citation");
480 enable = getStatus(fr).enabled();
484 // This could be used for the no-GUI version. The GUI version is handled in
485 // LyXView::getStatus(). See above.
487 case LFUN_BUFFER_WRITE:
488 case LFUN_BUFFER_WRITE_AS: {
489 Buffer * b = theBufferList().getBuffer(FileName(cmd.getArg(0)));
490 enable = b && (b->isUnnamed() || !b->isClean());
495 case LFUN_BUFFER_WRITE_ALL: {
496 // We enable the command only if there are some modified buffers
497 Buffer * first = theBufferList().first();
502 // We cannot use a for loop as the buffer list is a cycle.
508 b = theBufferList().next(b);
509 } while (b != first);
513 case LFUN_BOOKMARK_GOTO: {
514 const unsigned int num = convert<unsigned int>(to_utf8(cmd.argument()));
515 enable = theSession().bookmarks().isValid(num);
519 case LFUN_BOOKMARK_CLEAR:
520 enable = theSession().bookmarks().hasValid();
523 // this one is difficult to get right. As a half-baked
524 // solution, we consider only the first action of the sequence
525 case LFUN_COMMAND_SEQUENCE: {
526 // argument contains ';'-terminated commands
527 string const firstcmd = token(to_utf8(cmd.argument()), ';', 0);
528 FuncRequest func(lyxaction.lookupFunc(firstcmd));
529 func.origin = cmd.origin;
530 flag = getStatus(func);
534 // we want to check if at least one of these is enabled
535 case LFUN_COMMAND_ALTERNATIVES: {
536 // argument contains ';'-terminated commands
537 string arg = to_utf8(cmd.argument());
538 while (!arg.empty()) {
540 arg = split(arg, first, ';');
541 FuncRequest func(lyxaction.lookupFunc(first));
542 func.origin = cmd.origin;
543 flag = getStatus(func);
544 // if this one is enabled, the whole thing is
553 string name = to_utf8(cmd.argument());
554 if (theTopLevelCmdDef().lock(name, func)) {
555 func.origin = cmd.origin;
556 flag = getStatus(func);
557 theTopLevelCmdDef().release(name);
559 // catch recursion or unknown command
560 // definition. all operations until the
561 // recursion or unknown command definition
562 // occurs are performed, so set the state to
569 case LFUN_MASTER_BUFFER_UPDATE:
570 case LFUN_MASTER_BUFFER_VIEW:
571 if (!buf->parent()) {
575 case LFUN_BUFFER_UPDATE:
576 case LFUN_BUFFER_VIEW: {
577 string format = to_utf8(cmd.argument());
578 if (cmd.argument().empty())
579 format = buf->getDefaultOutputFormat();
580 typedef vector<Format const *> Formats;
582 formats = buf->exportableFormats(true);
583 Formats::const_iterator fit = formats.begin();
584 Formats::const_iterator end = formats.end();
586 for (; fit != end ; ++fit) {
587 if ((*fit)->name() == format)
593 case LFUN_WORD_FINDADV:
594 case LFUN_COMMAND_PREFIX:
595 case LFUN_COMMAND_EXECUTE:
597 case LFUN_META_PREFIX:
598 case LFUN_BUFFER_CLOSE:
599 case LFUN_BUFFER_IMPORT:
600 case LFUN_BUFFER_AUTO_SAVE:
601 case LFUN_RECONFIGURE:
603 case LFUN_DROP_LAYOUTS_CHOICE:
605 case LFUN_SERVER_GET_FILENAME:
606 case LFUN_SERVER_NOTIFY:
607 case LFUN_SERVER_GOTO_FILE_ROW:
608 case LFUN_DIALOG_HIDE:
609 case LFUN_DIALOG_DISCONNECT_INSET:
610 case LFUN_BUFFER_CHILD_OPEN:
611 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
612 case LFUN_KEYMAP_OFF:
613 case LFUN_KEYMAP_PRIMARY:
614 case LFUN_KEYMAP_SECONDARY:
615 case LFUN_KEYMAP_TOGGLE:
617 case LFUN_BUFFER_EXPORT_CUSTOM:
618 case LFUN_PREFERENCES_SAVE:
620 case LFUN_INSET_EDIT:
621 case LFUN_BUFFER_LANGUAGE:
622 case LFUN_TEXTCLASS_APPLY:
623 case LFUN_TEXTCLASS_LOAD:
624 case LFUN_BUFFER_SAVE_AS_DEFAULT:
625 case LFUN_BUFFER_PARAMS_APPLY:
626 case LFUN_LAYOUT_MODULES_CLEAR:
627 case LFUN_LAYOUT_MODULE_ADD:
628 case LFUN_LAYOUT_RELOAD:
629 case LFUN_LYXRC_APPLY:
630 case LFUN_BUFFER_NEXT:
631 case LFUN_BUFFER_PREVIOUS:
632 // these are handled in our dispatch()
640 if (theApp()->getStatus(cmd, flag))
643 // Does the view know something?
648 if (lv->getStatus(cmd, flag))
651 BufferView * bv = lv->currentBufferView();
652 // If we do not have a BufferView, then other functions are disabled
657 // Is this a function that acts on inset at point?
658 Inset * inset = bv->cursor().nextInset();
659 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
660 && inset && inset->getStatus(bv->cursor(), cmd, flag))
663 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
665 // try the BufferView
666 decided = bv->getStatus(cmd, flag);
669 bv->buffer().getStatus(cmd, flag);
673 flag.setEnabled(false);
675 // Can we use a readonly buffer?
676 if (buf && buf->isReadonly()
677 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
678 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
679 flag.message(from_utf8(N_("Document is read-only")));
680 flag.setEnabled(false);
683 // Are we in a DELETED change-tracking region?
684 if (lyx_view_ && lyx_view_->documentBufferView()
685 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
687 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
688 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
689 flag.message(from_utf8(N_("This portion of the document is deleted.")));
690 flag.setEnabled(false);
693 // the default error message if we disable the command
694 if (!flag.enabled() && flag.message().empty())
695 flag.message(from_utf8(N_("Command disabled")));
703 bool loadLayoutFile(string const & name, string const & buf_path)
705 if (!LayoutFileList::get().haveClass(name)) {
706 lyxerr << "Document class \"" << name
707 << "\" does not exist."
712 LayoutFile & tc = LayoutFileList::get()[name];
713 if (!tc.load(buf_path)) {
714 docstring s = bformat(_("The document class %1$s "
715 "could not be loaded."), from_utf8(name));
716 Alert::error(_("Could not load class"), s);
723 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
728 void LyXFunc::dispatch(FuncRequest const & cmd)
730 string const argument = to_utf8(cmd.argument());
731 FuncCode const action = cmd.action;
733 LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
734 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
736 // we have not done anything wrong yet.
738 dispatch_buffer.erase();
740 // redraw the screen at the end (first of the two drawing steps).
741 //This is done unless explicitely requested otherwise
742 Update::flags updateFlags = Update::FitCursor;
744 FuncStatus const flag = getStatus(cmd);
745 if (!flag.enabled()) {
746 // We cannot use this function here
747 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
748 << lyxaction.getActionName(action)
749 << " [" << action << "] is disabled at this location");
750 setErrorMessage(flag.message());
752 lyx_view_->restartCursor();
755 if (lyx_view_ && lyx_view_->currentBufferView())
756 buffer = &lyx_view_->currentBufferView()->buffer();
759 case LFUN_COMMAND_PREFIX:
760 LASSERT(lyx_view_, /**/);
761 lyx_view_->message(keyseq.printOptions(true));
765 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
767 meta_fake_bit = NoModifier;
769 // cancel any selection
770 dispatch(FuncRequest(LFUN_MARK_OFF));
771 setMessage(from_ascii(N_("Cancel")));
774 case LFUN_META_PREFIX:
775 meta_fake_bit = AltModifier;
776 setMessage(keyseq.print(KeySequence::ForGui));
779 case LFUN_BUFFER_TOGGLE_READ_ONLY: {
780 LASSERT(lyx_view_ && lyx_view_->currentBufferView() && buffer, /**/);
781 if (buffer->lyxvc().inUse())
782 buffer->lyxvc().toggleReadOnly();
784 buffer->setReadonly(!buffer->isReadonly());
788 // --- Menus -----------------------------------------------
789 case LFUN_BUFFER_CLOSE:
790 lyx_view_->closeBuffer();
792 updateFlags = Update::None;
795 case LFUN_BUFFER_CLOSE_ALL:
796 lyx_view_->closeBufferAll();
798 updateFlags = Update::None;
801 case LFUN_BUFFER_UPDATE: {
802 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
803 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
804 string format = argument;
805 if (argument.empty())
806 format = doc_buffer.getDefaultOutputFormat();
807 doc_buffer.doExport(format, true);
811 case LFUN_BUFFER_VIEW: {
812 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
813 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
814 string format = argument;
815 if (argument.empty())
816 format = doc_buffer.getDefaultOutputFormat();
817 doc_buffer.preview(format);
821 case LFUN_MASTER_BUFFER_UPDATE: {
822 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
823 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
824 string format = argument;
825 if (argument.empty())
826 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
827 doc_buffer.masterBuffer()->doExport(format, true);
831 case LFUN_MASTER_BUFFER_VIEW: {
832 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
833 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
834 string format = argument;
835 if (argument.empty())
836 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
837 doc_buffer.masterBuffer()->preview(format);
841 case LFUN_BUILD_PROGRAM:
842 LASSERT(lyx_view_ && buffer, /**/);
843 buffer->doExport("program", true);
846 case LFUN_BUFFER_CHKTEX:
847 LASSERT(lyx_view_ && buffer, /**/);
851 case LFUN_BUFFER_EXPORT:
852 LASSERT(lyx_view_ && buffer, /**/);
853 if (argument == "custom")
854 dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
856 buffer->doExport(argument, false);
859 case LFUN_BUFFER_EXPORT_CUSTOM: {
860 LASSERT(lyx_view_ && buffer, /**/);
862 string command = split(argument, format_name, ' ');
863 Format const * format = formats.getFormat(format_name);
865 lyxerr << "Format \"" << format_name
866 << "\" not recognized!"
871 // The name of the file created by the conversion process
874 // Output to filename
875 if (format->name() == "lyx") {
876 string const latexname = buffer->latexName(false);
877 filename = changeExtension(latexname,
878 format->extension());
879 filename = addName(buffer->temppath(), filename);
881 if (!buffer->writeFile(FileName(filename)))
885 buffer->doExport(format_name, true, filename);
888 // Substitute $$FName for filename
889 if (!contains(command, "$$FName"))
890 command = "( " + command + " ) < $$FName";
891 command = subst(command, "$$FName", filename);
893 // Execute the command in the background
895 call.startscript(Systemcall::DontWait, command);
899 // FIXME: There is need for a command-line import.
901 case LFUN_BUFFER_IMPORT:
906 case LFUN_BUFFER_AUTO_SAVE:
910 case LFUN_RECONFIGURE:
911 // argument is any additional parameter to the configure.py command
912 reconfigure(lyx_view_, argument);
915 case LFUN_HELP_OPEN: {
917 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
918 string const arg = argument;
920 setErrorMessage(from_utf8(N_("Missing argument")));
923 FileName fname = i18nLibFileSearch("doc", arg, "lyx");
925 fname = i18nLibFileSearch("examples", arg, "lyx");
928 lyxerr << "LyX: unable to find documentation file `"
929 << arg << "'. Bad installation?" << endl;
932 lyx_view_->message(bformat(_("Opening help file %1$s..."),
933 makeDisplayPath(fname.absFilename())));
934 Buffer * buf = lyx_view_->loadDocument(fname, false);
937 lyx_view_->setBuffer(buf);
938 buf->errors("Parse");
940 updateFlags = Update::None;
944 // --- lyxserver commands ----------------------------
945 case LFUN_SERVER_GET_FILENAME:
946 LASSERT(lyx_view_ && buffer, /**/);
947 setMessage(from_utf8(buffer->absFileName()));
948 LYXERR(Debug::INFO, "FNAME["
949 << buffer->absFileName() << ']');
952 case LFUN_SERVER_NOTIFY:
953 dispatch_buffer = keyseq.print(KeySequence::Portable);
954 theServer().notifyClient(to_utf8(dispatch_buffer));
957 case LFUN_SERVER_GOTO_FILE_ROW: {
958 LASSERT(lyx_view_, /**/);
961 istringstream is(argument);
962 is >> file_name >> row;
963 file_name = os::internal_path(file_name);
966 string const abstmp = package().temp_dir().absFilename();
967 string const realtmp = package().temp_dir().realPath();
968 // We have to use os::path_prefix_is() here, instead of
969 // simply prefixIs(), because the file name comes from
970 // an external application and may need case adjustment.
971 if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
972 || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
973 // Needed by inverse dvi search. If it is a file
974 // in tmpdir, call the apropriated function.
975 // If tmpdir is a symlink, we may have the real
976 // path passed back, so we correct for that.
977 if (!prefixIs(file_name, abstmp))
978 file_name = subst(file_name, realtmp, abstmp);
979 buf = theBufferList().getBufferFromTmp(file_name);
981 // Must replace extension of the file to be .lyx
983 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
984 // Either change buffer or load the file
985 if (theBufferList().exists(s))
986 buf = theBufferList().getBuffer(s);
987 else if (s.exists()) {
988 buf = lyx_view_->loadDocument(s);
991 lyx_view_->message(bformat(
992 _("File does not exist: %1$s"),
993 makeDisplayPath(file_name)));
997 updateFlags = Update::None;
1001 buf->updateLabels();
1002 lyx_view_->setBuffer(buf);
1003 lyx_view_->documentBufferView()->setCursorFromRow(row);
1005 buf->errors("Parse");
1006 updateFlags = Update::FitCursor;
1011 case LFUN_DIALOG_SHOW_NEW_INSET: {
1012 LASSERT(lyx_view_, /**/);
1013 string const name = cmd.getArg(0);
1014 InsetCode code = insetCode(name);
1015 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1016 bool insetCodeOK = true;
1023 case NOMENCL_PRINT_CODE:
1026 case HYPERLINK_CODE: {
1027 InsetCommandParams p(code);
1028 data = InsetCommand::params2string(name, p);
1031 case INCLUDE_CODE: {
1032 // data is the include type: one of "include",
1033 // "input", "verbatiminput" or "verbatiminput*"
1035 // default type is requested
1037 InsetCommandParams p(INCLUDE_CODE, data);
1038 data = InsetCommand::params2string("include", p);
1042 // \c data == "Boxed" || "Frameless" etc
1043 InsetBoxParams p(data);
1044 data = InsetBox::params2string(p);
1048 InsetBranchParams p;
1049 data = InsetBranch::params2string(p);
1053 InsetCommandParams p(CITE_CODE);
1054 data = InsetCommand::params2string(name, p);
1058 data = InsetERT::params2string(InsetCollapsable::Open);
1061 case EXTERNAL_CODE: {
1062 InsetExternalParams p;
1063 data = InsetExternal::params2string(p, *buffer);
1068 data = InsetFloat::params2string(p);
1071 case LISTINGS_CODE: {
1072 InsetListingsParams p;
1073 data = InsetListings::params2string(p);
1076 case GRAPHICS_CODE: {
1077 InsetGraphicsParams p;
1078 data = InsetGraphics::params2string(p, *buffer);
1083 data = InsetNote::params2string(p);
1086 case PHANTOM_CODE: {
1087 InsetPhantomParams p;
1088 data = InsetPhantom::params2string(p);
1093 data = InsetSpace::params2string(p);
1098 data = InsetVSpace::params2string(space);
1103 data = InsetWrap::params2string(p);
1107 lyxerr << "Inset type '" << name <<
1108 "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << endl;
1109 insetCodeOK = false;
1111 } // end switch(code)
1113 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
1117 case LFUN_CITATION_INSERT: {
1118 LASSERT(lyx_view_, /**/);
1119 if (!argument.empty()) {
1120 // we can have one optional argument, delimited by '|'
1121 // citation-insert <key>|<text_before>
1122 // this should be enhanced to also support text_after
1123 // and citation style
1124 string arg = argument;
1126 if (contains(argument, "|")) {
1127 arg = token(argument, '|', 0);
1128 opt1 = token(argument, '|', 1);
1130 InsetCommandParams icp(CITE_CODE);
1131 icp["key"] = from_utf8(arg);
1133 icp["before"] = from_utf8(opt1);
1134 string icstr = InsetCommand::params2string("citation", icp);
1135 FuncRequest fr(LFUN_INSET_INSERT, icstr);
1138 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
1142 case LFUN_BUFFER_CHILD_OPEN: {
1143 LASSERT(lyx_view_ && buffer, /**/);
1144 FileName filename = makeAbsPath(argument, buffer->filePath());
1145 lyx_view_->documentBufferView()->saveBookmark(false);
1147 bool parsed = false;
1148 if (theBufferList().exists(filename)) {
1149 child = theBufferList().getBuffer(filename);
1151 setMessage(bformat(_("Opening child document %1$s..."),
1152 makeDisplayPath(filename.absFilename())));
1153 child = lyx_view_->loadDocument(filename, false);
1157 // Set the parent name of the child document.
1158 // This makes insertion of citations and references in the child work,
1159 // when the target is in the parent or another child document.
1160 child->setParent(buffer);
1161 child->masterBuffer()->updateLabels();
1162 lyx_view_->setBuffer(child);
1164 child->errors("Parse");
1167 // If a screen update is required (in case where auto_open is false),
1168 // setBuffer() would have taken care of it already. Otherwise we shall
1169 // reset the update flag because it can cause a circular problem.
1171 updateFlags = Update::None;
1175 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
1176 LASSERT(lyx_view_, /**/);
1177 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1180 case LFUN_KEYMAP_OFF:
1181 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1182 lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
1185 case LFUN_KEYMAP_PRIMARY:
1186 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1187 lyx_view_->currentBufferView()->getIntl().keyMapPrim();
1190 case LFUN_KEYMAP_SECONDARY:
1191 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1192 lyx_view_->currentBufferView()->getIntl().keyMapSec();
1195 case LFUN_KEYMAP_TOGGLE:
1196 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1197 lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
1203 string rest = split(argument, countstr, ' ');
1204 istringstream is(countstr);
1207 //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1208 for (int i = 0; i < count; ++i)
1209 dispatch(lyxaction.lookupFunc(rest));
1213 case LFUN_COMMAND_SEQUENCE: {
1214 // argument contains ';'-terminated commands
1215 string arg = argument;
1216 if (theBufferList().isLoaded(buffer))
1217 buffer->undo().beginUndoGroup();
1218 while (!arg.empty()) {
1220 arg = split(arg, first, ';');
1221 FuncRequest func(lyxaction.lookupFunc(first));
1222 func.origin = cmd.origin;
1225 if (theBufferList().isLoaded(buffer))
1226 buffer->undo().endUndoGroup();
1230 case LFUN_COMMAND_ALTERNATIVES: {
1231 // argument contains ';'-terminated commands
1232 string arg = argument;
1233 while (!arg.empty()) {
1235 arg = split(arg, first, ';');
1236 FuncRequest func(lyxaction.lookupFunc(first));
1237 func.origin = cmd.origin;
1238 FuncStatus stat = getStatus(func);
1239 if (stat.enabled()) {
1249 if (theTopLevelCmdDef().lock(argument, func)) {
1250 func.origin = cmd.origin;
1252 theTopLevelCmdDef().release(argument);
1254 if (func.action == LFUN_UNKNOWN_ACTION) {
1255 // unknown command definition
1256 lyxerr << "Warning: unknown command definition `"
1260 // recursion detected
1261 lyxerr << "Warning: Recursion in the command definition `"
1262 << argument << "' detected"
1269 case LFUN_PREFERENCES_SAVE: {
1270 lyxrc.write(makeAbsPath("preferences",
1271 package().user_support().absFilename()),
1277 LASSERT(lyx_view_, /**/);
1278 lyx_view_->message(from_utf8(argument));
1281 case LFUN_BUFFER_LANGUAGE: {
1282 LASSERT(lyx_view_, /**/);
1283 Language const * oldL = buffer->params().language;
1284 Language const * newL = languages.getLanguage(argument);
1285 if (!newL || oldL == newL)
1288 if (oldL->rightToLeft() == newL->rightToLeft()
1289 && !buffer->isMultiLingual())
1290 buffer->changeLanguage(oldL, newL);
1294 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1295 string const fname =
1296 addName(addPath(package().user_support().absFilename(), "templates/"),
1298 Buffer defaults(fname);
1300 istringstream ss(argument);
1303 int const unknown_tokens = defaults.readHeader(lex);
1305 if (unknown_tokens != 0) {
1306 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1307 << unknown_tokens << " unknown token"
1308 << (unknown_tokens == 1 ? "" : "s")
1312 if (defaults.writeFile(FileName(defaults.absFileName())))
1313 setMessage(bformat(_("Document defaults saved in %1$s"),
1314 makeDisplayPath(fname)));
1316 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1320 case LFUN_BUFFER_PARAMS_APPLY: {
1321 LASSERT(lyx_view_, /**/);
1323 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1324 Cursor & cur = lyx_view_->documentBufferView()->cursor();
1325 cur.recordUndoFullDocument();
1327 istringstream ss(argument);
1330 int const unknown_tokens = buffer->readHeader(lex);
1332 if (unknown_tokens != 0) {
1333 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1334 << unknown_tokens << " unknown token"
1335 << (unknown_tokens == 1 ? "" : "s")
1339 updateLayout(oldClass, buffer);
1341 updateFlags = Update::Force | Update::FitCursor;
1342 // We are most certainly here because of a change in the document
1343 // It is then better to make sure that all dialogs are in sync with
1344 // current document settings. LyXView::restartCursor() achieve this.
1345 lyx_view_->restartCursor();
1349 case LFUN_LAYOUT_MODULES_CLEAR: {
1350 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1351 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1352 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1353 buffer->params().clearLayoutModules();
1354 buffer->params().makeDocumentClass();
1355 updateLayout(oldClass, buffer);
1356 updateFlags = Update::Force | Update::FitCursor;
1360 case LFUN_LAYOUT_MODULE_ADD: {
1361 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1362 BufferParams const & params = buffer->params();
1363 if (!params.moduleCanBeAdded(argument)) {
1364 LYXERR0("Module `" << argument <<
1365 "' cannot be added due to failed requirements or "
1366 "conflicts with installed modules.");
1369 DocumentClass const * const oldClass = params.documentClassPtr();
1370 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1371 buffer->params().addLayoutModule(argument);
1372 buffer->params().makeDocumentClass();
1373 updateLayout(oldClass, buffer);
1374 updateFlags = Update::Force | Update::FitCursor;
1378 case LFUN_TEXTCLASS_APPLY: {
1379 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1381 if (!loadLayoutFile(argument, buffer->temppath()) &&
1382 !loadLayoutFile(argument, buffer->filePath()))
1385 LayoutFile const * old_layout = buffer->params().baseClass();
1386 LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1388 if (old_layout == new_layout)
1392 //Save the old, possibly modular, layout for use in conversion.
1393 DocumentClass const * const oldDocClass =
1394 buffer->params().documentClassPtr();
1395 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1396 buffer->params().setBaseClass(argument);
1397 buffer->params().makeDocumentClass();
1398 updateLayout(oldDocClass, buffer);
1399 updateFlags = Update::Force | Update::FitCursor;
1403 case LFUN_LAYOUT_RELOAD: {
1404 LASSERT(lyx_view_, /**/);
1405 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1406 LayoutFileIndex bc = buffer->params().baseClassID();
1407 LayoutFileList::get().reset(bc);
1408 buffer->params().setBaseClass(bc);
1409 buffer->params().makeDocumentClass();
1410 updateLayout(oldClass, buffer);
1411 updateFlags = Update::Force | Update::FitCursor;
1415 case LFUN_TEXTCLASS_LOAD:
1416 loadLayoutFile(argument, buffer->temppath()) ||
1417 loadLayoutFile(argument, buffer->filePath());
1420 case LFUN_LYXRC_APPLY: {
1421 // reset active key sequences, since the bindings
1422 // are updated (bug 6064)
1424 LyXRC const lyxrc_orig = lyxrc;
1426 istringstream ss(argument);
1427 bool const success = lyxrc.read(ss) == 0;
1430 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1431 << "Unable to read lyxrc data"
1436 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1440 theApp()->resetGui();
1442 /// We force the redraw in any case because there might be
1443 /// some screen font changes.
1444 /// FIXME: only the current view will be updated. the Gui
1445 /// class is able to furnish the list of views.
1446 updateFlags = Update::Force;
1450 case LFUN_BOOKMARK_GOTO:
1451 // go to bookmark, open unopened file and switch to buffer if necessary
1452 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1453 updateFlags = Update::FitCursor;
1456 case LFUN_BOOKMARK_CLEAR:
1457 theSession().bookmarks().clear();
1461 LASSERT(theApp(), /**/);
1462 // Let the frontend dispatch its own actions.
1463 if (theApp()->dispatch(cmd))
1464 // Nothing more to do.
1467 // Everything below is only for active lyx_view_
1471 // Start an undo group. This may be needed for
1472 // some stuff like inset-apply on labels.
1473 if (theBufferList().isLoaded(buffer))
1474 buffer->undo().beginUndoGroup();
1476 // Let the current LyXView dispatch its own actions.
1477 if (lyx_view_->dispatch(cmd)) {
1478 if (lyx_view_->currentBufferView()) {
1479 updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1480 if (theBufferList().isLoaded(buffer))
1481 buffer->undo().endUndoGroup();
1486 LASSERT(lyx_view_->currentBufferView(), /**/);
1488 // Let the current BufferView dispatch its own actions.
1489 if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1490 // The BufferView took care of its own updates if needed.
1491 updateFlags = Update::None;
1492 if (theBufferList().isLoaded(buffer))
1493 buffer->undo().endUndoGroup();
1497 // OK, so try the Buffer itself
1499 BufferView * bv = lyx_view_->currentBufferView();
1500 bv->buffer().dispatch(cmd, dr);
1501 if (dr.dispatched()) {
1502 updateFlags = dr.update();
1506 // Is this a function that acts on inset at point?
1507 Inset * inset = bv->cursor().nextInset();
1508 if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1510 bv->cursor().result().dispatched(true);
1511 bv->cursor().result().update(Update::FitCursor | Update::Force);
1512 FuncRequest tmpcmd = cmd;
1513 inset->dispatch(bv->cursor(), tmpcmd);
1514 if (bv->cursor().result().dispatched()) {
1515 updateFlags = bv->cursor().result().update();
1520 // Let the current Cursor dispatch its own actions.
1521 Cursor old = bv->cursor();
1522 bv->cursor().getPos(cursorPosBeforeDispatchX_,
1523 cursorPosBeforeDispatchY_);
1524 bv->cursor().dispatch(cmd);
1526 // notify insets we just left
1527 if (bv->cursor() != old) {
1529 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1531 bv->cursor().fixIfBroken();
1534 if (theBufferList().isLoaded(buffer))
1535 buffer->undo().endUndoGroup();
1537 // update completion. We do it here and not in
1538 // processKeySym to avoid another redraw just for a
1539 // changed inline completion
1540 if (cmd.origin == FuncRequest::KEYBOARD) {
1541 if (cmd.action == LFUN_SELF_INSERT
1542 || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1543 lyx_view_->updateCompletion(bv->cursor(), true, true);
1544 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1545 lyx_view_->updateCompletion(bv->cursor(), false, true);
1547 lyx_view_->updateCompletion(bv->cursor(), false, false);
1550 updateFlags = bv->cursor().result().update();
1553 // if we executed a mutating lfun, mark the buffer as dirty
1554 if (theBufferList().isLoaded(buffer) && flag.enabled()
1555 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1556 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1557 buffer->markDirty();
1559 if (lyx_view_ && lyx_view_->currentBufferView()) {
1560 // BufferView::update() updates the ViewMetricsInfo and
1561 // also initializes the position cache for all insets in
1562 // (at least partially) visible top-level paragraphs.
1563 // We will redraw the screen only if needed.
1564 lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1566 // Do we have a selection?
1567 theSelection().haveSelection(
1568 lyx_view_->currentBufferView()->cursor().selection());
1571 lyx_view_->restartCursor();
1575 // Some messages may already be translated, so we cannot use _()
1576 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1581 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1583 const bool verbose = (cmd.origin == FuncRequest::MENU
1584 || cmd.origin == FuncRequest::TOOLBAR
1585 || cmd.origin == FuncRequest::COMMANDBUFFER);
1587 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1588 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1590 lyx_view_->message(msg);
1594 docstring dispatch_msg = msg;
1595 if (!dispatch_msg.empty())
1596 dispatch_msg += ' ';
1598 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1600 bool argsadded = false;
1602 if (!cmd.argument().empty()) {
1603 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1604 comname += ' ' + cmd.argument();
1609 docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1611 if (!shortcuts.empty())
1612 comname += ": " + shortcuts;
1613 else if (!argsadded && !cmd.argument().empty())
1614 comname += ' ' + cmd.argument();
1616 if (!comname.empty()) {
1617 comname = rtrim(comname);
1618 dispatch_msg += '(' + rtrim(comname) + ')';
1621 LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1622 if (!dispatch_msg.empty())
1623 lyx_view_->message(dispatch_msg);
1627 // Each "lyx_view_" should have it's own message method. lyxview and
1628 // the minibuffer would use the minibuffer, but lyxserver would
1629 // send an ERROR signal to its client. Alejandro 970603
1630 // This function is bit problematic when it comes to NLS, to make the
1631 // lyx servers client be language indepenent we must not translate
1632 // strings sent to this func.
1633 void LyXFunc::setErrorMessage(docstring const & m) const
1635 dispatch_buffer = m;
1640 void LyXFunc::setMessage(docstring const & m) const
1642 dispatch_buffer = m;
1646 docstring LyXFunc::viewStatusMessage()
1648 // When meta-fake key is pressed, show the key sequence so far + "M-".
1650 return keyseq.print(KeySequence::ForGui) + "M-";
1652 // Else, when a non-complete key sequence is pressed,
1653 // show the available options.
1654 if (keyseq.length() > 0 && !keyseq.deleted())
1655 return keyseq.printOptions(true);
1657 LASSERT(lyx_view_, /**/);
1658 if (!lyx_view_->currentBufferView())
1659 return _("Welcome to LyX!");
1661 return lyx_view_->currentBufferView()->cursor().currentState();
1665 bool LyXFunc::wasMetaKey() const
1667 return (meta_fake_bit != NoModifier);
1671 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1673 lyx_view_->message(_("Converting document to new document class..."));
1675 StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1676 ErrorList & el = buf->errorList("Class Switch");
1677 cap::switchBetweenClasses(
1678 oldlayout, buf->params().documentClassPtr(),
1679 static_cast<InsetText &>(buf->inset()), el);
1681 lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1683 buf->errors("Class Switch");
1684 buf->updateLabels();
1690 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1692 // Why the switch you might ask. It is a trick to ensure that all
1693 // the elements in the LyXRCTags enum is handled. As you can see
1694 // there are no breaks at all. So it is just a huge fall-through.
1695 // The nice thing is that we will get a warning from the compiler
1696 // if we forget an element.
1697 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1699 case LyXRC::RC_ACCEPT_COMPOUND:
1700 case LyXRC::RC_ALT_LANG:
1701 case LyXRC::RC_PLAINTEXT_LINELEN:
1702 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1703 case LyXRC::RC_AUTOCORRECTION_MATH:
1704 case LyXRC::RC_AUTOREGIONDELETE:
1705 case LyXRC::RC_AUTORESET_OPTIONS:
1706 case LyXRC::RC_AUTOSAVE:
1707 case LyXRC::RC_AUTO_NUMBER:
1708 case LyXRC::RC_BACKUPDIR_PATH:
1709 case LyXRC::RC_BIBTEX_ALTERNATIVES:
1710 case LyXRC::RC_BIBTEX_COMMAND:
1711 case LyXRC::RC_BINDFILE:
1712 case LyXRC::RC_CHECKLASTFILES:
1713 case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1714 case LyXRC::RC_COMPLETION_INLINE_DELAY:
1715 case LyXRC::RC_COMPLETION_INLINE_DOTS:
1716 case LyXRC::RC_COMPLETION_INLINE_MATH:
1717 case LyXRC::RC_COMPLETION_INLINE_TEXT:
1718 case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1719 case LyXRC::RC_COMPLETION_POPUP_DELAY:
1720 case LyXRC::RC_COMPLETION_POPUP_MATH:
1721 case LyXRC::RC_COMPLETION_POPUP_TEXT:
1722 case LyXRC::RC_USELASTFILEPOS:
1723 case LyXRC::RC_LOADSESSION:
1724 case LyXRC::RC_CHKTEX_COMMAND:
1725 case LyXRC::RC_CONVERTER:
1726 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1727 case LyXRC::RC_COPIER:
1728 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1729 case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1730 case LyXRC::RC_DATE_INSERT_FORMAT:
1731 case LyXRC::RC_DEFAULT_LANGUAGE:
1732 case LyXRC::RC_GUI_LANGUAGE:
1733 case LyXRC::RC_DEFAULT_PAPERSIZE:
1734 case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1735 case LyXRC::RC_DEFFILE:
1736 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1737 case LyXRC::RC_DISPLAY_GRAPHICS:
1738 case LyXRC::RC_DOCUMENTPATH:
1739 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1740 FileName path(lyxrc_new.document_path);
1741 if (path.exists() && path.isDirectory())
1742 package().document_dir() = FileName(lyxrc.document_path);
1744 case LyXRC::RC_EDITOR_ALTERNATIVES:
1745 case LyXRC::RC_ESC_CHARS:
1746 case LyXRC::RC_EXAMPLEPATH:
1747 case LyXRC::RC_FONT_ENCODING:
1748 case LyXRC::RC_FORMAT:
1749 case LyXRC::RC_GROUP_LAYOUTS:
1750 case LyXRC::RC_HUNSPELLDIR_PATH:
1751 case LyXRC::RC_INDEX_ALTERNATIVES:
1752 case LyXRC::RC_INDEX_COMMAND:
1753 case LyXRC::RC_JBIBTEX_COMMAND:
1754 case LyXRC::RC_JINDEX_COMMAND:
1755 case LyXRC::RC_NOMENCL_COMMAND:
1756 case LyXRC::RC_INPUT:
1757 case LyXRC::RC_KBMAP:
1758 case LyXRC::RC_KBMAP_PRIMARY:
1759 case LyXRC::RC_KBMAP_SECONDARY:
1760 case LyXRC::RC_LABEL_INIT_LENGTH:
1761 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1762 case LyXRC::RC_LANGUAGE_AUTO_END:
1763 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1764 case LyXRC::RC_LANGUAGE_COMMAND_END:
1765 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1766 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1767 case LyXRC::RC_LANGUAGE_PACKAGE:
1768 case LyXRC::RC_LANGUAGE_USE_BABEL:
1769 case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1770 case LyXRC::RC_MACRO_EDIT_STYLE:
1771 case LyXRC::RC_MAKE_BACKUP:
1772 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1773 case LyXRC::RC_MOUSE_WHEEL_SPEED:
1774 case LyXRC::RC_NUMLASTFILES:
1775 case LyXRC::RC_PARAGRAPH_MARKERS:
1776 case LyXRC::RC_PATH_PREFIX:
1777 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1778 prependEnvPath("PATH", lyxrc.path_prefix);
1780 case LyXRC::RC_PERS_DICT:
1781 case LyXRC::RC_PREVIEW:
1782 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1783 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1784 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1785 case LyXRC::RC_PRINTCOPIESFLAG:
1786 case LyXRC::RC_PRINTER:
1787 case LyXRC::RC_PRINTEVENPAGEFLAG:
1788 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1789 case LyXRC::RC_PRINTFILEEXTENSION:
1790 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1791 case LyXRC::RC_PRINTODDPAGEFLAG:
1792 case LyXRC::RC_PRINTPAGERANGEFLAG:
1793 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1794 case LyXRC::RC_PRINTPAPERFLAG:
1795 case LyXRC::RC_PRINTREVERSEFLAG:
1796 case LyXRC::RC_PRINTSPOOL_COMMAND:
1797 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1798 case LyXRC::RC_PRINTTOFILE:
1799 case LyXRC::RC_PRINTTOPRINTER:
1800 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1801 case LyXRC::RC_PRINT_COMMAND:
1802 case LyXRC::RC_RTL_SUPPORT:
1803 case LyXRC::RC_SCREEN_DPI:
1804 case LyXRC::RC_SCREEN_FONT_ROMAN:
1805 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1806 case LyXRC::RC_SCREEN_FONT_SANS:
1807 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1808 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1809 case LyXRC::RC_SCREEN_FONT_SIZES:
1810 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1811 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1812 case LyXRC::RC_GEOMETRY_SESSION:
1813 case LyXRC::RC_SCREEN_ZOOM:
1814 case LyXRC::RC_SERVERPIPE:
1815 case LyXRC::RC_SET_COLOR:
1816 case LyXRC::RC_SHOW_BANNER:
1817 case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1818 case LyXRC::RC_SPELL_COMMAND:
1819 case LyXRC::RC_SPELLCHECKER:
1820 case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1821 case LyXRC::RC_SPLITINDEX_COMMAND:
1822 case LyXRC::RC_TEMPDIRPATH:
1823 case LyXRC::RC_TEMPLATEPATH:
1824 case LyXRC::RC_TEX_ALLOWS_SPACES:
1825 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1826 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1827 os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1829 case LyXRC::RC_THESAURUSDIRPATH:
1830 case LyXRC::RC_UIFILE:
1831 case LyXRC::RC_USER_EMAIL:
1832 case LyXRC::RC_USER_NAME:
1833 case LyXRC::RC_USETEMPDIR:
1834 case LyXRC::RC_USE_ALT_LANG:
1835 case LyXRC::RC_USE_CONVERTER_CACHE:
1836 case LyXRC::RC_USE_ESC_CHARS:
1837 case LyXRC::RC_USE_INP_ENC:
1838 case LyXRC::RC_USE_PERS_DICT:
1839 case LyXRC::RC_USE_TOOLTIP:
1840 case LyXRC::RC_USE_PIXMAP_CACHE:
1841 case LyXRC::RC_USE_SPELL_LIB:
1842 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1843 case LyXRC::RC_SORT_LAYOUTS:
1844 case LyXRC::RC_FULL_SCREEN_LIMIT:
1845 case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1846 case LyXRC::RC_FULL_SCREEN_MENUBAR:
1847 case LyXRC::RC_FULL_SCREEN_TABBAR:
1848 case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1849 case LyXRC::RC_FULL_SCREEN_WIDTH:
1850 case LyXRC::RC_VISUAL_CURSOR:
1851 case LyXRC::RC_VIEWER:
1852 case LyXRC::RC_VIEWER_ALTERNATIVES:
1853 case LyXRC::RC_LAST: