X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxfunc.C;h=244a858dbca70488982b1fd23ae0c899a75d5db6;hb=de3c8e5b80effa940c92980032389c868f377d6b;hp=60756dfe8e29d36ec38621373036f732f460d490;hpb=59fefa0759d0330d7db8066f5a1197f4f1dfc5a8;p=lyx.git diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 60756dfe8e..244a858dbc 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -28,34 +28,46 @@ #include "bufferparams.h" #include "BufferView.h" #include "cursor.h" +#include "CutAndPaste.h" #include "debug.h" #include "dispatchresult.h" #include "encoding.h" +#include "errorlist.h" #include "exporter.h" #include "format.h" #include "funcrequest.h" #include "gettext.h" #include "importer.h" +#include "insetiterator.h" #include "intl.h" -#include "iterators.h" #include "kbmap.h" +#include "language.h" #include "LColor.h" #include "lyx_cb.h" #include "LyXAction.h" #include "lyxfind.h" +#include "lyxlex.h" #include "lyxrc.h" #include "lyxrow.h" #include "lyxserver.h" +#include "lyxtextclasslist.h" #include "lyxvc.h" #include "paragraph.h" +#include "pariterator.h" #include "ParagraphParameters.h" #include "undo.h" +#include "insets/insetbox.h" +#include "insets/insetbranch.h" #include "insets/insetcommand.h" +#include "insets/insetert.h" #include "insets/insetexternal.h" +#include "insets/insetfloat.h" +#include "insets/insetgraphics.h" +#include "insets/insetnote.h" #include "insets/insettabular.h" - -#include "mathed/math_cursor.h" +#include "insets/insetvspace.h" +#include "insets/insetwrap.h" #include "frontends/Alert.h" #include "frontends/Dialogs.h" @@ -69,22 +81,23 @@ #include "support/FileInfo.h" #include "support/filetools.h" #include "support/forkedcontr.h" +#include "support/globbing.h" +#include "support/lstrings.h" #include "support/path.h" #include "support/path_defines.h" +#include "support/systemcall.h" #include "support/tostr.h" #include "support/std_sstream.h" #include "support/os.h" -using bv_funcs::changeDepth; -using bv_funcs::currentState; -using bv_funcs::DEC_DEPTH; using bv_funcs::freefont2string; -using bv_funcs::INC_DEPTH; using lyx::support::AddName; using lyx::support::AddPath; using lyx::support::bformat; using lyx::support::ChangeExtension; +using lyx::support::contains; +using lyx::support::FileFilterList; using lyx::support::FileInfo; using lyx::support::FileSearch; using lyx::support::ForkedcallsController; @@ -95,11 +108,14 @@ using lyx::support::isStrInt; using lyx::support::MakeAbsPath; using lyx::support::MakeDisplayPath; using lyx::support::Path; +using lyx::support::QuoteName; using lyx::support::rtrim; using lyx::support::split; using lyx::support::strToInt; using lyx::support::strToUnsignedInt; +using lyx::support::subst; using lyx::support::system_lyxdir; +using lyx::support::Systemcall; using lyx::support::token; using lyx::support::trim; using lyx::support::user_lyxdir; @@ -108,6 +124,7 @@ using lyx::support::os::getTmpDir; using std::endl; using std::make_pair; +using std::pair; using std::string; using std::istringstream; @@ -121,11 +138,9 @@ extern boost::scoped_ptr toplevel_keymap; // (alkis) extern tex_accent_struct get_accent(kb_action action); -extern void ShowLatexLog(); - -LyXFunc::LyXFunc(LyXView * o) - : owner(o), +LyXFunc::LyXFunc(LyXView * lv) + : owner(lv), encoded_last_key(0), keyseq(toplevel_keymap.get(), toplevel_keymap.get()), cancel_meta_seq(toplevel_keymap.get(), toplevel_keymap.get()), @@ -134,16 +149,6 @@ LyXFunc::LyXFunc(LyXView * o) } -void LyXFunc::moveCursorUpdate() -{ - LyXText * lt = view()->text; - if (lt->selection.mark()) - lt->setSelection(); - view()->update(); - view()->switchKeyMap(); -} - - void LyXFunc::handleKeyFunc(kb_action action) { char c = encoded_last_key; @@ -158,21 +163,14 @@ void LyXFunc::handleKeyFunc(kb_action action) // actions keyseq.clear(); // copied verbatim from do_accent_char + view()->cursor().resetAnchor(); view()->update(); - view()->getLyXText()->selection.cursor = view()->getLyXText()->cursor; } -void LyXFunc::processKeySym(LyXKeySymPtr keysym, - key_modifier::state state) +void LyXFunc::processKeySym(LyXKeySymPtr keysym, key_modifier::state state) { - string argument; - - if (lyxerr.debugging(Debug::KEY)) { - lyxerr << "KeySym is " - << keysym->getSymbolName() - << endl; - } + lyxerr[Debug::KEY] << "KeySym is " << keysym->getSymbolName() << endl; // Do nothing if we have nothing (JMarc) if (!keysym->isOK()) { @@ -186,7 +184,7 @@ void LyXFunc::processKeySym(LyXKeySymPtr keysym, return; } - Encoding const * encoding = view()->getEncoding(); + Encoding const * encoding = view()->cursor().getEncoding(); encoded_last_key = keysym->getISOEncoded(encoding ? encoding->Name() : ""); @@ -256,13 +254,10 @@ void LyXFunc::processKeySym(LyXKeySymPtr keysym, if (func.action == LFUN_SELFINSERT) { if (encoded_last_key != 0) { - string arg; - arg += encoded_last_key; - - dispatch(FuncRequest(view(), LFUN_SELFINSERT, arg)); - - lyxerr[Debug::KEY] << "SelfInsert arg[`" - << argument << "']" << endl; + string arg(1, encoded_last_key); + dispatch(FuncRequest(LFUN_SELFINSERT, arg)); + lyxerr[Debug::KEY] + << "SelfInsert arg[`" << arg << "']" << endl; } } else { dispatch(func); @@ -270,27 +265,29 @@ void LyXFunc::processKeySym(LyXKeySymPtr keysym, } -FuncStatus LyXFunc::getStatus(FuncRequest const & ev) const +FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const { + //lyxerr << "LyXFunc::getStatus: cmd: " << cmd << endl; FuncStatus flag; Buffer * buf = owner->buffer(); + LCursor & cur = view()->cursor(); - if (ev.action == LFUN_NOACTION) { + if (cmd.action == LFUN_NOACTION) { setStatusMessage(N_("Nothing to do")); - flag.disabled(true); + flag.enabled(false); return flag; } - switch (ev.action) { + switch (cmd.action) { case LFUN_UNKNOWN_ACTION: #ifndef HAVE_LIBAIKSAURUS case LFUN_THESAURUS_ENTRY: #endif flag.unknown(true); - flag.disabled(true); + flag.enabled(false); break; default: - flag |= lyx_gui::getStatus(ev); + flag |= lyx_gui::getStatus(cmd); } if (flag.unknown()) { @@ -302,220 +299,110 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & ev) const setStatusMessage(N_("Command disabled")); // Check whether we need a buffer - if (!lyxaction.funcHasFlag(ev.action, LyXAction::NoBuffer)) { - // Yes we need a buffer, do we have one? - if (buf) { - // yes - // Can we use a readonly buffer? - if (buf->isReadonly() && - !lyxaction.funcHasFlag(ev.action, - LyXAction::ReadOnly)) { - // no - setStatusMessage(N_("Document is read-only")); - flag.disabled(true); - } - } else { - // no - setStatusMessage(N_("Command not allowed with" - "out any document open")); - flag.disabled(true); - return flag; - } + if (!lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) && !buf) { + // no, exit directly + setStatusMessage(N_("Command not allowed with" + "out any document open")); + flag.enabled(false); + return flag; } - UpdatableInset * tli = view()->cursor().innerInset(); - InsetTabular * tab = view()->cursor().innerInsetTabular(); - // I would really like to avoid having this switch and rather try to // encode this in the function itself. - bool disable = false; - switch (ev.action) { - case LFUN_EXPORT: - disable = ev.argument != "custom" - && !Exporter::IsExportable(*buf, ev.argument); + // -- And I'd rather let an inset decide which LFUNs it is willing + // to handle (Andre') + bool enable = true; + switch (cmd.action) { + case LFUN_TOOLTIPS_TOGGLE: + flag.setOnOff(owner->getDialogs().tooltipsEnabled()); + break; + + case LFUN_READ_ONLY_TOGGLE: + flag.setOnOff(buf->isReadonly()); break; - case LFUN_UNDO: - disable = buf->undostack().empty(); + + case LFUN_SWITCHBUFFER: + // toggle on the current buffer, but do not toggle off + // the other ones (is that a good idea?) + if (cmd.argument == buf->fileName()) + flag.setOnOff(true); break; - case LFUN_REDO: - disable = buf->redostack().empty(); + + case LFUN_EXPORT: + enable = cmd.argument == "custom" + || Exporter::IsExportable(*buf, cmd.argument); break; case LFUN_CUT: case LFUN_COPY: - if (tab && tab->hasSelection()) - disable = false; - else - disable = !mathcursor && !view()->getLyXText()->selection.set(); + enable = cur.selection(); break; case LFUN_RUNCHKTEX: - disable = !buf->isLatex() || lyxrc.chktex_command == "none"; + enable = buf->isLatex() && lyxrc.chktex_command != "none"; break; case LFUN_BUILDPROG: - disable = !Exporter::IsExportable(*buf, "program"); + enable = Exporter::IsExportable(*buf, "program"); break; case LFUN_LAYOUT_TABULAR: - disable = !view()->cursor().innerInsetTabular(); - break; - - case LFUN_DEPTH_MIN: - disable = !changeDepth(view(), view()->getLyXText(), DEC_DEPTH, true); - break; - - case LFUN_DEPTH_PLUS: - disable = !changeDepth(view(), view()->getLyXText(), INC_DEPTH, true); + enable = cur.innerInsetOfType(InsetBase::TABULAR_CODE); break; case LFUN_LAYOUT: - case LFUN_LAYOUT_PARAGRAPH: { - InsetOld * inset = view()->getLyXText()->cursorPar()->inInset(); - disable = inset && inset->forceDefaultParagraphs(inset); - break; - } - - case LFUN_INSET_OPTARG: - disable = (view()->getLyXText()->cursorPar()->layout()->optionalargs == 0); - break; - - case LFUN_TABULAR_FEATURE: -#if 0 - if (mathcursor) { - // FIXME: check temporarily disabled - // valign code - char align = mathcursor->valign(); - if (align == '\0') { - disable = true; - break; - } - if (ev.argument.empty()) { - flag.clear(); - break; - } - if (!contains("tcb", ev.argument[0])) { - disable = true; - break; - } - flag.setOnOff(ev.argument[0] == align); - } else { - disable = true; - - char align = mathcursor->halign(); - if (align == '\0') { - disable = true; - break; - } - if (ev.argument.empty()) { - flag.clear(); - break; - } - if (!contains("lcr", ev.argument[0])) { - disable = true; - break; - } - flag.setOnOff(ev.argument[0] == align); - - disable = !mathcursor->halign(); - break; - } - - if (tli) { - FuncStatus ret; - //ret.disabled(true); - InsetTabular * tab = view()->cursor().innerInsetTabular(); - if (tab) { - ret = tab->getStatus(ev.argument); - flag |= ret; - disable = false; - } else { - disable = true; - } - } else { - static InsetTabular inset(*buf, 1, 1); - disable = true; - FuncStatus ret = inset.getStatus(ev.argument); - if (ret.onoff(true) || ret.onoff(false)) - flag.setOnOff(false); - } -#endif + case LFUN_LAYOUT_PARAGRAPH: + enable = !cur.inset().forceDefaultParagraphs(&cur.inset()); break; case LFUN_VC_REGISTER: - disable = buf->lyxvc().inUse(); + enable = !buf->lyxvc().inUse(); break; case LFUN_VC_CHECKIN: - disable = !buf->lyxvc().inUse() || buf->isReadonly(); + enable = buf->lyxvc().inUse() && !buf->isReadonly(); break; case LFUN_VC_CHECKOUT: - disable = !buf->lyxvc().inUse() || !buf->isReadonly(); + enable = buf->lyxvc().inUse() && buf->isReadonly(); break; case LFUN_VC_REVERT: case LFUN_VC_UNDO: - disable = !buf->lyxvc().inUse(); + enable = buf->lyxvc().inUse(); break; case LFUN_MENURELOAD: - disable = buf->isUnnamed() || buf->isClean(); - break; - case LFUN_BOOKMARK_GOTO: - disable = !view()-> - isSavedPosition(strToUnsignedInt(ev.argument)); - break; - - case LFUN_MERGE_CHANGES: - case LFUN_ACCEPT_CHANGE: - case LFUN_REJECT_CHANGE: - case LFUN_ACCEPT_ALL_CHANGES: - case LFUN_REJECT_ALL_CHANGES: - disable = !buf->params().tracking_changes; + enable = !buf->isUnnamed() && !buf->isClean(); break; - case LFUN_INSET_TOGGLE: { - LyXText * lt = view()->getLyXText(); - disable = !(isEditableInset(lt->getInset()) - || (lt->inset_owner - && lt->inset_owner->owner() - && lt->inset_owner->owner()->isOpen())); - break; - } case LFUN_INSET_SETTINGS: { - disable = true; - UpdatableInset * inset = view()->cursor().innerInset(); - + enable = false; + if (!cur.size()) + break; + UpdatableInset * inset = cur.inset().asUpdatableInset(); + lyxerr << "inset: " << inset << endl; if (!inset) break; - // jump back to owner if an InsetText, so - // we get back to the InsetTabular or whatever - if (inset->lyxCode() == InsetOld::TEXT_CODE) - inset = inset->owner(); - InsetOld::Code code = inset->lyxCode(); switch (code) { case InsetOld::TABULAR_CODE: - disable = ev.argument != "tabular"; + enable = cmd.argument == "tabular"; break; case InsetOld::ERT_CODE: - disable = ev.argument != "ert"; + enable = cmd.argument == "ert"; break; case InsetOld::FLOAT_CODE: - disable = ev.argument != "float"; - break; - case InsetOld::MINIPAGE_CODE: - disable = ev.argument != "minipage"; + enable = cmd.argument == "float"; break; case InsetOld::WRAP_CODE: - disable = ev.argument != "wrap"; + enable = cmd.argument == "wrap"; break; case InsetOld::NOTE_CODE: - disable = ev.argument != "note"; + enable = cmd.argument == "note"; break; case InsetOld::BRANCH_CODE: - disable = ev.argument != "branch"; + enable = cmd.argument == "branch"; break; case InsetOld::BOX_CODE: - disable = ev.argument != "box"; + enable = cmd.argument == "box"; break; default: break; @@ -523,291 +410,109 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & ev) const break; } - case LFUN_MATH_MUTATE: - if (mathcursor) - //flag.setOnOff(mathcursor->formula()->hullType() == ev.argument); - flag.setOnOff(false); - else - disable = true; - break; - - // we just need to be in math mode to enable that - case LFUN_MATH_SIZE: - case LFUN_MATH_SPACE: - case LFUN_MATH_LIMITS: - case LFUN_MATH_NONUMBER: - case LFUN_MATH_NUMBER: - case LFUN_MATH_EXTERN: - disable = !mathcursor; - break; - case LFUN_DIALOG_SHOW: { - string const name = ev.getArg(0); - if (!buf) { - disable = !(name == "aboutlyx" || - name == "file" || - name == "forks" || - name == "preferences" || - name == "texinfo"); - break; - } - - if (name == "print") { - disable = !Exporter::IsExportable(*buf, "dvi") || - lyxrc.print_command == "none"; - } else if (name == "character") { - UpdatableInset * tli = view()->cursor().innerInset(); - disable = tli && tli->lyxCode() == InsetOld::ERT_CODE; - } else if (name == "vclog") { - disable = !buf->lyxvc().inUse(); - } else if (name == "latexlog") { - disable = !IsFileReadable(buf->getLogName().second); - } + string const name = cmd.getArg(0); + if (!buf) + enable = name == "aboutlyx" + || name == "file" + || name == "forks" + || name == "prefs" + || name == "texinfo"; + else if (name == "print") + enable = Exporter::IsExportable(*buf, "dvi") + && lyxrc.print_command != "none"; + else if (name == "character") + enable = cur.inset().lyxCode() != InsetOld::ERT_CODE; + else if (name == "vclog") + enable = buf->lyxvc().inUse(); + else if (name == "latexlog") + enable = IsFileReadable(buf->getLogName().second); break; } - default: + case LFUN_DIALOG_UPDATE: { + string const name = cmd.getArg(0); + if (!buf) + enable = name == "prefs"; break; } - // the functions which insert insets - InsetOld::Code code = InsetOld::NO_CODE; - switch (ev.action) { + case LFUN_MENUNEW: + case LFUN_MENUNEWTMPLT: + case LFUN_WORDFINDFORWARD: + case LFUN_WORDFINDBACKWARD: + case LFUN_PREFIX: + case LFUN_EXEC_COMMAND: + case LFUN_CANCEL: + case LFUN_META_FAKE: + case LFUN_CLOSEBUFFER: + case LFUN_MENUWRITE: + case LFUN_WRITEAS: + case LFUN_UPDATE: + case LFUN_PREVIEW: + case LFUN_IMPORT: + case LFUN_QUIT: + case LFUN_TOCVIEW: + case LFUN_AUTOSAVE: + case LFUN_RECONFIGURE: + case LFUN_HELP_OPEN: + case LFUN_FILE_NEW: + case LFUN_FILE_OPEN: + case LFUN_DROP_LAYOUTS_CHOICE: + case LFUN_MENU_OPEN_BY_NAME: + case LFUN_GETNAME: + case LFUN_NOTIFY: + case LFUN_GOTOFILEROW: + case LFUN_GOTO_PARAGRAPH: case LFUN_DIALOG_SHOW_NEW_INSET: - if (ev.argument == "bibitem") - code = InsetOld::BIBITEM_CODE; - else if (ev.argument == "bibtex") - code = InsetOld::BIBTEX_CODE; - else if (ev.argument == "citation") - code = InsetOld::CITE_CODE; - else if (ev.argument == "ert") - code = InsetOld::ERT_CODE; - else if (ev.argument == "external") - code = InsetOld::EXTERNAL_CODE; - else if (ev.argument == "float") - code = InsetOld::FLOAT_CODE; - else if (ev.argument == "graphics") - code = InsetOld::GRAPHICS_CODE; - else if (ev.argument == "include") - code = InsetOld::INCLUDE_CODE; - else if (ev.argument == "index") - code = InsetOld::INDEX_CODE; - else if (ev.argument == "label") - code = InsetOld::LABEL_CODE; - else if (ev.argument == "minipage") - code = InsetOld::MINIPAGE_CODE; - else if (ev.argument == "ref") - code = InsetOld::REF_CODE; - else if (ev.argument == "toc") - code = InsetOld::TOC_CODE; - else if (ev.argument == "url") - code = InsetOld::URL_CODE; - else if (ev.argument == "wrap") - code = InsetOld::WRAP_CODE; + case LFUN_DIALOG_SHOW_NEXT_INSET: + case LFUN_DIALOG_HIDE: + case LFUN_DIALOG_DISCONNECT_INSET: + case LFUN_CHILDOPEN: + case LFUN_TOGGLECURSORFOLLOW: + case LFUN_KMAP_OFF: + case LFUN_KMAP_PRIM: + case LFUN_KMAP_SEC: + case LFUN_KMAP_TOGGLE: + case LFUN_REPEAT: + case LFUN_EXPORT_CUSTOM: + case LFUN_PRINT: + case LFUN_SEQUENCE: + case LFUN_SAVEPREFERENCES: + case LFUN_SCREEN_FONT_UPDATE: + case LFUN_SET_COLOR: + case LFUN_MESSAGE: + case LFUN_EXTERNAL_EDIT: + case LFUN_GRAPHICS_EDIT: + case LFUN_ALL_INSETS_TOGGLE: + case LFUN_LANGUAGE_BUFFER: + case LFUN_TEXTCLASS_APPLY: + case LFUN_TEXTCLASS_LOAD: + case LFUN_SAVE_AS_DEFAULT: + case LFUN_BUFFERPARAMS_APPLY: + case LFUN_LYXRC_APPLY: + // these are handled in our dispatch() break; - case LFUN_INSET_ERT: - code = InsetOld::ERT_CODE; - break; - case LFUN_INSET_FOOTNOTE: - code = InsetOld::FOOT_CODE; - break; - case LFUN_TABULAR_INSERT: - code = InsetOld::TABULAR_CODE; - break; - case LFUN_INSET_MARGINAL: - code = InsetOld::MARGIN_CODE; - break; - case LFUN_INSET_MINIPAGE: - code = InsetOld::MINIPAGE_CODE; - break; - case LFUN_INSET_FLOAT: - case LFUN_INSET_WIDE_FLOAT: - code = InsetOld::FLOAT_CODE; - break; - case LFUN_INSET_WRAP: - code = InsetOld::WRAP_CODE; - break; - case LFUN_FLOAT_LIST: - code = InsetOld::FLOAT_LIST_CODE; - break; -#if 0 - case LFUN_INSET_LIST: - code = InsetOld::LIST_CODE; - break; - case LFUN_INSET_THEOREM: - code = InsetOld::THEOREM_CODE; - break; -#endif - case LFUN_INSET_CAPTION: - code = InsetOld::CAPTION_CODE; - break; - case LFUN_INSERT_NOTE: - code = InsetOld::NOTE_CODE; - break; - case LFUN_INSERT_CHARSTYLE: - code = InsetOld::CHARSTYLE_CODE; - if (buf->params().getLyXTextClass().charstyles().empty()) - disable = true; - break; - case LFUN_INSERT_BOX: - code = InsetOld::BOX_CODE; - break; - case LFUN_INSERT_BRANCH: - code = InsetOld::BRANCH_CODE; - if (buf->params().branchlist().empty()) - disable = true; - break; - case LFUN_INSERT_LABEL: - code = InsetOld::LABEL_CODE; - break; - case LFUN_INSET_OPTARG: - code = InsetOld::OPTARG_CODE; - break; - case LFUN_ENVIRONMENT_INSERT: - code = InsetOld::MINIPAGE_CODE; - break; - case LFUN_INDEX_INSERT: - code = InsetOld::INDEX_CODE; - break; - case LFUN_INDEX_PRINT: - code = InsetOld::INDEX_PRINT_CODE; - break; - case LFUN_TOC_INSERT: - code = InsetOld::TOC_CODE; - break; - case LFUN_HTMLURL: - case LFUN_URL: - code = InsetOld::URL_CODE; - break; - case LFUN_QUOTE: - // always allow this, since we will inset a raw quote - // if an inset is not allowed. - break; - case LFUN_HYPHENATION: - case LFUN_LIGATURE_BREAK: - case LFUN_HFILL: - case LFUN_MENU_SEPARATOR: - case LFUN_LDOTS: - case LFUN_END_OF_SENTENCE: - code = InsetOld::SPECIALCHAR_CODE; - break; - case LFUN_SPACE_INSERT: - // slight hack: we know this is allowed in math mode - if (!mathcursor) - code = InsetOld::SPACE_CODE; - break; - case LFUN_INSET_DIALOG_SHOW: { - InsetOld * inset = view()->getLyXText()->getInset(); - disable = !inset; - if (!disable) { - code = inset->lyxCode(); - if (!(code == InsetOld::INCLUDE_CODE - || code == InsetOld::BIBTEX_CODE - || code == InsetOld::FLOAT_LIST_CODE - || code == InsetOld::TOC_CODE)) - disable = true; - } - break; - } default: - break; - } - if (code != InsetOld::NO_CODE && tli && !tli->insetAllowed(code)) - disable = true; - - if (disable) - flag.disabled(true); - - // A few general toggles - switch (ev.action) { - case LFUN_TOOLTIPS_TOGGLE: - flag.setOnOff(owner->getDialogs().tooltipsEnabled()); - break; - case LFUN_READ_ONLY_TOGGLE: - flag.setOnOff(buf->isReadonly()); - break; - case LFUN_APPENDIX: - flag.setOnOff(view()->getLyXText()->cursorPar()->params().startOfAppendix()); - break; - case LFUN_SWITCHBUFFER: - // toggle on the current buffer, but do not toggle off - // the other ones (is that a good idea?) - if (ev.argument == buf->fileName()) - flag.setOnOff(true); - break; - case LFUN_TRACK_CHANGES: - flag.setOnOff(buf->params().tracking_changes); - break; - default: - break; + cur.getStatus(cmd, flag); + if (!flag.enabled()) + flag = view()->getStatus(cmd); } -#ifdef LOCK - // the font related toggles - if (!mathcursor) { - LyXFont const & font = view()->getLyXText()->real_current_font; - switch (ev.action) { - case LFUN_EMPH: - flag.setOnOff(font.emph() == LyXFont::ON); - break; - case LFUN_NOUN: - flag.setOnOff(font.noun() == LyXFont::ON); - break; - case LFUN_BOLD: - flag.setOnOff(font.series() == LyXFont::BOLD_SERIES); - break; - case LFUN_SANS: - flag.setOnOff(font.family() == LyXFont::SANS_FAMILY); - break; - case LFUN_ROMAN: - flag.setOnOff(font.family() == LyXFont::ROMAN_FAMILY); - break; - case LFUN_CODE: - flag.setOnOff(font.family() == LyXFont::TYPEWRITER_FAMILY); - break; - default: - break; - } - } else { - string tc = mathcursor->getLastCode(); - switch (ev.action) { - case LFUN_BOLD: - flag.setOnOff(tc == "mathbf"); - break; - case LFUN_SANS: - flag.setOnOff(tc == "mathsf"); - break; - case LFUN_EMPH: - flag.setOnOff(tc == "mathcal"); - break; - case LFUN_ROMAN: - flag.setOnOff(tc == "mathrm"); - break; - case LFUN_CODE: - flag.setOnOff(tc == "mathtt"); - break; - case LFUN_NOUN: - flag.setOnOff(tc == "mathbb"); - break; - case LFUN_DEFAULT: - flag.setOnOff(tc == "mathnormal"); - break; - default: - break; - } - } -#endif + if (!enable) + flag.enabled(false); - // this one is difficult to get right. As a half-baked - // solution, we consider only the first action of the sequence - if (ev.action == LFUN_SEQUENCE) { - // argument contains ';'-terminated commands -#warning LyXAction arguments not handled here. - flag = getStatus(FuncRequest(lyxaction.lookupFunc(token(ev.argument, ';', 0)))); + // Can we use a readonly buffer? + if (buf && buf->isReadonly() + && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly) + && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer)) { + setStatusMessage(N_("Document is read-only")); + flag.enabled(false); } + //lyxerr << "LyXFunc::getStatus: got: " << flag.enabled() << endl; return flag; } @@ -834,626 +539,869 @@ bool ensureBufferClean(BufferView * bv) return buf.isClean(); } + +void showPrintError(string const & name) +{ + string str = bformat(_("Could not print the document %1$s.\n" + "Check that your printer is set up correctly."), + MakeDisplayPath(name, 50)); + Alert::error(_("Print document failed"), str); +} + + +void loadTextclass(string const & name) +{ + std::pair const tc_pair = + textclasslist.NumberOfClass(name); + + if (!tc_pair.first) { + lyxerr << "Document class \"" << name + << "\" does not exist." + << std::endl; + return; + } + + lyx::textclass_type const tc = tc_pair.second; + + if (!textclasslist[tc].load()) { + string s = bformat(_("The document could not be converted\n" + "into the document class %1$s."), + textclasslist[tc].name()); + Alert::error(_("Could not change class"), s); + } +} + } //namespace anon -void LyXFunc::dispatch(FuncRequest const & func, bool verbose) +void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) { - string argument = func.argument; - kb_action action = func.action; + string const argument = cmd.argument; + kb_action const action = cmd.action; - //lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << func << endl; - lyxerr << "LyXFunc::dispatch: cmd: " << func << endl; + lyxerr[Debug::ACTION] << "LyXFunc::dispatch: cmd: " << cmd << endl; + //lyxerr << "LyXFunc::dispatch: cmd: " << cmd << endl; // we have not done anything wrong yet. errorstat = false; dispatch_buffer.erase(); - -#ifdef NEW_DISPATCHER - // We try do call the most specific dispatcher first: - // 1. the lockinginset's dispatch - // 2. the bufferview's dispatch - // 3. the lyxview's dispatch -#endif - selection_possible = false; + bool update = true; + // We cannot use this function here - if (getStatus(func).disabled()) { + if (!getStatus(cmd).enabled()) { lyxerr[Debug::ACTION] << "LyXFunc::dispatch: " << lyxaction.getActionName(action) << " [" << action << "] is disabled at this location" << endl; setErrorMessage(getStatusMessage()); - goto exit_with_message; - } - if (view()->available()) - view()->hideCursor(); + } else { - switch (action) { + if (view()->available()) + view()->hideCursor(); - case LFUN_ESCAPE: { - if (!view()->available()) - break; - view()->cursor().pop(); - // Tell the paragraph dialog that we changed paragraph - dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); - break; - } + switch (action) { - case LFUN_WORDFINDFORWARD: - case LFUN_WORDFINDBACKWARD: { - static string last_search; - string searched_string; + case LFUN_WORDFINDFORWARD: + case LFUN_WORDFINDBACKWARD: { + static string last_search; + string searched_string; - if (!argument.empty()) { - last_search = argument; - searched_string = argument; - } else { - searched_string = last_search; + if (!argument.empty()) { + last_search = argument; + searched_string = argument; + } else { + searched_string = last_search; + } + + if (searched_string.empty()) + break; + + bool const fw = action == LFUN_WORDFINDFORWARD; + string const data = + lyx::find::find2string(searched_string, true, false, fw); + lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data)); + break; } - bool fw = (action == LFUN_WORDFINDFORWARD); - if (!searched_string.empty()) - lyx::find::find(view(), searched_string, - true, false, fw); - break; - } - case LFUN_PREFIX: - if (view()->available()) - view()->update(); - owner->message(keyseq.printOptions()); - break; + case LFUN_PREFIX: + owner->message(keyseq.printOptions()); + break; - // --- Misc ------------------------------------------- - case LFUN_EXEC_COMMAND: - owner->focus_command_buffer(); - break; + case LFUN_EXEC_COMMAND: + owner->getToolbar().display("minibuffer", true); + owner->focus_command_buffer(); + break; - case LFUN_CANCEL: - keyseq.reset(); - meta_fake_bit = key_modifier::none; - if (view()->available()) - // cancel any selection - dispatch(FuncRequest(LFUN_MARK_OFF)); - setMessage(N_("Cancel")); - break; + case LFUN_CANCEL: + keyseq.reset(); + meta_fake_bit = key_modifier::none; + if (view()->available()) + // cancel any selection + dispatch(FuncRequest(LFUN_MARK_OFF)); + setMessage(N_("Cancel")); + break; - case LFUN_META_FAKE: - meta_fake_bit = key_modifier::alt; - setMessage(keyseq.print()); - break; + case LFUN_META_FAKE: + meta_fake_bit = key_modifier::alt; + setMessage(keyseq.print()); + break; - case LFUN_READ_ONLY_TOGGLE: - if (owner->buffer()->lyxvc().inUse()) - owner->buffer()->lyxvc().toggleReadOnly(); - else - owner->buffer()->setReadonly( - !owner->buffer()->isReadonly()); - break; + case LFUN_READ_ONLY_TOGGLE: + if (owner->buffer()->lyxvc().inUse()) + owner->buffer()->lyxvc().toggleReadOnly(); + else + owner->buffer()->setReadonly( + !owner->buffer()->isReadonly()); + break; - case LFUN_CENTER: // this is center and redraw. - view()->center(); - break; + // --- Menus ----------------------------------------------- + case LFUN_MENUNEW: + menuNew(argument, false); + break; - // --- Menus ----------------------------------------------- - case LFUN_MENUNEW: - menuNew(argument, false); - break; + case LFUN_MENUNEWTMPLT: + menuNew(argument, true); + break; + + case LFUN_CLOSEBUFFER: + closeBuffer(); + break; + + case LFUN_MENUWRITE: + if (!owner->buffer()->isUnnamed()) { + string const str = bformat(_("Saving document %1$s..."), + MakeDisplayPath(owner->buffer()->fileName())); + owner->message(str); + MenuWrite(owner->buffer()); + owner->message(str + _(" done.")); + } else + WriteAs(owner->buffer()); + break; + + case LFUN_WRITEAS: + WriteAs(owner->buffer(), argument); + break; + + case LFUN_MENURELOAD: { + string const file = MakeDisplayPath(view()->buffer()->fileName(), 20); + string text = bformat(_("Any changes will be lost. Are you sure " + "you want to revert to the saved version of the document %1$s?"), file); + int const ret = Alert::prompt(_("Revert to saved document?"), + text, 0, 1, _("&Revert"), _("&Cancel")); + + if (ret == 0) + view()->reload(); + break; + } + + case LFUN_UPDATE: + Exporter::Export(owner->buffer(), argument, true); + view()->showErrorList(BufferFormat(*owner->buffer())); + break; + + case LFUN_PREVIEW: + Exporter::Preview(owner->buffer(), argument); + view()->showErrorList(BufferFormat(*owner->buffer())); + break; - case LFUN_MENUNEWTMPLT: - menuNew(argument, true); - break; + case LFUN_BUILDPROG: + Exporter::Export(owner->buffer(), "program", true); + view()->showErrorList(_("Build")); + break; - case LFUN_CLOSEBUFFER: - closeBuffer(); - break; + case LFUN_RUNCHKTEX: + owner->buffer()->runChktex(); + view()->showErrorList(_("ChkTeX")); + break; - case LFUN_MENUWRITE: - if (!owner->buffer()->isUnnamed()) { - string const str = bformat(_("Saving document %1$s..."), - MakeDisplayPath(owner->buffer()->fileName())); - owner->message(str); - MenuWrite(owner->buffer()); - owner->message(str + _(" done.")); - } else - WriteAs(owner->buffer()); - break; + case LFUN_EXPORT: + if (argument == "custom") + owner->getDialogs().show("sendto"); + else { + Exporter::Export(owner->buffer(), argument, false); + view()->showErrorList(BufferFormat(*owner->buffer())); + } + break; - case LFUN_WRITEAS: - WriteAs(owner->buffer(), argument); - break; + case LFUN_EXPORT_CUSTOM: { + string format_name; + string command = split(argument, format_name, ' '); + Format const * format = formats.getFormat(format_name); + if (!format) { + lyxerr << "Format \"" << format_name + << "\" not recognized!" + << std::endl; + break; + } - case LFUN_MENURELOAD: { - string const file = MakeDisplayPath(view()->buffer()->fileName(), 20); - string text = bformat(_("Any changes will be lost. Are you sure " - "you want to revert to the saved version of the document %1$s?"), file); - int const ret = Alert::prompt(_("Revert to saved document?"), - text, 0, 1, _("&Revert"), _("&Cancel")); + Buffer * buffer = owner->buffer(); - if (ret == 0) - view()->reload(); - break; - } + // The name of the file created by the conversion process + string filename; - case LFUN_UPDATE: - Exporter::Export(owner->buffer(), argument, true); - view()->showErrorList(BufferFormat(*owner->buffer())); - break; + // Output to filename + if (format->name() == "lyx") { + string const latexname = + buffer->getLatexName(false); + filename = ChangeExtension(latexname, + format->extension()); + filename = AddName(buffer->temppath(), filename); - case LFUN_PREVIEW: - Exporter::Preview(owner->buffer(), argument); - view()->showErrorList(BufferFormat(*owner->buffer())); - break; + if (!buffer->writeFile(filename)) + break; - case LFUN_BUILDPROG: - Exporter::Export(owner->buffer(), "program", true); - view()->showErrorList(_("Build")); - break; + } else { + Exporter::Export(buffer, format_name, true, + filename); + } - case LFUN_RUNCHKTEX: - owner->buffer()->runChktex(); - view()->showErrorList(_("ChkTeX")); - break; + // Substitute $$FName for filename + if (!contains(command, "$$FName")) + command = "( " + command + " ) < $$FName"; + command = subst(command, "$$FName", filename); - case LFUN_EXPORT: - if (argument == "custom") - owner->getDialogs().showSendto(); - else { - Exporter::Export(owner->buffer(), argument, false); - view()->showErrorList(BufferFormat(*owner->buffer())); + // Execute the command in the background + Systemcall call; + call.startscript(Systemcall::DontWait, command); + break; } - break; - case LFUN_IMPORT: - doImport(argument); - break; + case LFUN_PRINT: { + string target; + string target_name; + string command = split(split(argument, target, ' '), + target_name, ' '); + + if (target.empty() + || target_name.empty() + || command.empty()) { + lyxerr << "Unable to parse \"" + << argument << '"' << std::endl; + break; + } + if (target != "printer" && target != "file") { + lyxerr << "Unrecognized target \"" + << target << '"' << std::endl; + break; + } - case LFUN_QUIT: - QuitLyX(); - break; + Buffer * buffer = owner->buffer(); - case LFUN_TOCVIEW: { - InsetCommandParams p("tableofcontents"); - string const data = InsetCommandMailer::params2string("toc", p); - owner->getDialogs().show("toc", data, 0); - break; - } + if (!Exporter::Export(buffer, "dvi", true)) { + showPrintError(buffer->fileName()); + break; + } - case LFUN_AUTOSAVE: - AutoSave(view()); - break; + // Push directory path. + string const path = buffer->temppath(); + Path p(path); + + // there are three cases here: + // 1. we print to a file + // 2. we print directly to a printer + // 3. we print using a spool command (print to file first) + Systemcall one; + int res = 0; + string const dviname = + ChangeExtension(buffer->getLatexName(true), + "dvi"); + + if (target == "printer") { + if (!lyxrc.print_spool_command.empty()) { + // case 3: print using a spool + string const psname = + ChangeExtension(dviname,".ps"); + command += lyxrc.print_to_file + + QuoteName(psname) + + ' ' + + QuoteName(dviname); + + string command2 = + lyxrc.print_spool_command +' '; + if (target_name != "default") { + command2 += lyxrc.print_spool_printerprefix + + target_name + + ' '; + } + command2 += QuoteName(psname); + // First run dvips. + // If successful, then spool command + res = one.startscript( + Systemcall::Wait, + command); + + if (res == 0) + res = one.startscript( + Systemcall::DontWait, + command2); + } else { + // case 2: print directly to a printer + res = one.startscript( + Systemcall::DontWait, + command + QuoteName(dviname)); + } - case LFUN_UNDO: - view()->undo(); - break; + } else { + // case 1: print to a file + command += lyxrc.print_to_file + + QuoteName(MakeAbsPath(target_name, + path)) + + ' ' + + QuoteName(dviname); + res = one.startscript(Systemcall::DontWait, + command); + } - case LFUN_REDO: - view()->redo(); - break; + if (res != 0) + showPrintError(buffer->fileName()); + break; + } - case LFUN_RECONFIGURE: - Reconfigure(view()); - break; + case LFUN_IMPORT: + doImport(argument); + break; - case LFUN_HELP_OPEN: { - string const arg = argument; - if (arg.empty()) { - setErrorMessage(N_("Missing argument")); + case LFUN_QUIT: + QuitLyX(); break; - } - string const fname = i18nLibFileSearch("doc", arg, "lyx"); - if (fname.empty()) { - lyxerr << "LyX: unable to find documentation file `" - << arg << "'. Bad installation?" << endl; + + case LFUN_TOCVIEW: { + InsetCommandParams p("tableofcontents"); + string const data = InsetCommandMailer::params2string("toc", p); + owner->getDialogs().show("toc", data, 0); break; } - owner->message(bformat(_("Opening help file %1$s..."), - MakeDisplayPath(fname))); - view()->loadLyXFile(fname, false); - break; - } - // --- version control ------------------------------- - case LFUN_VC_REGISTER: - if (!ensureBufferClean(view())) + case LFUN_AUTOSAVE: + AutoSave(view()); break; - if (!owner->buffer()->lyxvc().inUse()) { - owner->buffer()->lyxvc().registrer(); - view()->reload(); - } - break; - case LFUN_VC_CHECKIN: - if (!ensureBufferClean(view())) + case LFUN_RECONFIGURE: + Reconfigure(view()); break; - if (owner->buffer()->lyxvc().inUse() - && !owner->buffer()->isReadonly()) { - owner->buffer()->lyxvc().checkIn(); - view()->reload(); - } - break; - case LFUN_VC_CHECKOUT: - if (!ensureBufferClean(view())) + case LFUN_HELP_OPEN: { + string const arg = argument; + if (arg.empty()) { + setErrorMessage(N_("Missing argument")); + break; + } + string const fname = i18nLibFileSearch("doc", arg, "lyx"); + if (fname.empty()) { + lyxerr << "LyX: unable to find documentation file `" + << arg << "'. Bad installation?" << endl; + break; + } + owner->message(bformat(_("Opening help file %1$s..."), + MakeDisplayPath(fname))); + view()->loadLyXFile(fname, false); break; - if (owner->buffer()->lyxvc().inUse() - && owner->buffer()->isReadonly()) { - owner->buffer()->lyxvc().checkOut(); - view()->reload(); } - break; - case LFUN_VC_REVERT: - owner->buffer()->lyxvc().revert(); - view()->reload(); - break; + // --- version control ------------------------------- + case LFUN_VC_REGISTER: + if (!ensureBufferClean(view())) + break; + if (!owner->buffer()->lyxvc().inUse()) { + owner->buffer()->lyxvc().registrer(); + view()->reload(); + } + break; - case LFUN_VC_UNDO: - owner->buffer()->lyxvc().undoLast(); - view()->reload(); - break; + case LFUN_VC_CHECKIN: + if (!ensureBufferClean(view())) + break; + if (owner->buffer()->lyxvc().inUse() + && !owner->buffer()->isReadonly()) { + owner->buffer()->lyxvc().checkIn(); + view()->reload(); + } + break; - // --- buffers ---------------------------------------- - case LFUN_SWITCHBUFFER: - view()->buffer(bufferlist.getBuffer(argument)); - break; + case LFUN_VC_CHECKOUT: + if (!ensureBufferClean(view())) + break; + if (owner->buffer()->lyxvc().inUse() + && owner->buffer()->isReadonly()) { + owner->buffer()->lyxvc().checkOut(); + view()->reload(); + } + break; - case LFUN_FILE_NEW: - NewFile(view(), argument); - break; + case LFUN_VC_REVERT: + owner->buffer()->lyxvc().revert(); + view()->reload(); + break; - case LFUN_FILE_OPEN: - open(argument); - break; + case LFUN_VC_UNDO: + owner->buffer()->lyxvc().undoLast(); + view()->reload(); + break; - case LFUN_LAYOUT_TABULAR: - if (InsetTabular * tab = view()->cursor().innerInsetTabular()) - tab->openLayoutDialog(view()); - break; + // --- buffers ---------------------------------------- + case LFUN_SWITCHBUFFER: + view()->setBuffer(bufferlist.getBuffer(argument)); + break; - case LFUN_DROP_LAYOUTS_CHOICE: - owner->getToolbar().openLayoutList(); - break; + case LFUN_FILE_NEW: + NewFile(view(), argument); + break; - case LFUN_MENU_OPEN_BY_NAME: - owner->getMenubar().openByName(argument); - break; + case LFUN_FILE_OPEN: + open(argument); + break; - // --- lyxserver commands ---------------------------- - case LFUN_GETNAME: - setMessage(owner->buffer()->fileName()); - lyxerr[Debug::INFO] << "FNAME[" - << owner->buffer()->fileName() - << "] " << endl; - break; + case LFUN_DROP_LAYOUTS_CHOICE: + owner->getToolbar().openLayoutList(); + break; - case LFUN_NOTIFY: - dispatch_buffer = keyseq.print(); - lyxserver->notifyClient(dispatch_buffer); - break; + case LFUN_MENU_OPEN_BY_NAME: + owner->getMenubar().openByName(argument); + break; - case LFUN_GOTOFILEROW: { - string file_name; - int row; - istringstream is(argument); - is >> file_name >> row; - if (prefixIs(file_name, getTmpDir())) { - // Needed by inverse dvi search. If it is a file - // in tmpdir, call the apropriated function - view()->buffer(bufferlist.getBufferFromTmp(file_name)); - } else { - // Must replace extension of the file to be .lyx - // and get full path - string const s = ChangeExtension(file_name, ".lyx"); - // Either change buffer or load the file - if (bufferlist.exists(s)) { - view()->buffer(bufferlist.getBuffer(s)); + // --- lyxserver commands ---------------------------- + case LFUN_GETNAME: + setMessage(owner->buffer()->fileName()); + lyxerr[Debug::INFO] << "FNAME[" + << owner->buffer()->fileName() + << "] " << endl; + break; + + case LFUN_NOTIFY: + dispatch_buffer = keyseq.print(); + lyxserver->notifyClient(dispatch_buffer); + break; + + case LFUN_GOTOFILEROW: { + string file_name; + int row; + istringstream is(argument); + is >> file_name >> row; + if (prefixIs(file_name, getTmpDir())) { + // Needed by inverse dvi search. If it is a file + // in tmpdir, call the apropriated function + view()->setBuffer(bufferlist.getBufferFromTmp(file_name)); } else { - view()->loadLyXFile(s); + // Must replace extension of the file to be .lyx + // and get full path + string const s = ChangeExtension(file_name, ".lyx"); + // Either change buffer or load the file + if (bufferlist.exists(s)) { + view()->setBuffer(bufferlist.getBuffer(s)); + } else { + view()->loadLyXFile(s); + } } + + view()->setCursorFromRow(row); + + view()->center(); + // see BufferView_pimpl::center() + view()->updateScrollbar(); + break; } - view()->setCursorFromRow(row); + case LFUN_GOTO_PARAGRAPH: { + istringstream is(argument); + int id; + is >> id; + ParIterator par = owner->buffer()->getParFromID(id); + if (par == owner->buffer()->par_iterator_end()) { + lyxerr[Debug::INFO] << "No matching paragraph found! [" + << id << ']' << endl; + break; + } else { + lyxerr[Debug::INFO] << "Paragraph " << par->id() + << " found." << endl; + } + + // Set the cursor + view()->setCursor(par, 0); - view()->center(); - // see BufferView_pimpl::center() - view()->updateScrollbar(); - break; - } + view()->switchKeyMap(); + owner->view_state_changed(); - case LFUN_GOTO_PARAGRAPH: { - istringstream is(argument); - int id; - is >> id; - ParIterator par = owner->buffer()->getParFromID(id); - if (par == owner->buffer()->par_iterator_end()) { - lyxerr[Debug::INFO] << "No matching paragraph found! [" - << id << ']' << endl; + view()->center(); + // see BufferView_pimpl::center() + view()->updateScrollbar(); break; - } else { - lyxerr[Debug::INFO] << "Paragraph " << par->id() - << " found." << endl; } - par.lockPath(view()); - LyXText * lt = par.text(view()); + case LFUN_DIALOG_SHOW: { + string const name = cmd.getArg(0); + string data = trim(cmd.argument.substr(name.size())); - // Set the cursor - lt->setCursor(par.pit(), 0); - view()->switchKeyMap(); - owner->view_state_changed(); + if (name == "character") { + data = freefont2string(); + if (!data.empty()) + owner->getDialogs().show("character", data); + } - view()->center(); - // see BufferView_pimpl::center() - view()->updateScrollbar(); - break; - } + else if (name == "latexlog") { + pair const logfile = + owner->buffer()->getLogName(); + switch (logfile.first) { + case Buffer::latexlog: + data = "latex "; + break; + case Buffer::buildlog: + data = "literate "; + break; + } + data += logfile.second; + owner->getDialogs().show("log", data); + } + else if (name == "vclog") { + string const data = "vc " + + owner->buffer()->lyxvc().getLogFile(); + owner->getDialogs().show("log", data); + } + else + owner->getDialogs().show(name, data); + break; + } - // --- Mathed stuff. If we are here, there is no locked inset yet. - case LFUN_MATH_EXTERN: - case LFUN_MATH_NUMBER: - case LFUN_MATH_NONUMBER: - case LFUN_MATH_LIMITS: - setErrorMessage(N_("This is only allowed in math mode!")); - break; + case LFUN_DIALOG_SHOW_NEW_INSET: { + string const name = cmd.getArg(0); + string data = trim(cmd.argument.substr(name.size())); + if (name == "bibitem" || + name == "bibtex" || + name == "include" || + name == "index" || + name == "label" || + name == "ref" || + name == "toc" || + name == "url") { + InsetCommandParams p(name); + data = InsetCommandMailer::params2string(name, p); + } else if (name == "box") { + // \c data == "Boxed" || "Frameless" etc + InsetBoxParams p(data); + data = InsetBoxMailer::params2string(p); + } else if (name == "branch") { + InsetBranchParams p; + data = InsetBranchMailer::params2string(p); + } else if (name == "citation") { + InsetCommandParams p("cite"); + data = InsetCommandMailer::params2string(name, p); + } else if (name == "ert") { + data = InsetERTMailer::params2string(InsetCollapsable::Open); + } else if (name == "external") { + InsetExternalParams p; + Buffer const & buffer = *owner->buffer(); + data = InsetExternalMailer::params2string(p, buffer); + } else if (name == "float") { + InsetFloatParams p; + data = InsetFloatMailer::params2string(p); + } else if (name == "graphics") { + InsetGraphicsParams p; + Buffer const & buffer = *owner->buffer(); + data = InsetGraphicsMailer::params2string(p, buffer); + } else if (name == "note") { + InsetNoteParams p; + data = InsetNoteMailer::params2string(p); + } else if (name == "vspace") { + VSpace space; + data = InsetVSpaceMailer::params2string(space); + } else if (name == "wrap") { + InsetWrapParams p; + data = InsetWrapMailer::params2string(p); + } + owner->getDialogs().show(name, data, 0); + break; + } - // passthrough hat and underscore outside mathed: - case LFUN_SUBSCRIPT: - dispatch(FuncRequest(view(), LFUN_SELFINSERT, "_")); - break; + case LFUN_DIALOG_SHOW_NEXT_INSET: + break; - case LFUN_SUPERSCRIPT: - dispatch(FuncRequest(view(), LFUN_SELFINSERT, "^")); - break; + case LFUN_DIALOG_UPDATE: { + string const & name = argument; + // Can only update a dialog connected to an existing inset + InsetBase * inset = owner->getDialogs().getOpenInset(name); + if (inset) { + FuncRequest fr(LFUN_INSET_DIALOG_UPDATE, cmd.argument); + inset->dispatch(view()->cursor(), fr); + } else if (name == "paragraph") { + dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); + } else if (name == "prefs") { + owner->getDialogs().update(name, string()); + } + break; + } - case LFUN_DIALOG_SHOW: { - string const name = func.getArg(0); - string data = trim(func.argument.substr(name.size())); - - if (name == "character") { - data = freefont2string(); - if (!data.empty()) - owner->getDialogs().show("character", data); - } else if (name == "document") - owner->getDialogs().showDocument(); - else if (name == "findreplace") - owner->getDialogs().showSearch(); - else if (name == "forks") - owner->getDialogs().showForks(); - else if (name == "preamble") - owner->getDialogs().showPreamble(); - else if (name == "preferences") - owner->getDialogs().showPreferences(); - else if (name == "print") - owner->getDialogs().showPrint(); - else if (name == "spellchecker") - owner->getDialogs().showSpellchecker(); - else - owner->getDialogs().show(name, data); - break; - } + case LFUN_DIALOG_HIDE: + Dialogs::hide(argument, 0); + break; - case LFUN_DIALOG_SHOW_NEW_INSET: { - string const & name = argument; - string data; - if (name == "bibitem" || - name == "bibtex" || - name == "include" || - name == "index" || - name == "ref" || - name == "toc" || - name == "url") { - InsetCommandParams p(name); - data = InsetCommandMailer::params2string(name, p); - } else if (name == "citation") { - InsetCommandParams p("cite"); - data = InsetCommandMailer::params2string(name, p); + case LFUN_DIALOG_DISCONNECT_INSET: + owner->getDialogs().disconnect(argument); + break; + + case LFUN_CHILDOPEN: { + string const filename = + MakeAbsPath(argument, owner->buffer()->filePath()); + setMessage(N_("Opening child document ") + + MakeDisplayPath(filename) + "..."); + view()->savePosition(0); + string const parentfilename = owner->buffer()->fileName(); + if (bufferlist.exists(filename)) + view()->setBuffer(bufferlist.getBuffer(filename)); + else + view()->loadLyXFile(filename); + // Set the parent name of the child document. + // This makes insertion of citations and references in the child work, + // when the target is in the parent or another child document. + owner->buffer()->setParentName(parentfilename); + break; } - owner->getDialogs().show(name, data, 0); - break; - } - case LFUN_DIALOG_SHOW_NEXT_INSET: - break; + case LFUN_TOGGLECURSORFOLLOW: + lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar; + break; - case LFUN_INSET_DIALOG_SHOW: { - InsetOld * inset = view()->getLyXText()->getInset(); - if (inset) - inset->dispatch(FuncRequest(view(), LFUN_INSET_DIALOG_SHOW)); - break; - } + case LFUN_KMAP_OFF: + owner->getIntl().KeyMapOn(false); + break; - case LFUN_DIALOG_UPDATE: { - string const & name = argument; - // Can only update a dialog connected to an existing inset - InsetBase * inset = owner->getDialogs().getOpenInset(name); - if (inset) { - FuncRequest fr(view(), LFUN_INSET_DIALOG_UPDATE, - func.argument); - inset->dispatch(fr); - } else if (name == "paragraph") { - dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); - } - break; - } + case LFUN_KMAP_PRIM: + owner->getIntl().KeyMapPrim(); + break; - case LFUN_DIALOG_HIDE: - Dialogs::hide(argument, 0); - break; + case LFUN_KMAP_SEC: + owner->getIntl().KeyMapSec(); + break; - case LFUN_DIALOG_DISCONNECT_INSET: - owner->getDialogs().disconnect(argument); - break; + case LFUN_KMAP_TOGGLE: + owner->getIntl().ToggleKeyMap(); + break; - case LFUN_CHILDOPEN: { - string const filename = - MakeAbsPath(argument, owner->buffer()->filePath()); - setMessage(N_("Opening child document ") + - MakeDisplayPath(filename) + "..."); - view()->savePosition(0); - if (bufferlist.exists(filename)) - view()->buffer(bufferlist.getBuffer(filename)); - else - view()->loadLyXFile(filename); - break; - } + case LFUN_REPEAT: { + // repeat command + string countstr; + string rest = split(argument, countstr, ' '); + istringstream is(countstr); + int count = 0; + is >> count; + lyxerr << "repeat: count: " << count << " cmd: " << rest << endl; + for (int i = 0; i < count; ++i) + dispatch(lyxaction.lookupFunc(rest)); + break; + } - case LFUN_TOGGLECURSORFOLLOW: - lyxrc.cursor_follows_scrollbar = !lyxrc.cursor_follows_scrollbar; - break; + case LFUN_SEQUENCE: + // argument contains ';'-terminated commands + while (!argument.empty()) { + string first; + string rest = split(argument, first, ';'); + dispatch(lyxaction.lookupFunc(rest)); + } + break; - case LFUN_KMAP_OFF: - owner->getIntl().KeyMapOn(false); - break; + case LFUN_SAVEPREFERENCES: { + Path p(user_lyxdir()); + lyxrc.write("preferences", false); + break; + } - case LFUN_KMAP_PRIM: - owner->getIntl().KeyMapPrim(); - break; + case LFUN_SCREEN_FONT_UPDATE: + // handle the screen font changes. + lyxrc.set_font_norm_type(); + lyx_gui::update_fonts(); + // All visible buffers will need resize + view()->resize(); + break; - case LFUN_KMAP_SEC: - owner->getIntl().KeyMapSec(); - break; + case LFUN_SET_COLOR: { + string lyx_name; + string const x11_name = split(argument, lyx_name, ' '); + if (lyx_name.empty() || x11_name.empty()) { + setErrorMessage(N_("Syntax: set-color " + " ")); + break; + } - case LFUN_KMAP_TOGGLE: - owner->getIntl().ToggleKeyMap(); - break; + bool const graphicsbg_changed = + (lyx_name == lcolor.getLyXName(LColor::graphicsbg) && + x11_name != lcolor.getX11Name(LColor::graphicsbg)); - case LFUN_REPEAT: { - // repeat command - string countstr; - argument = split(argument, countstr, ' '); - istringstream is(countstr); - int count = 0; - is >> count; - lyxerr << "repeat: count: " << count << " cmd: " << argument << endl; - for (int i = 0; i < count; ++i) - dispatch(lyxaction.lookupFunc(argument)); - break; - } + if (!lcolor.setColor(lyx_name, x11_name)) { + setErrorMessage( + bformat(_("Set-color \"%1$s\" failed " + "- color is undefined or " + "may not be redefined"), lyx_name)); + break; + } - case LFUN_SEQUENCE: - // argument contains ';'-terminated commands - while (!argument.empty()) { - string first; - argument = split(argument, first, ';'); - dispatch(lyxaction.lookupFunc(first)); + lyx_gui::update_color(lcolor.getFromLyXName(lyx_name)); + + if (graphicsbg_changed) { +#ifdef WITH_WARNINGS +#warning FIXME!! The graphics cache no longer has a changeDisplay method. +#endif +#if 0 + lyx::graphics::GCache::get().changeDisplay(true); +#endif + } + break; } - break; - case LFUN_SAVEPREFERENCES: { - Path p(user_lyxdir()); - lyxrc.write("preferences"); - break; - } + case LFUN_MESSAGE: + owner->message(argument); + break; - case LFUN_SCREEN_FONT_UPDATE: - // handle the screen font changes. - lyxrc.set_font_norm_type(); - lyx_gui::update_fonts(); - // All visible buffers will need resize - view()->resize(); - view()->update(); - break; + case LFUN_TOOLTIPS_TOGGLE: + owner->getDialogs().toggleTooltips(); + break; - case LFUN_SET_COLOR: { - string lyx_name; - string const x11_name = split(argument, lyx_name, ' '); - if (lyx_name.empty() || x11_name.empty()) { - setErrorMessage(N_("Syntax: set-color " - " ")); + case LFUN_EXTERNAL_EDIT: { + FuncRequest fr(action, argument); + InsetExternal().dispatch(view()->cursor(), fr); break; } - bool const graphicsbg_changed = - (lyx_name == lcolor.getLyXName(LColor::graphicsbg) && - x11_name != lcolor.getX11Name(LColor::graphicsbg)); + case LFUN_GRAPHICS_EDIT: { + FuncRequest fr(action, argument); + InsetGraphics().dispatch(view()->cursor(), fr); + break; + } - if (!lcolor.setColor(lyx_name, x11_name)) { - setErrorMessage( - bformat(_("Set-color \"%1$s\" failed " - "- color is undefined or " - "may not be redefined"), lyx_name)); + case LFUN_ALL_INSETS_TOGGLE: { + string action; + string const name = split(argument, action, ' '); + InsetBase::Code const inset_code = + InsetBase::translate(name); + + LCursor & cur = view()->cursor(); + FuncRequest fr(LFUN_INSET_TOGGLE, action); + + InsetBase & inset = owner->buffer()->inset(); + InsetIterator it = inset_iterator_begin(inset); + InsetIterator const end = inset_iterator_end(inset); + for (; it != end; ++it) { + if (inset_code == InsetBase::NO_CODE + || inset_code == it->lyxCode()) + it->dispatch(cur, fr); + } break; } - lyx_gui::update_color(lcolor.getFromLyXName(lyx_name)); + case LFUN_LANGUAGE_BUFFER: { + Buffer & buffer = *owner->buffer(); + Language const * oldL = buffer.params().language; + Language const * newL = languages.getLanguage(argument); + if (!newL || oldL == newL) + break; - if (graphicsbg_changed) { -#ifdef WITH_WARNINGS -#warning FIXME!! The graphics cache no longer has a changeDisplay method. -#endif -#if 0 - lyx::graphics::GCache::get().changeDisplay(true); -#endif + if (oldL->RightToLeft() == newL->RightToLeft() + && !buffer.isMultiLingual()) + buffer.changeLanguage(oldL, newL); + else + buffer.updateDocLang(newL); + break; } - view()->update(); - break; - } + case LFUN_BUFFERPARAMS_APPLY: { + istringstream ss(argument); + LyXLex lex(0,0); + lex.setStream(ss); + int const unknown_tokens = + owner->buffer()->readHeader(lex); + + if (unknown_tokens != 0) { + lyxerr << "Warning in LFUN_BUFFERPARAMS_APPLY!\n" + << unknown_tokens << " unknown token" + << (unknown_tokens == 1 ? "" : "s") + << endl; + } + break; + } - case LFUN_MESSAGE: - owner->message(argument); - break; + case LFUN_TEXTCLASS_APPLY: { + Buffer * buffer = owner->buffer(); + + lyx::textclass_type const old_class = + buffer->params().textclass; + + loadTextclass(argument); + + std::pair const tc_pair = + textclasslist.NumberOfClass(argument); + + if (!tc_pair.first) + break; + + lyx::textclass_type const new_class = tc_pair.second; + if (old_class == new_class) + // nothing to do + break; + + owner->message(_("Converting document to new document class...")); + ErrorList el; + lyx::cap::SwitchLayoutsBetweenClasses( + old_class, new_class, + buffer->paragraphs(), el); - case LFUN_FORKS_KILL: - if (isStrInt(argument)) { - pid_t const pid = strToInt(argument); - ForkedcallsController::get().kill(pid); + bufferErrors(*buffer, el); + view()->showErrorList(_("Class switch")); break; } - case LFUN_TOOLTIPS_TOGGLE: - owner->getDialogs().toggleTooltips(); - break; + case LFUN_TEXTCLASS_LOAD: + loadTextclass(argument); + break; - case LFUN_EXTERNAL_EDIT: - InsetExternal().dispatch(FuncRequest(view(), action, argument)); - break; + case LFUN_LYXRC_APPLY: { + istringstream ss(argument); + bool const success = lyxrc.read(ss) == 0; - default: { - DispatchResult result = - view()->cursor().dispatch(FuncRequest(func, view())); - if (result.dispatched()) { - if (result.update()) - view()->update(); - lyxerr << "dispatched by Cursor::dispatch()" << endl; - } else { - lyxerr << "### NOT DISPATCHED BY Cursor::dispatch() ###" << endl; + if (!success) { + lyxerr << "Warning in LFUN_LYXRC_APPLY!\n" + << "Unable to read lyxrc data" + << endl; } break; } - } -exit_with_message: + default: { + update = false; + DispatchResult res = view()->cursor().dispatch(cmd); + if (res.dispatched()) + update |= res.update(); + else + update |= view()->dispatch(cmd); - view()->owner()->updateLayoutChoice(); + break; + } + } - if (view()->available()) { - if (view()->fitCursor()) { - //lyxerr << "LyXFunc->fitCursor->update" << endl; - view()->update(); + if (view()->available()) { + if (view()->fitCursor() || update) + view()->update(); + // if we executed a mutating lfun, mark the buffer as dirty + if (getStatus(cmd).enabled() + && !lyxaction.funcHasFlag(cmd.action, LyXAction::NoBuffer) + && !lyxaction.funcHasFlag(cmd.action, LyXAction::ReadOnly)) + view()->buffer()->markDirty(); } - // If we executed a mutating lfun, mark the buffer as dirty - if (!getStatus(func).disabled() - && !lyxaction.funcHasFlag(func.action, LyXAction::NoBuffer) - && !lyxaction.funcHasFlag(func.action, LyXAction::ReadOnly)) - view()->buffer()->markDirty(); + if (view()->cursor().inTexted()) { + view()->owner()->updateLayoutChoice(); + sendDispatchMessage(getMessage(), cmd, verbose); + } } - - sendDispatchMessage(getMessage(), func, verbose); } void LyXFunc::sendDispatchMessage(string const & msg, - FuncRequest const & func, bool verbose) + FuncRequest const & cmd, bool verbose) { owner->updateMenubar(); owner->updateToolbar(); - if (func.action == LFUN_SELFINSERT || !verbose) { + if (cmd.action == LFUN_SELFINSERT || !verbose) { lyxerr[Debug::ACTION] << "dispatch msg is " << msg << endl; if (!msg.empty()) owner->message(msg); @@ -1464,23 +1412,23 @@ void LyXFunc::sendDispatchMessage(string const & msg, if (!dispatch_msg.empty()) dispatch_msg += ' '; - string comname = lyxaction.getActionName(func.action); + string comname = lyxaction.getActionName(cmd.action); bool argsadded = false; - if (!func.argument.empty()) { - if (func.action != LFUN_UNKNOWN_ACTION) { - comname += ' ' + func.argument; + if (!cmd.argument.empty()) { + if (cmd.action != LFUN_UNKNOWN_ACTION) { + comname += ' ' + cmd.argument; argsadded = true; } } - string const shortcuts = toplevel_keymap->findbinding(func); + string const shortcuts = toplevel_keymap->findbinding(cmd); if (!shortcuts.empty()) { comname += ": " + shortcuts; - } else if (!argsadded && !func.argument.empty()) { - comname += ' ' + func.argument; + } else if (!argsadded && !cmd.argument.empty()) { + comname += ' ' + cmd.argument; } if (!comname.empty()) { @@ -1496,8 +1444,10 @@ void LyXFunc::sendDispatchMessage(string const & msg, void LyXFunc::setupLocalKeymap() { - keyseq.stdmap = keyseq.curmap = toplevel_keymap.get(); - cancel_meta_seq.stdmap = cancel_meta_seq.curmap = toplevel_keymap.get(); + keyseq.stdmap = toplevel_keymap.get(); + keyseq.curmap = toplevel_keymap.get(); + cancel_meta_seq.stdmap = toplevel_keymap.get(); + cancel_meta_seq.curmap = toplevel_keymap.get(); } @@ -1540,16 +1490,14 @@ void LyXFunc::menuNew(string const & name, bool fromTemplate) FileDialog::Result result = fileDlg.open(lyxrc.template_path, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; - - string const fname = result.second; - - if (fname.empty()) + if (result.second.empty()) return; - templname = fname; + templname = result.second; } view()->newFile(filename, templname, !name.empty()); @@ -1579,7 +1527,8 @@ void LyXFunc::open(string const & fname) FileDialog::Result result = fileDlg.open(initpath, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; @@ -1652,12 +1601,13 @@ void LyXFunc::doImport(string const & argument) make_pair(string(_("Examples|#E#e")), string(AddPath(system_lyxdir(), "examples")))); - string const extension = "*." + formats.extension(format) - + "| " + formats.prettyName(format) + string const filter = formats.prettyName(format) + " (*." + formats.extension(format) + ')'; - FileDialog::Result result = fileDlg.open(initpath, - extension); + FileDialog::Result result = + fileDlg.open(initpath, + FileFilterList(filter), + string()); if (result.first == FileDialog::Later) return; @@ -1714,7 +1664,7 @@ void LyXFunc::closeBuffer() // since there's no current buffer owner->getDialogs().hideBufferDependent(); } else { - view()->buffer(bufferlist.first()); + view()->setBuffer(bufferlist.first()); } } } @@ -1723,7 +1673,7 @@ void LyXFunc::closeBuffer() // Each "owner" should have it's own message method. lyxview and // the minibuffer would use the minibuffer, but lyxserver would // send an ERROR signal to its client. Alejandro 970603 -// This func is bit problematic when it comes to NLS, to make the +// This function is bit problematic when it comes to NLS, to make the // lyx servers client be language indepenent we must not translate // strings sent to this func. void LyXFunc::setErrorMessage(string const & m) const @@ -1745,23 +1695,21 @@ void LyXFunc::setStatusMessage(string const & m) const } -string const LyXFunc::view_status_message() +string const LyXFunc::viewStatusMessage() { // When meta-fake key is pressed, show the key sequence so far + "M-". - if (wasMetaKey()) { + if (wasMetaKey()) return keyseq.print() + "M-"; - } // Else, when a non-complete key sequence is pressed, // show the available options. - if (keyseq.length() > 0 && !keyseq.deleted()) { + if (keyseq.length() > 0 && !keyseq.deleted()) return keyseq.printOptions(); - } if (!view()->available()) return _("Welcome to LyX!"); - return currentState(view()); + return view()->cursor().currentState(); }