Bo Peng schrieb:
The attached patch overkills these bugs
Confirmed.
so it may introduce some new bugs.
I couldn't find new bugs. While searching for bugs I found these two Bug 3725: http://bugzilla.lyx.org/show_bug.cgi?id=3725 and bug 3726: http://bugzilla.lyx.org/show_bug.cgi?id=3726 but they were both introduced by the patch that implemented the language dialects. So I give an OK to commit this patch. Attached is a Bo's patch but changed so that can be applied. regards Uwe
Index: src/insets/InsetListingsParams.h =================================================================== --- src/insets/InsetListingsParams.h (revision 18476) +++ src/insets/InsetListingsParams.h (working copy) @@ -12,7 +12,7 @@ #ifndef INSETLISTINGSPARAMS_H #define INSETLISTINGSPARAMS_H -#include <vector> +#include <map> #include <exception> #include "Lexer.h" #include "InsetCollapsable.h" @@ -35,7 +35,7 @@ void read(Lexer &); /// valid parameter string - std::string params() const { return params_; } + std::string params(std::string sep=",") const; /// add key=value to params_ void addParam(std::string const & key, std::string const & value); @@ -79,13 +79,9 @@ /// inline or normal listings bool inline_; - /// listing parameters, this will always be a *valid* string - /// that can be passed to listing packages. - std::string params_; + /// key-value pairs of the parameters + std::map<std::string, std::string> params_; - /// keys defined in params_ - std::vector<std::string> keys_; - /// collapsable status InsetCollapsable::CollapseStatus status_; }; Index: src/insets/InsetInclude.cpp =================================================================== --- src/insets/InsetInclude.cpp (revision 18477) +++ src/insets/InsetInclude.cpp (working copy) @@ -551,7 +551,7 @@ // opt is set in QInclude dialog and should have passed validation. InsetListingsParams params(opt); if (!params.params().empty()) - os << "[" << from_utf8(params.encodedString()) << "]"; + os << "[" << from_utf8(params.params()) << "]"; os << '{' << from_utf8(incfile) << '}'; } else { runparams.exportdata->addExternalFile(tex_format, writefile, Index: src/insets/InsetListings.cpp =================================================================== --- src/insets/InsetListings.cpp (revision 18476) +++ src/insets/InsetListings.cpp (working copy) @@ -128,7 +128,7 @@ int InsetListings::latex(Buffer const & buf, odocstream & os, OutputParams const & runparams) const { - string param_string = params().encodedString(); + string param_string = params().params(); // NOTE: I use {} to quote text, which is an experimental feature // of the listings package (see page 25 of the manual) int lines = 0; Index: src/insets/InsetListingsParams.cpp =================================================================== --- src/insets/InsetListingsParams.cpp (revision 18476) +++ src/insets/InsetListingsParams.cpp (working copy) @@ -20,18 +20,23 @@ #include <boost/assert.hpp> #include "support/lstrings.h" +#include "support/textutils.h" #include "support/convert.h" +using std::map; using std::vector; using std::ostream; using std::string; using std::exception; using lyx::support::bformat; using lyx::support::trim; +using lyx::support::subst; using lyx::support::isStrInt; using lyx::support::prefixIs; using lyx::support::suffixIs; using lyx::support::getVectorFromString; +using lyx::isAlphaASCII; +using lyx::isDigit; namespace lyx { @@ -455,13 +460,13 @@ InsetListingsParams::InsetListingsParams() : - inline_(false), params_(), keys_(0), status_(InsetCollapsable::Open) + inline_(false), params_(), status_(InsetCollapsable::Open) { } InsetListingsParams::InsetListingsParams(string const & par, bool in, InsetCollapsable::CollapseStatus s) - : inline_(in), params_(), keys_(0), status_(s) + : inline_(in), params_(), status_(s) { // this will activate parameter validation. fromEncodedString(par); @@ -491,6 +496,22 @@ } +string InsetListingsParams::params(string sep) const +{ + string par; + for (map<string, string>::const_iterator it = params_.begin(); + it != params_.end(); ++it) { + if (!par.empty()) + par += sep; + if (it->second.empty()) + par += it->first; + else + par += it->first + '=' + it->second; + } + return par; +} + + void InsetListingsParams::addParam(string const & key, string const & value) { if (key.empty()) @@ -498,25 +519,33 @@ // exception may be thown. parValidator(key).validate(value); // duplicate parameters! - if (find(keys_.begin(), keys_.end(), key) != keys_.end()) + if (params_.find(key) != params_.end()) throw invalidParam(bformat(_("Parameter %1$s has already been defined"), from_utf8(key))); - else - keys_.push_back(key); - if (!params_.empty()) - params_ += ','; - if (value.empty()) - params_ += key; + // check onoff flag + size_t idx = 0; + while (listings_param_table[idx].name != key) + ++idx; + BOOST_ASSERT(listings_param_table[idx].name == key); + // onoff parameter with value false + if (listings_param_table[idx].onoff && (value == "false" || value == "{false}")) + params_[key] = string(); + // if the parameter is surrounded with {}, good + else if (prefixIs(value, "{") && suffixIs(value, "}")) + params_[key] = value; + // otherwise, check if {} is needed. Add {} to all values with + // non-ascii/number characters, just to be safe else { - // check onoff flag - size_t idx = 0; - while (listings_param_table[idx].name != key) - ++idx; - BOOST_ASSERT(listings_param_table[idx].name == key); - if (listings_param_table[idx].onoff && value == "false") - params_ += key; + bool has_special_char = false; + for (size_t i = 0; i < value.size(); ++i) + if (!isAlphaASCII(value[i]) && !isDigit(value[i])) { + has_special_char = true; + break; + } + if (has_special_char) + params_[key] = "{" + value + "}"; else - params_ += key + '=' + value; + params_[key] = value; } } @@ -546,7 +575,7 @@ continue; } else if (par[i] == '{' && par[i - 1] == '=') braces ++; - else if (par[i] == '}' && (i == par.size() - 1 || par[i + 1] == ',')) + else if (par[i] == '}' && (i == par.size() - 1 || par[i + 1] == ',' || par[i + 1] == '\n')) braces --; if (isValue) @@ -562,7 +591,6 @@ void InsetListingsParams::setParams(string const & par) { params_.clear(); - keys_.clear(); addParams(par); } @@ -570,74 +598,49 @@ string InsetListingsParams::encodedString() const { // Encode string! - // FIXME: - // '"' should be handled differently because it will - // terminate a lyx token. Right now, it is silently ignored. - string par; - for (size_t i = 0; i < params_.size(); ++i) { - BOOST_ASSERT(params_[i] != '\n'); - if (params_[i] != '"') - par += params_[i]; - } - return par; + // '"' is handled differently because it will + // terminate a lyx token. + string par = params(); + // '"' is now " ==> '"' is now &quot; + par = subst(par, "&", "&"); + // '"' is now &quot; ==> '"' is now &quot; + par = subst(par, "\"", """); + return par; } string InsetListingsParams::separatedParams(bool keepComma) const { - // , might be used as regular parameter option so - // the prcess might be more complicated than what I am doing here - string opt; - int braces = 0; - for (size_t i = 0; i < params_.size(); ++i) - if (params_[i] == ',' && braces == 0) { - if (keepComma) - opt += ",\n"; - else - opt += "\n"; - } else if (params_[i] == '{' && params_[i - 1] == '=') { - braces ++; - opt += params_[i]; - } else if (params_[i] == '}' && (i == params_.size() -1 || params_[i + 1] == ',')) { - braces --; - opt += params_[i]; - } else - opt += params_[i]; - return opt; + if (keepComma) + return params(",\n"); + else + return params("\n"); } void InsetListingsParams::fromEncodedString(string const & in) { - // Decode string! - // Do nothing because " was silently ignored. - setParams(in); + // Decode string! Reversal of encodedString + string par = in; + // '"' is now &quot; ==> '"' is now &quot; + par = subst(par, """, "\""); + // '"' is now &quot; ==> '"' is now " + par = subst(par, "&", "&"); + setParams(par); } bool InsetListingsParams::isFloat() const { - return find(keys_.begin(), keys_.end(), "float") != keys_.end(); + return params_.find("float") != params_.end(); } string InsetListingsParams::getParamValue(string const & param) const { // is this parameter defined? - if (find(keys_.begin(), keys_.end(), param) == keys_.end()) - return string(); - // if so, search for it - vector<string> pars = getVectorFromString(separatedParams(), "\n"); - for (vector<string>::iterator it = pars.begin(); it != pars.end(); ++it) - if (prefixIs(*it, param + "=")) { - string par = it->substr(param.size() + 1); - if (prefixIs(par, "{") && suffixIs(par, "}")) - return par.substr(1, par.size() - 2); - else - return par; - } - // if param= is not found, should be something like float, return "" - return string(); + map<string, string>::const_iterator it = params_.find(param); + return (it == params_.end()) ? string() : it->second; }