]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetTabular.cpp
#7379 avoid the wrap spell check question when buffer is empty
[lyx.git] / src / insets / InsetTabular.cpp
index 48229d413a3ba0b1dcf493ac97cb08deb4b47d87..c5cc505004cd2723a9d856d6af45baeac221d488 100644 (file)
@@ -183,6 +183,7 @@ TabularFeature tabularFeature[] =
        { Tabular::LONGTABULAR_ALIGN_CENTER, "longtabular-align-center", false },
        { Tabular::LONGTABULAR_ALIGN_RIGHT, "longtabular-align-right", false },
        { Tabular::SET_DECIMAL_POINT, "set-decimal-point", true },
+       { Tabular::SET_TABULAR_WIDTH, "set-tabular-width", true },
        { Tabular::LAST_ACTION, "", false }
 };
 
@@ -678,6 +679,7 @@ void Tabular::init(Buffer * buf, row_type rows_arg,
        updateIndexes();
        is_long_tabular = false;
        tabular_valignment = LYX_VALIGN_MIDDLE;
+       tabular_width = Length();
        longtabular_alignment = LYX_LONGTABULAR_ALIGN_CENTER;
        rotate = false;
        use_booktabs = false;
@@ -1340,8 +1342,9 @@ Tabular::idx_type Tabular::getFirstCellInRow(row_type row) const
 Tabular::idx_type Tabular::getLastCellInRow(row_type row) const
 {
        col_type c = ncols() - 1;
-       while (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
-               || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN)
+       while (c > 0
+              && (cell_info[row][c].multirow == CELL_PART_OF_MULTIROW
+                  || cell_info[row][c].multicolumn == CELL_PART_OF_MULTICOLUMN))
                --c;
        return cell_info[row][c].cellno;
 }
@@ -1391,8 +1394,10 @@ void Tabular::write(ostream & os) const
           << write_attribute("lastFootBottomDL", endlastfoot.bottomDL)
           << write_attribute("lastFootEmpty", endlastfoot.empty);
        // longtables cannot be aligned vertically
-       if (!is_long_tabular)
+       if (!is_long_tabular) {
           os << write_attribute("tabularvalignment", tabular_valignment);
+          os << write_attribute("tabularwidth", tabular_width);
+       }
        if (is_long_tabular)
           os << write_attribute("longtabularalignment",
                                 longtabular_alignment);
@@ -1489,6 +1494,7 @@ void Tabular::read(Lexer & lex)
        getTokenValue(line, "booktabs", use_booktabs);
        getTokenValue(line, "islongtable", is_long_tabular);
        getTokenValue(line, "tabularvalignment", tabular_valignment);
+       getTokenValue(line, "tabularwidth", tabular_width);
        getTokenValue(line, "longtabularalignment", longtabular_alignment);
        getTokenValue(line, "firstHeadTopDL", endfirsthead.topDL);
        getTokenValue(line, "firstHeadBottomDL", endfirsthead.bottomDL);
@@ -2022,7 +2028,7 @@ bool Tabular::isPartOfMultiRow(row_type row, col_type column) const
 }
 
 
-int Tabular::TeXTopHLine(otexstream & os, row_type row, string const lang) const
+void Tabular::TeXTopHLine(otexstream & os, row_type row, string const lang) const
 {
        // we only output complete row lines and the 1st row here, the rest
        // is done in Tabular::TeXBottomHLine(...)
@@ -2044,7 +2050,7 @@ int Tabular::TeXTopHLine(otexstream & os, row_type row, string const lang) const
 
        // do nothing if empty first row, or incomplete row line after
        if ((row == 0 && nset == 0) || (row > 0 && nset != ncols()))
-               return 0;
+               return;
 
        // only output complete row lines and the 1st row's clines
        if (nset == ncols()) {
@@ -2081,11 +2087,10 @@ int Tabular::TeXTopHLine(otexstream & os, row_type row, string const lang) const
                }
        }
        os << "\n";
-       return 1;
 }
 
 
-int Tabular::TeXBottomHLine(otexstream & os, row_type row, string const lang) const
+void Tabular::TeXBottomHLine(otexstream & os, row_type row, string const lang) const
 {
        // we output bottomlines of row r and the toplines of row r+1
        // if the latter do not span the whole tabular
@@ -2119,7 +2124,7 @@ int Tabular::TeXBottomHLine(otexstream & os, row_type row, string const lang) co
 
        // do nothing if empty, OR incomplete row line with a topline in next row
        if (nset == 0 || (nextrowset && nset != ncols()))
-               return 0;
+               return;
 
        if (nset == ncols()) {
                if (use_booktabs)
@@ -2154,17 +2159,15 @@ int Tabular::TeXBottomHLine(otexstream & os, row_type row, string const lang) co
                }
        }
        os << "\n";
-       return 1;
 }
 
 
-int Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
-                            bool & ismulticol, bool & ismultirow) const
+void Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
+                             bool & ismulticol, bool & ismultirow) const
 {
-       int ret = 0;
        row_type const r = cellRow(cell);
        if (is_long_tabular && row_info[r].caption)
-               return ret;
+               return;
 
        Tabular::VAlignment valign =  getVAlignment(cell, !isMultiColumn(cell));
        LyXAlignment align = getAlignment(cell, !isMultiColumn(cell));
@@ -2270,7 +2273,6 @@ int Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
 
        if (getRotateCell(cell)) {
                os << "\\begin{sideways}\n";
-               ++ret;
        }
        if (getUsebox(cell) == BOX_PARBOX) {
                os << "\\parbox[";
@@ -2302,139 +2304,99 @@ int Tabular::TeXCellPreamble(otexstream & os, idx_type cell,
                }
                os << "]{" << from_ascii(getPWidth(cell).asLatexString())
                   << "}\n";
-               ++ret;
        }
-       return ret;
 }
 
 
-int Tabular::TeXCellPostamble(otexstream & os, idx_type cell,
-                             bool ismulticol, bool ismultirow) const
+void Tabular::TeXCellPostamble(otexstream & os, idx_type cell,
+                              bool ismulticol, bool ismultirow) const
 {
-       int ret = 0;
        row_type const r = cellRow(cell);
        if (is_long_tabular && row_info[r].caption)
-               return ret;
+               return;
 
        // usual cells
        if (getUsebox(cell) == BOX_PARBOX)
                os << '}';
-       else if (getUsebox(cell) == BOX_MINIPAGE) {
-               os << "%\n\\end{minipage}";
-               ret += 2;
-       }
-       if (getRotateCell(cell)) {
-               os << "%\n\\end{sideways}";
-               ++ret;
-       }
+       else if (getUsebox(cell) == BOX_MINIPAGE)
+               os << breakln << "\\end{minipage}";
+       if (getRotateCell(cell))
+               os << breakln << "\\end{sideways}";
        if (ismultirow)
                os << '}';
        if (ismulticol)
                os << '}';
-
-       return ret;
 }
 
 
-int Tabular::TeXLongtableHeaderFooter(otexstream & os,
-                                        OutputParams const & runparams) const
+void Tabular::TeXLongtableHeaderFooter(otexstream & os,
+                                       OutputParams const & runparams) const
 {
        if (!is_long_tabular)
-               return 0;
+               return;
 
-       int ret = 0;
        // caption handling
        // the caption must be output before the headers
        if (haveLTCaption()) {
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].caption) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].caption)
+                               TeXRow(os, r, runparams);
                }
        }
        // output first header info
        // first header must be output before the header, otherwise the
        // correct caption placement becomes really weird
        if (haveLTFirstHead()) {
-               if (endfirsthead.topDL) {
+               if (endfirsthead.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endfirsthead) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endfirsthead)
+                               TeXRow(os, r, runparams);
                }
-               if (endfirsthead.bottomDL) {
+               if (endfirsthead.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endfirsthead\n";
-               ++ret;
        }
        // output header info
        if (haveLTHead()) {
-               if (endfirsthead.empty && !haveLTFirstHead()) {
+               if (endfirsthead.empty && !haveLTFirstHead())
                        os << "\\endfirsthead\n";
-                       ++ret;
-               }
-               if (endhead.topDL) {
+               if (endhead.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endhead) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endhead)
+                               TeXRow(os, r, runparams);
                }
-               if (endhead.bottomDL) {
+               if (endhead.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endhead\n";
-               ++ret;
        }
        // output footer info
        if (haveLTFoot()) {
-               if (endfoot.topDL) {
+               if (endfoot.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endfoot) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endfoot)
+                               TeXRow(os, r, runparams);
                }
-               if (endfoot.bottomDL) {
+               if (endfoot.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endfoot\n";
-               ++ret;
-               if (endlastfoot.empty && !haveLTLastFoot()) {
+               if (endlastfoot.empty && !haveLTLastFoot())
                        os << "\\endlastfoot\n";
-                       ++ret;
-               }
        }
        // output lastfooter info
        if (haveLTLastFoot()) {
-               if (endlastfoot.topDL) {
+               if (endlastfoot.topDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                for (row_type r = 0; r < nrows(); ++r) {
-                       if (row_info[r].endlastfoot) {
-                               ret += TeXRow(os, r, runparams);
-                       }
+                       if (row_info[r].endlastfoot)
+                               TeXRow(os, r, runparams);
                }
-               if (endlastfoot.bottomDL) {
+               if (endlastfoot.bottomDL)
                        os << "\\hline\n";
-                       ++ret;
-               }
                os << "\\endlastfoot\n";
-               ++ret;
        }
-       return ret;
 }
 
 
@@ -2448,8 +2410,8 @@ bool Tabular::isValidRow(row_type row) const
 }
 
 
-int Tabular::TeXRow(otexstream & os, row_type row,
-                      OutputParams const & runparams) const
+void Tabular::TeXRow(otexstream & os, row_type row,
+                    OutputParams const & runparams) const
 {
        idx_type cell = cellIndex(row, 0);
        shared_ptr<InsetTableCell> inset = cellInset(cell);
@@ -2457,14 +2419,13 @@ int Tabular::TeXRow(otexstream & os, row_type row,
        string const lang = par.getParLanguage(buffer().params())->lang();
 
        //output the top line
-       int ret = TeXTopHLine(os, row, lang);
+       TeXTopHLine(os, row, lang);
 
        if (row_info[row].top_space_default) {
                if (use_booktabs)
                        os << "\\addlinespace\n";
                else
                        os << "\\noalign{\\vskip\\doublerulesep}\n";
-               ++ret;
        } else if(!row_info[row].top_space.zero()) {
                if (use_booktabs)
                        os << "\\addlinespace["
@@ -2475,22 +2436,23 @@ int Tabular::TeXRow(otexstream & os, row_type row,
                           << from_ascii(row_info[row].top_space.asLatexString())
                           << "}\n";
                }
-               ++ret;
        }
        bool ismulticol = false;
        bool ismultirow = false;
        for (col_type c = 0; c < ncols(); ++c) {
                if (isPartOfMultiColumn(row, c))
                        continue;
-                       
-               if (isPartOfMultiRow(row, c) && 
-                       column_info[c].alignment != LYX_ALIGN_DECIMAL) {
-                       os << " & "; 
+
+               cell = cellIndex(row, c);
+
+               if (isPartOfMultiRow(row, c)
+                   && column_info[c].alignment != LYX_ALIGN_DECIMAL) {
+                       if (cell != getLastCellInRow(row))
+                               os << " & "; 
                        continue;
                }
 
-               cell = cellIndex(row, c);
-               ret += TeXCellPreamble(os, cell, ismulticol, ismultirow);
+               TeXCellPreamble(os, cell, ismulticol, ismultirow);
                shared_ptr<InsetTableCell> inset = cellInset(cell);
 
                Paragraph const & par = inset->paragraphs().front();
@@ -2532,17 +2494,23 @@ int Tabular::TeXRow(otexstream & os, row_type row,
                        tail.setBuffer(head.buffer());
                        head.latex(os, newrp);
                        os << '&';
-                       ret += tail.latex(os, newrp);
-               } else if (!isPartOfMultiRow(row, c))
-                       ret += inset->latex(os, newrp);
+                       tail.latex(os, newrp);
+               } else if (!isPartOfMultiRow(row, c)) {
+                       if (!runparams.nice)
+                               os.texrow().start(par.id(), 0);
+                       inset->latex(os, newrp);
+               }
 
                runparams.encoding = newrp.encoding;
                if (rtl)
                        os << '}';
 
-               ret += TeXCellPostamble(os, cell, ismulticol, ismultirow);
+               TeXCellPostamble(os, cell, ismulticol, ismultirow);
                if (cell != getLastCellInRow(row)) { // not last cell in row
-                       os << " & ";
+                       if (runparams.nice)
+                               os << " & ";
+                       else
+                               os << " &\n";
                }
        }
        if (row_info[row].caption && !endfirsthead.empty && !haveLTFirstHead())
@@ -2565,17 +2533,15 @@ int Tabular::TeXRow(otexstream & os, row_type row,
                   << ']';
        }
        os << '\n';
-       ++ret;
 
        //output the bottom line
-       ret += TeXBottomHLine(os, row, lang);
+       TeXBottomHLine(os, row, lang);
 
        if (row_info[row].interline_space_default) {
                if (use_booktabs)
                        os << "\\addlinespace\n";
                else
                        os << "\\noalign{\\vskip\\doublerulesep}\n";
-               ++ret;
        } else if (!row_info[row].interline_space.zero()) {
                if (use_booktabs)
                        os << "\\addlinespace["
@@ -2585,24 +2551,25 @@ int Tabular::TeXRow(otexstream & os, row_type row,
                        os << "\\noalign{\\vskip"
                           << from_ascii(row_info[row].interline_space.asLatexString())
                           << "}\n";
-               ++ret;
        }
-       return ret;
 }
 
 
-int Tabular::latex(otexstream & os, OutputParams const & runparams) const
+void Tabular::latex(otexstream & os, OutputParams const & runparams) const
 {
-       int ret = 0;
+       bool const is_tabular_star = !tabular_width.zero();
 
        //+---------------------------------------------------------------------
        //+                      first the opening preamble                    +
        //+---------------------------------------------------------------------
 
-       if (rotate) {
+       os << safebreakln;
+       if (runparams.lastid != -1)
+               os.texrow().start(runparams.lastid, runparams.lastpos);
+
+       if (rotate)
                os << "\\begin{sideways}\n";
-               ++ret;
-       }
+
        if (is_long_tabular) {
                os << "\\begin{longtable}";
                switch (longtabular_alignment) {
@@ -2616,7 +2583,10 @@ int Tabular::latex(otexstream & os, OutputParams const & runparams) const
                        break;
                }
        } else {
-               os << "\\begin{tabular}";
+               if (is_tabular_star)
+                       os << "\\begin{tabular*}{" << from_ascii(tabular_width.asLatexString()) << "}";
+               else
+                       os << "\\begin{tabular}";
                switch (tabular_valignment) {
                case LYX_VALIGN_TOP:
                        os << "[t]";
@@ -2631,6 +2601,9 @@ int Tabular::latex(otexstream & os, OutputParams const & runparams) const
        
        os << "{";
 
+       if (is_tabular_star)
+               os << "@{\\extracolsep{\\fill}}";
+
        for (col_type c = 0; c < ncols(); ++c) {
                if (columnLeftLine(c))
                        os << '|';
@@ -2691,9 +2664,8 @@ int Tabular::latex(otexstream & os, OutputParams const & runparams) const
                        os << '|';
        }
        os << "}\n";
-       ++ret;
 
-       ret += TeXLongtableHeaderFooter(os, runparams);
+       TeXLongtableHeaderFooter(os, runparams);
 
        //+---------------------------------------------------------------------
        //+                      the single row and columns (cells)            +
@@ -2701,11 +2673,9 @@ int Tabular::latex(otexstream & os, OutputParams const & runparams) const
 
        for (row_type r = 0; r < nrows(); ++r) {
                if (isValidRow(r)) {
-                       ret += TeXRow(os, r, runparams);
-                       if (is_long_tabular && row_info[r].newpage) {
+                       TeXRow(os, r, runparams);
+                       if (is_long_tabular && row_info[r].newpage)
                                os << "\\newpage\n";
-                               ++ret;
-                       }
                }
        }
 
@@ -2715,16 +2685,15 @@ int Tabular::latex(otexstream & os, OutputParams const & runparams) const
 
        if (is_long_tabular)
                os << "\\end{longtable}";
-       else
-               os << "\\end{tabular}";
-       if (rotate) {
-               // clear counter
-               os.countLines();
-               os << breakln << "\\end{sideways}";
-               ret += os.countLines();
+       else {
+               if (is_tabular_star)
+                       os << "\\end{tabular*}";
+               else
+                       os << "\\end{tabular}";
        }
 
-       return ret;
+       if (rotate)
+               os << breakln << "\\end{sideways}";
 }
 
 
@@ -4036,6 +4005,8 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cmd = FuncRequest(finish_lfun);
                else
                        cur.dispatched();
+
+               cur.screenUpdateFlags(Update::Force | Update::FitCursor);
                break;
 
        }
@@ -4072,6 +4043,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.setCurrentFont();
                        return;
                }
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
        case LFUN_UP_SELECT:
@@ -4105,6 +4077,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd)
                        cur.setCurrentFont();
                        return;
                }
+               cur.screenUpdateFlags(Update::FitCursor);
                break;
 
 //     case LFUN_SCREEN_DOWN: {
@@ -4316,8 +4289,16 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                if (&cur.inset() != this || cmd.getArg(0) != "tabular") 
                        break;
 
-               string const s = cmd.getArg(1);
                // FIXME: We only check for the very first argument...
+               string const s = cmd.getArg(1);
+               // We always enable the lfun if it is coming from the dialog
+               // because the dialog makes sure all the settings are valid,
+               // even though the first argument might not be valid now.
+               if (s == "from-dialog") {
+                       status.setEnabled(true);
+                       return true;
+               }
+
                int action = Tabular::LAST_ACTION;
                int i = 0;
                for (; tabularFeature[i].action != Tabular::LAST_ACTION; ++i) {
@@ -4360,6 +4341,11 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
                        status.clear();
                        return true;
 
+               case Tabular::SET_TABULAR_WIDTH:
+                       status.setEnabled(!tabular.rotate &&  !tabular.is_long_tabular
+                               && tabular.tabular_valignment == Tabular::LYX_VALIGN_MIDDLE);
+                       break;
+
                case Tabular::SET_DECIMAL_POINT:
                        status.setEnabled(
                                tabular.getAlignment(cur.idx()) == LYX_ALIGN_DECIMAL);
@@ -4498,18 +4484,22 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
 
                case Tabular::TOGGLE_ROTATE_TABULAR:
                case Tabular::SET_ROTATE_TABULAR:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.rotate);
                        break;
 
                case Tabular::TABULAR_VALIGN_TOP:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_TOP);
                        break;
                case Tabular::TABULAR_VALIGN_MIDDLE:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_MIDDLE);
                        break;
                case Tabular::TABULAR_VALIGN_BOTTOM:
+                       status.setEnabled(tabular.tabular_width.zero());
                        status.setOnOff(tabular.tabular_valignment 
                                == Tabular::LYX_VALIGN_BOTTOM);
                        break;
@@ -4658,8 +4648,13 @@ bool InsetTabular::getStatus(Cursor & cur, FuncRequest const & cmd,
        }
 
        // disable in non-fixed-width cells
-       case LFUN_NEWLINE_INSERT:
-       case LFUN_BREAK_PARAGRAPH: {
+       case LFUN_BREAK_PARAGRAPH:
+               // multirow does not allow paragraph breaks
+               if (tabular.isMultiRow(cur.idx())) {
+                       status.setEnabled(false);
+                       return true;
+               }
+       case LFUN_NEWLINE_INSERT: {
                if (tabular.getPWidth(cur.idx()).zero()) {
                        status.setEnabled(false);
                        return true;
@@ -4720,9 +4715,9 @@ Inset::DisplayType InsetTabular::display() const
 }
 
 
-int InsetTabular::latex(otexstream & os, OutputParams const & runparams) const
+void InsetTabular::latex(otexstream & os, OutputParams const & runparams) const
 {
-       return tabular.latex(os, runparams);
+       tabular.latex(os, runparams);
 }
 
 
@@ -5187,34 +5182,21 @@ void InsetTabular::tabularFeatures(Cursor & cur,
 
        switch (feature) {
 
+       case Tabular::SET_TABULAR_WIDTH:
+               tabular.setTabularWidth(Length(value));
+               break;
+
        case Tabular::SET_PWIDTH: {
                Length const len(value);
                tabular.setColumnPWidth(cur, cur.idx(), len);
                if (len.zero()
                    && tabular.getAlignment(cur.idx(), true) == LYX_ALIGN_BLOCK)
                        tabularFeatures(cur, Tabular::ALIGN_CENTER, string());
-               // check if there is a 1-column multicolumn cell
-               // if so it must get the same width
-               for (row_type r = 0; r < tabular.nrows(); ++r) {
-                       if (tabular.isMultiColumn(tabular.cellIndex(r, column))
-                               && tabular.columnSpan(tabular.cellIndex(r, column)) == 1)
-                               tabular.setMColumnPWidth(cur, tabular.cellIndex(r, column), len);
-               }
                break;
        }
 
        case Tabular::SET_MPWIDTH:
                tabular.setMColumnPWidth(cur, cur.idx(), Length(value));
-               // if the multicolumn only spans 1 column, the width of the whole column
-               // must have the same width, see bug #7055
-               if (tabular.columnSpan(cur.idx()) == 1)
-                       for (row_type r = 0; r < tabular.nrows(); ++r) {
-                               if (!tabular.isMultiColumn(tabular.cellIndex(r, column)))
-                                       tabular.setColumnPWidth(cur, tabular.cellIndex(r, column), Length(value));
-                               else if (tabular.isMultiColumn(tabular.cellIndex(r, column))
-                                       && tabular.columnSpan(tabular.cellIndex(r, column)) == 1)
-                                       tabular.setMColumnPWidth(cur, tabular.cellIndex(r, column), Length(value));
-                       }
                break;
 
        case Tabular::SET_MROFFSET: