X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxfunc.C;h=244a858dbca70488982b1fd23ae0c899a75d5db6;hb=de3c8e5b80effa940c92980032389c868f377d6b;hp=87802db1a4d10a1dbbf76609286a527b1b0a995a;hpb=b634b3eb3b5cc1c47fd3bc63294e16536d4f7664;p=lyx.git diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 87802db1a4..244a858dbc 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -28,26 +28,32 @@ #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" @@ -76,8 +82,10 @@ #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" @@ -88,6 +96,7 @@ 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; @@ -99,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; @@ -287,25 +299,12 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const setStatusMessage(N_("Command disabled")); // Check whether we need a buffer - if (!lyxaction.funcHasFlag(cmd.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(cmd.action, - LyXAction::ReadOnly)) { - // no - setStatusMessage(N_("Document is read-only")); - flag.enabled(false); - } - } else { - // no - setStatusMessage(N_("Command not allowed with" - "out any document open")); - flag.enabled(false); - 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; } // I would really like to avoid having this switch and rather try to @@ -329,20 +328,10 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const flag.setOnOff(true); break; - case LFUN_TRACK_CHANGES: - flag.setOnOff(buf->params().tracking_changes); - break; - case LFUN_EXPORT: enable = cmd.argument == "custom" || Exporter::IsExportable(*buf, cmd.argument); break; - case LFUN_UNDO: - enable = !buf->undostack().empty(); - break; - case LFUN_REDO: - enable = !buf->redostack().empty(); - break; case LFUN_CUT: case LFUN_COPY: enable = cur.selection(); @@ -381,17 +370,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const case LFUN_MENURELOAD: enable = !buf->isUnnamed() && !buf->isClean(); break; - case LFUN_BOOKMARK_GOTO: - enable = view()->isSavedPosition(strToUnsignedInt(cmd.argument)); - break; - case LFUN_MERGE_CHANGES: - case LFUN_ACCEPT_CHANGE: - case LFUN_REJECT_CHANGE: - case LFUN_ACCEPT_ALL_CHANGES: - case LFUN_REJECT_ALL_CHANGES: - enable = buf && buf->params().tracking_changes; - break; case LFUN_INSET_SETTINGS: { enable = false; @@ -402,14 +381,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const 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(); - lyxerr << "inset 2: " << inset << endl; - if (!inset) - break; - InsetOld::Code code = inset->lyxCode(); switch (code) { case InsetOld::TABULAR_CODE: @@ -445,7 +416,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const enable = name == "aboutlyx" || name == "file" || name == "forks" - || name == "preferences" + || name == "prefs" || name == "texinfo"; else if (name == "print") enable = Exporter::IsExportable(*buf, "dvi") @@ -459,6 +430,13 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const break; } + case LFUN_DIALOG_UPDATE: { + string const name = cmd.getArg(0); + if (!buf) + enable = name == "prefs"; + break; + } + case LFUN_MENUNEW: case LFUN_MENUNEWTMPLT: case LFUN_WORDFINDFORWARD: @@ -488,7 +466,6 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const case LFUN_GOTO_PARAGRAPH: case LFUN_DIALOG_SHOW_NEW_INSET: case LFUN_DIALOG_SHOW_NEXT_INSET: - case LFUN_DIALOG_UPDATE: case LFUN_DIALOG_HIDE: case LFUN_DIALOG_DISCONNECT_INSET: case LFUN_CHILDOPEN: @@ -498,22 +475,44 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const 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_FORKS_KILL: 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; default: + cur.getStatus(cmd, flag); - return flag; + if (!flag.enabled()) + flag = view()->getStatus(cmd); } - flag.enabled(enable); + if (!enable) + flag.enabled(false); + + // 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; } @@ -540,6 +539,38 @@ 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 @@ -556,6 +587,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) dispatch_buffer.erase(); selection_possible = false; + bool update = true; + // We cannot use this function here if (!getStatus(cmd).enabled()) { lyxerr[Debug::ACTION] << "LyXFunc::dispatch: " @@ -579,8 +612,9 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) if (!argument.empty()) { last_search = argument; searched_string = argument; - } else + } else { searched_string = last_search; + } if (searched_string.empty()) break; @@ -588,7 +622,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) bool const fw = action == LFUN_WORDFINDFORWARD; string const data = lyx::find::find2string(searched_string, true, false, fw); - view()->dispatch(FuncRequest(LFUN_WORD_FIND, data)); + lyx::find::find(view(), FuncRequest(LFUN_WORD_FIND, data)); break; } @@ -597,6 +631,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) break; case LFUN_EXEC_COMMAND: + owner->getToolbar().display("minibuffer", true); owner->focus_command_buffer(); break; @@ -684,13 +719,147 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) case LFUN_EXPORT: if (argument == "custom") - owner->getDialogs().showSendto(); + owner->getDialogs().show("sendto"); else { Exporter::Export(owner->buffer(), argument, false); view()->showErrorList(BufferFormat(*owner->buffer())); } 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; + } + + Buffer * buffer = owner->buffer(); + + // The name of the file created by the conversion process + string filename; + + // Output to filename + if (format->name() == "lyx") { + string const latexname = + buffer->getLatexName(false); + filename = ChangeExtension(latexname, + format->extension()); + filename = AddName(buffer->temppath(), filename); + + if (!buffer->writeFile(filename)) + break; + + } else { + Exporter::Export(buffer, format_name, true, + filename); + } + + // Substitute $$FName for filename + if (!contains(command, "$$FName")) + command = "( " + command + " ) < $$FName"; + command = subst(command, "$$FName", filename); + + // Execute the command in the background + Systemcall call; + call.startscript(Systemcall::DontWait, command); + 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; + } + + Buffer * buffer = owner->buffer(); + + if (!Exporter::Export(buffer, "dvi", true)) { + showPrintError(buffer->fileName()); + 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)); + } + + } 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); + } + + if (res != 0) + showPrintError(buffer->fileName()); + break; + } + case LFUN_IMPORT: doImport(argument); break; @@ -870,16 +1039,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) if (!data.empty()) owner->getDialogs().show("character", data); } - else if (name == "document") - owner->getDialogs().showDocument(); - 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 if (name == "latexlog") { pair const logfile = @@ -967,6 +1126,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) inset->dispatch(view()->cursor(), fr); } else if (name == "paragraph") { dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); + } else if (name == "prefs") { + owner->getDialogs().update(name, string()); } break; } @@ -1041,7 +1202,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) case LFUN_SAVEPREFERENCES: { Path p(user_lyxdir()); - lyxrc.write("preferences"); + lyxrc.write("preferences", false); break; } @@ -1066,8 +1227,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) (lyx_name == lcolor.getLyXName(LColor::graphicsbg) && x11_name != lcolor.getX11Name(LColor::graphicsbg)); - LColor::color col = lcolor.getFromLyXName(lyx_name); - if (!lcolor.setColor(col, x11_name)) { + if (!lcolor.setColor(lyx_name, x11_name)) { setErrorMessage( bformat(_("Set-color \"%1$s\" failed " "- color is undefined or " @@ -1102,29 +1262,135 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) break; } + case LFUN_GRAPHICS_EDIT: { + FuncRequest fr(action, argument); + InsetGraphics().dispatch(view()->cursor(), fr); + break; + } + + 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; + } + + 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 (oldL->RightToLeft() == newL->RightToLeft() + && !buffer.isMultiLingual()) + buffer.changeLanguage(oldL, newL); + else + buffer.updateDocLang(newL); + 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_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); + + bufferErrors(*buffer, el); + view()->showErrorList(_("Class switch")); + break; + } + + case LFUN_TEXTCLASS_LOAD: + loadTextclass(argument); + break; + + case LFUN_LYXRC_APPLY: { + istringstream ss(argument); + bool const success = lyxrc.read(ss) == 0; + + if (!success) { + lyxerr << "Warning in LFUN_LYXRC_APPLY!\n" + << "Unable to read lyxrc data" + << endl; + } + break; + } + default: { + update = false; DispatchResult res = view()->cursor().dispatch(cmd); - if (!res.dispatched()); - view()->dispatch(cmd); + if (res.dispatched()) + update |= res.update(); + else + update |= view()->dispatch(cmd); + break; } } - } - if (view()->available()) { - view()->fitCursor(); - view()->update(); - view()->cursor().updatePos(); - // 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 (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 (view()->cursor().inTexted()) { - view()->owner()->updateLayoutChoice(); - sendDispatchMessage(getMessage(), cmd, verbose); + if (view()->cursor().inTexted()) { + view()->owner()->updateLayoutChoice(); + sendDispatchMessage(getMessage(), cmd, verbose); + } } }