X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetTabular.cpp;h=69f9e73e59f0f0f11e125f2c80e4ba5449048455;hb=8124e6c02ea1fd6779bb6c47ffe2bca2c8bd2d97;hp=8c571d655a7850087c0036bf8991979a1ebed9cb;hpb=72f630cb8f370f2ab2b600be7c16f49fd8f1f276;p=lyx.git diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 8c571d655a..69f9e73e59 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -3007,7 +3007,7 @@ void Tabular::TeXCellPreamble(otexstream & os, idx_type cell, << "}\n"; } else if (getUsebox(cell) == BOX_VARWIDTH && (getRotateCell(cell) != 0 || align != LYX_ALIGN_LEFT - || valign != LYX_VALIGN_TOP)) { + || valign != LYX_VALIGN_TOP || hasNewlines(cell))) { os << "\\begin{cellvarwidth}["; switch (valign) { case LYX_VALIGN_TOP: @@ -3056,7 +3056,7 @@ void Tabular::TeXCellPostamble(otexstream & os, idx_type cell, os << breakln << "\\end{minipage}"; else if (getUsebox(cell) == BOX_VARWIDTH && (getRotateCell(cell) != 0 || getAlignment(cell) != LYX_ALIGN_LEFT - || getVAlignment(cell) != LYX_VALIGN_TOP)) + || getVAlignment(cell) != LYX_VALIGN_TOP || hasNewlines(cell))) os << breakln << "\\end{cellvarwidth}"; if (getRotateCell(cell) != 0) os << breakln << "\\end{turn}"; @@ -3208,7 +3208,7 @@ void Tabular::TeXRow(otexstream & os, row_type row, bool rtl = par.isRTL(buffer().params()) && !par.empty() && getPWidth(cell).zero() - && !runparams.use_polyglossia; + && !runparams.isFullUnicode(); if (rtl) { string const lang = @@ -3272,7 +3272,7 @@ void Tabular::TeXRow(otexstream & os, row_type row, } else if (!isPartOfMultiRow(row, c)) { if (!runparams.nice) os.texrow().start(par.id(), 0); - if (isMultiRow(cell) && !LaTeXFeatures::isAvailable("multirow-2021/01/29")) + if (isMultiRow(cell) && !LaTeXFeatures::isAvailableAtLeastFrom("multirow", 2021, 1, 29)) newrp.isNonLong = true; inset->latex(os, newrp); } @@ -3628,76 +3628,221 @@ std::string Tabular::getVAlignAsXmlAttribute(idx_type cell) const } -std::string Tabular::getHAlignAsXmlAttribute(idx_type cell, bool is_xhtml) const +std::string Tabular::getVAlignAsCssAttribute(idx_type cell) const +{ + switch (getVAlignment(cell)) { + case LYX_VALIGN_TOP: + return "vertical-align: top"; + case LYX_VALIGN_BOTTOM: + return "vertical-align: bottom"; + case LYX_VALIGN_MIDDLE: + return "vertical-align: middle"; + default: + // This case only silences a compiler warning, as all the cases are covered above. + return ""; + } +} + + +std::string Tabular::getHAlignAsXmlAttribute(idx_type cell) const { - // TODO: the Boolean flag isn't really clean; switch to an enum at some point. switch (getAlignment(cell)) { case LYX_ALIGN_LEFT: return "align='left'"; case LYX_ALIGN_RIGHT: return "align='right'"; + case LYX_ALIGN_BLOCK: + return "align='justify'"; + case LYX_ALIGN_DECIMAL: { + Language const *lang = buffer().paragraphs().front().getParLanguage(buffer().params()); + return "align='char' char='" + to_utf8(lang->decimalSeparator()) + "'"; + } + default: + return "align='center'"; + } +} + +std::string Tabular::getHAlignAsCssAttribute(idx_type cell) const +{ + switch (getAlignment(cell)) { + case LYX_ALIGN_LEFT: + return "text-align: left"; + case LYX_ALIGN_RIGHT: + return "text-align: right"; + case LYX_ALIGN_BLOCK: + return "text-align: justify"; + case LYX_ALIGN_DECIMAL: { + // In theory, character-level alignment is supported for CSS4, but it's + // experimental. + // https://www.w3.org/TR/css-text-4/#character-alignment + Language const *lang = buffer().paragraphs().front().getParLanguage(buffer().params()); + return "text-align: \"" + to_utf8(lang->decimalSeparator()) + "\""; + } default: - // HTML only supports left, right, and center. - if (is_xhtml) - return "align='center'"; - - // DocBook also has justify and decimal. - if (getAlignment(cell) == LYX_ALIGN_BLOCK) { - return "align='justify'"; - } else if (getAlignment(cell) == LYX_ALIGN_DECIMAL) { - Language const *tlang = buffer().paragraphs().front().getParLanguage(buffer().params()); - return "align='char' char='" + to_utf8(tlang->decimalSeparator()) + "'"; - } else { - return "align='center'"; + return "text-align: center"; + } +} + + +Tabular::XmlRowWiseBorders Tabular::computeXmlBorders(row_type row) const +{ + Tabular::XmlRowWiseBorders borders; + + // Determine whether borders are required. + for (col_type c = 0; c < ncols(); ++c) { + if (row < nrows() - 1) { + if (!bottomLine(cellIndex(row, c)) + || !topLine(cellIndex(row + 1, c))) { + borders.completeBorder = false; + } + if (!bottomLine(cellIndex(row, c)) + && !topLine(cellIndex(row + 1, c))) { + borders.completeBorderBelow = false; + } + } else if (row == nrows() - 1 && !bottomLine(cellIndex(row, c))) { + borders.completeBorderBelow = false; + } + + if ((row > 0 && !bottomLine(cellIndex(row - 1, c)) && !topLine(cellIndex(row, c))) || + (row == 0 && !topLine(cellIndex(row, c)))) { + borders.completeBorderAbove = false; + } + } + + // Size of booktabs borders. + if (use_booktabs) { + if (borders.completeBorderAbove) + borders.borderTopWidth = row == 0 ? 2 : 1.5; + if (borders.completeBorderBelow) { + borders.borderBottomWidth = row == nrows() - 1 ? 2 : 1.5; + borders.borderBottomWidthComplete = 3 * borders.borderBottomWidth; } } + + return borders; } -docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & runparams, - bool header, bool is_xhtml, BufferParams::TableOutput docbook_table_output) const +std::vector Tabular::computeCssStylePerCell(row_type row, col_type col, idx_type cell) const { - docstring ret; + std::vector styles; + + // Fixed width. + Length const col_width = column_info[col].p_width; + if (!col_width.zero()) + styles.emplace_back("width: " + col_width.asHTMLString()); + + // Borders and booktabs. + const Tabular::XmlRowWiseBorders borders = computeXmlBorders(row); + + if (bottomLine(cell)) { + if (row < nrows() - 1 && borders.completeBorder) + styles.emplace_back("border-bottom: " + to_string(borders.borderBottomWidthComplete) + "px double"); + else + styles.emplace_back("border-bottom: " + to_string(borders.borderBottomWidth) + "px solid"); + } + if (rightLine(cell)) { + if (col < ncols() - 1 && leftLine(cell + 1)) + styles.emplace_back("border-right: 3px double"); + else + styles.emplace_back("border-right: 1px solid"); + } + if (leftLine(cell)) + styles.emplace_back("border-left: 1px solid"); + if (topLine(cell)) + styles.emplace_back("border-top: " + to_string(borders.borderTopWidth) + "px solid"); + + return styles; +} + - std::string const row_tag = (is_xhtml || docbook_table_output == BufferParams::TableOutput::HTMLTable) ? "tr" : "row"; - std::string const cell_tag = (is_xhtml || docbook_table_output == BufferParams::TableOutput::HTMLTable) ? (header ? "th" : "td") : "entry"; +docstring Tabular::xmlRow(XMLStream & xs, const row_type row, OutputParams const & runparams, + const bool header, const XmlOutputFormat output_format, BufferParams::TableOutput docbook_table_output) const +{ + docstring ret; + const bool is_xhtml_table = output_format == XmlOutputFormat::XHTML || + docbook_table_output == BufferParams::TableOutput::HTMLTable; + const bool is_cals_table = output_format == XmlOutputFormat::DOCBOOK && + docbook_table_output == BufferParams::TableOutput::CALSTable; + + std::string const row_tag = is_xhtml_table ? "tr" : "row"; + std::string const cell_tag = is_xhtml_table ? (header ? "th" : "td") : "entry"; + Tabular::XmlRowWiseBorders const borders = computeXmlBorders(row); idx_type cell = getFirstCellInRow(row); - xs << xml::StartTag(row_tag); + std::string row_attr; + bool cals_row_has_rowsep = false; // TODO: is this required? Is it possible that only a/several cells request a row separator, but not the complete row? + // CALS only: all cases where there should be a line *below* this row. + if (is_cals_table && (row_info[row].bottom_space_default || bottomLine(cell))) { + if (borders.completeBorderBelow) { + row_attr = "rowsep='1'"; + cals_row_has_rowsep = true; + } + } + + xs << xml::StartTag(row_tag, row_attr); xs << xml::CR(); - for (col_type c = 0; c < ncols(); ++c) { + for (col_type c = 0; c < ncols(); ++c, ++cell) { if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c)) continue; - stringstream attr; + stringstream attr; // Tag-level attributes, both for HTML and CALS. + stringstream style; // Tag-level CSS, only for HTML tables output in HTML. - if (is_xhtml || docbook_table_output == BufferParams::TableOutput::HTMLTable) { - Length const cwidth = column_info[c].p_width; - if (!cwidth.zero()) { - string const hwidth = cwidth.asHTMLString(); - attr << "style='width: " << hwidth << ";' "; - } + if (is_cals_table) { + if (!cals_row_has_rowsep && bottomLine(cell)) + attr << "rowsep='1' "; } - attr << getHAlignAsXmlAttribute(cell, false) << " " << getVAlignAsXmlAttribute(cell); + if (output_format == XmlOutputFormat::XHTML) { + // In HTML5, prefer to use CSS instead of attributes for alignment + // (align and valign). + style << getHAlignAsCssAttribute(cell) << "; " + << getVAlignAsCssAttribute(cell); + } else { + // In DocBook, both for HTML and CALS tables, stick to attributes. + attr << getHAlignAsXmlAttribute(cell) << " " + << getVAlignAsXmlAttribute(cell); + } + + if (is_xhtml_table) { + if (isMultiColumn(cell)) + attr << " colspan='" << columnSpan(cell) << "'"; + else if (isMultiRow(cell)) + attr << " rowspan='" << rowSpan(cell) << "'"; + } else if (is_cals_table) { + if (isMultiColumn(cell)) + attr << " namest='c" << c << " nameend='c" << (c + columnSpan(cell)) << "'"; + else if (isMultiRow(cell)) + attr << " morerows='" << rowSpan(cell) << "'"; + else + attr << " colname='c" << (c + 1) << "'"; // CALS column numbering starts at 1. + } - if (isMultiColumn(cell)) - attr << " colspan='" << columnSpan(cell) << "'"; - else if (isMultiRow(cell)) - attr << " rowspan='" << rowSpan(cell) << "'"; - else if (!is_xhtml && docbook_table_output == BufferParams::TableOutput::CALSTable) - attr << " colname='c" << (c + 1) << "'"; // CALS column numbering starts at 1. + // Final step: prepend the CSS style. + std::string attr_str = attr.str(); + if (is_xhtml_table) { + const std::vector styles = computeCssStylePerCell(row, c, cell); - // All cases where there should be a line *below* this row. - if (!is_xhtml && docbook_table_output == BufferParams::TableOutput::CALSTable && row_info[row].bottom_space_default) - attr << " rowsep='1'"; + std::string attr_str_prefix = "style='" + style.str(); + if (!styles.empty()) + attr_str_prefix += "; "; + for (auto it = styles.begin(); it != styles.end(); ++it) { + attr_str_prefix += *it; + if (it != styles.end() - 1) + attr_str_prefix += "; "; + } + attr_str_prefix += "' "; + + attr_str.insert(0, attr_str_prefix); + } // Render the cell as either XHTML or DocBook. - xs << xml::StartTag(cell_tag, attr.str(), true); - if (is_xhtml) { + xs << xml::StartTag(cell_tag, attr_str, true); + if (output_format == XmlOutputFormat::XHTML) { ret += cellInset(cell)->xhtml(xs, runparams); - } else { + } else if (output_format == XmlOutputFormat::DOCBOOK) { // DocBook: no return value for this function. OutputParams rp = runparams; rp.docbook_in_par = false; @@ -3706,7 +3851,6 @@ docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & run } xs << xml::EndTag(cell_tag); xs << xml::CR(); - ++cell; } xs << xml::EndTag(row_tag); xs << xml::CR(); @@ -3715,6 +3859,66 @@ docstring Tabular::xmlRow(XMLStream & xs, row_type row, OutputParams const & run } +void Tabular::xmlHeader(XMLStream & xs, OutputParams const & runparams, const XmlOutputFormat output_format) const +{ + // Output the header of the table. For both HTML and CALS, this is surrounded by a thead. + bool const have_first_head = 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 HTML or DocBook. + bool const have_head = !have_first_head && haveLTHead(false); + + if (have_head || have_first_head) { + xs << xml::StartTag("thead") << xml::CR(); + for (row_type r = 0; r < nrows(); ++r) { + if (((have_first_head && row_info[r].endfirsthead) || + (have_head && row_info[r].endhead)) && + !row_info[r].caption) { + xmlRow(xs, r, runparams, true, output_format, buffer().params().docbook_table_output); + } + } + xs << xml::EndTag("thead"); + xs << xml::CR(); + } +} + + +void Tabular::xmlFooter(XMLStream & xs, OutputParams const & runparams, const XmlOutputFormat output_format) const +{ + // 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 have_last_foot = haveLTLastFoot(false); + bool const have_foot = !have_last_foot && haveLTFoot(false); + + if (have_foot || have_last_foot) { + xs << xml::StartTag("tfoot") << xml::CR(); + for (row_type r = 0; r < nrows(); ++r) { + if (((have_last_foot && row_info[r].endlastfoot) || + (have_foot && row_info[r].endfoot)) && + !row_info[r].caption) { + xmlRow(xs, r, runparams, false, output_format, buffer().params().docbook_table_output); + } + } + xs << xml::EndTag("tfoot"); + xs << xml::CR(); + } +} + + +void Tabular::xmlBody(XMLStream & xs, OutputParams const & runparams, const XmlOutputFormat output_format) const +{ + // 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) + if (isValidRow(r)) + xmlRow(xs, r, runparams, false, output_format, buffer().params().docbook_table_output); + xs << xml::EndTag("tbody"); + xs << xml::CR(); +} + + void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const { // Some tables are inline. Likely limitation: cannot output a table within a table; is that really a limitation? @@ -3727,13 +3931,13 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const // "Formal" tables have a title and use the tag ; the distinction with is done outside. // HTML has the caption first with titles forbidden, and CALS has a title first. if (haveLTCaption()) { - std::string tag = ((buffer().params().docbook_table_output) == BufferParams::HTMLTable) ? "caption" : "title"; + std::string caption_tag = ((buffer().params().docbook_table_output) == BufferParams::HTMLTable) ? "caption" : "title"; - xs << xml::StartTag(tag); + xs << xml::StartTag(caption_tag); for (row_type r = 0; r < nrows(); ++r) if (row_info[r].caption) - xmlRow(xs, r, runparams, false, false, buffer().params().docbook_table_output); - xs << xml::EndTag(tag); + xmlRow(xs, r, runparams, false, XmlOutputFormat::DOCBOOK, buffer().params().docbook_table_output); + xs << xml::EndTag(caption_tag); xs << xml::CR(); } @@ -3754,52 +3958,9 @@ void Tabular::docbook(XMLStream & xs, OutputParams const & runparams) const } } - // 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 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) { - xmlRow(xs, r, runparams, true, false, buffer().params().docbook_table_output); - } - } - xs << xml::EndTag("thead"); - xs << xml::CR(); - } - - // 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); - if (havefoot || havelastfoot) { - 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) { - xmlRow(xs, r, runparams, false, false, buffer().params().docbook_table_output); - } - } - 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) - if (isValidRow(r)) - xmlRow(xs, r, runparams, false, false, buffer().params().docbook_table_output); - xs << xml::EndTag("tbody"); - xs << xml::CR(); + xmlHeader(xs, runparams, XmlOutputFormat::DOCBOOK); + xmlFooter(xs, runparams, XmlOutputFormat::DOCBOOK); + xmlBody(xs, runparams, XmlOutputFormat::DOCBOOK); // If this method started the table tag, also make it close it. if (!runparams.docbook_in_table) { @@ -3814,7 +3975,7 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const docstring ret; if (is_long_tabular) { - // we'll wrap it in a div, so as to deal with alignment + // We'll wrap it in a div to deal with alignment. string align; switch (longtabular_alignment) { case LYX_LONGTABULAR_ALIGN_LEFT: @@ -3829,13 +3990,14 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const } xs << xml::StartTag("div", "class='longtable' style='text-align: " + align + ";'"); xs << xml::CR(); - // The caption flag wins over head/foot + + // The caption flag is output before header/footer. if (haveLTCaption()) { xs << xml::StartTag("div", "class='longtable-caption' style='text-align: " + align + ";'"); xs << xml::CR(); for (row_type r = 0; r < nrows(); ++r) if (row_info[r].caption) - ret += xmlRow(xs, r, runparams); + ret += xmlRow(xs, r, runparams, false, XmlOutputFormat::XHTML); xs << xml::EndTag("div"); xs << xml::CR(); } @@ -3844,48 +4006,10 @@ docstring Tabular::xhtml(XMLStream & xs, OutputParams const & runparams) const xs << xml::StartTag("table"); xs << xml::CR(); - // output header info - 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. - bool const havehead = !havefirsthead && haveLTHead(false); - if (havehead || havefirsthead) { - xs << xml::StartTag("thead"); - xs << 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) { - ret += xmlRow(xs, r, runparams, true); - } - } - xs << xml::EndTag("thead"); - xs << xml::CR(); - } - // output footer info - bool const havelastfoot = haveLTLastFoot(false); - // as before. - bool const havefoot = !havelastfoot && haveLTFoot(false); - if (havefoot || havelastfoot) { - 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) { - ret += xmlRow(xs, r, runparams); - } - } - xs << xml::EndTag("tfoot"); - xs << xml::CR(); - } + xmlHeader(xs, runparams, XmlOutputFormat::XHTML); + xmlFooter(xs, runparams, XmlOutputFormat::XHTML); + xmlBody(xs, runparams, XmlOutputFormat::XHTML); - xs << xml::StartTag("tbody") << xml::CR(); - for (row_type r = 0; r < nrows(); ++r) - if (isValidRow(r)) - ret += xmlRow(xs, r, runparams); - xs << xml::EndTag("tbody"); - xs << xml::CR(); xs << xml::EndTag("table"); xs << xml::CR(); if (is_long_tabular) { @@ -4197,6 +4321,21 @@ Tabular::BoxType Tabular::useBox(idx_type cell) const } +bool Tabular::hasNewlines(idx_type cell) const +{ + ParagraphList const & parlist = cellInset(cell)->paragraphs(); + ParagraphList::const_iterator cit = parlist.begin(); + ParagraphList::const_iterator end = parlist.end(); + + for (; cit != end; ++cit) + for (int i = 0; i < cit->size(); ++i) + if (cit->isNewline(i)) + return true; + + return false; +} + + ///////////////////////////////////////////////////////////////////// // // InsetTableCell @@ -4970,7 +5109,9 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) if (bvcur.selIsMultiCell()) { bvcur.pit() = bvcur.lastpit(); bvcur.pos() = bvcur.lastpos(); - } + } else + // Let InsetTableCell do it + cell(cur.idx())->dispatch(cur, cmd); } break; @@ -5323,6 +5464,7 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHANGE_ACCEPT: case LFUN_CHANGE_REJECT: + case LFUN_FONT_DEFAULT: case LFUN_FONT_EMPH: case LFUN_FONT_BOLD: case LFUN_FONT_BOLDSYMBOL: @@ -7374,10 +7516,15 @@ docstring InsetTabular::asString(idx_type stidx, idx_type enidx, { LASSERT(stidx <= enidx, return docstring()); docstring retval; - col_type const col1 = tabular.cellColumn(stidx); - col_type const col2 = tabular.cellColumn(enidx); - row_type const row1 = tabular.cellRow(stidx); - row_type const row2 = tabular.cellRow(enidx); + col_type col1 = tabular.cellColumn(stidx); + col_type col2 = tabular.cellColumn(enidx); + row_type row1 = tabular.cellRow(stidx); + row_type row2 = tabular.cellRow(enidx); + // stidx might be in a later column or row than enidx + if (col1 > col2) + swap(col1, col2); + if (row1 > row2) + swap(row1, row2); bool first = true; for (col_type col = col1; col <= col2; col++) for (row_type row = row1; row <= row2; row++) { @@ -7395,10 +7542,15 @@ ParagraphList InsetTabular::asParList(idx_type stidx, idx_type enidx) { LASSERT(stidx <= enidx, return ParagraphList()); ParagraphList retval; - col_type const col1 = tabular.cellColumn(stidx); - col_type const col2 = tabular.cellColumn(enidx); - row_type const row1 = tabular.cellRow(stidx); - row_type const row2 = tabular.cellRow(enidx); + col_type col1 = tabular.cellColumn(stidx); + col_type col2 = tabular.cellColumn(enidx); + row_type row1 = tabular.cellRow(stidx); + row_type row2 = tabular.cellRow(enidx); + // stidx might be in a later column or row than enidx + if (col1 > col2) + swap(col1, col2); + if (row1 > row2) + swap(row1, row2); for (col_type col = col1; col <= col2; col++) for (row_type row = row1; row <= row2; row++) for (auto const & par : tabular.cellInset(row, col)->paragraphs()) @@ -7669,12 +7821,12 @@ docstring InsetTabular::completionPrefix(Cursor const & cur) const } -bool InsetTabular::insertCompletion(Cursor & cur, docstring const & s, bool finished) +bool InsetTabular::insertCompletion(Cursor & cur, docstring const & s, bool /*finished*/) { if (!completionSupported(cur)) return false; - return cur.text()->insertCompletion(cur, s, finished); + return cur.text()->insertCompletion(cur, s); }