Oops, I forgot the changed files. Here they are.
Georg
/** * \file insetcommandparams.C * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Angus Leeming * * Full author contact details are available in file CREDITS. */ #include <config.h> #include "insetcommandparams.h" #include "debug.h" #include "lyxlex.h" using std::string; using std::pair; InsetCommandParams::InsetCommandParams() {} InsetCommandParams::InsetCommandParams(string const & n, string const & c, string const & o, string const & s, string const & sc) : cmdname(n), //contents(c), options(o), sec_options(s), sec_contents(sc), preview_(false) { if (!c.empty()) setContents(c); if (!sc.empty()) setSecContents(sc); if (!o.empty()) setOptions(o); if (!s.empty()) setSecOptions(s); } InsetCommandParams::InsetCommandParams(string const & n, vector<string> const & c, vector<string> const & o) : cmdname(n), contents_(c) , options_(o), preview_(false) { //TODO never tested, but should work!! :/ } //TODO apparently this function is only needed for insetBibItem.. remove after fix.. void InsetCommandParams::scanCommand(string const & cmd) { string tcmdname, toptions, tsecoptions, tcontents; if (cmd.empty()) return; enum { WS, CMDNAME, OPTION, SECOPTION, CONTENT } state = WS; // Used to handle things like \command[foo[bar]]{foo{bar}} int nestdepth = 0; for (string::size_type i = 0; i < cmd.length(); ++i) { char const c = cmd[i]; if ((state == CMDNAME && c == ' ') || (state == CMDNAME && c == '[') || (state == CMDNAME && c == '{')) { state = WS; } if ((state == OPTION && c == ']') || (state == SECOPTION && c == ']') || (state == CONTENT && c == '}')) { if (nestdepth == 0) { state = WS; } else { --nestdepth; } } if ((state == OPTION && c == '[') || (state == SECOPTION && c == '[') || (state == CONTENT && c == '{')) { ++nestdepth; } switch (state) { case CMDNAME: tcmdname += c; break; case OPTION: toptions += c; break; case SECOPTION: tsecoptions += c; break; case CONTENT: tcontents += c; break; case WS: { char const b = i? cmd[i-1]: 0; if (c == '\\') { state = CMDNAME; } else if (c == '[' && b != ']') { state = OPTION; nestdepth = 0; // Just to be sure } else if (c == '[' && b == ']') { state = SECOPTION; nestdepth = 0; // Just to be sure } else if (c == '{') { state = CONTENT; nestdepth = 0; // Just to be sure } break; } } } // Don't mess with this. if (!tcmdname.empty()) setCmdName(tcmdname); if (!toptions.empty()) setOptions(toptions); if (!tsecoptions.empty()) setSecOptions(tsecoptions); if (!tcontents.empty()) setContents(tcontents); if (lyxerr.debugging(Debug::PARSER)) lyxerr << "Command <" << cmd << "> == <" << getCommand() << "> == <" << getCmdName() << '|' << getContents() << '|' << getOptions() << '|' << getSecOptions() << '>' << endl; } void InsetCommandParams::read(LyXLex & lex) { string token; /////////////////////////////////////////////////////////////////////// // left for compatibility issues. remove if necessary!! if (lex.eatLine()) { token = lex.getString(); //scanCommand(token); } else { lex.printError("InsetCommand: Parse error: `$$Token'"); } /////////////////////////////////////////////////////////////////////// options_.clear(); contents_.clear(); while (lex.isOK()) { lex.next(); token = lex.getString(); if (token == "\\end_inset") break; if (token == "\\command_name") { lex.eatLine(); setCmdName(clearText(lex.getString())); } if (token == "\\add_contents") { lex.eatLine(); addContents(clearText(lex.getString())); } if (token == "\\add_options") { lex.eatLine(); addOptions(clearText(lex.getString())); } if (hasKey(token)) { lex.eatLine(); entrymap_.insert(pair<string,string>(token,clearText(lex.getString()))); } if (token == "preview") { lex.next(); preview_ = lex.getBool(); } } if (token != "\\end_inset") { lex.printError("Missing \\end_inset at this point. " "Read: `$$Token'"); } } // it is necessary to put the input into {}, since some options or contents // should be set even if it is null.. // nest depth stuff that was introduced in scanCommand should be avoided, // since user can enter an erroneous input like foo{boo . // It is not necessary to mix up things even more! :) string InsetCommandParams::clearText(string const & cmd) { return string(cmd, cmd.find_first_not_of('{', 0 ), cmd.find_last_not_of ('}', cmd.size())); } void InsetCommandParams::write(ostream & os) const { os << "LatexCommand " << getCommand() << "\n"; os << "\\command_name {" << getCmdName() << "}\n"; for (unsigned int ii = 0; ii < options_.size(); ++ii) os << "\\add_options {" << getOptions(ii) << "}\n"; for (unsigned int ii = 0; ii < contents_.size(); ++ii) os << "\\add_contents {" << getContents(ii) << "}\n"; } string const InsetCommandParams::getCommand() const { string s; if (!getCmdName().empty()) s += '\\' + getCmdName(); for (unsigned int ii = 0; ii < options_.size(); ++ii) s += '[' + getOptions(ii) + ']'; if (getNumContents() == 0) s += "{}"; for (unsigned int ii = 0; ii < contents_.size(); ++ii) s += '{' + getContents(ii) + '}'; return s; } bool operator==(InsetCommandParams const & o1, InsetCommandParams const & o2) { bool isequal = (o1.getNumOptions() == o2.getNumOptions()) && (o1.getNumContents() == o2.getNumContents()); for (int ii = 0; ii < o1.getNumOptions() && isequal; ++ii) isequal = o1.getOptions(ii) == o2.getOptions(ii); for (int ii = 0; ii < o1.getNumContents() && isequal; ++ii) isequal = o1.getContents(ii) == o2.getContents(ii); return isequal && (o1.getCmdName() == o2.getCmdName()); } bool operator!=(InsetCommandParams const & o1, InsetCommandParams const & o2) { return !(o1 == o2); }
// -*- C++ -*- /** * \file insetcommandparams.h * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Angus Leeming * * Full author contact details are available in file CREDITS. */ #ifndef INSETCOMMANDPARAMS_H #define INSETCOMMANDPARAMS_H #include <string> #include <iosfwd> #include <vector> #include <map> #include "debug.h" class LyXLex; using std::string; using std::endl; using std::ostream; using std::vector; using std::map; class InsetCommandParams { public: /// InsetCommandParams(); /// explicit InsetCommandParams(std::string const & n, std::string const & c = std::string(), std::string const & o = std::string(), std::string const & s = std::string(), std::string const & sc = std::string()); explicit InsetCommandParams(std::string const & n, std::vector<std::string> const & c, std::vector<std::string> const & o); /// void read(LyXLex &); ///Parse the command void scanCommand(std::string const &); /// void write(std::ostream &) const; /// std::string const & getCmdName() const { return cmdname; } /// std::string const & getOptions() const { return (options_.size()) ? options_[0] : null_str; } /// std::string const & getSecOptions() const { return (options_.size() > 1) ? options_[1] : null_str; } /// std::string const & getContents() const { return (contents_.size()) ? contents_[0] : null_str; } /// std::string const & getSecContents() const { return (contents_.size() > 1) ? contents_[1] : null_str; } /// int getNumOptions() const { return options_.size(); } /// int getNumContents() const { return contents_.size(); } /// void setCmdName(std::string const & n) { cmdname = n; } /// void setOptions(std::string const & c){ setElement(options_, 0, c); } /// void setSecOptions(std::string const & c) { setElement(options_, 1, c); } /// void setContents(std::string const & c) { setElement(contents_, 0, c); } /// void setSecContents(std::string const & s) { setElement(contents_, 1, s); } /// bool preview() const { return preview_; } /// void preview(bool p) { preview_ = p; } /// void addOptions(std::string const & o) { options_.push_back(o); } /// void addContents(std::string const & c) { contents_.push_back(c); } /// std::string const & getOptions(int i) const { return options_[i]; } /// std::string const & getContents(int i) const { return contents_[i]; } /// std::vector<std::string> getValuesForKeys(std::string const & v) /*TODO*/; /// std::string getValueForKeys(std::string const & v) { return (*(std::multimap<std::string,std::string>::iterator(entrymap_.find(v)))).first; } /// Build the complete LaTeX command std::string const getCommand() const; private: /// std::string clearText(std::string const &); /// bool hasKey(std::string const & k) {return !(find(keys_.begin() , keys_.end() ,k) == keys_.end());}; /// void setElement(std::vector<std::string> & , int , std::string const & c); /// std::string cmdname; /// std::string null_str; /// bool preview_; /// std::vector<std::string> contents_; /// std::vector<std::string> options_; /// std::vector<std::string> keys_; /// std::multimap<std::string,std::string> entrymap_; }; /// inline void InsetCommandParams::setElement(std::vector<std::string> & vec_, int ii, std::string const & c) { for (int i = vec_.size(); i <= ii; ++i) vec_.push_back(""); vec_[ii] = c; } /// bool operator==(InsetCommandParams const &, InsetCommandParams const &); /// bool operator!=(InsetCommandParams const &, InsetCommandParams const &); #endif