diff --git a/src/mathed/Makefile.am b/src/mathed/Makefile.am index a1a379d661..0ec4638b10 100644 --- a/src/mathed/Makefile.am +++ b/src/mathed/Makefile.am @@ -110,5 +110,7 @@ libmathed_la_SOURCES = \ math_support.h \ math_symbolinset.C \ math_symbolinset.h \ + math_unknowninset.C \ + math_unknowninset.h \ math_xdata.C \ math_xdata.h diff --git a/src/mathed/math_data.C b/src/mathed/math_data.C index 170ae41491..987dc0ff13 100644 --- a/src/mathed/math_data.C +++ b/src/mathed/math_data.C @@ -24,6 +24,11 @@ MathArray::MathArray(MathArray const & ar, size_type from, size_type to) {} +MathArray::MathArray(iterator from, iterator to) + : bf_(from, to) +{} + + void MathArray::substitute(MathMacro const & m) { for (iterator it = begin(); it != end(); ++it) @@ -96,7 +101,7 @@ MathArray::size_type MathArray::size() const void MathArray::erase() { - erase(0, size()); + bf_.erase(begin(), end()); } @@ -107,6 +112,18 @@ void MathArray::erase(size_type pos) } +void MathArray::erase(iterator pos1, iterator pos2) +{ + bf_.erase(pos1, pos2); +} + + +void MathArray::erase(iterator pos) +{ + bf_.erase(pos); +} + + void MathArray::erase(size_type pos1, size_type pos2) { bf_.erase(begin() + pos1, begin() + pos2); diff --git a/src/mathed/math_data.h b/src/mathed/math_data.h index eaca3d61eb..f47d9dac01 100644 --- a/src/mathed/math_data.h +++ b/src/mathed/math_data.h @@ -56,6 +56,8 @@ public: MathArray(); /// MathArray(MathArray const &, size_type from, size_type to); + /// + MathArray(iterator from, iterator to); /// size_type size() const; @@ -71,6 +73,10 @@ public: /// void insert(size_type pos, MathArray const &); + /// + void erase(iterator pos1, iterator pos2); + /// + void erase(iterator pos); /// void erase(size_type pos1, size_type pos2); /// diff --git a/src/mathed/math_deliminset.C b/src/mathed/math_deliminset.C index 435b33f1f0..f74f8086a3 100644 --- a/src/mathed/math_deliminset.C +++ b/src/mathed/math_deliminset.C @@ -91,9 +91,27 @@ void MathDelimInset::draw(Painter & pain, int x, int y) const } +bool MathDelimInset::isParanthesis() const +{ + return left_ == "(" && right_ == ")"; +} + + +bool MathDelimInset::isBrackets() const +{ + return left_ == "[" && right_ == "]"; +} + + +bool MathDelimInset::isAbs() const +{ + return left_ == "|" && right_ == "|"; +} + + void MathDelimInset::maplize(MapleStream & os) const { - if (left_ == "|" && right_ == "|") { + if (isAbs()) { bool mat = cell(0).size() == 1 && cell(0).begin()->nucleus() && cell(0).begin()->nucleus()->asMatrixInset(); @@ -116,7 +134,7 @@ void MathDelimInset::mathmlize(MathMLStream & os) const void MathDelimInset::octavize(OctaveStream & os) const { - if (left_ == "|" && right_ == "|") + if (isAbs()) os << "det(" << cell(0) << ")"; else os << left_.c_str() << cell(0) << right_.c_str(); diff --git a/src/mathed/math_deliminset.h b/src/mathed/math_deliminset.h index c896ee7ca3..16ff2f20d3 100644 --- a/src/mathed/math_deliminset.h +++ b/src/mathed/math_deliminset.h @@ -23,6 +23,12 @@ public: MathDelimInset * asDelimInset() { return this; } /// MathDelimInset const * asDelimInset() const { return this; } + /// is it (...)? + bool isParanthesis() const; + /// is it [...]? + bool isBrackets() const; + /// is it |...|? + bool isAbs() const; /// void metrics(MathMetricsInfo const & st) const; /// diff --git a/src/mathed/math_exfuncinset.C b/src/mathed/math_exfuncinset.C index 8b08428c1e..475932c23b 100644 --- a/src/mathed/math_exfuncinset.C +++ b/src/mathed/math_exfuncinset.C @@ -6,9 +6,11 @@ using std::ostream; -MathExFuncInset::MathExFuncInset(string const & name) +MathExFuncInset::MathExFuncInset(string const & name, MathArray const & arg) : MathNestInset(1), name_(name) -{} +{ + cell(0) = arg; +} MathInset * MathExFuncInset::clone() const diff --git a/src/mathed/math_exfuncinset.h b/src/mathed/math_exfuncinset.h index 0c71ad57ec..5144bb6825 100644 --- a/src/mathed/math_exfuncinset.h +++ b/src/mathed/math_exfuncinset.h @@ -10,7 +10,7 @@ class MathExFuncInset : public MathNestInset { public: /// - explicit MathExFuncInset(string const & name); + MathExFuncInset(string const & name, MathArray const & arg); /// MathInset * clone() const; /// diff --git a/src/mathed/math_extern.C b/src/mathed/math_extern.C new file mode 100644 index 0000000000..7e1f1122bf --- /dev/null +++ b/src/mathed/math_extern.C @@ -0,0 +1,309 @@ + +// This file contains most of the magic that extracts "context +// information" from the unstructered layout-oriented stuff in an +// MathArray. + + +#include "math_charinset.h" +#include "math_deliminset.h" +#include "math_exfuncinset.h" +#include "math_funcinset.h" +#include "math_matrixinset.h" +#include "math_mathmlstream.h" +#include "math_scriptinset.h" +#include "math_stringinset.h" +#include "debug.h" + + +std::ostream & operator<<(ostream & os, MathArray const & ar) +{ + NormalStream ws(os); + ws << ar; + return os; +} + + +MathScriptInset const * asScript(MathArray::const_iterator it) +{ + if (it->nucleus()->asScriptInset()) + return 0; + ++it; + if (!it->nucleus()) + return 0; + return it->nucleus()->asScriptInset(); +} + + + +// 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) +{ + string s; + MathCharInset const * p = it->nucleus()->asCharInset(); + if (p) { + for (MathTextCodes c = p->code(); it != end; ++it) { + if (!it->nucleus()) + break; + p = it->nucleus()->asCharInset(); + if (!p || p->code() != c) + break; + s += p->getChar(); + } + } + return s; +} + + +void glueChars(MathArray & dat) +{ + 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; + } + } + ar.swap(dat); +} + + +bool needAsterisk(MathAtom const &, MathAtom const &) +{ + return false; +} + + +void guessAsterisks(MathArray & dat) +{ + if (dat.size() <= 1) + return; + MathArray ar; + ar.push_back(*dat.begin()); + MathArray::const_iterator it = dat.begin(); + MathArray::const_iterator jt = it + 1; + for (; jt != dat.end(); ++it, ++jt) { + if (needAsterisk(*it, *jt)) + ar.push_back(MathAtom(new MathCharInset('*'))); + ar.push_back(*it); + } + ar.push_back(*dat.end()); + ar.swap(dat); +} + + +MathInset * singleItem(MathArray & ar) +{ + lyxerr << "ar.size: " << ar.size() << "\n"; + //lyxerr << "ar.begin: " << ar.begin() << "\n"; + //lyxerr << "ar.nuc: " << ar.begin()->nucleus() << "\n"; + lyxerr << "ar.nuc: " << *ar.begin()->nucleus() << "\n"; + return ar.size() == 1 ? ar.begin()->nucleus() : 0; +} + + +void extractMatrices(MathArray & ar) +{ + for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it) { + if (!it->nucleus()) + continue; + MathDelimInset * del = it->nucleus()->asDelimInset(); + if (!del) + continue; + MathInset * arr = singleItem(del->cell(0)); + if (!arr || !arr->asArrayInset()) + continue; + *it = MathAtom(new MathMatrixInset(*(arr->asArrayInset()))); + } +} + + +void extractDelims(MathArray & ar) { + // use indices rather than iterators for the loop because we are going + // to modify the array. + for (MathArray::size_type i = 0; i < ar.size(); ++i) { + MathArray::iterator it = ar.begin() + i; + if (!it->nucleus()) + continue; + if ((*it)->getChar() != '(') + continue; + + // search last closing paranthesis + MathArray::iterator et = ar.end(); + for (MathArray::iterator jt = it + 1; jt != ar.end(); ++jt) + if ((*jt)->getChar() == ')') + et = jt; + if (et == ar.end()) + continue; + + // create a proper deliminset + MathAtom at(new MathDelimInset("(", ")")); + at->cell(0) = MathArray(it + 1, et); + + // replace the original stuff by the new inset + ar.erase(it + 1, et + 1); + *it = at; + } +} + + +// assume 'extractDelims' ran before +void extractFunctions(MathArray & ar) +{ + // we need at least two items... + if (ar.size() <= 1) + return; + + for (MathArray::size_type i = 0; i < ar.size() - 1; ++i) { + MathArray::iterator it = ar.begin() + i; + + // is this a function name? + if (!it->nucleus()) + continue; + MathFuncInset * func = (*it)->asFuncInset(); + if (!func) + 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()) + continue; + ++jt; + if (jt == ar.end()) + continue; + } + + // jt points now to the "argument". Since we had run "extractDelims" + // before, this could be a single argument only. Get hold of this. + MathArray arg; + MathDelimInset * del = (*jt)->asDelimInset(); + if (del && del->isParanthesis()) + arg = del->cell(0); + else + arg.push_back(*jt); + + // replace the function name by a real function inset + (*it).reset(new MathExFuncInset(func->name(), arg)); + + // remove the source of the argument from the array + ar.erase(jt); + } +} + + +void extractStructure(MathArray & ar) +{ + glueChars(ar); + extractMatrices(ar); + extractDelims(ar); + extractFunctions(ar); +} + + +void write(MathArray const & dat, WriteStream & wi) +{ + MathArray ar = dat; + glueChars(ar); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (it + 1 != ar.end()) { + if (MathScriptInset const * q = asScript(it)) { + q->write(p, wi); + ++it; + continue; + } + } + p->write(wi); + } +} + + +void normalize(MathArray const & dat, NormalStream & os) +{ + MathArray ar = dat; + glueChars(ar); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (it + 1 != ar.end()) { + if (MathScriptInset const * q = asScript(it)) { + q->normalize(p, os); + ++it; + continue; + } + } + p->normalize(os); + } +} + + +void octavize(MathArray const & dat, OctaveStream & os) +{ + MathArray ar = dat; + extractStructure(ar); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (it + 1 != ar.end()) { + if (MathScriptInset const * q = asScript(it)) { + q->octavize(p, os); + ++it; + continue; + } + } + p->octavize(os); + } +} + + +void maplize(MathArray const & dat, MapleStream & os) +{ + MathArray ar = dat; + extractStructure(ar); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (it + 1 != ar.end()) { + if (MathScriptInset const * q = asScript(it)) { + q->maplize(p, os); + ++it; + continue; + } + } + p->maplize(os); + } +} + + +void mathmlize(MathArray const & dat, MathMLStream & os) +{ + MathArray ar = dat; + extractStructure(ar); + if (ar.size() == 0) + os << ""; + else if (ar.size() == 1) + os << ar.begin()->nucleus(); + else { + os << MTag("mrow"); + for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (it + 1 != ar.end()) { + if (MathScriptInset const * q = asScript(it)) { + q->mathmlize(p, os); + ++it; + continue; + } + } + p->mathmlize(os); + } + os << ETag("mrow"); + } +} + diff --git a/src/mathed/math_extern.h b/src/mathed/math_extern.h new file mode 100644 index 0000000000..134561cf5f --- /dev/null +++ b/src/mathed/math_extern.h @@ -0,0 +1,17 @@ +#ifndef MATH_EXTERN_H +#define MATH_EXTERN_H + +class NormalStream; +class MapleStream; +class MathMLStream; +class OctaveStream; +class WriteStream; +class MathArray; + +void write(MathArray const &, WriteStream &); +void normalize(MathArray const &, NormalStream &); +void maplize(MathArray const &, MapleStream &); +void mathmlize(MathArray const &, MathMLStream &); +void octavize(MathArray const &, OctaveStream &); + +#endif diff --git a/src/mathed/math_factory.C b/src/mathed/math_factory.C index a23ea6e197..327624ec0d 100644 --- a/src/mathed/math_factory.C +++ b/src/mathed/math_factory.C @@ -18,8 +18,9 @@ #include "math_spaceinset.h" #include "math_specialcharinset.h" #include "math_sqrtinset.h" -#include "math_symbolinset.h" #include "math_stackrelinset.h" +#include "math_symbolinset.h" +#include "math_unknowninset.h" MathAtom createMathInset(latexkeys const * l) @@ -65,8 +66,10 @@ MathAtom createMathInset(latexkeys const * l) return MathAtom(new MathDotsInset(l->name)); case LM_TK_BOX: return MathAtom(new MathBoxInset(l->name)); + case LM_TK_FUNC: + return MathAtom(new MathFuncInset(l->name)); } - return MathAtom(new MathFuncInset(l->name)); + return MathAtom(new MathUnknownInset(l->name)); } @@ -88,5 +91,5 @@ MathAtom createMathInset(string const & s) return MathAtom(new MathMacro(s)); //cerr << "creating inset 2 with name: '" << s << "'\n"; - return MathAtom(new MathFuncInset(s)); + return MathAtom(new MathUnknownInset(s)); } diff --git a/src/mathed/math_funcinset.h b/src/mathed/math_funcinset.h index 42d4a2e055..d5d270c7f1 100644 --- a/src/mathed/math_funcinset.h +++ b/src/mathed/math_funcinset.h @@ -23,19 +23,22 @@ public: /// void draw(Painter &, int x, int y) const; /// - void write(WriteStream &) const; - /// - void normalize(NormalStream &) const; - /// string const & name() const; + /// identifies FuncInsets + MathFuncInset * asFuncInset() { return this; } /// void setName(string const &); + + /// + void normalize(NormalStream &) const; /// void maplize(MapleStream &) const; /// void mathmlize(MathMLStream &) const; /// void octavize(OctaveStream &) const; + /// + void write(WriteStream &) const; private: /// string name_; diff --git a/src/mathed/math_hullinset.C b/src/mathed/math_hullinset.C index 8cb6fc62c3..08c8dc1926 100644 --- a/src/mathed/math_hullinset.C +++ b/src/mathed/math_hullinset.C @@ -532,14 +532,12 @@ void MathHullInset::mutate(MathInsetTypes newtype) // split it "nicely" on the firest relop pos_type pos = firstRelOp(cell(0)); - cell(1) = cell(0); + cell(1) = MathArray(cell(0), pos, cell(0).size()); cell(0).erase(pos, cell(0).size()); - cell(1).erase(0, pos); if (cell(1).size()) { - cell(2) = cell(1); + cell(2) = MathArray(cell(1), 1, cell(1).size()); cell(1).erase(1, cell(1).size()); - cell(2).erase(0); } setType(LM_OT_EQNARRAY); diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 315af30e24..8b611d3efa 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -42,6 +42,7 @@ class MathArrayInset; class MathBoxInset; class MathCharInset; class MathDelimInset; +class MathFuncInset; class MathGridInset; class MathHullInset; class MathMatrixInset; @@ -170,39 +171,38 @@ public: virtual bool covers(int x, int y) const; /// identifies NestInsets - virtual MathNestInset * asNestInset() { return 0; } + virtual MathNestInset * asNestInset() { return 0; } /// identifies CharInsets - virtual MathCharInset const * asCharInset() const { return 0; } + virtual MathCharInset const * asCharInset() const { return 0; } /// identifies ScriptInsets + virtual MathScriptInset * asScriptInset() { return 0; } virtual MathScriptInset const * asScriptInset() const { return 0; } - /// identifies ScriptInsets - virtual MathScriptInset * asScriptInset() { return 0; } /// identifies HullInsets - virtual MathHullInset const * asHullInset() const { return 0; } - /// identifies HullInsets - virtual MathHullInset * asHullInset() { return 0; } + virtual MathHullInset * asHullInset() { return 0; } + virtual MathHullInset const * asHullInset() const { return 0; } /// identifies SpaceInset - virtual MathSpaceInset * asSpaceInset() { return 0; } + virtual MathSpaceInset * asSpaceInset() { return 0; } /// identifies GridInset - virtual MathGridInset * asGridInset() { return 0; } + virtual MathGridInset * asGridInset() { return 0; } /// identifies ArrayInsets - virtual MathArrayInset * asArrayInset() { return 0; } + virtual MathArrayInset * asArrayInset() { return 0; } /// identifies MatrixInsets virtual MathMatrixInset const * asMatrixInset() const { return 0; } /// identifies BoxInsets - virtual MathBoxInset * asBoxInset() { return 0; } + virtual MathBoxInset * asBoxInset() { return 0; } /// identifies DelimInsets - virtual MathDelimInset * asDelimInset() { return 0; } - /// identifies DelimInsets - virtual MathDelimInset const * asDelimInset() const { return 0; } + virtual MathDelimInset * asDelimInset() { return 0; } + virtual MathDelimInset const * asDelimInset() const { return 0; } + /// identifies FuncInsets + virtual MathFuncInset * asFuncInset() { return 0; } /// identifies macro templates - virtual MathMacroTemplate * asMacroTemplate() { return 0; } + virtual MathMacroTemplate * asMacroTemplate() { return 0; } /// identifies hyperactive insets - virtual UpdatableInset * asHyperActiveInset() const { return 0; } + virtual UpdatableInset * asHyperActiveInset() const { return 0; } /// identifies things that can get scripts virtual bool isScriptable() const { return false; } - /// + /// thing that can be moved into virtual bool isActive() const { return nargs() > 0; } /// identifies insets from the outer world virtual bool isHyperActive() const { return 0; } diff --git a/src/mathed/math_unknowninset.C b/src/mathed/math_unknowninset.C new file mode 100644 index 0000000000..20e83eb96f --- /dev/null +++ b/src/mathed/math_unknowninset.C @@ -0,0 +1,79 @@ +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "math_unknowninset.h" +#include "font.h" +#include "Painter.h" +#include "math_support.h" +#include "math_mathmlstream.h" + + + +extern LyXFont WhichFont(short type, int size); + + +MathUnknownInset::MathUnknownInset(string const & nm) + : name_(nm) +{} + + +MathInset * MathUnknownInset::clone() const +{ + return new MathUnknownInset(*this); +} + + +string const & MathUnknownInset::name() const +{ + return name_; +} + + +void MathUnknownInset::setName(string const & n) +{ + name_ = n; +} + + +void MathUnknownInset::write(WriteStream & os) const +{ + os << "\\" << name_.c_str() << ' '; +} + + +void MathUnknownInset::normalize(NormalStream & os) const +{ + os << "[func " << name_.c_str() << ']'; +} + + +void MathUnknownInset::metrics(MathMetricsInfo const & mi) const +{ + mi_ = mi; + mathed_string_dim(LM_TC_TEX, mi_, name_, ascent_, descent_, width_); +} + + +void MathUnknownInset::draw(Painter & pain, int x, int y) const +{ + drawStr(pain, LM_TC_TEX, mi_, x, y, name_); +} + + +void MathUnknownInset::maplize(MapleStream & os) const +{ + os << name_.c_str(); +} + + +void MathUnknownInset::mathmlize(MathMLStream & os) const +{ + os << MTag("mi") << name_.c_str() << ETag("mi"); +} + + +void MathUnknownInset::octavize(OctaveStream & os) const +{ + os << name_.c_str(); +} diff --git a/src/mathed/math_unknowninset.h b/src/mathed/math_unknowninset.h new file mode 100644 index 0000000000..05805ff89f --- /dev/null +++ b/src/mathed/math_unknowninset.h @@ -0,0 +1,48 @@ +// -*- C++ -*- +#ifndef MATH_UNKNOWNINSET_H +#define MATH_UNKNOWNINSET_H + +#include "math_diminset.h" +#include "math_defs.h" + +#ifdef __GNUG__ +#pragma interface +#endif + +/** + Unknowntions or LaTeX names for objects that we really don't know + */ +class MathUnknownInset : public MathDimInset { +public: + /// + explicit MathUnknownInset(string const & nm); + /// + MathInset * clone() const; + /// + void metrics(MathMetricsInfo const & st) const; + /// + void draw(Painter &, int x, int y) const; + /// + string const & name() const; + /// identifies UnknownInsets + MathUnknownInset const * asUnknownInset() const { return this; } + /// + void setName(string const &); + + /// + void normalize(NormalStream &) const; + /// + void maplize(MapleStream &) const; + /// + void mathmlize(MathMLStream &) const; + /// + void octavize(OctaveStream &) const; + /// + void write(WriteStream &) const; +private: + /// + string name_; + /// + mutable MathMetricsInfo mi_; +}; +#endif