+bool testSumSymbol(MathAtom const & p)
+{
+ return testSymbol(p, "sum");
+}
+
+
+bool testSum(MathAtom const & at)
+{
+ return
+ testSumSymbol(at) ||
+ ( at->asScriptInset()
+ && at->asScriptInset()->nuc().size()
+ && testSumSymbol(at->asScriptInset()->nuc().back()) );
+}
+
+
+// replace '\sum' ['_^'] f(x) sequences by a real MathExIntInset
+// assume 'extractDelims' ran before
+void extractSums(MathArray & ar)
+{
+ // we need at least two items...
+ if (ar.size() < 2)
+ return;
+
+ //lyxerr << "\nSums from: " << ar << endl;
+ for (size_t i = 0; i + 1 < ar.size(); ++i) {
+ MathArray::iterator it = ar.begin() + i;
+
+ // is this a sum name?
+ if (!testSum(ar[i]))
+ continue;
+
+ // create a proper inset as replacement
+ auto_ptr<MathExIntInset> p(new MathExIntInset("sum"));
+
+ // collect lower bound and summation index
+ MathScriptInset const * sub = ar[i]->asScriptInset();
+ if (sub && sub->hasDown()) {
+ // try to figure out the summation index from the subscript
+ MathArray const & ar = sub->down();
+ MathArray::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) = MathArray(ar.begin(), xt);
+ p->cell(2) = MathArray(xt + 1, ar.end());
+ } else {
+ // use everything as summation 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
+ MathArray::iterator tt = extractArgument(p->cell(0), it + 1, ar.end());
+
+ // cleanup
+ ar.erase(it + 1, tt);
+ *it = MathAtom(p.release());
+ }
+ //lyxerr << "\nSums to: " << ar << endl;
+}
+
+
+//
+// search differential stuff
+//
+
+// tests for 'd' or '\partial'
+bool testDiffItem(MathAtom const & at)
+{
+ return testString(at, "d");
+}
+
+
+bool testDiffArray(MathArray const & ar)
+{
+ return ar.size() && testDiffItem(ar.front());
+}
+
+
+bool testDiffFrac(MathAtom const & at)
+{
+ return
+ at->asFracInset()
+ && testDiffArray(at->asFracInset()->cell(0))
+ && testDiffArray(at->asFracInset()->cell(1));
+}
+
+
+void extractDiff(MathArray & ar)
+{
+ //lyxerr << "\nDiffs from: " << ar << endl;
+ for (size_t i = 0; i < ar.size(); ++i) {
+ MathArray::iterator it = ar.begin() + i;
+
+ // is this a "differential fraction"?
+ if (!testDiffFrac(*it))
+ continue;
+
+ MathFracInset const * f = (*it)->asFracInset();
+ if (!f) {
+ lyxerr << "should not happen" << endl;
+ continue;
+ }
+
+ // create a proper diff inset
+ auto_ptr<MathDiffInset> diff(new MathDiffInset);
+
+ // collect function, let jt point behind last used item
+ MathArray::iterator jt = it + 1;
+ //int n = 1;
+ MathArray const & numer = f->cell(0);
+ if (numer.size() > 1 && numer[1]->asScriptInset()) {
+ // this is something like d^n f(x) / d... or d^n / d...
+ // FIXME
+ //n = 1;
+ if (numer.size() > 2)
+ diff->cell(0) = MathArray(numer.begin() + 2, numer.end());
+ else
+ jt = extractArgument(diff->cell(0), jt, ar.end());
+ } else {
+ // simply d f(x) / d... or d/d...
+ if (numer.size() > 1)
+ diff->cell(0) = MathArray(numer.begin() + 1, numer.end());
+ else
+ jt = extractArgument(diff->cell(0), jt, ar.end());
+ }
+
+ // collect denominator parts
+ MathArray const & denom = f->cell(1);
+ for (MathArray::const_iterator dt = denom.begin(); dt != denom.end();) {
+ // find the next 'd'
+ MathArray::const_iterator et
+ = find_if(dt + 1, denom.end(), &testDiffItem);
+
+ // point before this
+ MathArray::const_iterator st = et - 1;
+ MathScriptInset const * script = (*st)->asScriptInset();
+ if (script && script->hasUp()) {
+ // things like d.../dx^n
+ int mult = 1;
+ if (extractNumber(script->up(), mult)) {
+ //lyxerr << "mult: " << mult << endl;
+ for (int i = 0; i < mult; ++i)
+ diff->addDer(MathArray(dt + 1, st));
+ }
+ } else {
+ // just d.../dx
+ diff->addDer(MathArray(dt + 1, et));
+ }
+ dt = et;
+ }
+
+ // cleanup
+ ar.erase(it + 1, jt);
+ *it = MathAtom(diff.release());
+ }
+ //lyxerr << "\nDiffs to: " << ar << endl;
+}
+
+
+//
+// search limits
+//
+
+
+bool testRightArrow(MathAtom const & at)
+{
+ return testSymbol(at, "to") || testSymbol(at, "rightarrow");
+}
+
+
+
+// replace '\lim_{x->x0} f(x)' sequences by a real MathLimInset
+// assume 'extractDelims' ran before
+void extractLims(MathArray & ar)
+{
+ // we need at least three items...
+ if (ar.size() < 3)
+ return;
+
+ //lyxerr << "\nLimits from: " << ar << endl;
+ for (size_t i = 0; i + 2 < ar.size(); ++i) {
+ MathArray::iterator it = ar.begin() + i;
+
+ // is this a limit function?
+ if (!testSymbol(*it, "lim"))
+ continue;
+
+ // the next one must be a subscript (without superscript)
+ MathScriptInset const * sub = (*(it + 1))->asScriptInset();
+ if (!sub || !sub->hasDown() || sub->hasUp())
+ continue;
+
+ // and it must contain a -> symbol
+ MathArray const & s = sub->down();
+ MathArray::const_iterator st = find_if(s.begin(), s.end(), &testRightArrow);
+ if (st == s.end())
+ continue;
+
+ // the -> splits the subscript int x and x0
+ MathArray x = MathArray(s.begin(), st);
+ MathArray x0 = MathArray(st + 1, s.end());
+
+ // use something behind the script as core
+ MathArray f;
+ MathArray::iterator tt = extractArgument(f, it + 2, ar.end());
+
+ // cleanup
+ ar.erase(it + 1, tt);
+
+ // create a proper inset as replacement
+ *it = MathAtom(new MathLimInset(f, x, x0));
+ }
+ //lyxerr << "\nLimits to: " << ar << endl;
+}
+
+
+//
+// combine searches
+//
+