X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Finsets%2FInsetCommand.cpp;h=7693d08fd7c70010f323eddd24956697932d09fd;hb=79cf3f5ec1088e7de988e889247ec300d42fb70b;hp=542d99e28937451485dd8a13aa9462c5c214c074;hpb=9a097259be06cb00b8e1f6962611750f97c926ee;p=lyx.git diff --git a/src/insets/InsetCommand.cpp b/src/insets/InsetCommand.cpp index 542d99e289..7693d08fd7 100644 --- a/src/insets/InsetCommand.cpp +++ b/src/insets/InsetCommand.cpp @@ -4,7 +4,7 @@ * Licence details can be found in the file COPYING. * * \author Angus Leeming - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * * Full author contact details are available in file CREDITS. */ @@ -14,122 +14,207 @@ #include "InsetCommand.h" #include "Buffer.h" +#include "BufferEncodings.h" +#include "BufferParams.h" #include "BufferView.h" +#include "Cursor.h" #include "DispatchResult.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "gettext.h" #include "Lexer.h" #include "MetricsInfo.h" +#include "texstream.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/InsetIndex.h" +#include "insets/InsetLine.h" +#include "insets/InsetListings.h" +#include "insets/InsetNote.h" +#include "insets/InsetPhantom.h" +#include "insets/InsetSpace.h" +#include "insets/InsetTabular.h" +#include "insets/InsetVSpace.h" +#include "insets/InsetWrap.h" + +#include "support/debug.h" +#include "support/gettext.h" +#include "support/lstrings.h" + +#include "frontends/Application.h" #include +using namespace std; +using namespace lyx::support; + namespace lyx { -using std::string; -using std::istringstream; -using std::ostringstream; +// FIXME Would it now be possible to use the InsetCode in +// place of the mailer name and recover that information? +InsetCommand::InsetCommand(Buffer * buf, InsetCommandParams const & p) + : Inset(buf), p_(p) +{} -InsetCommand::InsetCommand(InsetCommandParams const & p, - string const & mailer_name) - : p_(p), - mailer_name_(mailer_name), - mouse_hover_(false), - updateButtonLabel_(true) +// The sole purpose of this copy constructor is to make sure +// that the mouse_hover_ map is not copied and remains empty. +InsetCommand::InsetCommand(InsetCommand const & rhs) + : Inset(rhs), p_(rhs.p_) {} +InsetCommand & InsetCommand::operator=(InsetCommand const & rhs) +{ + if (&rhs == this) + return *this; + + Inset::operator=(rhs); + p_ = rhs.p_; + mouse_hover_.clear(); + button_ = RenderButton(); + + return *this; +} + + InsetCommand::~InsetCommand() { - if (!mailer_name_.empty()) - InsetCommandMailer(mailer_name_, *this).hideDialog(); + if (p_.code() != NO_CODE) + hideDialogs(insetName(p_.code()), this); + + map::iterator it = mouse_hover_.begin(); + map::iterator end = mouse_hover_.end(); + for (; it != end; ++it) + if (it->second) + it->first->clearLastInset(this); } void InsetCommand::metrics(MetricsInfo & mi, Dimension & dim) const { - if (updateButtonLabel_) { - updateButtonLabel_ = false; - button_.update(getScreenLabel(mi.base.bv->buffer()), - editable() != NOT_EDITABLE); - } + button_.update(screenLabel(), editable() || clickable(*mi.base.bv, 0, 0), + inheritFont()); button_.metrics(mi, dim); } -bool InsetCommand::setMouseHover(bool mouse_hover) +bool InsetCommand::setMouseHover(BufferView const * bv, bool mouse_hover) + const { - mouse_hover_ = mouse_hover; + mouse_hover_[bv] = mouse_hover; return true; } void InsetCommand::draw(PainterInfo & pi, int x, int y) const { - button_.setRenderState(mouse_hover_); + button_.setRenderState(mouse_hover_[pi.base.bv]); button_.draw(pi, x, y); } +void InsetCommand::setParam(string const & name, docstring const & value) +{ + p_[name] = value; +} + + +docstring const & InsetCommand::getParam(string const & name) const +{ + return p_[name]; +} + + void InsetCommand::setParams(InsetCommandParams const & p) { p_ = p; - updateButtonLabel_ = true; + initView(); } -int InsetCommand::latex(Buffer const &, odocstream & os, - OutputParams const &) const +void InsetCommand::latex(otexstream & os, OutputParams const & runparams_in) const { - os << getCommand(); - return 0; + OutputParams runparams = runparams_in; + docstring command = getCommand(runparams); + if (buffer().params().use_minted + && prefixIs(command, from_ascii("\\lstlistoflistings"))) + command.erase(1, 3); + os << command; } -int InsetCommand::plaintext(Buffer const & buf, odocstream & os, - OutputParams const &) const +int InsetCommand::plaintext(odocstringstream & os, + OutputParams const &, size_t) const { - docstring const str = "[" + buf.B_("LaTeX Command: ") + from_utf8(getCmdName()) + "]"; + docstring const str = "[" + buffer().B_("LaTeX Command: ") + + from_utf8(getCmdName()) + "]"; os << str; return str.size(); } -int InsetCommand::docbook(Buffer const &, odocstream &, - OutputParams const &) const +int InsetCommand::docbook(odocstream &, OutputParams const &) const { return 0; } -void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd) +void InsetCommand::validate(LaTeXFeatures & features) const { - switch (cmd.action) { - case LFUN_INSET_REFRESH: - updateButtonLabel_ = true; - break; + if (params().info().hasParam("literal") + && params()["literal"] == "true") + return; + + ParamInfo::const_iterator it = params().info().begin(); + ParamInfo::const_iterator end = params().info().end(); + for (; it != end; ++it) { + if (it->handling() == ParamInfo::HANDLING_LATEXIFY) { + docstring const text = params()[it->name()]; + // Validate the contents (if we LaTeXify, specific + // macros might require packages) + for (pos_type i = 0; i < int(text.size()) ; ++i) + BufferEncodings::validate(text[i], features); + } + } +} + +void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd) +{ + switch (cmd.action()) { case LFUN_INSET_MODIFY: { - InsetCommandParams p(p_.insetType()); - InsetCommandMailer::string2params(mailer_name_, to_utf8(cmd.argument()), p); + if (cmd.getArg(0) == "changetype") { + cur.recordUndo(); + p_.setCmdName(cmd.getArg(1)); + cur.forceBufferUpdate(); + initView(); + break; + } + InsetCommandParams p(p_.code()); + InsetCommand::string2params(to_utf8(cmd.argument()), p); if (p.getCmdName().empty()) - cur.noUpdate(); - else + cur.noScreenUpdate(); + else { + cur.recordUndo(); setParams(p); + } + // FIXME We might also want to check here if this one is in the TOC. + // But I think most of those are labeled. + if (isLabeled()) + cur.forceBufferUpdate(); break; } case LFUN_INSET_DIALOG_UPDATE: { string const name = to_utf8(cmd.argument()); - InsetCommandMailer(name, *this).updateDialog(&cur.bv()); - break; - } - - case LFUN_MOUSE_RELEASE: { - if (!cur.selection()) - edit(cur, true); + cur.bv().updateDialog(name, params2string(params())); break; } @@ -144,86 +229,188 @@ void InsetCommand::doDispatch(Cursor & cur, FuncRequest & cmd) bool InsetCommand::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & status) const { - switch (cmd.action) { + switch (cmd.action()) { // suppress these case LFUN_ERT_INSERT: - status.enabled(false); + status.setEnabled(false); return true; + // we handle these - case LFUN_INSET_REFRESH: case LFUN_INSET_MODIFY: + if (cmd.getArg(0) == "changetype") { + string const newtype = cmd.getArg(1); + status.setEnabled(p_.isCompatibleCommand(p_.code(), newtype)); + status.setOnOff(newtype == p_.getCmdName()); + } + status.setEnabled(true); + return true; + case LFUN_INSET_DIALOG_UPDATE: - status.enabled(true); + status.setEnabled(true); return true; + default: return Inset::getStatus(cur, cmd, status); } } -void InsetCommand::edit(Cursor & cur, bool) +string InsetCommand::contextMenuName() const { - if (!mailer_name_.empty()) - InsetCommandMailer(mailer_name_, *this).showDialog(&cur.bv()); + return "context-" + insetName(p_.code()); } -void InsetCommand::replaceContents(std::string const & from, string const & to) +bool InsetCommand::showInsetDialog(BufferView * bv) const { - if (getContents() == from) - setContents(to); -} - - -InsetCommandMailer::InsetCommandMailer( - string const & name, InsetCommand & inset) - : name_(name), inset_(inset) -{} - - -string const InsetCommandMailer::inset2string(Buffer const &) const -{ - return params2string(name(), inset_.params()); + if (p_.code() != NO_CODE) + bv->showDialog(insetName(p_.code()), params2string(p_), + const_cast(this)); + return true; } -void InsetCommandMailer::string2params( - string const & name, string const & in, InsetCommandParams & params) +bool InsetCommand::string2params(string const & data, + InsetCommandParams & params) { params.clear(); - if (in.empty()) - return; - - istringstream data(in); - Lexer lex(0,0); - lex.setStream(data); - - string n; - lex >> n; - if (!lex || n != name) - return print_mailer_error("InsetCommandMailer", in, 1, name); - - // This is part of the inset proper that is usually swallowed - // by Text::readInset - string id; - lex >> id; - if (!lex || id != "CommandInset") - return print_mailer_error("InsetCommandMailer", in, 2, "LatexCommand"); - + if (data.empty()) + return false; + // This happens when inset-insert is called without argument except for the + // inset type; ex: + // "inset-insert toc" + string const name = insetName(params.code()); + if (data == name) + return true; + istringstream dstream(data); + Lexer lex; + lex.setStream(dstream); + lex.setContext("InsetCommand::string2params"); + lex >> name.c_str(); // check for name + lex >> "CommandInset"; params.read(lex); + return true; } -string const -InsetCommandMailer::params2string(string const & name, - InsetCommandParams const & params) +string InsetCommand::params2string(InsetCommandParams const & params) { ostringstream data; - data << name << ' '; + data << insetName(params.code()) << ' '; params.write(data); data << "\\end_inset\n"; return data.str(); } +bool decodeInsetParam(string const & name, string & data, + Buffer const & buffer) +{ + InsetCode const code = insetCode(name); + switch (code) { + case BIBITEM_CODE: + case BIBTEX_CODE: + case INDEX_PRINT_CODE: + case LABEL_CODE: + case LINE_CODE: + case NOMENCL_CODE: + case NOMENCL_PRINT_CODE: + case REF_CODE: + case TOC_CODE: + case HYPERLINK_CODE: { + InsetCommandParams p(code); + data = InsetCommand::params2string(p); + break; + } + case INCLUDE_CODE: { + // data is the include type: one of "include", + // "input", "verbatiminput" or "verbatiminput*" + if (data.empty()) + // default type is requested + data = "include"; + InsetCommandParams p(INCLUDE_CODE, data); + data = InsetCommand::params2string(p); + break; + } + case BOX_CODE: { + // \c data == "Boxed" || "Frameless" etc + InsetBoxParams p(data); + data = InsetBox::params2string(p); + break; + } + case BRANCH_CODE: { + InsetBranchParams p; + data = InsetBranch::params2string(p); + break; + } + case CITE_CODE: { + InsetCommandParams p(CITE_CODE); + data = InsetCommand::params2string(p); + break; + } + case ERT_CODE: { + data = InsetERT::params2string(InsetCollapsible::Open); + break; + } + case EXTERNAL_CODE: { + InsetExternalParams p; + data = InsetExternal::params2string(p, buffer); + break; + } + case FLOAT_CODE: { + InsetFloatParams p; + data = InsetFloat::params2string(p); + break; + } + case INDEX_CODE: { + InsetIndexParams p; + data = InsetIndex::params2string(p); + break; + } + case LISTINGS_CODE: { + InsetListingsParams p; + data = InsetListings::params2string(p); + break; + } + case GRAPHICS_CODE: { + InsetGraphicsParams p; + data = InsetGraphics::params2string(p, buffer); + break; + } + case MATH_SPACE_CODE: { + InsetSpaceParams p(true); + data = InsetSpace::params2string(p); + break; + } + case NOTE_CODE: { + InsetNoteParams p; + data = InsetNote::params2string(p); + break; + } + case PHANTOM_CODE: { + InsetPhantomParams p; + data = InsetPhantom::params2string(p); + break; + } + case SPACE_CODE: { + InsetSpaceParams p; + data = InsetSpace::params2string(p); + break; + } + case VSPACE_CODE: { + VSpace space; + data = InsetVSpace::params2string(space); + break; + } + case WRAP_CODE: { + InsetWrapParams p; + data = InsetWrap::params2string(p); + break; + } + default: + return false; + } // end switch(code) + return true; +} + } // namespace lyx