X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathGrid.cpp;h=85511e6ddfad4af59d26c1dd50bd3af42506430e;hb=593bfe248a15be99bfce7e12cde6c59c92951f5f;hp=536f4bd163a671347d7a15150f7da6c407a1d4bb;hpb=764a2163bb6437fdd150a6a60db2573412f10d37;p=lyx.git diff --git a/src/mathed/InsetMathGrid.cpp b/src/mathed/InsetMathGrid.cpp index 536f4bd163..85511e6ddf 100644 --- a/src/mathed/InsetMathGrid.cpp +++ b/src/mathed/InsetMathGrid.cpp @@ -22,10 +22,13 @@ #include "Buffer.h" #include "BufferParams.h" #include "BufferView.h" -#include "CutAndPaste.h" -#include "FuncStatus.h" +#include "CoordCache.h" #include "Cursor.h" +#include "CutAndPaste.h" #include "FuncRequest.h" +#include "FuncStatus.h" +#include "LaTeXFeatures.h" +#include "TexRow.h" #include "frontends/Clipboard.h" #include "frontends/Painter.h" @@ -34,7 +37,6 @@ #include "support/docstream.h" #include "support/gettext.h" #include "support/lstrings.h" - #include "support/lassert.h" #include @@ -76,41 +78,15 @@ static void resetGrid(InsetMathGrid & grid) } - ////////////////////////////////////////////////////////////// -InsetMathGrid::CellInfo::CellInfo() - : multi_(CELL_NORMAL), glue_(0), begin_(0), end_(0) -{} - - - -////////////////////////////////////////////////////////////// - - -InsetMathGrid::RowInfo::RowInfo() - : descent_(0), ascent_(0), offset_(0), lines_(0), skip_(0), - allow_newpage_(true) -{} - - - int InsetMathGrid::RowInfo::skipPixels(MetricsInfo const & mi) const { - return crskip_.inPixels(mi.base); + return mi.base.inPixels(crskip); } - -////////////////////////////////////////////////////////////// - - -InsetMathGrid::ColInfo::ColInfo() - : align_('c'), width_(0), offset_(0), lines_(0), skip_(0) -{} - - ////////////////////////////////////////////////////////////// @@ -156,7 +132,7 @@ Inset * InsetMathGrid::clone() const } -InsetMath::idx_type InsetMathGrid::index(row_type row, col_type col) const +idx_type InsetMathGrid::index(row_type row, col_type col) const { return col + ncols() * row; } @@ -169,23 +145,23 @@ void InsetMathGrid::setDefaults() //if (nrows() <= 0) // lyxerr << "positive number of rows expected" << endl; for (col_type col = 0; col < ncols(); ++col) { - colinfo_[col].align_ = defaultColAlign(col); - colinfo_[col].skip_ = defaultColSpace(col); - colinfo_[col].special_.clear(); + colinfo_[col].align = defaultColAlign(col); + colinfo_[col].skip = defaultColSpace(col); + colinfo_[col].special.clear(); } for (idx_type idx = 0; idx < nargs(); ++idx) - cellinfo_[idx].multi_ = CELL_NORMAL; + cellinfo_[idx].multi = CELL_NORMAL; } bool InsetMathGrid::interpretString(Cursor & cur, docstring const & str) { if (str == "\\hline") { - FuncRequest fr = FuncRequest(LFUN_INSET_MODIFY, "tabular add-hline-above"); + FuncRequest fr = FuncRequest(LFUN_TABULAR_FEATURE, "add-hline-above"); FuncStatus status; if (getStatus(cur, fr, status)) { if (status.enabled()) { - rowinfo_[cur.row()].lines_++; + rowinfo_[cur.row()].lines++; return true; } } @@ -200,7 +176,7 @@ void InsetMathGrid::setHorizontalAlignments(docstring const & hh) for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it) { char_type c = *it; if (c == '|') { - colinfo_[col].lines_++; + colinfo_[col].lines++; } else if ((c == 'p' || c == 'm' || c == 'b'|| c == '!' || c == '@' || c == '>' || c == '<') && it + 1 != hh.end() && *(it + 1) == '{') { @@ -213,18 +189,18 @@ void InsetMathGrid::setHorizontalAlignments(docstring const & hh) // Only intercolumn stuff is allowed // in the last dummy column break; - colinfo_[col].align_ = 'l'; + colinfo_[col].align = 'l'; } else { // this is intercolumn stuff - if (colinfo_[col].special_.empty()) + if (colinfo_[col].special.empty()) // Overtake possible lines - colinfo_[col].special_ = docstring(colinfo_[col].lines_, '|'); + colinfo_[col].special = docstring(colinfo_[col].lines, '|'); } int brace_open = 0; int brace_close = 0; while (it != hh.end()) { c = *it; - colinfo_[col].special_ += c; + colinfo_[col].special += c; if (c == '{') ++brace_open; else if (c == '}') @@ -235,32 +211,32 @@ void InsetMathGrid::setHorizontalAlignments(docstring const & hh) } --it; if (newcolumn) { - colinfo_[col].lines_ = count( - colinfo_[col].special_.begin(), - colinfo_[col].special_.end(), '|'); + colinfo_[col].lines = count( + colinfo_[col].special.begin(), + colinfo_[col].special.end(), '|'); LYXERR(Debug::MATHED, "special column separator: `" - << to_utf8(colinfo_[col].special_) << '\''); + << to_utf8(colinfo_[col].special) << '\''); ++col; - colinfo_[col].lines_ = 0; - colinfo_[col].special_.clear(); + colinfo_[col].lines = 0; + colinfo_[col].special.clear(); } } else if (col >= ncols()) { // Only intercolumn stuff is allowed in the last // dummy column break; } else if (c == 'c' || c == 'l' || c == 'r') { - colinfo_[col].align_ = static_cast(c); - if (!colinfo_[col].special_.empty()) { - colinfo_[col].special_ += c; - colinfo_[col].lines_ = count( - colinfo_[col].special_.begin(), - colinfo_[col].special_.end(), '|'); + colinfo_[col].align = static_cast(c); + if (!colinfo_[col].special.empty()) { + colinfo_[col].special += c; + colinfo_[col].lines = count( + colinfo_[col].special.begin(), + colinfo_[col].special.end(), '|'); LYXERR(Debug::MATHED, "special column separator: `" - << to_utf8(colinfo_[col].special_) << '\''); + << to_utf8(colinfo_[col].special) << '\''); } ++col; - colinfo_[col].lines_ = 0; - colinfo_[col].special_.clear(); + colinfo_[col].lines = 0; + colinfo_[col].special.clear(); } else { lyxerr << "unknown column separator: '" << c << "'" << endl; } @@ -271,17 +247,17 @@ void InsetMathGrid::setHorizontalAlignments(docstring const & hh) if (n > ncols()) n = ncols(); for (col_type col = 0; col < n; ++col) - colinfo_[col].align_ = hh[col]; + colinfo_[col].align = hh[col]; */ } -InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) +col_type InsetMathGrid::guessColumns(docstring const & hh) { col_type col = 0; - for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it) - if (*it == 'c' || *it == 'l' || *it == 'r'|| - *it == 'p' || *it == 'm' || *it == 'b') + for (char_type const c : hh) + if (c == 'c' || c == 'l' || c == 'r'|| + c == 'p' || c == 'm' || c == 'b') ++col; // let's have at least one column, even if we did not recognize its // alignment @@ -293,9 +269,9 @@ InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) void InsetMathGrid::setHorizontalAlignment(char h, col_type col) { - colinfo_[col].align_ = h; - if (!colinfo_[col].special_.empty()) { - char_type & c = colinfo_[col].special_[colinfo_[col].special_.size() - 1]; + colinfo_[col].align = h; + if (!colinfo_[col].special.empty()) { + char_type & c = colinfo_[col].special[colinfo_[col].special.size() - 1]; if (c == 'l' || c == 'c' || c == 'r') c = h; } @@ -305,7 +281,7 @@ void InsetMathGrid::setHorizontalAlignment(char h, col_type col) char InsetMathGrid::horizontalAlignment(col_type col) const { - return colinfo_[col].align_; + return colinfo_[col].align; } @@ -313,15 +289,15 @@ docstring InsetMathGrid::horizontalAlignments() const { docstring res; for (col_type col = 0; col < ncols(); ++col) { - if (colinfo_[col].special_.empty()) { - res += docstring(colinfo_[col].lines_, '|'); - res += colinfo_[col].align_; + if (colinfo_[col].special.empty()) { + res += docstring(colinfo_[col].lines, '|'); + res += colinfo_[col].align; } else - res += colinfo_[col].special_; + res += colinfo_[col].special; } - if (colinfo_[ncols()].special_.empty()) - return res + docstring(colinfo_[ncols()].lines_, '|'); - return res + colinfo_[ncols()].special_; + if (colinfo_[ncols()].special.empty()) + return res + docstring(colinfo_[ncols()].lines, '|'); + return res + colinfo_[ncols()].special; } @@ -337,34 +313,34 @@ char InsetMathGrid::verticalAlignment() const } -InsetMathGrid::col_type InsetMathGrid::ncols() const +col_type InsetMathGrid::ncols() const { return colinfo_.size() - 1; } -InsetMathGrid::row_type InsetMathGrid::nrows() const +row_type InsetMathGrid::nrows() const { return rowinfo_.size() - 1; } -InsetMathGrid::col_type InsetMathGrid::col(idx_type idx) const +col_type InsetMathGrid::col(idx_type idx) const { return idx % ncols(); } -InsetMathGrid::row_type InsetMathGrid::row(idx_type idx) const +row_type InsetMathGrid::row(idx_type idx) const { return idx / ncols(); } -InsetMathGrid::col_type InsetMathGrid::ncellcols(idx_type idx) const +col_type InsetMathGrid::ncellcols(idx_type idx) const { col_type cols = 1; - if (cellinfo_[idx].multi_ == CELL_NORMAL) + if (cellinfo_[idx].multi == CELL_NORMAL) return cols; // If the cell at idx is already CELL_PART_OF_MULTICOLUMN we return // the number of remaining columns, not the ones of the complete @@ -372,7 +348,7 @@ InsetMathGrid::col_type InsetMathGrid::ncellcols(idx_type idx) const // cell with idx + ncellcols(idx) - 1. row_type const r = row(idx); while (idx+cols < nargs() && row(idx+cols) == r && - cellinfo_[idx+cols].multi_ == CELL_PART_OF_MULTICOLUMN) + cellinfo_[idx+cols].multi == CELL_PART_OF_MULTICOLUMN) cols++; return cols; } @@ -380,13 +356,13 @@ InsetMathGrid::col_type InsetMathGrid::ncellcols(idx_type idx) const void InsetMathGrid::vcrskip(Length const & crskip, row_type row) { - rowinfo_[row].crskip_ = crskip; + rowinfo_[row].crskip = crskip; } Length InsetMathGrid::vcrskip(row_type row) const { - return rowinfo_[row].crskip_; + return rowinfo_[row].crskip; } @@ -394,9 +370,10 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const { // let the cells adjust themselves for (idx_type i = 0; i < nargs(); ++i) { - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { Dimension dimc; - cell(i).metrics(mi, dimc); + // the 'false' is to make sure that the cell is tall enough + cell(i).metrics(mi, dimc, false); } } @@ -408,29 +385,28 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const int desc = 0; for (col_type col = 0; col < ncols(); ++col) { idx_type const i = index(row, col); - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { Dimension const & dimc = cell(i).dimension(bv); asc = max(asc, dimc.asc); desc = max(desc, dimc.des); } } - rowinfo_[row].ascent_ = asc; - rowinfo_[row].descent_ = desc; + rowinfo_[row].ascent = asc; + rowinfo_[row].descent = desc; } - rowinfo_[0].ascent_ += hlinesep() * rowinfo_[0].lines_; - rowinfo_[nrows()].ascent_ = 0; - rowinfo_[nrows()].descent_ = 0; + rowinfo_[nrows()].ascent = 0; + rowinfo_[nrows()].descent = 0; // compute vertical offsets - rowinfo_[0].offset_ = 0; + rowinfo_[0].offset[&bv] = 0; for (row_type row = 1; row <= nrows(); ++row) { - rowinfo_[row].offset_ = - rowinfo_[row - 1].offset_ + - rowinfo_[row - 1].descent_ + + rowinfo_[row].offset[&bv] = + rowinfo_[row - 1].offset[&bv] + + rowinfo_[row - 1].descent + rowinfo_[row - 1].skipPixels(mi) + rowsep() + - rowinfo_[row].lines_ * hlinesep() + - rowinfo_[row].ascent_; + rowinfo_[row].lines * hlinesep() + + rowinfo_[row].ascent; } // adjust vertical offset @@ -440,13 +416,13 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const h = 0; break; case 'b': - h = rowinfo_[nrows() - 1].offset_; + h = rowinfo_[nrows() - 1].offset[&bv]; break; default: - h = rowinfo_[nrows() - 1].offset_ / 2; + h = rowinfo_[nrows() - 1].offset[&bv] / 2; } for (row_type row = 0; row <= nrows(); ++row) - rowinfo_[row].offset_ -= h; + rowinfo_[row].offset[&bv] -= h; // multicolumn cell widths, as a map from first column to width in a @@ -460,7 +436,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const int wid = 0; for (row_type row = 0; row < nrows(); ++row) { idx_type const i = index(row, col); - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { int const w = cell(i).dimension(bv).wid; col_type const cols = ncellcols(i); if (cols > 1 && nrows() > 1) { @@ -476,19 +452,19 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const wid = max(wid, w); } } - colinfo_[col].width_ = wid; + colinfo_[col].width = wid; } - colinfo_[ncols()].width_ = 0; + colinfo_[ncols()].width = 0; // compute horizontal offsets - colinfo_[0].offset_ = border(); + colinfo_[0].offset = border() + colinfo_[0].lines * vlinesep(); for (col_type col = 1; col <= ncols(); ++col) { - colinfo_[col].offset_ = - colinfo_[col - 1].offset_ + - colinfo_[col - 1].width_ + - colinfo_[col - 1].skip_ + + colinfo_[col].offset = + colinfo_[col - 1].offset + + colinfo_[col - 1].width + + displayColSpace(col - 1) + colsep() + - colinfo_[col].lines_ * vlinesep(); + colinfo_[col].lines * vlinesep(); } // increase column widths for multicolumn cells if needed @@ -506,44 +482,44 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const int const wid = it->second; col_type const first = it->first; int const nextoffset = - colinfo_[first].offset_ + + colinfo_[first].offset + wid + - colinfo_[last].skip_ + + displayColSpace(last) + colsep() + - colinfo_[last+1].lines_ * vlinesep(); - int const dx = nextoffset - colinfo_[last+1].offset_; + colinfo_[last+1].lines * vlinesep(); + int const dx = nextoffset - colinfo_[last+1].offset; if (dx > 0) { - colinfo_[last].width_ += dx; + colinfo_[last].width += dx; for (col_type col = last + 1; col <= ncols(); ++col) - colinfo_[col].offset_ += dx; + colinfo_[col].offset += dx; } } } - dim.wid = colinfo_[ncols() - 1].offset_ - + colinfo_[ncols() - 1].width_ - + vlinesep() * colinfo_[ncols()].lines_ + dim.wid = colinfo_[ncols() - 1].offset + + colinfo_[ncols() - 1].width + + vlinesep() * colinfo_[ncols()].lines + border(); - dim.asc = - rowinfo_[0].offset_ - + rowinfo_[0].ascent_ - + hlinesep() * rowinfo_[0].lines_ + dim.asc = - rowinfo_[0].offset[&bv] + + rowinfo_[0].ascent + + hlinesep() * rowinfo_[0].lines + border(); - dim.des = rowinfo_[nrows() - 1].offset_ - + rowinfo_[nrows() - 1].descent_ - + hlinesep() * rowinfo_[nrows()].lines_ - + border(); + dim.des = rowinfo_[nrows() - 1].offset[&bv] + + rowinfo_[nrows() - 1].descent + + hlinesep() * rowinfo_[nrows()].lines + + border() + 1; /* // Increase ws_[i] for 'R' columns (except the first one) for (int i = 1; i < nc_; ++i) - if (align_[i] == 'R') + if (align[i] == 'R') ws_[i] += 10 * df_width; // Increase ws_[i] for 'C' column - if (align_[0] == 'C') + if (align[0] == 'C') if (ws_[0] < 7 * workwidth / 8) ws_[0] = 7 * workwidth / 8; @@ -558,7 +534,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const cxrow->setTab(i, df_width); isvoid = true; } - switch (align_[i]) { + switch (align[i]) { case 'l': lf = 0; break; @@ -587,90 +563,83 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const cxrow->setBaseline(cxrow->getBaseline() - ascent); } */ - metricsMarkers2(dim); - // Cache the inset dimension. - setDimCache(mi, dim); + dim.wid += leftMargin() + rightMargin(); } -void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const +int InsetMathGrid::vLineHOffset(col_type col, unsigned int line) const { - drawWithMargin(pi, x, y, 1, 1); + if (col < ncols()) + return leftMargin() + colinfo_[col].offset + - (colinfo_[col].lines - line - 1) * vlinesep() + - vlinesep()/2 - colsep()/2; + else { + LASSERT(col == ncols(), return 0); + return leftMargin() + colinfo_[col-1].offset + colinfo_[col-1].width + + line * vlinesep() + + vlinesep()/2 + colsep()/2; + } } -void InsetMathGrid::drawWithMargin(PainterInfo & pi, int x, int y, - int lmargin, int rmargin) const +int InsetMathGrid::hLineVOffset(BufferView const & bv, row_type row, + unsigned int line) const +{ + return rowinfo_[row].offset[&bv] + - rowinfo_[row].ascent + - line * hlinesep() + - hlinesep()/2 - rowsep()/2; +} + + +void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const { - Dimension const dim = dimension(*pi.base.bv); BufferView const & bv = *pi.base.bv; for (idx_type idx = 0; idx < nargs(); ++idx) { - if (cellinfo_[idx].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[idx].multi != CELL_PART_OF_MULTICOLUMN) { cell(idx).draw(pi, - x + lmargin + cellXOffset(bv, idx), - y + cellYOffset(idx)); - - // draw inner lines cell by cell because of possible multicolumns - // FIXME: multicolumn lines are not yet considered - row_type const r = row(idx); - col_type const c = col(idx); - if (r > 0 && r < nrows()) { - for (unsigned int i = 0; i < rowinfo_[r].lines_; ++i) { - int yy = y + rowinfo_[r].offset_ - - rowinfo_[r].ascent_ - - i * hlinesep() - - hlinesep()/2 - rowsep()/2; - pi.pain.line( - x + lmargin + colinfo_[c].offset_, - yy, - x + lmargin + colinfo_[c+1].offset_, - yy, Color_foreground); + x + leftMargin() + cellXOffset(bv, idx), + y + cellYOffset(bv, idx)); + + row_type r = row(idx); + int const yy1 = y + hLineVOffset(bv, r, 0); + int const yy2 = y + hLineVOffset(bv, r + 1, rowinfo_[r + 1].lines - 1); + auto draw_left_borders = [&](col_type c) { + for (unsigned int i = 0; i < colinfo_[c].lines; ++i) { + int const xx = x + vLineHOffset(c, i); + pi.pain.line(xx, yy1, xx, yy2, Color_foreground); } - } - if (c > 0 && c < ncols()) { - for (unsigned int i = 0; i < colinfo_[c].lines_; ++i) { - int xx = x + lmargin - + colinfo_[c].offset_ - - i * vlinesep() - - vlinesep()/2 - colsep()/2; - pi.pain.line(xx, - rowinfo_[r].offset_ - rowinfo_[r].ascent_, - xx, - rowinfo_[r].offset_ + rowinfo_[r].descent_, - Color_foreground); - } - } + }; + col_type c = col(idx); + // Draw inner left borders cell-by-cell because of multicolumns + draw_left_borders(c); + // Draw the right border (only once) + if (c == 0) + draw_left_borders(ncols()); } } - // draw outer lines in one go - for (row_type row = 0; row <= nrows(); row += nrows()) - for (unsigned int i = 0; i < rowinfo_[row].lines_; ++i) { - int yy = y + rowinfo_[row].offset_ - rowinfo_[row].ascent_ - - i * hlinesep() - hlinesep()/2 - rowsep()/2; - pi.pain.line(x + lmargin + 1, yy, - x + dim.width() - rmargin - 1, yy, - Color_foreground); - } - - for (col_type col = 0; col <= ncols(); col += ncols()) - for (unsigned int i = 0; i < colinfo_[col].lines_; ++i) { - int xx = x + lmargin + colinfo_[col].offset_ - - i * vlinesep() - vlinesep()/2 - colsep()/2; - pi.pain.line(xx, y - dim.ascent() + 1, - xx, y + dim.descent() - 1, - Color_foreground); + // Draw horizontal borders + for (row_type r = 0; r <= nrows(); ++r) { + int const xx1 = x + vLineHOffset(0, 0); + int const xx2 = x + vLineHOffset(ncols(), colinfo_[ncols()].lines - 1); + for (unsigned int i = 0; i < rowinfo_[r].lines; ++i) { + int const yy = y + hLineVOffset(bv, r, i); + pi.pain.line(xx1, yy, xx2, yy, Color_foreground); } - drawMarkers2(pi, x, y); + } } -void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const +void InsetMathGrid::metricsT(TextMetricsInfo const & /*mi*/, Dimension & /*dim*/) const { +// FIXME: this does not compile anymore with offset being a map +// It is not worth fixing it at this point since the code is basically dead. +#if 0 // let the cells adjust themselves for (idx_type i = 0; i < nargs(); ++i) - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) cell(i).metricsT(mi, dim); // compute absolute sizes of vertical structure @@ -679,7 +648,7 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const int desc = 0; for (col_type col = 0; col < ncols(); ++col) { idx_type const i = index(row, col); - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { //MathData const & c = cell(i); // FIXME: BROKEN! Dimension dimc; @@ -687,23 +656,22 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const desc = max(desc, dimc.descent()); } } - rowinfo_[row].ascent_ = asc; - rowinfo_[row].descent_ = desc; + rowinfo_[row].ascent = asc; + rowinfo_[row].descent = desc; } - //rowinfo_[0].ascent_ += hlinesep() * rowinfo_[0].lines_; - rowinfo_[nrows()].ascent_ = 0; - rowinfo_[nrows()].descent_ = 0; + rowinfo_[nrows()].ascent = 0; + rowinfo_[nrows()].descent = 0; // compute vertical offsets - rowinfo_[0].offset_ = 0; + rowinfo_[0].offset[&bv] = 0; for (row_type row = 1; row <= nrows(); ++row) { - rowinfo_[row].offset_ = - rowinfo_[row - 1].offset_ + - rowinfo_[row - 1].descent_ + + rowinfo_[row].offset[&bv] = + rowinfo_[row - 1].offset + + rowinfo_[row - 1].descent + //rowinfo_[row - 1].skipPixels(mi) + 1 + //rowsep() + - //rowinfo_[row].lines_ * hlinesep() + - rowinfo_[row].ascent_; + //rowinfo_[row].lines * hlinesep() + + rowinfo_[row].ascent; } // adjust vertical offset @@ -713,13 +681,13 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const h = 0; break; case 'b': - h = rowinfo_[nrows() - 1].offset_; + h = rowinfo_[nrows() - 1].offset; break; default: - h = rowinfo_[nrows() - 1].offset_ / 2; + h = rowinfo_[nrows() - 1].offset / 2; } for (row_type row = 0; row <= nrows(); ++row) - rowinfo_[row].offset_ -= h; + rowinfo_[row].offset -= h; // compute absolute sizes of horizontal structure @@ -728,67 +696,68 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const for (row_type row = 0; row < nrows(); ++row) { // FIXME: BROKEN! //idx_type const i = index(row, col); - //if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) + //if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) // wid = max(wid, cell(i).width()); } - colinfo_[col].width_ = wid; + colinfo_[col].width = wid; } - colinfo_[ncols()].width_ = 0; + colinfo_[ncols()].width = 0; // compute horizontal offsets - colinfo_[0].offset_ = border(); + colinfo_[0].offset = border(); for (col_type col = 1; col <= ncols(); ++col) { - colinfo_[col].offset_ = - colinfo_[col - 1].offset_ + - colinfo_[col - 1].width_ + - colinfo_[col - 1].skip_ + + colinfo_[col].offset = + colinfo_[col - 1].offset + + colinfo_[col - 1].width + + displayColSpace(col - 1) + 1 ; //colsep() + - //colinfo_[col].lines_ * vlinesep(); + //colinfo_[col].lines * vlinesep(); } - dim.wid = colinfo_[ncols() - 1].offset_ - + colinfo_[ncols() - 1].width_ - //+ vlinesep() * colinfo_[ncols()].lines_ + dim.wid = colinfo_[ncols() - 1].offset + + colinfo_[ncols() - 1].width + //+ vlinesep() * colinfo_[ncols()].lines + 2; - dim.asc = -rowinfo_[0].offset_ - + rowinfo_[0].ascent_ - //+ hlinesep() * rowinfo_[0].lines_ + dim.asc = -rowinfo_[0].offset + + rowinfo_[0].ascent + //+ hlinesep() * rowinfo_[0].lines + 1; - dim.des = rowinfo_[nrows() - 1].offset_ - + rowinfo_[nrows() - 1].descent_ - //+ hlinesep() * rowinfo_[nrows()].lines_ + dim.des = rowinfo_[nrows() - 1].offset + + rowinfo_[nrows() - 1].descent + //+ hlinesep() * rowinfo_[nrows()].lines + 1; +#endif } void InsetMathGrid::drawT(TextPainter & /*pain*/, int /*x*/, int /*y*/) const { // for (idx_type idx = 0; idx < nargs(); ++idx) -// if (cellinfo_[idx].multi_ != CELL_PART_OF_MULTICOLUMN) +// if (cellinfo_[idx].multi != CELL_PART_OF_MULTICOLUMN) // cell(idx).drawT(pain, x + cellXOffset(idx), y + cellYOffset(idx)); } -void InsetMathGrid::updateBuffer(ParIterator const & it, UpdateType utype) +void InsetMathGrid::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted) { // pass down for (idx_type idx = 0; idx < nargs(); ++idx) - if (cellinfo_[idx].multi_ != CELL_PART_OF_MULTICOLUMN) - cell(idx).updateBuffer(it, utype); + if (cellinfo_[idx].multi != CELL_PART_OF_MULTICOLUMN) + cell(idx).updateBuffer(it, utype, deleted); } -docstring InsetMathGrid::eolString(row_type row, bool fragile, +void InsetMathGrid::eol(TeXMathStream & os, row_type row, bool fragile, bool /*latex*/, bool last_eoln) const { docstring eol; - if (!rowinfo_[row].crskip_.zero()) - eol += '[' + from_utf8(rowinfo_[row].crskip_.asLatexString()) + ']'; - else if(!rowinfo_[row].allow_newpage_) + if (!rowinfo_[row].crskip.zero()) + eol += '[' + from_utf8(rowinfo_[row].crskip.asLatexString()) + ']'; + else if(!rowinfo_[row].allow_newpage) eol += '*'; // make sure an upcoming '[' does not break anything @@ -801,9 +770,9 @@ docstring InsetMathGrid::eolString(row_type row, bool fragile, // only add \\ if necessary if (eol.empty() && row + 1 == nrows() && (nrows() == 1 || !last_eoln)) - return docstring(); + return; - return (fragile ? "\\protect\\\\" : "\\\\") + eol; + os << (fragile ? "\\protect\\\\" : "\\\\") << eol; } @@ -819,7 +788,7 @@ void InsetMathGrid::addRow(row_type row) { rowinfo_.insert(rowinfo_.begin() + row + 1, RowInfo()); cells_.insert - (cells_.begin() + (row + 1) * ncols(), ncols(), MathData()); + (cells_.begin() + (row + 1) * ncols(), ncols(), MathData(buffer_)); cellinfo_.insert (cellinfo_.begin() + (row + 1) * ncols(), ncols(), CellInfo()); } @@ -843,8 +812,11 @@ void InsetMathGrid::delRow(row_type row) void InsetMathGrid::copyRow(row_type row) { addRow(row); - for (col_type col = 0; col < ncols(); ++col) + for (col_type col = 0; col < ncols(); ++col) { cells_[(row + 1) * ncols() + col] = cells_[row * ncols() + col]; + // copying the cell does not set the buffer + cells_[(row + 1) * ncols() + col].setBuffer(*buffer_); + } } @@ -874,11 +846,13 @@ void InsetMathGrid::addCol(col_type newcol) = cellinfo_[row * nc + col]; } swap(cells_, new_cells); + // copying cells loses the buffer reference + setBuffer(*buffer_); swap(cellinfo_, new_cellinfo); ColInfo inf; - inf.skip_ = defaultColSpace(newcol); - inf.align_ = defaultColAlign(newcol); + inf.skip = defaultColSpace(newcol); + inf.align = defaultColAlign(newcol); colinfo_.insert(colinfo_.begin() + newcol, inf); } @@ -896,6 +870,8 @@ void InsetMathGrid::delCol(col_type col) tmpcellinfo.push_back(cellinfo_[i]); } swap(cells_, tmpcells); + // copying cells loses the buffer reference + setBuffer(*buffer_); swap(cellinfo_, tmpcellinfo); colinfo_.erase(colinfo_.begin() + col); @@ -905,8 +881,11 @@ void InsetMathGrid::delCol(col_type col) void InsetMathGrid::copyCol(col_type col) { addCol(col+1); - for (row_type row = 0; row < nrows(); ++row) + for (row_type row = 0; row < nrows(); ++row) { cells_[row * ncols() + col + 1] = cells_[row * ncols() + col]; + // copying the cell does not set the buffer + cells_[row * ncols() + col + 1].setBuffer(*buffer_); + } } @@ -923,10 +902,10 @@ void InsetMathGrid::swapCol(col_type col) int InsetMathGrid::cellXOffset(BufferView const & bv, idx_type idx) const { - if (cellinfo_[idx].multi_ == CELL_PART_OF_MULTICOLUMN) + if (cellinfo_[idx].multi == CELL_PART_OF_MULTICOLUMN) return 0; col_type c = col(idx); - int x = colinfo_[c].offset_; + int x = colinfo_[c].offset; char align = displayColAlign(idx); Dimension const & celldim = cell(idx).dimension(bv); if (align == 'r' || align == 'R') @@ -937,25 +916,25 @@ int InsetMathGrid::cellXOffset(BufferView const & bv, idx_type idx) const } -int InsetMathGrid::cellYOffset(idx_type idx) const +int InsetMathGrid::cellYOffset(BufferView const & bv, idx_type idx) const { - return rowinfo_[row(idx)].offset_; + return rowinfo_[row(idx)].offset[&bv]; } int InsetMathGrid::cellWidth(idx_type idx) const { - switch (cellinfo_[idx].multi_) { + switch (cellinfo_[idx].multi) { case CELL_NORMAL: - return colinfo_[col(idx)].width_; + return colinfo_[col(idx)].width; case CELL_BEGIN_OF_MULTICOLUMN: { col_type c1 = col(idx); col_type c2 = c1 + ncellcols(idx); - return colinfo_[c2].offset_ - - colinfo_[c1].offset_ - - colinfo_[c2].skip_ + return colinfo_[c2].offset + - colinfo_[c1].offset + - displayColSpace(c2) - colsep() - - colinfo_[c2].lines_ * vlinesep(); + - colinfo_[c2].lines * vlinesep(); } case CELL_PART_OF_MULTICOLUMN: return 0; @@ -976,11 +955,18 @@ bool InsetMathGrid::idxUpDown(Cursor & cur, bool up) const cur.idx() += ncols(); } // If we are in a multicolumn cell, move to the "real" cell - while (cellinfo_[cur.idx()].multi_ == CELL_PART_OF_MULTICOLUMN) { + while (cellinfo_[cur.idx()].multi == CELL_PART_OF_MULTICOLUMN) { LASSERT(cur.idx() > 0, return false); --cur.idx(); } - cur.pos() = cur.cell().x2pos(&cur.bv(), cur.x_target() - cur.cell().xo(cur.bv())); + // FIXME: this is only a workaround to avoid a crash if the inset + // in not in coord cache. The best would be to force a FitCursor + // operation. + CoordCache::Arrays const & arraysCache = cur.bv().coordCache().arrays(); + if (arraysCache.has(&cur.cell())) + cur.pos() = cur.cell().x2pos(&cur.bv(), cur.x_target() - cur.cell().xo(cur.bv())); + else + cur.pos() = 0; return true; } @@ -992,7 +978,7 @@ bool InsetMathGrid::idxBackward(Cursor & cur) const return false; --cur.idx(); // If we are in a multicolumn cell, move to the "real" cell - while (cellinfo_[cur.idx()].multi_ == CELL_PART_OF_MULTICOLUMN) { + while (cellinfo_[cur.idx()].multi == CELL_PART_OF_MULTICOLUMN) { LASSERT(cur.idx() > 0, return false); --cur.idx(); } @@ -1008,7 +994,7 @@ bool InsetMathGrid::idxForward(Cursor & cur) const return false; ++cur.idx(); // If we are in a multicolumn cell, move to the next cell - while (cellinfo_[cur.idx()].multi_ == CELL_PART_OF_MULTICOLUMN) { + while (cellinfo_[cur.idx()].multi == CELL_PART_OF_MULTICOLUMN) { // leave matrix if at the back edge if (cur.col() + 1 == ncols()) return false; @@ -1019,47 +1005,47 @@ bool InsetMathGrid::idxForward(Cursor & cur) const } -bool InsetMathGrid::idxFirst(Cursor & cur) const +idx_type InsetMathGrid::firstIdx() const { + size_type idx = 0; switch (v_align_) { case 't': - cur.idx() = 0; + //idx = 0; break; case 'b': - cur.idx() = (nrows() - 1) * ncols(); + idx = (nrows() - 1) * ncols(); break; default: - cur.idx() = ((nrows() - 1) / 2) * ncols(); + idx = ((nrows() - 1) / 2) * ncols(); } // If we are in a multicolumn cell, move to the "real" cell - while (cellinfo_[cur.idx()].multi_ == CELL_PART_OF_MULTICOLUMN) { - LASSERT(cur.idx() > 0, return false); - --cur.idx(); + while (cellinfo_[idx].multi == CELL_PART_OF_MULTICOLUMN) { + LASSERT(idx > 0, return 0); + --idx; } - cur.pos() = 0; - return true; + return idx; } -bool InsetMathGrid::idxLast(Cursor & cur) const +idx_type InsetMathGrid::lastIdx() const { + size_type idx = 0; switch (v_align_) { case 't': - cur.idx() = ncols() - 1; + idx = ncols() - 1; break; case 'b': - cur.idx() = nargs() - 1; + idx = nargs() - 1; break; default: - cur.idx() = ((nrows() - 1) / 2 + 1) * ncols() - 1; + idx = ((nrows() - 1) / 2 + 1) * ncols() - 1; } // If we are in a multicolumn cell, move to the "real" cell - while (cellinfo_[cur.idx()].multi_ == CELL_PART_OF_MULTICOLUMN) { - LASSERT(cur.idx() > 0, return false); - --cur.idx(); + while (cellinfo_[idx].multi == CELL_PART_OF_MULTICOLUMN) { + LASSERT(idx > 0, return false); + --idx; } - cur.pos() = cur.lastpos(); - return true; + return idx; } @@ -1110,7 +1096,7 @@ void InsetMathGrid::idxGlue(idx_type idx) } else { idx_type idx_next = idx + 1; while (idx_next < nargs() && - cellinfo_[idx_next].multi_ == CELL_PART_OF_MULTICOLUMN) + cellinfo_[idx_next].multi == CELL_PART_OF_MULTICOLUMN) ++idx_next; if (idx_next < nargs()) cell(idx).append(cell(idx_next)); @@ -1153,7 +1139,7 @@ void InsetMathGrid::normalize(NormalStream & os) const os << "[row "; for (col_type col = 0; col < ncols(); ++col) { idx_type const i = index(row, col); - switch (cellinfo_[i].multi_) { + switch (cellinfo_[i].multi) { case CELL_NORMAL: os << "[cell " << cell(i) << ']'; break; @@ -1172,38 +1158,38 @@ void InsetMathGrid::normalize(NormalStream & os) const } -void InsetMathGrid::mathmlize(MathStream & os) const +void InsetMathGrid::mathmlize(MathMLStream & ms) const { bool const havetable = nrows() > 1 || ncols() > 1; if (havetable) - os << MTag("mtable"); + ms << MTag("mtable"); char const * const celltag = havetable ? "mtd" : "mrow"; for (row_type row = 0; row < nrows(); ++row) { if (havetable) - os << MTag("mtr"); + ms << MTag("mtr"); for (col_type col = 0; col < ncols(); ++col) { idx_type const i = index(row, col); - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { col_type const cellcols = ncellcols(i); ostringstream attr; if (havetable && cellcols > 1) attr << "colspan='" << cellcols << '\''; - os << MTag(celltag, attr.str()); - os << cell(index(row, col)); - os << ETag(celltag); + ms << MTag(celltag, attr.str()); + ms << cell(index(row, col)); + ms << ETag(celltag); } } if (havetable) - os << ETag("mtr"); + ms << ETag("mtr"); } if (havetable) - os << ETag("mtable"); + ms << ETag("mtable"); } // FIXME XHTML // We need to do something about alignment here. -void InsetMathGrid::htmlize(HtmlStream & os, string attrib) const +void InsetMathGrid::htmlize(HtmlStream & os, string const & attrib) const { bool const havetable = nrows() > 1 || ncols() > 1; if (!havetable) { @@ -1215,7 +1201,7 @@ void InsetMathGrid::htmlize(HtmlStream & os, string attrib) const os << MTag("tr"); for (col_type col = 0; col < ncols(); ++col) { idx_type const i = index(row, col); - if (cellinfo_[i].multi_ != CELL_PART_OF_MULTICOLUMN) { + if (cellinfo_[i].multi != CELL_PART_OF_MULTICOLUMN) { col_type const cellcols = ncellcols(i); ostringstream attr; if (cellcols > 1) @@ -1237,19 +1223,38 @@ void InsetMathGrid::htmlize(HtmlStream & os) const } -void InsetMathGrid::write(WriteStream & os) const +void InsetMathGrid::validate(LaTeXFeatures & features) const +{ + if (features.runparams().math_flavor == OutputParams::MathAsHTML + && (nrows() > 1 || ncols() > 1)) { + // CSS taken from InsetMathCases + features.addCSSSnippet( + "table.mathtable{display: inline-block; text-align: center; border: none;" + "border-left: thin solid black; vertical-align: middle; padding-left: 0.5ex;}\n" + "table.mathtable td {text-align: left; border: none;}"); + } + InsetMathNest::validate(features); +} + + +void InsetMathGrid::write(TeXMathStream & os) const { write(os, 0, 0, nrows(), ncols()); } -void InsetMathGrid::write(WriteStream & os, - row_type beg_row, col_type beg_col, - row_type end_row, col_type end_col) const +void InsetMathGrid::write(TeXMathStream & os, + row_type beg_row, col_type beg_col, + row_type end_row, col_type end_col) const { MathEnsurer ensurer(os, false); - docstring eol; + docstring eolstr; + // As of 2018 (with amendment in LaTeX 2021/06), + // \\ is a robust command and its protection + // is no longer necessary + bool const fragile = os.fragile() + && !LaTeXFeatures::isAvailable("LaTeX-2021/06/01"); for (row_type row = beg_row; row < end_row; ++row) { - os << verboseHLine(rowinfo_[row].lines_); + os << verboseHLine(rowinfo_[row].lines); // don't write & and empty cells at end of line, // unless there are vertical lines col_type lastcol = 0; @@ -1258,10 +1263,10 @@ void InsetMathGrid::write(WriteStream & os, for (col_type col = beg_col; col < end_col; ++col) { idx_type const idx = index(row, col); bool const empty_cell = cell(idx).empty(); - if (!empty_cell || cellinfo_[idx].multi_ != CELL_NORMAL) + if (last_eoln && (!empty_cell || cellinfo_[idx].multi != CELL_NORMAL)) last_eoln = false; - if (!empty_cell || cellinfo_[idx].multi_ != CELL_NORMAL || - colinfo_[col + 1].lines_) { + if (!empty_cell || cellinfo_[idx].multi != CELL_NORMAL || + colinfo_[col + 1].lines) { lastcol = col + 1; emptyline = false; } @@ -1269,45 +1274,43 @@ void InsetMathGrid::write(WriteStream & os, for (col_type col = beg_col; col < end_col;) { int nccols = 1; idx_type const idx = index(row, col); - TexRow::RowEntry entry = os.texrow().mathEntry(id(),idx); - os.texrow().startMath(id(),idx); + TexRow::RowEntry const entry = TexRow::mathEntry(id(),idx); + os.texrow().start(entry); if (col >= lastcol) { ++col; continue; } - os.pushRowEntry(entry); - if (cellinfo_[idx].multi_ == CELL_BEGIN_OF_MULTICOLUMN) { + Changer dummy = os.changeRowEntry(entry); + if (cellinfo_[idx].multi == CELL_BEGIN_OF_MULTICOLUMN) { size_t s = col + 1; while (s < ncols() && - cellinfo_[index(row, s)].multi_ == CELL_PART_OF_MULTICOLUMN) + cellinfo_[index(row, s)].multi == CELL_PART_OF_MULTICOLUMN) s++; nccols = s - col; os << "\\multicolumn{" << nccols - << "}{" << cellinfo_[idx].align_ + << "}{" << cellinfo_[idx].align << "}{"; } os << cell(idx); if (os.pendingBrace()) ModeSpecifier specifier(os, TEXT_MODE); - if (cellinfo_[idx].multi_ == CELL_BEGIN_OF_MULTICOLUMN) + if (cellinfo_[idx].multi == CELL_BEGIN_OF_MULTICOLUMN) os << '}'; os << eocString(col + nccols - 1, lastcol); col += nccols; - os.popRowEntry(); } - eol = eolString(row, os.fragile(), os.latex(), last_eoln); - os << eol; + eol(os, row, fragile, os.latex(), last_eoln); // append newline only if line wasn't completely empty // and the formula is not written on a single line - bool const empty = emptyline && eol.empty(); + bool const empty = emptyline && eolstr.empty(); if (!empty && nrows() > 1) os << "\n"; } // @TODO use end_row instead of nrows() ? - docstring const s = verboseHLine(rowinfo_[nrows()].lines_); + docstring const s = verboseHLine(rowinfo_[nrows()].lines); if (!s.empty()) { - if (eol.empty()) { - if (os.fragile()) + if (eolstr.empty()) { + if (fragile) os << "\\protect"; os << "\\\\"; } @@ -1355,7 +1358,7 @@ void InsetMathGrid::splitCell(Cursor & cur) cur.cell().erase(cur.pos(), cur.lastpos()); ++cur.idx(); while (cur.idx() << nargs() && - cellinfo_[cur.idx()].multi_ == CELL_BEGIN_OF_MULTICOLUMN) + cellinfo_[cur.idx()].multi == CELL_BEGIN_OF_MULTICOLUMN) ++cur.idx(); cur.pos() = 0; cur.cell().insert(0, ar); @@ -1364,20 +1367,25 @@ void InsetMathGrid::splitCell(Cursor & cur) char InsetMathGrid::displayColAlign(idx_type idx) const { - if (cellinfo_[idx].multi_ == CELL_BEGIN_OF_MULTICOLUMN) { - // align_ may also contain lines like "||r|", so this is + if (cellinfo_[idx].multi == CELL_BEGIN_OF_MULTICOLUMN) { + // align may also contain lines like "||r|", so this is // not complete, but we catch at least the simple cases. - if (cellinfo_[idx].align_ == "c") + if (cellinfo_[idx].align == "c") return 'c'; - if (cellinfo_[idx].align_ == "l") + if (cellinfo_[idx].align == "l") return 'l'; - if (cellinfo_[idx].align_ == "r") + if (cellinfo_[idx].align == "r") return 'r'; } - return colinfo_[col(idx)].align_; + return colinfo_[col(idx)].align; } +int InsetMathGrid::displayColSpace(col_type col) const +{ + return colinfo_[col].skip; +} + void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) { //lyxerr << "*** InsetMathGrid: request: " << cmd << endl; @@ -1409,25 +1417,6 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) splitCell(cur); break; - case LFUN_CELL_BACKWARD: - // See below. - cur.setSelection(false); - if (!idxPrev(cur)) { - cmd = FuncRequest(LFUN_FINISHED_BACKWARD); - cur.undispatched(); - } - break; - - case LFUN_CELL_FORWARD: - // Can't handle selection by additional 'shift' as this is - // hard bound to LFUN_CELL_BACKWARD - cur.setSelection(false); - if (!idxNext(cur)) { - cmd = FuncRequest(LFUN_FINISHED_FORWARD); - cur.undispatched(); - } - break; - case LFUN_NEWLINE_INSERT: { cur.recordUndoInset(); row_type const r = cur.row(); @@ -1450,17 +1439,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_INSET_MODIFY: { + case LFUN_TABULAR_FEATURE: { cur.recordUndoInset(); //lyxerr << "handling tabular-feature " << to_utf8(cmd.argument()) << endl; istringstream is(to_utf8(cmd.argument())); string s; is >> s; - if (s != "tabular") { - InsetMathNest::doDispatch(cur, cmd); - return; - } - is >> s; if (s == "valign-top") setVerticalAlignment('t'); else if (s == "valign-middle") @@ -1501,13 +1485,13 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pos() = 0; } else if (s == "add-hline-above") - rowinfo_[cur.row()].lines_++; + rowinfo_[cur.row()].lines++; else if (s == "add-hline-below") - rowinfo_[cur.row()+1].lines_++; + rowinfo_[cur.row()+1].lines++; else if (s == "delete-hline-above") - rowinfo_[cur.row()].lines_--; + rowinfo_[cur.row()].lines--; else if (s == "delete-hline-below") - rowinfo_[cur.row()+1].lines_--; + rowinfo_[cur.row()+1].lines--; else if (s == "append-column") { row_type const r = cur.row(); col_type const c = cur.col(); @@ -1535,18 +1519,18 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) cur.pos() = 0; // trick, see above } else if (s == "add-vline-left") { - colinfo_[cur.col()].lines_++; - if (!colinfo_[cur.col()].special_.empty()) - colinfo_[cur.col()].special_ += '|'; + colinfo_[cur.col()].lines++; + if (!colinfo_[cur.col()].special.empty()) + colinfo_[cur.col()].special += '|'; } else if (s == "add-vline-right") { - colinfo_[cur.col()+1].lines_++; - if (!colinfo_[cur.col()+1].special_.empty()) - colinfo_[cur.col()+1].special_.insert(0, 1, '|'); + colinfo_[cur.col()+1].lines++; + if (!colinfo_[cur.col()+1].special.empty()) + colinfo_[cur.col()+1].special.insert(0, 1, '|'); } else if (s == "delete-vline-left") { - colinfo_[cur.col()].lines_--; - docstring & special = colinfo_[cur.col()].special_; + colinfo_[cur.col()].lines--; + docstring & special = colinfo_[cur.col()].special; if (!special.empty()) { docstring::size_type i = special.rfind('|'); LASSERT(i != docstring::npos, break); @@ -1554,8 +1538,8 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } } else if (s == "delete-vline-right") { - colinfo_[cur.col()+1].lines_--; - docstring & special = colinfo_[cur.col()+1].special_; + colinfo_[cur.col()+1].lines--; + docstring & special = colinfo_[cur.col()+1].special; if (!special.empty()) { docstring::size_type i = special.find('|'); LASSERT(i != docstring::npos, break); @@ -1575,18 +1559,19 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) parseflg |= Parse::VERBATIM; // fall through case LFUN_PASTE: { - if (cur.currentMode() <= TEXT_MODE) + if (cur.currentMode() != MATH_MODE) parseflg |= Parse::TEXTMODE; cur.message(_("Paste")); cap::replaceSelection(cur); docstring topaste; if (cmd.argument().empty() && !theClipboard().isInternal()) - topaste = theClipboard().getAsText(Clipboard::PlainTextType); + topaste = theClipboard().getAsText(frontend::Clipboard::PlainTextType); else { idocstringstream is(cmd.argument()); int n = 0; is >> n; - topaste = cap::selection(n, buffer().params().documentClassPtr()); + topaste = cap::selection(n, make_pair(buffer().params().documentClassPtr(), + buffer().params().authors()), true); } InsetMathGrid grid(buffer_, 1, 1); if (!topaste.empty()) @@ -1597,7 +1582,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } bool hline_enabled = false; - FuncRequest fr = FuncRequest(LFUN_INSET_MODIFY, "tabular add-hline-above"); + FuncRequest fr = FuncRequest(LFUN_TABULAR_FEATURE, "add-hline-above"); FuncStatus status; if (getStatus(cur, fr, status)) hline_enabled = status.enabled(); @@ -1607,9 +1592,9 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) cur.cell().insert(cur.pos(), grid.cell(0)); cur.pos() += grid.cell(0).size(); if (hline_enabled) - rowinfo_[cur.row()].lines_ += grid.rowinfo_[0].lines_; + rowinfo_[cur.row()].lines += grid.rowinfo_[0].lines; else { - for (unsigned int l = 0; l < grid.rowinfo_[0].lines_; ++l) { + for (unsigned int l = 0; l < grid.rowinfo_[0].lines; ++l) { cur.cell().insert(0, MathAtom(new InsetMathUnknown(from_ascii("\\hline")))); cur.pos()++; @@ -1618,38 +1603,49 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } else { // multiple cells cur.recordUndoInset(); - col_type const numcols = - min(grid.ncols(), ncols() - col(cur.idx())); + col_type startcol = col(cur.idx()); + row_type startrow = cur.row(); + col_type oldncols = ncols(); + col_type numcols = + min(grid.ncols(), ncols() - startcol); row_type const numrows = min(grid.nrows(), nrows() - cur.row()); for (row_type r = 0; r < numrows; ++r) { for (col_type c = 0; c < numcols; ++c) { - idx_type i = index(r + cur.row(), c + col(cur.idx())); - cell(i).insert(0, grid.cell(grid.index(r, c))); + idx_type i = index(r + startrow, c + startcol); + pos_type const ipos = min(cur.pos(), pos_type(cell(i).size())); + cell(i).insert(ipos, grid.cell(grid.index(r, c))); } if (hline_enabled) - rowinfo_[r].lines_ += grid.rowinfo_[r].lines_; + rowinfo_[r].lines += grid.rowinfo_[r].lines; else { - for (unsigned int l = 0; l < grid.rowinfo_[r].lines_; ++l) { - idx_type i = index(r + cur.row(), 0); + for (unsigned int l = 0; l < grid.rowinfo_[r].lines; ++l) { + idx_type i = index(r + startrow, 0); cell(i).insert(0, MathAtom(new InsetMathUnknown(from_ascii("\\hline")))); } } - // append the left over horizontal cells to the last column - idx_type i = index(r + cur.row(), ncols() - 1); - for (InsetMath::col_type c = numcols; c < grid.ncols(); ++c) + // append columns for the left over horizontal cells + for (col_type c = numcols; c < grid.ncols(); ++c) { + addCol(c + startcol); + idx_type i = index(r + startrow, min(c + startcol, ncols() - 1)); cell(i).append(grid.cell(grid.index(r, c))); + ++numcols; + } } - // append the left over vertical cells to the last _cell_ + // amend cursor position if cols have been appended + cur.idx() += startrow * (ncols() - oldncols); + // append rows for the left over vertical cells idx_type i = nargs() - 1; for (row_type r = numrows; r < grid.nrows(); ++r) { + row_type crow = startrow + r; + addRow(crow - 1); for (col_type c = 0; c < grid.ncols(); ++c) - cell(i).append(grid.cell(grid.index(r, c))); + cell(index(min(crow, nrows() - 1), min(c + startcol, ncols() - 1))).append(grid.cell(grid.index(r, c))); if (hline_enabled) - rowinfo_[r].lines_ += grid.rowinfo_[r].lines_; + rowinfo_[crow].lines += grid.rowinfo_[r].lines; else { - for (unsigned int l = 0; l < grid.rowinfo_[r].lines_; ++l) { + for (unsigned int l = 0; l < grid.rowinfo_[r].lines; ++l) { cell(i).insert(0, MathAtom(new InsetMathUnknown(from_ascii("\\hline")))); } @@ -1665,13 +1661,9 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_LINE_BEGIN: - case LFUN_WORD_BACKWARD: - case LFUN_WORD_LEFT: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); // fall through case LFUN_LINE_BEGIN_SELECT: - case LFUN_WORD_BACKWARD_SELECT: - case LFUN_WORD_LEFT_SELECT: cur.selHandle(act == LFUN_WORD_BACKWARD_SELECT || act == LFUN_WORD_LEFT_SELECT || act == LFUN_LINE_BEGIN_SELECT); @@ -1690,13 +1682,9 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd) } break; - case LFUN_WORD_FORWARD: - case LFUN_WORD_RIGHT: case LFUN_LINE_END: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); // fall through - case LFUN_WORD_FORWARD_SELECT: - case LFUN_WORD_RIGHT_SELECT: case LFUN_LINE_END_SELECT: cur.selHandle(act == LFUN_WORD_FORWARD_SELECT || act == LFUN_WORD_RIGHT_SELECT || @@ -1727,14 +1715,8 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & status) const { switch (cmd.action()) { - case LFUN_INSET_MODIFY: { - istringstream is(to_utf8(cmd.argument())); - string s; - is >> s; - if (s != "tabular") { - // We only now about table actions here. - break; - } + case LFUN_TABULAR_FEATURE: { + string s = cmd.getArg(0); if (&cur.inset() != this) { // Table actions requires that the cursor is _inside_ the // table. @@ -1742,7 +1724,6 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd, status.message(from_utf8(N_("Cursor not in table"))); return true; } - is >> s; if (nrows() <= 1 && (s == "delete-row" || s == "swap-row")) { status.setEnabled(false); status.message(from_utf8(N_("Only one row"))); @@ -1754,18 +1735,18 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd, status.message(from_utf8(N_("Only one column"))); return true; } - if ((rowinfo_[cur.row()].lines_ == 0 && + if ((rowinfo_[cur.row()].lines == 0 && s == "delete-hline-above") || - (rowinfo_[cur.row() + 1].lines_ == 0 && + (rowinfo_[cur.row() + 1].lines == 0 && s == "delete-hline-below")) { status.setEnabled(false); status.message(from_utf8(N_("No hline to delete"))); return true; } - if ((colinfo_[cur.col()].lines_ == 0 && + if ((colinfo_[cur.col()].lines == 0 && s == "delete-vline-left") || - (colinfo_[cur.col() + 1].lines_ == 0 && + (colinfo_[cur.col() + 1].lines == 0 && s == "delete-vline-right")) { status.setEnabled(false); status.message(from_utf8(N_("No vline to delete"))); @@ -1797,28 +1778,10 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd, } else { status.setEnabled(false); status.message(bformat( - from_utf8(N_("Unknown tabular feature '%1$s'")), lyx::from_ascii(s))); + from_utf8(N_("Unknown tabular feature '%1$s'")), + from_utf8(s))); } -#if 0 - // FIXME: What did this code do? - // Please check whether it is still needed! - // should be more precise - if (v_align_ == '\0') { - status.enable(true); - break; - } - if (cmd.argument().empty()) { - status.enable(false); - break; - } - if (!contains("tcb", cmd.argument()[0])) { - status.enable(false); - break; - } - status.setOnOff(cmd.argument()[0] == v_align_); - status.setEnabled(true); -#endif return true; } @@ -1838,4 +1801,75 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd, } +char InsetMathGrid::colAlign(HullType type, col_type col) const +{ + switch (type) { + case hullEqnArray: + return "rcl"[col % 3]; + + case hullMultline: + return 'c'; + case hullGather: + LASSERT(isBufferValid(), + LYXERR0("Buffer not set correctly. Please report!"); + return 'c';); + if (buffer().params().is_math_indent) + return 'l'; + else + return 'c'; + + case hullAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullFlAlign: + return "rl"[col & 1]; + + case hullUnknown: + case hullNone: + case hullSimple: + case hullEquation: + case hullRegexp: + return 'c'; + } + // avoid warning + return 'c'; +} + + +//static +int InsetMathGrid::colSpace(HullType type, col_type col) +{ + int alignInterSpace = 0; + switch (type) { + case hullUnknown: + case hullNone: + case hullSimple: + case hullEquation: + case hullMultline: + case hullGather: + case hullRegexp: + return 0; + + case hullEqnArray: + return 5; + + case hullAlign: + alignInterSpace = 20; + break; + case hullAlignAt: + alignInterSpace = 0; + break; + case hullXAlignAt: + alignInterSpace = 40; + break; + case hullXXAlignAt: + case hullFlAlign: + alignInterSpace = 60; + break; + } + return (col % 2) ? alignInterSpace : 0; +} + + } // namespace lyx