]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathGrid.cpp
Change the interface to a paragraph's layout. We still store a LayoutPtr, but now...
[lyx.git] / src / mathed / InsetMathGrid.cpp
index 594b1c264baa5994e17b3c4779b8eb0f8255b345..11f08ad9914d7a9987896dc892d78c6969625121 100644 (file)
 #include <config.h>
 
 #include "InsetMathGrid.h"
+
 #include "MathData.h"
 #include "MathParser.h"
 #include "MathStream.h"
+#include "MetricsInfo.h"
 
 #include "BufferView.h"
 #include "CutAndPaste.h"
 #include "FuncStatus.h"
-#include "Color.h"
 #include "Cursor.h"
-#include "debug.h"
 #include "FuncRequest.h"
-#include "gettext.h"
-#include "Undo.h"
 
 #include "frontends/Clipboard.h"
 #include "frontends/Painter.h"
 
-#include "insets/MailInset.h"
-
+#include "support/debug.h"
+#include "support/docstream.h"
+#include "support/gettext.h"
 #include "support/lstrings.h"
 
 #include <sstream>
 
+using namespace std;
+using namespace lyx::support;
 
 namespace lyx {
 
-using support::bformat;
-
-using std::endl;
-using std::max;
-using std::min;
-using std::swap;
-
-using std::string;
-using std::auto_ptr;
-using std::istream;
-using std::istringstream;
-using std::vector;
-
-class GridInsetMailer : public MailInset {
-public:
-       GridInsetMailer(InsetMathGrid & inset) : inset_(inset) {}
-       ///
-       virtual string const & name() const
-       {
-               static string const theName = "tabular";
-               return theName;
-       }
-       ///
-       virtual string const inset2string(Buffer const &) const
-       {
-               odocstringstream data;
-               //data << name() << " active_cell " << inset.getActCell() << '\n';
-               data << from_utf8(name()) << " active_cell " << 0 << '\n';
-               WriteStream ws(data);
-               inset_.write(ws);
-               return to_utf8(data.str());
-       }
-
-protected:
-       Inset & inset() const { return inset_; }
-       InsetMathGrid & inset_;
-};
-
-
 namespace {
 
 docstring verboseHLine(int n)
@@ -113,7 +75,7 @@ InsetMathGrid::CellInfo::CellInfo()
 
 
 InsetMathGrid::RowInfo::RowInfo()
-       : lines_(0), skip_(0), allow_pagebreak_(true)
+       : lines_(0), skip_(0), allow_newpage_(true)
 {}
 
 
@@ -184,9 +146,9 @@ InsetMathGrid::InsetMathGrid(col_type m, row_type n, char v, docstring const & h
 }
 
 
-auto_ptr<Inset> InsetMathGrid::doClone() const
+Inset * InsetMathGrid::clone() const
 {
-       return auto_ptr<Inset>(new InsetMathGrid(*this));
+       return new InsetMathGrid(*this);
 }
 
 
@@ -205,6 +167,7 @@ void InsetMathGrid::setDefaults()
        for (col_type col = 0; col < ncols(); ++col) {
                colinfo_[col].align_ = defaultColAlign(col);
                colinfo_[col].skip_  = defaultColSpace(col);
+               colinfo_[col].special_.clear();
        }
 }
 
@@ -216,13 +179,66 @@ void InsetMathGrid::halign(docstring const & hh)
                char_type c = *it;
                if (c == '|') {
                        colinfo_[col].lines_++;
+               } else if ((c == 'p' || c == 'm' || c == 'b'||
+                           c == '!' || c == '@' || c == '>' || c == '<') &&
+                          it + 1 != hh.end() && *(it + 1) == '{') {
+                       // @{decl.} and p{width} are standard LaTeX, the
+                       // others are extensions by array.sty
+                       bool const newcolumn = c == 'p' || c == 'm' || c == 'b';
+                       if (newcolumn) {
+                               // this declares a new column
+                               if (col >= ncols())
+                                       // Only intercolumn stuff is allowed
+                                       // in the last dummy column
+                                       break;
+                               colinfo_[col].align_ = 'l';
+                       } else {
+                               // this is intercolumn stuff
+                               if (colinfo_[col].special_.empty())
+                                       // Overtake possible 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;
+                               if (c == '{')
+                                       ++brace_open;
+                               else if (c == '}')
+                                       ++brace_close;
+                               ++it;
+                               if (brace_open > 0 && brace_open == brace_close)
+                                       break;
+                       }
+                       --it;
+                       if (newcolumn) {
+                               colinfo_[col].lines_ = count(
+                                       colinfo_[col].special_.begin(),
+                                       colinfo_[col].special_.end(), '|');
+                               LYXERR(Debug::MATHED, "special column separator: `"
+                                       << to_utf8(colinfo_[col].special_) << '\'');
+                               ++col;
+                               colinfo_[col].lines_ = 0;
+                               colinfo_[col].special_.clear();
+                       }
                } else if (col >= ncols()) {
-                       // Only '|' is allowed in the last dummy column
+                       // Only intercolumn stuff is allowed in the last
+                       // dummy column
                        break;
                } else if (c == 'c' || c == 'l' || c == 'r') {
-                       colinfo_[col].align_ = (char)c;
+                       colinfo_[col].align_ = static_cast<char>(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_) << '\'');
+                       }
                        ++col;
                        colinfo_[col].lines_ = 0;
+                       colinfo_[col].special_.clear();
                } else {
                        lyxerr << "unknown column separator: '" << c << "'" << endl;
                }
@@ -242,7 +258,8 @@ InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) const
 {
        col_type col = 0;
        for (docstring::const_iterator it = hh.begin(); it != hh.end(); ++it)
-               if (*it == 'c' || *it == 'l' || *it == 'r')
+               if (*it == 'c' || *it == 'l' || *it == 'r'||
+                   *it == 'p' || *it == 'm' || *it == 'b')
                        ++col;
        // let's have at least one column, even if we did not recognize its
        // alignment
@@ -255,6 +272,12 @@ InsetMathGrid::col_type InsetMathGrid::guessColumns(docstring const & hh) const
 void InsetMathGrid::halign(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];
+               if (c == 'l' || c == 'c' || c == 'r')
+                       c = h;
+       }
+       // FIXME: Change alignment of p, m and b columns, too
 }
 
 
@@ -268,10 +291,15 @@ docstring InsetMathGrid::halign() const
 {
        docstring res;
        for (col_type col = 0; col < ncols(); ++col) {
-               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_;
        }
-       return res + docstring(colinfo_[ncols()].lines_, '|');
+       if (colinfo_[ncols()].special_.empty())
+               return res + docstring(colinfo_[ncols()].lines_, '|');
+       return res + colinfo_[ncols()].special_;
 }
 
 
@@ -323,19 +351,21 @@ Length InsetMathGrid::vcrskip(row_type row) const
 }
 
 
-void InsetMathGrid::metrics(MetricsInfo & mi) const
+void InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
 {
        // let the cells adjust themselves
        InsetMathNest::metrics(mi);
 
+       BufferView & bv = *mi.base.bv;
+
        // compute absolute sizes of vertical structure
        for (row_type row = 0; row < nrows(); ++row) {
                int asc  = 0;
                int desc = 0;
                for (col_type col = 0; col < ncols(); ++col) {
-                       MathData const & c = cell(index(row, col));
-                       asc  = max(asc,  c.ascent());
-                       desc = max(desc, c.descent());
+                       Dimension const & dimc = cell(index(row, col)).dimension(bv);
+                       asc  = max(asc,  dimc.asc);
+                       desc = max(desc, dimc.des);
                }
                rowinfo_[row].ascent_  = asc;
                rowinfo_[row].descent_ = desc;
@@ -376,7 +406,7 @@ void InsetMathGrid::metrics(MetricsInfo & mi) const
        for (col_type col = 0; col < ncols(); ++col) {
                int wid = 0;
                for (row_type row = 0; row < nrows(); ++row)
-                       wid = max(wid, cell(index(row, col)).width());
+                       wid = max(wid, cell(index(row, col)).dimension(bv).wid);
                colinfo_[col].width_ = wid;
        }
        colinfo_[ncols()].width_  = 0;
@@ -393,17 +423,17 @@ void InsetMathGrid::metrics(MetricsInfo & mi) const
        }
 
 
-       dim_.wid   =   colinfo_[ncols() - 1].offset_
+       dim.wid   =   colinfo_[ncols() - 1].offset_
                       + colinfo_[ncols() - 1].width_
                 + vlinesep() * colinfo_[ncols()].lines_
                       + border();
 
-       dim_.asc  = - rowinfo_[0].offset_
+       dim.asc  = - rowinfo_[0].offset_
                       + rowinfo_[0].ascent_
                 + hlinesep() * rowinfo_[0].lines_
                       + border();
 
-       dim_.des =   rowinfo_[nrows() - 1].offset_
+       dim.des =   rowinfo_[nrows() - 1].offset_
                       + rowinfo_[nrows() - 1].descent_
                 + hlinesep() * rowinfo_[nrows()].lines_
                       + border();
@@ -459,31 +489,26 @@ void InsetMathGrid::metrics(MetricsInfo & mi) const
                cxrow->setBaseline(cxrow->getBaseline() - ascent);
        }
 */
-       metricsMarkers2(dim_);
-}
-
-
-bool InsetMathGrid::metrics(MetricsInfo & mi, Dimension & dim) const
-{
-       dim = dim_;
-       metrics(mi);
-       if (dim_ == dim)
-               return false;
-       dim = dim_;
-       return true;
+       metricsMarkers2(dim);
+       // Cache the inset dimension. 
+       setDimCache(mi, dim);
 }
 
 
 void InsetMathGrid::draw(PainterInfo & pi, int x, int y) const
 {
-       drawWithMargin(pi, x, y, 0, 0);
+       drawWithMargin(pi, x, y, 1, 1);
 }
 
+
 void InsetMathGrid::drawWithMargin(PainterInfo & pi, int x, int y,
        int lmargin, int rmargin) const
 {
+       Dimension const dim = dimension(*pi.base.bv);
+       BufferView const & bv = *pi.base.bv;
+
        for (idx_type idx = 0; idx < nargs(); ++idx)
-               cell(idx).draw(pi, x + lmargin + cellXOffset(idx),
+               cell(idx).draw(pi, x + lmargin + cellXOffset(bv, idx),
                        y + cellYOffset(idx));
 
        for (row_type row = 0; row <= nrows(); ++row)
@@ -491,17 +516,17 @@ void InsetMathGrid::drawWithMargin(PainterInfo & pi, int x, int y,
                        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);
+                                    x + dim.width() - rmargin - 1, yy,
+                                    Color_foreground);
                }
 
        for (col_type col = 0; col <= ncols(); ++col)
                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);
+                       pi.pain.line(xx, y - dim.ascent() + 1,
+                                    xx, y + dim.descent() - 1,
+                                    Color_foreground);
                }
        drawMarkers2(pi, x, y);
 }
@@ -519,9 +544,11 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
                int asc  = 0;
                int desc = 0;
                for (col_type col = 0; col < ncols(); ++col) {
-                       MathData const & c = cell(index(row, col));
-                       asc  = max(asc,  c.ascent());
-                       desc = max(desc, c.descent());
+                       //MathData const & c = cell(index(row, col));
+                       // FIXME: BROKEN!
+                       Dimension dimc;
+                       asc  = max(asc,  dimc.ascent());
+                       desc = max(desc, dimc.descent());
                }
                rowinfo_[row].ascent_  = asc;
                rowinfo_[row].descent_ = desc;
@@ -561,8 +588,10 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
        // compute absolute sizes of horizontal structure
        for (col_type col = 0; col < ncols(); ++col) {
                int wid = 0;
-               for (row_type row = 0; row < nrows(); ++row)
-                       wid = max(wid, cell(index(row, col)).width());
+               for (row_type row = 0; row < nrows(); ++row) {
+                       // FIXME: BROKEN!
+                       //wid = max(wid, cell(index(row, col)).width());
+               }
                colinfo_[col].width_ = wid;
        }
        colinfo_[ncols()].width_  = 0;
@@ -596,10 +625,10 @@ void InsetMathGrid::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
 }
 
 
-void InsetMathGrid::drawT(TextPainter & pain, int x, int y) const
+void InsetMathGrid::drawT(TextPainter & /*pain*/, int /*x*/, int /*y*/) const
 {
-       for (idx_type idx = 0; idx < nargs(); ++idx)
-               cell(idx).drawT(pain, x + cellXOffset(idx), y + cellYOffset(idx));
+//     for (idx_type idx = 0; idx < nargs(); ++idx)
+//             cell(idx).drawT(pain, x + cellXOffset(idx), y + cellYOffset(idx));
 }
 
 
@@ -609,7 +638,7 @@ docstring InsetMathGrid::eolString(row_type row, bool emptyline, bool fragile) c
 
        if (!rowinfo_[row].crskip_.zero())
                eol += '[' + from_utf8(rowinfo_[row].crskip_.asLatexString()) + ']';
-       else if(!rowinfo_[row].allow_pagebreak_)
+       else if(!rowinfo_[row].allow_newpage_)
                eol += '*';
 
        // make sure an upcoming '[' does not break anything
@@ -700,9 +729,9 @@ void InsetMathGrid::addCol(col_type newcol)
 
        for (row_type row = 0; row < nr; ++row)
                for (col_type col = 0; col < nc; ++col) {
-                       new_cells[row * (nc + 1) + col + (col > newcol)]
+                       new_cells[row * (nc + 1) + col + (col >= newcol)]
                                = cells_[row * nc + col];
-                       new_cellinfo[row * (nc + 1) + col + (col > newcol)]
+                       new_cellinfo[row * (nc + 1) + col + (col >= newcol)]
                                = cellinfo_[row * nc + col];
                }
        swap(cells_, new_cells);
@@ -753,15 +782,16 @@ void InsetMathGrid::swapCol(col_type col)
 }
 
 
-int InsetMathGrid::cellXOffset(idx_type idx) const
+int InsetMathGrid::cellXOffset(BufferView const & bv, idx_type idx) const
 {
        col_type c = col(idx);
        int x = colinfo_[c].offset_;
        char align = colinfo_[c].align_;
+       Dimension const & celldim = cell(idx).dimension(bv);
        if (align == 'r' || align == 'R')
-               x += colinfo_[c].width_ - cell(idx).width();
+               x += colinfo_[c].width_ - celldim.wid;
        if (align == 'c' || align == 'C')
-               x += (colinfo_[c].width_ - cell(idx).width()) / 2;
+               x += (colinfo_[c].width_ - celldim.wid) / 2;
        return x;
 }
 
@@ -783,14 +813,14 @@ bool InsetMathGrid::idxUpDown(Cursor & cur, bool up) const
                        return false;
                cur.idx() += ncols();
        }
-       cur.pos() = cur.cell().x2pos(cur.x_target() - cur.cell().xo(cur.bv()));
+       cur.pos() = cur.cell().x2pos(&cur.bv(), cur.x_target() - cur.cell().xo(cur.bv()));
        return true;
 }
 
 
-bool InsetMathGrid::idxLeft(Cursor & cur) const
+bool InsetMathGrid::idxBackward(Cursor & cur) const
 {
-       // leave matrix if on the left hand edge
+       // leave matrix if at the front edge
        if (cur.col() == 0)
                return false;
        --cur.idx();
@@ -799,9 +829,9 @@ bool InsetMathGrid::idxLeft(Cursor & cur) const
 }
 
 
-bool InsetMathGrid::idxRight(Cursor & cur) const
+bool InsetMathGrid::idxForward(Cursor & cur) const
 {
-       // leave matrix if on the right hand edge
+       // leave matrix if at the back edge
        if (cur.col() + 1 == ncols())
                return false;
        ++cur.idx();
@@ -1030,18 +1060,6 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
        //lyxerr << "*** InsetMathGrid: request: " << cmd << endl;
        switch (cmd.action) {
 
-       case LFUN_MOUSE_RELEASE:
-               //if (cmd.button() == mouse_button::button3) {
-               //      GridInsetMailer(*this).showDialog();
-               //      return DispatchResult(true, true);
-               //}
-               InsetMathNest::doDispatch(cur, cmd);
-               break;
-
-       case LFUN_INSET_DIALOG_UPDATE:
-//             GridInsetMailer(*this).updateDialog(&cur.bv());
-               break;
-
        // insert file functions
        case LFUN_LINE_DELETE:
                // FIXME: We use recordUndoInset when a change reflects more
@@ -1049,7 +1067,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                // multiple cells. Unfortunately this puts the cursor in front
                // of the inset after undo. This is (especilally for large
                // grids) annoying.
-               recordUndoInset(cur);
+               cur.recordUndoInset();
                //autocorrect_ = false;
                //macroModeClose();
                //if (selection_) {
@@ -1065,7 +1083,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                break;
 
        case LFUN_CELL_SPLIT:
-               recordUndo(cur);
+               cur.recordUndo();
                splitCell(cur);
                break;
 
@@ -1073,7 +1091,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                // See below.
                cur.selection() = false;
                if (!idxPrev(cur)) {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
                        cur.undispatched();
                }
                break;
@@ -1083,13 +1101,13 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                // hard bound to LFUN_CELL_BACKWARD
                cur.selection() = false;
                if (!idxNext(cur)) {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cmd = FuncRequest(LFUN_FINISHED_FORWARD);
                        cur.undispatched();
                }
                break;
 
-       case LFUN_BREAK_LINE: {
-               recordUndoInset(cur);
+       case LFUN_NEW_LINE: {
+               cur.recordUndoInset();
                row_type const r = cur.row();
                addRow(r);
 
@@ -1105,12 +1123,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                cur.pos() = cur.lastpos();
 
                //mathcursor->normalize();
-               //cmd = FuncRequest(LFUN_FINISHED_LEFT);
+               //cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
                break;
        }
 
        case LFUN_TABULAR_FEATURE: {
-               recordUndoInset(cur);
+               cur.recordUndoInset();
                //lyxerr << "handling tabular-feature " << to_utf8(cmd.argument()) << endl;
                istringstream is(to_utf8(cmd.argument()));
                string s;
@@ -1131,6 +1149,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        for (int i = 0, n = extractInt(is); i < n; ++i)
                                addRow(cur.row());
                else if (s == "delete-row") {
+                       cur.clearSelection(); // bug 4323
                        for (int i = 0, n = extractInt(is); i < n; ++i) {
                                delRow(cur.row());
                                if (cur.idx() >= nargs())
@@ -1165,10 +1184,11 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        row_type const r = cur.row();
                        col_type const c = cur.col();
                        for (int i = 0, n = extractInt(is); i < n; ++i)
-                               addCol(cur.col());
+                               addCol(cur.col() + 1);
                        cur.idx() = index(r, c);
                }
                else if (s == "delete-column") {
+                       cur.clearSelection(); // bug 4323
                        row_type const r = cur.row();
                        col_type const c = cur.col();
                        for (int i = 0, n = extractInt(is); i < n; ++i)
@@ -1186,18 +1206,39 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        swapCol(cur.col());
                        cur.pos() = 0; // trick, see above
                }
-               else if (s == "add-vline-left")
+               else if (s == "add-vline-left") {
                        colinfo_[cur.col()].lines_++;
-               else if (s == "add-vline-right")
+                       if (!colinfo_[cur.col()].special_.empty())
+                               colinfo_[cur.col()].special_ += '|';
+               }
+               else if (s == "add-vline-right") {
                        colinfo_[cur.col()+1].lines_++;
-               else if (s == "delete-vline-left")
+                       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_--;
-               else if (s == "delete-vline-right")
+                       docstring & special = colinfo_[cur.col()].special_;
+                       if (!special.empty()) {
+                               docstring::size_type i = special.rfind('|');
+                               BOOST_ASSERT(i != docstring::npos);
+                               special.erase(i, 1);
+                       }
+               }
+               else if (s == "delete-vline-right") {
                        colinfo_[cur.col()+1].lines_--;
+                       docstring & special = colinfo_[cur.col()+1].special_;
+                       if (!special.empty()) {
+                               docstring::size_type i = special.find('|');
+                               BOOST_ASSERT(i != docstring::npos);
+                               special.erase(i, 1);
+                       }
+               }
                else {
                        cur.undispatched();
                        break;
                }
+               // perhaps this should be FINISHED_BACKWARD -- just for clarity?
                lyxerr << "returning FINISHED_LEFT" << endl;
                break;
        }
@@ -1212,7 +1253,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        idocstringstream is(cmd.argument());
                        int n = 0;
                        is >> n;
-                       topaste = cap::getSelection(cur.buffer(), n);
+                       topaste = cap::selection(n);
                }
                InsetMathGrid grid(1, 1);
                if (!topaste.empty())
@@ -1220,12 +1261,12 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
 
                if (grid.nargs() == 1) {
                        // single cell/part of cell
-                       recordUndo(cur);
+                       cur.recordUndo();
                        cur.cell().insert(cur.pos(), grid.cell(0));
                        cur.pos() += grid.cell(0).size();
                } else {
                        // multiple cells
-                       recordUndoInset(cur);
+                       cur.recordUndoInset();
                        col_type const numcols =
                                min(grid.ncols(), ncols() - col(cur.idx()));
                        row_type const numrows =
@@ -1247,8 +1288,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                                        cell(i).append(grid.cell(grid.index(r, c)));
                }
                cur.clearSelection(); // bug 393
-               cur.bv().switchKeyMap();
-               finishUndo();
+               cur.finishUndo();
                break;
        }
 
@@ -1256,7 +1296,10 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_LINE_BEGIN:
        case LFUN_WORD_BACKWARD_SELECT:
        case LFUN_WORD_BACKWARD:
+       case LFUN_WORD_LEFT_SELECT:
+       case LFUN_WORD_LEFT:
                cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
+                               cmd.action == LFUN_WORD_LEFT_SELECT ||
                                cmd.action == LFUN_LINE_BEGIN_SELECT);
                cur.macroModeClose();
                if (cur.pos() != 0) {
@@ -1268,16 +1311,19 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.idx() = 0;
                        cur.pos() = 0;
                } else {
-                       cmd = FuncRequest(LFUN_FINISHED_LEFT);
+                       cmd = FuncRequest(LFUN_FINISHED_BACKWARD);
                        cur.undispatched();
                }
                break;
 
        case LFUN_WORD_FORWARD_SELECT:
        case LFUN_WORD_FORWARD:
+       case LFUN_WORD_RIGHT_SELECT:
+       case LFUN_WORD_RIGHT:
        case LFUN_LINE_END_SELECT:
        case LFUN_LINE_END:
                cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
+                               cmd.action == LFUN_WORD_RIGHT_SELECT ||
                                cmd.action == LFUN_LINE_END_SELECT);
                cur.macroModeClose();
                cur.clearTargetX();
@@ -1290,7 +1336,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.idx() = cur.lastidx();
                        cur.pos() = cur.lastpos();
                } else {
-                       cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+                       cmd = FuncRequest(LFUN_FINISHED_FORWARD);
                        cur.undispatched();
                }
                break;
@@ -1353,12 +1399,12 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                                from_utf8(N_("Unknown tabular feature '%1$s'")), lyx::from_ascii(s)));
                }
 
-               status.setOnOff(s == "align-left"    && halign(cur.col()) == 'l'
-                          || s == "align-right"   && halign(cur.col()) == 'r'
-                          || s == "align-center"  && halign(cur.col()) == 'c'
-                          || s == "valign-top"    && valign() == 't'
-                          || s == "valign-bottom" && valign() == 'b'
-                          || s == "valign-middle" && valign() == 'm');
+               status.setOnOff((s == "align-left" && halign(cur.col()) == 'l')
+                          || (s == "align-right"   && halign(cur.col()) == 'r')
+                          || (s == "align-center"  && halign(cur.col()) == 'c')
+                          || (s == "valign-top"    && valign() == 't')
+                          || (s == "valign-bottom" && valign() == 'b')
+                          || (s == "valign-middle" && valign() == 'm'));
 
 #if 0
                // FIXME: What did this code do?
@@ -1372,7 +1418,7 @@ bool InsetMathGrid::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.enable(false);
                        break;
                }
-               if (!support::contains("tcb", cmd.argument()[0])) {
+               if (!contains("tcb", cmd.argument()[0])) {
                        status.enable(false);
                        break;
                }