]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathGrid.cpp
Substack should not be allowed to change columns
[lyx.git] / src / mathed / InsetMathGrid.cpp
index d6f275a3aaf518e6492af5e6f00d6e83190be159..85511e6ddfad4af59d26c1dd50bd3af42506430e 100644 (file)
@@ -78,41 +78,15 @@ static void resetGrid(InsetMathGrid & grid)
 }
 
 
-
 //////////////////////////////////////////////////////////////
 
 
-InsetMathGrid::CellInfo::CellInfo()
-       : multi(CELL_NORMAL)
-{}
-
-
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::RowInfo::RowInfo()
-       : descent(0), ascent(0), lines(0), skip(0),
-         allow_newpage(true)
-{}
-
-
-
 int InsetMathGrid::RowInfo::skipPixels(MetricsInfo const & mi) const
 {
        return mi.base.inPixels(crskip);
 }
 
 
-
-//////////////////////////////////////////////////////////////
-
-
-InsetMathGrid::ColInfo::ColInfo()
-       : align('c'), width(0), offset(0), lines(0), skip(0)
-{}
-
-
 //////////////////////////////////////////////////////////////
 
 
@@ -158,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;
 }
@@ -278,12 +252,12 @@ void InsetMathGrid::setHorizontalAlignments(docstring const & hh)
 }
 
 
-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
@@ -339,31 +313,31 @@ 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)
@@ -483,7 +457,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
        colinfo_[ncols()].width  = 0;
 
        // compute horizontal offsets
-       colinfo_[0].offset = border() + colinfo_[0].lines * vlinesep();;
+       colinfo_[0].offset = border() + colinfo_[0].lines * vlinesep();
        for (col_type col = 1; col <= ncols(); ++col) {
                colinfo_[col].offset =
                        colinfo_[col - 1].offset +
@@ -776,7 +750,7 @@ void InsetMathGrid::updateBuffer(ParIterator const & it, UpdateType utype, bool
 }
 
 
-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;
@@ -796,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;
 }
 
 
@@ -1184,7 +1158,7 @@ void InsetMathGrid::normalize(NormalStream & os) const
 }
 
 
-void InsetMathGrid::mathmlize(MathStream & ms) const
+void InsetMathGrid::mathmlize(MathMLStream & ms) const
 {
        bool const havetable = nrows() > 1 || ncols() > 1;
        if (havetable)
@@ -1215,7 +1189,7 @@ void InsetMathGrid::mathmlize(MathStream & ms) const
 
 // 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) {
@@ -1263,17 +1237,22 @@ void InsetMathGrid::validate(LaTeXFeatures & features) const
 }
 
 
-void InsetMathGrid::write(WriteStream & os) const
+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);
                // don't write & and empty cells at end of line,
@@ -1284,7 +1263,7 @@ 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) {
@@ -1295,7 +1274,7 @@ 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 = TexRow::mathEntry(id(),idx);
+                       TexRow::RowEntry const entry = TexRow::mathEntry(id(),idx);
                        os.texrow().start(entry);
                        if (col >= lastcol) {
                                ++col;
@@ -1320,19 +1299,18 @@ void InsetMathGrid::write(WriteStream & os,
                        os << eocString(col + nccols - 1, lastcol);
                        col += nccols;
                }
-               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);
        if (!s.empty()) {
-               if (eol.empty()) {
-                       if (os.fragile())
+               if (eolstr.empty()) {
+                       if (fragile)
                                os << "\\protect";
                        os << "\\\\";
                }
@@ -1592,7 +1570,8 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        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())
@@ -1624,37 +1603,47 @@ 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(c == 0 ? cur.pos() : 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;
                                else {
                                        for (unsigned int l = 0; l < grid.rowinfo_[r].lines; ++l) {
-                                               idx_type i = index(r + cur.row(), 0);
+                                               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) {
                                                cell(i).insert(0,