]> git.lyx.org Git - lyx.git/blobdiff - src/insets/insettabular.C
updates to minipage inset
[lyx.git] / src / insets / insettabular.C
index 8e052f9eec167d9a49e90105d401c958921de3b0..e77fbe3bfeb07eb9bfaad0422326c3c8b4496898 100644 (file)
@@ -35,6 +35,7 @@
 #include "frontends/Dialogs.h"
 #include "debug.h"
 #include "lyxfunc.h"
+#include "WorkArea.h"
 
 const int ADD_TO_HEIGHT = 2;
 const int ADD_TO_TABULAR_WIDTH = 2;
@@ -50,6 +51,7 @@ using std::ifstream;
 using std::max;
 using std::endl;
 using std::swap;
+using std::max;
 
     
 struct tabular_features {
@@ -107,14 +109,6 @@ static tabular_features tabularFeatures[] =
     { 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)
 {
@@ -127,12 +121,11 @@ InsetTabular::InsetTabular(Buffer const & buf, int rows, int columns)
     // just for test!!!
     the_locking_inset = 0;
     locked = no_selection = cursor_visible = false;
-    cursor.x_fix(-1);
     oldcell = -1;
     actrow = actcell = 0;
-    cursor.pos(0);
     clearSelection();
     need_update = INIT;
+    no_draw = false;
 }
 
 
@@ -142,12 +135,11 @@ InsetTabular::InsetTabular(InsetTabular const & tab, Buffer const & buf)
     tabular = new LyXTabular(this, *(tab.tabular));
     the_locking_inset = 0;
     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;
+    sel_cell_start = sel_cell_end = 0;
     need_update = INIT;
+    no_draw = false;
 }
 
 
@@ -222,10 +214,13 @@ int InsetTabular::width(BufferView *, LyXFont const &) const
 void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
                        float & x, bool cleared) const
 {
+    if (no_draw)
+       return;
+
     Painter & pain = bv->painter();
-    int i, j;
+    int i;
+    int j;
     int nx;
-    float cx;
 
     UpdatableInset::draw(bv, font, baseline, x, cleared);
     if (!cleared && ((need_update == INIT) || (need_update == FULL) ||
@@ -253,6 +248,8 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
     x += ADD_TO_TABULAR_WIDTH;
     if (cleared) {
        int cell = 0;
+       float cx;
+       first_visible_cell = -1;
        for (i = 0; i < tabular->rows(); ++i) {
            nx = int(x);
            dodraw = ((baseline + tabular->GetDescentOfRow(i)) > 0) &&
@@ -262,6 +259,8 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
                    continue;
                cx = nx + tabular->GetBeginningOfTextInCell(cell);
                if (dodraw) {
+                   if (first_visible_cell < 0)
+                       first_visible_cell = cell;
                    if (hasSelection())
                        DrawCellSelection(pain, nx, baseline, i, j, cell);
                    tabular->GetCellInset(cell)->draw(bv, font, baseline, cx,
@@ -319,34 +318,13 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
            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);
+       float dx;
+       float cx;
+       cx = dx = nx + tabular->GetBeginningOfTextInCell(cell);
+       tabular->GetCellInset(cell)->draw(bv,font,baseline, dx, false);
+       if (bv->text->status == LyXText::CHANGED_IN_DRAW)
+           return;
+       // clear only if we didn't have a change
        if (need_update == CELL) {
            // clear before the inset
            pain.fillRectangle(
@@ -366,10 +344,6 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
                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);
@@ -383,7 +357,7 @@ void InsetTabular::draw(BufferView * bv, LyXFont const & font, int baseline,
 void InsetTabular::DrawCellLines(Painter & pain, int x, int baseline,
                                  int row, int cell) const
 {
-    int  x2 = x + tabular->GetWidthOfColumn(cell);
+    int x2 = x + tabular->GetWidthOfColumn(cell);
     bool on_off;
 
     if (!tabular->TopAlreadyDrawed(cell)) {
@@ -487,15 +461,13 @@ void InsetTabular::Edit(BufferView * bv, int x, int y, unsigned int button)
     }
     locked = true;
     the_locking_inset = 0;
-    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->text->FinishUndo();
-    if (InsetHit(bv, x, y)) {
-       ActivateCellInset(bv, x, y, button);
+    if (InsetHit(bv, x, y) && (button != 3)) {
+       ActivateCellInsetAbs(bv, x, y, button);
     }
 //    UpdateLocal(bv, NONE, false);
 //    bv->getOwner()->getPopups().updateFormTabular();
@@ -513,11 +485,9 @@ void InsetTabular::InsetUnlock(BufferView * bv)
     oldcell = -1;
     locked = false;
     if (scroll() || hasSelection()) {
+       sel_cell_start = sel_cell_end = 0;
        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);
     }
@@ -529,6 +499,8 @@ void InsetTabular::UpdateLocal(BufferView * bv, UpdateCodes what,
 {
     if (need_update < what) // only set this if it has greater update
        need_update = what;
+    if ((what == INIT) && hasSelection())
+       clearSelection();
     // Dirty Cast! (Lgb)
     if (need_update != NONE) {
        bv->updateInset(const_cast<InsetTabular *>(this), mark_dirty);
@@ -550,17 +522,12 @@ bool InsetTabular::LockInsetInInset(BufferView * bv, UpdatableInset * inset)
        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;
-       }
+       lyxerr[Debug::INSETS] << "OK" << endl;
+       resetPos(bv);
+       inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+       inset_y = cursor.y();
     } else if (the_locking_inset) {
        lyxerr[Debug::INSETS] << "MAYBE" << endl;
        return the_locking_inset->LockInsetInInset(bv, inset);
@@ -578,10 +545,8 @@ bool InsetTabular::UnlockInsetInInset(BufferView * bv, UpdatableInset * inset,
     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);
+       ShowInsetCursor(bv, false);
         return true;
     }
     if (the_locking_inset->UnlockInsetInInset(bv, inset, lr)) {
@@ -645,10 +610,14 @@ bool InsetTabular::InsertInset(BufferView * bv, Inset * inset)
 
 void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
 {
-    if (hasSelection() && (button != 3)) {
+    if (hasSelection() && (button == 3))
+       return;
+
+    if (hasSelection()) {
        clearSelection();
        UpdateLocal(bv, SELECTION, false);
     }
+
     no_selection = false;
 
     int const ocell = actcell;
@@ -658,13 +627,19 @@ void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
     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;
+    if (button == 3) {
+       if ((ocell != actcell) && the_locking_inset) {
+           the_locking_inset->InsetUnlock(bv);
+           the_locking_inset = 0;
+       }
+       ShowInsetCursor(bv);
+       return;
+    }
 
     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);
@@ -673,8 +648,12 @@ void InsetTabular::InsetButtonPress(BufferView * bv, int x, int y, int button)
        the_locking_inset->InsetUnlock(bv);
     }
     the_locking_inset = 0;
+    if (button == 2) {
+       LocalDispatch(bv, LFUN_PASTESELECTION, "paragraph");
+       return;
+    }
     if (inset_hit && bv->theLockingInset()) {
-       if (ActivateCellInset(bv, x, y, button))
+       if (ActivateCellInsetAbs(bv, x, y, button))
            the_locking_inset->InsetButtonPress(bv, x - inset_x,
                                                y - inset_y, button);
        return;
@@ -714,13 +693,11 @@ void InsetTabular::InsetMotionNotify(BufferView * bv, int x, int y, int button)
     }
     if (!no_selection) {
        HideInsetCursor(bv);
-       LyXParagraph::size_type const old_pos = sel_pos_end;
        int const old_cell = actcell;
 
        setPos(bv, x, y);
-       sel_pos_end = cursor.pos();
        sel_cell_end = actcell;
-       if ((sel_cell_end != old_cell) || (old_pos != sel_pos_end))
+       if (sel_cell_end != old_cell)
            UpdateLocal(bv, SELECTION, false);
        ShowInsetCursor(bv);
     }
@@ -737,16 +714,17 @@ void InsetTabular::InsetKeyPress(XKeyEvent * xke)
 }
 
 
-UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
+UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv,
+                                                  kb_action action,
                                                   string const & arg)
 {
-    UpdatableInset::RESULT 
-        result;
-
+    // We need to save the value of the_locking_inset as the call to 
+    // the_locking_inset->LocalDispatch might unlock it.
+    old_locking_inset = the_locking_inset;
     no_selection = false;
-    if (((result=UpdatableInset::LocalDispatch(bv, action, arg)) == DISPATCHED)
-       || (result == DISPATCHED_NOUPDATE)) {
-
+    UpdatableInset::RESULT result =
+           UpdatableInset::LocalDispatch(bv, action, arg);
+    if (result == DISPATCHED || result == DISPATCHED_NOUPDATE) {
        resetPos(bv);
        return result;
     }
@@ -754,29 +732,23 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     if ((action < 0) && arg.empty())
         return FINISHED;
 
-    if ((action != LFUN_DOWN) && (action != LFUN_UP) &&
-        (action != LFUN_DOWNSEL) && (action != LFUN_UPSEL))
-        cursor.x_fix(-1);
     if (the_locking_inset) {
         result=the_locking_inset->LocalDispatch(bv, action, arg);
-       if (result == DISPATCHED_NOUPDATE)
+       if (result == DISPATCHED_NOUPDATE) {
+           int sc = scroll();
+           resetPos(bv);
+           if (sc != scroll()) { // inset has been scrolled
+               the_locking_inset->ToggleInsetCursor(bv);
+               UpdateLocal(bv, FULL, false);
+               the_locking_inset->ToggleInsetCursor(bv);
+           }
            return result;
-       else if (result == DISPATCHED) {
+       else if (result == DISPATCHED) {
            the_locking_inset->ToggleInsetCursor(bv);
            UpdateLocal(bv, CELL, false);
            the_locking_inset->ToggleInsetCursor(bv);
             return result;
         } else if (result == FINISHED) {
-           if ((action == LFUN_RIGHT) || (action == -1)) {
-               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;
        }
     }
 
@@ -786,53 +758,27 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     switch (action) {
        // --- Cursor Movements ---------------------------------------------
     case LFUN_RIGHTSEL:
-       if (tabular->IsLastCellInRow(actcell) && !cellstart(cursor.pos()))
+       if (tabular->IsLastCellInRow(actcell))
            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()))
+       if (tabular->IsFirstCellInRow(actcell))
            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);
@@ -840,8 +786,7 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     case LFUN_DOWNSEL:
     {
        int const ocell = actcell;
-       moveDown(bv);
-       sel_pos_end = cursor.pos();
+       moveDown(bv, false);
        if ((ocell == sel_cell_end) ||
            (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
            sel_cell_end = tabular->GetCellBelow(sel_cell_end);
@@ -851,8 +796,7 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     }
     break;
     case LFUN_DOWN:
-       result = moveDown(bv);
-       sel_pos_start = sel_pos_end = cursor.pos();
+       result = moveDown(bv, old_locking_inset != 0);
        sel_cell_start = sel_cell_end = actcell;
        if (hs)
            UpdateLocal(bv, SELECTION, false);
@@ -860,8 +804,7 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     case LFUN_UPSEL:
     {
        int const ocell = actcell;
-       moveUp(bv);
-       sel_pos_end = cursor.pos();
+       moveUp(bv, false);
        if ((ocell == sel_cell_end) ||
            (tabular->column_of_cell(ocell)>tabular->column_of_cell(actcell)))
            sel_cell_end = tabular->GetCellAbove(sel_cell_end);
@@ -871,12 +814,50 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
     }
     break;
     case LFUN_UP:
-       result = moveUp(bv);
-       sel_pos_start = sel_pos_end = cursor.pos();
+       result = moveUp(bv, old_locking_inset != 0);
        sel_cell_start = sel_cell_end = actcell;
        if (hs)
            UpdateLocal(bv, SELECTION, false);
        break;
+    case LFUN_NEXT: {
+       int column = actcol;
+       if (the_locking_inset) {
+           UnlockInsetInInset(bv, the_locking_inset);
+           the_locking_inset = 0;
+       }
+       if (bv->text->first + bv->painter().paperHeight() <
+           (top_baseline + tabular->GetHeightOfTabular()))
+       {
+           bv->scrollCB(bv->text->first + bv->painter().paperHeight());
+           UpdateLocal(bv, FULL, false);
+           actcell = tabular->GetCellBelow(first_visible_cell) + column;
+       } else {
+           actcell = tabular->GetFirstCellInRow(tabular->rows() - 1) + column;
+       }
+       resetPos(bv);
+       UpdateLocal(bv, CURSOR, false);
+       break;
+    }
+    case LFUN_PRIOR: {
+       int column = actcol;
+       if (the_locking_inset) {
+           UnlockInsetInInset(bv, the_locking_inset);
+           the_locking_inset = 0;
+       }
+       if (top_baseline < 0) {
+           bv->scrollCB(bv->text->first - bv->painter().paperHeight());
+           UpdateLocal(bv, FULL, false);
+           if (top_baseline > 0)
+               actcell = column;
+           else
+               actcell = tabular->GetCellBelow(first_visible_cell) + column;
+       } else {
+           actcell = column;
+       }
+       resetPos(bv);
+       UpdateLocal(bv, CURSOR, false);
+       break;
+    }
     case LFUN_BACKSPACE:
        break;
     case LFUN_DELETE:
@@ -887,19 +868,20 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
        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);
+           moveNextCell(bv, old_locking_inset != 0);
        else
-           movePrevCell(bv);
-       sel_pos_start = sel_pos_end = cursor.pos();
+           movePrevCell(bv, old_locking_inset != 0);
        sel_cell_start = sel_cell_end = actcell;
        if (hs)
            UpdateLocal(bv, SELECTION, false);
        break;
+    }
     case LFUN_LAYOUT_TABULAR:
     {
        bv->owner()->getDialogs()->showTabular(this);
@@ -914,11 +896,11 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
            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
+         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
+         bv->text->cursor.par()->previous(),
+         bv->text->cursor.par()->next()
 #endif
                );
        cutSelection();
@@ -930,39 +912,109 @@ UpdatableInset::RESULT InsetTabular::LocalDispatch(BufferView * bv, int action,
        bv->text->FinishUndo();
        copySelection(bv);
        break;
-    case LFUN_PASTE:
-       if (!hasPasteBuffer())
+    case LFUN_PASTESELECTION:
+    {
+       string clip(bv->workarea()->getClipboard());
+       
+       if (clip.empty())
            break;
-       bv->text->SetUndo(bv->buffer(), Undo::INSERT,
+       if (clip.find('\t') != string::npos) {
+           int cols = 1;
+           int rows = 1;
+           int maxCols = 1;
+           unsigned int len = clip.length();
+           string::size_type p = 0;
+
+           while((p < len) &&
+                 ((p = clip.find_first_of("\t\n", p)) != string::npos))
+           {
+               switch(clip[p]) {
+               case '\t':
+                   ++cols;
+                   break;
+               case '\n':
+                   if ((p+1) < len)
+                       ++rows;
+                   maxCols = max(cols, maxCols);
+                   cols = 1;
+                   break;
+               }
+               ++p;
+           }
+           maxCols = max(cols, maxCols);
+           delete paste_tabular;
+           paste_tabular = new LyXTabular(this, rows, maxCols);
+           string::size_type op = 0;
+           int cell = 0;
+           int cells = paste_tabular->GetNumberOfCells();
+           p = cols = 0;
+           while((cell < cells) && (p < len) &&
+                 (p = clip.find_first_of("\t\n", p)) != string::npos)
+           {
+               if (p >= len)
+                   break;
+               switch(clip[p]) {
+               case '\t':
+                   paste_tabular->GetCellInset(cell)->SetText(clip.substr(op, p-op));
+                   ++cols;
+                   ++cell;
+                   break;
+               case '\n':
+                   paste_tabular->GetCellInset(cell)->SetText(clip.substr(op, p-op));
+                   while(cols++ < maxCols)
+                       ++cell;
+                   cols = 0;
+                   break;
+               }
+               ++p;
+               op = p;
+           }
+           // check for the last cell if there is no trailing '\n'
+           if ((cell < cells) && (op < len))
+               paste_tabular->GetCellInset(cell)->SetText(clip.substr(op, len-op));
+       } else {
+           // so that the clipboard is used and it goes on to default
+           // and executes LFUN_PASTESELECTION in insettext!
+           delete paste_tabular;
+           paste_tabular = 0;
+       }
+    }
+    case LFUN_PASTE:
+       if (hasPasteBuffer()) {
+           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
+             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
+             bv->text->cursor.par()->previous(),
+             bv->text->cursor.par()->next()
 #endif
                );
-       pasteSelection(bv);
-       UpdateLocal(bv, INIT, true);
-       break;
+           pasteSelection(bv);
+           UpdateLocal(bv, INIT, true);
+           break;
+       }
+    // ATTENTION: the function above has to be PASTE and PASTESELECTION!!!
     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()))) {
+       no_draw = true;
+       if (ActivateCellInset(bv)) {
            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;
+           if ((result == UNDISPATCHED) || (result == FINISHED)) {
+               UnlockInsetInInset(bv, the_locking_inset);
+               no_draw = false;
+               the_locking_inset = 0;
+               return UNDISPATCHED;
            }
+           no_draw = false;
+           the_locking_inset->ToggleInsetCursor(bv);
+           UpdateLocal(bv, CELL, false);
+           the_locking_inset->ToggleInsetCursor(bv);
+           return result;
        }
        break;
     }
@@ -1013,7 +1065,8 @@ bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
                                                 bool reinit) const
 {
     int cell = -1;
-    int maxAsc, maxDesc;
+    int maxAsc = 0;
+    int maxDesc = 0;
     InsetText * inset;
     bool changed = false;
     
@@ -1021,15 +1074,20 @@ bool InsetTabular::calculate_dimensions_of_cells(BufferView * bv,
     // 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);
+       for(int i = 0; i < tabular->columns(); ++i) {
+           maxAsc = max(tabular->GetCellInset(actrow, i)->ascent(bv, font),
+                        maxAsc);
+           maxDesc = max(tabular->GetCellInset(actrow, i)->descent(bv, font),
+                         maxDesc);
+       }
        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;
+       maxAsc = 0;
+       maxDesc = 0;
        for (int j= 0; j < tabular->columns(); ++j) {
            if (tabular->IsPartOfMultiColumn(i,j))
                continue;
@@ -1105,7 +1163,6 @@ void InsetTabular::HideInsetCursor(BufferView * bv)
 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);
@@ -1124,8 +1181,8 @@ void InsetTabular::setPos(BufferView * bv, int x, int y) const
     // now search the right column
     int lx = tabular->GetWidthOfColumn(actcell) -
        tabular->GetAdditionalWidth(actcell);
-#warning Jürgen, can you rewrite this to _not_ use the sequencing operator. (Lgb)
 #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));
@@ -1137,14 +1194,7 @@ void InsetTabular::setPos(BufferView * bv, int x, int y) const
     }
     
 #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);
-    }
+    cursor.x(lx - tabular->GetWidthOfColumn(actcell) + top_x + 2);
     resetPos(bv);
 }
 
@@ -1182,45 +1232,59 @@ void InsetTabular::resetPos(BufferView * bv) const
     }
     static int const offset = ADD_TO_TABULAR_WIDTH + 2;
     int new_x = getCellXPos(actcell);
+    int old_x = cursor.x();
     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)))
+    if (scroll() && (tabular->GetWidthOfTabular() < bv->workWidth()-20))
+       scroll(bv, 0.0F);
+    else if (the_locking_inset &&
+            (tabular->GetWidthOfColumn(actcell) > bv->workWidth()-20))
+    {
+           int xx = cursor.x() - offset + bv->text->GetRealCursorX(bv);
+           if (xx > (bv->workWidth()-20))
+               scroll(bv, -(xx - bv->workWidth() + 60));
+           else if (xx < 20) {
+               if (xx < 0)
+                   xx = -xx + 60;
+               else
+                   xx = 60;
+               scroll(bv, xx);
+           }
+    } else 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));
+    } else if (scroll() && (top_x > 20) &&
+              ((top_x+tabular->GetWidthOfTabular()) > (bv->workWidth()-20))) {
+       scroll(bv, old_x - cursor.x());
     }
     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;
+       InsetTabular * inset = const_cast<InsetTabular *>(this);
+       bv->owner()->getDialogs()->updateTabular(inset);
+       oldcell = actcell;
     }
 }
 
 
 UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
 {
-    if (!cellstart(cursor.pos())) {
-       if (tabular->IsLastCell(actcell))
-           return FINISHED;
-       ++actcell;
-       cursor.pos(0);
-    } else if (lock) {
+    if (lock && !old_locking_inset) {
        if (ActivateCellInset(bv))
            return DISPATCHED;
-    } else {              // before the inset
-       cursor.pos(1);
+    } else {
+       bool moved = isRightToLeft(bv) ? movePrevCell(bv) : moveNextCell(bv);
+       if (!moved)
+           return FINISHED;
+       if (lock && ActivateCellInset(bv))
+           return DISPATCHED;
     }
     resetPos(bv);
     return DISPATCHED_NOUPDATE;
@@ -1229,60 +1293,113 @@ UpdatableInset::RESULT InsetTabular::moveRight(BufferView * bv, bool lock)
 
 UpdatableInset::RESULT InsetTabular::moveLeft(BufferView * bv, bool lock)
 {
-    if (cellstart(cursor.pos()) && !actcell)
+    bool moved = isRightToLeft(bv) ? moveNextCell(bv) : movePrevCell(bv);
+    if (!moved)
        return FINISHED;
-    if (cellstart(cursor.pos())) {
-       --actcell;
-       cursor.pos(1);
-    } else if (lock) {       // behind the inset
-       cursor.pos(0);
+    if (lock) {       // behind the inset
        if (ActivateCellInset(bv, 0, 0, 0, true))
            return DISPATCHED;
-    } else {
-       cursor.pos(0);
     }
     resetPos(bv);
     return DISPATCHED_NOUPDATE;
 }
 
 
-UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv)
+UpdatableInset::RESULT InsetTabular::moveUp(BufferView * bv, bool lock)
 {
     int const ocell = actcell;
     actcell = tabular->GetCellAbove(actcell);
     if (actcell == ocell) // we moved out of the inset
        return FINISHED;
     resetPos(bv);
+   if (lock) {
+       int x = 0;
+       int y = 0;
+       if (old_locking_inset) {
+           old_locking_inset->GetCursorPos(bv, x, y);
+           x -= cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
+       }
+       if (ActivateCellInset(bv, x, 0))
+           return DISPATCHED;
+    }
     return DISPATCHED_NOUPDATE;
 }
 
 
-UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv)
+UpdatableInset::RESULT InsetTabular::moveDown(BufferView * bv, bool lock)
 {
     int const ocell = actcell;
     actcell = tabular->GetCellBelow(actcell);
     if (actcell == ocell) // we moved out of the inset
        return FINISHED;
     resetPos(bv);
+    if (lock) {
+       int x = 0;
+       int y = 0;
+       if (old_locking_inset) {
+           old_locking_inset->GetCursorPos(bv, x, y);
+           x -= cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
+       }
+       if (ActivateCellInset(bv, x, 0))
+           return DISPATCHED;
+    }
     return DISPATCHED_NOUPDATE;
 }
 
 
-bool InsetTabular::moveNextCell(BufferView * bv)
+bool InsetTabular::moveNextCell(BufferView * bv, bool lock)
 {
-    if (tabular->IsLastCell(actcell))
-       return false;
-    ++actcell;
+    if (isRightToLeft(bv)) {
+       if (tabular->IsFirstCellInRow(actcell)) {
+           int row = tabular->row_of_cell(actcell);
+           if (row == tabular->rows() - 1)
+               return false;
+           actcell = tabular->GetLastCellInRow(row);
+           actcell = tabular->GetCellBelow(actcell);
+       } else {
+           if (!actcell)
+               return false;
+           --actcell;
+       }
+    } else {
+       if (tabular->IsLastCell(actcell))
+           return false;
+       ++actcell;
+    }
+    if (lock) {
+       bool rtl = tabular->GetCellInset(actcell)->par->
+               isRightToLeftPar(bv->buffer()->params);
+       ActivateCellInset(bv, 0, 0, 0, !rtl);
+    }
     resetPos(bv);
     return true;
 }
 
 
-bool InsetTabular::movePrevCell(BufferView * bv)
+bool InsetTabular::movePrevCell(BufferView * bv, bool lock)
 {
-    if (!actcell) // first cell
-       return false;
-    --actcell;
+    if (isRightToLeft(bv)) {
+       if (tabular->IsLastCellInRow(actcell)) {
+           int row = tabular->row_of_cell(actcell);
+           if (row == 0)
+               return false;
+           actcell = tabular->GetFirstCellInRow(row);
+           actcell = tabular->GetCellAbove(actcell);
+       } else {
+           if (tabular->IsLastCell(actcell))
+               return false;
+           ++actcell;
+       }
+    } else {
+       if (!actcell) // first cell
+           return false;
+       --actcell;
+    }
+    if (lock) {
+       bool rtl = tabular->GetCellInset(actcell)->par->
+               isRightToLeftPar(bv->buffer()->params);
+       ActivateCellInset(bv, 0, 0, 0, !rtl);
+    }
     resetPos(bv);
     return true;
 }
@@ -1310,7 +1427,7 @@ bool InsetTabular::TabularFeatures(BufferView * bv, string const & what)
        string const tmp = tabularFeatures[i].feature;
            
        if (tmp == what.substr(0, tmp.length())) {
-       //if (!strncmp(tabularFeatures[i].feature.c_str(), what.c_str(),
+       //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
              //tabularFeatures[i].feature.length())) {
            action = tabularFeatures[i].action;
            break;
@@ -1394,11 +1511,11 @@ void InsetTabular::TabularFeatures(BufferView * bv,
     }
     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
+             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
+             bv->text->cursor.par()->previous(),
+             bv->text->cursor.par()->next()
 #endif
            );
 
@@ -1445,11 +1562,13 @@ void InsetTabular::TabularFeatures(BufferView * bv,
        break;
     case LyXTabular::APPEND_COLUMN:
        // append the column into the tabular
+       UnlockInsetInInset(bv, the_locking_inset);
        tabular->AppendColumn(actcell);
        actcell = tabular->GetCellNumber(row, column);
        UpdateLocal(bv, INIT, true);
        break;
     case LyXTabular::DELETE_ROW:
+       UnlockInsetInInset(bv, the_locking_inset);
        tabular->DeleteRow(tabular->row_of_cell(actcell));
        if ((row+1) > tabular->rows())
            --row;
@@ -1458,6 +1577,7 @@ void InsetTabular::TabularFeatures(BufferView * bv,
        UpdateLocal(bv, INIT, true);
        break;
     case LyXTabular::DELETE_COLUMN:
+       UnlockInsetInInset(bv, the_locking_inset);
        tabular->DeleteColumn(tabular->column_of_cell(actcell));
        if ((column+1) > tabular->columns())
            --column;
@@ -1518,10 +1638,7 @@ void InsetTabular::TabularFeatures(BufferView * bv,
            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);
+       UpdateLocal(bv, INIT, true);
        break;
     case LyXTabular::M_VALIGN_TOP:
     case LyXTabular::M_VALIGN_BOTTOM:
@@ -1534,10 +1651,7 @@ void InsetTabular::TabularFeatures(BufferView * bv,
            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);
+       UpdateLocal(bv, INIT, true);
        break;
     case LyXTabular::MULTICOLUMN:
     {
@@ -1573,9 +1687,7 @@ void InsetTabular::TabularFeatures(BufferView * bv,
        }
        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;
     }
@@ -1647,12 +1759,6 @@ void InsetTabular::TabularFeatures(BufferView * bv,
 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);
@@ -1660,9 +1766,9 @@ bool InsetTabular::ActivateCellInset(BufferView * bv, int x, int y, int button,
        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);
+    //inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+    //inset_y = cursor.y();
+    inset->Edit(bv, x,  y, button);
     if (!the_locking_inset)
        return false;
     UpdateLocal(bv, CELL, false);
@@ -1670,20 +1776,18 @@ bool InsetTabular::ActivateCellInset(BufferView * bv, int x, int y, int button,
 }
 
 
-bool InsetTabular::InsetHit(BufferView * bv, int x, int ) const
+bool InsetTabular::ActivateCellInsetAbs(BufferView * bv, int x, int y,
+                                       int button)
 {
-    InsetText * inset = tabular->GetCellInset(actcell);
-    int const x1 = x + top_x;
+       inset_x = cursor.x() - top_x + tabular->GetBeginningOfTextInCell(actcell);
+       inset_y = cursor.y();
+       return ActivateCellInset(bv, x - inset_x, y - inset_y, button);
+}
 
-    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))));
-    }
+
+bool InsetTabular::InsetHit(BufferView *, int x, int) const
+{
+    return x + top_x > cursor.x() + tabular->GetBeginningOfTextInCell(actcell);
 }
 
 
@@ -1724,11 +1828,11 @@ void InsetTabular::resizeLyXText(BufferView *) const
 }
 
 
-LyXText * InsetTabular::getLyXText(BufferView * bv) const
+LyXText * InsetTabular::getLyXText(BufferView const * bv, bool const recursive) const
 {
     if (the_locking_inset)
-       return the_locking_inset->getLyXText(bv);
-    return Inset::getLyXText(bv);
+       return the_locking_inset->getLyXText(bv, recursive);
+    return Inset::getLyXText(bv, recursive);
 }
 
 
@@ -1761,7 +1865,7 @@ LyXFunc::func_status InsetTabular::getStatus(string const & what) const
     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(),
+       //if (!compare(tabularFeatures[i].feature.c_str(), what.c_str(),
        //   tabularFeatures[i].feature.length())) {
            action = tabularFeatures[i].action;
            break;
@@ -1772,7 +1876,8 @@ LyXFunc::func_status InsetTabular::getStatus(string const & what) const
 
     string const argument = frontStrip(what.substr(tabularFeatures[i].feature.length()));
 
-    int sel_row_start, sel_row_end;
+    int sel_row_start;
+    int sel_row_end;
     int dummy;
     bool flag = true;
 
@@ -1978,8 +2083,10 @@ bool InsetTabular::copySelection(BufferView * bv)
        return false;
     delete paste_tabular;
 
-    int sel_col_start, sel_col_end;
-    int sel_row_start, sel_row_end;
+    int sel_col_start;
+    int sel_col_end;
+    int sel_row_start;
+    int sel_row_end;
 
     sel_col_start = tabular->column_of_cell(sel_cell_start);
     sel_col_end = tabular->column_of_cell(sel_cell_end);
@@ -2028,18 +2135,32 @@ 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);
+
+    for (int r1 = 0, r2 = actrow;
+        (r1 < paste_tabular->rows()) && (r2 < tabular->rows());
+        ++r1, ++r2)
+    {
+       for(int c1 = 0, c2 = actcol;
+           (c1 < paste_tabular->columns()) && (c2 < tabular->columns());
+           ++c1, ++c2)
+       {
+           if (paste_tabular->IsPartOfMultiColumn(r1,c1) &&
+               tabular->IsPartOfMultiColumn(r2,c2))
+               continue;
+           if (paste_tabular->IsPartOfMultiColumn(r1,c1)) {
+               --c2;
+               continue;
+           }
+           if (tabular->IsPartOfMultiColumn(r2,c2)) {
+               --c1;
+               continue;
+           }
+           int n1 = paste_tabular->GetCellNumber(r1, c1);
+           int n2 = tabular->GetCellNumber(r2, c2);
+           *(tabular->GetCellInset(n2)) = *(paste_tabular->GetCellInset(n1));
+           tabular->GetCellInset(n2)->setOwner(this);
+           tabular->GetCellInset(n2)->deleteLyXText(bv);
+       }
     }
     return true;
 }
@@ -2050,8 +2171,10 @@ bool InsetTabular::cutSelection()
     if (!hasSelection())
        return false;
 
-    int sel_col_start, sel_col_end;
-    int sel_row_start, sel_row_end;
+    int sel_col_start;
+    int sel_col_end;
+    int sel_row_start;
+    int sel_row_end;
 
     sel_col_start = tabular->column_of_cell(sel_cell_start);
     sel_col_end = tabular->column_of_cell(sel_cell_end);
@@ -2083,3 +2206,7 @@ bool InsetTabular::cutSelection()
     return true;
 }
 
+bool InsetTabular::isRightToLeft(BufferView *bv )
+{
+       return bv->getParentLanguage(this)->RightToLeft();
+}