X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetCommandParams.cpp;h=bb4882874af1b0220dba13776023ab8e34f1250e;hb=2906a35663b92030b0668a42ab370dba8ffca4cf;hp=f1804a29d9cefb8762b56064b5b86a08d86c0944;hpb=8e9410b3d034178f5e391c6cfffca3d65afe59ff;p=lyx.git diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp index f1804a29d9..bb4882874a 100644 --- a/src/insets/InsetCommandParams.cpp +++ b/src/insets/InsetCommandParams.cpp @@ -11,6 +11,7 @@ */ #include +#include #include "InsetCommandParams.h" @@ -18,45 +19,106 @@ #include "InsetBibtex.h" #include "InsetCitation.h" #include "InsetFloatList.h" -#include "InsetHFill.h" #include "InsetHyperlink.h" #include "InsetInclude.h" #include "InsetIndex.h" #include "InsetLabel.h" +#include "InsetLine.h" #include "InsetNomencl.h" #include "InsetRef.h" #include "InsetTOC.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 namespace std; using namespace lyx::support; + namespace lyx { -ParamInfo::ParamData::ParamData(std::string const & s, bool b) : - name_(s), optional_(b) +/// 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: + return InsetBibitem::findInfo(cmdName); + case BIBTEX_CODE: + return InsetBibtex::findInfo(cmdName); + case CITE_CODE: + return InsetCitation::findInfo(cmdName); + case FLOAT_LIST_CODE: + return InsetFloatList::findInfo(cmdName); + case HYPERLINK_CODE: + return InsetHyperlink::findInfo(cmdName); + case INCLUDE_CODE: + return InsetInclude::findInfo(cmdName); + case INDEX_PRINT_CODE: + return InsetPrintIndex::findInfo(cmdName); + case LABEL_CODE: + return InsetLabel::findInfo(cmdName); + case LINE_CODE: + return InsetLine::findInfo(cmdName); + case NOMENCL_CODE: + return InsetNomencl::findInfo(cmdName); + case NOMENCL_PRINT_CODE: + return InsetPrintNomencl::findInfo(cmdName); + case REF_CODE: + return InsetRef::findInfo(cmdName); + case TOC_CODE: + return InsetTOC::findInfo(cmdName); + default: + LASSERT(false, /**/); + } + static 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; +} + + bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const { - return name() == rhs.name() && isOptional() == rhs.isOptional(); + return name() == rhs.name() && type() == rhs.type() + && handling() == rhs.handling(); } bool ParamInfo::hasParam(std::string const & name) const { const_iterator it = begin(); - for (; it != end(); ++it) { + const_iterator last = end(); + for (; it != last; ++it) { if (it->name() == name) return true; } @@ -64,36 +126,42 @@ bool ParamInfo::hasParam(std::string const & name) const } -void ParamInfo::add(std::string const & name, bool opt) +void ParamInfo::add(std::string const & name, ParamType type, + ParamHandling handling) { - info_.push_back(ParamData(name, opt)); + info_.push_back(ParamData(name, type, handling)); } bool ParamInfo::operator==(ParamInfo const & rhs) const { - // the idea here is to check each ParamData for equality - const_iterator itL = begin(); - const_iterator itR = rhs.begin(); - const_iterator endL = end(); - const_iterator endR = rhs.end(); - while (true) { - // if they both end together, return true - if (itL == endL && itR == endR) - return true; - // but if one ends before the other, return false - if (itL == endL || itR == endR) - return false; - //check this one for equality - if (*itL != *itR) - return false; - // equal, so check the next one - ++itL; - ++itR; + 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) { @@ -110,45 +178,14 @@ InsetCommandParams::InsetCommandParams(InsetCode code, } -ParamInfo const & InsetCommandParams::findInfo( - InsetCode code, string const & cmdName) +std::string InsetCommandParams::insetType() const { - switch (code) { - case BIBITEM_CODE: - return InsetBibitem::findInfo(cmdName); - case BIBTEX_CODE: - return InsetBibtex::findInfo(cmdName); - case CITE_CODE: - 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: - return InsetInclude::findInfo(cmdName); - case INDEX_PRINT_CODE: - return InsetPrintIndex::findInfo(cmdName); - case LABEL_CODE: - return InsetLabel::findInfo(cmdName); - case NOMENCL_CODE: - return InsetNomencl::findInfo(cmdName); - case NOMENCL_PRINT_CODE: - return InsetPrintNomencl::findInfo(cmdName); - case REF_CODE: - return InsetRef::findInfo(cmdName); - case TOC_CODE: - return InsetTOC::findInfo(cmdName); - default: - BOOST_ASSERT(false); - } - static const ParamInfo pi; - return pi; // to silence the warning + return insetName(insetCode_); } -string InsetCommandParams::getDefaultCmd(InsetCode code) { +string InsetCommandParams::getDefaultCmd(InsetCode code) +{ switch (code) { case BIBITEM_CODE: return InsetBibitem::defaultCommand(); @@ -158,8 +195,6 @@ 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: @@ -168,6 +203,8 @@ string InsetCommandParams::getDefaultCmd(InsetCode code) { return InsetPrintIndex::defaultCommand(); case LABEL_CODE: return InsetLabel::defaultCommand(); + case LINE_CODE: + return InsetLine::defaultCommand(); case NOMENCL_CODE: return InsetNomencl::defaultCommand(); case NOMENCL_PRINT_CODE: @@ -177,14 +214,13 @@ string InsetCommandParams::getDefaultCmd(InsetCode code) { case TOC_CODE: return InsetTOC::defaultCommand(); default: - BOOST_ASSERT(false); + LASSERT(false, /**/); } return string(); // silence the warning } -bool InsetCommandParams::isCompatibleCommand( - InsetCode code, string const & s) +bool InsetCommandParams::isCompatibleCommand(InsetCode code, string const & s) { switch (code) { case BIBITEM_CODE: @@ -195,8 +231,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: @@ -205,6 +239,8 @@ bool InsetCommandParams::isCompatibleCommand( return InsetPrintIndex::isCompatibleCommand(s); case LABEL_CODE: return InsetLabel::isCompatibleCommand(s); + case LINE_CODE: + return InsetLine::isCompatibleCommand(s); case NOMENCL_CODE: return InsetNomencl::isCompatibleCommand(s); case NOMENCL_PRINT_CODE: @@ -214,7 +250,7 @@ bool InsetCommandParams::isCompatibleCommand( case TOC_CODE: return InsetTOC::isCompatibleCommand(s); default: - BOOST_ASSERT(false); + LASSERT(false, /**/); } return false; // silence the warning } @@ -222,7 +258,7 @@ bool InsetCommandParams::isCompatibleCommand( 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: "), @@ -236,30 +272,12 @@ void InsetCommandParams::setCmdName(string const & name) 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("InsetCommandParams: Attempt to change type of inset."); - throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "), - _("Attempt to change type of parameters.")); - } - } - - if (lex.isOK()) { - lex.next(); - string const test = lex.getString(); - if (test != "LatexCommand") { - lex.printError("InsetCommandParams: No LatexCommand line found."); - throw ExceptionMessage(WarningException, _("InsetCommandParams error:"), - _("Can't find LatexCommand line.")); - } - } - lex.next(); - cmdName_ = lex.getString(); - if (!isCompatibleCommand(insetCode_, cmdName_)){ - lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + "."); + 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.")); } @@ -291,8 +309,8 @@ 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)); } } @@ -318,7 +336,88 @@ void InsetCommandParams::write(ostream & os) const } -docstring const InsetCommandParams::getCommand() const +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; + switch (handling) { + case ParamInfo::HANDLING_LATEXIFY: { + docstring uncodable; + for (size_t n = 0; n < command.size(); ++n) { + try { + char_type const c = command[n]; + docstring const latex = runparams.encoding->latexChar(c); + result += latex; + if (latex.length() > 1 && latex[latex.length() - 1] != '}') { + // Prevent eating of a following + // space or command corruption by + // following characters + result += "{}"; + } + } 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)); + } + break; + } + case ParamInfo::HANDLING_ESCAPE: + result = escape(command); + break; + case ParamInfo::HANDLING_NONE: + result = command; + break; + } // switch + + return result; +} + + +docstring InsetCommandParams::getCommand(OutputParams const & runparams) const { docstring s = '\\' + from_ascii(cmdName_); bool noparam = true; @@ -326,33 +425,30 @@ docstring const InsetCommandParams::getCommand() const ParamInfo::const_iterator end = info_.end(); for (; it != end; ++it) { std::string const & name = it->name(); - docstring const & data = (*this)[name]; - if (!it->isOptional()) { + 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; - continue; - } - if (!data.empty()) { - s += '[' + data + ']'; - noparam = false; - continue; + break; } - // This param is therefore optional but empty. - // But we need to write it anyway if nonempty - // optional parameters follow before the next - // required parameter. - ParamInfo::const_iterator it2 = it; - for (++it2; it2 != end; ++it2) { - if (!it2->isOptional()) - break; - std::string const & name2 = it2->name(); - docstring const & data2 = (*this)[name2]; - if (!data2.empty()) { - s += "[]"; + case ParamInfo::LATEX_OPTIONAL: { + docstring const data = + prepareCommand(runparams, (*this)[name], it->handling()); + if (!data.empty()) { + s += '[' + data + ']'; noparam = false; - break; + } else if (writeEmptyOptional(it)) { + s += "[]"; + noparam = false; } - } + break; + } + } //end switch } if (noparam) // Make sure that following stuff does not change the @@ -362,20 +458,14 @@ docstring const InsetCommandParams::getCommand() const } -namespace { - //predicate for what follows - bool paramIsNonOptional(ParamInfo::ParamData pi) - { - return !pi.isOptional(); - } -} - -docstring const InsetCommandParams::getFirstNonOptParam() const +docstring InsetCommandParams::getFirstNonOptParam() const { ParamInfo::const_iterator it = - find_if(info_.begin(), info_.end(), paramIsNonOptional); - if (it == info_.end()) - BOOST_ASSERT(false); + 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()]; } @@ -383,8 +473,7 @@ docstring const InsetCommandParams::getFirstNonOptParam() const docstring const & InsetCommandParams::operator[](string const & name) const { static const docstring dummy; //so we don't return a ref to temporary - if (!info_.hasParam(name)) - BOOST_ASSERT(false); + LASSERT(info_.hasParam(name), return dummy); ParamMap::const_iterator data = params_.find(name); if (data == params_.end() || data->second.empty()) return dummy; @@ -394,8 +483,7 @@ docstring const & InsetCommandParams::operator[](string const & name) const docstring & InsetCommandParams::operator[](string const & name) { - if (!info_.hasParam(name)) - BOOST_ASSERT(false); + LASSERT(info_.hasParam(name), /**/); return params_[name]; } @@ -406,19 +494,17 @@ void InsetCommandParams::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); }