commit e743f6f6d3e57ae7e687e3e1adc964aadf23d3ee Author: Enrico Forestieri <for...@lyx.org> Date: Sun May 18 22:14:43 2025 +0200
Fix bug #13186 Correctly parse \prod constructs for maxima, mathematica and maple. --- src/mathed/InsetMathExInt.cpp | 6 ++++ src/mathed/MathExtern.cpp | 84 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/mathed/InsetMathExInt.cpp b/src/mathed/InsetMathExInt.cpp index 70d1ba1604..05a58d964b 100644 --- a/src/mathed/InsetMathExInt.cpp +++ b/src/mathed/InsetMathExInt.cpp @@ -75,6 +75,8 @@ void InsetMathExInt::maple(MapleStream & os) const { if (symbol_ == "int" || symbol_ == "intop") os << (os.maxima() ? "integrate(" : "int("); + else if (symbol_ == "prod") + os << "product("; else os << symbol_ << '('; @@ -100,6 +102,8 @@ void InsetMathExInt::maxima(MaximaStream & os) const { if (symbol_ == "int" || symbol_ == "intop") os << "integrate("; + else if (symbol_ == "prod") + os << "product("; else os << symbol_ << '('; @@ -119,6 +123,8 @@ void InsetMathExInt::mathematica(MathematicaStream & os) const os << "Integrate["; else if (symbol_ == "sum") os << "Sum["; + else if (symbol_ == "prod") + os << "Product["; else os << symbol_ << '['; diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp index 43ae76f0af..7834331216 100644 --- a/src/mathed/MathExtern.cpp +++ b/src/mathed/MathExtern.cpp @@ -372,9 +372,10 @@ void splitScripts(MathData & md) continue; if (script->nuc().size() == 1) { - // leave alone sums and integrals + // leave alone sums, prods and integrals MathAtom const & atom = script->nuc().front(); - if (testSymbol(atom, "sum") || testSymbol(atom, "int")) + if (testSymbol(atom, "sum") || testSymbol(atom, "int") + || testSymbol(atom, "prod")) continue; } @@ -842,6 +843,81 @@ void extractSums(MathData & md) } +// +// search prods +// + + +bool testProdSymbol(MathAtom const & p) +{ + return testSymbol(p, from_ascii("prod")); +} + + +bool testProd(MathAtom const & at) +{ + return + testProdSymbol(at) || + ( at->asScriptInset() + && !at->asScriptInset()->nuc().empty() + && testProdSymbol(at->asScriptInset()->nuc().back()) ); +} + + +// replace '\prod' ['_^'] f(x) sequences by a real InsetMathExInt +// assume 'extractDelims' ran before +void extractProds(MathData & md) +{ + // we need at least two items... + if (md.size() < 2) + return; + + Buffer * buf = md.buffer(); + + //lyxerr << "\nProds from: " << md << endl; + for (size_t i = 0; i + 1 < md.size(); ++i) { + MathData::iterator it = md.begin() + i; + + // is this a prod name? + if (!testProd(md[i])) + continue; + + // create a proper inset as replacement + auto p = make_unique<InsetMathExInt>(buf, from_ascii("prod")); + + // collect lower bound and summation index + InsetMathScript const * sub = md[i]->asScriptInset(); + if (sub && sub->hasDown()) { + // try to figure out the product index from the subscript + MathData const & ar = sub->down(); + MathData::const_iterator xt = + find_if(ar.begin(), ar.end(), &testEqualSign); + if (xt != ar.end()) { + // we found a '=', use everything in front of that as index, + // and everything behind as lower index + p->cell(1) = MathData(buf, ar.begin(), xt); + p->cell(2) = MathData(buf, xt + 1, ar.end()); + } else { + // use everything as product index, don't use scripts. + p->cell(1) = ar; + } + } + + // collect upper bound + if (sub && sub->hasUp()) + p->cell(3) = sub->up(); + + // use something behind the script as core + MathData::iterator tt = extractTerm(p->cell(0), it + 1, md.end()); + + // cleanup + md.erase(it + 1, tt); + *it = MathAtom(p.release()); + } + //lyxerr << "\nProds to: " << md << endl; +} + + // // search differential stuff // @@ -1021,8 +1097,10 @@ void extractStructure(MathData & md, ExternalMath kind) splitScripts(md); extractDelims(md); extractIntegrals(md, kind); - if (kind != MATHML && kind != HTML) + if (kind != MATHML && kind != HTML) { extractSums(md); + extractProds(md); + } extractNumbers(md); extractMatrices(md); if (kind != MATHML && kind != HTML) { -- lyx-cvs mailing list lyx-cvs@lists.lyx.org https://lists.lyx.org/mailman/listinfo/lyx-cvs