X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetCommandParams.cpp;h=a0cbd6e785be498fdc71b2ec85d1d54b55fc3245;hb=142caff8336c54627606c09d3ce5bb7de7a8adb6;hp=39b066bace83c53fdb2ae64e9d10e4526b2266f9;hpb=9d0ea8aeff32833a90b3fe64df0c5518a9e241be;p=lyx.git diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp index 39b066bace..a0cbd6e785 100644 --- a/src/insets/InsetCommandParams.cpp +++ b/src/insets/InsetCommandParams.cpp @@ -11,6 +11,7 @@ */ #include +#include #include "InsetCommandParams.h" @@ -18,7 +19,6 @@ #include "InsetBibtex.h" #include "InsetCitation.h" #include "InsetFloatList.h" -#include "InsetHFill.h" #include "InsetHyperlink.h" #include "InsetInclude.h" #include "InsetIndex.h" @@ -27,47 +27,31 @@ #include "InsetRef.h" #include "InsetTOC.h" -#include "support/debug.h" -#include "support/gettext.h" +#include "Encoding.h" #include "Lexer.h" +#include "OutputParams.h" +#include "frontends/alert.h" + +#include "support/debug.h" +#include "support/docstream.h" #include "support/ExceptionMessage.h" +#include "support/gettext.h" #include "support/lstrings.h" -#include "support/docstream.h" -#include +#include "support/lassert.h" -using std::string; +using namespace std; +using namespace lyx::support; namespace lyx { -using support::findToken; -using support::ExceptionMessage; -using support::WarningException; - -InsetCommandParams::InsetCommandParams(InsetCode code) - : insetCode_(code), preview_(false) -{ - cmdName_ = getDefaultCmd(code); - info_ = findInfo(code, cmdName_); - BOOST_ASSERT(info_); - params_.resize(info_->n); -} - - -InsetCommandParams::InsetCommandParams(InsetCode code, - string const & cmdName) - : insetCode_(code), cmdName_(cmdName), preview_(false) -{ - info_ = findInfo(code, cmdName); - BOOST_ASSERT(info_); - params_.resize(info_->n); -} - - -CommandInfo const * InsetCommandParams::findInfo( - InsetCode code, std::string const & cmdName) +/// Get information for \p code and command \p cmdName. +/// Returns 0 if the combination is not known. [FIXME: 0?] +/// Don't call this without first making sure the command name is +/// acceptable to the inset. +static ParamInfo const & findInfo(InsetCode code, string const & cmdName) { switch (code) { case BIBITEM_CODE: @@ -75,11 +59,9 @@ CommandInfo const * InsetCommandParams::findInfo( case BIBTEX_CODE: return InsetBibtex::findInfo(cmdName); case CITE_CODE: - return InsetCitation::findInfo(cmdName); + return InsetCitation::findInfo(cmdName); case FLOAT_LIST_CODE: return InsetFloatList::findInfo(cmdName); - case HFILL_CODE: - return InsetHFill::findInfo(cmdName); case HYPERLINK_CODE: return InsetHyperlink::findInfo(cmdName); case INCLUDE_CODE: @@ -87,7 +69,7 @@ CommandInfo const * InsetCommandParams::findInfo( case INDEX_PRINT_CODE: return InsetPrintIndex::findInfo(cmdName); case LABEL_CODE: - return InsetLabel::findInfo(cmdName); + return InsetLabel::findInfo(cmdName); case NOMENCL_CODE: return InsetNomencl::findInfo(cmdName); case NOMENCL_PRINT_CODE: @@ -97,13 +79,110 @@ CommandInfo const * InsetCommandParams::findInfo( case TOC_CODE: return InsetTOC::findInfo(cmdName); default: - BOOST_ASSERT(false); + LASSERT(false, /**/); } - return 0; + static const ParamInfo pi; + return pi; // to silence the warning +} + + +///////////////////////////////////////////////////////////////////// +// +// ParamInfo::ParamData +// +///////////////////////////////////////////////////////////////////// + +ParamInfo::ParamData::ParamData(std::string const & s, ParamType t, + ParamHandling h) + : name_(s), type_(t), handling_(h) +{} + + +bool ParamInfo::ParamData::isOptional() const +{ + return type_ == ParamInfo::LATEX_OPTIONAL; } -std::string InsetCommandParams::getDefaultCmd(InsetCode code) { +bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const +{ + return name() == rhs.name() && type() == rhs.type() + && handling() == rhs.handling(); +} + + +bool ParamInfo::hasParam(std::string const & name) const +{ + const_iterator it = begin(); + const_iterator last = end(); + for (; it != last; ++it) { + if (it->name() == name) + return true; + } + return false; +} + + +void ParamInfo::add(std::string const & name, ParamType type, + ParamHandling handling) +{ + info_.push_back(ParamData(name, type, handling)); +} + + +bool ParamInfo::operator==(ParamInfo const & rhs) const +{ + if (size() != rhs.size()) + return false; + return equal(begin(), end(), rhs.begin()); +} + + +ParamInfo::ParamData const & + ParamInfo::operator[](std::string const & name) const +{ + LASSERT(hasParam(name), /**/); + const_iterator it = begin(); + const_iterator last = end(); + for (; it != last; ++it) { + if (it->name() == name) + return *it; + } + return *it; // silence warning +} + + +///////////////////////////////////////////////////////////////////// +// +// InsetCommandParams +// +///////////////////////////////////////////////////////////////////// + + +InsetCommandParams::InsetCommandParams(InsetCode code) + : insetCode_(code), preview_(false) +{ + cmdName_ = getDefaultCmd(code); + info_ = findInfo(code, cmdName_); +} + + +InsetCommandParams::InsetCommandParams(InsetCode code, + string const & cmdName) + : insetCode_(code), cmdName_(cmdName), preview_(false) +{ + info_ = findInfo(code, cmdName); +} + + +std::string InsetCommandParams::insetType() const +{ + return insetName(insetCode_); +} + + +string InsetCommandParams::getDefaultCmd(InsetCode code) +{ switch (code) { case BIBITEM_CODE: return InsetBibitem::defaultCommand(); @@ -113,8 +192,6 @@ std::string InsetCommandParams::getDefaultCmd(InsetCode code) { return InsetCitation::defaultCommand(); case FLOAT_LIST_CODE: return InsetFloatList::defaultCommand(); - case HFILL_CODE: - return InsetHFill::defaultCommand(); case HYPERLINK_CODE: return InsetHyperlink::defaultCommand(); case INCLUDE_CODE: @@ -132,14 +209,13 @@ std::string InsetCommandParams::getDefaultCmd(InsetCode code) { case TOC_CODE: return InsetTOC::defaultCommand(); default: - BOOST_ASSERT(false); + LASSERT(false, /**/); } - return string(); //silence the warning + return string(); // silence the warning } -bool InsetCommandParams::isCompatibleCommand( - InsetCode code, std::string const & s) +bool InsetCommandParams::isCompatibleCommand(InsetCode code, string const & s) { switch (code) { case BIBITEM_CODE: @@ -150,8 +226,6 @@ bool InsetCommandParams::isCompatibleCommand( return InsetCitation::isCompatibleCommand(s); case FLOAT_LIST_CODE: return InsetFloatList::isCompatibleCommand(s); - case HFILL_CODE: - return InsetHFill::isCompatibleCommand(s); case HYPERLINK_CODE: return InsetHyperlink::isCompatibleCommand(s); case INCLUDE_CODE: @@ -169,76 +243,39 @@ bool InsetCommandParams::isCompatibleCommand( case TOC_CODE: return InsetTOC::isCompatibleCommand(s); default: - BOOST_ASSERT(false); + LASSERT(false, /**/); } - return false; //silence the warning + return false; // silence the warning } void InsetCommandParams::setCmdName(string const & name) { - if (!isCompatibleCommand(insetCode_, cmdName_)){ + if (!isCompatibleCommand(insetCode_, name)) { LYXERR0("InsetCommand: Incompatible command name " << name << "."); throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Incompatible command name.")); + _("Incompatible command name.")); } cmdName_ = name; - CommandInfo const * const info = findInfo(insetCode_, cmdName_); - if (!info) { - LYXERR0("Command '" << name << "' is not compatible with a '" << - insetType() << "' inset."); - return; - } - ParamVector params(info->n); - // Overtake parameters with the same name - for (size_t i = 0; i < info_->n; ++i) { - int j = findToken(info->paramnames, info_->paramnames[i]); - if (j >= 0) - params[j] = params_[i]; - } - info_ = info; - std::swap(params, params_); + info_ = findInfo(insetCode_, cmdName_); } void InsetCommandParams::read(Lexer & lex) { - if (lex.isOK()) { - lex.next(); - string const insetType = lex.getString(); - InsetCode const code = insetCode(insetType); - if (code != insetCode_) { - lex.printError("InsetCommand: Attempt to change type of parameters."); - throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Attempt to change type of parameters.")); - } - } - - if (lex.isOK()) { - lex.next(); - string const test = lex.getString(); - if (test != "LatexCommand") { - lex.printError("InsetCommand: no LatexCommand line found."); - throw ExceptionMessage(WarningException, _("InsetCommand error:"), - from_utf8("Can't find LatexCommand line.")); - } - } - lex.next(); - cmdName_ = lex.getString(); - if (!isCompatibleCommand(insetCode_, cmdName_)){ - lex.printError("InsetCommand: Incompatible command name " + cmdName_ + "."); - throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Incompatible command name.")); + lex.setContext("InsetCommandParams::read"); + lex >> insetName(insetCode_).c_str(); + lex >> "LatexCommand"; + lex >> cmdName_; + if (!isCompatibleCommand(insetCode_, cmdName_)) { + lex.printError("Incompatible command name " + cmdName_ + "."); + throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "), + _("Incompatible command name.")); } info_ = findInfo(insetCode_, cmdName_); - if (!info_) { - lex.printError("InsetCommand: Unknown inset name `$$Token'"); - throw ExceptionMessage(WarningException, - _("Unknown inset name: "), from_utf8(insetType())); - } string token; while (lex.isOK()) { @@ -251,14 +288,13 @@ void InsetCommandParams::read(Lexer & lex) preview_ = lex.getBool(); continue; } - int const i = findToken(info_->paramnames, token); - if (i >= 0) { + if (info_.hasParam(token)) { lex.next(true); - params_[i] = lex.getDocString(); + params_[token] = lex.getDocString(); } else { lex.printError("Unknown parameter name `$$Token' for command " + cmdName_); throw ExceptionMessage(WarningException, - _("Inset Command: ") + from_ascii(cmdName_), + _("InsetCommandParams: ") + from_ascii(cmdName_), _("Unknown parameter name: ") + from_utf8(token)); } } @@ -266,54 +302,133 @@ void InsetCommandParams::read(Lexer & lex) lex.printError("Missing \\end_inset at this point. " "Read: `$$Token'"); throw ExceptionMessage(WarningException, - _("Missing \\end_inset at this point."), - from_utf8(token)); + _("InsetCommandParams Error: "), + _("Missing \\end_inset at this point: ") + from_utf8(token)); } } -void InsetCommandParams::write(std::ostream & os) const +void InsetCommandParams::write(ostream & os) const { os << "CommandInset " << insetType() << '\n'; os << "LatexCommand " << cmdName_ << '\n'; if (preview_) os << "preview true\n"; - for (size_t i = 0; i < info_->n; ++i) - if (!params_[i].empty()) + ParamInfo::const_iterator it = info_.begin(); + ParamInfo::const_iterator end = info_.end(); + for (; it != end; ++it) { + std::string const & name = it->name(); + docstring const & data = (*this)[name]; + if (!data.empty()) { // FIXME UNICODE - os << info_->paramnames[i] << ' ' - << Lexer::quoteString(to_utf8(params_[i])) + os << name << ' ' + << Lexer::quoteString(to_utf8(data)) << '\n'; + } + } +} + + +bool InsetCommandParams::writeEmptyOptional(ParamInfo::const_iterator ci) const +{ + if (!ci->isOptional()) { + LASSERT(false, /**/); + } + ++ci; // we want to start with the next one + ParamInfo::const_iterator end = info_.end(); + for (; ci != end; ++ci) { + switch (ci->type()) { + case ParamInfo::LYX_INTERNAL: + break; + + case ParamInfo::LATEX_REQUIRED: + return false; + + case ParamInfo::LATEX_OPTIONAL: { + std::string const & name = ci->name(); + docstring const & data = (*this)[name]; + if (!data.empty()) + return true; + break; + } + + } //end switch + } + return false; +} + + + +docstring InsetCommandParams::prepareCommand(OutputParams const & runparams, + docstring const & command, + ParamInfo::ParamHandling handling) const +{ + docstring result; + if (handling == ParamInfo::HANDLING_LATEXIFY) { + docstring uncodable; + for (size_t n = 0; n < command.size(); ++n) { + try { + result += runparams.encoding->latexChar(command[n]); + } catch (EncodingException & /* e */) { + LYXERR0("Uncodable character in command inset!"); + if (runparams.dryrun) { + result += "<" + _("LyX Warning: ") + + _("uncodable character") + " '"; + result += docstring(1, command[n]); + result += "'>"; + } else + uncodable += command[n]; + } + } + if (!uncodable.empty()) { + // issue a warning about omitted characters + // FIXME: should be passed to the error dialog + frontend::Alert::warning(_("Uncodable characters"), + bformat(_("The following characters that are used in the inset %1$s are not\n" + "representable in the current encoding and therefore have been omitted:\n%2$s."), + from_utf8(insetType()), uncodable)); + } + } else if (handling == ParamInfo::HANDLING_ESCAPE) + result = escape(command); + else + result = command; + + return result; } -docstring const InsetCommandParams::getCommand() const +docstring InsetCommandParams::getCommand(OutputParams const & runparams) const { docstring s = '\\' + from_ascii(cmdName_); bool noparam = true; - for (size_t i = 0; i < info_->n; ++i) { - if (info_->optional[i]) { - if (params_[i].empty()) { - // We need to write this parameter even if - // it is empty if nonempty optional parameters - // follow before the next required parameter. - for (size_t j = i + 1; j < info_->n; ++j) { - if (!info_->optional[j]) - break; - if (!params_[j].empty()) { - s += "[]"; - noparam = false; - break; - } - } - } else { - s += '[' + params_[i] + ']'; - noparam = false; - } - } else { - s += '{' + params_[i] + '}'; + ParamInfo::const_iterator it = info_.begin(); + ParamInfo::const_iterator end = info_.end(); + for (; it != end; ++it) { + std::string const & name = it->name(); + switch (it->type()) { + case ParamInfo::LYX_INTERNAL: + break; + + case ParamInfo::LATEX_REQUIRED: { + docstring const & data = + prepareCommand(runparams, (*this)[name], it->handling()); + s += '{' + data + '}'; noparam = false; + break; } + case ParamInfo::LATEX_OPTIONAL: { + docstring const & data = + prepareCommand(runparams, (*this)[name], it->handling()); + if (!data.empty()) { + s += '[' + data + ']'; + noparam = false; + } else if (writeEmptyOptional(it)) { + s += "[]"; + noparam = false; + } + break; + } + } //end switch } if (noparam) // Make sure that following stuff does not change the @@ -323,52 +438,53 @@ docstring const InsetCommandParams::getCommand() const } -docstring const InsetCommandParams::getFirstNonOptParam() const +docstring InsetCommandParams::getFirstNonOptParam() const { - for (size_t i = 0; i < info_->n; ++i) - if (!info_->optional[i]) - return params_[i]; - BOOST_ASSERT(false); - return docstring(); + ParamInfo::const_iterator it = + find_if(info_.begin(), info_.end(), + not1(mem_fun_ref(&ParamInfo::ParamData::isOptional))); + if (it == info_.end()) { + LASSERT(false, return docstring()); + } + return (*this)[it->name()]; } docstring const & InsetCommandParams::operator[](string const & name) const { - int const i = findToken(info_->paramnames, name); - BOOST_ASSERT(i >= 0); - return params_[i]; + static const docstring dummy; //so we don't return a ref to temporary + LASSERT(info_.hasParam(name), return dummy); + ParamMap::const_iterator data = params_.find(name); + if (data == params_.end() || data->second.empty()) + return dummy; + return data->second; } docstring & InsetCommandParams::operator[](string const & name) { - int const i = findToken(info_->paramnames, name); - BOOST_ASSERT(i >= 0); - return params_[i]; + LASSERT(info_.hasParam(name), /**/); + return params_[name]; } void InsetCommandParams::clear() { - for (size_t i = 0; i < info_->n; ++i) - params_[i].clear(); + params_.clear(); } -bool operator==(InsetCommandParams const & o1, - InsetCommandParams const & o2) +bool operator==(InsetCommandParams const & o1, InsetCommandParams const & o2) { - return o1.insetCode_ == o2.insetCode_ && - o1.cmdName_ == o2.cmdName_ && - o1.info_ == o2.info_ && - o1.params_ == o2.params_ && - o1.preview_ == o2.preview_; + return o1.insetCode_ == o2.insetCode_ + && o1.cmdName_ == o2.cmdName_ + && o1.info_ == o2.info_ + && o1.params_ == o2.params_ + && o1.preview_ == o2.preview_; } -bool operator!=(InsetCommandParams const & o1, - InsetCommandParams const & o2) +bool operator!=(InsetCommandParams const & o1, InsetCommandParams const & o2) { return !(o1 == o2); }