* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
- * \author André Pönitz
+ * \author André Pönitz
+ * \author Stefan Schimanski
*
* Full author contact details are available in file CREDITS.
*/
#include "frontends/Painter.h"
+#include "support/lassert.h"
#include "support/convert.h"
#include "support/debug.h"
#include "support/gettext.h"
int optionals, MacroType type,
vector<MathData> const & optionalValues,
MathData const & def, MathData const & display)
- : InsetMathNest(optionals + 3), numargs_(numargs), argsInLook_(0),
+ : InsetMathNest(optionals + 3), numargs_(numargs), argsInLook_(numargs),
optionals_(optionals), optionalValues_(optionalValues),
type_(type), lookOutdated_(true)
{
if (optionals_ > 0) {
look_.push_back(MathAtom(new InsetLabelBox(_("optional"), *this, false)));
+ MathData * optData = &look_[look_.size() - 1].nucleus()->cell(0);
for (; i < optionals_; ++i) {
- MathData * optData = &look_[look_.size() - 1].nucleus()->cell(0);
-
- // color it red, if it is to be remove when the cursor leaves
- if (optionals_ > argsInLook_) {
+ // color it light grey, if it is to be removed when the cursor leaves
+ if (i == argsInLook_) {
optData->push_back(MathAtom(
new InsetColoredCell(Color_mathbg, Color_mathmacrooldarg)));
- optData = &(*optData)[0].nucleus()->cell(0);
+ optData = &(*optData)[optData->size() - 1].nucleus()->cell(0);
}
optData->push_back(MathAtom(new InsetMathChar('[')));
pi.pain.rectangle(x, a, w, h, Color_mathframe);
// just to be sure: set some dummy values for coord cache
- for (idx_type i = 0; i < nargs(); ++i) {
+ for (idx_type i = 0; i < nargs(); ++i)
cell(i).setXY(*pi.base.bv, x, y);
- }
// draw contents
look_.draw(pi, x + 3, y);
// find this in cursor old
Cursor insetCur = old;
int scriptSlice = insetCur.find(this);
- BOOST_ASSERT(scriptSlice != -1);
+ LASSERT(scriptSlice != -1, /**/);
insetCur.cutOff(scriptSlice);
commitEditChanges(insetCur);
}
-void MathMacroTemplate::removeArguments(Cursor & cur, int from, int to) {
- for (DocIterator it = doc_iterator_begin(*this); it; it.forwardChar()) {
+void MathMacroTemplate::removeArguments(Cursor & cur, int from, int to)
+{
+ for (DocIterator it = doc_iterator_begin(&buffer(), this); it; it.forwardChar()) {
if (!it.nextInset())
continue;
if (it.nextInset()->lyxCode() != MATHMACROARG_CODE)
}
-void MathMacroTemplate::shiftArguments(size_t from, int by) {
- for (DocIterator it = doc_iterator_begin(*this); it; it.forwardChar()) {
+void MathMacroTemplate::shiftArguments(size_t from, int by)
+{
+ for (DocIterator it = doc_iterator_begin(&buffer(), this); it; it.forwardChar()) {
if (!it.nextInset())
continue;
if (it.nextInset()->lyxCode() != MATHMACROARG_CODE)
continue;
MathMacroArgument * arg = static_cast<MathMacroArgument*>(it.nextInset());
- if (arg->number() >= from + 1)
+ if (arg->number() >= int(from) + 1)
arg->setNumber(arg->number() + by);
}
int MathMacroTemplate::maxArgumentInDefinition() const
{
int maxArg = 0;
- MathMacroTemplate * nonConst = const_cast<MathMacroTemplate *>(this);
- DocIterator it = doc_iterator_begin(*nonConst);
+ DocIterator it = doc_iterator_begin(&buffer(), this);
it.idx() = defIdx();
for (; it; it.forwardChar()) {
if (!it.nextInset())
idx_type idx = cell(displayIdx()).empty() ? defIdx() : displayIdx();
// search for #n macros arguments
- DocIterator it = doc_iterator_begin(*this);
+ DocIterator it = doc_iterator_begin(&buffer(), this);
it.idx() = idx;
for (; it && it[0].idx() == idx; it.forwardChar()) {
if (!it.nextInset())
num = convert<int>(arg);
bool on = (num >= optionals_
&& numargs_ < 9 && num <= numargs_ + 1);
- flag.enabled(on);
+ flag.setEnabled(on);
break;
}
case LFUN_MATH_MACRO_APPEND_GREEDY_PARAM:
- flag.enabled(numargs_ < 9);
+ flag.setEnabled(numargs_ < 9);
break;
case LFUN_MATH_MACRO_REMOVE_PARAM: {
int num = numargs_;
if (arg.size() != 0)
num = convert<int>(arg);
- flag.enabled(num >= 1 && num <= numargs_);
+ flag.setEnabled(num >= 1 && num <= numargs_);
break;
}
case LFUN_MATH_MACRO_MAKE_OPTIONAL:
- flag.enabled(numargs_ > 0
+ flag.setEnabled(numargs_ > 0
&& optionals_ < numargs_
&& type_ != MacroTypeDef);
break;
case LFUN_MATH_MACRO_MAKE_NONOPTIONAL:
- flag.enabled(optionals_ > 0
+ flag.setEnabled(optionals_ > 0
&& type_ != MacroTypeDef);
break;
case LFUN_MATH_MACRO_ADD_OPTIONAL_PARAM:
- flag.enabled(numargs_ < 9);
+ flag.setEnabled(numargs_ < 9);
break;
case LFUN_MATH_MACRO_REMOVE_OPTIONAL_PARAM:
- flag.enabled(optionals_ > 0);
+ flag.setEnabled(optionals_ > 0);
break;
case LFUN_MATH_MACRO_ADD_GREEDY_OPTIONAL_PARAM:
- flag.enabled(numargs_ == 0
+ flag.setEnabled(numargs_ == 0
&& type_ != MacroTypeDef);
break;
case LFUN_IN_MATHMACROTEMPLATE:
- flag.enabled();
+ flag.setEnabled(true);
break;
default:
void MathMacroTemplate::write(ostream & os) const
{
odocstringstream oss;
- WriteStream wi(oss, false, false);
+ WriteStream wi(oss, false, false, false);
oss << "FormulaMacro\n";
write(wi);
os << to_utf8(oss.str());
void MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) const
{
- // newcommand or renewcommand
- if (os.latex() && optionals_ > 1)
- os << "\\newlyxcommand";
- else {
+ if (os.latex()) {
+ if (optionals_ > 0) {
+ // macros with optionals use the xargs package, e.g.:
+ // \newcommandx{\foo}[2][usedefault, addprefix=\global,1=default]{#1,#2}
+ // \long is implicit by xargs
+ if (redefinition_ && !overwriteRedefinition)
+ os << "\\renewcommandx";
+ else
+ os << "\\newcommandx";
+
+ os << "\\" << name()
+ << "[" << numargs_ << "]"
+ << "[usedefault, addprefix=\\global";
+ for (int i = 0; i < optionals_; ++i) {
+ docstring optValue = asString(cell(optIdx(i)));
+ if (optValue.find(']') != docstring::npos
+ || optValue.find(',') != docstring::npos)
+ os << ", " << i + 1 << "="
+ << "{" << cell(optIdx(i)) << "}";
+ else
+ os << ", " << i + 1 << "="
+ << cell(optIdx(i));
+ }
+ os << "]";
+ } else {
+ // Macros without optionals use standard _global_ \def macros:
+ // \global\def\long\foo#1#2{#1,#2}
+ // We use the \long prefix as this is the equivalent to \newcommand.
+ // We cannot use \newcommand directly because \global does not work with it.
+ os << "\\global\\long\\def\\" << name();
+ docstring param = from_ascii("#0");
+ for (int i = 1; i <= numargs_; ++i) {
+ param[1] = '0' + i;
+ os << param;
+ }
+ }
+ } else {
+ // in LyX output we use some pseudo syntax which is implementation
+ // independent, e.g.
+ // \newcommand{\foo}[2][default]{#1,#2}
if (redefinition_ && !overwriteRedefinition)
os << "\\renewcommand";
else
os << "\\newcommand";
- }
- os << "{\\" << name().c_str() << '}';
- if (numargs_ > 0)
- os << '[' << numargs_ << ']';
-
- // optional values
- for (int i = 0; i < optionals_; ++i) {
- docstring optValue = asString(cell(optIdx(i)));
- if (optValue.find(']') != docstring::npos)
- os << "[{" << cell(optIdx(i)) << "}]";
- else
- os << "[" << cell(optIdx(i)) << "]";
+ os << "{\\" << name() << '}';
+ if (numargs_ > 0)
+ os << '[' << numargs_ << ']';
+
+ for (int i = 0; i < optionals_; ++i) {
+ docstring optValue = asString(cell(optIdx(i)));
+ if (optValue.find(']') != docstring::npos)
+ os << "[{" << cell(optIdx(i)) << "}]";
+ else
+ os << "[" << cell(optIdx(i)) << "]";
+ }
}
os << "{" << cell(defIdx()) << "}";
void MathMacroTemplate::validate(LaTeXFeatures & features) const
{
- if (optionals_ > 1) {
- features.require("newlyxcommand");
- }
+ // we need global optional macro arguments. They are not available
+ // with \def, and \newcommand does not support global macros. So we
+ // are bound to xargs also for the single-optional-parameter case.
+ if (optionals_ > 0)
+ features.require("xargs");
}
void MathMacroTemplate::getDefaults(vector<docstring> & defaults) const
os << "Math Macro: \\" << name();
}
+
+docstring MathMacroTemplate::contextMenu(BufferView const &, int, int) const
+{
+ return from_ascii("context-math-macro-definition");
+}
+
} // namespace lyx