a step towards world domination^H^H^H

aehm... move things from the parbox inset to an abstract base class
'MathTextInset' and have a shot on implementing an ERT inset on top of
that.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4819 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
André Pönitz 2002-07-31 17:26:14 +00:00
parent cdbe361370
commit 990069f546
21 changed files with 395 additions and 383 deletions

View File

@ -51,6 +51,8 @@ libmathed_la_SOURCES = \
math_dotsinset.h \ math_dotsinset.h \
math_envinset.C \ math_envinset.C \
math_envinset.h \ math_envinset.h \
math_ertinset.C \
math_ertinset.h \
math_extern.C \ math_extern.C \
math_extern.h \ math_extern.h \
math_exfuncinset.C \ math_exfuncinset.C \
@ -134,6 +136,8 @@ libmathed_la_SOURCES = \
math_support.h \ math_support.h \
math_symbolinset.C \ math_symbolinset.C \
math_symbolinset.h \ math_symbolinset.h \
math_textinset.C \
math_textinset.h \
math_unknowninset.C \ math_unknowninset.C \
math_unknowninset.h \ math_unknowninset.h \
math_undersetinset.C \ math_undersetinset.C \

View File

@ -208,9 +208,11 @@ void InsetFormulaBase::insetUnlock(BufferView * bv)
} }
void InsetFormulaBase::getCursorPos(BufferView * bv, int & x, int & y) const void InsetFormulaBase::getCursorPos(BufferView *, int & x, int & y) const
{ {
metrics(bv); // calling metrics here destroys the cached xo,yo positions e.g. in
// MathParboxinset. And it would be too expensive anyway...
//metrics(bv);
mathcursor->getPos(x, y); mathcursor->getPos(x, y);
//x -= xo_; //x -= xo_;
y -= yo_; y -= yo_;
@ -403,6 +405,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
if (!mathcursor) if (!mathcursor)
return UNDISPATCHED; return UNDISPATCHED;
string argument = arg;
RESULT result = DISPATCHED; RESULT result = DISPATCHED;
bool sel = false; bool sel = false;
@ -696,11 +699,6 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
result = UNDISPATCHED; result = UNDISPATCHED;
break; break;
case LFUN_BREAKPARAGRAPH:
case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
//lyxerr << "LFUN ignored\n";
break;
case LFUN_INSET_ERT: case LFUN_INSET_ERT:
// interpret this as if a backslash was typed // interpret this as if a backslash was typed
bv->lockedInsetStoreUndo(Undo::EDIT); bv->lockedInsetStoreUndo(Undo::EDIT);
@ -708,15 +706,21 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
updateLocal(bv, true); updateLocal(bv, true);
break; break;
case LFUN_BREAKPARAGRAPH:
case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
case LFUN_BREAKPARAGRAPH_SKIP:
argument = "\n";
// fall through
case -1: case -1:
case LFUN_INSERT_MATH: case LFUN_INSERT_MATH:
case LFUN_SELFINSERT: case LFUN_SELFINSERT:
if (!arg.empty()) { if (!argument.empty()) {
bv->lockedInsetStoreUndo(Undo::EDIT); bv->lockedInsetStoreUndo(Undo::EDIT);
if (arg.size() == 1) if (argument.size() == 1)
result = mathcursor->interpret(arg[0]) ? DISPATCHED : FINISHED_RIGHT; result = mathcursor->interpret(argument[0]) ? DISPATCHED : FINISHED_RIGHT;
else else
result = mathcursor->interpret(arg) ? DISPATCHED : FINISHED_RIGHT; result = mathcursor->interpret(argument) ? DISPATCHED : FINISHED_RIGHT;
updateLocal(bv, true); updateLocal(bv, true);
} }
break; break;

View File

@ -1399,6 +1399,12 @@ bool MathCursor::interpret(char c)
return true; return true;
} }
if (c == '\n') {
if (currentMode() == MathInset::TEXT_MODE)
insert(c);
return true;
}
if (c == ' ') { if (c == ' ') {
if (currentMode() == MathInset::TEXT_MODE) { if (currentMode() == MathInset::TEXT_MODE) {
// insert spaces in text mode, // insert spaces in text mode,

View File

@ -0,0 +1,42 @@
#include "math_ertinset.h"
#include "math_mathmlstream.h"
MathInset * MathErtInset::clone() const
{
return new MathErtInset(*this);
}
void MathErtInset::metrics(MathMetricsInfo & mi) const
{
MathFontSetChanger dummy(mi.base, "lyxert");
MathTextInset::metrics(mi);
cache_.colinfo_[0].align_ = 'l';
metricsMarkers2();
}
void MathErtInset::draw(MathPainterInfo & pi, int x, int y) const
{
MathFontSetChanger dummy(pi.base, "lyxert");
MathTextInset::draw(pi, x + 1, y);
drawMarkers2(pi, x, y);
}
void MathErtInset::write(WriteStream & os) const
{
if (os.latex())
os << cell(0);
else
os << "\\lyxert{" << cell(0) << '}';
}
void MathErtInset::infoize(std::ostream & os) const
{
os << "Box: Ert";
}

View File

@ -0,0 +1,26 @@
#ifndef MATH_ERTINSET_H
#define MATH_ERTINSET_H
#include "math_textinset.h"
// implements support for \parbox
class MathErtInset : public MathTextInset {
public:
///
MathErtInset() {}
///
MathInset * clone() const;
///
mode_type currentMode() const { return TEXT_MODE; }
///
void metrics(MathMetricsInfo & mi) const;
///
void draw(MathPainterInfo & pi, int x, int y) const;
///
void infoize(std::ostream & os) const;
///
void write(WriteStream & os) const;
};
#endif

View File

@ -8,6 +8,7 @@
#include "math_casesinset.h" #include "math_casesinset.h"
#include "math_decorationinset.h" #include "math_decorationinset.h"
#include "math_dotsinset.h" #include "math_dotsinset.h"
#include "math_ertinset.h"
#include "math_fboxinset.h" #include "math_fboxinset.h"
#include "math_fontinset.h" #include "math_fontinset.h"
#include "math_fontoldinset.h" #include "math_fontoldinset.h"
@ -180,41 +181,6 @@ latexkeys const * in_word_set(string const & str)
MathAtom createMathInset(string const & s) MathAtom createMathInset(string const & s)
{ {
lyxerr[Debug::MATHED] << "creating inset with name: '" << s << "'\n"; lyxerr[Debug::MATHED] << "creating inset with name: '" << s << "'\n";
if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
return MathAtom(new MathMacroArgument(s[1] - '0'));
if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
&& s[2] >= '1' && s[2] <= '9')
return MathAtom(new MathMacroArgument(s[2] - '0'));
if (s == "kern")
return MathAtom(new MathKernInset);
if (s == "xymatrix")
return MathAtom(new MathXYMatrixInset);
if (s == "xrightarrow" || s == "xleftarrow")
return MathAtom(new MathXArrowInset(s));
if (s == "split" || s == "gathered" || s == "aligned")
return MathAtom(new MathSplitInset(s));
if (s == "cases")
return MathAtom(new MathCasesInset);
if (s == "substack")
return MathAtom(new MathSubstackInset);
if (s == "subarray" || s == "array")
return MathAtom(new MathArrayInset(s, 1, 1));
if (s == "sqrt")
return MathAtom(new MathSqrtInset);
if (s == "root")
return MathAtom(new MathRootInset);
if (s == "stackrel")
return MathAtom(new MathStackrelInset);
if (s == "binom" || s == "choose")
return MathAtom(new MathBinomInset(s == "choose"));
if (s == "over" || s == "frac")
return MathAtom(new MathFracInset);
if (s == "atop")
return MathAtom(new MathFracInset(true));
if (s == "lefteqn")
return MathAtom(new MathLefteqnInset);
latexkeys const * l = in_word_set(s); latexkeys const * l = in_word_set(s);
if (l) { if (l) {
string const & inset = l->inset; string const & inset = l->inset;
@ -246,6 +212,42 @@ MathAtom createMathInset(string const & s)
return MathAtom(new MathSymbolInset(l)); return MathAtom(new MathSymbolInset(l));
} }
if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
return MathAtom(new MathMacroArgument(s[1] - '0'));
if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
&& s[2] >= '1' && s[2] <= '9')
return MathAtom(new MathMacroArgument(s[2] - '0'));
if (s == "kern")
return MathAtom(new MathKernInset);
if (s == "xymatrix")
return MathAtom(new MathXYMatrixInset);
if (s == "xrightarrow" || s == "xleftarrow")
return MathAtom(new MathXArrowInset(s));
if (s == "split" || s == "gathered" || s == "aligned")
return MathAtom(new MathSplitInset(s));
if (s == "cases")
return MathAtom(new MathCasesInset);
if (s == "substack")
return MathAtom(new MathSubstackInset);
if (s == "subarray" || s == "array")
return MathAtom(new MathArrayInset(s, 1, 1));
if (s == "sqrt")
return MathAtom(new MathSqrtInset);
if (s == "root")
return MathAtom(new MathRootInset);
if (s == "stackrel")
return MathAtom(new MathStackrelInset);
if (s == "binom" || s == "choose")
return MathAtom(new MathBinomInset(s == "choose"));
if (s == "over" || s == "frac")
return MathAtom(new MathFracInset);
if (s == "atop")
return MathAtom(new MathFracInset(true));
if (s == "lefteqn")
return MathAtom(new MathLefteqnInset);
if (s == "lyxert")
return MathAtom(new MathErtInset);
if (MathMacroTable::has(s)) if (MathMacroTable::has(s))
return MathAtom(new MathMacro(s)); return MathAtom(new MathMacro(s));

View File

@ -128,8 +128,8 @@ void MathGridInset::setDefaults()
{ {
if (ncols() <= 0) if (ncols() <= 0)
lyxerr << "positive number of columns expected\n"; lyxerr << "positive number of columns expected\n";
if (nrows() <= 0) //if (nrows() <= 0)
lyxerr << "positive number of rows expected\n"; // lyxerr << "positive number of rows expected\n";
for (col_type col = 0; col < ncols(); ++col) { for (col_type col = 0; col < ncols(); ++col) {
colinfo_[col].align_ = defaultColAlign(col); colinfo_[col].align_ = defaultColAlign(col);
colinfo_[col].skip_ = defaultColSpace(col); colinfo_[col].skip_ = defaultColSpace(col);

View File

@ -26,6 +26,13 @@ class MathGridInset : public MathNestInset {
int dummy_; int dummy_;
/// special multi colums alignment /// special multi colums alignment
string align_; string align_;
/// these should be a per-cell property, but ok to have it here
/// for single-column grids like paragraphs
mutable int glue_;
///
mutable pos_type begin_;
///
mutable pos_type end_;
}; };
/// additional per-row information /// additional per-row information
@ -198,9 +205,9 @@ public:
//void octavize(OctaveStream &) const; //void octavize(OctaveStream &) const;
protected: protected:
/// returns x offset of cell comapared to inset /// returns x offset of cell compared to inset
int cellXOffset(idx_type idx) const; int cellXOffset(idx_type idx) const;
/// returns y offset of cell comapared to inset /// returns y offset of cell compared to inset
int cellYOffset(idx_type idx) const; int cellYOffset(idx_type idx) const;
/// returns proper 'end of line' code for LaTeX /// returns proper 'end of line' code for LaTeX
string eolString(row_type row, bool fragile = false) const; string eolString(row_type row, bool fragile = false) const;
@ -209,6 +216,7 @@ protected:
/// extract number of columns from alignment string /// extract number of columns from alignment string
col_type guessColumns(string const & halign) const; col_type guessColumns(string const & halign) const;
public:
/// row info /// row info
std::vector<RowInfo> rowinfo_; std::vector<RowInfo> rowinfo_;
/// column info /// column info

View File

@ -280,7 +280,7 @@ WriteStream & operator<<(WriteStream & ws, MathArray const & ar)
WriteStream & operator<<(WriteStream & ws, char const * s) WriteStream & operator<<(WriteStream & ws, char const * s)
{ {
ws.os() << s; ws.os() << s;
ws.addlines(int(lyx::count(s, s+strlen(s), '\n'))); ws.addlines(int(lyx::count(s, s + strlen(s), '\n')));
return ws; return ws;
} }
@ -288,8 +288,10 @@ WriteStream & operator<<(WriteStream & ws, char const * s)
WriteStream & operator<<(WriteStream & ws, char c) WriteStream & operator<<(WriteStream & ws, char c)
{ {
ws.os() << c; ws.os() << c;
if (c == '\n') if (c == '\n') {
lyxerr << "writing a newline\n";
ws.addlines(1); ws.addlines(1);
}
return ws; return ws;
} }

View File

@ -3,7 +3,6 @@
#include "math_metricsinfo.h" #include "math_metricsinfo.h"
#include "math_support.h" #include "math_support.h"
#include "debug.h"
#include "frontends/Painter.h" #include "frontends/Painter.h"

View File

@ -7,9 +7,9 @@
using std::vector; using std::vector;
MathParboxInset::MathParboxInset() MathParboxInset::MathParboxInset()
: MathNestInset(1), lyx_width_(0), tex_width_("0mm"), : lyx_width_(0), tex_width_("0mm"), position_('c')
position_('c')
{ {
lyxerr << "constructing MathParboxInset\n"; lyxerr << "constructing MathParboxInset\n";
} }
@ -35,207 +35,23 @@ void MathParboxInset::setWidth(string const & w)
} }
int MathParboxInset::screenrows() const
{
return rows_.size();
}
int MathParboxInset::pos2row(pos_type pos) const
{
for (int r = 0, n = rows_.size(); r < n; ++r)
if (pos >= rows_[r].begin && pos <= rows_[r].end)
return r;
lyxerr << "illegal row for pos " << pos << "\n";
return 0;
}
void MathParboxInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const
{
int const r = pos2row(pos);
MathXArray const & ar = cells_[idx];
x = ar.xo() + ar.pos2x(rows_[r].begin, pos, rows_[r].glue);
y = ar.yo() + rows_[r].yo;
// move cursor visually into empty cells ("blue rectangles");
if (cell(0).empty())
x += 2;
//lyxerr << "getPos cursor at pos " << pos << " in row " << r
// << " x: " << x << " y: " << y << "\n";
}
bool MathParboxInset::idxUpDown(idx_type & idx, pos_type & pos, bool up,
int targetx) const
{
// try to move only one screen row up or down if possible
int row = pos2row(pos);
int const x = cells_[idx].pos2x(rows_[row].begin, pos, rows_[row].glue);
if (up) {
if (row == 0)
return false;
--row;
} else {
++row;
if (row == screenrows())
return false;
}
pos = xcell(0).x2pos(rows_[row].begin, x, rows_[row].glue);
return true;
}
void MathParboxInset::metrics(MathMetricsInfo & mi) const void MathParboxInset::metrics(MathMetricsInfo & mi) const
{ {
MathFontSetChanger dummy(mi.base, "textnormal"); MathFontSetChanger dummy1(mi.base, "textnormal");
MathWidthChanger dummy2(mi.base, lyx_width_);
// we do our own metrics fiddling MathTextInset::metrics(mi);
// delete old cache
rows_.clear();
#if 0
dim_ = xcell(0).metrics(mi);
#else
vector<Dimension> dims;
xcell(0).metricsExternal(mi, dims);
int spaces = 0;
Dimension safe;
Dimension curr;
safe.clear(mi.base.font);
curr.clear(mi.base.font);
int begin = 0;
int safepos = 0;
int yo = 0;
for (size_type i = 0, n = cell(0).size(); i < n; ++i) {
//lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos
// << " curr: " << curr << " safe: " << safe
// << " spaces: " << spaces << endl;
// 0 1 2 3 4 5 6
// <char> <char> <char> <space> <char> <char> <char>
// ................... <safe>
// ..........................<curr>
// ....................<safepos>
// Special handling of spaces. We reached a safe position for breaking.
if (cell(0)[i]->getChar() == ' ') {
//lyxerr << "reached safe pos\n";
// we don't count the space into the safe pos
safe += curr;
// we reset to this safepos if the next chunk does not fit
safepos = i;
++spaces;
// restart chunk with size of the space
curr.clear(mi.base.font);
curr += dims[i];
continue;
}
// This is a regular char. Go on if we either don't care for
// the width limit or have not reached that limit.
curr += dims[i];
if (curr.w + safe.w <= lyx_width_)
continue;
// We passed the limit. Create a row entry.
//lyxerr << "passed limit\n";
MathXArray::Row row;
if (spaces) {
// but we had a space break before this position.
// so retreat to this position
int glue = lyx_width_ - safe.w + dims[safepos].w;
row.dim = safe;
row.glue = glue / spaces;
row.begin = begin;
row.end = safepos; // this is position of the safe space
i = safepos; // i gets incremented at end of loop
begin = i + 1; // next chunk starts after the space
//lyxerr << "... but had safe pos. glue: " << row.glue << "\n";
//lyxerr << " safe.w: " << safe.w
// << " dim.w: " << dims[safepos].w << " spaces: " << spaces << "\n";
spaces = 0;
} else {
lyxerr << "... without safe pos\n";
// This item is too large and it is the only one.
// We have no choice but to produce an overfull box.
row.dim = curr; // safe should be 0.
row.glue = 0; // does not matter
row.begin = begin;
row.end = i + 1;
begin = i + 1;
}
row.yo = yo;
yo += row.dim.height();
rows_.push_back(row);
// in any case, start the new row with empty boxes
curr.clear(mi.base.font);
safe.clear(mi.base.font);
}
// last row: put in everything else
MathXArray::Row row;
row.dim = safe;
row.dim += curr;
row.begin = begin;
row.end = cell(0).size();
row.glue = 0; // last line is left aligned
row.yo = yo;
rows_.push_back(row);
// what to report?
dim_.w = lyx_width_;
dim_.a = rows_.front().dim.a;
dim_.d = rows_.back().dim.d + yo;
metricsMarkers2(); metricsMarkers2();
xcell(0).setDim(dim_);
#endif
} }
void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const
{ {
MathFontSetChanger dummy(pi.base, "textnormal"); MathFontSetChanger dummy(pi.base, "textnormal");
#if 0 MathTextInset::draw(pi, x + 1, y);
xcell(0).draw(pi, x + 1, y);
#else
xcell(0).drawExternal(pi, x + 1, y, rows_);
#endif
drawMarkers2(pi, x, y); drawMarkers2(pi, x, y);
} }
void MathParboxInset::drawSelection(MathPainterInfo & pi,
idx_type, pos_type pos1, idx_type, pos_type pos2) const
{
int row1 = pos2row(pos1);
int row2 = pos2row(pos2);
if (row1 == row2) {
/*
MathXArray & c = xcell(0);
int x1 = c.xo() + c.pos2x(i1.pos_);
int y1 = c.yo() - c.ascent();
int x2 = c.xo() + c.pos2x(i2.pos_);
int y2 = c.yo() + c.descent();
pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
} else {
vector<MathInset::idx_type> indices = idxBetween(idx1, idx2);
for (unsigned i = 0; i < indices.size(); ++i) {
MathXArray & c = i1.xcell(indices[i]);
int x1 = c.xo();
int y1 = c.yo() - c.ascent();
int x2 = c.xo() + c.width();
int y2 = c.yo() + c.descent();
pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
}
*/
}
}
void MathParboxInset::write(WriteStream & os) const void MathParboxInset::write(WriteStream & os) const
{ {
os << "\\parbox"; os << "\\parbox";

View File

@ -1,9 +1,11 @@
#ifndef MATH_PARBOXINSET_H #ifndef MATH_PARBOXINSET_H
#define MATH_PARBOXINSET_H #define MATH_PARBOXINSET_H
#include "math_nestinset.h" #include "math_textinset.h"
class MathParboxInset : public MathNestInset { // implements support for \parbox
class MathParboxInset : public MathTextInset {
public: public:
/// ///
MathParboxInset(); MathParboxInset();
@ -13,15 +15,10 @@ public:
MathInset * clone() const; MathInset * clone() const;
/// ///
mode_type currentMode() const { return TEXT_MODE; } mode_type currentMode() const { return TEXT_MODE; }
/// get cursor position
void getPos(idx_type idx, pos_type pos, int & x, int & y) const;
/// ///
void metrics(MathMetricsInfo & mi) const; void metrics(MathMetricsInfo & mi) const;
/// ///
void draw(MathPainterInfo &, int x, int y) const; void draw(MathPainterInfo &, int x, int y) const;
/// draw selection background
void drawSelection(MathPainterInfo & pi,
idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const;
/// ///
void infoize(std::ostream & os) const; void infoize(std::ostream & os) const;
/// ///
@ -30,21 +27,13 @@ public:
void setWidth(string const & width); void setWidth(string const & width);
/// ///
void setPosition(string const & pos); void setPosition(string const & pos);
/// moves cursor up or down
bool idxUpDown(idx_type &, pos_type & pos, bool up, int targetx) const;
private: private:
/// number of rows on screen
int screenrows() const;
/// row corresponding to given position
int pos2row(pos_type pos) const;
/// width on screen /// width on screen
int lyx_width_; int lyx_width_;
/// width for TeX /// width for TeX
string tex_width_; string tex_width_;
/// htb /// one of htb
char position_; char position_;
/// cached metrics
mutable std::vector<MathXArray::Row> rows_;
}; };
#endif #endif

View File

@ -4,12 +4,6 @@
#include "debug.h" #include "debug.h"
MathParInset::MathParInset()
{
lyxerr << "constructing MathParInset\n";
}
void MathParInset::metrics(MathMetricsInfo & mi) const void MathParInset::metrics(MathMetricsInfo & mi) const
{ {
MathFontSetChanger dummy1(mi.base, "textnormal"); MathFontSetChanger dummy1(mi.base, "textnormal");

View File

@ -6,7 +6,7 @@
class MathParInset : public MathHullInset { class MathParInset : public MathHullInset {
public: public:
/// ///
MathParInset(); MathParInset() {}
/// ///
mode_type currentMode() const { return TEXT_MODE; } mode_type currentMode() const { return TEXT_MODE; }
/// ///

View File

@ -69,14 +69,12 @@ following hack as starting point to write some macros:
#include "support/lstrings.h" #include "support/lstrings.h"
#include <cctype> #include <cctype>
#include <stack>
#include <algorithm> #include <algorithm>
using std::istream; using std::istream;
using std::ostream; using std::ostream;
using std::ios; using std::ios;
using std::endl; using std::endl;
using std::stack;
using std::fill; using std::fill;
using std::vector; using std::vector;
using std::atoi; using std::atoi;
@ -156,7 +154,7 @@ void catInit()
theCatcode[''] = catIgnore; theCatcode[''] = catIgnore;
theCatcode[' '] = catSpace; theCatcode[' '] = catSpace;
theCatcode['\t'] = catSpace; theCatcode['\t'] = catSpace;
theCatcode['\r'] = catSpace; theCatcode['\r'] = catNewline;
theCatcode['~'] = catActive; theCatcode['~'] = catActive;
theCatcode['%'] = catComment; theCatcode['%'] = catComment;
} }
@ -184,8 +182,6 @@ public:
char character() const { return char_; } char character() const { return char_; }
/// ///
string asString() const; string asString() const;
///
bool isCR() const;
private: private:
/// ///
@ -196,11 +192,6 @@ private:
CatCode cat_; CatCode cat_;
}; };
bool Token::isCR() const
{
return cs_ == "\\" || cs_ == "cr" || cs_ == "crcr";
}
string Token::asString() const string Token::asString() const
{ {
return cs_.size() ? cs_ : string(1, char_); return cs_.size() ? cs_ : string(1, char_);
@ -371,6 +362,17 @@ string Parser::getArg(char left, char right)
} }
void Parser::skipSpaceTokens(istream & is, char c)
{
// skip trailing spaces
while (catcode(c) == catSpace || catcode(c) == catNewline)
if (!is.get(c))
break;
//lyxerr << "putting back: " << c << "\n";
is.putback(c);
}
void Parser::tokenize(istream & is) void Parser::tokenize(istream & is)
{ {
// eat everything up to the next \end_inset or end of stream // eat everything up to the next \end_inset or end of stream
@ -390,17 +392,6 @@ void Parser::tokenize(istream & is)
} }
void Parser::skipSpaceTokens(istream & is, char c)
{
// skip trailing spaces
while (catcode(c) == catSpace || catcode(c) == catNewline)
if (!is.get(c))
break;
//lyxerr << "putting back: " << c << "\n";
is.putback(c);
}
void Parser::tokenize(string const & buffer) void Parser::tokenize(string const & buffer)
{ {
static bool init_done = false; static bool init_done = false;
@ -423,7 +414,7 @@ void Parser::tokenize(string const & buffer)
if (catcode(c) == catNewline) if (catcode(c) == catNewline)
; //push_back(Token("par")); ; //push_back(Token("par"));
else { else {
push_back(Token(' ', catSpace)); push_back(Token('\n', catNewline));
is.putback(c); is.putback(c);
} }
break; break;
@ -620,6 +611,9 @@ void Parser::parse1(MathGridInset & grid, unsigned flags,
else if (t.cat() == catSpace && !mathmode) else if (t.cat() == catSpace && !mathmode)
cell->push_back(MathAtom(new MathCharInset(t.character()))); cell->push_back(MathAtom(new MathCharInset(t.character())));
else if (t.cat() == catNewline && !mathmode)
cell->push_back(MathAtom(new MathCharInset(t.character())));
else if (t.cat() == catParameter) { else if (t.cat() == catParameter) {
Token const & n = getToken(); Token const & n = getToken();
cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0'))); cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
@ -1065,8 +1059,13 @@ void Parser::parse1(MathGridInset & grid, unsigned flags,
else { else {
MathAtom p = createMathInset(t.cs()); MathAtom p = createMathInset(t.cs());
bool mode = mathmode;
if (mathmode && p->currentMode() == MathInset::TEXT_MODE)
mode = false;
if (!mathmode && p->currentMode() == MathInset::MATH_MODE)
mode = true;
for (MathInset::idx_type i = 0; i < p->nargs(); ++i) for (MathInset::idx_type i = 0; i < p->nargs(); ++i)
parse(p->cell(i), FLAG_ITEM, mathmode); parse(p->cell(i), FLAG_ITEM, mode);
cell->push_back(p); cell->push_back(p);
} }
} }

View File

@ -355,10 +355,10 @@ void MathScriptInset::write(WriteStream & os) const
os << "{}"; os << "{}";
} }
if (hasDown() && down().data().size()) if (hasDown() && down().size())
os << "_{" << down().data() << '}'; os << "_{" << down().data() << '}';
if (hasUp() && up().data().size()) if (hasUp() && up().size())
os << "^{" << up().data() << '}'; os << "^{" << up().data() << '}';
} }
@ -423,8 +423,8 @@ void MathScriptInset::mathematicize(MathematicaStream & os) const
void MathScriptInset::mathmlize( MathMLStream & os) const void MathScriptInset::mathmlize( MathMLStream & os) const
{ {
bool d = hasDown() && down().data().size(); bool d = hasDown() && down().size();
bool u = hasUp() && up().data().size(); bool u = hasUp() && up().size();
if (u && d) if (u && d)
os << MTag("msubsup"); os << MTag("msubsup");

View File

@ -557,6 +557,7 @@ fontinfo fontinfos[] = {
{"textipa", inh_family, inh_series, inh_shape, LColor::black}, {"textipa", inh_family, inh_series, inh_shape, LColor::black},
{"lyxtex", inh_family, inh_series, inh_shape, LColor::latex}, {"lyxtex", inh_family, inh_series, inh_shape, LColor::latex},
{"lyxert", LyXFont::TYPEWRITER_FAMILY, inh_series, inh_shape, LColor::latex},
{"lyxsymbol", LyXFont::SYMBOL_FAMILY, inh_series, inh_shape, LColor::math}, {"lyxsymbol", LyXFont::SYMBOL_FAMILY, inh_series, inh_shape, LColor::math},
{"lyxboldsymbol", {"lyxboldsymbol",
LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES, inh_shape, LColor::math}, LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES, inh_shape, LColor::math},

165
src/mathed/math_textinset.C Normal file
View File

@ -0,0 +1,165 @@
#include "math_textinset.h"
#include "debug.h"
MathTextInset::MathTextInset()
: MathNestInset(1)
{}
MathInset * MathTextInset::clone() const
{
return new MathTextInset(*this);
}
MathInset::idx_type MathTextInset::pos2row(pos_type pos) const
{
for (pos_type r = 0, n = cache_.nargs(); r < n; ++r)
if (pos >= cache_.cellinfo_[r].begin_ && pos <= cache_.cellinfo_[r].end_)
return r;
lyxerr << "illegal row for pos " << pos << "\n";
return 0;
}
void MathTextInset::getPos(idx_type, pos_type pos, int & x, int & y) const
{
idx_type const i = pos2row(pos);
pos_type const p = pos - cache_.cellinfo_[i].begin_;
cache_.getPos(i, p, x, y);
}
bool MathTextInset::idxUpDown(idx_type &, pos_type & pos, bool up,
int targetx) const
{
// try to move only one screen row up or down if possible
idx_type i = pos2row(pos);
MathGridInset::CellInfo const & cell1 = cache_.cellinfo_[i];
int const x = cells_[0].pos2x(cell1.begin_, pos, cell1.glue_);
if (up) {
if (i == 0)
return false;
--i;
} else {
++i;
if (i == cache_.nargs())
return false;
}
MathGridInset::CellInfo const & cell2 = cache_.cellinfo_[i];
pos = xcell(0).x2pos(cell2.begin_, x, cell2.glue_);
return true;
}
void MathTextInset::metrics(MathMetricsInfo & mi) const
{
xcell(0).metrics(mi);
// we do our own metrics fiddling
// delete old cache
cache_ = MathGridInset(1, 0);
int spaces = 0;
int safe = 0;
int curr = 0;
int begin = 0;
int safepos = 0;
for (size_type i = 0, n = cell(0).size(); i < n; ++i) {
//lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos
// << " curr: " << curr << " safe: " << safe
// << " spaces: " << spaces << endl;
// 0 1 2 3 4 5 6
// <char> <char> <char> <space> <char> <char> <char>
// ................... <safe>
// ..........................<curr>
// ....................<safepos>
// Special handling of spaces. We reached a safe position for breaking.
char const c = cell(0)[i]->getChar();
if (c == ' ') {
//lyxerr << "reached safe pos\n";
// we don't count the space into the safe pos
safe += curr;
// we reset to this safepos if the next chunk does not fit
safepos = i;
++spaces;
// restart chunk with size of the space
curr = cell(0)[i]->width();
continue;
}
if (c != '\n') {
// This is a regular char. Go on if we either don't care for
// the width limit or have not reached that limit.
curr += cell(0)[i]->width();
if (!mi.base.restrictwidth || curr + safe <= mi.base.textwidth)
continue;
}
// We passed the limit. Create a row entry.
//lyxerr << "passed limit\n";
cache_.appendRow();
MathXArray & ar = cache_.xcell(cache_.nargs() - 1);
MathGridInset::CellInfo & row = cache_.cellinfo_.back();
if (c == '\n') {
// we are here because we hit a hard newline
row.begin_ = begin;
row.end_ = i + 1;
begin = i + 1; // next chunk starts after the newline
spaces = 0;
} else if (spaces) {
// but we had a space break before this position.
// so retreat to this position
//lyxerr << "... but had safe pos.\n";
row.begin_ = begin;
row.end_ = safepos; // this is position of the safe space
i = safepos; // i gets incremented at end of loop
begin = i + 1; // next chunk starts after the space
spaces = 0;
} else {
// This item is too large and it is the only one.
// We have no choice but to produce an overfull box.
lyxerr << "... without safe pos\n";
row.begin_ = begin;
row.end_ = i + 1;
begin = i + 1;
}
ar.data() =
MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_);
//lyxerr << "line: " << ar << "\n";
// in any case, start the new row with empty boxes
curr = 0;
safe = 0;
}
// last row: put in everything else
cache_.appendRow();
MathXArray & ar = cache_.xcell(cache_.nargs() - 1);
MathGridInset::CellInfo & row = cache_.cellinfo_.back();
row.begin_ = begin;
row.end_ = cell(0).size();
ar.data() =
MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_);
//lyxerr << "last line: " << ar.data() << "\n";
// what to report?
cache_.metrics(mi);
dim_ = cache_.dimensions();
//lyxerr << "outer dim: " << dim_ << endl;
}
void MathTextInset::draw(MathPainterInfo & pi, int x, int y) const
{
cache_.draw(pi, x + 1, y);
}
void MathTextInset::drawSelection(MathPainterInfo & pi,
idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const
{
cache_.drawSelection(pi, idx1, pos1, idx2, pos2);
}

View File

@ -0,0 +1,32 @@
#ifndef MATH_TEXTINSET_H
#define MATH_TEXTINSET_H
#include "math_gridinset.h"
// not yet a substitute for the real text inset...
class MathTextInset : public MathNestInset {
public:
///
MathTextInset();
///
MathInset * clone() const;
/// get cursor position
void getPos(idx_type idx, pos_type pos, int & x, int & y) const;
/// this stores metrics information in cache_
void metrics(MathMetricsInfo & mi) const;
/// draw according to cached metrics
void draw(MathPainterInfo &, int x, int y) const;
/// draw selection background
void drawSelection(MathPainterInfo & pi,
idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const;
/// moves cursor up or down
bool idxUpDown(idx_type &, pos_type & pos, bool up, int targetx) const;
protected:
/// row corresponding to given position
idx_type pos2row(pos_type pos) const;
/// cached metrics
mutable MathGridInset cache_;
};
#endif

View File

@ -50,38 +50,11 @@ Dimension const & MathXArray::metrics(MathMetricsInfo & mi) const
} }
void MathXArray::metricsExternal(MathMetricsInfo & mi,
std::vector<Dimension> & v) const
{
//if (clean_)
// return;
clean_ = true;
drawn_ = false;
if (empty()) {
mathed_char_dim(mi.base.font, 'I', dim_);
return;
}
dim_.clear();
for (const_iterator it = begin(), et = end(); it != et; ++it) {
MathInset const * p = it->nucleus();
p->metrics(mi);
v.push_back(p->dimensions());
}
//for (int i = 0; i < size(); ++i)
// lyxerr << "i: " << i << " dim: " << v[i] << endl;
//lyxerr << "MathXArray::metrics(): '" << dim_ << "\n";
}
void MathXArray::draw(MathPainterInfo & pi, int x, int y) const void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
{ {
//if (drawn_ && x == xo_ && y == yo_) //if (drawn_ && x == xo_ && y == yo_)
// return; // return;
//lyxerr << "MathXArray::draw: x: " << x << " y: " << y << endl;
//lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
xo_ = x; xo_ = x;
yo_ = y; yo_ = y;
@ -96,48 +69,18 @@ void MathXArray::draw(MathPainterInfo & pi, int x, int y) const
if (x >= pi.pain.paperWidth()) // don't draw right of workarea if (x >= pi.pain.paperWidth()) // don't draw right of workarea
return; return;
const_iterator it = begin(), et = end(); if (empty()) {
if (it == et) {
pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline); pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
return; return;
} }
for (; it != et; ++it) { for (const_iterator it = begin(), et = end(); it != et; ++it) {
(*it)->draw(pi, x, y); (*it)->draw(pi, x, y);
x += (*it)->width(); x += (*it)->width();
} }
} }
void MathXArray::drawExternal(MathPainterInfo & pi, int x, int y,
std::vector<Row> const & v) const
{
//for (size_type r = 0; r < v.size(); ++r)
// lyxerr << "row " << r << " to: " << v[r].end << endl;
//lyxerr << " data: " << *this << endl;
xo_ = x;
yo_ = y;
for (size_type r = 0; r < v.size(); ++r) {
int xx = x;
int yy = y + v[r].yo;
for (size_type pos = v[r].begin; pos < v[r].end && pos < size(); ++pos) {
//lyxerr << "drawing pos " << pos << " of " << size()
// << " " << int(operator[](pos)->getChar()) << endl;
MathInset const * p = operator[](pos).nucleus();
// insert extra glue if necessary
if (p->getChar() == ' ')
xx += v[r].glue;
// ordinary case
p->draw(pi, xx, yy);
xx += p->width();
}
}
}
Dimension const & MathXArray::metricsT(TextMetricsInfo const & mi) const Dimension const & MathXArray::metricsT(TextMetricsInfo const & mi) const
{ {
//if (clean_) //if (clean_)
@ -155,19 +98,14 @@ void MathXArray::drawT(TextPainter & pain, int x, int y) const
{ {
//if (drawn_ && x == xo_ && y == yo_) //if (drawn_ && x == xo_ && y == yo_)
// return; // return;
//lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl; //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
xo_ = x; xo_ = x;
yo_ = y; yo_ = y;
drawn_ = true; drawn_ = true;
const_iterator it = begin(), et = end(); for (const_iterator it = begin(), et = end(); it != et; ++it) {
(*it)->drawT(pain, x, y);
for (; it != et; ++it) { x += (*it)->width();
MathInset const * p = it->nucleus();
p->drawT(pain, x, y);
x += p->width();
} }
} }
@ -282,3 +220,10 @@ void MathXArray::towards(int & x, int & y) const
x = cx + int(r * (x - cx)); x = cx + int(r * (x - cx));
y = cy + int(r * (y - cy)); y = cy + int(r * (y - cy));
} }
std::ostream & operator<<(std::ostream & os, MathXArray const & ar)
{
os << ar.data();
}

View File

@ -36,34 +36,12 @@ public:
MathArray & data() { return *this; } MathArray & data() { return *this; }
MathArray const & data() const { return *this; } MathArray const & data() const { return *this; }
// helper structure for external metrics computations as done
// in parboxes
struct Row {
/// constructor
Row() {}
/// first position of this row
size_type begin;
/// last position of this row plus one
size_type end;
/// y offset relative to yo
int yo;
/// dimensions of this row
Dimension dim;
/// glue between words
int glue;
};
/// constructor /// constructor
MathXArray(); MathXArray();
/// rebuild cached metrics information /// rebuild cached metrics information
Dimension const & metrics(MathMetricsInfo & mi) const; Dimension const & metrics(MathMetricsInfo & mi) const;
/// rebuild cached metrics information
void metricsExternal(MathMetricsInfo & mi, std::vector<Dimension> &) const;
/// redraw cell using cache metrics information /// redraw cell using cache metrics information
void draw(MathPainterInfo & pi, int x, int y) const; void draw(MathPainterInfo & pi, int x, int y) const;
/// redraw cell using external metrics information
void drawExternal(MathPainterInfo & pi, int x, int y,
std::vector<MathXArray::Row> const &) const;
/// rebuild cached metrics information /// rebuild cached metrics information
Dimension const & metricsT(TextMetricsInfo const & mi) const; Dimension const & metricsT(TextMetricsInfo const & mi) const;
/// redraw cell using cache metrics information /// redraw cell using cache metrics information