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_envinset.C \
math_envinset.h \
math_ertinset.C \
math_ertinset.h \
math_extern.C \
math_extern.h \
math_exfuncinset.C \
@ -134,6 +136,8 @@ libmathed_la_SOURCES = \
math_support.h \
math_symbolinset.C \
math_symbolinset.h \
math_textinset.C \
math_textinset.h \
math_unknowninset.C \
math_unknowninset.h \
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);
//x -= xo_;
y -= yo_;
@ -403,6 +405,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
if (!mathcursor)
return UNDISPATCHED;
string argument = arg;
RESULT result = DISPATCHED;
bool sel = false;
@ -696,11 +699,6 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
result = UNDISPATCHED;
break;
case LFUN_BREAKPARAGRAPH:
case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
//lyxerr << "LFUN ignored\n";
break;
case LFUN_INSET_ERT:
// interpret this as if a backslash was typed
bv->lockedInsetStoreUndo(Undo::EDIT);
@ -708,15 +706,21 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action,
updateLocal(bv, true);
break;
case LFUN_BREAKPARAGRAPH:
case LFUN_BREAKPARAGRAPHKEEPLAYOUT:
case LFUN_BREAKPARAGRAPH_SKIP:
argument = "\n";
// fall through
case -1:
case LFUN_INSERT_MATH:
case LFUN_SELFINSERT:
if (!arg.empty()) {
if (!argument.empty()) {
bv->lockedInsetStoreUndo(Undo::EDIT);
if (arg.size() == 1)
result = mathcursor->interpret(arg[0]) ? DISPATCHED : FINISHED_RIGHT;
if (argument.size() == 1)
result = mathcursor->interpret(argument[0]) ? DISPATCHED : FINISHED_RIGHT;
else
result = mathcursor->interpret(arg) ? DISPATCHED : FINISHED_RIGHT;
result = mathcursor->interpret(argument) ? DISPATCHED : FINISHED_RIGHT;
updateLocal(bv, true);
}
break;

View File

@ -1399,6 +1399,12 @@ bool MathCursor::interpret(char c)
return true;
}
if (c == '\n') {
if (currentMode() == MathInset::TEXT_MODE)
insert(c);
return true;
}
if (c == ' ') {
if (currentMode() == MathInset::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_decorationinset.h"
#include "math_dotsinset.h"
#include "math_ertinset.h"
#include "math_fboxinset.h"
#include "math_fontinset.h"
#include "math_fontoldinset.h"
@ -180,41 +181,6 @@ latexkeys const * in_word_set(string const & str)
MathAtom createMathInset(string const & s)
{
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);
if (l) {
string const & inset = l->inset;
@ -246,6 +212,42 @@ MathAtom createMathInset(string const & s)
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))
return MathAtom(new MathMacro(s));

View File

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

View File

@ -26,6 +26,13 @@ class MathGridInset : public MathNestInset {
int dummy_;
/// special multi colums alignment
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
@ -198,9 +205,9 @@ public:
//void octavize(OctaveStream &) const;
protected:
/// returns x offset of cell comapared to inset
/// returns x offset of cell compared to inset
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;
/// returns proper 'end of line' code for LaTeX
string eolString(row_type row, bool fragile = false) const;
@ -209,6 +216,7 @@ protected:
/// extract number of columns from alignment string
col_type guessColumns(string const & halign) const;
public:
/// row info
std::vector<RowInfo> rowinfo_;
/// column info

View File

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

View File

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

View File

@ -7,9 +7,9 @@
using std::vector;
MathParboxInset::MathParboxInset()
: MathNestInset(1), lyx_width_(0), tex_width_("0mm"),
position_('c')
: lyx_width_(0), tex_width_("0mm"), position_('c')
{
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
{
MathFontSetChanger dummy(mi.base, "textnormal");
// we do our own metrics fiddling
// 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;
MathFontSetChanger dummy1(mi.base, "textnormal");
MathWidthChanger dummy2(mi.base, lyx_width_);
MathTextInset::metrics(mi);
metricsMarkers2();
xcell(0).setDim(dim_);
#endif
}
void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const
{
MathFontSetChanger dummy(pi.base, "textnormal");
#if 0
xcell(0).draw(pi, x + 1, y);
#else
xcell(0).drawExternal(pi, x + 1, y, rows_);
#endif
MathTextInset::draw(pi, x + 1, 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
{
os << "\\parbox";

View File

@ -1,9 +1,11 @@
#ifndef 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:
///
MathParboxInset();
@ -13,15 +15,10 @@ public:
MathInset * clone() const;
///
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 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;
///
@ -30,21 +27,13 @@ public:
void setWidth(string const & width);
///
void setPosition(string const & pos);
/// moves cursor up or down
bool idxUpDown(idx_type &, pos_type & pos, bool up, int targetx) const;
private:
/// number of rows on screen
int screenrows() const;
/// row corresponding to given position
int pos2row(pos_type pos) const;
/// width on screen
int lyx_width_;
/// width for TeX
string tex_width_;
/// htb
/// one of htb
char position_;
/// cached metrics
mutable std::vector<MathXArray::Row> rows_;
};
#endif

View File

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

View File

@ -6,7 +6,7 @@
class MathParInset : public MathHullInset {
public:
///
MathParInset();
MathParInset() {}
///
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 <cctype>
#include <stack>
#include <algorithm>
using std::istream;
using std::ostream;
using std::ios;
using std::endl;
using std::stack;
using std::fill;
using std::vector;
using std::atoi;
@ -156,7 +154,7 @@ void catInit()
theCatcode[''] = catIgnore;
theCatcode[' '] = catSpace;
theCatcode['\t'] = catSpace;
theCatcode['\r'] = catSpace;
theCatcode['\r'] = catNewline;
theCatcode['~'] = catActive;
theCatcode['%'] = catComment;
}
@ -184,8 +182,6 @@ public:
char character() const { return char_; }
///
string asString() const;
///
bool isCR() const;
private:
///
@ -196,11 +192,6 @@ private:
CatCode cat_;
};
bool Token::isCR() const
{
return cs_ == "\\" || cs_ == "cr" || cs_ == "crcr";
}
string Token::asString() const
{
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)
{
// 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)
{
static bool init_done = false;
@ -423,7 +414,7 @@ void Parser::tokenize(string const & buffer)
if (catcode(c) == catNewline)
; //push_back(Token("par"));
else {
push_back(Token(' ', catSpace));
push_back(Token('\n', catNewline));
is.putback(c);
}
break;
@ -620,6 +611,9 @@ void Parser::parse1(MathGridInset & grid, unsigned flags,
else if (t.cat() == catSpace && !mathmode)
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) {
Token const & n = getToken();
cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0')));
@ -1065,8 +1059,13 @@ void Parser::parse1(MathGridInset & grid, unsigned flags,
else {
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)
parse(p->cell(i), FLAG_ITEM, mathmode);
parse(p->cell(i), FLAG_ITEM, mode);
cell->push_back(p);
}
}

View File

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

View File

@ -557,6 +557,7 @@ fontinfo fontinfos[] = {
{"textipa", inh_family, inh_series, inh_shape, LColor::black},
{"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},
{"lyxboldsymbol",
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
{
//if (drawn_ && x == xo_ && y == yo_)
// return;
//lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
//lyxerr << "MathXArray::draw: x: " << x << " y: " << y << endl;
xo_ = x;
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
return;
const_iterator it = begin(), et = end();
if (it == et) {
if (empty()) {
pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline);
return;
}
for (; it != et; ++it) {
for (const_iterator it = begin(), et = end(); it != et; ++it) {
(*it)->draw(pi, x, y);
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
{
//if (clean_)
@ -155,19 +98,14 @@ void MathXArray::drawT(TextPainter & pain, int x, int y) const
{
//if (drawn_ && x == xo_ && y == yo_)
// return;
//lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl;
xo_ = x;
yo_ = y;
drawn_ = true;
const_iterator it = begin(), et = end();
for (; it != et; ++it) {
MathInset const * p = it->nucleus();
p->drawT(pain, x, y);
x += p->width();
for (const_iterator it = begin(), et = end(); it != et; ++it) {
(*it)->drawT(pain, x, y);
x += (*it)->width();
}
}
@ -282,3 +220,10 @@ void MathXArray::towards(int & x, int & y) const
x = cx + int(r * (x - cx));
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 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
MathXArray();
/// rebuild cached metrics information
Dimension const & metrics(MathMetricsInfo & mi) const;
/// rebuild cached metrics information
void metricsExternal(MathMetricsInfo & mi, std::vector<Dimension> &) const;
/// redraw cell using cache metrics information
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
Dimension const & metricsT(TextMetricsInfo const & mi) const;
/// redraw cell using cache metrics information