]> git.lyx.org Git - features.git/blobdiff - src/insets/InsetTabular.cpp
Make InsetIterator compatible with range-based loops
[features.git] / src / insets / InsetTabular.cpp
index 0f2a557a6b791f2ae450033fdacec9cb9eed376f..21947f46a5a7e9c45d208581b2fe1118632af804 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "InsetTabular.h"
 
+#include "Author.h"
 #include "buffer_funcs.h"
 #include "Buffer.h"
 #include "BufferParams.h"
@@ -560,7 +561,7 @@ string const write_attribute(string const & name, int const & i)
 
 
 template <>
-string const write_attribute(string const & name, Tabular::idx_type const & i)
+string const write_attribute(string const & name, idx_type const & i)
 {
        // we write only true attribute values so we remove a bit of the
        // file format bloat for tabulars.
@@ -619,7 +620,7 @@ InsetTableCell splitCell(InsetTableCell & head, docstring const & align_d, bool
 {
        InsetTableCell tail = InsetTableCell(head);
        DocIterator const dit = separatorPos(&head, align_d);
-       hassep = (bool)dit;
+       hassep = static_cast<bool>(dit);
        if (hassep) {
                pos_type const psize = head.paragraphs().front().size();
                head.paragraphs().front().eraseChars(dit.pos(), psize, false);
@@ -1040,7 +1041,7 @@ void Tabular::updateIndexes()
 }
 
 
-Tabular::idx_type Tabular::numberOfCellsInRow(row_type const row) const
+idx_type Tabular::numberOfCellsInRow(row_type const row) const
 {
        idx_type result = 0;
        for (col_type c = 0; c < ncols(); ++c)
@@ -1176,7 +1177,7 @@ bool Tabular::updateColumnWidths(MetricsInfo & mi)
        if (!tab_width.zero()) {
                restwidth = mi.base.inPixels(tab_width);
                // Subtract the fixed widths from the table width
-               for (auto const w : max_pwidth)
+               for (auto const w : max_pwidth)
                        restwidth -= w.second;
        }
 
@@ -1190,7 +1191,7 @@ bool Tabular::updateColumnWidths(MetricsInfo & mi)
        // Now consider that some variable width columns exceed the vcolwidth
        if (vcolwidth > 0) {
                bool changed = false;
-               for (auto const w : max_width) {
+               for (auto const w : max_width) {
                        if (tabularx || w.second > vcolwidth) {
                                --restcols;
                                restwidth -= w.second;
@@ -1648,7 +1649,7 @@ int Tabular::textVOffset(idx_type cell) const
 }
 
 
-Tabular::idx_type Tabular::getFirstCellInRow(row_type row, bool const ct) const
+idx_type Tabular::getFirstCellInRow(row_type row, bool const ct) const
 {
        col_type c = 0;
        idx_type const numcells = numberOfCellsInRow(row);
@@ -1664,7 +1665,7 @@ Tabular::idx_type Tabular::getFirstCellInRow(row_type row, bool const ct) const
 }
 
 
-Tabular::idx_type Tabular::getLastCellInRow(row_type row, bool const ct) const
+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
@@ -1679,7 +1680,7 @@ Tabular::idx_type Tabular::getLastCellInRow(row_type row, bool const ct) const
 }
 
 
-Tabular::row_type Tabular::getFirstRow(bool const ct) const
+row_type Tabular::getFirstRow(bool const ct) const
 {
        row_type r = 0;
        if (!ct)
@@ -1691,7 +1692,7 @@ Tabular::row_type Tabular::getFirstRow(bool const ct) const
 }
 
 
-Tabular::row_type Tabular::getLastRow(bool const ct) const
+row_type Tabular::getLastRow(bool const ct) const
 {
        row_type r = nrows() - 1;
        if (!ct)
@@ -1703,7 +1704,7 @@ Tabular::row_type Tabular::getLastRow(bool const ct) const
 }
 
 
-Tabular::row_type Tabular::cellRow(idx_type cell) const
+row_type Tabular::cellRow(idx_type cell) const
 {
        if (cell >= numberofcells)
                return nrows() - 1;
@@ -1713,7 +1714,7 @@ Tabular::row_type Tabular::cellRow(idx_type cell) const
 }
 
 
-Tabular::col_type Tabular::cellColumn(idx_type cell) const
+col_type Tabular::cellColumn(idx_type cell) const
 {
        if (cell >= numberofcells)
                return ncols() - 1;
@@ -2004,7 +2005,7 @@ Tabular::CellData & Tabular::cellInfo(idx_type cell)
 }
 
 
-Tabular::idx_type Tabular::setMultiColumn(Cursor & cur, idx_type cell, idx_type number,
+idx_type Tabular::setMultiColumn(Cursor & cur, idx_type cell, idx_type number,
                                          bool const right_border)
 {
        idx_type const col = cellColumn(cell);
@@ -2055,7 +2056,7 @@ bool Tabular::hasMultiRow(row_type r) const
        return false;
 }
 
-Tabular::idx_type Tabular::setMultiRow(Cursor & cur, idx_type cell, idx_type number,
+idx_type Tabular::setMultiRow(Cursor & cur, idx_type cell, idx_type number,
                                       bool const bottom_border,
                                       LyXAlignment const halign)
 {
@@ -2101,7 +2102,7 @@ Tabular::idx_type Tabular::setMultiRow(Cursor & cur, idx_type cell, idx_type num
 }
 
 
-Tabular::idx_type Tabular::columnSpan(idx_type cell) const
+idx_type Tabular::columnSpan(idx_type cell) const
 {
        row_type const row = cellRow(cell);
        col_type const col = cellColumn(cell);
@@ -2113,7 +2114,7 @@ Tabular::idx_type Tabular::columnSpan(idx_type cell) const
 }
 
 
-Tabular::idx_type Tabular::rowSpan(idx_type cell) const
+idx_type Tabular::rowSpan(idx_type cell) const
 {
        col_type const column = cellColumn(cell);
        col_type row = cellRow(cell) + 1;
@@ -2189,13 +2190,11 @@ bool Tabular::needRotating() const
 
 bool Tabular::isLastCell(idx_type cell) const
 {
-       if (cell + 1 < numberofcells)
-               return false;
-       return true;
+       return cell + 1 >= numberofcells;
 }
 
 
-Tabular::idx_type Tabular::cellAbove(idx_type cell) const
+idx_type Tabular::cellAbove(idx_type cell) const
 {
        if (cellRow(cell) == 0)
                return cell;
@@ -2209,7 +2208,7 @@ Tabular::idx_type Tabular::cellAbove(idx_type cell) const
 }
 
 
-Tabular::idx_type Tabular::cellBelow(idx_type cell) const
+idx_type Tabular::cellBelow(idx_type cell) const
 {
        row_type const nextrow = cellRow(cell) + rowSpan(cell);
        if (nextrow < nrows())
@@ -2218,7 +2217,7 @@ Tabular::idx_type Tabular::cellBelow(idx_type cell) const
 }
 
 
-Tabular::idx_type Tabular::cellIndex(row_type row, col_type column) const
+idx_type Tabular::cellIndex(row_type row, col_type column) const
 {
        LASSERT(column != npos && column < ncols(), column = 0);
        LASSERT(row != npos && row < nrows(), row = 0);
@@ -2369,7 +2368,7 @@ bool Tabular::haveLTLastFoot(bool withcaptions) const
 }
 
 
-Tabular::idx_type Tabular::setLTCaption(Cursor & cur, row_type row, bool what)
+idx_type Tabular::setLTCaption(Cursor & cur, row_type row, bool what)
 {
        idx_type i = getFirstCellInRow(row);
        if (what) {
@@ -3133,12 +3132,11 @@ void Tabular::TeXRow(otexstream & os, row_type row,
                } else if (ltCaption(row)) {
                        // Inside longtable caption rows, we must only output the caption inset
                        // with its content and omit anything outside of that (see #10791)
-                       InsetIterator it = inset_iterator_begin(*const_cast<InsetTableCell *>(inset));
-                       InsetIterator i_end = inset_iterator_end(*const_cast<InsetTableCell *>(inset));
-                       for (; it != i_end; ++it) {
-                               if (it->lyxCode() != CAPTION_CODE)
+                       InsetTableCell & tc_inset = *const_cast<InsetTableCell *>(inset);
+                       for (Inset const & it : tc_inset) {
+                               if (it.lyxCode() != CAPTION_CODE)
                                        continue;
-                               it->latex(os, runparams);
+                               it.latex(os, runparams);
                                break;
                        }
                } else if (!isPartOfMultiRow(row, c)) {
@@ -3501,6 +3499,20 @@ void Tabular::latex(otexstream & os, OutputParams const & runparams) const
 
 void Tabular::docbookRow(XMLStream & xs, row_type row,
                   OutputParams const & runparams, bool header) const
+{
+       switch (buffer().params().docbook_table_output) {
+       case BufferParams::HTMLTable:
+               docbookRowAsHTML(xs, row, runparams, header);
+               break;
+       case BufferParams::CALSTable:
+               docbookRowAsCALS(xs, row, runparams);
+               break;
+       }
+}
+
+
+void Tabular::docbookRowAsHTML(XMLStream & xs, row_type row,
+                  OutputParams const & runparams, bool header) const
 {
        string const celltag = header ? "th" : "td";
        idx_type cell = getFirstCellInRow(row);
@@ -3521,6 +3533,14 @@ void Tabular::docbookRow(XMLStream & xs, row_type row,
 
                attr << "align='";
                switch (getAlignment(cell)) {
+               case LYX_ALIGN_BLOCK:
+                       attr << "justify";
+                       break;
+               case LYX_ALIGN_DECIMAL: {
+                       Language const *tlang = buffer().paragraphs().front().getParLanguage(buffer().params());
+                       attr << "char' char='" << to_utf8(tlang->decimalSeparator());
+               }
+                       break;
                case LYX_ALIGN_LEFT:
                        attr << "left";
                        break;
@@ -3557,7 +3577,77 @@ void Tabular::docbookRow(XMLStream & xs, row_type row,
                ++cell;
        }
        xs << xml::EndTag("tr");
-       xs<< xml::CR();
+       xs << xml::CR();
+}
+
+
+void Tabular::docbookRowAsCALS(XMLStream & xs, row_type row,
+                                OutputParams const & runparams) const
+{
+       idx_type cell = getFirstCellInRow(row);
+
+       xs << xml::StartTag("row");
+       xs << xml::CR();
+       for (col_type c = 0; c < ncols(); ++c) {
+               if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c))
+                       continue;
+
+               stringstream attr;
+
+               attr << "align='";
+               switch (getAlignment(cell)) {
+               case LYX_ALIGN_BLOCK:
+                       attr << "justify";
+                       break;
+               case LYX_ALIGN_DECIMAL: {
+                       Language const *tlang = buffer().paragraphs().front().getParLanguage(buffer().params());
+                       attr << "char' char='" << to_utf8(tlang->decimalSeparator());
+               }
+                       break;
+               case LYX_ALIGN_LEFT:
+                       attr << "left";
+                       break;
+               case LYX_ALIGN_RIGHT:
+                       attr << "right";
+                       break;
+
+               default:
+                       attr << "center";
+                       break;
+               }
+               attr << "'";
+               attr << " valign='";
+               switch (getVAlignment(cell)) {
+               case LYX_VALIGN_TOP:
+                       attr << "top";
+                       break;
+               case LYX_VALIGN_BOTTOM:
+                       attr << "bottom";
+                       break;
+               case LYX_VALIGN_MIDDLE:
+                       attr << "middle";
+               }
+               attr << "'";
+
+               if (isMultiColumn(cell))
+                       attr << " colspan='" << columnSpan(cell) << "'";
+               else if (isMultiRow(cell))
+                       attr << " rowspan='" << rowSpan(cell) << "'";
+               else
+                       attr << " colname='c" << (c + 1) << "'"; // Column numbering starts at 1.
+
+               // All cases where there should be a line *below* this row.
+               if (row_info[row].bottom_space_default)
+                       attr << " rowsep='1'";
+
+               xs << xml::StartTag("entry", attr.str(), true);
+               cellInset(cell)->docbook(xs, runparams);
+               xs << xml::EndTag("entry");
+               xs << xml::CR();
+               ++cell;
+       }
+       xs << xml::EndTag("row");
+       xs << xml::CR();
 }
 
 
@@ -3566,41 +3656,63 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
        docstring ret;
 
        // Some tables are inline. Likely limitation: cannot output a table within a table; is that really a limitation?
-       bool hasTableStarted = xs.isTagOpen(xml::StartTag("informaltable")) || xs.isTagOpen(xml::StartTag("table"));
-       if (!hasTableStarted) {
+       if (!runparams.docbook_in_table) { // Check on the *outer* set of parameters, so that the table can be closed
+               // properly at the end of this function.
                xs << xml::StartTag("informaltable");
                xs << xml::CR();
        }
 
-       // "Formal" tables have a caption and use the tag <table>; the distinction with <informaltable> is done outside.
+       // "Formal" tables have a title and use the tag <table>; the distinction with <informaltable> is done outside.
+       // HTML has the caption first with titles forbidden, and CALS has a title first.
        if (haveLTCaption()) {
-               xs << xml::StartTag("caption");
+               std::string tag = ((buffer().params().docbook_table_output) == BufferParams::HTMLTable) ? "caption" : "title";
+
+               xs << xml::StartTag(tag);
                for (row_type r = 0; r < nrows(); ++r)
                        if (row_info[r].caption)
                                docbookRow(xs, r, runparams);
-               xs << xml::EndTag("caption");
+               xs << xml::EndTag(tag);
                xs << xml::CR();
        }
 
-       // output header info
+       // CALS header: describe all columns in this table. For names, take 'c' then the ID of the column.
+       // Start at one, as is customary with CALS!
+       if (buffer().params().docbook_table_output == BufferParams::CALSTable) {
+               for (col_type c = 0; c < ncols(); ++c) {
+                       std::stringstream attr;
+                       attr << "colnum='" << (c + 1) << "' ";
+                       attr << "colname='c" << (c + 1) << "' ";
+                       Length const cwidth = column_info[c].p_width;
+                       if (!cwidth.zero())
+                               attr << "colwidth='" << cwidth.asHTMLString() << "' ";
+                       attr << "rowheader='norowheader'"; // Last attribute, hence no space at the end.
+
+                       xs << xml::CompTag("colspec", attr.str());
+                       xs << xml::CR();
+               }
+       }
+
+       // Output the header of the table. For both HTML and CALS, this is surrounded by a thead.
        bool const havefirsthead = haveLTFirstHead(false);
        // if we have a first head, then we are going to ignore the
        // headers for the additional pages, since there aren't any
-       // in XHTML. this test accomplishes that.
+       // in DocBook. this test accomplishes that.
        bool const havehead = !havefirsthead && haveLTHead(false);
        if (havehead || havefirsthead) {
                xs << xml::StartTag("thead") << xml::CR();
                for (row_type r = 0; r < nrows(); ++r) {
                        if (((havefirsthead && row_info[r].endfirsthead) ||
-                                (havehead && row_info[r].endhead)) &&
-                               !row_info[r].caption) {
-                               docbookRow(xs, r, runparams, true);
+                            (havehead && row_info[r].endhead)) &&
+                           !row_info[r].caption) {
+                               docbookRow(xs, r, runparams, true); // TODO: HTML vs CALS
                        }
                }
                xs << xml::EndTag("thead");
                xs << xml::CR();
        }
-       // output footer info
+
+       // Output the footer of the table. For both HTML and CALS, this is surrounded by a tfoot and output just after
+       // the header (and before the body).
        bool const havelastfoot = haveLTLastFoot(false);
        // as before.
        bool const havefoot = !havelastfoot && haveLTFoot(false);
@@ -3608,15 +3720,17 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
                xs << xml::StartTag("tfoot") << xml::CR();
                for (row_type r = 0; r < nrows(); ++r) {
                        if (((havelastfoot && row_info[r].endlastfoot) ||
-                                (havefoot && row_info[r].endfoot)) &&
-                               !row_info[r].caption) {
-                               docbookRow(xs, r, runparams);
+                            (havefoot && row_info[r].endfoot)) &&
+                           !row_info[r].caption) {
+                               docbookRow(xs, r, runparams); // TODO: HTML vs CALS
                        }
                }
                xs << xml::EndTag("tfoot");
                xs << xml::CR();
        }
 
+       // Output the main part of the table. The tbody container is mandatory for CALS, but optional for HTML (only if
+       // there is no header and no footer). It never hurts to have it, though.
        xs << xml::StartTag("tbody");
        xs << xml::CR();
        for (row_type r = 0; r < nrows(); ++r)
@@ -3625,7 +3739,8 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const
        xs << xml::EndTag("tbody");
        xs << xml::CR();
 
-       if (!hasTableStarted) {
+       // If this method started the table tag, also make it close it.
+       if (!runparams.docbook_in_table) {
                xs << xml::EndTag("informaltable");
                xs << xml::CR();
        }
@@ -4090,7 +4205,6 @@ InsetTableCell::InsetTableCell(Buffer * buf)
          isMultiColumn(false), isMultiRow(false), contentAlign(LYX_ALIGN_CENTER)
 {}
 
-
 bool InsetTableCell::forcePlainLayout(idx_type) const
 {
        return isMultiRow || (isMultiColumn && !isFixedWidth);
@@ -4249,6 +4363,18 @@ bool InsetTabular::insetAllowed(InsetCode code) const
 }
 
 
+bool InsetTabular::allowMultiPar() const
+{
+       for (col_type c = 0; c < tabular.ncols(); ++c) {
+               for (row_type r = 0; r < tabular.nrows(); ++r) {
+                       if (tabular.cellInset(r,c)->allowMultiPar())
+                               return true;
+               }
+       }
+       return false;
+}
+
+
 bool InsetTabular::allowsCaptionVariation(std::string const & newtype) const
 {
        return tabular.is_long_tabular &&
@@ -4384,7 +4510,7 @@ void InsetTabular::metrics(MetricsInfo & mi, Dimension & dim) const
 
                        // with LYX_VALIGN_BOTTOM the descent is relative to the last par
                        // = descent of text in last par + bottomOffset:
-                       int const lastpardes = tm.parMetrics(tm.lastPit()).descent()
+                       int const lastpardes = tm.last().second->descent()
                                + bottomOffset(mi.base.bv);
                        int offset = 0;
                        switch (tabular.getVAlignment(cell)) {
@@ -5626,8 +5752,8 @@ bool InsetTabular::getFeatureStatus(Cursor & cur, string const & s,
                case Tabular::SET_LONGTABULAR:
                case Tabular::TOGGLE_LONGTABULAR:
                        // setting as longtable is not allowed when table is inside a float
-                       if (cur.innerInsetOfType(FLOAT_CODE) != 0
-                               || cur.innerInsetOfType(WRAP_CODE) != 0)
+                       if (cur.innerInsetOfType(FLOAT_CODE) != nullptr
+                               || cur.innerInsetOfType(WRAP_CODE) != nullptr)
                                status.setEnabled(false);
                        else
                                status.setEnabled(true);
@@ -6099,7 +6225,7 @@ void InsetTabular::setCursorFromCoordinates(Cursor & cur, int x, int y) const
 }
 
 
-InsetTabular::idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int y) const
+idx_type InsetTabular::getNearestCell(BufferView & bv, int x, int y) const
 {
        idx_type idx_min = 0;
        int dist_min = numeric_limits<int>::max();
@@ -7062,7 +7188,7 @@ bool InsetTabular::copySelection(Cursor & cur)
        paste_tabular->setBuffer(tabular.buffer());
 
        odocstringstream os;
-       OutputParams const runparams(0);
+       OutputParams const runparams(nullptr);
        paste_tabular->plaintext(os, runparams, 0, true, '\t', INT_MAX);
        // Needed for the "Edit->Paste recent" menu and the system clipboard.
        cap::copySelection(cur, os.str());
@@ -7204,7 +7330,7 @@ ParagraphList InsetTabular::asParList(idx_type stidx, idx_type enidx)
        row_type const row2 = tabular.cellRow(enidx);
        for (col_type col = col1; col <= col2; col++)
                for (row_type row = row1; row <= row2; row++)
-                       for (auto par : tabular.cellInset(row, col)->paragraphs())
+                       for (auto const & par : tabular.cellInset(row, col)->paragraphs())
                                retval.push_back(par);
        return retval;
 }
@@ -7229,7 +7355,7 @@ void InsetTabular::getSelection(Cursor & cur,
 
 Text * InsetTabular::getText(int idx) const
 {
-       return size_t(idx) < nargs() ? cell(idx)->getText(0) : 0;
+       return size_t(idx) < nargs() ? cell(idx)->getText(0) : nullptr;
 }
 
 
@@ -7465,7 +7591,7 @@ bool InsetTabular::showCompletionCursor() const
 
 CompletionList const * InsetTabular::createCompletionList(Cursor const & cur) const
 {
-       return completionSupported(cur) ? cur.text()->createCompletionList(cur) : 0;
+       return completionSupported(cur) ? cur.text()->createCompletionList(cur) : nullptr;
 }
 
 
@@ -7534,8 +7660,8 @@ string InsetTabular::params2string(InsetTabular const & inset)
 
 void InsetTabular::setLayoutForHiddenCells(DocumentClass const & dc)
 {
-       for (Tabular::col_type c = 0; c < tabular.ncols(); ++c) {
-               for (Tabular::row_type r = 0; r < tabular.nrows(); ++r) {
+       for (col_type c = 0; c < tabular.ncols(); ++c) {
+               for (row_type r = 0; r < tabular.nrows(); ++r) {
                        if (!tabular.isPartOfMultiColumn(r,c) &&
                            !tabular.isPartOfMultiRow(r,c))
                                continue;