diff --git a/src/mathed/math_exintinset.C b/src/mathed/math_exintinset.C index 23758c6ee7..0a8c4979e5 100644 --- a/src/mathed/math_exintinset.C +++ b/src/mathed/math_exintinset.C @@ -6,9 +6,14 @@ MathExIntInset::MathExIntInset(string const & name) - : MathNestInset(2), symbol_(name), scripts_(new MathScriptInset) + : MathNestInset(4), symbol_(name) {} +// 0 - core +// 1 - diff +// 2 - lower +// 3 - upper + MathInset * MathExIntInset::clone() const { @@ -16,18 +21,6 @@ MathInset * MathExIntInset::clone() const } -void MathExIntInset::scripts(MathAtom const & at) -{ - scripts_ = at; -} - - -MathAtom & MathExIntInset::scripts() -{ - return scripts_; -} - - void MathExIntInset::symbol(string const & symbol) { symbol_ = symbol; @@ -37,17 +30,15 @@ void MathExIntInset::symbol(string const & symbol) bool MathExIntInset::hasScripts() const { // take empty upper bound as "no scripts" - return !scripts_->asScriptInset()->up().data_.empty(); + return !cell(3).empty(); } void MathExIntInset::normalize(NormalStream & os) const { - os << '[' << symbol_.c_str() << ' ' << cell(0) << ' ' << cell(1); - if (hasScripts()) - os << ' ' << scripts_.nucleus(); - os << ']'; + os << '[' << symbol_.c_str() << ' ' << cell(0) << ' ' << cell(1) << ' ' + << cell(2) << ' ' << cell(3) << ']'; } @@ -71,10 +62,8 @@ void MathExIntInset::maplize(MapleStream & os) const else os << '1'; os << ',' << cell(1); - if (hasScripts()) { - MathScriptInset * p = scripts_->asScriptInset(); - os << '=' << p->down().data_ << ".." << p->up().data_; - } + if (hasScripts()) + os << '=' << cell(2) << ".." << cell(3); os << ')'; } @@ -82,9 +71,9 @@ void MathExIntInset::maplize(MapleStream & os) const void MathExIntInset::mathmlize(MathMLStream & os) const { MathSymbolInset * sym = new MathSymbolInset(symbol_.c_str()); - if (hasScripts()) - scripts_->asScriptInset()->mathmlize(sym, os); - else + //if (hasScripts()) + // mathmlize(sym, os); + //else sym->mathmlize(os); delete sym; os << cell(0) << "" diff --git a/src/mathed/math_exintinset.h b/src/mathed/math_exintinset.h index 3767aaaeb5..67bebf3b2d 100644 --- a/src/mathed/math_exintinset.h +++ b/src/mathed/math_exintinset.h @@ -5,7 +5,7 @@ // \int_l^u f(x) dx in one block (as opposed to 'f','(','x',')' or 'f','x') // or \sum, \prod... for interfacing external programs -#include "math_scriptinset.h" +#include "math_nestinset.h" // cell(0) is stuff before the 'd', cell(1) the stuff after class MathExIntInset : public MathNestInset { @@ -15,10 +15,6 @@ public: /// MathInset * clone() const; /// - void scripts(MathAtom const &); - /// - MathAtom & scripts(); - /// void symbol(string const &); /// void metrics(MathMetricsInfo const & st) const; @@ -39,8 +35,6 @@ private: /// string symbol_; - /// - MathAtom scripts_; }; #endif diff --git a/src/mathed/math_extern.C b/src/mathed/math_extern.C index d6e0d68603..d6b6476502 100644 --- a/src/mathed/math_extern.C +++ b/src/mathed/math_extern.C @@ -17,6 +17,7 @@ #include "math_scriptinset.h" #include "math_stringinset.h" #include "math_symbolinset.h" +#include "Lsstream.h" #include "debug.h" @@ -36,6 +37,26 @@ typedef MathInset * ReplaceArgumentFunc(const MathArray & ar); +// try to extract a super/subscript +// modify iterator position to point behind the thing +bool extractScript(MathArray & ar, + MathArray::iterator & pos, MathArray::iterator last) +{ + // nothing to get here + if (pos == last) + return false; + + // is this a scriptinset? + if (!(*pos)->asScriptInset()) + return false; + + // it is a scriptinset, use it. + ar.push_back(*pos); + ++pos; + return true; +} + + // try to extract an "argument" to some function. // returns position behind the argument MathArray::iterator extractArgument(MathArray & ar, @@ -61,13 +82,9 @@ MathArray::iterator extractArgument(MathArray & ar, // if the next item is a subscript, it most certainly belongs to the // thing we have - if ((*pos)->asScriptInset()) { - ar.push_back(*pos); - // go ahead if possible - ++pos; - if (pos == last) - return pos; - } + extractScript(ar, pos, last); + if (pos == last) + return pos; // but it might be more than that. // FIXME: not implemented @@ -96,39 +113,38 @@ MathScriptInset const * asScript(MathArray::const_iterator it) // returns sequence of char with same code starting at it up to end // it might be less, though... -string charSequence(MathArray::const_iterator it, MathArray::const_iterator end) +MathArray::const_iterator charSequence(MathArray::const_iterator it, + MathArray::const_iterator end, string & s, MathTextCodes & c) { - string s; - MathCharInset const * p = it->nucleus()->asCharInset(); - if (p) { - for (MathTextCodes c = p->code(); it != end; ++it) { - p = it->nucleus()->asCharInset(); - if (!p || p->code() != c) - break; - s += p->getChar(); - } + MathCharInset const * p = (*it)->asCharInset(); + c = p->code(); + for (; it != end; ++it) { + p = (*it)->asCharInset(); + if (!p || p->code() != c) + break; + s += p->getChar(); } - return s; + return it; } -void extractStrings(MathArray & dat) +void extractStrings(MathArray & ar) { //lyxerr << "\nStrings from: " << ar << "\n"; - MathArray ar; - MathArray::const_iterator it = dat.begin(); - while (it != dat.end()) { - if (it->nucleus() && it->nucleus()->asCharInset()) { - string s = charSequence(it, dat.end()); - MathTextCodes c = it->nucleus()->asCharInset()->code(); - ar.push_back(MathAtom(new MathStringInset(s, c))); - it += s.size(); - } else { - ar.push_back(*it); - ++it; - } + for (MathArray::size_type i = 0; i < ar.size(); ++i) { + MathArray::iterator it = ar.begin() + i; + if (!(*it)->asCharInset()) + continue; + + // create proper string inset + MathStringInset * p = new MathStringInset; + MathArray::const_iterator + jt = charSequence(it, ar.end(), p->str_, p->code_); + + // clean up + (*it).reset(p); + ar.erase(i + 1, jt - ar.begin()); } - ar.swap(dat); //lyxerr << "\nStrings to: " << ar << "\n"; } @@ -156,19 +172,38 @@ void extractMatrices(MathArray & ar) // convert this inset somehow to a string -string extractString(MathInset * p) +bool extractString(MathInset * p, string & str) { - if (p && p->getChar()) - return string(1, p->getChar()); - if (p && p->asStringInset()) - return p->asStringInset()->str(); - return string(); + if (!p) + return false; + if (p->getChar()) { + str = string(1, p->getChar()); + return true; + } + if (p->asStringInset()) { + str = p->asStringInset()->str(); + return true; + } + return false; } -bool stringTest(MathInset * p, const string & str) +// convert this inset somehow to a number +bool extractNumber(MathArray const & ar, int & i) { - return extractString(p) == str; + string s; + MathTextCodes c; + charSequence(ar.begin(), ar.end(), s, c); + std::istringstream is(s); + is >> i; + return is; +} + + +bool testString(MathInset * p, const string & str) +{ + string s; + return extractString(p, s) && str == s; } @@ -223,23 +258,59 @@ void replaceNested( } + +// +// split scripts into seperate super- and subscript insets. sub goes in +// front of super... +// + +void splitScripts(MathArray & ar) +{ + lyxerr << "\nScripts from: " << ar << "\n"; + for (MathArray::size_type i = 0; i < ar.size(); ++i) { + MathArray::iterator it = ar.begin() + i; + + // is this script inset? + MathScriptInset * p = (*it)->asScriptInset(); + if (!p) + continue; + + // no problem if we don't have both... + if (!p->hasUp() || !p->hasDown()) + continue; + + // create extra script inset and move superscript over + MathScriptInset * q = new MathScriptInset; + q->ensure(true); + q->up().data_.swap(p->up().data_); + p->removeScript(true); + + // insert new inset behind + ++i; + ar.insert(i, MathAtom(q)); + } + lyxerr << "\nScripts to: " << ar << "\n"; +} + + + // // search deliminiters // -bool openParanTest(MathInset * p) +bool testOpenParan(MathInset * p) { - return stringTest(p, "("); + return testString(p, "("); } -bool closeParanTest(MathInset * p) +bool testCloseParan(MathInset * p) { - return stringTest(p, ")"); + return testString(p, ")"); } -MathInset * delimReplacement(const MathArray & ar) +MathInset * replaceDelims(const MathArray & ar) { MathDelimInset * del = new MathDelimInset("(", ")"); del->cell(0) = ar; @@ -251,7 +322,7 @@ MathInset * delimReplacement(const MathArray & ar) void extractDelims(MathArray & ar) { lyxerr << "\nDelims from: " << ar << "\n"; - replaceNested(ar, openParanTest, closeParanTest, delimReplacement); + replaceNested(ar, testOpenParan, testCloseParan, replaceDelims); lyxerr << "\nDelims to: " << ar << "\n"; } @@ -273,35 +344,33 @@ void extractFunctions(MathArray & ar) lyxerr << "\nFunctions from: " << ar << "\n"; for (MathArray::size_type i = 0; i + 1 < ar.size(); ++i) { MathArray::iterator it = ar.begin() + i; - - // is this a well known function name? - MathFuncInset * func = (*it)->asFuncInset(); - string name; - if (func) - name = func->name(); - else { - // is this a user defined function? - // guess so, if this is a "string" and it is followed by - // a DelimInset - //name = extractString((*it)->nucleus()); - //if (name.size() && it + 1 - //if ((*it - // FIXME - continue; - } - - // do we have an exponent? - // simply skippping the postion does the right thing: - // 'sin' '^2' 'x' -> 'sin(x)' '^2' MathArray::iterator jt = it + 1; - if (MathScriptInset * script = (*jt)->asScriptInset()) { - // allow superscripts only - if (script->hasDown()) + + string name; + // is it a function? + if ((*it)->asFuncInset()) { + // it certainly is if it is well known... + name = (*it)->asFuncInset()->name(); + } else { + // is this a user defined function? + // it it probably not, if it doesn't have a name. + if (!extractString((*it).nucleus(), name)) continue; - ++jt; + // it is not if it has no argument if (jt == ar.end()) continue; + // guess so, if this is followed by + // a DelimInset with a single item in the cell + MathDelimInset * del = (*jt)->asDelimInset(); + if (!del || del->cell(0).size() != 1) + continue; + // fall trough into main branch } + + // do we have an exponent like in + // 'sin' '^2' 'x' -> 'sin(x)' '^2' + MathArray exp; + extractScript(exp, jt, ar.end()); // create a proper inset as replacement MathExFuncInset * p = new MathExFuncInset(name); @@ -313,7 +382,10 @@ void extractFunctions(MathArray & ar) (*it).reset(p); // remove the source of the argument from the array - ar.erase(jt, st); + ar.erase(it + 1, st); + + // re-insert exponent + ar.insert(i + 1, exp); lyxerr << "\nFunctions to: " << ar << "\n"; } } @@ -323,21 +395,21 @@ void extractFunctions(MathArray & ar) // search integrals // -bool symbolTest(MathInset * p, string const & name) +bool testSymbol(MathInset * p, string const & name) { return p->asSymbolInset() && p->asSymbolInset()->name() == name; } -bool intSymbolTest(MathInset * p) +bool testIntSymbol(MathInset * p) { - return symbolTest(p, "int"); + return testSymbol(p, "int"); } -bool intDiffTest(MathInset * p) +bool testIntDiff(MathInset * p) { - return stringTest(p, "d"); + return testString(p, "d"); } @@ -350,16 +422,16 @@ void extractIntegrals(MathArray & ar) return; lyxerr << "\nIntegrals from: " << ar << "\n"; - for (MathArray::size_type i = 0; i + 1< ar.size(); ++i) { + for (MathArray::size_type i = 0; i + 1 < ar.size(); ++i) { MathArray::iterator it = ar.begin() + i; // is this a integral name? - if (!intSymbolTest(it->nucleus())) + if (!testIntSymbol(it->nucleus())) continue; // search 'd' MathArray::iterator jt = - endNestSearch(it, ar.end(), intSymbolTest, intDiffTest); + endNestSearch(it, ar.end(), testIntSymbol, testIntDiff); // something sensible found? if (jt == ar.end()) @@ -368,16 +440,27 @@ void extractIntegrals(MathArray & ar) // create a proper inset as replacement MathExIntInset * p = new MathExIntInset("int"); - // collect scripts + // collect subscript if any MathArray::iterator st = it + 1; - if ((*st)->asScriptInset()) { - p->scripts(*st); - p->cell(0) = MathArray(st + 1, jt); - } else { - p->cell(0) = MathArray(st, jt); - } + if (st != ar.end()) + if (MathScriptInset * sub = (*st)->asScriptInset()) + if (sub->hasDown()) { + p->cell(2) = sub->down().data_; + ++st; + } - // use the atom behind the 'd' as differential + // collect superscript if any + if (st != ar.end()) + if (MathScriptInset * sup = (*st)->asScriptInset()) + if (sup->hasUp()) { + p->cell(3) = sup->up().data_; + ++st; + } + + // core ist part from behind the scripts to the 'd' + p->cell(0) = MathArray(st, jt); + + // use the "thing" behind the 'd' as differential MathArray::iterator tt = extractArgument(p->cell(1), jt + 1, ar.end()); // remove used parts @@ -392,21 +475,15 @@ void extractIntegrals(MathArray & ar) // search sums // -bool sumSymbolTest(MathInset * p) +bool testSumSymbol(MathInset * p) { - return p->asSymbolInset() && p->asSymbolInset()->name() == "sum"; + return testSymbol(p, "sum"); } -bool equalSign(MathInset * p) +bool testEqualSign(MathAtom const & at) { - return stringTest(p, "="); -} - - -bool equalSign1(MathAtom const & at) -{ - return equalSign(at.nucleus()); + return testString(at.nucleus(), "="); } @@ -424,35 +501,40 @@ void extractSums(MathArray & ar) MathArray::iterator it = ar.begin() + i; // is this a sum name? - if (!sumSymbolTest(it->nucleus())) + if (!testSumSymbol(it->nucleus())) continue; // create a proper inset as replacement MathExIntInset * p = new MathExIntInset("sum"); - // collect scripts + // collect lower bound and summation index MathArray::iterator st = it + 1; - if (st != ar.end() && (*st)->asScriptInset()) { - p->scripts(*st); - ++st; - - // try to figure out the summation index from the subscript - MathScriptInset * script = p->scripts()->asScriptInset(); - if (script->hasDown()) { - MathArray & ar = script->down().data_; - MathArray::iterator it = - std::find_if(ar.begin(), ar.end(), &equalSign1); - if (it != ar.end()) { - // we found a '=', use everything in front of that as index, - // and everything behind as start value - p->cell(1) = MathArray(ar.begin(), it); - ar.erase(ar.begin(), it + 1); - } else { - // use everything as summation index, don't use scripts. - p->cell(1) = ar; + if (st != ar.end()) + if (MathScriptInset * sub = (*st)->asScriptInset()) + if (sub->hasDown()) { + // try to figure out the summation index from the subscript + MathArray & ar = sub->down().data_; + MathArray::iterator it = + std::find_if(ar.begin(), ar.end(), &testEqualSign); + if (it != 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(), it); + p->cell(2) = MathArray(it + 1, ar.end()); + } else { + // use everything as summation index, don't use scripts. + p->cell(1) = ar; + } + ++st; + } + + // collect upper bound + if (st != ar.end()) + if (MathScriptInset * sup = (*st)->asScriptInset()) + if (sup->hasUp()) { + p->cell(3) = sup->up().data_; + ++st; } - } - } // use some behind the script as core MathArray::iterator tt = extractArgument(p->cell(0), st, ar.end()); @@ -470,26 +552,40 @@ void extractSums(MathArray & ar) // // tests for 'd' or '\partial' -bool diffItemTest(MathInset * p) +bool testDiffItem(MathAtom const & at) { - return stringTest(p, "d"); + return testString(at.nucleus(), "d"); } -bool diffItemTest(MathArray const & ar) +bool testDiffArray(MathArray const & ar) { - return ar.size() && diffItemTest(ar.front().nucleus()); + return ar.size() && testDiffItem(ar.front()); } -bool diffFracTest(MathInset * p) +bool testDiffFrac(MathInset * p) { - return - p->asFracInset() && - diffItemTest(p->asFracInset()->cell(0)) && - diffItemTest(p->asFracInset()->cell(1)); + MathFracInset * f = p->asFracInset(); + return f && testDiffArray(f->cell(0)) && testDiffArray(f->cell(1)); } + +// is this something like ^number? +bool extractDiffExponent(MathArray::iterator it, int & i) +{ + if (!(*it)->asScriptInset()) + return false; + + string s; + if (!extractString((*it).nucleus(), s)) + return false; + std::istringstream is(s); + is >> i; + return is; +} + + void extractDiff(MathArray & ar) { lyxerr << "\nDiffs from: " << ar << "\n"; @@ -497,7 +593,7 @@ void extractDiff(MathArray & ar) MathArray::iterator it = ar.begin() + i; // is this a "differential fraction"? - if (!diffFracTest(it->nucleus())) + if (!testDiffFrac(it->nucleus())) continue; MathFracInset * f = (*it)->asFracInset(); @@ -507,7 +603,7 @@ void extractDiff(MathArray & ar) } // create a proper diff inset - MathDiffInset * p = new MathDiffInset; + MathDiffInset * diff = new MathDiffInset; // collect function, let jt point behind last used item MathArray::iterator jt = it + 1; @@ -515,37 +611,47 @@ void extractDiff(MathArray & ar) MathArray & numer = f->cell(0); if (numer.size() > 1 && numer.at(1)->asScriptInset()) { // this is something like d^n f(x) / d... or d^n / d... - n = 1; // FIXME + // FIXME + n = 1; if (numer.size() > 2) - p->cell(0) = MathArray(numer.begin() + 2, numer.end()); + diff->cell(0) = MathArray(numer.begin() + 2, numer.end()); else - jt = extractArgument(p->cell(0), jt, ar.end()); + jt = extractArgument(diff->cell(0), jt, ar.end()); } else { // simply d f(x) / d... or d/d... if (numer.size() > 1) - p->cell(0) = MathArray(numer.begin() + 1, numer.end()); + diff->cell(0) = MathArray(numer.begin() + 1, numer.end()); else - jt = extractArgument(p->cell(0), jt, ar.end()); + jt = extractArgument(diff->cell(0), jt, ar.end()); } - // collect denominator + // collect denominator parts MathArray & denom = f->cell(1); - for (MathArray::iterator dt = denom.begin(); dt + 1 != denom.end(); ) { - if (!diffItemTest((*dt).nucleus())) { - lyxerr << "extractDiff: should not happen 2\n"; - return; + for (MathArray::iterator dt = denom.begin(); dt != denom.end(); ) { + // find the next 'd' + MathArray::iterator et = std::find_if(dt + 1, denom.end(), &testDiffItem); + + // point before this + MathArray::iterator st = et - 1; + MathScriptInset * script = (*st)->asScriptInset(); + if (script && script->hasUp()) { + // things like d.../dx^n + int mult = 1; + if (extractNumber(script->up().data_, 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)); } - MathArray diff; - dt = extractArgument(diff, dt + 1, denom.end()); - p->addDer(diff); - // safeguard - if (dt == denom.end()) - break; + dt = et; } // cleanup ar.erase(it + 1, jt); - (*it).reset(p); + (*it).reset(diff); } lyxerr << "\nDiffs to: " << ar << "\n"; } @@ -556,6 +662,7 @@ void extractDiff(MathArray & ar) void extractStructure(MathArray & ar) { + splitScripts(ar); extractMatrices(ar); extractDelims(ar); extractFunctions(ar); diff --git a/src/mathed/math_spaceinset.C b/src/mathed/math_spaceinset.C index 8e32f7c8b3..e13b10daf3 100644 --- a/src/mathed/math_spaceinset.C +++ b/src/mathed/math_spaceinset.C @@ -21,19 +21,6 @@ MathInset * MathSpaceInset::clone() const } -void MathSpaceInset::write(WriteStream & os) const -{ - if (space_ >= 0 && space_ < 6) - os << '\\' << latex_mathspace[space_] << ' '; -} - - -void MathSpaceInset::normalize(NormalStream & os) const -{ - os << "[space " << space_ << "] "; -} - - void MathSpaceInset::metrics(MathMetricsInfo const & mi) const { width_ = space_ ? space_ * 2 : 2; @@ -70,3 +57,30 @@ void MathSpaceInset::incSpace() { space_ = (space_ + 1) % 6; } + + +void MathSpaceInset::maplize(MapleStream & os) const +{ + os << ' '; +} + + +void MathSpaceInset::octavize(OctaveStream & os) const +{ + os << ' '; +} + + +void MathSpaceInset::normalize(NormalStream & os) const +{ + os << "[space " << space_ << "] "; +} + + +void MathSpaceInset::write(WriteStream & os) const +{ + if (space_ >= 0 && space_ < 6) + os << '\\' << latex_mathspace[space_] << ' '; +} + + diff --git a/src/mathed/math_spaceinset.h b/src/mathed/math_spaceinset.h index b9554ee4d4..74c86d8848 100644 --- a/src/mathed/math_spaceinset.h +++ b/src/mathed/math_spaceinset.h @@ -17,19 +17,24 @@ public: /// MathInset * clone() const; /// - void draw(Painter &, int x, int y) const; - /// - void write(WriteStream & os) const; - /// - void normalize(NormalStream &) const; - /// - void metrics(MathMetricsInfo const & st) const; - /// MathSpaceInset const * asSpaceInset() const { return this; } /// MathSpaceInset * asSpaceInset() { return this; } /// void incSpace(); + /// + void metrics(MathMetricsInfo const & st) const; + /// + void draw(Painter &, int x, int y) const; + + /// + void normalize(NormalStream &) const; + /// + void maplize(MapleStream &) const; + /// + void octavize(OctaveStream &) const; + /// + void write(WriteStream & os) const; private: /// int space_; diff --git a/src/mathed/math_stringinset.C b/src/mathed/math_stringinset.C index 9f896fd289..6a41af3cd9 100644 --- a/src/mathed/math_stringinset.C +++ b/src/mathed/math_stringinset.C @@ -13,6 +13,10 @@ #include "debug.h" +MathStringInset::MathStringInset() + : str_(), code_(LM_TC_MIN) +{} + MathStringInset::MathStringInset(string const & s, MathTextCodes t) : str_(s), code_(t) {} diff --git a/src/mathed/math_stringinset.h b/src/mathed/math_stringinset.h index 1a63f7c772..a3ff6af078 100644 --- a/src/mathed/math_stringinset.h +++ b/src/mathed/math_stringinset.h @@ -14,6 +14,8 @@ class MathStringInset : public MathInset { public: + /// + MathStringInset(); /// MathStringInset(string const & s, MathTextCodes t = LM_TC_TEXTRM); /// @@ -44,7 +46,7 @@ public: /// void write(WriteStream & os) const; -private: +public: /// the string string str_; /// the font to be used on screen