2002-07-08 11:29:51 +00:00
|
|
|
|
|
|
|
#include "math_parboxinset.h"
|
|
|
|
#include "math_mathmlstream.h"
|
|
|
|
#include "math_streamstr.h"
|
|
|
|
#include "lyxlength.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
2002-07-17 12:07:57 +00:00
|
|
|
using std::vector;
|
2002-07-08 11:29:51 +00:00
|
|
|
|
|
|
|
MathParboxInset::MathParboxInset()
|
|
|
|
: MathNestInset(1), lyx_width_(0), tex_width_("0mm"),
|
|
|
|
position_('c')
|
|
|
|
{
|
|
|
|
lyxerr << "constructing MathParboxInset\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MathInset * MathParboxInset::clone() const
|
|
|
|
{
|
|
|
|
return new MathParboxInset(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MathParboxInset::setPosition(string const & p)
|
|
|
|
{
|
|
|
|
position_ = p.size() > 0 ? p[0] : 'c';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MathParboxInset::setWidth(string const & w)
|
|
|
|
{
|
|
|
|
tex_width_ = w;
|
|
|
|
lyx_width_ = LyXLength(w).inBP();
|
|
|
|
lyxerr << "setting " << w << " to " << lyx_width_ << " pixel\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-26 13:13:20 +00:00
|
|
|
int MathParboxInset::screenrows() const
|
|
|
|
{
|
|
|
|
return rows_.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-17 10:25:33 +00:00
|
|
|
int MathParboxInset::pos2row(pos_type pos) const
|
|
|
|
{
|
|
|
|
for (int r = 0, n = rows_.size(); r < n; ++r)
|
2002-07-26 13:13:20 +00:00
|
|
|
if (pos >= rows_[r].begin && pos <= rows_[r].end)
|
2002-07-17 10:25:33 +00:00
|
|
|
return r;
|
|
|
|
lyxerr << "illegal row for pos " << pos << "\n";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-16 18:22:45 +00:00
|
|
|
void MathParboxInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const
|
|
|
|
{
|
2002-07-17 10:25:33 +00:00
|
|
|
int const r = pos2row(pos);
|
2002-07-26 13:13:20 +00:00
|
|
|
MathXArray const & ar = cells_[idx];
|
|
|
|
x = ar.xo() + ar.pos2x(rows_[r].begin, pos, rows_[r].glue);
|
|
|
|
y = ar.yo() + rows_[r].yo;
|
2002-07-16 18:22:45 +00:00
|
|
|
// move cursor visually into empty cells ("blue rectangles");
|
|
|
|
if (cell(0).empty())
|
|
|
|
x += 2;
|
2002-07-26 13:13:20 +00:00
|
|
|
//lyxerr << "getPos cursor at pos " << pos << " in row " << r
|
|
|
|
// << " x: " << x << " y: " << y << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-30 13:56:02 +00:00
|
|
|
bool MathParboxInset::idxUpDown(idx_type & idx, pos_type & pos, bool up,
|
|
|
|
int targetx) const
|
2002-07-26 13:13:20 +00:00
|
|
|
{
|
|
|
|
// 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;
|
2002-07-16 18:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-08 11:29:51 +00:00
|
|
|
void MathParboxInset::metrics(MathMetricsInfo & mi) const
|
|
|
|
{
|
2002-07-09 08:24:33 +00:00
|
|
|
MathFontSetChanger dummy(mi.base, "textnormal");
|
|
|
|
|
|
|
|
// we do our own metrics fiddling
|
|
|
|
// delete old cache
|
|
|
|
rows_.clear();
|
|
|
|
|
2002-07-16 18:22:45 +00:00
|
|
|
#if 0
|
2002-07-09 08:24:33 +00:00
|
|
|
|
2002-07-11 11:27:24 +00:00
|
|
|
dim_ = xcell(0).metrics(mi);
|
2002-07-09 08:24:33 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2002-07-16 18:22:45 +00:00
|
|
|
vector<Dimension> dims;
|
|
|
|
xcell(0).metricsExternal(mi, dims);
|
2002-07-09 08:24:33 +00:00
|
|
|
|
|
|
|
int spaces = 0;
|
2002-07-16 18:22:45 +00:00
|
|
|
Dimension safe;
|
|
|
|
Dimension curr;
|
|
|
|
safe.clear(mi.base.font);
|
|
|
|
curr.clear(mi.base.font);
|
|
|
|
int begin = 0;
|
2002-07-09 08:24:33 +00:00
|
|
|
int safepos = 0;
|
|
|
|
int yo = 0;
|
2002-07-16 18:22:45 +00:00
|
|
|
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>
|
|
|
|
|
2002-07-09 08:24:33 +00:00
|
|
|
// Special handling of spaces. We reached a safe position for breaking.
|
|
|
|
if (cell(0)[i]->getChar() == ' ') {
|
2002-07-16 18:22:45 +00:00
|
|
|
//lyxerr << "reached safe pos\n";
|
|
|
|
// we don't count the space into the safe pos
|
2002-07-09 08:24:33 +00:00
|
|
|
safe += curr;
|
2002-07-16 18:22:45 +00:00
|
|
|
// we reset to this safepos if the next chunk does not fit
|
|
|
|
safepos = i;
|
2002-07-09 08:24:33 +00:00
|
|
|
++spaces;
|
2002-07-16 18:22:45 +00:00
|
|
|
// restart chunk with size of the space
|
|
|
|
curr.clear(mi.base.font);
|
|
|
|
curr += dims[i];
|
2002-07-09 08:24:33 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-07-16 18:22:45 +00:00
|
|
|
// This is a regular char. Go on if we either don't care for
|
2002-07-09 08:24:33 +00:00
|
|
|
// the width limit or have not reached that limit.
|
2002-07-16 18:22:45 +00:00
|
|
|
curr += dims[i];
|
2002-07-09 08:24:33 +00:00
|
|
|
if (curr.w + safe.w <= lyx_width_)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We passed the limit. Create a row entry.
|
2002-07-16 18:22:45 +00:00
|
|
|
//lyxerr << "passed limit\n";
|
2002-07-09 08:24:33 +00:00
|
|
|
MathXArray::Row row;
|
|
|
|
if (spaces) {
|
|
|
|
// but we had a space break before this position.
|
2002-07-16 18:22:45 +00:00
|
|
|
// so retreat to this position
|
2002-07-26 13:13:20 +00:00
|
|
|
int glue = lyx_width_ - safe.w + dims[safepos].w;
|
2002-07-16 18:22:45 +00:00
|
|
|
row.dim = safe;
|
2002-07-26 13:13:20 +00:00
|
|
|
row.glue = glue / spaces;
|
2002-07-16 18:22:45 +00:00
|
|
|
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";
|
2002-07-26 13:13:20 +00:00
|
|
|
//lyxerr << " safe.w: " << safe.w
|
|
|
|
// << " dim.w: " << dims[safepos].w << " spaces: " << spaces << "\n";
|
2002-07-09 08:24:33 +00:00
|
|
|
spaces = 0;
|
|
|
|
} else {
|
2002-07-16 18:22:45 +00:00
|
|
|
lyxerr << "... without safe pos\n";
|
2002-07-09 08:24:33 +00:00
|
|
|
// This item is too large and it is the only one.
|
|
|
|
// We have no choice but to produce an overfull box.
|
2002-07-16 18:22:45 +00:00
|
|
|
row.dim = curr; // safe should be 0.
|
|
|
|
row.glue = 0; // does not matter
|
|
|
|
row.begin = begin;
|
|
|
|
row.end = i + 1;
|
|
|
|
begin = i + 1;
|
2002-07-09 08:24:33 +00:00
|
|
|
}
|
|
|
|
row.yo = yo;
|
2002-07-16 18:22:45 +00:00
|
|
|
yo += row.dim.height();
|
2002-07-09 08:24:33 +00:00
|
|
|
rows_.push_back(row);
|
2002-07-16 18:22:45 +00:00
|
|
|
// in any case, start the new row with empty boxes
|
|
|
|
curr.clear(mi.base.font);
|
|
|
|
safe.clear(mi.base.font);
|
2002-07-09 08:24:33 +00:00
|
|
|
}
|
2002-07-16 18:22:45 +00:00
|
|
|
// last row: put in everything else
|
2002-07-09 08:24:33 +00:00
|
|
|
MathXArray::Row row;
|
2002-07-16 18:22:45 +00:00
|
|
|
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;
|
2002-07-09 08:24:33 +00:00
|
|
|
rows_.push_back(row);
|
|
|
|
|
|
|
|
// what to report?
|
2002-07-16 18:22:45 +00:00
|
|
|
dim_.w = lyx_width_;
|
|
|
|
dim_.a = rows_.front().dim.a;
|
|
|
|
dim_.d = rows_.back().dim.d + yo;
|
2002-07-26 14:11:19 +00:00
|
|
|
metricsMarkers2();
|
2002-07-26 13:13:20 +00:00
|
|
|
xcell(0).setDim(dim_);
|
2002-07-09 08:24:33 +00:00
|
|
|
#endif
|
2002-07-08 11:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const
|
|
|
|
{
|
2002-07-09 08:24:33 +00:00
|
|
|
MathFontSetChanger dummy(pi.base, "textnormal");
|
2002-07-16 18:22:45 +00:00
|
|
|
#if 0
|
2002-07-08 11:29:51 +00:00
|
|
|
xcell(0).draw(pi, x + 1, y);
|
2002-07-09 08:24:33 +00:00
|
|
|
#else
|
|
|
|
xcell(0).drawExternal(pi, x + 1, y, rows_);
|
|
|
|
#endif
|
2002-07-26 14:11:19 +00:00
|
|
|
drawMarkers2(pi, x, y);
|
2002-07-08 11:29:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-26 17:23:44 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-08 11:29:51 +00:00
|
|
|
void MathParboxInset::write(WriteStream & os) const
|
|
|
|
{
|
|
|
|
os << "\\parbox";
|
|
|
|
if (position_ != 'c')
|
|
|
|
os << '[' << position_ << ']';
|
|
|
|
os << '{' << tex_width_ << "}{" << cell(0) << '}';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MathParboxInset::infoize(std::ostream & os) const
|
|
|
|
{
|
2002-07-10 07:15:36 +00:00
|
|
|
os << "Box: Parbox " << tex_width_;
|
2002-07-08 11:29:51 +00:00
|
|
|
}
|
|
|
|
|