]> git.lyx.org Git - lyx.git/commitdiff
start native C++ support for Octave, Maple and MathML
authorAndré Pönitz <poenitz@gmx.net>
Wed, 7 Nov 2001 08:51:35 +0000 (08:51 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Wed, 7 Nov 2001 08:51:35 +0000 (08:51 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@2969 a592a061-630c-0410-9148-cb99ea01b6c8

20 files changed:
src/mathed/ChangeLog
src/mathed/array.C
src/mathed/array.h
src/mathed/formula.C
src/mathed/math_arrayinset.C
src/mathed/math_arrayinset.h
src/mathed/math_deliminset.C
src/mathed/math_deliminset.h
src/mathed/math_fracinset.C
src/mathed/math_fracinset.h
src/mathed/math_gridinset.C
src/mathed/math_gridinset.h
src/mathed/math_inset.C
src/mathed/math_inset.h
src/mathed/math_scriptinset.C
src/mathed/math_scriptinset.h
src/mathed/math_stringinset.C
src/mathed/math_stringinset.h
src/mathed/math_symbolinset.C
src/mathed/math_symbolinset.h

index 70d047a3ee2d64f67077d10248c240fa8eb0e6c2..c19f1761db6a919b06c880ac241f643938a035f1 100644 (file)
@@ -1,3 +1,9 @@
+
+2001-11-07  André Pönitz  <poenitz@gmx.net>
+
+       * math_*inset.[Ch]:
+               array.[Ch]: start native C++ support for Octave, Maple and MathML
+
 2001-10-31  Angus Leeming  <a.leeming@ic.ac.uk>
 
        * math_defs.h: remove non-standard trailing comma from MathSymbolTypes.
index 48deaf73ab7066e3b125c9b91b8cb0d7bb11a3bb..507aa2cc2f7a37ebcd55e69a58705afbd52f3c00 100644 (file)
@@ -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();
 }
+
+
index 7ce020c73ff42829045865defab406f5ce49e6ff..52dc1528f81a2916b953ca70259ff546c58b8f67 100644 (file)
@@ -18,7 +18,9 @@
 
 #include <vector>
 #include <iosfwd>
+
 #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_;
index f8916e42d434b3593459fad006fb235824f1c4ff..3eb2424bc231c59a9fa679b62c599eaee631f418 100644 (file)
@@ -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));
index 57eb16832f678229fb5dea413576fd279204b1b6..4cd48211ec1f3a13b88123791236cf19463fabc1 100644 (file)
@@ -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);
 }
-
index 79fa2130dabad47dee6bc63ab4c5bd9f271c7a0b..e80acf6d0a8a33447741f9e99af77ffcf8d640cc 100644 (file)
@@ -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; }
index 3c6ad1691588d52c433fb7113d7dcc0ecd7b8bb1..7c5c736b900d2d0e5acbcbb4a5d1a55c58b13073 100644 (file)
@@ -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_;
+}
index f1fb2bf60595d12a95be8a9f8c9e36a51430988c..24a3ab22550de0f0438fea98324264a8081390b1 100644 (file)
@@ -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;
index 0dcf7a801497cf7bf146a8804887a2fd98f4556e..70e7737a395a70fc9269f5cdce0f9748b53405a2 100644 (file)
@@ -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() + ')';
+}
index 0c227c6f8cb8547994ab81e8318d1df03a0069e2..4d14aaded6f152e7f65a68516751946a4df8abf1 100644 (file)
@@ -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_;
index e2b3239a5c14efa051f658d7673d164cc50c4e25..5b31df9cbdb6e57469e3df915935fc4d8f96eec6 100644 (file)
@@ -585,3 +585,23 @@ std::vector<MathInset::idx_type>
                        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;
+}
+
index 8226b5101f2d8a3434f90d867d0b31f45015164b..60027ec5685a00fd13804f330e69055e39dd901a 100644 (file)
@@ -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;
index 6c20b0e1817c740aca4973ddf20baecfd432d68e..a1245c40547737fb19171f38c642341cbd5d38a5 100644 (file)
@@ -19,6 +19,8 @@
 #pragma implementation
 #endif
 
+#include <sstream>
+
 #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();
+}
index 065672fb6ebba18599f54dc6aae83ea9248d9666..59335a33315ad3bf7320d8af5a42eba1124cf25c 100644 (file)
@@ -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 &);
index a66ec9c67624912ff435eb340c65745d484e0484..10f9163788128bff09959a44b7ccd8c5ecbcd396 100644 (file)
@@ -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();
+}
index 134db752390dfefdad8f31a23587260e0001ede6..b48dbc8bef44a5eb4aaebbcdfd7843dbcb9f8fc4 100644 (file)
@@ -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;
index 7a79dca1cb914fbf412e15f504edf574923158ee..32981c22e2ea1743e6971c11fb931df74a33786f 100644 (file)
@@ -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;
+}
index 6dfc02214572de31963326e8ed630671235287b4..87aaa9d98d8f6085f83743e4017247a27247fb4e 100644 (file)
@@ -34,6 +34,10 @@ public:
        int width() const;
        ///
        string & str();
+       ///
+       string octavize() const;
+       ///
+       string maplize() const;
 
 private:
        /// the string
index c895aa89519837a59483550807e2bfbb0a2daaa8..0e8c4a609ac5d5e9e7a9ccd584c4cd2f1b5cad01 100644 (file)
@@ -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;
+}
index 7d73c85fe36d3147b9413f6b93a6d9a8eab4ddf2..3125f490b5c3fbc033a1f7358ee2da42280da13b 100644 (file)
@@ -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;