]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathGrid.cpp
Fix bug 5802 (http://bugzilla.lyx.org/show_bug.cgi?id=5802)
[lyx.git] / src / mathed / InsetMathGrid.cpp
index 683235e748e8da3e12f2f33dfa5b25db39a0bb79..61e13dfe8c0904839ad562563138a05d8cc9b6bd 100644 (file)
@@ -3,7 +3,7 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author André Pönitz
+ * \author André Pönitz
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -25,6 +25,7 @@
 #include "FuncRequest.h"
 
 #include "frontends/Clipboard.h"
+#include "frontends/FontMetrics.h"
 #include "frontends/Painter.h"
 
 #include "support/debug.h"
@@ -61,6 +62,17 @@ static int extractInt(istream & is)
 }
 
 
+static void resetGrid(InsetMathGrid & grid)
+{
+       while (grid.ncols() > 1)
+               grid.delCol(grid.ncols());
+       while (grid.nrows() > 1)
+               grid.delRow(grid.nrows());
+       grid.cell(0).erase(0, grid.cell(0).size());
+       grid.setDefaults();
+}
+
+
 
 //////////////////////////////////////////////////////////////
 
@@ -80,9 +92,11 @@ InsetMathGrid::RowInfo::RowInfo()
 
 
 
-int InsetMathGrid::RowInfo::skipPixels() const
+int InsetMathGrid::RowInfo::skipPixels(MetricsInfo const & mi) const
 {
-       return crskip_.inBP();
+       frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
+       return crskip_.inPixels(mi.base.textwidth,
+                               fm.width(char_type('M')));
 }
 
 
@@ -367,7 +381,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
                rowinfo_[row].offset_  =
                        rowinfo_[row - 1].offset_  +
                        rowinfo_[row - 1].descent_ +
-                       rowinfo_[row - 1].skipPixels() +
+                       rowinfo_[row - 1].skipPixels(mi) +
                        rowsep() +
                        rowinfo_[row].lines_ * hlinesep() +
                        rowinfo_[row].ascent_;
@@ -477,7 +491,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
        }
 */
        metricsMarkers2(dim);
-       // Cache the inset dimension. 
+       // Cache the inset dimension.
        setDimCache(mi, dim);
 }
 
@@ -550,7 +564,7 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
                rowinfo_[row].offset_  =
                        rowinfo_[row - 1].offset_  +
                        rowinfo_[row - 1].descent_ +
-                       //rowinfo_[row - 1].skipPixels() +
+                       //rowinfo_[row - 1].skipPixels(mi) +
                        1 + //rowsep() +
                        //rowinfo_[row].lines_ * hlinesep() +
                        rowinfo_[row].ascent_;
@@ -752,7 +766,7 @@ void InsetMathGrid::delCol(col_type col)
 
 void InsetMathGrid::copyCol(col_type col)
 {
-       addCol(col);
+       addCol(col+1);
        for (row_type row = 0; row < nrows(); ++row)
                cells_[row * ncols() + col + 1] = cells_[row * ncols() + col];
 }
@@ -967,26 +981,39 @@ void InsetMathGrid::mathmlize(MathStream & os) const
 
 void InsetMathGrid::write(WriteStream & 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
+{
+       MathEnsurer ensurer(os, false);
        docstring eol;
-       for (row_type row = 0; row < nrows(); ++row) {
+       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
                col_type lastcol = 0;
                bool emptyline = true;
-               for (col_type col = 0; col < ncols(); ++col)
+               for (col_type col = beg_col; col < end_col; ++col)
                        if (!cell(index(row, col)).empty()) {
                                lastcol = col + 1;
                                emptyline = false;
                        }
-               for (col_type col = 0; col < lastcol; ++col)
-                       os << cell(index(row, col)) << eocString(col, lastcol);
+               for (col_type col = beg_col; col < lastcol; ++col) {
+                       os << cell(index(row, col));
+                       if (os.pendingBrace())
+                               ModeSpecifier specifier(os, TEXT_MODE);
+                       os << eocString(col, lastcol);
+               }
                eol = eolString(row, emptyline, os.fragile());
                os << eol;
                // append newline only if line wasn't completely empty
                // and this was not the last line in the grid
-               if (!emptyline && row + 1 < nrows())
+               if (!emptyline && row + 1 < end_row)
                        os << "\n";
        }
+       // @TODO use end_row instead of nrows() ?
        docstring const s = verboseHLine(rowinfo_[nrows()].lines_);
        if (!s.empty()) {
                if (eol.empty()) {
@@ -1045,15 +1072,13 @@ void InsetMathGrid::splitCell(Cursor & cur)
 void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
 {
        //lyxerr << "*** InsetMathGrid: request: " << cmd << endl;
+
+       Parse::flags parseflg = Parse::QUIET;
+
        switch (cmd.action) {
 
        // insert file functions
        case LFUN_LINE_DELETE:
-               // FIXME: We use recordUndoInset when a change reflects more
-               // than one cell, because recordUndo does not work for
-               // multiple cells. Unfortunately this puts the cursor in front
-               // of the inset after undo. This is (especilally for large
-               // grids) annoying.
                cur.recordUndoInset();
                //autocorrect_ = false;
                //macroModeClose();
@@ -1076,7 +1101,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_CELL_BACKWARD:
                // See below.
-               cur.selection() = false;
+               cur.setSelection(false);
                if (!idxPrev(cur)) {
                        cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
                        cur.undispatched();
@@ -1086,7 +1111,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CELL_FORWARD:
                // Can't handle selection by additional 'shift' as this is
                // hard bound to LFUN_CELL_BACKWARD
-               cur.selection() = false;
+               cur.setSelection(false);
                if (!idxNext(cur)) {
                        cmd = FuncRequest(LFUN_FINISHED_FORWARD);
                        cur.undispatched();
@@ -1230,7 +1255,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_CLIPBOARD_PASTE:
+               parseflg |= Parse::VERBATIM;
+               // fall through
        case LFUN_PASTE: {
+               if (cur.currentMode() == TEXT_MODE)
+                       parseflg |= Parse::TEXTMODE;
                cur.message(_("Paste"));
                cap::replaceSelection(cur);
                docstring topaste;
@@ -1244,7 +1274,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                }
                InsetMathGrid grid(1, 1);
                if (!topaste.empty())
-                       mathed_parse_normal(grid, topaste);
+                       if (topaste.size() == 1
+                           || !mathed_parse_normal(grid, topaste, parseflg)) {
+                               resetGrid(grid);
+                               mathed_parse_normal(grid, topaste,
+                                               parseflg | Parse::VERBATIM);
+                       }
 
                if (grid.nargs() == 1) {
                        // single cell/part of cell
@@ -1339,15 +1374,15 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
 {
        switch (cmd.action) {
        case LFUN_TABULAR_FEATURE: {
-               string const s = to_utf8(cmd.argument());
+               string const s = cmd.getArg(0);
                if (nrows() <= 1 && (s == "delete-row" || s == "swap-row")) {
-                       status.enabled(false);
+                       status.setEnabled(false);
                        status.message(from_utf8(N_("Only one row")));
                        return true;
                }
                if (ncols() <= 1 &&
                    (s == "delete-column" || s == "swap-column")) {
-                       status.enabled(false);
+                       status.setEnabled(false);
                        status.message(from_utf8(N_("Only one column")));
                        return true;
                }
@@ -1355,7 +1390,7 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                     s == "delete-hline-above") ||
                    (rowinfo_[cur.row() + 1].lines_ == 0 &&
                     s == "delete-hline-below")) {
-                       status.enabled(false);
+                       status.setEnabled(false);
                        status.message(from_utf8(N_("No hline to delete")));
                        return true;
                }
@@ -1364,14 +1399,24 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                     s == "delete-vline-left") ||
                    (colinfo_[cur.col() + 1].lines_ == 0 &&
                     s == "delete-vline-right")) {
-                       status.enabled(false);
+                       status.setEnabled(false);
                        status.message(from_utf8(N_("No vline to delete")));
                        return true;
                }
                if (s == "valign-top" || s == "valign-middle" ||
                    s == "valign-bottom" || s == "align-left" ||
-                   s == "align-right" || s == "align-center" ||
-                   s == "append-row" || s == "delete-row" ||
+                   s == "align-right" || s == "align-center") {
+                       status.setEnabled(true);
+                       char const ha = horizontalAlignment(cur.col());
+                       char const va = verticalAlignment();
+                       status.setOnOff((s == "align-left" && ha == 'l')
+                                       || (s == "align-right"   && ha == 'r')
+                                       || (s == "align-center"  && ha == 'c')
+                                       || (s == "valign-top"    && va == 't')
+                                       || (s == "valign-bottom" && va == 'b')
+                                       || (s == "valign-middle" && va == 'm'));
+               }
+               if (s == "append-row" || s == "delete-row" ||
                    s == "copy-row" || s == "swap-row" ||
                    s == "add-hline-above" || s == "add-hline-below" ||
                    s == "delete-hline-above" || s == "delete-hline-below" ||
@@ -1379,22 +1424,13 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                    s == "copy-column" || s == "swap-column" ||
                    s == "add-vline-left" || s == "add-vline-right" ||
                    s == "delete-vline-left" || s == "delete-vline-right")
-                       status.enabled(true);
+                       status.setEnabled(true);
                else {
-                       status.enabled(false);
+                       status.setEnabled(false);
                        status.message(bformat(
                                from_utf8(N_("Unknown tabular feature '%1$s'")), lyx::from_ascii(s)));
                }
 
-               char const ha = horizontalAlignment(cur.col());
-               char const va = verticalAlignment();
-               status.setOnOff((s == "align-left" && ha == 'l')
-                          || (s == "align-right"   && ha == 'r')
-                          || (s == "align-center"  && ha == 'c')
-                          || (s == "valign-top"    && va == 't')
-                          || (s == "valign-bottom" && va == 'b')
-                          || (s == "valign-middle" && va == 'm'));
-
 #if 0
                // FIXME: What did this code do?
                // Please check whether it is still needed!
@@ -1412,18 +1448,18 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                        break;
                }
                status.setOnOff(cmd.argument()[0] == v_align_);
-               status.enabled(true);
+               status.setEnabled(true);
 #endif
                return true;
        }
 
        case LFUN_CELL_SPLIT:
-               status.enabled(true);
+               status.setEnabled(true);
                return true;
 
        case LFUN_CELL_BACKWARD:
        case LFUN_CELL_FORWARD:
-               status.enabled(true);
+               status.setEnabled(true);
                return true;
 
        default: