X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetTabular.cpp;h=69f9e73e59f0f0f11e125f2c80e4ba5449048455;hb=8124e6c02ea1fd6779bb6c47ffe2bca2c8bd2d97;hp=e2529a9fd0abe03b3ba1aefb0e370c26f5d4905d;hpb=8508c3fe04aa40bef4cc5099bda21a1c48e193cf;p=lyx.git diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index e2529a9fd0..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,31 +3628,63 @@ std::string Tabular::getVAlignAsXmlAttribute(idx_type cell) const } -std::string Tabular::getHAlignAsXmlAttribute(idx_type cell, const XmlOutputFormat output_format) 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 { 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 (output_format == XmlOutputFormat::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; @@ -3755,25 +3787,24 @@ docstring Tabular::xmlRow(XMLStream & xs, const row_type row, OutputParams const if (isPartOfMultiColumn(row, c) || isPartOfMultiRow(row, c)) continue; - stringstream attr; - - if (is_xhtml_table) { - const std::vector styles = computeCssStylePerCell(row, c, cell); - attr << "style='" ; - for (auto it = styles.begin(); it != styles.end(); ++it) { - attr << *it; - if (it != styles.end() - 1) - attr << "; "; - } - 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_cals_table) { if (!cals_row_has_rowsep && bottomLine(cell)) attr << "rowsep='1' "; } - attr << getHAlignAsXmlAttribute(cell, output_format) << " " << 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)) @@ -3789,8 +3820,26 @@ docstring Tabular::xmlRow(XMLStream & xs, const row_type row, OutputParams const 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); + + 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); + xs << xml::StartTag(cell_tag, attr_str, true); if (output_format == XmlOutputFormat::XHTML) { ret += cellInset(cell)->xhtml(xs, runparams); } else if (output_format == XmlOutputFormat::DOCBOOK) { @@ -4272,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 @@ -7452,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++) { @@ -7473,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())