/**
- * \file math_macrotemplate.C
+ * \file MathMacroTemplate.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
#include <config.h>
+#include "MathMacroTemplate.h"
+
#include "DocIterator.h"
#include "InsetMathBrace.h"
#include "InsetMathChar.h"
#include "InsetMathSqrt.h"
#include "MathMacro.h"
#include "MathMacroArgument.h"
-#include "MathMacroTemplate.h"
#include "MathStream.h"
#include "MathParser.h"
#include "MathSupport.h"
#include "Buffer.h"
#include "Color.h"
#include "Cursor.h"
-#include "debug.h"
+#include "support/debug.h"
#include "DispatchResult.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
-#include "gettext.h"
+#include "support/gettext.h"
#include "Lexer.h"
#include "Undo.h"
#include "frontends/Painter.h"
#include "support/convert.h"
+#include "support/docstream.h"
#include "support/lstrings.h"
-#include "debug.h"
-
-#include <boost/assert.hpp>
-#include <boost/bind.hpp>
-#include <boost/function.hpp>
+#include "support/debug.h"
#include <sstream>
+using namespace std;
namespace lyx {
using support::bformat;
-using std::ostream;
-using std::endl;
-
class InsetMathWrapper : public InsetMath {
public:
MathMacroTemplate::MathMacroTemplate()
- : InsetMathNest(3), numargs_(0), optionals_(0), type_(from_ascii("newcommand"))
+ : InsetMathNest(3), numargs_(0), optionals_(0),
+ type_(MacroTypeNewcommand)
{
initMath();
}
-MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs, int optionals,
- docstring const & type,
- std::vector<MathData> const & optionalValues,
- MathData const & def, MathData const & display)
-: InsetMathNest(optionals + 3), numargs_(numargs),
- optionals_(optionals), optionalValues_(optionalValues), type_(type)
+MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
+ int optionals, MacroType type,
+ vector<MathData> const & optionalValues,
+ MathData const & def, MathData const & display)
+ : InsetMathNest(optionals + 3), numargs_(numargs),
+ optionals_(optionals), optionalValues_(optionalValues),
+ type_(type)
{
initMath();
if (numargs_ > 9)
lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
- << numargs_ << std::endl;
+ << numargs_ << endl;
asArray(name, cell(0));
optionalValues_.resize(9);
MathMacroTemplate::MathMacroTemplate(docstring const & str)
- : InsetMathNest(3), numargs_(0)
+ : InsetMathNest(3), numargs_(0), optionals_(0),
+ type_(from_ascii("newcommand"))
{
initMath();
mathed_parse_cell(ar, str);
if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
lyxerr << "Cannot read macro from '" << ar << "'" << endl;
+ asArray(from_ascii("invalidmacro"), cell(0));
+ // FIXME: The macro template does not make sense after this.
+ // The whole parsing should not be in a constructor which
+ // has no chance to report failure.
return;
}
operator=( *(ar[0]->asMacroTemplate()) );
}
+void MathMacroTemplate::updateToContext(MacroContext const & mc) const
+{
+ redefinition_ = mc.get(name()) != 0;
+}
+
+
void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
{
FontSetChanger dummy1(mi.base, from_ascii("mathnormal"));
// valid macro?
MacroData const * macro = 0;
- if (validName() && mi.macrocontext.has(name())) {
- macro = &mi.macrocontext.get(name());
- if (type_ == from_ascii("newcommand") || type_ == from_ascii("renewcommand")) {
- // use the MacroData::redefinition_ information instead of MacroContext::has
- // because the macro is known here already anyway to detect recursive definitions
- type_ = macro->redefinition() ? from_ascii("renewcommand") : from_ascii("newcommand");
- }
+ if (validName()) {
+ macro = mi.macrocontext.get(name());
+
+ // updateToContext() - avoids another lookup
+ redefinition_ = macro != 0;
}
// create label "{#1}{#2}:="
defdim.width() + 16 + dspdim.width() + 2;
dim.asc = dim0.ascent();
- dim.asc = std::max(dim.asc, labeldim.ascent());
- dim.asc = std::max(dim.asc, defdim.ascent());
- dim.asc = std::max(dim.asc, dspdim.ascent());
+ dim.asc = max(dim.asc, labeldim.ascent());
+ dim.asc = max(dim.asc, defdim.ascent());
+ dim.asc = max(dim.asc, dspdim.ascent());
dim.des = dim0.descent();
- dim.des = std::max(dim.des, labeldim.descent());
- dim.des = std::max(dim.des, defdim.descent());
- dim.des = std::max(dim.des, dspdim.descent());
+ dim.des = max(dim.des, labeldim.descent());
+ dim.des = max(dim.des, defdim.descent());
+ dim.des = max(dim.des, dspdim.descent());
// make the name cell vertically centered, and 5 pixel lines margin
int real_asc = dim.asc - dim0.ascent() / 2;
int real_des = dim.des + dim0.ascent() / 2;
- dim.asc = std::max(real_asc, real_des) + dim0.ascent() / 2 + 5;
- dim.des = std::max(real_asc, real_des) - dim0.ascent() / 2 + 5;
-
+ dim.asc = max(real_asc, real_des) + dim0.ascent() / 2 + 5;
+ dim.des = max(real_asc, real_des) - dim0.ascent() / 2 + 5;
+
setDimCache(mi, dim);
}
void MathMacroTemplate::makeNonOptional(Cursor & cur) {
if (numargs_ > 0 && optionals_ > 0) {
--optionals_;
- optionalValues_[optionals_ - 1] = cell(optIdx(optionals_));
+
+ // store default value for later if the use changes his mind
+ optionalValues_[optionals_] = cell(optIdx(optionals_));
cells_.erase(cells_.begin() + optIdx(optionals_));
// fix cursor
void MathMacroTemplate::doDispatch(Cursor & cur, FuncRequest & cmd)
{
- std::string const arg = to_utf8(cmd.argument());
+ string const arg = to_utf8(cmd.argument());
switch (cmd.action) {
case LFUN_MATH_MACRO_ADD_PARAM:
break;
case LFUN_MATH_MACRO_REMOVE_OPTIONAL_PARAM:
- if (optionals_ > 0)
+ if (optionals_ > 0) {
+ cur.recordUndoFullDocument();
removeParameter(cur, optionals_ - 1);
- break;
+ } break;
case LFUN_MATH_MACRO_ADD_GREEDY_OPTIONAL_PARAM:
if (numargs_ == optionals_) {
}
-bool MathMacroTemplate::getStatus(Cursor & cur, FuncRequest const & cmd,
+bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd,
FuncStatus & flag) const
{
bool ret = true;
- std::string const arg = to_utf8(cmd.argument());
+ string const arg = to_utf8(cmd.argument());
switch (cmd.action) {
case LFUN_MATH_MACRO_ADD_PARAM: {
int num = numargs_ + 1;
if (arg.size() != 0)
num = convert<int>(arg);
- bool on = (num >= optionals_ && numargs_ < 9 && num <= numargs_ + 1);
+ bool on = (num >= optionals_
+ && numargs_ < 9 && num <= numargs_ + 1);
flag.enabled(on);
break;
}
}
case LFUN_MATH_MACRO_MAKE_OPTIONAL:
- flag.enabled(numargs_ > 0 && optionals_ < numargs_ && type_ != from_ascii("def"));
+ flag.enabled(numargs_ > 0
+ && optionals_ < numargs_
+ && type_ != MacroTypeDef);
break;
case LFUN_MATH_MACRO_MAKE_NONOPTIONAL:
- flag.enabled(optionals_ > 0 && type_ != from_ascii("def"));
+ flag.enabled(optionals_ > 0
+ && type_ != MacroTypeDef);
break;
case LFUN_MATH_MACRO_ADD_OPTIONAL_PARAM:
break;
case LFUN_MATH_MACRO_ADD_GREEDY_OPTIONAL_PARAM:
- flag.enabled(numargs_ == 0 && type_ != from_ascii("def"));
+ flag.enabled(numargs_ == 0
+ && type_ != MacroTypeDef);
break;
default:
}
-void MathMacroTemplate::write(Buffer const &, std::ostream & os) const
+void MathMacroTemplate::write(Buffer const &, ostream & os) const
{
odocstringstream oss;
WriteStream wi(oss, false, false);
void MathMacroTemplate::write(WriteStream & os) const
{
- if (type_ == "def") {
+ write(os, false);
+}
+
+
+void MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) const
+{
+ if (type_ == MacroTypeDef) {
os << "\\def\\" << name().c_str();
for (int i = 1; i <= numargs_; ++i)
os << '#' << i;
} else {
// newcommand or renewcommand
- os << "\\" << type_.c_str() << "{\\" << name().c_str() << '}';
+ if (redefinition_ && !overwriteRedefinition)
+ os << "\\renewcommand";
+ else
+ os << "\\newcommand";
+ os << "{\\" << name().c_str() << '}';
if (numargs_ > 0)
os << '[' << numargs_ << ']';
}
-MacroData MathMacroTemplate::asMacroData() const
+bool MathMacroTemplate::fixNameAndCheckIfValid()
+{
+ // check all the characters/insets in the name cell
+ size_t i = 0;
+ MathData & data = cell(0);
+ while (i < data.size()) {
+ InsetMathChar const * cinset = data[i]->asCharInset();
+ if (cinset) {
+ // valid character in [a-zA-Z]?
+ char_type c = cinset->getChar();
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')) {
+ ++i;
+ continue;
+ }
+ }
+
+ // throw cell away
+ data.erase(i);
+ }
+
+ // now it should be valid if anything in the name survived
+ return data.size() > 0;
+}
+
+
+void MathMacroTemplate::getDefaults(vector<docstring> & defaults) const
{
- std::vector<docstring> defaults(numargs_);
+ defaults.resize(numargs_);
for (int i = 0; i < optionals_; ++i)
- defaults[i] = asString(cell(optIdx(i)));
- return MacroData(asString(cell(defIdx())), defaults,
- numargs_, optionals_, asString(cell(displayIdx())), std::string());
+ defaults[i] = asString(cell(optIdx(i)));
+}
+
+
+docstring MathMacroTemplate::definition() const
+{
+ return asString(cell(defIdx()));
}
+docstring MathMacroTemplate::displayDefinition() const
+{
+ return asString(cell(displayIdx()));
+}
+
+
+size_t MathMacroTemplate::numArgs() const
+{
+ return numargs_;
+}
+
+
+size_t MathMacroTemplate::numOptionals() const
+{
+ return optionals_;
+}
+
} // namespace lyx