X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathMacro.cpp;h=144318130ae52bddf49208f234c6b78e2bd5f37d;hb=e709a6626e731b460a98ea34d762a776de90b54c;hp=4b5242e5fc93f23e66584bdcc7c8e91fc06cea23;hpb=e763f902443b863c49ab32e41ecb74672ab312bf;p=lyx.git diff --git a/src/mathed/InsetMathMacro.cpp b/src/mathed/InsetMathMacro.cpp index 4b5242e5fc..144318130a 100644 --- a/src/mathed/InsetMathMacro.cpp +++ b/src/mathed/InsetMathMacro.cpp @@ -64,6 +64,12 @@ public: asArray(def, def_); } /// + void setBuffer(Buffer & buffer) + { + Inset::setBuffer(buffer); + def_.setBuffer(buffer); + } + /// void setOwner(InsetMathMacro * mathMacro) { mathMacro_ = mathMacro; } /// InsetMathMacro const * owner() { return mathMacro_; } @@ -136,7 +142,7 @@ public: void afterDraw(PainterInfo const & pi) const { if (mathMacro_->editMetrics(pi.base.bv)) - pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend); + pi.pain.enterMonochromeMode(Color_mathmacroblend); } /// void metrics(MetricsInfo &, Dimension &) const { @@ -233,7 +239,7 @@ public: /// mutable std::map editing_; /// - std::string requires_; + std::string required_; /// update macro representation bool needsUpdate_; /// @@ -365,6 +371,38 @@ bool InsetMathMacro::addToMathRow(MathRow & mrow, MetricsInfo & mi) const return has_contents; } +/// Whether the inset allows \(no)limits +bool InsetMathMacro::allowsLimitsChange() const +{ + // similar to the code in mathClass(), except that we search for + // the right-side class. + MathClass mc = MC_UNKNOWN; + if (MacroData const * m = macroBackup()) { + // If it is a global macro and is defined explicitly + if (m->symbol()) + mc = string_to_class(m->symbol()->extra); + } + // Otherwise guess from the expanded macro + if (mc == MC_UNKNOWN) + mc = d->expanded_.lastMathClass(); + + return mc == MC_OP; +} + + +Limits InsetMathMacro::defaultLimits() const +{ + if (d->expanded_.empty()) + return NO_LIMITS; + // Guess from the expanded macro + InsetMath const * in = d->expanded_.back().nucleus(); + Limits const lim = in->limits() == AUTO_LIMITS + ? in->defaultLimits() : in->limits(); + LATTEST(lim != AUTO_LIMITS); + return lim; +} + + void InsetMathMacro::beforeMetrics() const { d->macro_->lock(); @@ -380,7 +418,7 @@ void InsetMathMacro::afterMetrics() const void InsetMathMacro::beforeDraw(PainterInfo const & pi) const { if (d->editing_[pi.base.bv]) - pi.pain.enterMonochromeMode(Color_mathbg, Color_mathmacroblend); + pi.pain.enterMonochromeMode(Color_mathmacroblend); } @@ -638,7 +676,7 @@ void InsetMathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc, d->nesting_ = nesting; // update requires - d->requires_ = d->macro_->requires(); + d->required_ = d->macro_->required(); if (!d->needsUpdate_ // non-normal mode? We are done! @@ -661,17 +699,21 @@ void InsetMathMacro::updateRepresentation(Cursor * cur, MacroContext const & mc, values[i].insert(0, MathAtom(proxy)); } // expanding macro with the values - // Only update the argument macros if anything was expanded, otherwise - // we would get an endless loop (bug 9140). UpdateLocker does not work - // in this case, since MacroData::expand() creates new InsetMathMacro - // objects, so this would be a different recursion path than the one - // protected by UpdateLocker. - if (d->macro_->expand(values, d->expanded_)) { + // Only update the argument macros if anything was expanded or the LyX + // representation part does not contain the macro itself, otherwise we + // would get an endless loop (bugs 9140 and 11595). UpdateLocker does + // not work in this case, since MacroData::expand() creates new + // InsetMathMacro objects, so this would be a different recursion path + // than the one protected by UpdateLocker. + docstring const & display = d->macro_->display(); + docstring const latexname = from_ascii("\\") + macroName(); + bool const ret = d->macro_->expand(values, d->expanded_); + d->expanded_.setBuffer(buffer()); + if (ret && !support::contains(display, latexname)) { if (utype == OutputUpdate && !d->expanded_.empty()) d->expanded_.updateMacros(cur, mc, utype, nesting); } // get definition for list edit mode - docstring const & display = d->macro_->display(); asArray(display.empty() ? d->macro_->definition() : display, d->definition_, Parse::QUIET | Parse::MACRODEF); } @@ -734,7 +776,7 @@ void InsetMathMacro::draw(PainterInfo & pi, int x, int y) const pi.pain.text(x, y, from_ascii(":"), labelFont); x += strw2; - // draw paramter + // draw parameter cell(i).draw(pi, x, y); // next line @@ -896,13 +938,13 @@ void InsetMathMacro::validate(LaTeXFeatures & features) const // instant preview is on for math, in which case we will be missing // the corresponding requirements. // In this case, we get the required info from the global macro table. - if (!d->requires_.empty()) - features.require(d->requires_); + if (!d->required_.empty()) + features.require(d->required_); else if (!d->macro_) { // Update requires for known global macros. MacroData const * data = MacroTable::globalMacros().get(name()); - if (data && !data->requires().empty()) - features.require(data->requires()); + if (data && !data->required().empty()) + features.require(data->required()); } if (name() == "binom") @@ -1101,14 +1143,24 @@ void InsetMathMacro::write(WriteStream & os) const // For correctly parsing it when a document is reloaded, we // need to enclose an optional argument in braces if it starts // with a script inset with empty nucleus or ends with a - // delimiter-size-modifier macro (see #10497 and #11346) + // delimiter-size-modifier macro (see #10497 and #11346). + // We also need to do that when the optional argument + // contains macros with optionals. bool braced = false; size_type last = cell(i).size() - 1; - if (cell(i).size() && cell(i)[last].nucleus()->asUnknownInset()) { - latexkeys const * l = in_word_set(cell(i)[last].nucleus()->name()); + if (cell(i).size() && cell(i)[last]->asUnknownInset()) { + latexkeys const * l = in_word_set(cell(i)[last]->name()); braced = (l && l->inset == "big"); - } else if (cell(i).size() && cell(i)[0].nucleus()->asScriptInset()) { - braced = cell(i)[0].nucleus()->asScriptInset()->nuc().empty(); + } else if (cell(i).size() && cell(i)[0]->asScriptInset()) { + braced = cell(i)[0]->asScriptInset()->nuc().empty(); + } else { + for (size_type j = 0; j < cell(i).size(); ++j) { + InsetMathMacro const * ma = cell(i)[j]->asMacro(); + if (ma && ma->optionals()) { + braced = true; + break; + } + } } if (braced) os << "[{" << cell(i) << "}]"; @@ -1135,6 +1187,9 @@ void InsetMathMacro::write(WriteStream & os) const // add space if there was no argument if (first) os.pendingSpace(true); + + // write \(no)limits modifiers if relevant + writeLimits(os); } @@ -1156,16 +1211,17 @@ void InsetMathMacro::mathematica(MathematicaStream & os) const } -void InsetMathMacro::mathmlize(MathStream & os) const +void InsetMathMacro::mathmlize(MathStream & ms) const { // macro_ is 0 if this is an unknown macro LATTEST(d->macro_ || d->displayMode_ != DISPLAY_NORMAL); if (d->macro_) { - docstring const xmlname = d->macro_->xmlname(); + docstring const xmlname = (ms.xmlMode()) ? d->macro_->xmlname() : d->macro_->htmlname(); if (!xmlname.empty()) { char const * type = d->macro_->MathMLtype(); - os << '<' << type << "> " << xmlname << " '; + ms << "<" << from_ascii(ms.namespacedTag(type)) << ">" + << xmlname + << ""; return; } } @@ -1173,7 +1229,7 @@ void InsetMathMacro::mathmlize(MathStream & os) const // this means that we do not recognize the macro throw MathExportException(); } - os << d->expanded_; + ms << d->expanded_; } @@ -1182,7 +1238,7 @@ void InsetMathMacro::htmlize(HtmlStream & os) const // macro_ is 0 if this is an unknown macro LATTEST(d->macro_ || d->displayMode_ != DISPLAY_NORMAL); if (d->macro_) { - docstring const xmlname = d->macro_->xmlname(); + docstring const xmlname = d->macro_->htmlname(); if (!xmlname.empty()) { os << ' ' << xmlname << ' '; return; @@ -1220,7 +1276,6 @@ bool InsetMathMacro::completionSupported(Cursor const & cur) const return InsetMathNest::completionSupported(cur); return lyxrc.completion_popup_math - && displayMode() == DISPLAY_UNFOLDED && cur.bv().cursor().pos() == int(name().size()); } @@ -1231,7 +1286,6 @@ bool InsetMathMacro::inlineCompletionSupported(Cursor const & cur) const return InsetMathNest::inlineCompletionSupported(cur); return lyxrc.completion_inline_math - && displayMode() == DISPLAY_UNFOLDED && cur.bv().cursor().pos() == int(name().size()); }