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_COMMAND_PREFIX:
594 case LFUN_COMMAND_EXECUTE:
596 case LFUN_META_PREFIX:
597 case LFUN_BUFFER_CLOSE:
598 case LFUN_BUFFER_IMPORT:
599 case LFUN_BUFFER_AUTO_SAVE:
600 case LFUN_RECONFIGURE:
602 case LFUN_DROP_LAYOUTS_CHOICE:
603 case LFUN_SERVER_GET_FILENAME:
604 case LFUN_SERVER_NOTIFY:
605 case LFUN_SERVER_GOTO_FILE_ROW:
606 case LFUN_BUFFER_CHILD_OPEN:
607 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
608 case LFUN_KEYMAP_OFF:
609 case LFUN_KEYMAP_PRIMARY:
610 case LFUN_KEYMAP_SECONDARY:
611 case LFUN_KEYMAP_TOGGLE:
613 case LFUN_BUFFER_EXPORT_CUSTOM:
614 case LFUN_PREFERENCES_SAVE:
616 case LFUN_INSET_EDIT:
617 case LFUN_BUFFER_LANGUAGE:
618 case LFUN_TEXTCLASS_APPLY:
619 case LFUN_TEXTCLASS_LOAD:
620 case LFUN_BUFFER_SAVE_AS_DEFAULT:
621 case LFUN_BUFFER_PARAMS_APPLY:
622 case LFUN_LAYOUT_MODULES_CLEAR:
623 case LFUN_LAYOUT_MODULE_ADD:
624 case LFUN_LAYOUT_RELOAD:
625 case LFUN_LYXRC_APPLY:
626 // these are handled in our dispatch()
634 if (theApp()->getStatus(cmd, flag))
637 // Does the view know something?
642 if (lv->getStatus(cmd, flag))
645 BufferView * bv = lv->currentBufferView();
646 // If we do not have a BufferView, then other functions are disabled
651 // Is this a function that acts on inset at point?
652 Inset * inset = bv->cursor().nextInset();
653 if (lyxaction.funcHasFlag(cmd.action, LyXAction::AtPoint)
654 && inset && inset->getStatus(bv->cursor(), cmd, flag))
657 bool decided = getLocalStatus(bv->cursor(), cmd, flag);
659 // try the BufferView
660 decided = bv->getStatus(cmd, flag);
663 bv->buffer().getStatus(cmd, flag);
667 flag.setEnabled(false);
669 // Can we use a readonly buffer?
670 if (buf && buf->isReadonly()
671 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
672 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
673 flag.message(from_utf8(N_("Document is read-only")));
674 flag.setEnabled(false);
677 // Are we in a DELETED change-tracking region?
678 if (lyx_view_ && lyx_view_->documentBufferView()
679 && (lookupChangeType(lyx_view_->documentBufferView()->cursor(), true)
681 && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)
682 && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) {
683 flag.message(from_utf8(N_("This portion of the document is deleted.")));
684 flag.setEnabled(false);
687 // the default error message if we disable the command
688 if (!flag.enabled() && flag.message().empty())
689 flag.message(from_utf8(N_("Command disabled")));
697 bool loadLayoutFile(string const & name, string const & buf_path)
699 if (!LayoutFileList::get().haveClass(name)) {
700 lyxerr << "Document class \"" << name
701 << "\" does not exist."
706 LayoutFile & tc = LayoutFileList::get()[name];
707 if (!tc.load(buf_path)) {
708 docstring s = bformat(_("The document class %1$s "
709 "could not be loaded."), from_utf8(name));
710 Alert::error(_("Could not load class"), s);
717 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new);
722 void LyXFunc::dispatch(FuncRequest const & cmd)
724 string const argument = to_utf8(cmd.argument());
725 FuncCode const action = cmd.action;
727 LYXERR(Debug::ACTION, "\nLyXFunc::dispatch: cmd: " << cmd);
728 //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl;
730 // we have not done anything wrong yet.
732 dispatch_buffer.erase();
734 // redraw the screen at the end (first of the two drawing steps).
735 //This is done unless explicitely requested otherwise
736 Update::flags updateFlags = Update::FitCursor;
738 FuncStatus const flag = getStatus(cmd);
739 if (!flag.enabled()) {
740 // We cannot use this function here
741 LYXERR(Debug::ACTION, "LyXFunc::dispatch: "
742 << lyxaction.getActionName(action)
743 << " [" << action << "] is disabled at this location");
744 setErrorMessage(flag.message());
746 lyx_view_->restartCursor();
749 if (lyx_view_ && lyx_view_->currentBufferView())
750 buffer = &lyx_view_->currentBufferView()->buffer();
753 case LFUN_COMMAND_PREFIX:
754 LASSERT(lyx_view_, /**/);
755 lyx_view_->message(keyseq.printOptions(true));
759 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
761 meta_fake_bit = NoModifier;
763 // cancel any selection
764 dispatch(FuncRequest(LFUN_MARK_OFF));
765 setMessage(from_ascii(N_("Cancel")));
768 case LFUN_META_PREFIX:
769 meta_fake_bit = AltModifier;
770 setMessage(keyseq.print(KeySequence::ForGui));
773 case LFUN_BUFFER_TOGGLE_READ_ONLY: {
774 LASSERT(lyx_view_ && lyx_view_->currentBufferView() && buffer, /**/);
775 if (buffer->lyxvc().inUse())
776 buffer->lyxvc().toggleReadOnly();
778 buffer->setReadonly(!buffer->isReadonly());
782 // --- Menus -----------------------------------------------
783 case LFUN_BUFFER_CLOSE:
784 lyx_view_->closeBuffer();
786 updateFlags = Update::None;
789 case LFUN_BUFFER_CLOSE_ALL:
790 lyx_view_->closeBufferAll();
792 updateFlags = Update::None;
795 case LFUN_BUFFER_UPDATE: {
796 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
797 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
798 string format = argument;
799 if (argument.empty())
800 format = doc_buffer.getDefaultOutputFormat();
801 doc_buffer.doExport(format, true);
805 case LFUN_BUFFER_VIEW: {
806 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
807 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
808 string format = argument;
809 if (argument.empty())
810 format = doc_buffer.getDefaultOutputFormat();
811 doc_buffer.preview(format);
815 case LFUN_MASTER_BUFFER_UPDATE: {
816 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
817 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
818 string format = argument;
819 if (argument.empty())
820 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
821 doc_buffer.masterBuffer()->doExport(format, true);
825 case LFUN_MASTER_BUFFER_VIEW: {
826 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
827 Buffer & doc_buffer = lyx_view_->documentBufferView()->buffer();
828 string format = argument;
829 if (argument.empty())
830 format = doc_buffer.masterBuffer()->getDefaultOutputFormat();
831 doc_buffer.masterBuffer()->preview(format);
835 case LFUN_BUILD_PROGRAM:
836 LASSERT(lyx_view_ && buffer, /**/);
837 buffer->doExport("program", true);
840 case LFUN_BUFFER_CHKTEX:
841 LASSERT(lyx_view_ && buffer, /**/);
845 case LFUN_BUFFER_EXPORT:
846 LASSERT(lyx_view_ && buffer, /**/);
847 if (argument == "custom")
848 dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
850 buffer->doExport(argument, false);
853 case LFUN_BUFFER_EXPORT_CUSTOM: {
854 LASSERT(lyx_view_ && buffer, /**/);
856 string command = split(argument, format_name, ' ');
857 Format const * format = formats.getFormat(format_name);
859 lyxerr << "Format \"" << format_name
860 << "\" not recognized!"
865 // The name of the file created by the conversion process
868 // Output to filename
869 if (format->name() == "lyx") {
870 string const latexname = buffer->latexName(false);
871 filename = changeExtension(latexname,
872 format->extension());
873 filename = addName(buffer->temppath(), filename);
875 if (!buffer->writeFile(FileName(filename)))
879 buffer->doExport(format_name, true, filename);
882 // Substitute $$FName for filename
883 if (!contains(command, "$$FName"))
884 command = "( " + command + " ) < $$FName";
885 command = subst(command, "$$FName", filename);
887 // Execute the command in the background
889 call.startscript(Systemcall::DontWait, command);
893 // FIXME: There is need for a command-line import.
895 case LFUN_BUFFER_IMPORT:
900 case LFUN_BUFFER_AUTO_SAVE:
904 case LFUN_RECONFIGURE:
905 // argument is any additional parameter to the configure.py command
906 reconfigure(lyx_view_, argument);
909 case LFUN_HELP_OPEN: {
911 theApp()->dispatch(FuncRequest(LFUN_WINDOW_NEW));
912 string const arg = argument;
914 setErrorMessage(from_utf8(N_("Missing argument")));
917 FileName fname = i18nLibFileSearch("doc", arg, "lyx");
919 fname = i18nLibFileSearch("examples", arg, "lyx");
922 lyxerr << "LyX: unable to find documentation file `"
923 << arg << "'. Bad installation?" << endl;
926 lyx_view_->message(bformat(_("Opening help file %1$s..."),
927 makeDisplayPath(fname.absFilename())));
928 Buffer * buf = lyx_view_->loadDocument(fname, false);
931 lyx_view_->setBuffer(buf);
932 buf->errors("Parse");
934 updateFlags = Update::None;
938 // --- lyxserver commands ----------------------------
939 case LFUN_SERVER_GET_FILENAME:
940 LASSERT(lyx_view_ && buffer, /**/);
941 setMessage(from_utf8(buffer->absFileName()));
942 LYXERR(Debug::INFO, "FNAME["
943 << buffer->absFileName() << ']');
946 case LFUN_SERVER_NOTIFY:
947 dispatch_buffer = keyseq.print(KeySequence::Portable);
948 theServer().notifyClient(to_utf8(dispatch_buffer));
951 case LFUN_SERVER_GOTO_FILE_ROW: {
952 LASSERT(lyx_view_, /**/);
955 istringstream is(argument);
956 is >> file_name >> row;
957 file_name = os::internal_path(file_name);
960 string const abstmp = package().temp_dir().absFilename();
961 string const realtmp = package().temp_dir().realPath();
962 // We have to use os::path_prefix_is() here, instead of
963 // simply prefixIs(), because the file name comes from
964 // an external application and may need case adjustment.
965 if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
966 || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
967 // Needed by inverse dvi search. If it is a file
968 // in tmpdir, call the apropriated function.
969 // If tmpdir is a symlink, we may have the real
970 // path passed back, so we correct for that.
971 if (!prefixIs(file_name, abstmp))
972 file_name = subst(file_name, realtmp, abstmp);
973 buf = theBufferList().getBufferFromTmp(file_name);
975 // Must replace extension of the file to be .lyx
977 FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
978 // Either change buffer or load the file
979 if (theBufferList().exists(s))
980 buf = theBufferList().getBuffer(s);
981 else if (s.exists()) {
982 buf = lyx_view_->loadDocument(s);
985 lyx_view_->message(bformat(
986 _("File does not exist: %1$s"),
987 makeDisplayPath(file_name)));
991 updateFlags = Update::None;
996 lyx_view_->setBuffer(buf);
997 lyx_view_->documentBufferView()->setCursorFromRow(row);
999 buf->errors("Parse");
1000 updateFlags = Update::FitCursor;
1005 case LFUN_DIALOG_SHOW_NEW_INSET: {
1006 LASSERT(lyx_view_, /**/);
1007 string const name = cmd.getArg(0);
1008 InsetCode code = insetCode(name);
1009 string data = trim(to_utf8(cmd.argument()).substr(name.size()));
1010 bool insetCodeOK = true;
1017 case NOMENCL_PRINT_CODE:
1020 case HYPERLINK_CODE: {
1021 InsetCommandParams p(code);
1022 data = InsetCommand::params2string(name, p);
1025 case INCLUDE_CODE: {
1026 // data is the include type: one of "include",
1027 // "input", "verbatiminput" or "verbatiminput*"
1029 // default type is requested
1031 InsetCommandParams p(INCLUDE_CODE, data);
1032 data = InsetCommand::params2string("include", p);
1036 // \c data == "Boxed" || "Frameless" etc
1037 InsetBoxParams p(data);
1038 data = InsetBox::params2string(p);
1042 InsetBranchParams p;
1043 data = InsetBranch::params2string(p);
1047 InsetCommandParams p(CITE_CODE);
1048 data = InsetCommand::params2string(name, p);
1052 data = InsetERT::params2string(InsetCollapsable::Open);
1055 case EXTERNAL_CODE: {
1056 InsetExternalParams p;
1057 data = InsetExternal::params2string(p, *buffer);
1062 data = InsetFloat::params2string(p);
1065 case LISTINGS_CODE: {
1066 InsetListingsParams p;
1067 data = InsetListings::params2string(p);
1070 case GRAPHICS_CODE: {
1071 InsetGraphicsParams p;
1072 data = InsetGraphics::params2string(p, *buffer);
1077 data = InsetNote::params2string(p);
1080 case PHANTOM_CODE: {
1081 InsetPhantomParams p;
1082 data = InsetPhantom::params2string(p);
1087 data = InsetSpace::params2string(p);
1092 data = InsetVSpace::params2string(space);
1097 data = InsetWrap::params2string(p);
1101 lyxerr << "Inset type '" << name <<
1102 "' not recognized in LFUN_DIALOG_SHOW_NEW_INSET" << endl;
1103 insetCodeOK = false;
1105 } // end switch(code)
1107 dispatch(FuncRequest(LFUN_DIALOG_SHOW, name + " " + data));
1111 case LFUN_CITATION_INSERT: {
1112 LASSERT(lyx_view_, /**/);
1113 if (!argument.empty()) {
1114 // we can have one optional argument, delimited by '|'
1115 // citation-insert <key>|<text_before>
1116 // this should be enhanced to also support text_after
1117 // and citation style
1118 string arg = argument;
1120 if (contains(argument, "|")) {
1121 arg = token(argument, '|', 0);
1122 opt1 = token(argument, '|', 1);
1124 InsetCommandParams icp(CITE_CODE);
1125 icp["key"] = from_utf8(arg);
1127 icp["before"] = from_utf8(opt1);
1128 string icstr = InsetCommand::params2string("citation", icp);
1129 FuncRequest fr(LFUN_INSET_INSERT, icstr);
1132 dispatch(FuncRequest(LFUN_DIALOG_SHOW_NEW_INSET, "citation"));
1136 case LFUN_BUFFER_CHILD_OPEN: {
1137 LASSERT(lyx_view_ && buffer, /**/);
1138 FileName filename = makeAbsPath(argument, buffer->filePath());
1139 lyx_view_->documentBufferView()->saveBookmark(false);
1141 bool parsed = false;
1142 if (theBufferList().exists(filename)) {
1143 child = theBufferList().getBuffer(filename);
1145 setMessage(bformat(_("Opening child document %1$s..."),
1146 makeDisplayPath(filename.absFilename())));
1147 child = lyx_view_->loadDocument(filename, false);
1151 // Set the parent name of the child document.
1152 // This makes insertion of citations and references in the child work,
1153 // when the target is in the parent or another child document.
1154 child->setParent(buffer);
1155 child->masterBuffer()->updateLabels();
1156 lyx_view_->setBuffer(child);
1158 child->errors("Parse");
1161 // If a screen update is required (in case where auto_open is false),
1162 // setBuffer() would have taken care of it already. Otherwise we shall
1163 // reset the update flag because it can cause a circular problem.
1165 updateFlags = Update::None;
1169 case LFUN_CURSOR_FOLLOWS_SCROLLBAR_TOGGLE:
1170 LASSERT(lyx_view_, /**/);
1171 lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar;
1174 case LFUN_KEYMAP_OFF:
1175 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1176 lyx_view_->currentBufferView()->getIntl().keyMapOn(false);
1179 case LFUN_KEYMAP_PRIMARY:
1180 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1181 lyx_view_->currentBufferView()->getIntl().keyMapPrim();
1184 case LFUN_KEYMAP_SECONDARY:
1185 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1186 lyx_view_->currentBufferView()->getIntl().keyMapSec();
1189 case LFUN_KEYMAP_TOGGLE:
1190 LASSERT(lyx_view_ && lyx_view_->currentBufferView(), /**/);
1191 lyx_view_->currentBufferView()->getIntl().toggleKeyMap();
1197 string rest = split(argument, countstr, ' ');
1198 istringstream is(countstr);
1201 //lyxerr << "repeat: count: " << count << " cmd: " << rest << endl;
1202 for (int i = 0; i < count; ++i)
1203 dispatch(lyxaction.lookupFunc(rest));
1207 case LFUN_COMMAND_SEQUENCE: {
1208 // argument contains ';'-terminated commands
1209 string arg = argument;
1210 if (theBufferList().isLoaded(buffer))
1211 buffer->undo().beginUndoGroup();
1212 while (!arg.empty()) {
1214 arg = split(arg, first, ';');
1215 FuncRequest func(lyxaction.lookupFunc(first));
1216 func.origin = cmd.origin;
1219 if (theBufferList().isLoaded(buffer))
1220 buffer->undo().endUndoGroup();
1224 case LFUN_COMMAND_ALTERNATIVES: {
1225 // argument contains ';'-terminated commands
1226 string arg = argument;
1227 while (!arg.empty()) {
1229 arg = split(arg, first, ';');
1230 FuncRequest func(lyxaction.lookupFunc(first));
1231 func.origin = cmd.origin;
1232 FuncStatus stat = getStatus(func);
1233 if (stat.enabled()) {
1243 if (theTopLevelCmdDef().lock(argument, func)) {
1244 func.origin = cmd.origin;
1246 theTopLevelCmdDef().release(argument);
1248 if (func.action == LFUN_UNKNOWN_ACTION) {
1249 // unknown command definition
1250 lyxerr << "Warning: unknown command definition `"
1254 // recursion detected
1255 lyxerr << "Warning: Recursion in the command definition `"
1256 << argument << "' detected"
1263 case LFUN_PREFERENCES_SAVE: {
1264 lyxrc.write(makeAbsPath("preferences",
1265 package().user_support().absFilename()),
1271 LASSERT(lyx_view_, /**/);
1272 lyx_view_->message(from_utf8(argument));
1275 case LFUN_BUFFER_LANGUAGE: {
1276 LASSERT(lyx_view_, /**/);
1277 Language const * oldL = buffer->params().language;
1278 Language const * newL = languages.getLanguage(argument);
1279 if (!newL || oldL == newL)
1282 if (oldL->rightToLeft() == newL->rightToLeft()
1283 && !buffer->isMultiLingual())
1284 buffer->changeLanguage(oldL, newL);
1288 case LFUN_BUFFER_SAVE_AS_DEFAULT: {
1289 string const fname =
1290 addName(addPath(package().user_support().absFilename(), "templates/"),
1292 Buffer defaults(fname);
1294 istringstream ss(argument);
1297 int const unknown_tokens = defaults.readHeader(lex);
1299 if (unknown_tokens != 0) {
1300 lyxerr << "Warning in LFUN_BUFFER_SAVE_AS_DEFAULT!\n"
1301 << unknown_tokens << " unknown token"
1302 << (unknown_tokens == 1 ? "" : "s")
1306 if (defaults.writeFile(FileName(defaults.absFileName())))
1307 setMessage(bformat(_("Document defaults saved in %1$s"),
1308 makeDisplayPath(fname)));
1310 setErrorMessage(from_ascii(N_("Unable to save document defaults")));
1314 case LFUN_BUFFER_PARAMS_APPLY: {
1315 LASSERT(lyx_view_, /**/);
1317 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1318 Cursor & cur = lyx_view_->documentBufferView()->cursor();
1319 cur.recordUndoFullDocument();
1321 istringstream ss(argument);
1324 int const unknown_tokens = buffer->readHeader(lex);
1326 if (unknown_tokens != 0) {
1327 lyxerr << "Warning in LFUN_BUFFER_PARAMS_APPLY!\n"
1328 << unknown_tokens << " unknown token"
1329 << (unknown_tokens == 1 ? "" : "s")
1333 updateLayout(oldClass, buffer);
1335 updateFlags = Update::Force | Update::FitCursor;
1336 // We are most certainly here because of a change in the document
1337 // It is then better to make sure that all dialogs are in sync with
1338 // current document settings. LyXView::restartCursor() achieve this.
1339 lyx_view_->restartCursor();
1343 case LFUN_LAYOUT_MODULES_CLEAR: {
1344 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1345 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1346 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1347 buffer->params().clearLayoutModules();
1348 buffer->params().makeDocumentClass();
1349 updateLayout(oldClass, buffer);
1350 updateFlags = Update::Force | Update::FitCursor;
1354 case LFUN_LAYOUT_MODULE_ADD: {
1355 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1356 BufferParams const & params = buffer->params();
1357 if (!params.moduleCanBeAdded(argument)) {
1358 LYXERR0("Module `" << argument <<
1359 "' cannot be added due to failed requirements or "
1360 "conflicts with installed modules.");
1363 DocumentClass const * const oldClass = params.documentClassPtr();
1364 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1365 buffer->params().addLayoutModule(argument);
1366 buffer->params().makeDocumentClass();
1367 updateLayout(oldClass, buffer);
1368 updateFlags = Update::Force | Update::FitCursor;
1372 case LFUN_TEXTCLASS_APPLY: {
1373 LASSERT(lyx_view_ && lyx_view_->documentBufferView(), /**/);
1375 if (!loadLayoutFile(argument, buffer->temppath()) &&
1376 !loadLayoutFile(argument, buffer->filePath()))
1379 LayoutFile const * old_layout = buffer->params().baseClass();
1380 LayoutFile const * new_layout = &(LayoutFileList::get()[argument]);
1382 if (old_layout == new_layout)
1386 //Save the old, possibly modular, layout for use in conversion.
1387 DocumentClass const * const oldDocClass =
1388 buffer->params().documentClassPtr();
1389 lyx_view_->documentBufferView()->cursor().recordUndoFullDocument();
1390 buffer->params().setBaseClass(argument);
1391 buffer->params().makeDocumentClass();
1392 updateLayout(oldDocClass, buffer);
1393 updateFlags = Update::Force | Update::FitCursor;
1397 case LFUN_LAYOUT_RELOAD: {
1398 LASSERT(lyx_view_, /**/);
1399 DocumentClass const * const oldClass = buffer->params().documentClassPtr();
1400 LayoutFileIndex bc = buffer->params().baseClassID();
1401 LayoutFileList::get().reset(bc);
1402 buffer->params().setBaseClass(bc);
1403 buffer->params().makeDocumentClass();
1404 updateLayout(oldClass, buffer);
1405 updateFlags = Update::Force | Update::FitCursor;
1409 case LFUN_TEXTCLASS_LOAD:
1410 loadLayoutFile(argument, buffer->temppath()) ||
1411 loadLayoutFile(argument, buffer->filePath());
1414 case LFUN_LYXRC_APPLY: {
1415 // reset active key sequences, since the bindings
1416 // are updated (bug 6064)
1418 LyXRC const lyxrc_orig = lyxrc;
1420 istringstream ss(argument);
1421 bool const success = lyxrc.read(ss) == 0;
1424 lyxerr << "Warning in LFUN_LYXRC_APPLY!\n"
1425 << "Unable to read lyxrc data"
1430 actOnUpdatedPrefs(lyxrc_orig, lyxrc);
1434 theApp()->resetGui();
1436 /// We force the redraw in any case because there might be
1437 /// some screen font changes.
1438 /// FIXME: only the current view will be updated. the Gui
1439 /// class is able to furnish the list of views.
1440 updateFlags = Update::Force;
1444 case LFUN_BOOKMARK_GOTO:
1445 // go to bookmark, open unopened file and switch to buffer if necessary
1446 gotoBookmark(convert<unsigned int>(to_utf8(cmd.argument())), true, true);
1447 updateFlags = Update::FitCursor;
1450 case LFUN_BOOKMARK_CLEAR:
1451 theSession().bookmarks().clear();
1455 LASSERT(theApp(), /**/);
1456 // Let the frontend dispatch its own actions.
1457 if (theApp()->dispatch(cmd))
1458 // Nothing more to do.
1461 // Everything below is only for active lyx_view_
1465 // Start an undo group. This may be needed for
1466 // some stuff like inset-apply on labels.
1467 if (theBufferList().isLoaded(buffer))
1468 buffer->undo().beginUndoGroup();
1470 // Let the current LyXView dispatch its own actions.
1471 if (lyx_view_->dispatch(cmd)) {
1472 if (lyx_view_->currentBufferView()) {
1473 updateFlags = lyx_view_->currentBufferView()->cursor().result().update();
1474 if (theBufferList().isLoaded(buffer))
1475 buffer->undo().endUndoGroup();
1480 LASSERT(lyx_view_->currentBufferView(), /**/);
1482 // Let the current BufferView dispatch its own actions.
1483 if (lyx_view_->currentBufferView()->dispatch(cmd)) {
1484 // The BufferView took care of its own updates if needed.
1485 updateFlags = Update::None;
1486 if (theBufferList().isLoaded(buffer))
1487 buffer->undo().endUndoGroup();
1491 // OK, so try the Buffer itself
1493 BufferView * bv = lyx_view_->currentBufferView();
1494 bv->buffer().dispatch(cmd, dr);
1495 if (dr.dispatched()) {
1496 updateFlags = dr.update();
1500 // Is this a function that acts on inset at point?
1501 Inset * inset = bv->cursor().nextInset();
1502 if (lyxaction.funcHasFlag(action, LyXAction::AtPoint)
1504 bv->cursor().result().dispatched(true);
1505 bv->cursor().result().update(Update::FitCursor | Update::Force);
1506 FuncRequest tmpcmd = cmd;
1507 inset->dispatch(bv->cursor(), tmpcmd);
1508 if (bv->cursor().result().dispatched()) {
1509 updateFlags = bv->cursor().result().update();
1514 // Let the current Cursor dispatch its own actions.
1515 Cursor old = bv->cursor();
1516 bv->cursor().getPos(cursorPosBeforeDispatchX_,
1517 cursorPosBeforeDispatchY_);
1518 bv->cursor().dispatch(cmd);
1520 // notify insets we just left
1521 if (bv->cursor() != old) {
1523 bool badcursor = notifyCursorLeavesOrEnters(old, bv->cursor());
1525 bv->cursor().fixIfBroken();
1528 if (theBufferList().isLoaded(buffer))
1529 buffer->undo().endUndoGroup();
1531 // update completion. We do it here and not in
1532 // processKeySym to avoid another redraw just for a
1533 // changed inline completion
1534 if (cmd.origin == FuncRequest::KEYBOARD) {
1535 if (cmd.action == LFUN_SELF_INSERT
1536 || (cmd.action == LFUN_ERT_INSERT && bv->cursor().inMathed()))
1537 lyx_view_->updateCompletion(bv->cursor(), true, true);
1538 else if (cmd.action == LFUN_CHAR_DELETE_BACKWARD)
1539 lyx_view_->updateCompletion(bv->cursor(), false, true);
1541 lyx_view_->updateCompletion(bv->cursor(), false, false);
1544 updateFlags = bv->cursor().result().update();
1547 // if we executed a mutating lfun, mark the buffer as dirty
1548 if (theBufferList().isLoaded(buffer) && flag.enabled()
1549 && !lyxaction.funcHasFlag(action, LyXAction::NoBuffer)
1550 && !lyxaction.funcHasFlag(action, LyXAction::ReadOnly))
1551 buffer->markDirty();
1553 if (lyx_view_ && lyx_view_->currentBufferView()) {
1554 // BufferView::update() updates the ViewMetricsInfo and
1555 // also initializes the position cache for all insets in
1556 // (at least partially) visible top-level paragraphs.
1557 // We will redraw the screen only if needed.
1558 lyx_view_->currentBufferView()->processUpdateFlags(updateFlags);
1560 // Do we have a selection?
1561 theSelection().haveSelection(
1562 lyx_view_->currentBufferView()->cursor().selection());
1565 lyx_view_->restartCursor();
1569 // Some messages may already be translated, so we cannot use _()
1570 sendDispatchMessage(translateIfPossible(getMessage()), cmd);
1575 void LyXFunc::sendDispatchMessage(docstring const & msg, FuncRequest const & cmd)
1577 const bool verbose = (cmd.origin == FuncRequest::MENU
1578 || cmd.origin == FuncRequest::TOOLBAR
1579 || cmd.origin == FuncRequest::COMMANDBUFFER);
1581 if (cmd.action == LFUN_SELF_INSERT || !verbose) {
1582 LYXERR(Debug::ACTION, "dispatch msg is " << to_utf8(msg));
1584 lyx_view_->message(msg);
1588 docstring dispatch_msg = msg;
1589 if (!dispatch_msg.empty())
1590 dispatch_msg += ' ';
1592 docstring comname = from_utf8(lyxaction.getActionName(cmd.action));
1594 bool argsadded = false;
1596 if (!cmd.argument().empty()) {
1597 if (cmd.action != LFUN_UNKNOWN_ACTION) {
1598 comname += ' ' + cmd.argument();
1603 docstring const shortcuts = theTopLevelKeymap().printBindings(cmd, KeySequence::ForGui);
1605 if (!shortcuts.empty())
1606 comname += ": " + shortcuts;
1607 else if (!argsadded && !cmd.argument().empty())
1608 comname += ' ' + cmd.argument();
1610 if (!comname.empty()) {
1611 comname = rtrim(comname);
1612 dispatch_msg += '(' + rtrim(comname) + ')';
1615 LYXERR(Debug::ACTION, "verbose dispatch msg " << to_utf8(dispatch_msg));
1616 if (!dispatch_msg.empty())
1617 lyx_view_->message(dispatch_msg);
1621 // Each "lyx_view_" should have it's own message method. lyxview and
1622 // the minibuffer would use the minibuffer, but lyxserver would
1623 // send an ERROR signal to its client. Alejandro 970603
1624 // This function is bit problematic when it comes to NLS, to make the
1625 // lyx servers client be language indepenent we must not translate
1626 // strings sent to this func.
1627 void LyXFunc::setErrorMessage(docstring const & m) const
1629 dispatch_buffer = m;
1634 void LyXFunc::setMessage(docstring const & m) const
1636 dispatch_buffer = m;
1640 docstring LyXFunc::viewStatusMessage()
1642 // When meta-fake key is pressed, show the key sequence so far + "M-".
1644 return keyseq.print(KeySequence::ForGui) + "M-";
1646 // Else, when a non-complete key sequence is pressed,
1647 // show the available options.
1648 if (keyseq.length() > 0 && !keyseq.deleted())
1649 return keyseq.printOptions(true);
1651 LASSERT(lyx_view_, /**/);
1652 if (!lyx_view_->currentBufferView())
1653 return _("Welcome to LyX!");
1655 return lyx_view_->currentBufferView()->cursor().currentState();
1659 bool LyXFunc::wasMetaKey() const
1661 return (meta_fake_bit != NoModifier);
1665 void LyXFunc::updateLayout(DocumentClass const * const oldlayout, Buffer * buf)
1667 lyx_view_->message(_("Converting document to new document class..."));
1669 StableDocIterator backcur(lyx_view_->currentBufferView()->cursor());
1670 ErrorList & el = buf->errorList("Class Switch");
1671 cap::switchBetweenClasses(
1672 oldlayout, buf->params().documentClassPtr(),
1673 static_cast<InsetText &>(buf->inset()), el);
1675 lyx_view_->currentBufferView()->setCursor(backcur.asDocIterator(buf));
1677 buf->errors("Class Switch");
1678 buf->updateLabels();
1684 void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new)
1686 // Why the switch you might ask. It is a trick to ensure that all
1687 // the elements in the LyXRCTags enum is handled. As you can see
1688 // there are no breaks at all. So it is just a huge fall-through.
1689 // The nice thing is that we will get a warning from the compiler
1690 // if we forget an element.
1691 LyXRC::LyXRCTags tag = LyXRC::RC_LAST;
1693 case LyXRC::RC_ACCEPT_COMPOUND:
1694 case LyXRC::RC_ALT_LANG:
1695 case LyXRC::RC_PLAINTEXT_LINELEN:
1696 case LyXRC::RC_PLAINTEXT_ROFF_COMMAND:
1697 case LyXRC::RC_AUTOCORRECTION_MATH:
1698 case LyXRC::RC_AUTOREGIONDELETE:
1699 case LyXRC::RC_AUTORESET_OPTIONS:
1700 case LyXRC::RC_AUTOSAVE:
1701 case LyXRC::RC_AUTO_NUMBER:
1702 case LyXRC::RC_BACKUPDIR_PATH:
1703 case LyXRC::RC_BIBTEX_ALTERNATIVES:
1704 case LyXRC::RC_BIBTEX_COMMAND:
1705 case LyXRC::RC_BINDFILE:
1706 case LyXRC::RC_CHECKLASTFILES:
1707 case LyXRC::RC_COMPLETION_CURSOR_TEXT:
1708 case LyXRC::RC_COMPLETION_INLINE_DELAY:
1709 case LyXRC::RC_COMPLETION_INLINE_DOTS:
1710 case LyXRC::RC_COMPLETION_INLINE_MATH:
1711 case LyXRC::RC_COMPLETION_INLINE_TEXT:
1712 case LyXRC::RC_COMPLETION_POPUP_AFTER_COMPLETE:
1713 case LyXRC::RC_COMPLETION_POPUP_DELAY:
1714 case LyXRC::RC_COMPLETION_POPUP_MATH:
1715 case LyXRC::RC_COMPLETION_POPUP_TEXT:
1716 case LyXRC::RC_USELASTFILEPOS:
1717 case LyXRC::RC_LOADSESSION:
1718 case LyXRC::RC_CHKTEX_COMMAND:
1719 case LyXRC::RC_CONVERTER:
1720 case LyXRC::RC_CONVERTER_CACHE_MAXAGE:
1721 case LyXRC::RC_COPIER:
1722 case LyXRC::RC_CURSOR_FOLLOWS_SCROLLBAR:
1723 case LyXRC::RC_SCROLL_BELOW_DOCUMENT:
1724 case LyXRC::RC_DATE_INSERT_FORMAT:
1725 case LyXRC::RC_DEFAULT_LANGUAGE:
1726 case LyXRC::RC_GUI_LANGUAGE:
1727 case LyXRC::RC_DEFAULT_PAPERSIZE:
1728 case LyXRC::RC_DEFAULT_VIEW_FORMAT:
1729 case LyXRC::RC_DEFFILE:
1730 case LyXRC::RC_DIALOGS_ICONIFY_WITH_MAIN:
1731 case LyXRC::RC_DISPLAY_GRAPHICS:
1732 case LyXRC::RC_DOCUMENTPATH:
1733 if (lyxrc_orig.document_path != lyxrc_new.document_path) {
1734 FileName path(lyxrc_new.document_path);
1735 if (path.exists() && path.isDirectory())
1736 package().document_dir() = FileName(lyxrc.document_path);
1738 case LyXRC::RC_EDITOR_ALTERNATIVES:
1739 case LyXRC::RC_ESC_CHARS:
1740 case LyXRC::RC_EXAMPLEPATH:
1741 case LyXRC::RC_FONT_ENCODING:
1742 case LyXRC::RC_FORMAT:
1743 case LyXRC::RC_GROUP_LAYOUTS:
1744 case LyXRC::RC_HUNSPELLDIR_PATH:
1745 case LyXRC::RC_INDEX_ALTERNATIVES:
1746 case LyXRC::RC_INDEX_COMMAND:
1747 case LyXRC::RC_JBIBTEX_COMMAND:
1748 case LyXRC::RC_JINDEX_COMMAND:
1749 case LyXRC::RC_NOMENCL_COMMAND:
1750 case LyXRC::RC_INPUT:
1751 case LyXRC::RC_KBMAP:
1752 case LyXRC::RC_KBMAP_PRIMARY:
1753 case LyXRC::RC_KBMAP_SECONDARY:
1754 case LyXRC::RC_LABEL_INIT_LENGTH:
1755 case LyXRC::RC_LANGUAGE_AUTO_BEGIN:
1756 case LyXRC::RC_LANGUAGE_AUTO_END:
1757 case LyXRC::RC_LANGUAGE_COMMAND_BEGIN:
1758 case LyXRC::RC_LANGUAGE_COMMAND_END:
1759 case LyXRC::RC_LANGUAGE_COMMAND_LOCAL:
1760 case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS:
1761 case LyXRC::RC_LANGUAGE_PACKAGE:
1762 case LyXRC::RC_LANGUAGE_USE_BABEL:
1763 case LyXRC::RC_MAC_LIKE_WORD_MOVEMENT:
1764 case LyXRC::RC_MACRO_EDIT_STYLE:
1765 case LyXRC::RC_MAKE_BACKUP:
1766 case LyXRC::RC_MARK_FOREIGN_LANGUAGE:
1767 case LyXRC::RC_MOUSE_WHEEL_SPEED:
1768 case LyXRC::RC_NUMLASTFILES:
1769 case LyXRC::RC_PARAGRAPH_MARKERS:
1770 case LyXRC::RC_PATH_PREFIX:
1771 if (lyxrc_orig.path_prefix != lyxrc_new.path_prefix) {
1772 prependEnvPath("PATH", lyxrc.path_prefix);
1774 case LyXRC::RC_PERS_DICT:
1775 case LyXRC::RC_PREVIEW:
1776 case LyXRC::RC_PREVIEW_HASHED_LABELS:
1777 case LyXRC::RC_PREVIEW_SCALE_FACTOR:
1778 case LyXRC::RC_PRINTCOLLCOPIESFLAG:
1779 case LyXRC::RC_PRINTCOPIESFLAG:
1780 case LyXRC::RC_PRINTER:
1781 case LyXRC::RC_PRINTEVENPAGEFLAG:
1782 case LyXRC::RC_PRINTEXSTRAOPTIONS:
1783 case LyXRC::RC_PRINTFILEEXTENSION:
1784 case LyXRC::RC_PRINTLANDSCAPEFLAG:
1785 case LyXRC::RC_PRINTODDPAGEFLAG:
1786 case LyXRC::RC_PRINTPAGERANGEFLAG:
1787 case LyXRC::RC_PRINTPAPERDIMENSIONFLAG:
1788 case LyXRC::RC_PRINTPAPERFLAG:
1789 case LyXRC::RC_PRINTREVERSEFLAG:
1790 case LyXRC::RC_PRINTSPOOL_COMMAND:
1791 case LyXRC::RC_PRINTSPOOL_PRINTERPREFIX:
1792 case LyXRC::RC_PRINTTOFILE:
1793 case LyXRC::RC_PRINTTOPRINTER:
1794 case LyXRC::RC_PRINT_ADAPTOUTPUT:
1795 case LyXRC::RC_PRINT_COMMAND:
1796 case LyXRC::RC_RTL_SUPPORT:
1797 case LyXRC::RC_SCREEN_DPI:
1798 case LyXRC::RC_SCREEN_FONT_ROMAN:
1799 case LyXRC::RC_SCREEN_FONT_ROMAN_FOUNDRY:
1800 case LyXRC::RC_SCREEN_FONT_SANS:
1801 case LyXRC::RC_SCREEN_FONT_SANS_FOUNDRY:
1802 case LyXRC::RC_SCREEN_FONT_SCALABLE:
1803 case LyXRC::RC_SCREEN_FONT_SIZES:
1804 case LyXRC::RC_SCREEN_FONT_TYPEWRITER:
1805 case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY:
1806 case LyXRC::RC_GEOMETRY_SESSION:
1807 case LyXRC::RC_SCREEN_ZOOM:
1808 case LyXRC::RC_SERVERPIPE:
1809 case LyXRC::RC_SET_COLOR:
1810 case LyXRC::RC_SHOW_BANNER:
1811 case LyXRC::RC_OPEN_BUFFERS_IN_TABS:
1812 case LyXRC::RC_SPELL_COMMAND:
1813 case LyXRC::RC_SPELLCHECKER:
1814 case LyXRC::RC_SPELLCHECK_CONTINUOUSLY:
1815 case LyXRC::RC_SPLITINDEX_COMMAND:
1816 case LyXRC::RC_TEMPDIRPATH:
1817 case LyXRC::RC_TEMPLATEPATH:
1818 case LyXRC::RC_TEX_ALLOWS_SPACES:
1819 case LyXRC::RC_TEX_EXPECTS_WINDOWS_PATHS:
1820 if (lyxrc_orig.windows_style_tex_paths != lyxrc_new.windows_style_tex_paths) {
1821 os::windows_style_tex_paths(lyxrc_new.windows_style_tex_paths);
1823 case LyXRC::RC_THESAURUSDIRPATH:
1824 case LyXRC::RC_UIFILE:
1825 case LyXRC::RC_USER_EMAIL:
1826 case LyXRC::RC_USER_NAME:
1827 case LyXRC::RC_USETEMPDIR:
1828 case LyXRC::RC_USE_ALT_LANG:
1829 case LyXRC::RC_USE_CONVERTER_CACHE:
1830 case LyXRC::RC_USE_ESC_CHARS:
1831 case LyXRC::RC_USE_INP_ENC:
1832 case LyXRC::RC_USE_PERS_DICT:
1833 case LyXRC::RC_USE_TOOLTIP:
1834 case LyXRC::RC_USE_PIXMAP_CACHE:
1835 case LyXRC::RC_USE_SPELL_LIB:
1836 case LyXRC::RC_VIEWDVI_PAPEROPTION:
1837 case LyXRC::RC_SORT_LAYOUTS:
1838 case LyXRC::RC_FULL_SCREEN_LIMIT:
1839 case LyXRC::RC_FULL_SCREEN_SCROLLBAR:
1840 case LyXRC::RC_FULL_SCREEN_MENUBAR:
1841 case LyXRC::RC_FULL_SCREEN_TABBAR:
1842 case LyXRC::RC_FULL_SCREEN_TOOLBARS:
1843 case LyXRC::RC_FULL_SCREEN_WIDTH:
1844 case LyXRC::RC_VISUAL_CURSOR:
1845 case LyXRC::RC_VIEWER:
1846 case LyXRC::RC_VIEWER_ALTERNATIVES:
1847 case LyXRC::RC_LAST: