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
This commit is contained in:
André Pönitz 2001-11-07 08:51:35 +00:00
parent 80ac2a43a4
commit 6e3fcdf812
20 changed files with 376 additions and 41 deletions

View 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.

View 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();
}

View 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_;

View 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();
}
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));
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);
}
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));

View 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);
}

View 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; }

View 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_;
}

View 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;

View 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() + ')';
}

View 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_;

View 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;
}

View 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;

View 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();
}

View 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 &);

View 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();
}

View 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;

View 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;
}

View File

@ -34,6 +34,10 @@ public:
int width() const;
///
string & str();
///
string octavize() const;
///
string maplize() const;
private:
/// the string

View 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;
}

View 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;