]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
InsetTabular.cpp: fix bug that LyX allowed to specify the vertical alignment of table...
[lyx.git] / src / insets / InsetTabular.cpp
index 487d03b6bccfda4abc0d17a780bb7a8c0ac1db02..65ae8b912f43da27203f35629f8d5fe7354e850b 100644 (file)
@@ -113,6 +113,11 @@ TabularFeature tabularFeature[] =
        { Tabular::DELETE_COLUMN, "delete-column", false },
        { Tabular::COPY_ROW, "copy-row", false },
        { Tabular::COPY_COLUMN, "copy-column", false },
+       { Tabular::SET_LINE_TOP, "set-line-top", true },
+       { Tabular::SET_LINE_BOTTOM, "set-line-bottom", true },
+       { Tabular::SET_LINE_LEFT, "set-line-left", true },
+       { Tabular::SET_LINE_RIGHT, "set-line-right", true },
+       //FIXME: get rid of those 4 TOGGLE actions in favor of the 4 above.
        { Tabular::TOGGLE_LINE_TOP, "toggle-line-top", false },
        { Tabular::TOGGLE_LINE_BOTTOM, "toggle-line-bottom", false },
        { Tabular::TOGGLE_LINE_LEFT, "toggle-line-left", false },
@@ -164,9 +169,9 @@ TabularFeature tabularFeature[] =
        { Tabular::SET_BOTTOM_SPACE, "set-bottom-space", true },
        { Tabular::SET_INTERLINE_SPACE, "set-interline-space", true },
        { Tabular::SET_BORDER_LINES, "set-border-lines", false },
-       { Tabular::TABULAR_VALIGN_TOP, "tabular-valign-top"},
-       { Tabular::TABULAR_VALIGN_MIDDLE, "tabular-valign-middle"},
-       { Tabular::TABULAR_VALIGN_BOTTOM, "tabular-valign-bottom"},
+       { Tabular::TABULAR_VALIGN_TOP, "tabular-valign-top", false},
+       { Tabular::TABULAR_VALIGN_MIDDLE, "tabular-valign-middle", false},
+       { Tabular::TABULAR_VALIGN_BOTTOM, "tabular-valign-bottom", false},
        { Tabular::LONGTABULAR_ALIGN_LEFT, "longtabular-align-left", false },
        { Tabular::LONGTABULAR_ALIGN_CENTER, "longtabular-align-center", false },
        { Tabular::LONGTABULAR_ALIGN_RIGHT, "longtabular-align-right", false },
@@ -174,18 +179,6 @@ TabularFeature tabularFeature[] =
 };
 
 
-class FeatureEqual : public unary_function<TabularFeature, bool> {
-public:
-       FeatureEqual(Tabular::Feature feature)
-               : feature_(feature) {}
-       bool operator()(TabularFeature const & tf) const {
-               return tf.action == feature_;
-       }
-private:
-       Tabular::Feature feature_;
-};
-
-
 template <class T>
 string const write_attribute(string const & name, T const & t)
 {
@@ -500,13 +493,13 @@ void l_getline(istream & is, string & str)
 } // namespace
 
 
-string const featureAsString(Tabular::Feature feature)
+string const featureAsString(Tabular::Feature action)
 {
-       TabularFeature * end = tabularFeature +
-               sizeof(tabularFeature) / sizeof(TabularFeature);
-       TabularFeature * it = find_if(tabularFeature, end,
-                                          FeatureEqual(feature));
-       return (it == end) ? string() : it->feature;
+       for (size_t i = 0; i != Tabular::LAST_ACTION; ++i) {
+               if (tabularFeature[i].action == action)
+                       return tabularFeature[i].feature;
+       }
+       return string();
 }
 
 
@@ -874,32 +867,6 @@ bool Tabular::rightLine(idx_type cell) const
 }
 
 
-bool Tabular::topAlreadyDrawn(idx_type cell) const
-{
-       row_type const row = cellRow(cell);
-       if (row == 0)
-               return false;
-       
-       return !rowTopLine(row) && bottomLine(cellAbove(cell));
-}
-
-
-bool Tabular::leftAlreadyDrawn(idx_type cell) const
-{
-       col_type col = cellColumn(cell);
-       if (col == 0)
-               return false;
-       idx_type i = cellIndex(cellRow(cell), col - 1);
-       return rightLine(i) && !leftLine(cell);
-}
-
-
-bool Tabular::isLastRow(idx_type cell) const
-{
-       return cellRow(cell) == row_info.size() - 1;
-}
-
-
 int Tabular::interRowSpace(row_type row) const
 {
        if (!row || row >= row_info.size())
@@ -1068,6 +1035,11 @@ void Tabular::setColumnPWidth(Cursor & cur, idx_type cell,
        col_type const j = cellColumn(cell);
 
        column_info[j].p_width = width;
+       // reset the vertical alignment to top if the fixed with
+       // is removed or zero because only fixed width columns can
+       // have a vertical alignment
+       if (column_info[j].p_width.zero())
+               column_info[j].valignment = LYX_VALIGN_TOP;
        for (row_type i = 0; i < row_info.size(); ++i) {
                idx_type const cell = cellIndex(i, j);
                // because of multicolumns
@@ -3467,7 +3439,10 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
                onoffcol = change.color();
        }
 
-       if (!tabular.topAlreadyDrawn(cell)) {
+       bool topalreadydrawn = row > 0 && !tabular.rowTopLine(row) 
+               && tabular.bottomLine(tabular.cellAbove(cell));
+
+       if (!topalreadydrawn) {
                on_off = !tabular.topLine(cell);
                pain.line(x, y, x + w, y,
                        on_off ? onoffcol : col,
@@ -3477,7 +3452,12 @@ void InsetTabular::drawCellLines(Painter & pain, int x, int y,
        pain.line(x, y + h, x + w, y + h,
                on_off ? onoffcol : col,
                on_off ? Painter::line_onoffdash : Painter::line_solid);
-       if (!tabular.leftAlreadyDrawn(cell)) {
+
+       col_type const column = tabular.cellColumn(cell);
+       bool leftalreadydrawn = column > 0  && !tabular.leftLine(cell)
+               && tabular.rightLine(tabular.cellIndex(row, column - 1));
+
+       if (!leftalreadydrawn) {
                on_off = !tabular.leftLine(cell);
                pain.line(x, y, x, y + h,
                        on_off ? onoffcol : col,
@@ -3519,7 +3499,7 @@ void InsetTabular::edit(Cursor & cur, bool front, EntryDirection)
 }
 
 
-void InsetTabular::updateLabels(ParIterator const & it, UpdateType utype)
+void InsetTabular::updateBuffer(ParIterator const & it, UpdateType utype)
 {
        // In a longtable, tell captions what the current float is
        Counters & cnts = buffer().masterBuffer()->params().documentClass().counters();
@@ -3531,7 +3511,7 @@ void InsetTabular::updateLabels(ParIterator const & it, UpdateType utype)
        it2.forwardPos();
        size_t const end = it2.nargs();
        for ( ; it2.idx() < end; it2.top().forwardIdx())
-               buffer().updateLabels(it2, utype);
+               buffer().updateBuffer(it2, utype);
 
        //reset afterwards
        if (tabular.is_long_tabular)
@@ -4088,16 +4068,20 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::MULTICOLUMN:
                        // If a row is set as longtable caption, it must not be allowed
                        // to unset that this row is a multicolumn.
+                       // don't allow to set a multirow as multicolumn
                        status.setEnabled(sel_row_start == sel_row_end
-                               && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                               && !tabular.ltCaption(tabular.cellRow(cur.idx()))
+                               && !tabular.isMultiRow(cur.idx()) );
                        status.setOnOff(tabular.isMultiColumn(cur.idx()));
                        break;
 
                case Tabular::MULTIROW:
                        // If a row is set as longtable caption, it must not be allowed
                        // to unset that this row is a multirow.
+                       // don't allow to set a multicolumn as multirow
                        status.setEnabled(sel_col_start == sel_col_end
-                               && !tabular.ltCaption(tabular.cellRow(cur.idx())));
+                               && !tabular.ltCaption(tabular.cellRow(cur.idx()))
+                               && !tabular.isMultiColumn(cur.idx()) );
                        status.setOnOff(tabular.isMultiRow(cur.idx()));
                        break;
 
@@ -4107,6 +4091,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
                        break;
 
+               case Tabular::SET_LINE_TOP:
+               case Tabular::SET_LINE_BOTTOM:
+               case Tabular::SET_LINE_LEFT:
+               case Tabular::SET_LINE_RIGHT:
+                       status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
+                       break;
+
                case Tabular::TOGGLE_LINE_TOP:
                        status.setEnabled(!tabular.ltCaption(tabular.cellRow(cur.idx())));
                        status.setOnOff(tabular.topLine(cur.idx()));
@@ -4153,6 +4144,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_TOP:
                        flag = false;
                case Tabular::VALIGN_TOP:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_TOP);
                        break;
@@ -4160,6 +4152,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_BOTTOM:
                        flag = false;
                case Tabular::VALIGN_BOTTOM:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_BOTTOM);
                        break;
@@ -4167,6 +4160,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                case Tabular::M_VALIGN_MIDDLE:
                        flag = false;
                case Tabular::VALIGN_MIDDLE:
+                       status.setEnabled(!tabular.getPWidth(cur.idx()).zero());
                        status.setOnOff(
                                tabular.getVAlignment(cur.idx(), flag) == Tabular::LYX_VALIGN_MIDDLE);
                        break;
@@ -4276,6 +4270,7 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        break;
 
                // only one row can be the caption
+               // and a multirow cannot be set as caption
                case Tabular::TOGGLE_LTCAPTION:
                        status.setEnabled(sel_row_start == sel_row_end
                                && !tabular.getRowOfLTFirstHead(sel_row_start, dummyltt)
@@ -4283,7 +4278,8 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                                && !tabular.getRowOfLTFoot(sel_row_start, dummyltt)
                                && !tabular.getRowOfLTLastFoot(sel_row_start, dummyltt)
                                && (!tabular.haveLTCaption()
-                                       || tabular.ltCaption(sel_row_start)));
+                                       || tabular.ltCaption(sel_row_start))
+                               && !tabular.isMultiRow(sel_row_start));
                        status.setOnOff(tabular.ltCaption(sel_row_start));
                        break;
 
@@ -4744,14 +4740,14 @@ bool InsetTabular::tabularFeatures(Cursor & cur, string const & argument)
        // Safe guard.
        size_t safe_guard = 0;
        for (;;) {
+               if (is.eof())
+                       break;
                safe_guard++;
                if (safe_guard > 1000) {
                        LYXERR0("parameter max count reached!");
                        break;
                }
                is >> s;
-               if (is.eof())
-                       break;
                Tabular::Feature action = Tabular::LAST_ACTION;
 
                size_t i = 0;
@@ -4937,32 +4933,40 @@ void InsetTabular::tabularFeatures(Cursor & cur,
                cur.idx() = tabular.cellIndex(row, column);
                break;
 
+       case Tabular::SET_LINE_TOP:
        case Tabular::TOGGLE_LINE_TOP: {
-               bool lineSet = !tabular.topLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_TOP)
+                              ? (value == "true") : !tabular.topLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setTopLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_BOTTOM:
        case Tabular::TOGGLE_LINE_BOTTOM: {
-               bool lineSet = !tabular.bottomLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_BOTTOM)
+                              ? (value == "true") : !tabular.bottomLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setBottomLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_LEFT:
        case Tabular::TOGGLE_LINE_LEFT: {
-               bool lineSet = !tabular.leftLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_LEFT)
+                              ? (value == "true") : !tabular.leftLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setLeftLine(tabular.cellIndex(i, j), lineSet);
                break;
        }
 
+       case Tabular::SET_LINE_RIGHT:
        case Tabular::TOGGLE_LINE_RIGHT: {
-               bool lineSet = !tabular.rightLine(cur.idx());
+               bool lineSet = (feature == Tabular::SET_LINE_RIGHT)
+                              ? (value == "true") : !tabular.rightLine(cur.idx());
                for (row_type i = sel_row_start; i <= sel_row_end; ++i)
                        for (col_type j = sel_col_start; j <= sel_col_end; ++j)
                                tabular.setRightLine(tabular.cellIndex(i, j), lineSet);