+
+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.
using std::endl;
+
MathArray::MathArray()
{}
const_iterator jt = it + 1;
if (jt == end())
return 0;
+ if (!jt->nucleus())
+ return 0;
return jt->nucleus()->asScriptInset();
}
}
-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 {
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);
}
{
return bf_.end();
}
+
+
#include <vector>
#include <iosfwd>
+
#include "math_atom.h"
+#include "LString.h"
class MathScriptInset;
class MathMacro;
#pragma interface
#endif
+
/** \class MathArray
\brief Low level container for math insets
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;
///
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_;
}
+ 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;
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;
}
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));
}
+void MathArrayInset::writeNormal(std::ostream & os) const
+{
+ os << "[array ";
+ MathGridInset::writeNormal(os);
+ os << "]";
+}
+
+
void MathArrayInset::metrics(MathMetricsInfo const & st) const
{
MathMetricsInfo mi = st;
mi.style = LM_ST_TEXT;
MathGridInset::metrics(mi);
}
-
///
void write(MathWriteInfo & os) const;
///
+ void writeNormal(std::ostream &) const;
+ ///
void metrics(MathMetricsInfo const & st) const;
///
MathArrayInset * asArrayInset() { return this; }
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_;
+}
void writeNormal(std::ostream &) const;
///
void metrics(MathMetricsInfo const & st) const;
+ ///
+ string octavize() const;
+ ///
+ string maplize() const;
private:
///
int dw() const;
cell(1).writeNormal(os);
os << "] ";
}
+
+
+string MathFracInset::maplize() const
+{
+ return '(' + cell(0).maplize() + '/' + cell(1).maplize() + ')';
+}
void metrics(MathMetricsInfo const & st) const;
///
void draw(Painter &, int x, int y) const;
+ ///
+ string maplize() const;
public:
///
const bool atop_;
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;
+}
+
///
void setDefaults();
+ ///
+ string octavize() const;
+
protected:
/// returns proper 'end of line' code for LaTeX
string eolString(row_type row) const;
#pragma implementation
#endif
+#include <sstream>
+
#include "math_inset.h"
#include "math_scriptinset.h"
#include "debug.h"
}
-bool MathInset::covers(int x, int y) const
+bool MathInset::covers(int, int) const
{
lyxerr << "MathInset::covers() called directly!\n";
return false;
{
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();
+}
#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
class Buffer;
class BufferView;
class UpdatableInset;
+class MathOctaveInfo;
struct MathWriteInfo {
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 &);
}
+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();
+}
///
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;
{
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;
+}
int width() const;
///
string & str();
+ ///
+ string octavize() const;
+ ///
+ string maplize() const;
private:
/// the string
{
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;
+}
/// identifies things that can get \limits or \nolimits
bool takesLimits() const;
+ ///
+ string octavize() const;
+ ///
+ string maplize() const;
+ ///
+ string mathmlize() const;
private:
///
MathTextCodes code() const;