From: André Pönitz Date: Wed, 7 Nov 2001 08:51:35 +0000 (+0000) Subject: start native C++ support for Octave, Maple and MathML X-Git-Tag: 1.6.10~20396 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=6e3fcdf812f007c7c272bf7b1a7c650c109f709d;p=lyx.git start native C++ support for Octave, Maple and MathML git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2969 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/mathed/ChangeLog b/src/mathed/ChangeLog index 70d047a3ee..c19f1761db 100644 --- a/src/mathed/ChangeLog +++ b/src/mathed/ChangeLog @@ -1,3 +1,9 @@ + +2001-11-07 André Pönitz + + * math_*inset.[Ch]: + array.[Ch]: start native C++ support for Octave, Maple and MathML + 2001-10-31 Angus Leeming * math_defs.h: remove non-standard trailing comma from MathSymbolTypes. diff --git a/src/mathed/array.C b/src/mathed/array.C index 48deaf73ab..507aa2cc2f 100644 --- a/src/mathed/array.C +++ b/src/mathed/array.C @@ -15,6 +15,7 @@ using std::ostream; using std::endl; + MathArray::MathArray() {} @@ -38,6 +39,8 @@ MathScriptInset const * MathArray::asScript(const_iterator it) const const_iterator jt = it + 1; if (jt == end()) return 0; + if (!jt->nucleus()) + return 0; return jt->nucleus()->asScriptInset(); } @@ -191,19 +194,34 @@ MathArray MathArray::glueChars() const } -void MathArray::write(MathWriteInfo & wi) const +bool needAsterisk(MathAtom const & a, MathAtom const & b) { - glueChars().write1(wi); + return false; } -void MathArray::write1(MathWriteInfo & wi) const +MathArray MathArray::guessAsterisks() const { - for (const_iterator it = begin(); it != end(); ++it) { - MathInset * p = it->nucleus(); - if (!p) - continue; - if (MathScriptInset const * q = asScript(it)) { + if (size() <= 1) + return *this; + MathArray ar; + ar.push_back(*begin()); + for (const_iterator it = begin(), jt = begin()+1 ; jt != end(); ++it, ++jt) { + if (needAsterisk(*it, *jt)) + ar.push_back(MathAtom(new MathCharInset('*'))); + ar.push_back(*it); + } + ar.push_back(*end()); + return ar; +} + + +void MathArray::write(MathWriteInfo & wi) const +{ + MathArray ar = glueChars(); + for (const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (MathScriptInset const * q = ar.asScript(it)) { q->write(p, wi); ++it; } else { @@ -215,24 +233,71 @@ void MathArray::write1(MathWriteInfo & wi) const void MathArray::writeNormal(ostream & os) const { - for (const_iterator it = begin(); it != end(); ++it) { - MathInset * p = it->nucleus(); - if (!p) - continue; - if (MathScriptInset const * q = asScript(it)) { + MathArray ar = glueChars(); + for (const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (MathScriptInset const * q = ar.asScript(it)) { q->writeNormal(p, os); ++it; - } else { + } else p->writeNormal(os); - } } } +string MathArray::octavize() const +{ + MathArray ar = glueChars(); + string res; + for (const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (MathScriptInset const * q = ar.asScript(it)) { + res += q->octavize(p); + ++it; + } else + res += p->octavize(); + } + return res; +} + + +string MathArray::maplize() const +{ + MathArray ar = glueChars(); + string res; + for (const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (MathScriptInset const * q = ar.asScript(it)) { + res += q->maplize(p); + ++it; + } else + res += p->maplize(); + } + return res; +} + + +string MathArray::mathmlize() const +{ + MathArray ar = glueChars(); + string res; + for (const_iterator it = ar.begin(); it != ar.end(); ++it) { + MathInset const * p = it->nucleus(); + if (MathScriptInset const * q = ar.asScript(it)) { + res += q->mathmlize(p); + ++it; + } else + res += p->mathmlize(); + } + return res; +} + + void MathArray::validate(LaTeXFeatures & features) const { for (const_iterator it = begin(); it != end(); ++it) - it->nucleus()->validate(features); + if (it->nucleus()) + it->nucleus()->validate(features); } @@ -268,3 +333,5 @@ MathArray::iterator MathArray::end() { return bf_.end(); } + + diff --git a/src/mathed/array.h b/src/mathed/array.h index 7ce020c73f..52dc1528f8 100644 --- a/src/mathed/array.h +++ b/src/mathed/array.h @@ -18,7 +18,9 @@ #include #include + #include "math_atom.h" +#include "LString.h" class MathScriptInset; class MathMacro; @@ -30,6 +32,7 @@ class LaTeXFeatures; #pragma interface #endif + /** \class MathArray \brief Low level container for math insets @@ -99,8 +102,6 @@ public: MathAtom const & at(size_type pos) const; /// glue chars if necessary void write(MathWriteInfo & os) const; - /// raw write - void write1(MathWriteInfo & os) const; /// void writeNormal(std::ostream &) const; /// @@ -117,6 +118,16 @@ public: MathScriptInset const * asScript(const_iterator it) const; /// glues chars with the same attributes into MathStringInsets MathArray glueChars() const; + /// insert asterisks in "suitable" places + MathArray guessAsterisks() const; + + /// interface to Octave + string octavize() const; + /// interface to Maple + string maplize() const; + /// interface to MathML + string mathmlize() const; + private: /// Buffer buffer_type bf_; diff --git a/src/mathed/formula.C b/src/mathed/formula.C index f8916e42d4..3eb2424bc2 100644 --- a/src/mathed/formula.C +++ b/src/mathed/formula.C @@ -64,6 +64,64 @@ namespace { } + string captureOutput(string const & cmd, string const & data) + { + string outfile = lyx::tempName(string(), "mathextern"); + string full = "echo '" + data + "' | " + cmd + " > " + outfile; + lyxerr << "calling: " << full << "\n"; + Systemcalls dummy(Systemcalls::System, full, 0); + string out = GetFileContents(outfile); + lyxerr << "result: " << out << "\n"; + return out; + } + + + string pipeThroughMaple(string const & extra, MathArray const & ar) + { + string header = + "readlib(latex):\n" + "`latex/csname_font` := ``:\n" + "`latex/latex/*` := subs(`\\,`=`\\cdot `,eval(`latex/latex/*`)):\n"; + //"#`latex/csname_font` := `\\it `:" + //"#`latex/latex/symbol` " + // " := subs((\\'_\\' = \\'`\\_`\\',eval(`latex/latex/symbol`)): "; + + string trailer = "quit;"; + string expr = ar.maplize(); + + for (int i = 0; i < 100; ++i) { // at most 100 attempts + // try to fix missing '*' the hard way by using mint + // + // ... > echo "1A;" | mint -i 1 -S -s -q + // on line 1: 1A; + // ^ syntax error - + // Probably missing an operator such as * p + // + lyxerr << "checking expr: '" << expr << "'\n"; + string out = captureOutput("mint -i 1 -S -s -q -q", expr + ";"); + if (out.empty()) + break; // expression syntax is ok + istringstream is(out); + string line; + getline(is, line); + if (line.find("on line") != 0) + break; // error message not identified + getline(is, line); + string::size_type pos = line.find('^'); + if (pos == string::npos || pos < 15) + break; // caret position not found + expr.insert(pos - 15, "*"); + } + + string full = "latex(" + extra + '(' + expr + "));"; + string res = captureOutput("maple -q", header + full + trailer); + + // change \_ into _ + return res; + } + + + MathArray pipeThroughExtern(string const & arg, MathArray const & ar) { string lang; @@ -73,27 +131,40 @@ namespace { if (extra.empty()) extra = "noextra"; - // create normalized expression - string outfile = lyx::tempName(string(), "mathextern"); - ostringstream os; - os << "[" << extra << ' '; - ar.writeNormal(os); - os << "]"; - string code = os.str().c_str(); - - // run external sript - string file = LibFileSearch("mathed", "extern_" + lang); - if (file.empty()) { - lyxerr << "converter to '" << lang << "' not found\n"; - return MathArray(); + MathArray res; + + if (lang == "octave") { + + string out = captureOutput("octave -q", ar.octavize()); + if (out.size() > 6) + out = out.substr(6); + mathed_parse_cell(res, out); + + } else if (lang == "maple") { + + mathed_parse_cell(res, pipeThroughMaple(extra, ar)); + + } else { + + // create normalized expression + ostringstream os; + os << "[" << extra << ' '; + ar.writeNormal(os); + os << "]"; + string data = os.str().c_str(); + + // search external script + string file = LibFileSearch("mathed", "extern_" + lang); + if (file.empty()) { + lyxerr << "converter to '" << lang << "' not found\n"; + return MathArray(); + } + + // run external sript + string out = captureOutput(file, data); + mathed_parse_cell(res, out); } - string script = file + " '" + code + "' " + outfile; - lyxerr << "calling: " << script << endl; - Systemcalls cmd(Systemcalls::System, script, 0); - // append result - MathArray res; - mathed_parse_cell(res, GetFileContents(outfile)); return res; } @@ -371,7 +442,7 @@ void InsetFormula::handleExtern(const string & arg) ar = mathcursor->cursor().cell(); stripFromLastEqualSign(ar); mathcursor->insert(MathAtom(new MathCharInset('=', LM_TC_VAR))); - lyxerr << "use whole cell: " << ar << "\n"; + //lyxerr << "use whole cell: " << ar << "\n"; } mathcursor->insert(pipeThroughExtern(arg, ar)); diff --git a/src/mathed/math_arrayinset.C b/src/mathed/math_arrayinset.C index 57eb16832f..4cd48211ec 100644 --- a/src/mathed/math_arrayinset.C +++ b/src/mathed/math_arrayinset.C @@ -44,6 +44,14 @@ void MathArrayInset::write(MathWriteInfo & os) const } +void MathArrayInset::writeNormal(std::ostream & os) const +{ + os << "[array "; + MathGridInset::writeNormal(os); + os << "]"; +} + + void MathArrayInset::metrics(MathMetricsInfo const & st) const { MathMetricsInfo mi = st; @@ -51,4 +59,3 @@ void MathArrayInset::metrics(MathMetricsInfo const & st) const mi.style = LM_ST_TEXT; MathGridInset::metrics(mi); } - diff --git a/src/mathed/math_arrayinset.h b/src/mathed/math_arrayinset.h index 79fa2130da..e80acf6d0a 100644 --- a/src/mathed/math_arrayinset.h +++ b/src/mathed/math_arrayinset.h @@ -20,6 +20,8 @@ public: /// void write(MathWriteInfo & os) const; /// + void writeNormal(std::ostream &) const; + /// void metrics(MathMetricsInfo const & st) const; /// MathArrayInset * asArrayInset() { return this; } diff --git a/src/mathed/math_deliminset.C b/src/mathed/math_deliminset.C index 3c6ad16915..7c5c736b90 100644 --- a/src/mathed/math_deliminset.C +++ b/src/mathed/math_deliminset.C @@ -91,3 +91,19 @@ void MathDelimInset::draw(Painter & pain, int x, int y) const mathed_draw_deco(pain, x + 1, b, w, height(), left_); mathed_draw_deco(pain, x + width() - w - 1, b, w, height(), right_); } + + +string MathDelimInset::octavize() const +{ + if (left_ == "|" && right_ == "|") + return "det(" + cell(0).octavize() + ")"; + return left_ + cell(0).octavize() + right_; +} + + +string MathDelimInset::maplize() const +{ + if (left_ == "|" && right_ == "|") + return "abs(" + cell(0).octavize() + ")"; + return left_ + cell(0).octavize() + right_; +} diff --git a/src/mathed/math_deliminset.h b/src/mathed/math_deliminset.h index f1fb2bf605..24a3ab2255 100644 --- a/src/mathed/math_deliminset.h +++ b/src/mathed/math_deliminset.h @@ -27,6 +27,10 @@ public: void writeNormal(std::ostream &) const; /// void metrics(MathMetricsInfo const & st) const; + /// + string octavize() const; + /// + string maplize() const; private: /// int dw() const; diff --git a/src/mathed/math_fracinset.C b/src/mathed/math_fracinset.C index 0dcf7a8014..70e7737a39 100644 --- a/src/mathed/math_fracinset.C +++ b/src/mathed/math_fracinset.C @@ -61,3 +61,9 @@ void MathFracInset::writeNormal(std::ostream & os) const cell(1).writeNormal(os); os << "] "; } + + +string MathFracInset::maplize() const +{ + return '(' + cell(0).maplize() + '/' + cell(1).maplize() + ')'; +} diff --git a/src/mathed/math_fracinset.h b/src/mathed/math_fracinset.h index 0c227c6f8c..4d14aaded6 100644 --- a/src/mathed/math_fracinset.h +++ b/src/mathed/math_fracinset.h @@ -25,6 +25,8 @@ public: void metrics(MathMetricsInfo const & st) const; /// void draw(Painter &, int x, int y) const; + /// + string maplize() const; public: /// const bool atop_; diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index e2b3239a5c..5b31df9cbd 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -585,3 +585,23 @@ std::vector res.push_back(index(i, j)); return res; } + + +string MathGridInset::octavize() const +{ + string res; + res += '['; + for (row_type row = 0; row < nrows(); ++row) { + if (row) + res += ';'; + res += '['; + for (col_type col = 0; col < ncols(); ++col) { + res += cell(index(row, col)).octavize(); + res += ' '; + } + res += ']'; + } + res += ']'; + return res; +} + diff --git a/src/mathed/math_gridinset.h b/src/mathed/math_gridinset.h index 8226b5101f..60027ec568 100644 --- a/src/mathed/math_gridinset.h +++ b/src/mathed/math_gridinset.h @@ -149,6 +149,9 @@ public: /// void setDefaults(); + /// + string octavize() const; + protected: /// returns proper 'end of line' code for LaTeX string eolString(row_type row) const; diff --git a/src/mathed/math_inset.C b/src/mathed/math_inset.C index 6c20b0e181..a1245c4054 100644 --- a/src/mathed/math_inset.C +++ b/src/mathed/math_inset.C @@ -19,6 +19,8 @@ #pragma implementation #endif +#include + #include "math_inset.h" #include "math_scriptinset.h" #include "debug.h" @@ -175,7 +177,7 @@ void MathInset::dump() const } -bool MathInset::covers(int x, int y) const +bool MathInset::covers(int, int) const { lyxerr << "MathInset::covers() called directly!\n"; return false; @@ -212,3 +214,24 @@ void MathInset::write(MathWriteInfo &) const { lyxerr << "MathInset::write() called directly!\n"; } + + +string MathInset::octavize() const +{ + ostringstream os; + writeNormal(os); + return os.str(); + return string(); +} + + +string MathInset::maplize() const +{ + return octavize(); +} + + +string MathInset::mathmlize() const +{ + return string(); +} diff --git a/src/mathed/math_inset.h b/src/mathed/math_inset.h index 065672fb6e..59335a3331 100644 --- a/src/mathed/math_inset.h +++ b/src/mathed/math_inset.h @@ -30,6 +30,7 @@ #include "xarray.h" #include "math_defs.h" +#include "LString.h" /** Abstract base class for all math objects. A math insets is for use of the math editor only, it isn't a @@ -52,6 +53,7 @@ class LaTeXFeatures; class Buffer; class BufferView; class UpdatableInset; +class MathOctaveInfo; struct MathWriteInfo { @@ -249,6 +251,13 @@ public: virtual void validate(LaTeXFeatures & features) const; /// virtual void handleFont(MathTextCodes) {} + + /// + virtual string octavize() const; + /// + virtual string maplize() const; + /// + virtual string mathmlize() const; }; std::ostream & operator<<(std::ostream &, MathInset const &); diff --git a/src/mathed/math_scriptinset.C b/src/mathed/math_scriptinset.C index a66ec9c676..10f9163788 100644 --- a/src/mathed/math_scriptinset.C +++ b/src/mathed/math_scriptinset.C @@ -346,3 +346,28 @@ bool MathScriptInset::idxLeft(MathInset::idx_type &, } +string MathScriptInset::maplize(MathInset const * nuc) const +{ + string res; + if (nuc) + res += nuc->maplize(); + if (hasDown() && down().data_.size()) + res += "[" + down().data_.maplize() + "]"; + if (hasUp() && up().data_.size()) + res += "^(" + up().data_.maplize() + ")"; + return res; +} + + +string MathScriptInset::octavize(MathInset const * nuc) const +{ + return maplize(nuc); +} + + +string MathScriptInset::mathmlize(MathInset const * nuc) const +{ + if (nuc) + return nuc->mathmlize(); + return string(); +} diff --git a/src/mathed/math_scriptinset.h b/src/mathed/math_scriptinset.h index 134db75239..b48dbc8bef 100644 --- a/src/mathed/math_scriptinset.h +++ b/src/mathed/math_scriptinset.h @@ -81,6 +81,13 @@ public: /// void ensure(bool up); + /// + virtual string octavize(MathInset const * nuc) const; + /// + virtual string maplize(MathInset const * nuc) const; + /// + virtual string mathmlize(MathInset const * nuc) const; + public: /// returns x offset for main part int dxx(MathInset const * nuc) const; diff --git a/src/mathed/math_stringinset.C b/src/mathed/math_stringinset.C index 7a79dca1cb..32981c22e2 100644 --- a/src/mathed/math_stringinset.C +++ b/src/mathed/math_stringinset.C @@ -68,3 +68,27 @@ void MathStringInset::writeNormal(std::ostream & os) const { os << "[string " << str_ << " " << "mathalpha" << "]"; } + + +string MathStringInset::octavize() const +{ + return maplize(); +} + + +string MathStringInset::maplize() const +{ + if (code_ != LM_TC_VAR) + return str_; + if (str_.size() <= 1) + return str_; + string res; + + // insert '*' between adjacent chars if type is LM_TC_VAR + res += str_[0]; + for (string::size_type i = 1; i < str_.size(); ++i) { + res += '*'; + res += str_[i]; + } + return res; +} diff --git a/src/mathed/math_stringinset.h b/src/mathed/math_stringinset.h index 6dfc022145..87aaa9d98d 100644 --- a/src/mathed/math_stringinset.h +++ b/src/mathed/math_stringinset.h @@ -34,6 +34,10 @@ public: int width() const; /// string & str(); + /// + string octavize() const; + /// + string maplize() const; private: /// the string diff --git a/src/mathed/math_symbolinset.C b/src/mathed/math_symbolinset.C index c895aa8951..0e8c4a609a 100644 --- a/src/mathed/math_symbolinset.C +++ b/src/mathed/math_symbolinset.C @@ -112,3 +112,25 @@ bool MathSymbolInset::takesLimits() const { return sym_->token == LM_TK_CMEX; } + + +string MathSymbolInset::octavize() const +{ + if (sym_->name == "cdot") + return "*"; + return sym_->name; +} + + +string MathSymbolInset::maplize() const +{ + if (sym_->name == "cdot") + return "*"; + return sym_->name; +} + + +string MathSymbolInset::mathmlize() const +{ + return sym_->name; +} diff --git a/src/mathed/math_symbolinset.h b/src/mathed/math_symbolinset.h index 7d73c85fe3..3125f490b5 100644 --- a/src/mathed/math_symbolinset.h +++ b/src/mathed/math_symbolinset.h @@ -30,6 +30,12 @@ public: /// identifies things that can get \limits or \nolimits bool takesLimits() const; + /// + string octavize() const; + /// + string maplize() const; + /// + string mathmlize() const; private: /// MathTextCodes code() const;