]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
Do not output deleted rows columns if show changes in output is false
[lyx.git] / src / insets / InsetTabular.cpp
index ba9462c38a8163fe6c54f00cfd68d88a12298d16..f6897d617052bfccda3cbecf39b151136e0e635b 100644 (file)
@@ -451,18 +451,42 @@ bool getTokenValue(string const & str, char const * token, Length & len)
 }
 
 
-bool getTokenValue(string const & str, char const * token, Change::Type & change)
+bool getTokenValue(string const & str, char const * token, Change & change, BufferParams bp)
 {
-       // set the length to be zero() as default as this it should be if not
+       // set the change to be Change() as default as this it should be if not
        // in the file format.
-       change = Change::UNCHANGED;
+       change = Change();
        string tmp;
        if (getTokenValue(str, token, tmp)) {
-               if (tmp == "inserted") {
-                       change = Change::INSERTED;
+               vector<string> const changedata = getVectorFromString(tmp, " ");
+               if (changedata.size() != 3) {
+                       Alert::warning(_("Change tracking data incomplete"),
+                                      _("Change tracking information for tabular row/column "
+                                        "is incomplete. I will ignore this.\n"));
+                       return false;
+               }
+               BufferParams::AuthorMap const & am = bp.author_map_;
+               int aid = convert<int>(changedata[1]);
+               if (am.find(aid) == am.end()) {
+                       // FIXME Use ErrorList
+                       Alert::warning(_("Change tracking author index missing"),
+                               bformat(_("A change tracking author information for index "
+                                         "%1$d is missing. This can happen after a wrong "
+                                         "merge by a version control system. In this case, "
+                                         "either fix the merge, or have this information "
+                                         "missing until the corresponding tracked changes "
+                                         "are merged or this user edits the file again.\n"),
+                                       aid));
+                       bp.addAuthor(Author(aid));
+               }
+               istringstream is(changedata[2]);
+               time_t ct;
+               is >> ct;
+               if (changedata[0] == "inserted") {
+                       change = Change(Change::INSERTED, am.find(aid)->second, ct);
                        return true;
-               } else if (tmp == "deleted") {
-                       change = Change::DELETED;
+               } else if (changedata[0] == "deleted") {
+                       change = Change(Change::DELETED, am.find(aid)->second, ct);
                        return true;
                }
        }
@@ -550,13 +574,18 @@ string const write_attribute(string const & name, Length const & value)
        return value.zero() ? string() : write_attribute(name, value.asString());
 }
 
-template <>
-string const write_attribute(string const & name, Change::Type const & type)
+string const write_attribute(string const & name, Change const & change, BufferParams const bp)
 {
-       if (type == Change::INSERTED)
-               return write_attribute(name, from_ascii("inserted"));
-       else if (type == Change::DELETED)
-               return write_attribute(name, from_ascii("deleted"));
+       odocstringstream ods;
+       if (change.inserted())
+               ods << from_ascii("inserted");
+       else if (change.deleted())
+               ods << from_ascii("deleted");
+       if (change.changed()) {
+               ods << " " << bp.authors().get(change.author).bufferId()
+                   << " " << change.changetime;
+               return write_attribute(name, ods.str());
+       }
        return string();
 }
 
@@ -703,7 +732,7 @@ Tabular::RowData::RowData()
          endlastfoot(false),
          newpage(false),
          caption(false),
-         change(Change::UNCHANGED)
+         change(Change())
 {}
 
 
@@ -712,7 +741,7 @@ Tabular::ColumnData::ColumnData()
          valignment(LYX_VALIGN_TOP),
          width(0),
          varwidth(false),
-         change(Change::UNCHANGED)
+         change(Change())
 {
 }
 
@@ -778,9 +807,6 @@ void Tabular::deleteRow(row_type const row, bool const force)
        bool const ct = force ? false : buffer().params().track_changes;
 
        for (col_type c = 0; c < ncols(); ++c) {
-               // mark track changes
-               if (ct)
-                       cell_info[row][c].inset->setChange(Change(Change::DELETED));
                // Care about multirow cells
                if (row + 1 < nrows() &&
                    cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW &&
@@ -789,7 +815,7 @@ void Tabular::deleteRow(row_type const row, bool const force)
                }
        }
        if (ct)
-               row_info[row].change = Change::DELETED;
+               row_info[row].change.setDeleted();
        else {
                row_info.erase(row_info.begin() + row);
                cell_info.erase(cell_info.begin() + row);
@@ -819,8 +845,6 @@ void Tabular::insertRow(row_type const row, bool copy)
        for (col_type c = 0; c < ncols(); ++c) {
                cell_info[row + 1].insert(cell_info[row + 1].begin() + c,
                        copy ? CellData(cell_info[row][c]) : CellData(buffer_));
-               if (buffer().params().track_changes)
-                       cell_info[row + 1][c].inset->setChange(Change(Change::INSERTED));
                if (cell_info[row][c].multirow == CELL_BEGIN_OF_MULTIROW)
                        cell_info[row + 1][c].multirow = CELL_PART_OF_MULTIROW;
        }
@@ -839,12 +863,11 @@ void Tabular::insertRow(row_type const row, bool copy)
                        setBottomLine(i, true);
                        setBottomLine(j, false);
                }
-               // mark track changes
-               if (buffer().params().track_changes)
-                       cellInfo(i).inset->setChange(Change(Change::INSERTED));
        }
-       if (buffer().params().track_changes)
-               row_info[row + 1].change = Change::INSERTED;
+       if (buffer().params().track_changes) {
+               row_info[row + 1].change.setInserted();
+               updateIndexes();
+       }
 }
 
 
@@ -903,9 +926,6 @@ void Tabular::deleteColumn(col_type const col, bool const force)
        bool const ct = force ? false : buffer().params().track_changes;
 
        for (row_type r = 0; r < nrows(); ++r) {
-               // mark track changes
-               if (ct)
-                       cell_info[r][col].inset->setChange(Change(Change::DELETED));
                // Care about multicolumn cells
                if (col + 1 < ncols() &&
                    cell_info[r][col].multicolumn == CELL_BEGIN_OF_MULTICOLUMN &&
@@ -916,7 +936,7 @@ void Tabular::deleteColumn(col_type const col, bool const force)
                        cell_info[r].erase(cell_info[r].begin() + col);
        }
        if (ct)
-               column_info[col].change = Change::DELETED;
+               column_info[col].change.setDeleted();
        else
                column_info.erase(column_info.begin() + col);
        updateIndexes();
@@ -937,14 +957,12 @@ void Tabular::appendColumn(col_type col)
 
 void Tabular::insertColumn(col_type const col, bool copy)
 {
-       BufferParams const & bp = buffer().params();
+       bool const ct = buffer().params().track_changes;
        column_info.insert(column_info.begin() + col + 1, ColumnData(column_info[col]));
 
        for (row_type r = 0; r < nrows(); ++r) {
                cell_info[r].insert(cell_info[r].begin() + col + 1,
                        copy ? CellData(cell_info[r][col]) : CellData(buffer_));
-               if (bp.track_changes)
-                       cell_info[r][col + 1].inset->setChange(Change(Change::INSERTED));
                if (cell_info[r][col].multicolumn == CELL_BEGIN_OF_MULTICOLUMN)
                        cell_info[r][col + 1].multicolumn = CELL_PART_OF_MULTICOLUMN;
        }
@@ -960,11 +978,11 @@ void Tabular::insertColumn(col_type const col, bool copy)
                if (rightLine(i) && rightLine(j)) {
                        setRightLine(j, false);
                }
-               if (buffer().params().track_changes)
-                       cellInfo(i).inset->setChange(Change(Change::INSERTED));
        }
-       if (buffer().params().track_changes)
-               column_info[col + 1].change = Change::INSERTED;
+       if (ct) {
+               column_info[col + 1].change.setInserted();
+               updateIndexes();
+       }
 }
 
 
@@ -987,8 +1005,8 @@ void Tabular::updateIndexes()
        rowofcell.resize(numberofcells);
        columnofcell.resize(numberofcells);
        idx_type i = 0;
-       // reset column and row of cells and update their width and alignment
-       for (row_type row = 0; row < nrows(); ++row)
+       // reset column and row of cells and update their width, alignment and ct status
+       for (row_type row = 0; row < nrows(); ++row) {
                for (col_type column = 0; column < ncols(); ++column) {
                        if (isPartOfMultiColumn(row, column)) {
                                cell_info[row][column].inset->toggleMultiCol(true);
@@ -1009,8 +1027,15 @@ void Tabular::updateIndexes()
                        cell_info[row][column].inset->toggleMultiRow(false);
                        cell_info[row][column].inset->setContentAlignment(
                                getAlignment(cellIndex(row, column)));
+                       if (buffer().params().track_changes) {
+                               if (row_info[row].change.changed())
+                                       cell_info[row][column].inset->setChange(row_info[row].change);
+                               if (column_info[column].change.changed())
+                                       cell_info[row][column].inset->setChange(column_info[column].change);
+                       }
                        ++i;
                }
+       }
 }
 
 
@@ -1622,7 +1647,7 @@ int Tabular::textVOffset(idx_type cell) const
 }
 
 
-Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
+Tabular::idx_type Tabular::getFirstCellInRow(row_type row, bool const ct) const
 {
        col_type c = 0;
        idx_type const numcells = numberOfCellsInRow(row);
@@ -1631,26 +1656,52 @@ Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
        // is really invalid, i.e., it is NOT the first cell in the row. but
        // i do not know what to do here. (rgh)
        while (c < numcells - 1
-              && cell_info[row][c].multirow == CELL_PART_OF_MULTIROW)
+              && (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
+                  || (ct && column_info[c].change.deleted())))
                ++c;
        return cell_info[row][c].cellno;
 }
 
 
-Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
+Tabular::idx_type Tabular::getLastCellInRow(row_type row, bool const ct) const
 {
        col_type c = ncols() - 1;
        // of course we check against 0 so we don't crash. but we have the same
        // problem as in the previous routine: if all the cells are part of a
        // multirow or part of a multi column, then our return value is invalid.
        while (c > 0
-              && (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
-                  || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN))
+              && ((cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
+                  || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN)
+                 || (ct && column_info[c].change.deleted())))
                --c;
        return cell_info[row][c].cellno;
 }
 
 
+Tabular::row_type Tabular::getFirstRow(bool const ct) const
+{
+       row_type r = 0;
+       if (!ct)
+               return r;
+       // exclude deleted rows if ct == true
+       while (r < nrows() && row_info[r].change.deleted())
+               ++r;
+       return r;
+}
+
+
+Tabular::row_type Tabular::getLastRow(bool const ct) const
+{
+       row_type r = nrows() - 1;
+       if (!ct)
+               return r;
+       // exclude deleted rows if ct == true
+       while (r > 0 && row_info[r].change.deleted())
+               --r;
+       return r;
+}
+
+
 Tabular::row_type Tabular::cellRow(idx_type cell) const
 {
        if (cell >= numberofcells)
@@ -1706,7 +1757,7 @@ void Tabular::write(ostream & os) const
                   << write_attribute("alignment", column_info[c].alignment);
                if (column_info[c].alignment == LYX_ALIGN_DECIMAL)
                        os << write_attribute("decimal_point", column_info[c].decimal_point);
-               os << write_attribute("change", column_info[c].change)
+               os << write_attribute("change", column_info[c].change, buffer().params())
                   << write_attribute("valignment", column_info[c].valignment)
                   << write_attribute("width", column_info[c].p_width.asString())
                   << write_attribute("varwidth", column_info[c].varwidth)
@@ -1728,7 +1779,7 @@ void Tabular::write(ostream & os) const
                        os << write_attribute("interlinespace", def);
                else
                        os << write_attribute("interlinespace", row_info[r].interline_space);
-               os << write_attribute("change", row_info[r].change)
+               os << write_attribute("change", row_info[r].change, buffer().params())
                   << write_attribute("endhead", row_info[r].endhead)
                   << write_attribute("endfirsthead", row_info[r].endfirsthead)
                   << write_attribute("endfoot", row_info[r].endfoot)
@@ -1828,7 +1879,7 @@ void Tabular::read(Lexer & lex)
                getTokenValue(line, "width", column_info[c].p_width);
                getTokenValue(line, "special", column_info[c].align_special);
                getTokenValue(line, "varwidth", column_info[c].varwidth);
-               getTokenValue(line, "change", column_info[c].change);
+               getTokenValue(line, "change", column_info[c].change, buffer().params());
        }
 
        for (row_type i = 0; i < nrows(); ++i) {
@@ -1850,7 +1901,7 @@ void Tabular::read(Lexer & lex)
                getTokenValue(line, "endlastfoot", row_info[i].endlastfoot);
                getTokenValue(line, "newpage", row_info[i].newpage);
                getTokenValue(line, "caption", row_info[i].caption);
-               getTokenValue(line, "change", row_info[i].change);
+               getTokenValue(line, "change", row_info[i].change, buffer().params());
                for (col_type j = 0; j < ncols(); ++j) {
                        l_getline(is, line);
                        if (!prefixIs(line, "<cell")) {
@@ -2472,15 +2523,16 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, list<col_type> columns)
        }
 
        // do nothing if empty first row, or incomplete row line after
-       if ((row == 0 && nset == 0) || (row > 0 && nset != ncols()))
+       row_type first = getFirstRow(!buffer().params().output_changes);
+       if ((row == first && nset == 0) || (row > first && nset != columns.size()))
                return;
 
        // Is this the actual first row (excluding longtable caption row)?
-       bool const realfirstrow = (row == 0
-                                  || (is_long_tabular && row == 1 && ltCaption(0)));
+       bool const realfirstrow = (row == first
+                                  || (is_long_tabular && row == first + 1 && ltCaption(first)));
 
        // only output complete row lines and the 1st row's clines
-       if (nset == ncols() && !have_trims) {
+       if (nset == columns.size() && !have_trims) {
                if (use_booktabs) {
                        os << (realfirstrow ? "\\toprule " : "\\midrule ");
                } else {
@@ -2532,7 +2584,7 @@ void Tabular::TeXTopHLine(otexstream & os, row_type row, list<col_type> columns)
                                if (!trim.empty())
                                        os << "(" << trim << ")";
                                os << "{" << firstcol << '-' << lastcol << "}";
-                               if (c == ncols() - 1)
+                               if (c == columns.size() - 1)
                                        break;
                                ++c;
                        }
@@ -2548,7 +2600,7 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, list<col_type> colum
        // if the latter do not span the whole tabular
 
        // get the bottomlines of row r, and toplines in next row
-       bool lastrow = row == nrows() - 1;
+       bool lastrow = row == getLastRow(!buffer().params().output_changes);
        map<col_type, bool> bottomline, topline, topltrims, toprtrims, bottomltrims, bottomrtrims;
        bool nextrowset = true;
        for (auto const & c : columns) {
@@ -2601,10 +2653,10 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, list<col_type> colum
        }
 
        // do nothing if empty, OR incomplete row line with a topline in next row
-       if (nset == 0 || (nextrowset && nset != ncols()))
+       if (nset == 0 || (nextrowset && nset != columns.size()))
                return;
 
-       if (nset == ncols() && !have_trims) {
+       if (nset == columns.size() && !have_trims) {
                if (use_booktabs)
                        os << (lastrow ? "\\bottomrule" : "\\midrule");
                else
@@ -2657,7 +2709,7 @@ void Tabular::TeXBottomHLine(otexstream & os, row_type row, list<col_type> colum
                                if (!trim.empty())
                                        os << "(" << trim << ")";
                                os << "{" << firstcol << '-' << lastcol << "}";
-                               if (c == ncols() - 1)
+                               if (c == columns.size() - 1)
                                        break;
                                ++c;
                        }
@@ -2978,8 +3030,9 @@ void Tabular::TeXRow(otexstream & os, row_type row,
        bool const bidi_rtl =
                runparams.local_font->isRightToLeft()
                && runparams.useBidiPackage();
+       bool const ct = !buffer().params().output_changes;
        idx_type lastcell =
-               bidi_rtl ? getFirstCellInRow(row) : getLastCellInRow(row);
+               bidi_rtl ? getFirstCellInRow(row, ct) : getLastCellInRow(row, ct);
 
        for (auto const & c : columns) {
                if (isPartOfMultiColumn(row, c))
@@ -3150,6 +3203,8 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
                && runparams.useBidiPackage();
        list<col_type> columns;
        for (col_type cl = 0; cl < ncols(); ++cl) {
+               if (!buffer().params().output_changes && column_info[cl].change.deleted())
+                       continue;
                if (bidi_rtl)
                        columns.push_front(cl);
                else
@@ -3375,6 +3430,8 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
        //+---------------------------------------------------------------------
 
        for (row_type r = 0; r < nrows(); ++r) {
+               if (!buffer().params().output_changes && row_info[r].change.deleted())
+                       continue;
                if (isValidRow(r)) {
                        TeXRow(os, r, runparams, columns);
                        if (is_long_tabular && row_info[r].newpage)
@@ -4486,9 +4543,9 @@ void InsetTabular::drawSelection(PainterInfo & pi, int x, int y) const
 namespace {
 
 void tabline(PainterInfo const & pi, int x1, int y1, int x2, int y2, int lt, int rt,
-             bool drawline, bool heavy = false)
+             Color const incol, bool drawline, bool heavy = false)
 {
-       ColorCode const col = drawline ? Color_tabularline : Color_tabularonoffline;
+       Color const col = drawline ? incol : Color_tabularonoffline;
        if (drawline && lt > 0)
                pi.pain.line(x1, y1, x1 + lt, y2, pi.textColor(Color_tabularonoffline),
                                         Painter::line_onoffdash,
@@ -4516,6 +4573,12 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
 
        col_type const col = tabular.cellColumn(cell);
 
+       // Colour the frame if rows/columns are added or deleted
+       Color colour = Color_tabularline;
+       if (tabular.column_info[col].change.changed()
+           || tabular.row_info[row].change.changed())
+               colour = InsetTableCell(*tabular.cellInset(cell)).paragraphs().front().lookupChange(0).color();
+
        // Top
        bool drawline = tabular.topLine(cell)
                || (row > 0 && tabular.bottomLine(tabular.cellAbove(cell)));
@@ -4528,7 +4591,7 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        if (tabular.topLineTrim(cell).second
            || (row > 0 && tabular.bottomLineTrim(tabular.cellIndex(row - 1, col)).second))
                rt = 10;
-       tabline(pi, x, y, x + w, y, lt, rt, drawline, heavy);
+       tabline(pi, x, y, x + w, y, lt, rt, colour, drawline, heavy);
 
        // Bottom
        lt = rt = 0;
@@ -4546,12 +4609,12 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
                lt = 10;
        if (tabular.bottomLineTrim(cell).second)
                rt = 10;
-       tabline(pi, x, y + h, x + w, y + h, lt, rt, drawline, heavy);
+       tabline(pi, x, y + h, x + w, y + h, lt, rt, colour, drawline, heavy);
 
        // Left
        drawline = tabular.leftLine(cell)
                || (col > 0 && tabular.rightLine(tabular.cellIndex(row, col - 1)));
-       tabline(pi, x, y, x, y + h, 0, 0, drawline);
+       tabline(pi, x, y, x, y + h, 0, 0, colour, drawline);
 
        // Right
        x -= tabular.interColumnSpace(cell);
@@ -4562,7 +4625,7 @@ void InsetTabular::drawCellLines(PainterInfo & pi, int x, int y,
        drawline = tabular.rightLine(cell)
                   || (next_cell_col < tabular.ncols()
                       && tabular.leftLine(tabular.cellIndex(row, next_cell_col)));
-       tabline(pi, x + w, y, x + w, y + h, 0, 0, drawline);
+       tabline(pi, x + w, y, x + w, y + h, 0, 0, colour, drawline);
 }
 
 
@@ -5130,17 +5193,17 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                if (ct && cs == 0 && ce == tabular.ncols() - 1) {
                                        // whole row selected
                                        if (act == LFUN_CHANGE_ACCEPT) {
-                                               if (tabular.row_info[r].change == Change::INSERTED)
-                                                       tabular.row_info[r].change = Change::UNCHANGED;
-                                               else if (tabular.row_info[r].change == Change::DELETED) {
+                                               if (tabular.row_info[r].change.inserted())
+                                                       tabular.row_info[r].change.setUnchanged();
+                                               else if (tabular.row_info[r].change.deleted()) {
                                                        tabular.deleteRow(r, true);
                                                        --re;
                                                        continue;
                                                }
                                        } else {
-                                               if (tabular.row_info[r].change == Change::DELETED)
-                                                       tabular.row_info[r].change = Change::UNCHANGED;
-                                               else if (tabular.row_info[r].change == Change::INSERTED) {
+                                               if (tabular.row_info[r].change.deleted())
+                                                       tabular.row_info[r].change.setUnchanged();
+                                               else if (tabular.row_info[r].change.inserted()) {
                                                        tabular.deleteRow(r, true);
                                                        --re;
                                                        continue;
@@ -5151,17 +5214,17 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                        if (ct && rs == 0 && re == tabular.nrows() - 1) {
                                                // whole col selected
                                                if (act == LFUN_CHANGE_ACCEPT) {
-                                                       if (tabular.column_info[c].change == Change::INSERTED)
-                                                               tabular.column_info[c].change = Change::UNCHANGED;
-                                                       else if (tabular.column_info[c].change == Change::DELETED) {
+                                                       if (tabular.column_info[c].change.inserted())
+                                                               tabular.column_info[c].change.setUnchanged();
+                                                       else if (tabular.column_info[c].change.deleted()) {
                                                                tabular.deleteColumn(c, true);
                                                                --ce;
                                                                continue;
                                                        }
                                                } else {
-                                                       if (tabular.column_info[c].change == Change::DELETED)
-                                                               tabular.column_info[c].change = Change::UNCHANGED;
-                                                       else if (tabular.column_info[c].change == Change::INSERTED) {
+                                                       if (tabular.column_info[c].change.deleted())
+                                                               tabular.column_info[c].change.setUnchanged();
+                                                       else if (tabular.column_info[c].change.inserted()) {
                                                                tabular.deleteColumn(c, true);
                                                                --ce;
                                                                continue;
@@ -5182,8 +5245,12 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                                }
                        }
                        if (ct) {
+                               tabular.updateIndexes();
                                // cursor might be invalid
                                cur.fixIfBroken();
+                               // change bar might need to be redrawn
+                               cur.screenUpdateFlags(Update::Force);
+                               cur.forceBufferUpdate();
                        }
                        break;
                } else {
@@ -5196,7 +5263,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_CHANGE_PREVIOUS: {
                // BufferView::dispatch has already moved the cursor, we just
                // need to select here if we have a changed row or column
-               if (tabular.row_info[tabular.cellRow(cur.idx())].change != Change::UNCHANGED) {
+               if (tabular.row_info[tabular.cellRow(cur.idx())].change.changed()) {
                        // select row
                        cur.idx() = tabular.getFirstCellInRow(tabular.cellRow(cur.idx()));
                        cur.pit() = 0;
@@ -5209,7 +5276,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        bvcur = cur;
                        rowselect_ = true;
                }
-               else if (tabular.column_info[tabular.cellColumn(cur.idx())].change != Change::UNCHANGED) {
+               else if (tabular.column_info[tabular.cellColumn(cur.idx())].change.changed()) {
                        // select column
                        cur.idx() = tabular.cellIndex(0, tabular.cellColumn(cur.idx()));
                        cur.pit() = 0;
@@ -5787,23 +5854,23 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        col_type cs, ce;
                        getSelection(cur, rs, re, cs, ce);
                        for (row_type r = rs; r <= re; ++r) {
-                               if (tabular.row_info[r].change != Change::UNCHANGED) {
+                               if (tabular.row_info[r].change.changed()) {
                                        status.setEnabled(true);
                                        return true;
                                }
                                for (col_type c = cs; c <= ce; ++c) {
-                                       if (tabular.column_info[c].change != Change::UNCHANGED) {
+                                       if (tabular.column_info[c].change.changed()) {
                                                status.setEnabled(true);
                                                return true;
                                        }
                                }
                        }
                } else {
-                       if (tabular.row_info[tabular.cellRow(cur.idx())].change != Change::UNCHANGED) {
+                       if (tabular.row_info[tabular.cellRow(cur.idx())].change.changed()) {
                                status.setEnabled(true);
                                return true;
                        }
-                       else if (tabular.column_info[tabular.cellColumn(cur.idx())].change != Change::UNCHANGED) {
+                       else if (tabular.column_info[tabular.cellColumn(cur.idx())].change.changed()) {
                                status.setEnabled(true);
                                return true;
                        }
@@ -7124,10 +7191,14 @@ Text * InsetTabular::getText(int idx) const
 
 bool InsetTabular::isChanged() const
 {
-       for (idx_type idx = 0; idx < nargs(); ++idx)
+       for (idx_type idx = 0; idx < nargs(); ++idx) {
                if (cell(idx)->isChanged())
                        return true;
-       // FIXME: shall we look at row/columns changed status?
+               if (tabular.row_info[tabular.cellRow(idx)].change.changed())
+                       return true;
+               if (tabular.column_info[tabular.cellColumn(idx)].change.changed())
+                       return true;
+       }
        return false;
 }
 
@@ -7144,17 +7215,18 @@ void InsetTabular::acceptChanges()
        for (idx_type idx = 0; idx < nargs(); ++idx)
                cell(idx)->acceptChanges();
        for (row_type row = 0; row < tabular.nrows(); ++row) {
-               if (tabular.row_info[row].change == Change::INSERTED)
-                       tabular.row_info[row].change = Change::UNCHANGED;
-               else if (tabular.row_info[row].change == Change::DELETED)
+               if (tabular.row_info[row].change.inserted())
+                       tabular.row_info[row].change.setUnchanged();
+               else if (tabular.row_info[row].change.deleted())
                        tabular.deleteRow(row, true);
        }
        for (col_type col = 0; col < tabular.ncols(); ++col) {
-               if (tabular.column_info[col].change == Change::INSERTED)
-                       tabular.column_info[col].change = Change::UNCHANGED;
-               else if (tabular.column_info[col].change == Change::DELETED)
+               if (tabular.column_info[col].change.inserted())
+                       tabular.column_info[col].change.setUnchanged();
+               else if (tabular.column_info[col].change.deleted())
                        tabular.deleteColumn(col, true);
        }
+       tabular.updateIndexes();
 }
 
 
@@ -7163,17 +7235,18 @@ void InsetTabular::rejectChanges()
        for (idx_type idx = 0; idx < nargs(); ++idx)
                cell(idx)->rejectChanges();
        for (row_type row = 0; row < tabular.nrows(); ++row) {
-               if (tabular.row_info[row].change == Change::DELETED)
-                       tabular.row_info[row].change = Change::UNCHANGED;
-               else if (tabular.row_info[row].change == Change::INSERTED)
+               if (tabular.row_info[row].change.deleted())
+                       tabular.row_info[row].change.setUnchanged();
+               else if (tabular.row_info[row].change.inserted())
                        tabular.deleteRow(row, true);
        }
        for (col_type col = 0; col < tabular.ncols(); ++col) {
-               if (tabular.column_info[col].change == Change::DELETED)
-                       tabular.column_info[col].change = Change::UNCHANGED;
-               else if (tabular.column_info[col].change == Change::INSERTED)
+               if (tabular.column_info[col].change.deleted())
+                       tabular.column_info[col].change.setUnchanged();
+               else if (tabular.column_info[col].change.inserted())
                        tabular.deleteColumn(col, true);
        }
+       tabular.updateIndexes();
 }