mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
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:
parent
80ac2a43a4
commit
6e3fcdf812
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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() + ')';
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 &);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -34,6 +34,10 @@ public:
|
||||
int width() const;
|
||||
///
|
||||
string & str();
|
||||
///
|
||||
string octavize() const;
|
||||
///
|
||||
string maplize() const;
|
||||
|
||||
private:
|
||||
/// the string
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user