]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insettabular.C
prepare for 1.1.6pre2
[lyx.git] / src / insets / insettabular.C
index f14093d0706dfc795858e9f125be5ed9c59d9443..3636d99d7903110856b04d8374fcddc573840b5c 100644 (file)
@@ -3,9 +3,9 @@
  * 
  *           LyX, The Document Processor
  *
- *           Copyright (C) 2000 The LyX Team.
+ *           Copyright 2000 The LyX Team.
  *
- *======================================================
+ * ======================================================
  */
 
 #include <config.h>
 
 #include "buffer.h"
 #include "commandtags.h"
+#include "debug.h"
 #include "LaTeXFeatures.h"
 #include "Painter.h"
 #include "font.h"
+#include "lyxtext.h"
+#include "lyx_gui_misc.h"
+#include "LyXView.h"
+#include "lyxfunc.h"
 #include "insets/insettext.h"
+#include "frontends/Dialogs.h"
+#include "debug.h"
+#include "lyxfunc.h"
 
 const int ADD_TO_HEIGHT = 2;
-const int ADD_TO_TABLE_WIDTH = 2;
+const int ADD_TO_TABULAR_WIDTH = 2;
+///
+static LyXTabular * paste_tabular = 0;
+bool InsetTabular::hasPasteBuffer() const
+{
+    return (paste_tabular != 0);
+}
 
 using std::ostream;
 using std::ifstream;
+using std::max;
+using std::endl;
+using std::swap;
+
+    
+struct tabular_features {
+    LyXTabular::Feature action;
+    string feature;
+};
+
+//static tabular_features * tabularFeatures = 0;
 
-InsetTabular::InsetTabular(Buffer * buf, int rows=1, int columns=1)
+static tabular_features tabularFeatures[] =
+{
+    { LyXTabular::APPEND_ROW, "append-row" },
+    { LyXTabular::APPEND_COLUMN, "append-column" },
+    { LyXTabular::DELETE_ROW, "delete-row" },
+    { LyXTabular::DELETE_COLUMN, "delete-column" },
+    { LyXTabular::TOGGLE_LINE_TOP, "toggle-line-top" },
+    { LyXTabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom" },
+    { LyXTabular::TOGGLE_LINE_LEFT, "toggle-line-left" },
+    { LyXTabular::TOGGLE_LINE_RIGHT, "toggle-line-right" },
+    { LyXTabular::ALIGN_LEFT, "align-left" },
+    { LyXTabular::ALIGN_RIGHT, "align-right" },
+    { LyXTabular::ALIGN_CENTER, "align-center" },
+    { LyXTabular::VALIGN_TOP, "valign-top" },
+    { LyXTabular::VALIGN_BOTTOM, "valign-bottom" },
+    { LyXTabular::VALIGN_CENTER, "valign-center" },
+    { LyXTabular::M_TOGGLE_LINE_TOP, "m-toggle-line-top" },
+    { LyXTabular::M_TOGGLE_LINE_BOTTOM, "m-toggle-line-bottom" },
+    { LyXTabular::M_TOGGLE_LINE_LEFT, "m-toggle-line-left" },
+    { LyXTabular::M_TOGGLE_LINE_RIGHT, "m-toggle-line-right" },
+    { LyXTabular::M_ALIGN_LEFT, "m-align-left" },
+    { LyXTabular::M_ALIGN_RIGHT, "m-align-right" },
+    { LyXTabular::M_ALIGN_CENTER, "m-align-center" },
+    { LyXTabular::M_VALIGN_TOP, "m-valign-top" },
+    { LyXTabular::M_VALIGN_BOTTOM, "m-valign-bottom" },
+    { LyXTabular::M_VALIGN_CENTER, "m-valign-center" },
+    { LyXTabular::MULTICOLUMN, "multicolumn" },
+    { LyXTabular::SET_ALL_LINES, "set-all-lines" },
+    { LyXTabular::UNSET_ALL_LINES, "unset-all-lines" },
+    { LyXTabular::SET_LONGTABULAR, "set-longtabular" },
+    { LyXTabular::UNSET_LONGTABULAR, "unset-longtabular" },
+    { LyXTabular::SET_PWIDTH, "set-pwidth" },
+    { LyXTabular::SET_MPWIDTH, "set-mpwidth" },
+    { LyXTabular::SET_ROTATE_TABULAR, "set-rotate-tabular" },
+    { LyXTabular::UNSET_ROTATE_TABULAR, "unset-rotate-tabular" },
+    { LyXTabular::SET_ROTATE_CELL, "set-rotate-cell" },
+    { LyXTabular::UNSET_ROTATE_CELL, "unset-rotate-cell" },
+    { LyXTabular::SET_USEBOX, "set-usebox" },
+    { LyXTabular::SET_LTHEAD, "set-lthead" },
+    { LyXTabular::SET_LTFIRSTHEAD, "set-ltfirsthead" },
+    { LyXTabular::SET_LTFOOT, "set-ltfoot" },
+    { LyXTabular::SET_LTLASTFOOT, "set-ltlastfoot" },
+    { LyXTabular::SET_LTNEWPAGE, "set-ltnewpage" },
+    { LyXTabular::SET_SPECIAL_COLUMN, "set-special-column" },
+    { LyXTabular::SET_SPECIAL_MULTI, "set-special-multi" },
+    { LyXTabular::LAST_ACTION, "" }
+};
+
+
+static inline
+bool cellstart(LyXParagraph::size_type p) 
+{
+       return ((p % 2) == 0);
+}
+
+
+InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
+       : buffer(&buf)
 {
     if (rows <= 0)
         rows = 1;
     if (columns <= 0)
         columns = 1;
-    tabular = new LyXTable(rows,columns,buf);
+    tabular = new LyXTabular(this, rows,columns);
+    // for now make it always display as display() inset
+    // just for test!!!
     the_locking_inset = 0;
-    buffer = buf;
-    cursor_visible = false;
-    old_x = -1;
-    sel_pos_start = sel_pos_end = 0;
-    no_selection = false;
-    init = true;
+    locked = no_selection = cursor_visible = false;
+    cursor.x_fix(-1);
+    oldcell = -1;
+    actrow = actcell = 0;
+    cursor.pos(0);
+    clearSelection();
+    need_update = INIT;
 }
 
-InsetTabular::InsetTabular(InsetTabular const & tab, Buffer * buf)
+
+InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf)
+       : buffer(&buf)
 {
-    tabular = new LyXTable(*(tab.tabular), buf);
+    tabular = new LyXTabular(this, *(tab.tabular));
     the_locking_inset = 0;
-    buffer = buf;
-    cursor_visible = false;
-    old_x = -1;
-    sel_pos_start = sel_pos_end = 0;
-    no_selection = false;
-    init = true;
+    locked = no_selection = cursor_visible = false;
+    cursor.x_fix(-1);
+    oldcell = -1;
+    actrow = actcell = 0;
+    cursor.pos(0);
+    sel_pos_start = sel_pos_end = sel_cell_start = sel_cell_end = 0;
+    need_update = INIT;
 }
 
+
 InsetTabular::~InsetTabular()
 {
-    if (tabular)
-        delete tabular;
+    delete tabular;
+    hideDialog();
 }
 
 
-InsetTabular * InsetTabular::Clone() const
+Inset * InsetTabular::Clone(Buffer const & buf) const
 {
-    InsetTabular * t = new InsetTabular(*this, buffer);
+    InsetTabular * t = new InsetTabular(*this, buf);
+    delete t->tabular;
+    t->tabular = tabular->Clone(t);
     return t;
 }
 
 
-void InsetTabular::Write(ostream & os) const
+void InsetTabular::Write(Buffer const * buf, ostream & os) const
 {
-    os << "\\begin_inset Tabular\n";
-    tabular->Write(os,false);
-    os << "\\end_inset\n";
+    os << " Tabular" << endl;
+    tabular->Write(buf, os);
 }
 
 
-void InsetTabular::Read(LyXLex & lex)
+void InsetTabular::Read(Buffer const * buf, LyXLex & lex)
 {
+    bool old_format = (lex.GetString() == "\\LyXTable");
+    string token;
+
     if (tabular)
        delete tabular;
+    tabular = new LyXTabular(buf, this, lex);
+
+    need_update = INIT;
+
+    if (old_format)
+       return;
+
+    lex.nextToken();
+    token = lex.GetString();
+    while (lex.IsOK() && (token != "\\end_inset")) {
+       lex.nextToken();
+       token = lex.GetString();
+    }
+    if (token != "\\end_inset") {
+        lex.printError("Missing \\end_inset at this point. "
+                       "Read: `$$Token'");
+    }
+}
+
+
+int InsetTabular::ascent(BufferView *, LyXFont const &) const
+{
+    return tabular->GetAscentOfRow(0);
+}
+
 
-//    bool old_format = (lex.GetString() == "\\LyXTable");
-    tabular = new LyXTable(lex, buffer);
-    init = true;
+int InsetTabular::descent(BufferView *, LyXFont const &) const
+{
+    return tabular->GetHeightOfTabular() - tabular->GetAscentOfRow(0) + 1;
+}
+
+
+int InsetTabular::width(BufferView *, LyXFont const &) const
+{
+    return tabular->GetWidthOfTabular() + (2 * ADD_TO_TABULAR_WIDTH);
 }
 
 
-int InsetTabular::ascent(Painter & pain, LyXFont const & font) const
+void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
+                       float & x, bool cleared) const
 {
-    if (init) {
-       calculate_width_of_cells(pain, font);
-       init = false;
+    Painter & pain = bv->painter();
+    int i, j;
+    int nx;
+    float cx;
+
+    UpdatableInset::draw(bv, font, baseline, x, cleared);
+    if (!cleared && ((need_update == INIT) || (need_update == FULL) ||
+                    (top_x != int(x)) || (top_baseline != baseline))) {
+       int h = ascent(bv, font) + descent(bv, font);
+       int tx = display() || !owner() ? 0 : top_x;
+       int w =  tx ? width(bv, font) : pain.paperWidth();
+       int ty = baseline - ascent(bv, font);
+       
+       if (ty < 0)
+           ty = 0;
+       if ((ty + h) > pain.paperHeight())
+           h = pain.paperHeight();
+       if ((top_x + w) > pain.paperWidth())
+           w = pain.paperWidth();
+       pain.fillRectangle(tx, ty, w, h);
+       need_update = FULL;
+       cleared = true;
     }
-    return tabular->AscentOfRow(0);
+    top_x = int(x);
+    top_baseline = baseline;
+    if (bv->text->status == LyXText::CHANGED_IN_DRAW)
+       return;
+    bool dodraw;
+    x += ADD_TO_TABULAR_WIDTH;
+    if (cleared) {
+       int cell = 0;
+       for (i = 0; i < tabular->rows(); ++i) {
+           nx = int(x);
+           dodraw = ((baseline + tabular->GetDescentOfRow(i)) > 0) &&
+                   (baseline - tabular->GetAscentOfRow(i))<pain.paperHeight();
+           for (j = 0; j < tabular->columns(); ++j) {
+               if (tabular->IsPartOfMultiColumn(i, j))
+                   continue;
+               cx = nx + tabular->GetBeginningOfTextInCell(cell);
+               if (dodraw) {
+                   if (hasSelection())
+                       DrawCellSelection(pain, nx, baseline, i, j, cell);
+                   tabular->GetCellInset(cell)->draw(bv, font, baseline, cx,
+                                                     cleared);
+                   DrawCellLines(pain, nx, baseline, i, cell);
+               }
+               nx += tabular->GetWidthOfColumn(cell);
+               ++cell;
+           }
+           baseline += tabular->GetDescentOfRow(i) +
+               tabular->GetAscentOfRow(i + 1) +
+               tabular->GetAdditionalHeight(cell);
+       }
+    } else if (need_update == CELL) {
+       int cell = 0;
+       nx = int(x);
+       if (the_locking_inset) {
+           Inset * inset = tabular->GetCellInset(cell);
+           for (i = 0; (inset != the_locking_inset) && (i < tabular->rows());
+                ++i)
+           {
+               for (j = 0; (inset != the_locking_inset) && (j < tabular->columns()); ++j)
+               {
+                   if (tabular->IsPartOfMultiColumn(i, j))
+                       continue;
+                   nx += tabular->GetWidthOfColumn(cell);
+                   ++cell;
+                   inset = tabular->GetCellInset(cell);
+               }
+               if (tabular->row_of_cell(cell) > i) {
+                   nx = int(x);
+                   baseline += tabular->GetDescentOfRow(i) +
+                       tabular->GetAscentOfRow(i + 1) +
+                       tabular->GetAdditionalHeight(cell);
+               }
+           }
+       } else {
+           for (i = 0; (cell < actcell) && (i < tabular->rows()); ++i) {
+               for (j = 0; (cell < actcell) && (j < tabular->columns()); ++j) {
+                   if (tabular->IsPartOfMultiColumn(i, j))
+                       continue;
+                   nx += tabular->GetWidthOfColumn(cell);
+                   ++cell;
+               }
+               if (tabular->row_of_cell(cell) > i) {
+                   nx = int(x);
+                   baseline += tabular->GetDescentOfRow(i) +
+                       tabular->GetAscentOfRow(i + 1) +
+                       tabular->GetAdditionalHeight(cell);
+               }
+           }
+       }
+       i = tabular->row_of_cell(cell);
+       if (the_locking_inset != tabular->GetCellInset(cell)) {
+           lyxerr[Debug::INSETS] << "ERROR this shouldn't happen\n";
+           return;
+       }
+#if 0
+       LyXText::text_status st = bv->text->status;
+       do {
+           cx = nx + tabular->GetBeginningOfTextInCell(cell);
+           bv->text->status = st;
+           if (need_update == CELL) {
+               // clear before the inset
+               pain.fillRectangle(
+                   nx + 1,
+                   baseline - tabular->GetAscentOfRow(i) + 1,
+                   int(cx - nx - 1),
+                   tabular->GetAscentOfRow(i) +
+                   tabular->GetDescentOfRow(i) - 1);
+               // clear behind the inset
+               pain.fillRectangle(
+                   int(cx + the_locking_inset->width(bv,font) + 1),
+                   baseline - tabular->GetAscentOfRow(i) + 1,
+                   tabular->GetWidthOfColumn(cell) -
+                   tabular->GetBeginningOfTextInCell(cell) -
+                   the_locking_inset->width(bv,font) -
+                   tabular->GetAdditionalWidth(cell) - 1,
+                   tabular->GetAscentOfRow(i) +
+                   tabular->GetDescentOfRow(i) - 1);
+           }
+           tabular->GetCellInset(cell)->draw(bv,font,baseline, cx, false);
+       } while(bv->text->status == LyXText::CHANGED_IN_DRAW);
+#else
+       cx = nx + tabular->GetBeginningOfTextInCell(cell);
+       if (need_update == CELL) {
+           // clear before the inset
+           pain.fillRectangle(
+               nx + 1,
+               baseline - tabular->GetAscentOfRow(i) + 1,
+               int(cx - nx - 1),
+               tabular->GetAscentOfRow(i) +
+               tabular->GetDescentOfRow(i) - 1);
+           // clear behind the inset
+           pain.fillRectangle(
+               int(cx + the_locking_inset->width(bv,font) + 1),
+               baseline - tabular->GetAscentOfRow(i) + 1,
+               tabular->GetWidthOfColumn(cell) -
+               tabular->GetBeginningOfTextInCell(cell) -
+               the_locking_inset->width(bv,font) -
+               tabular->GetAdditionalWidth(cell) - 1,
+               tabular->GetAscentOfRow(i) +
+               tabular->GetDescentOfRow(i) - 1);
+       }
+       tabular->GetCellInset(cell)->draw(bv,font,baseline, cx, false);
+       if (bv->text->status == LyXText::CHANGED_IN_DRAW)
+           return;
+#endif
+    }
+    x -= ADD_TO_TABULAR_WIDTH;
+    x += width(bv, font);
+    if (bv->text->status == LyXText::CHANGED_IN_DRAW)
+       need_update = INIT;
+    else
+       need_update = NONE;
 }
 
 
-int InsetTabular::descent(Painter & pain, LyXFont const & font) const
+void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline,
+                                 int row, int cell) const
 {
-    if (init) {
-       calculate_width_of_cells(pain, font);
-       init = false;
+    int  x2 = x + tabular->GetWidthOfColumn(cell);
+    bool on_off;
+
+    if (!tabular->TopAlreadyDrawed(cell)) {
+       on_off = !tabular->TopLine(cell);
+       pain.line(x, baseline - tabular->GetAscentOfRow(row),
+                 x2, baseline -  tabular->GetAscentOfRow(row),
+                 on_off ? LColor::tabularonoffline : LColor::tabularline,
+                 on_off ? Painter::line_onoffdash : Painter::line_solid);
+    }
+    on_off = !tabular->BottomLine(cell);
+    pain.line(x,baseline +  tabular->GetDescentOfRow(row),
+             x2, baseline +  tabular->GetDescentOfRow(row),
+             on_off ? LColor::tabularonoffline : LColor::tabularline,
+             on_off ? Painter::line_onoffdash : Painter::line_solid);
+    if (!tabular->LeftAlreadyDrawed(cell)) {
+       on_off = !tabular->LeftLine(cell);
+       pain.line(x, baseline -  tabular->GetAscentOfRow(row),
+                 x, baseline +  tabular->GetDescentOfRow(row),
+                 on_off ? LColor::tabularonoffline : LColor::tabularline,
+                 on_off ? Painter::line_onoffdash : Painter::line_solid);
     }
-    return tabular->HeightOfTable() - tabular->AscentOfRow(0);
+    on_off = !tabular->RightLine(cell);
+    pain.line(x2 - tabular->GetAdditionalWidth(cell),
+              baseline -  tabular->GetAscentOfRow(row),
+              x2 - tabular->GetAdditionalWidth(cell),
+              baseline +  tabular->GetDescentOfRow(row),
+             on_off ? LColor::tabularonoffline : LColor::tabularline,
+              on_off ? Painter::line_onoffdash : Painter::line_solid);
 }
 
 
-int InsetTabular::width(Painter & pain, LyXFont const & font) const
+void InsetTabular::DrawCellSelection(Painter & pain, int x, int baseline,
+                                    int row, int column, int cell) const
 {
-    if (init) {
-       calculate_width_of_cells(pain, font);
-       init = false;
+    int cs = tabular->column_of_cell(sel_cell_start);
+    int ce = tabular->column_of_cell(sel_cell_end);
+    if (cs > ce) {
+       ce = cs;
+       cs = tabular->column_of_cell(sel_cell_end);
+    } else {
+       ce = tabular->right_column_of_cell(sel_cell_end);
+    }
+
+    int rs = tabular->row_of_cell(sel_cell_start);
+    int re = tabular->row_of_cell(sel_cell_end);
+    if (rs > re) swap(rs, re);
+
+    if ((column >= cs) && (column <= ce) && (row >= rs) && (row <= re)) {
+       int w = tabular->GetWidthOfColumn(cell);
+       int h = tabular->GetAscentOfRow(row) + tabular->GetDescentOfRow(row);
+       pain.fillRectangle(x, baseline - tabular->GetAscentOfRow(row),
+                          w, h, LColor::selection);
     }
-    return tabular->WidthOfTable() + (2 * ADD_TO_TABLE_WIDTH);
 }
 
 
-void InsetTabular::draw(Painter & pain, const LyXFont & font, int,
-                       float &) const
+void InsetTabular::update(BufferView * bv, LyXFont const & font, bool reinit)
 {
-    calculate_width_of_cells(pain, font);
+    if (reinit) {
+       need_update = INIT;
+       calculate_dimensions_of_cells(bv, font, true);
+       if (owner())
+           owner()->update(bv, font, true);
+       return;
+    }
+    if (the_locking_inset) {
+       the_locking_inset->update(bv, font, reinit);
+//     resetPos(bv);
+//     inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+//     inset_y = cursor.y();
+    }
+    switch (need_update) {
+    case INIT:
+    case FULL:
+    case CELL:
+       if (calculate_dimensions_of_cells(bv, font, false))
+           need_update = INIT;
+       break;
+    case SELECTION:
+       need_update = INIT;
+       break;
+    default:
+       break;
+    }
 }
 
 
-const char * InsetTabular::EditMessage() const
+string const InsetTabular::EditMessage() const
 {
     return _("Opened Tabular Inset");
 }
@@ -142,146 +481,248 @@ void InsetTabular::Edit(BufferView * bv, int x, int y, unsigned int button)
 {
     UpdatableInset::Edit(bv, x, y, button);
 
-    bv->lockInset(this);
+    if (!bv->lockInset(this)) {
+       lyxerr[Debug::INSETS] << "InsetTabular::Cannot lock inset" << endl;
+       return;
+    }
+    locked = true;
     the_locking_inset = 0;
-    inset_pos = inset_x = inset_y = 0;
-    no_selection = true;
-    setPos(x,y);
-    sel_pos_start = sel_pos_end = actpos;
+    inset_pos = 0;
+    inset_x = 0;
+    inset_y = 0;
+    setPos(bv, x, y);
+    sel_pos_start = sel_pos_end = cursor.pos();
     sel_cell_start = sel_cell_end = actcell;
-//    bv->getOwner()->getPopups().updateFormTable();
+    bv->text->FinishUndo();
+    if (InsetHit(bv, x, y)) {
+       ActivateCellInset(bv, x, y, button);
+    }
+//    UpdateLocal(bv, NONE, false);
+//    bv->getOwner()->getPopups().updateFormTabular();
 }
 
 
 void InsetTabular::InsetUnlock(BufferView * bv)
 {
-    if (the_locking_inset)
+    if (the_locking_inset) {
        the_locking_inset->InsetUnlock(bv);
+       the_locking_inset = 0;
+    }
     HideInsetCursor(bv);
-    the_locking_inset = 0;
-    if (hasCharSelection()) {
-       sel_pos_start = sel_pos_end = actpos;
-       UpdateLocal(bv, false);
-    } else
-       sel_pos_start = sel_pos_end = actpos;
     no_selection = false;
+    oldcell = -1;
+    locked = false;
+    if (scroll() || hasSelection()) {
+       if (scroll()) {
+           scroll(bv, 0.0F);
+       } else {
+           sel_pos_start = sel_pos_end = 0;
+           sel_cell_start = sel_cell_end = 0;
+       }
+       UpdateLocal(bv, FULL, false);
+    }
 }
 
-bool InsetTabular::LockInsetInInset(UpdatableInset *)
+
+void InsetTabular::UpdateLocal(BufferView * bv, UpdateCodes what,
+                              bool mark_dirty) const
 {
-    return true;
+    if (need_update < what) // only set this if it has greater update
+       need_update = what;
+    // Dirty Cast! (Lgb)
+    if (need_update != NONE) {
+       bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
+       if (locked) // && (what != NONE))
+           resetPos(bv);
+    }
 }
 
 
-bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
-                                     bool lr)
+bool InsetTabular::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
 {
-    if (!the_locking_inset)
+    lyxerr[Debug::INSETS] << "InsetTabular::LockInsetInInset(" <<inset<< "): ";
+    if (!inset)
        return false;
-    if (the_locking_inset == inset) {
-       the_locking_inset->InsetUnlock(bv);
-       the_locking_inset = 0;
-       if (lr)
-           moveRight(false);
+    oldcell = -1;
+    if (inset == tabular->GetCellInset(actcell)) {
+       lyxerr[Debug::INSETS] << "OK" << endl;
+       the_locking_inset = tabular->GetCellInset(actcell);
+       resetPos(bv);
+       inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+       inset_y = cursor.y();
+       inset_pos = cursor.pos();
        return true;
+    } else if (the_locking_inset && (the_locking_inset == inset)) {
+       if (cursor.pos() == inset_pos) {
+           lyxerr[Debug::INSETS] << "OK" << endl;
+           resetPos(bv);
+           inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+           inset_y = cursor.y();
+       } else {
+           lyxerr[Debug::INSETS] << "cursor.pos != inset_pos" << endl;
+       }
+    } else if (the_locking_inset) {
+       lyxerr[Debug::INSETS] << "MAYBE" << endl;
+       return the_locking_inset->LockInsetInInset(bv, inset);
     }
-    return the_locking_inset->UnlockInsetInInset(bv, inset, lr);
+    lyxerr[Debug::INSETS] << "NOT OK" << endl;
+    return false;
 }
 
 
-void InsetTabular::UpdateLocal(BufferView * bv, bool flag)
+bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
+                                  bool lr)
 {
-    resetPos();
-    bv->updateInset(this, flag);
+    if (!the_locking_inset)
+        return false;
+    if (the_locking_inset == inset) {
+        the_locking_inset->InsetUnlock(bv);
+        the_locking_inset = 0;
+        if (lr)
+            moveRight(bv, false);
+       ShowInsetCursor(bv, false);
+       UpdateLocal(bv, CELL, false);
+        return true;
+    }
+    if (the_locking_inset->UnlockInsetInInset(bv, inset, lr)) {
+       if (inset->LyxCode() == TABULAR_CODE &&
+           !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))
+       {
+               bv->owner()->getDialogs()->updateTabular(this);
+               oldcell = actcell;
+       }
+       return true;
+    }
+    return false;
 }
 
+
 bool InsetTabular::UpdateInsetInInset(BufferView * bv, Inset * inset)
 {
     if (!the_locking_inset)
        return false;
-    if (the_locking_inset != inset)
-       return the_locking_inset->UpdateInsetInInset(bv, inset);
-    UpdateLocal(bv);
+    if (the_locking_inset != inset) {
+       if (!the_locking_inset->UpdateInsetInInset(bv, inset))
+           return false;
+    }
+    UpdateLocal(bv, CELL, false);
     return true;
 }
 
-void InsetTabular::InsetButtonRelease(BufferView *bv, int x, int y, int button)
+
+unsigned int InsetTabular::InsetInInsetY()
 {
-    if (the_locking_inset) {
-        the_locking_inset->InsetButtonRelease(bv, x-inset_x,y-inset_y,button);
-        return;
-    }
-    no_selection = false;
+    if (!the_locking_inset)
+       return 0;
+
+    return (inset_y + the_locking_inset->InsetInInsetY());
 }
 
-void InsetTabular::InsetButtonPress(BufferView *bv, int x, int y, int)
+
+UpdatableInset * InsetTabular::GetLockingInset()
 {
-    if (hasCharSelection()) {
-       sel_pos_start = sel_pos_end = 0;
-       UpdateLocal(bv, false);
+    return the_locking_inset ? the_locking_inset->GetLockingInset() : this;
+}
+
+
+UpdatableInset * InsetTabular::GetFirstLockingInsetOfType(Inset::Code c)
+{
+    if (c == LyxCode())
+       return this;
+    if (the_locking_inset)
+       return the_locking_inset->GetFirstLockingInsetOfType(c);
+    return 0;
+}
+
+
+bool InsetTabular::InsertInset(BufferView * bv, Inset * inset)
+{
+    if (the_locking_inset)
+       return the_locking_inset->InsertInset(bv, inset);
+    return false;
+}
+
+
+void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
+{
+    if (hasSelection() && (button != 3)) {
+       clearSelection();
+       UpdateLocal(bv, SELECTION, false);
     }
     no_selection = false;
-    setPos(x,y,false);
-    if (the_locking_inset) {
-#if 0
-       UpdatableInset
-           * inset=0;
-       if (par->GetChar(actpos)==LYX_META_INSET)
-           inset=(UpdatableInset*)par->GetInset(actpos);
-       if (the_locking_inset == inset) {
-           the_locking_inset->InsetButtonPress(bv,x-inset_x,y-inset_y,button);
-           return;
-       } else if (inset) {
-           // otherwise unlock the_locking_inset and lock the new inset
-           inset_x = cx-top_x;
-           inset_y = cy;
-           inset_pos = actpos;
-           the_locking_inset->InsetUnlock(bv);
-           the_locking_inset = inset;
-           the_locking_inset->Edit(bv, x - inset_x, y - inset_y, button);
-           return;
-       }
-#endif
-       // otherwise only unlock the_locking_inset
+
+    int const ocell = actcell;
+    int const orow = actrow;
+
+    HideInsetCursor(bv);
+    setPos(bv, x, y);
+    if (actrow != orow)
+       UpdateLocal(bv, NONE, false);
+    sel_pos_start = sel_pos_end = cursor.pos();
+    sel_cell_start = sel_cell_end = actcell;
+
+    bool const inset_hit = InsetHit(bv, x, y);
+
+    if ((ocell == actcell) && the_locking_inset && inset_hit) {
+       cursor.pos(0); // always before the inset!
+       resetPos(bv);
+        the_locking_inset->InsetButtonPress(bv,
+                                           x - inset_x, y - inset_y, button);
+        return;
+    } else if (the_locking_inset) {
        the_locking_inset->InsetUnlock(bv);
     }
-#if 0
-    int
-       oldcell = actcell;
-#endif
-    setPos(x,y);
     the_locking_inset = 0;
-    sel_pos_start = sel_pos_end = actpos;
-    sel_cell_start = sel_cell_end = actcell;
-#if 0
-    if (button == 3)
-        bview->getOwner()->getPopups().showFormTable();
-    else if (oldcell != actcell)
-        bview->getOwner()->getPopups().updateFormTable();
-#endif
+    if (inset_hit && bv->theLockingInset()) {
+       if (ActivateCellInset(bv, x, y, button))
+           the_locking_inset->InsetButtonPress(bv, x - inset_x,
+                                               y - inset_y, button);
+       return;
+    }
+    ShowInsetCursor(bv);
+}
+
+
+void InsetTabular::InsetButtonRelease(BufferView * bv,
+                                     int x, int y, int button)
+{
+    if (button == 3) {
+       if (the_locking_inset) {
+           UpdatableInset * i;
+           if ((i=the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE))) {
+               i->InsetButtonRelease(bv, x, y, button);
+               return;
+           }
+       }
+       bv->owner()->getDialogs()->showTabular(this);
+       return;
+    }
+    if (the_locking_inset) {
+        the_locking_inset->InsetButtonRelease(bv, x-inset_x, y-inset_y,button);
+        return;
+    }
+    no_selection = false;
 }
 
 
 void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button)
 {
     if (the_locking_inset) {
-        the_locking_inset->InsetMotionNotify(bv, x-inset_x,y-inset_y,button);
+        the_locking_inset->InsetMotionNotify(bv, x - inset_x,
+                                            y - inset_y, button);
         return;
     }
     if (!no_selection) {
-       int
-//         oldcell = actcell,
-           old = sel_pos_end;
+       HideInsetCursor(bv);
+       LyXParagraph::size_type const old_pos = sel_pos_end;
+       int const old_cell = actcell;
 
-       setPos(x,y);
-       sel_pos_end = actpos;
+       setPos(bv, x, y);
+       sel_pos_end = cursor.pos();
        sel_cell_end = actcell;
-       if (old != sel_pos_end)
-           UpdateLocal(bv, false);
-#if 0
-       if (oldcell != actcell)
-           bview->getOwner()->getPopups().updateFormTable();
-#endif
+       if ((sel_cell_end != old_cell) || (old_pos != sel_pos_end))
+           UpdateLocal(bv, SELECTION, false);
+       ShowInsetCursor(bv);
     }
     no_selection = false;
 }
@@ -296,126 +737,237 @@ void InsetTabular::InsetKeyPress(XKeyEvent * xke)
 }
 
 
-UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView *bv, int action,
+UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
                                                   string const & arg)
 {
+    UpdatableInset::RESULT 
+        result;
+
     no_selection = false;
-    if (UpdatableInset::LocalDispatch(bv, action, arg)) {
-       resetPos();
-       return DISPATCHED;
+    if (((result=UpdatableInset::LocalDispatch(bv, action, arg)) == DISPATCHED)
+       || (result == DISPATCHED_NOUPDATE)) {
+
+       resetPos(bv);
+       return result;
     }
 
-    UpdatableInset::RESULT 
-        result=DISPATCHED;
     if ((action < 0) && arg.empty())
         return FINISHED;
 
     if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
         (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
-        old_x = -1;
+        cursor.x_fix(-1);
     if (the_locking_inset) {
         result=the_locking_inset->LocalDispatch(bv, action, arg);
-       if (result == DISPATCHED) {
-            setWidthOfCell(actpos,actcell,actrow);
+       if (result == DISPATCHED_NOUPDATE)
+           return result;
+       else if (result == DISPATCHED) {
            the_locking_inset->ToggleInsetCursor(bv);
-           UpdateLocal(bv, false);
+           UpdateLocal(bv, CELL, false);
            the_locking_inset->ToggleInsetCursor(bv);
             return result;
         } else if (result == FINISHED) {
            if ((action == LFUN_RIGHT) || (action == -1)) {
-               actpos = inset_pos + 1;
-               resetPos();
+               cursor.pos(inset_pos + 1);
+               resetPos(bv);
            }
+           sel_pos_start = sel_pos_end = cursor.pos();
+           sel_cell_start = sel_cell_end = actcell;
            the_locking_inset=0;
+           ShowInsetCursor(bv);
            result = DISPATCHED;
            return result;
        }
     }
 
+    bool hs = hasSelection();
     HideInsetCursor(bv);
+    result=DISPATCHED;
     switch (action) {
-      // Normal chars not handled here
-      case -1:
-         break;
-      // --- Cursor Movements ---------------------------------------------
-      case LFUN_RIGHTSEL:
-          moveRight(false);
-         sel_pos_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_RIGHT:
-          result= DISPATCH_RESULT(moveRight());
-         if (hasCharSelection()) {
-             sel_pos_start = sel_pos_end = actpos;
-             UpdateLocal(bv, false);
-         } else
-             sel_pos_start = sel_pos_end = actpos;
-          break;
-      case LFUN_LEFTSEL:
-          moveLeft(false);
-         sel_pos_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_LEFT:
-          result= DISPATCH_RESULT(moveLeft());
-         if (hasCharSelection()) {
-             sel_pos_start = sel_pos_end = actpos;
-             UpdateLocal(bv, false);
-         } else
-             sel_pos_start = sel_pos_end = actpos;
-          break;
-      case LFUN_DOWNSEL:
-          moveDown(false);
-         sel_pos_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_DOWN:
-          result= DISPATCH_RESULT(moveDown());
-         if (hasCharSelection()) {
-             sel_pos_start = sel_pos_end = actpos;
-             UpdateLocal(bv, false);
-         } else
-             sel_pos_start = sel_pos_end = actpos;
-          break;
-      case LFUN_UPSEL:
-          moveUp(false);
-         sel_pos_end = actpos;
-         UpdateLocal(bv, false);
-         break;
-      case LFUN_UP:
-          result= DISPATCH_RESULT(moveUp());
-         if (hasCharSelection()) {
-             sel_pos_start = sel_pos_end = actpos;
-             UpdateLocal(bv, false);
-         } else
-             sel_pos_start = sel_pos_end = actpos;
-          break;
-      case LFUN_BACKSPACE:
-         break;
-      case LFUN_DELETE:
-          break;
-      case LFUN_HOME:
-          break;
-      case LFUN_END:
-          break;
-      case LFUN_TAB:
-         if (hasCharSelection()) {
-             sel_pos_start = sel_pos_end = actpos;
-             UpdateLocal(bv, false);
-         }
-         sel_pos_start = sel_pos_end = actpos;
-          moveNextCell();
-          break;
-      default:
-          result = UNDISPATCHED;
-          break;
+       // --- Cursor Movements ---------------------------------------------
+    case LFUN_RIGHTSEL:
+       if (tabular->IsLastCellInRow(actcell) && !cellstart(cursor.pos()))
+           break;
+       moveRight(bv, false);
+#if 0
+       if (!cellstart(cursor.pos())) {
+           sel_pos_end = cursor.pos();
+           if (tabular->right_column_of_cell(sel_cell_start) >
+               tabular->right_column_of_cell(actcell))
+               sel_cell_end = actcell+1;
+           else
+               sel_cell_end = actcell;
+       }
+#else
+       sel_pos_end = cursor.pos();
+       sel_cell_end = actcell;
+#endif
+       UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_RIGHT:
+       result = moveRight(bv);
+       sel_pos_start = sel_pos_end = cursor.pos();
+       sel_cell_start = sel_cell_end = actcell;
+       if (hs)
+           UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_LEFTSEL:
+       if (tabular->IsFirstCellInRow(actcell) && cellstart(cursor.pos()))
+           break;
+       moveLeft(bv, false);
+#if 0
+       if (cellstart(cursor.pos())) {
+           sel_pos_end = cursor.pos();
+           if (tabular->column_of_cell(sel_cell_start) >=
+               tabular->column_of_cell(actcell))
+               sel_cell_end = actcell;
+           else
+               sel_cell_end = actcell-1;
+       }
+#else
+       sel_pos_end = cursor.pos();
+       sel_cell_end = actcell;
+#endif
+       UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_LEFT:
+       result = moveLeft(bv);
+       sel_pos_start = sel_pos_end = cursor.pos();
+       sel_cell_start = sel_cell_end = actcell;
+       if (hs)
+           UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_DOWNSEL:
+    {
+       int const ocell = actcell;
+       moveDown(bv);
+       sel_pos_end = cursor.pos();
+       if ((ocell == sel_cell_end) ||
+           (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
+           sel_cell_end = tabular->GetCellBelow(sel_cell_end);
+       else
+           sel_cell_end = tabular->GetLastCellBelow(sel_cell_end);
+       UpdateLocal(bv, SELECTION, false);
+    }
+    break;
+    case LFUN_DOWN:
+       result = moveDown(bv);
+       sel_pos_start = sel_pos_end = cursor.pos();
+       sel_cell_start = sel_cell_end = actcell;
+       if (hs)
+           UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_UPSEL:
+    {
+       int const ocell = actcell;
+       moveUp(bv);
+       sel_pos_end = cursor.pos();
+       if ((ocell == sel_cell_end) ||
+           (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
+           sel_cell_end = tabular->GetCellAbove(sel_cell_end);
+       else
+           sel_cell_end = tabular->GetLastCellAbove(sel_cell_end);
+       UpdateLocal(bv, SELECTION, false);
+    }
+    break;
+    case LFUN_UP:
+       result = moveUp(bv);
+       sel_pos_start = sel_pos_end = cursor.pos();
+       sel_cell_start = sel_cell_end = actcell;
+       if (hs)
+           UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_BACKSPACE:
+       break;
+    case LFUN_DELETE:
+       break;
+    case LFUN_HOME:
+       break;
+    case LFUN_END:
+       break;
+    case LFUN_SHIFT_TAB:
+    case LFUN_TAB:
+       if (the_locking_inset) {
+           UnlockInsetInInset(bv, the_locking_inset);
+           the_locking_inset = 0;
+       }
+       if (action == LFUN_TAB)
+           moveNextCell(bv);
+       else
+           movePrevCell(bv);
+       sel_pos_start = sel_pos_end = cursor.pos();
+       sel_cell_start = sel_cell_end = actcell;
+       if (hs)
+           UpdateLocal(bv, SELECTION, false);
+       break;
+    case LFUN_LAYOUT_TABULAR:
+    {
+       bv->owner()->getDialogs()->showTabular(this);
+    }
+    break;
+    case LFUN_TABULAR_FEATURE:
+       if (!TabularFeatures(bv, arg))
+           result = UNDISPATCHED;
+       break;
+    case LFUN_CUT:
+       if (!copySelection(bv))
+           break;
+       bv->text->SetUndo(bv->buffer(), Undo::DELETE,
+#ifndef NEW_INSETS
+         bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
+         bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
+#else
+         bv->text->cursor.par()->previous,
+         bv->text->cursor.par()->next
+#endif
+               );
+       cutSelection();
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LFUN_COPY:
+       if (!hasSelection())
+           break;
+       bv->text->FinishUndo();
+       copySelection(bv);
+       break;
+    case LFUN_PASTE:
+       if (!hasPasteBuffer())
+           break;
+       bv->text->SetUndo(bv->buffer(), Undo::INSERT,
+#ifndef NEW_INSETS
+         bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
+         bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
+#else
+         bv->text->cursor.par()->previous,
+         bv->text->cursor.par()->next
+#endif
+               );
+       pasteSelection(bv);
+       UpdateLocal(bv, INIT, true);
+       break;
+    default:
+       // we try to activate the actual inset and put this event down to
+       // the insets dispatch function.
+       result = UNDISPATCHED;
+       if (the_locking_inset)
+           break;
+       if (ActivateCellInset(bv, 0, 0, 0, !cellstart(cursor.pos()))) {
+           result=the_locking_inset->LocalDispatch(bv, action, arg);
+           if (result == DISPATCHED_NOUPDATE)
+               return result;
+           else if (result == DISPATCHED) {
+               the_locking_inset->ToggleInsetCursor(bv);
+               UpdateLocal(bv, CELL, false);
+               the_locking_inset->ToggleInsetCursor(bv);
+               return result;
+           } else {
+               result = UNDISPATCHED;
+           }
+       }
+       break;
     }
     if (result!=FINISHED) {
        if (!the_locking_inset) {
-#if 0      
-           if (oldcell != actcell)
-               bview->getOwner()->getPopups().updateFormTable();
-#endif
            ShowInsetCursor(bv);
        }
     } else
@@ -424,99 +976,83 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView *bv, int action,
 }
 
 
-int InsetTabular::Latex(ostream & os, bool, bool) const
+int InsetTabular::Latex(Buffer const * buf, ostream & os,
+                       bool fragile, bool fp) const
+{
+    return tabular->Latex(buf, os, fragile, fp);
+}
+
+
+int InsetTabular::Ascii(Buffer const * buf, ostream & os, int) const
 {
-    return tabular->Latex(os);
+    // This should be changed to a real ascii export
+    return tabular->Ascii(buf, os);
 }
 
-int InsetTabular::Linuxdoc(ostream &) const
+
+int InsetTabular::Linuxdoc(Buffer const *, ostream &) const
 {
     return 0;
 }
 
-int InsetTabular::DocBook(ostream &) const
+
+int InsetTabular::DocBook(Buffer const * buf, ostream & os) const
 {
-    return 0;
+    return tabular->DocBook(buf,os);
 }
 
+
 void InsetTabular::Validate(LaTeXFeatures & features) const
 {
-    if (tabular->IsLongTable())
-        features.longtable = true;
+    tabular->Validate(features);
 }
 
 
-void InsetTabular::calculate_width_of_cells(Painter & pain, LyXFont const & font) const
+bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
+                                                LyXFont const & font,
+                                                bool reinit) const
 {
-    int
-        cell=-1,
-        i,j,
-        maxAsc, maxDesc;
-    InsetText
-       *inset;
+    int cell = -1;
+    int maxAsc, maxDesc;
+    InsetText * inset;
+    bool changed = false;
     
-    for(i=0; i < tabular->rows; ++i) {
-        maxAsc = maxDesc = 0;
-        for(j=0; j < tabular->columns; ++j) {
-            if (tabular->IsPartOfMultiColumn(i,j))
-                continue;
-            ++cell;
+    // if we have a locking_inset we should have to check only this cell for
+    // change so I'll try this to have a boost, but who knows ;)
+    if ((need_update != INIT) &&
+       (the_locking_inset == tabular->GetCellInset(actcell))) {
+       maxAsc = the_locking_inset->ascent(bv, font);
+       maxDesc = the_locking_inset->descent(bv, font);
+       changed = tabular->SetWidthOfCell(actcell, the_locking_inset->width(bv, font));
+       changed = tabular->SetAscentOfRow(actrow, maxAsc + ADD_TO_HEIGHT) || changed;
+       changed = tabular->SetDescentOfRow(actrow, maxDesc + ADD_TO_HEIGHT) || changed;
+       return changed;
+    }
+    for (int i = 0; i < tabular->rows(); ++i) {
+       maxAsc = maxDesc = 0;
+       for (int j= 0; j < tabular->columns(); ++j) {
+           if (tabular->IsPartOfMultiColumn(i,j))
+               continue;
+           ++cell;
            inset = tabular->GetCellInset(cell);
-           maxAsc = max(maxAsc, inset->ascent(pain, font));
-           maxDesc = max(maxDesc, inset->descent(pain, font));
-            tabular->SetWidthOfCell(cell, inset->width(pain, font));
-        }
-        tabular->SetAscentOfRow(i,maxAsc+ADD_TO_HEIGHT);
-        tabular->SetDescentOfRow(i,maxDesc+ADD_TO_HEIGHT);
+           if (!reinit)
+               inset->update(bv, font, false);
+           maxAsc = max(maxAsc, inset->ascent(bv, font));
+           maxDesc = max(maxDesc, inset->descent(bv, font));
+           changed = tabular->SetWidthOfCell(cell, inset->width(bv, font)) || changed;
+       }
+       changed = tabular->SetAscentOfRow(i, maxAsc + ADD_TO_HEIGHT) || changed;
+       changed = tabular->SetDescentOfRow(i, maxDesc + ADD_TO_HEIGHT) || changed;
     }
+    return changed;
 }
 
 
-void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline,
-                                 int row, int cell)
-{
-    // Juergen, have you thought about drawing the on-off lines in a
-    // different color (gray of some kind), especially since those
-    // lines will not be there on the hardcopy anyway. (Lgb)
-    int
-        x_old = x;
-    bool
-        on_off;
-
-    x_old -= tabular->WidthOfColumn(cell);
-    on_off = !tabular->TopLine(cell);
-    if ((!on_off || !tabular->TopAlreadyDrawed(cell)) &&
-        !tabular->IsContRow(cell))
-        pain.line(x_old, baseline - tabular->AscentOfRow(row),
-                  x, baseline -  tabular->AscentOfRow(row),
-                  LColor::tableline,
-                  on_off ? Painter::line_onoffdash:Painter::line_solid);
-    on_off = !tabular->BottomLine(cell);
-    if ((!on_off && !tabular->RowHasContRow(cell)) || 
-        tabular->VeryLastRow(cell))
-        pain.line(x_old ,baseline +  tabular->DescentOfRow(row),
-                  x, baseline +  tabular->DescentOfRow(row),
-                  LColor::tableline,
-                  on_off ? Painter::line_onoffdash:Painter::line_solid);
-    on_off = !tabular->LeftLine(cell);
-    pain.line(x_old, baseline -  tabular->AscentOfRow(row),
-              x_old, baseline +  tabular->DescentOfRow(row),
-              LColor::tableline,
-              on_off ? Painter::line_onoffdash:Painter::line_solid);
-    on_off = !tabular->RightLine(cell);
-    pain.line(x - tabular->AdditionalWidth(cell),
-              baseline -  tabular->AscentOfRow(row),
-              x - tabular->AdditionalWidth(cell),
-              baseline +  tabular->DescentOfRow(row),
-              LColor::tableline,
-              on_off ? Painter::line_onoffdash:Painter::line_solid);
-}
-
-
-void InsetTabular::GetCursorPos(int & x, int & y)
+void InsetTabular::GetCursorPos(BufferView *,
+                               int & x, int & y) const
 {
-    x = cx-top_x;
-    y = cy;
+    x = cursor.x() - top_x;
+    y = cursor.y();
 }
 
 
@@ -526,36 +1062,30 @@ void InsetTabular::ToggleInsetCursor(BufferView * bv)
         the_locking_inset->ToggleInsetCursor(bv);
        return;
     }
-    int
-       x=0,y=0,
-        asc,desc;
 
-    LyXFont
-        font; // = the_locking_inset->GetFont(par, actpos);
+    LyXFont font; // = the_locking_inset->GetFont(par, cursor.pos);
 
-    asc = lyxfont::maxAscent(font);
-    desc = lyxfont::maxDescent(font);
+    int const asc = lyxfont::maxAscent(font);
+    int const desc = lyxfont::maxDescent(font);
   
     if (cursor_visible)
         bv->hideLockedInsetCursor();
     else
-        bv->showLockedInsetCursor(cx+x, cy+y, asc, desc);
+        bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
     cursor_visible = !cursor_visible;
 }
 
 
-void InsetTabular::ShowInsetCursor(BufferView * bv)
+void InsetTabular::ShowInsetCursor(BufferView * bv, bool show)
 {
     if (!cursor_visible) {
-       int
-           asc,desc;
-       LyXFont
-           font; // = GetFont(par, actpos);
+       LyXFont font; // = GetFont(par, cursor.pos);
     
-       asc = lyxfont::maxAscent(font);
-       desc = lyxfont::maxDescent(font);
-       bv->fitLockedInsetCursor(cx, cy, asc, desc);
-       bv->showLockedInsetCursor(cx, cy, asc, desc);
+       int const asc = lyxfont::maxAscent(font);
+       int const desc = lyxfont::maxDescent(font);
+       bv->fitLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
+       if (show)
+           bv->showLockedInsetCursor(cursor.x(), cursor.y(), asc, desc);
        cursor_visible = true;
     }
 }
@@ -563,402 +1093,993 @@ void InsetTabular::ShowInsetCursor(BufferView * bv)
 
 void InsetTabular::HideInsetCursor(BufferView * bv)
 {
-    if (cursor_visible)
-        ToggleInsetCursor(bv);
+    if (cursor_visible) {
+        bv->hideLockedInsetCursor();
+       cursor_visible = false;
+    }
+//    if (cursor_visible)
+//        ToggleInsetCursor(bv);
 }
 
 
-void InsetTabular::setPos(int, int, bool)
+void InsetTabular::setPos(BufferView * bv, int x, int y) const
 {
+    cursor.y(0);
+    cursor.pos(0);
+       
+    actcell = actrow = actcol = 0;
+    int ly = tabular->GetDescentOfRow(actrow);
+
+    // first search the right row
+    while((ly < y) && (actrow < tabular->rows())) {
+        cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
+           tabular->GetAscentOfRow(actrow + 1) +
+            tabular->GetAdditionalHeight(tabular->GetCellNumber(actrow + 1,
+                                                               actcol)));
+        ++actrow;
+        ly = cursor.y() + tabular->GetDescentOfRow(actrow);
+    }
+    actcell = tabular->GetCellNumber(actrow, actcol);
+
+    // now search the right column
+    int lx = tabular->GetWidthOfColumn(actcell) -
+       tabular->GetAdditionalWidth(actcell);
+#if 0
+#warning Jürgen, can you rewrite this to _not_ use the sequencing operator. (Lgb)
+    for (; !tabular->IsLastCellInRow(actcell) && (lx < x);
+       ++actcell,lx += tabular->GetWidthOfColumn(actcell) +
+           tabular->GetAdditionalWidth(actcell - 1));
+#else
+    // Jürgen, you should check that this is correct. (Lgb)
+    for (; !tabular->IsLastCellInRow(actcell) && lx < x; ++actcell) {
+           lx += tabular->GetWidthOfColumn(actcell + 1)
+                   + tabular->GetAdditionalWidth(actcell);
+    }
+    
+#endif
+    cursor.pos(0);
+    resetPos(bv);
+    if ((lx - (tabular->GetWidthOfColumn(actcell) / 2)) < x) {
+       cursor.x(lx + top_x - 2);
+       cursor.pos(1);
+    } else {
+       cursor.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
+    }
+    resetPos(bv);
 }
 
-void InsetTabular::setWidthOfCell(int, int, int)
+
+int InsetTabular::getCellXPos(int cell) const
 {
+    int c = cell;
+
+    for (; !tabular->IsFirstCellInRow(c); --c)
+       ;
+    int lx = tabular->GetWidthOfColumn(cell);
+    for (; c < cell; ++c) {
+       lx += tabular->GetWidthOfColumn(c);
+    }
+    return (lx - tabular->GetWidthOfColumn(cell) + top_x);
 }
 
-bool InsetTabular::moveRight(bool)
+
+void InsetTabular::resetPos(BufferView * bv) const
 {
-    return false;
+    if (!locked)
+       return;
+    actcol = tabular->column_of_cell(actcell);
+
+    int cell = 0;
+    actrow = 0;
+    cursor.y(0);
+    for (; (cell < actcell) && !tabular->IsLastRow(cell); ++cell) {
+       if (tabular->IsLastCellInRow(cell)) {
+           cursor.y(cursor.y() + tabular->GetDescentOfRow(actrow) +
+               tabular->GetAscentOfRow(actrow + 1) +
+               tabular->GetAdditionalHeight(cell + 1));
+           ++actrow;
+       }
+    }
+    static int const offset = ADD_TO_TABULAR_WIDTH + 2;
+    int new_x = getCellXPos(actcell);
+    new_x += offset;
+    cursor.x(new_x);
+//    cursor.x(getCellXPos(actcell) + offset);
+    if (((cursor.x() - offset) > 20) &&
+       ((cursor.x()-offset+tabular->GetWidthOfColumn(actcell)) >
+        (bv->workWidth()-20)))
+    {
+       scroll(bv, -tabular->GetWidthOfColumn(actcell)-20);
+       UpdateLocal(bv, FULL, false);
+    } else if ((cursor.x() - offset) < 20) {
+       scroll(bv, 20 - cursor.x() + offset);
+       UpdateLocal(bv, FULL, false);
+    } else if (!cellstart(cursor.pos())) {
+       LyXFont font(LyXFont::ALL_SANE);
+       cursor.x(cursor.x() + tabular->GetCellInset(actcell)->width(bv,font) +
+               tabular->GetBeginningOfTextInCell(actcell));
+    }
+    if ((!the_locking_inset ||
+        !the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE)) &&
+       (actcell != oldcell)) {
+           InsetTabular * inset = const_cast<InsetTabular *>(this);
+           bv->owner()->getDialogs()->updateTabular(inset);
+           oldcell = actcell;
+    }
 }
 
-bool InsetTabular::moveLeft(bool)
+
+UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
 {
-    return false;
+    if (!cellstart(cursor.pos())) {
+       if (tabular->IsLastCell(actcell))
+           return FINISHED;
+       ++actcell;
+       cursor.pos(0);
+    } else if (lock) {
+       if (ActivateCellInset(bv))
+           return DISPATCHED;
+    } else {              // before the inset
+       cursor.pos(1);
+    }
+    resetPos(bv);
+    return DISPATCHED_NOUPDATE;
 }
 
-bool InsetTabular::moveUp(bool)
+
+UpdatableInset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
 {
-    return false;
+    if (cellstart(cursor.pos()) && !actcell)
+       return FINISHED;
+    if (cellstart(cursor.pos())) {
+       --actcell;
+       cursor.pos(1);
+    } else if (lock) {       // behind the inset
+       cursor.pos(0);
+       if (ActivateCellInset(bv, 0, 0, 0, true))
+           return DISPATCHED;
+    } else {
+       cursor.pos(0);
+    }
+    resetPos(bv);
+    return DISPATCHED_NOUPDATE;
 }
 
-bool InsetTabular::moveDown(bool)
+
+UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv)
 {
-    return false;
+    int const ocell = actcell;
+    actcell = tabular->GetCellAbove(actcell);
+    if (actcell == ocell) // we moved out of the inset
+       return FINISHED;
+    resetPos(bv);
+    return DISPATCHED_NOUPDATE;
 }
 
-bool InsetTabular::moveNextCell()
+
+UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv)
 {
-    return false;
+    int const ocell = actcell;
+    actcell = tabular->GetCellBelow(actcell);
+    if (actcell == ocell) // we moved out of the inset
+       return FINISHED;
+    resetPos(bv);
+    return DISPATCHED_NOUPDATE;
 }
 
-bool InsetTabular::movePrevCell()
+
+bool InsetTabular::moveNextCell(BufferView * bv)
 {
-    return false;
+    if (tabular->IsLastCell(actcell))
+       return false;
+    ++actcell;
+    resetPos(bv);
+    return true;
 }
 
-void InsetTabular::resetPos()
+
+bool InsetTabular::movePrevCell(BufferView * bv)
 {
+    if (!actcell) // first cell
+       return false;
+    --actcell;
+    resetPos(bv);
+    return true;
 }
 
+
 bool InsetTabular::Delete()
 {
     return true;
 }
 
-void  InsetTabular::SetFont(LyXFont const &)
+
+void InsetTabular::SetFont(BufferView * bv, LyXFont const & font, bool tall)
 {
+    if (the_locking_inset)
+       the_locking_inset->SetFont(bv, font, tall);
 }
 
-void InsetTabular::TableFeatures(int, string)
+
+bool InsetTabular::TabularFeatures(BufferView * bv, string const & what)
 {
-#if 0
-    int
-       i,
-       selection_start,
-       selection_end,
-        setLines = 0,
-        setAlign = LYX_ALIGN_LEFT,
-        lineSet;
-    bool
-        what;
+    LyXTabular::Feature action = LyXTabular::LAST_ACTION;
+
+    int i = 0;
+    for (; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
+       string const tmp = tabularFeatures[i].feature;
+           
+       if (tmp == what.substr(0, tmp.length())) {
+       //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
+             //tabularFeatures[i].feature.length())) {
+           action = tabularFeatures[i].action;
+           break;
+       }
+    }
+    if (action == LyXTabular::LAST_ACTION)
+       return false;
+
+    string const val =
+           frontStrip(what.substr(tabularFeatures[i].feature.length()));
+    TabularFeatures(bv, action, val);
+    return true;
+}
+
+
+void InsetTabular::TabularFeatures(BufferView * bv,
+                                  LyXTabular::Feature feature,
+                                  string const & value)
+{
+    int i;
+    int j;
+    int sel_col_start;
+    int sel_col_end;
+    int sel_row_start;
+    int sel_row_end;
+    int setLines = 0;
+    LyXAlignment setAlign = LYX_ALIGN_LEFT;
+    LyXTabular::VAlignment setVAlign = LyXTabular::LYX_VALIGN_TOP;
+    int lineSet;
+    bool what;
 
     switch (feature) {
-      case LyXTable::ALIGN_LEFT:
+      case LyXTabular::M_ALIGN_LEFT:
+      case LyXTabular::ALIGN_LEFT:
           setAlign=LYX_ALIGN_LEFT;
           break;
-      case LyXTable::ALIGN_RIGHT:
+      case LyXTabular::M_ALIGN_RIGHT:
+      case LyXTabular::ALIGN_RIGHT:
           setAlign=LYX_ALIGN_RIGHT;
           break;
-      case LyXTable::ALIGN_CENTER:
+      case LyXTabular::M_ALIGN_CENTER:
+      case LyXTabular::ALIGN_CENTER:
           setAlign=LYX_ALIGN_CENTER;
           break;
+      case LyXTabular::M_VALIGN_TOP:
+      case LyXTabular::VALIGN_TOP:
+          setVAlign=LyXTabular::LYX_VALIGN_TOP;
+          break;
+      case LyXTabular::M_VALIGN_BOTTOM:
+      case LyXTabular::VALIGN_BOTTOM:
+          setVAlign=LyXTabular::LYX_VALIGN_BOTTOM;
+          break;
+      case LyXTabular::M_VALIGN_CENTER:
+      case LyXTabular::VALIGN_CENTER:
+          setVAlign=LyXTabular::LYX_VALIGN_CENTER;
+          break;
       default:
           break;
     }
-    if (hasCellSelection()) {
-       if (sel_cell_start > sel_cell_end) {
-           selection_start = sel_cell_end;
-           selection_end = sel_cell_start;
+    if (hasSelection()) {
+       sel_col_start = tabular->column_of_cell(sel_cell_start);
+       sel_col_end = tabular->column_of_cell(sel_cell_end);
+       if (sel_col_start > sel_col_end) {
+           sel_col_end = sel_col_start;
+           sel_col_start = tabular->column_of_cell(sel_cell_end);
        } else {
-           selection_start = sel_cell_start;
-           selection_end = sel_cell_end;
+           sel_col_end = tabular->right_column_of_cell(sel_cell_end);
        }
-    } else
-       selection_start = selection_end = actcell;
+       
+       sel_row_start = tabular->row_of_cell(sel_cell_start);
+       sel_row_end = tabular->row_of_cell(sel_cell_end);
+       if (sel_row_start > sel_row_end) {
+               //int tmp = sel_row_start;
+               //sel_row_start = sel_row_end;
+               //sel_row_end = tmp;
+           swap(sel_row_start, sel_row_end);
+       }
+    } else {
+       sel_col_start = sel_col_end = tabular->column_of_cell(actcell);
+       sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
+    }
+    bv->text->SetUndo(bv->buffer(), Undo::FINISH,
+#ifndef NEW_INSETS
+             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->previous,
+             bv->text->cursor.par()->ParFromPos(bv->text->cursor.pos())->next
+#else
+             bv->text->cursor.par()->previous,
+             bv->text->cursor.par()->next
+#endif
+           );
+
+    int row = tabular->row_of_cell(actcell);
+    int column = tabular->column_of_cell(actcell);
+    bool flag = true;
+    
     switch (feature) {
-      case LyXTable::SET_PWIDTH:
-          tabular->SetPWidth(actcell,val);
-          break;
-      case LyXTable::SET_SPECIAL_COLUMN:
-      case LyXTable::SET_SPECIAL_MULTI:
-          tabular->SetAlignSpecial(actcell,val,feature);
-          break;
-      case LyXTable::APPEND_ROW:
-      {
-         int
-              pos = actpos,
-              cell_org = actcell,
-              cell = actcell;
-
-          // if there is a ContRow following this row I have to add
-          // the row after the ContRow's
-          if ((pos < par->last()) && tabular->RowHasContRow(cell_org)) {
-              while((pos < par->last()) && !tabular->IsContRow(cell)) {
-                  while (pos < par->last() && !par->IsNewline(pos))
-                      ++pos;
-                  if (pos < par->last())
-                      ++pos;
-                  ++cell;
-              }
-              while((pos < par->last()) && tabular->IsContRow(cell)) {
-                  while (pos < par->last() && !par->IsNewline(pos))
-                      ++pos;
-                  if (pos < par->last())
-                      ++pos;
-                  ++cell;
-              }
-              cell_org = --cell;
-              if (pos < par->last())
-                  --pos;
-          }
-          while ((pos < par->last()) && 
-                 ((cell == cell_org) || !tabular->IsFirstCell(cell))) {
-              while ((pos < par->last()) && !par->IsNewline(pos))
-                  ++pos;
-              if (pos < par->last())
-                  ++pos;
-              ++cell;
-          }
-          // insert the new cells
-          int number = tabular->NumberOfCellsInRow(cell_org);
-          for (i=0; i<number; ++i)
-              par->InsertChar(pos, LYX_META_NEWLINE);
-               
-          // append the row into the table
-          tabular->AppendRow(cell_org);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      }
-      case LyXTable::APPEND_CONT_ROW:
-      {
-         int
-              pos = actpos,
-              cell_org = actcell,
-              cell = actcell;
-
-          // if there is already a controw but not for this cell
-          // the AppendContRow sets only the right values but does
-          // not actually add a row
-          if (tabular->RowHasContRow(cell_org) &&
-              (tabular->CellHasContRow(cell_org) < 0)) {
-              tabular->AppendContRow(cell_org);
-              calculate_width_of_cells();
-              UpdateLocal();
-              return;
-          }
-          while ((pos < par->last()) &&
-                 ((cell == cell_org) || !tabular->IsFirstCell(cell))) {
-              while (pos < par->last() && !par->IsNewline(pos))
-                  ++pos;
-              if (pos < par->last())
-                  ++pos;
-              ++cell;
-          }
-          // insert the new cells
-          int number = tabular->NumberOfCellsInRow(cell_org);
-          for (i=0; i<number; ++i)
-              par->InsertChar(pos, LYX_META_NEWLINE);
-          // append the row into the table
-          tabular->AppendContRow(cell_org);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      }
-      case LyXTable::APPEND_COLUMN:
-      { 
-         int
-              pos = 0,
-              cell_org = actcell,
-              cell = 0;
-          do {
-              if (pos && (par->IsNewline(pos-1))) {
-                  if (tabular->AppendCellAfterCell(cell_org, cell)) {
-                      par->InsertChar(pos, LYX_META_NEWLINE);
-                      if (pos <= actpos)
-                          ++actpos;
-                      ++pos;
-                  }
-                  ++cell;
-              }
-              ++pos;
-          } while (pos <= par->last());
-          // remember that the very last cell doesn't end with a newline.
-          // This saves one byte memory per table ;-)
-          if (tabular->AppendCellAfterCell(cell_org, cell))
-              par->InsertChar(par->last(), LYX_META_NEWLINE);
-          // append the column into the table
-          tabular->AppendColumn(cell_org);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      }
-      case LyXTable::DELETE_ROW:
-          RemoveTableRow();
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      case LyXTable::DELETE_COLUMN:
-      {
-          int pos = 0;
-          int cell = 0;
-          do {
-              if (!pos || (par->IsNewline(pos-1))){
-                  if (tabular->DeleteCellIfColumnIsDeleted(cell, actcell)) {
-                      // delete one cell
-                      while (pos < par->last() && !par->IsNewline(pos))
-                          par->Erase(pos);
-                      if (pos < par->last())
-                          par->Erase(pos);
-                      else 
-                          par->Erase(pos - 1); // the missing newline
-                                               // at the end of a table
-                      --pos; // because of ++pos below
-                  }
-                  ++cell;
-              }
-              ++pos;
-          } while (pos <= par->last());
-          /* delete the column from the table */ 
-          tabular->DeleteColumn(actcell);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      }
-      case LyXTable::TOGGLE_LINE_TOP:
-          lineSet = !tabular->TopLine(actcell);
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetTopLine(i,lineSet);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
+    case LyXTabular::SET_PWIDTH:
+    {
+       bool const update = (tabular->GetColumnPWidth(actcell) != value);
+       tabular->SetColumnPWidth(actcell,value);
+       if (update) {
+           for (int i=0; i < tabular->rows(); ++i) {
+               tabular->GetCellInset(tabular->GetCellNumber(i, column))->
+                   resizeLyXText(bv);
+           }
+           UpdateLocal(bv, INIT, true);
+       }
+    }
+    break;
+    case LyXTabular::SET_MPWIDTH:
+    {
+       bool const update = (tabular->GetPWidth(actcell) != value);
+       tabular->SetMColumnPWidth(actcell,value);
+       if (update) {
+           for (int i=0; i < tabular->rows(); ++i) {
+               tabular->GetCellInset(tabular->GetCellNumber(i, column))->
+                   resizeLyXText(bv);
+           }
+           UpdateLocal(bv, INIT, true);
+       }
+    }
+    break;
+    case LyXTabular::SET_SPECIAL_COLUMN:
+    case LyXTabular::SET_SPECIAL_MULTI:
+       tabular->SetAlignSpecial(actcell,value,feature);
+       break;
+    case LyXTabular::APPEND_ROW:
+       // append the row into the tabular
+       UnlockInsetInInset(bv, the_locking_inset);
+       tabular->AppendRow(actcell);
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::APPEND_COLUMN:
+       // append the column into the tabular
+       tabular->AppendColumn(actcell);
+       actcell = tabular->GetCellNumber(row, column);
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::DELETE_ROW:
+       tabular->DeleteRow(tabular->row_of_cell(actcell));
+       if ((row+1) > tabular->rows())
+           --row;
+       actcell = tabular->GetCellNumber(row, column);
+       clearSelection();
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::DELETE_COLUMN:
+       tabular->DeleteColumn(tabular->column_of_cell(actcell));
+       if ((column+1) > tabular->columns())
+           --column;
+       actcell = tabular->GetCellNumber(row, column);
+       clearSelection();
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::M_TOGGLE_LINE_TOP:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_TOP:
+       lineSet = !tabular->TopLine(actcell, flag);
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetTopLine(tabular->GetCellNumber(i,j),lineSet, flag);
+       UpdateLocal(bv, INIT, true);
+       break;
     
-      case LyXTable::TOGGLE_LINE_BOTTOM:
-          lineSet = !tabular->BottomLine(actcell); 
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetBottomLine(i,lineSet);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
+    case LyXTabular::M_TOGGLE_LINE_BOTTOM:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_BOTTOM:
+       lineSet = !tabular->BottomLine(actcell, flag); 
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetBottomLine(tabular->GetCellNumber(i,j),lineSet,
+                                      flag);
+       UpdateLocal(bv, INIT, true);
+       break;
                
-      case LyXTable::TOGGLE_LINE_LEFT:
-          lineSet = !tabular->LeftLine(actcell);
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetLeftLine(i,lineSet);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-
-      case LyXTable::TOGGLE_LINE_RIGHT:
-          lineSet = !tabular->RightLine(actcell);
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetRightLine(i,lineSet);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      case LyXTable::ALIGN_LEFT:
-      case LyXTable::ALIGN_RIGHT:
-      case LyXTable::ALIGN_CENTER:
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetAlignment(i,setAlign);
-          UpdateLocal();
-          return;
-      case LyXTable::MULTICOLUMN:
-      {
-         if (tabular->row_of_cell(selection_start) !=
-             tabular->row_of_cell(selection_end)) {
-             WriteAlert(_("Impossible Operation!"), 
-                        _("Multicolumns can only be horizontally."), 
-                        _("Sorry."));
-             return;
-         }
-         // just multicol for one Single Cell
-         if (!hasCellSelection()) {
-             // check wether we are completly in a multicol
-             if (tabular->IsMultiColumn(actcell)) {
-                 int
-                     newlines,
-                     pos = actpos;
-                 if ((newlines=tabular->UnsetMultiColumn(actcell))) {
-                     while ((pos < par->last()) && !par->IsNewline(pos))
-                         ++pos;
-                     for (;newlines;--newlines)
-                         par->InsertChar(pos, LYX_META_NEWLINE);
-                 }
-                 calculate_width_of_cells();
-             } else {
-                 tabular->SetMultiColumn(actcell, 1);
-             }
-             UpdateLocal();
-             return;
-         }
-         // we have a selection so this means we just add all this
-         // cells to form a multicolumn cell
-         int
-             number = 1,
-             s_start, s_end;
-
-         if (sel_pos_start > sel_pos_end) {
-             s_start = sel_pos_end;
-             s_end = sel_pos_start;
-         } else {
-             s_start = sel_pos_start;
-             s_end = sel_pos_end;
-         }
-         for(i=s_start; i < s_end; ++i) {
-             if (par->IsNewline(i)) {
-                 par->Erase(i);
-                 // check for double-blanks
-                 if ((i && !par->IsLineSeparator(i-1)) &&
-                     (i < par->last()) && !par->IsLineSeparator(i))
-                     par->InsertChar(i, ' ');
-                 else
-                     --i;
-                 ++number;
-             }
-         }
-         tabular->SetMultiColumn(selection_start,number);
-         actpos = s_start;
-         sel_cell_end = sel_cell_start;
-         calculate_width_of_cells();
-         UpdateLocal();
-          return;
-      }
-      case LyXTable::SET_ALL_LINES:
-          setLines = 1;
-      case LyXTable::UNSET_ALL_LINES:
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetAllLines(i, setLines);
-          calculate_width_of_cells();
-          UpdateLocal();
-          return;
-      case LyXTable::SET_LONGTABLE:
-          tabular->SetLongTable(true);
-         UpdateLocal(); // because this toggles displayed
-          return;
-      case LyXTable::UNSET_LONGTABLE:
-          tabular->SetLongTable(false);
-         UpdateLocal(); // because this toggles displayed
-          return;
-      case LyXTable::SET_ROTATE_TABLE:
-          tabular->SetRotateTable(true);
-          return;
-      case LyXTable::UNSET_ROTATE_TABLE:
-          tabular->SetRotateTable(false);
-          return;
-      case LyXTable::SET_ROTATE_CELL:
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetRotateCell(i,true);
-          return;
-      case LyXTable::UNSET_ROTATE_CELL:
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetRotateCell(i,false);
-          return;
-      case LyXTable::SET_LINEBREAKS:
-          what = !tabular->Linebreaks(tabular->FirstVirtualCell(actcell));
-         for(i=selection_start; i<=selection_end; ++i)
-             tabular->SetLinebreaks(i,what);
-          return;
-      case LyXTable::SET_LTFIRSTHEAD:
-          tabular->SetLTHead(actcell,true);
-          return;
-      case LyXTable::SET_LTHEAD:
-          tabular->SetLTHead(actcell,false);
-          return;
-      case LyXTable::SET_LTFOOT:
-          tabular->SetLTFoot(actcell,false);
-          return;
-      case LyXTable::SET_LTLASTFOOT:
-          tabular->SetLTFoot(actcell,true);
-          return;
-      case LyXTable::SET_LTNEWPAGE:
-          what = !tabular->LTNewPage(actcell);
-          tabular->SetLTNewPage(actcell,what);
-          return;
+    case LyXTabular::M_TOGGLE_LINE_LEFT:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_LEFT:
+       lineSet = !tabular->LeftLine(actcell, flag);
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetLeftLine(tabular->GetCellNumber(i,j),lineSet,
+                                    flag);
+       UpdateLocal(bv, INIT, true);
+       break;
+
+    case LyXTabular::M_TOGGLE_LINE_RIGHT:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_RIGHT:
+       lineSet = !tabular->RightLine(actcell, flag);
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetRightLine(tabular->GetCellNumber(i,j),lineSet,
+                                     flag);
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::M_ALIGN_LEFT:
+    case LyXTabular::M_ALIGN_RIGHT:
+    case LyXTabular::M_ALIGN_CENTER:
+       flag = false;
+    case LyXTabular::ALIGN_LEFT:
+    case LyXTabular::ALIGN_RIGHT:
+    case LyXTabular::ALIGN_CENTER:
+       for (i = sel_row_start; i <= sel_row_end; ++i)
+           for (j = sel_col_start; j <= sel_col_end; ++j)
+               tabular->SetAlignment(tabular->GetCellNumber(i, j), setAlign,
+                                     flag);
+       if (hasSelection())
+           UpdateLocal(bv, INIT, true);
+       else
+           UpdateLocal(bv, CELL, true);
+       break;
+    case LyXTabular::M_VALIGN_TOP:
+    case LyXTabular::M_VALIGN_BOTTOM:
+    case LyXTabular::M_VALIGN_CENTER:
+       flag = false;
+    case LyXTabular::VALIGN_TOP:
+    case LyXTabular::VALIGN_BOTTOM:
+    case LyXTabular::VALIGN_CENTER:
+       for (i = sel_row_start; i <= sel_row_end; ++i)
+           for (j = sel_col_start; j <= sel_col_end; ++j)
+               tabular->SetVAlignment(tabular->GetCellNumber(i, j),
+                                      setVAlign, flag);
+       if (hasSelection())
+           UpdateLocal(bv, INIT, true);
+       else
+           UpdateLocal(bv, CELL, true);
+       break;
+    case LyXTabular::MULTICOLUMN:
+    {
+       if (sel_row_start != sel_row_end) {
+           WriteAlert(_("Impossible Operation!"), 
+                      _("Multicolumns can only be horizontally."), 
+                      _("Sorry."));
+           return;
+       }
+       // just multicol for one Single Cell
+       if (!hasSelection()) {
+           // check wether we are completly in a multicol
+           if (tabular->IsMultiColumn(actcell)) {
+               tabular->UnsetMultiColumn(actcell);
+               UpdateLocal(bv, INIT, true);
+           } else {
+               tabular->SetMultiColumn(actcell, 1);
+               UpdateLocal(bv, CELL, true);
+           }
+           return;
+       }
+       // we have a selection so this means we just add all this
+       // cells to form a multicolumn cell
+       int s_start;
+       int s_end;
+
+       if (sel_cell_start > sel_cell_end) {
+           s_start = sel_cell_end;
+           s_end = sel_cell_start;
+       } else {
+           s_start = sel_cell_start;
+           s_end = sel_cell_end;
+       }
+       tabular->SetMultiColumn(s_start, s_end - s_start + 1);
+       actcell = s_start;
+       cursor.pos(0);
+       sel_cell_end = sel_cell_start;
+       sel_pos_end = sel_pos_start;
+       UpdateLocal(bv, INIT, true);
+       break;
     }
-#endif
+    case LyXTabular::SET_ALL_LINES:
+       setLines = 1;
+    case LyXTabular::UNSET_ALL_LINES:
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetAllLines(tabular->GetCellNumber(i,j), setLines);
+       UpdateLocal(bv, INIT, true);
+       break;
+    case LyXTabular::SET_LONGTABULAR:
+       tabular->SetLongTabular(true);
+       UpdateLocal(bv, INIT, true); // because this toggles displayed
+       break;
+    case LyXTabular::UNSET_LONGTABULAR:
+       tabular->SetLongTabular(false);
+       UpdateLocal(bv, INIT, true); // because this toggles displayed
+       break;
+    case LyXTabular::SET_ROTATE_TABULAR:
+       tabular->SetRotateTabular(true);
+       break;
+    case LyXTabular::UNSET_ROTATE_TABULAR:
+       tabular->SetRotateTabular(false);
+       break;
+    case LyXTabular::SET_ROTATE_CELL:
+       for (i=sel_row_start; i<=sel_row_end; ++i)
+           for (j=sel_col_start; j<=sel_col_end; ++j)
+               tabular->SetRotateCell(tabular->GetCellNumber(i,j),true);
+       break;
+    case LyXTabular::UNSET_ROTATE_CELL:
+       for (i = sel_row_start; i <= sel_row_end; ++i)
+           for (j = sel_col_start; j <= sel_col_end; ++j)
+               tabular->SetRotateCell(tabular->GetCellNumber(i, j), false);
+       break;
+    case LyXTabular::SET_USEBOX:
+    {
+       LyXTabular::BoxType val = LyXTabular::BoxType(strToInt(value));
+       if (val == tabular->GetUsebox(actcell))
+           val = LyXTabular::BOX_NONE;
+       for (i = sel_row_start; i <= sel_row_end; ++i)
+           for (j = sel_col_start; j <= sel_col_end; ++j)
+               tabular->SetUsebox(tabular->GetCellNumber(i, j), val);
+       break;
+    }
+    case LyXTabular::SET_LTFIRSTHEAD:
+       tabular->SetLTHead(actcell, true);
+       break;
+    case LyXTabular::SET_LTHEAD:
+       tabular->SetLTHead(actcell, false);
+       break;
+    case LyXTabular::SET_LTFOOT:
+       tabular->SetLTFoot(actcell, false);
+       break;
+    case LyXTabular::SET_LTLASTFOOT:
+       tabular->SetLTFoot(actcell, true);
+       break;
+    case LyXTabular::SET_LTNEWPAGE:
+       what = !tabular->GetLTNewPage(actcell);
+       tabular->SetLTNewPage(actcell, what);
+       break;
+    // dummy stuff just to avoid warnings
+    case LyXTabular::LAST_ACTION:
+       break;
+    }
+}
+
+
+bool InsetTabular::ActivateCellInset(BufferView * bv, int x, int y, int button,
+                                    bool behind)
+{
+    // the cursor.pos has to be before the inset so if it isn't now just
+    // reset the curor pos first!
+    if (!cellstart(cursor.pos())) {
+       cursor.pos(0);
+       resetPos(bv);
+    }
+    UpdatableInset * inset =
+       static_cast<UpdatableInset*>(tabular->GetCellInset(actcell));
+    LyXFont font(LyXFont::ALL_SANE);
+    if (behind) {
+       x = inset->x() + inset->width(bv, font);
+       y = inset->descent(bv, font);
+    }
+    inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+    inset_y = cursor.y();
+    inset->Edit(bv, x - inset_x, y - inset_y, button);
+    if (!the_locking_inset)
+       return false;
+    UpdateLocal(bv, CELL, false);
+    return (the_locking_inset != 0);
+}
+
+
+bool InsetTabular::InsetHit(BufferView * bv, int x, int ) const
+{
+    InsetText * inset = tabular->GetCellInset(actcell);
+    int const x1 = x + top_x;
+
+    if (!cellstart(cursor.pos())) {
+       return ((x + top_x) < cursor.x() &&
+               (x + top_x) > (cursor.x() - inset->width(bv,
+                                                     LyXFont(LyXFont::ALL_SANE))));
+    } else {
+       int const x2 = cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
+       return (x1 > x2 &&
+               x1 < (x2 + inset->width(bv, LyXFont(LyXFont::ALL_SANE))));
+    }
+}
+
+
+// This returns paperWidth() if the cell-width is unlimited or the width
+// in pixels if we have a pwidth for this cell.
+int InsetTabular::GetMaxWidthOfCell(Painter &, int cell) const
+{
+    string const s = tabular->GetPWidth(cell);
+
+    if (s.empty())
+       return -1;
+    return VSpace(s).inPixels(0, 0);
+}
+
+
+int InsetTabular::getMaxWidth(Painter & pain,
+                             UpdatableInset const * inset) const
+{
+    int const n = tabular->GetNumberOfCells();
+    int cell = 0;
+    for (; cell < n; ++cell) {
+       if (tabular->GetCellInset(cell) == inset)
+           break;
+    }
+    if (cell >= n)
+       return -1;
+    int w = GetMaxWidthOfCell(pain, cell);
+    if (w > 0)
+       // because the inset then subtracts it's top_x and owner->x()
+       w += (inset->x() - top_x);
+    return w;
+}
+
+
+void InsetTabular::resizeLyXText(BufferView *) const
+{
+    need_update = FULL;
+}
+
+
+LyXText * InsetTabular::getLyXText(BufferView * bv) const
+{
+    if (the_locking_inset)
+       return the_locking_inset->getLyXText(bv);
+    return Inset::getLyXText(bv);
 }
 
-void InsetTabular::RemoveTableRow()
+
+void InsetTabular::OpenLayoutDialog(BufferView * bv) const
 {
+    if (the_locking_inset) {
+       InsetTabular * i = static_cast<InsetTabular *>
+           (the_locking_inset->GetFirstLockingInsetOfType(TABULAR_CODE));
+       if (i) {
+           i->OpenLayoutDialog(bv);
+           return;
+       }
+    }
+    bv->owner()->getDialogs()->showTabular(const_cast<InsetTabular *>(this));
 }
+
+//
+// functions returns:
+// 0 ... disabled
+// 1 ... enabled
+// 2 ... toggled on
+// 3 ... toggled off
+//
+LyXFunc::func_status InsetTabular::getStatus(string const & what) const
+{
+    int action = LyXTabular::LAST_ACTION;
+    LyXFunc::func_status status = LyXFunc::OK;
+    
+    int i = 0;
+    for (; tabularFeatures[i].action != LyXTabular::LAST_ACTION; ++i) {
+       string const tmp = tabularFeatures[i].feature;
+       if (tmp == what.substr(0, tmp.length())) {                  
+       //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
+       //   tabularFeatures[i].feature.length())) {
+           action = tabularFeatures[i].action;
+           break;
+       }
+    }
+    if (action == LyXTabular::LAST_ACTION)
+       return LyXFunc::Unknown;
+
+    string const argument = frontStrip(what.substr(tabularFeatures[i].feature.length()));
+
+    int sel_row_start, sel_row_end;
+    int dummy;
+    bool flag = true;
+
+    if (hasSelection()) {
+       sel_row_start = tabular->row_of_cell(sel_cell_start);
+       sel_row_end = tabular->row_of_cell(sel_cell_end);
+       if (sel_row_start > sel_row_end) {
+               //int tmp = sel_row_start;
+               //sel_row_start = sel_row_end;
+               //sel_row_end = tmp;
+           swap(sel_row_start, sel_row_end);
+       }
+    } else {
+       sel_row_start = sel_row_end = tabular->row_of_cell(actcell);
+    }
+
+    switch (action) {
+    case LyXTabular::SET_PWIDTH:
+    case LyXTabular::SET_MPWIDTH:
+    case LyXTabular::SET_SPECIAL_COLUMN:
+    case LyXTabular::SET_SPECIAL_MULTI:
+       status |= LyXFunc::Disabled;
+       return status;
+
+    case LyXTabular::APPEND_ROW:
+    case LyXTabular::APPEND_COLUMN:
+    case LyXTabular::DELETE_ROW:
+    case LyXTabular::DELETE_COLUMN:
+    case LyXTabular::SET_ALL_LINES:
+    case LyXTabular::UNSET_ALL_LINES:
+       status |= LyXFunc::OK;
+       return status;
+
+    case LyXTabular::MULTICOLUMN:
+       if (tabular->IsMultiColumn(actcell))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_TOGGLE_LINE_TOP:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_TOP:
+       if (tabular->TopLine(actcell, flag))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_TOGGLE_LINE_BOTTOM:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_BOTTOM:
+       if (tabular->BottomLine(actcell, flag))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_TOGGLE_LINE_LEFT:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_LEFT:
+       if (tabular->LeftLine(actcell, flag))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_TOGGLE_LINE_RIGHT:
+       flag = false;
+    case LyXTabular::TOGGLE_LINE_RIGHT:
+       if (tabular->RightLine(actcell, flag))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_ALIGN_LEFT:
+       flag = false;
+    case LyXTabular::ALIGN_LEFT:
+       if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_LEFT)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_ALIGN_RIGHT:
+       flag = false;
+    case LyXTabular::ALIGN_RIGHT:
+       if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_RIGHT)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_ALIGN_CENTER:
+       flag = false;
+    case LyXTabular::ALIGN_CENTER:
+       if (tabular->GetAlignment(actcell, flag) == LYX_ALIGN_CENTER)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_VALIGN_TOP:
+       flag = false;
+    case LyXTabular::VALIGN_TOP:
+       if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_TOP)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_VALIGN_BOTTOM:
+       flag = false;
+    case LyXTabular::VALIGN_BOTTOM:
+       if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_BOTTOM)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::M_VALIGN_CENTER:
+       flag = false;
+    case LyXTabular::VALIGN_CENTER:
+       if (tabular->GetVAlignment(actcell, flag) == LyXTabular::LYX_VALIGN_CENTER)
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LONGTABULAR:
+       if (tabular->IsLongTabular())
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::UNSET_LONGTABULAR:
+       if (!tabular->IsLongTabular())
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_ROTATE_TABULAR:
+       if (tabular->GetRotateTabular())
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::UNSET_ROTATE_TABULAR:
+       if (!tabular->GetRotateTabular())
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_ROTATE_CELL:
+       if (tabular->GetRotateCell(actcell))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::UNSET_ROTATE_CELL:
+       if (!tabular->GetRotateCell(actcell))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_USEBOX:
+       if (strToInt(argument) == tabular->GetUsebox(actcell))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LTFIRSTHEAD:
+       if (tabular->GetRowOfLTHead(actcell, dummy))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LTHEAD:
+       if (tabular->GetRowOfLTHead(actcell, dummy))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LTFOOT:
+       if (tabular->GetRowOfLTFoot(actcell, dummy))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LTLASTFOOT:
+       if (tabular->GetRowOfLTFoot(actcell, dummy))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    case LyXTabular::SET_LTNEWPAGE:
+       if (tabular->GetLTNewPage(actcell))
+           status |= LyXFunc::ToggleOn;
+       else
+           status |= LyXFunc::ToggleOff;
+       break;
+    default:
+       status = LyXFunc::Disabled;
+       break;
+    }
+    return status;
+}
+
+
+bool InsetTabular::copySelection(BufferView * bv)
+{
+    if (!hasSelection())
+       return false;
+    delete paste_tabular;
+
+    int sel_col_start, sel_col_end;
+    int sel_row_start, sel_row_end;
+
+    sel_col_start = tabular->column_of_cell(sel_cell_start);
+    sel_col_end = tabular->column_of_cell(sel_cell_end);
+    if (sel_col_start > sel_col_end) {
+       sel_col_start = sel_col_end;
+       sel_col_end = tabular->right_column_of_cell(sel_cell_start);
+    } else {
+       sel_col_end = tabular->right_column_of_cell(sel_cell_end);
+    }
+    int columns = sel_col_end - sel_col_start + 1;
+
+    sel_row_start = tabular->row_of_cell(sel_cell_start);
+    sel_row_end = tabular->row_of_cell(sel_cell_end);
+    if (sel_row_start > sel_row_end) {
+           //int tmp tmp = sel_row_start;
+           //sel_row_start = sel_row_end;
+           //sel_row_end = tmp;
+       swap(sel_row_start, sel_row_end);
+    }
+    int rows = sel_row_end - sel_row_start + 1;
+
+    paste_tabular = new LyXTabular(this, *tabular); // rows, columns);
+    int i;
+    for (i=0; i < sel_row_start; ++i)
+       paste_tabular->DeleteRow(0);
+    while(paste_tabular->rows() > rows)
+       paste_tabular->DeleteRow(rows);
+    paste_tabular->SetTopLine(0, true, true);
+    paste_tabular->SetBottomLine(paste_tabular->GetFirstCellInRow(rows-1),
+                                true, true);
+    for (i=0; i < sel_col_start; ++i)
+       paste_tabular->DeleteColumn(0);
+    while(paste_tabular->columns() > columns)
+       paste_tabular->DeleteColumn(columns);
+    paste_tabular->SetLeftLine(0, true, true);
+    paste_tabular->SetRightLine(paste_tabular->GetLastCellInRow(0),true, true);
+
+    ostringstream sstr;
+    paste_tabular->Ascii(bv->buffer(), sstr);
+    bv->stuffClipboard(sstr.str().c_str());
+    return true;
+}
+
+
+bool InsetTabular::pasteSelection(BufferView * bv)
+{
+    if (!paste_tabular)
+       return false;
+    for (int j=0, i=actcell; j<paste_tabular->GetNumberOfCells(); ++j,++i) {
+       while (paste_tabular->row_of_cell(j) > tabular->row_of_cell(i)-actrow)
+           ++i;
+       if (tabular->GetNumberOfCells() <= i)
+           break;
+       while (paste_tabular->row_of_cell(j) < tabular->row_of_cell(i)-actrow)
+           ++j;
+       if (paste_tabular->GetNumberOfCells() <= j)
+           break;
+       *(tabular->GetCellInset(i)) = *(paste_tabular->GetCellInset(j));
+       tabular->GetCellInset(i)->setOwner(this);
+       tabular->GetCellInset(i)->deleteLyXText(bv);
+    }
+    return true;
+}
+
+
+bool InsetTabular::cutSelection()
+{
+    if (!hasSelection())
+       return false;
+
+    int sel_col_start, sel_col_end;
+    int sel_row_start, sel_row_end;
+
+    sel_col_start = tabular->column_of_cell(sel_cell_start);
+    sel_col_end = tabular->column_of_cell(sel_cell_end);
+    if (sel_col_start > sel_col_end) {
+       sel_col_start = sel_col_end;
+       sel_col_end = tabular->right_column_of_cell(sel_cell_start);
+    } else {
+       sel_col_end = tabular->right_column_of_cell(sel_cell_end);
+    }
+    sel_row_start = tabular->row_of_cell(sel_cell_start);
+    sel_row_end = tabular->row_of_cell(sel_cell_end);
+    if (sel_row_start > sel_row_end) {
+           //int tmp = sel_row_start;
+           //sel_row_start = sel_row_end;
+           //sel_row_end = tmp;
+       swap(sel_row_start, sel_row_end);
+    }
+    if (sel_cell_start > sel_cell_end) {
+           //int tmp = sel_cell_start;
+           //sel_cell_start = sel_cell_end;
+           //sel_cell_end = tmp;
+       swap(sel_cell_start, sel_cell_end);
+    }
+    for (int i = sel_row_start; i <= sel_row_end; ++i) {
+       for (int j = sel_col_start; j <= sel_col_end; ++j) {
+           tabular->GetCellInset(tabular->GetCellNumber(i, j))->clear();
+       }
+    }
+    return true;
+}
+