diff options
Diffstat (limited to 'sw/source/filter/html/htmltabw.cxx')
-rw-r--r-- | sw/source/filter/html/htmltabw.cxx | 414 |
1 files changed, 208 insertions, 206 deletions
diff --git a/sw/source/filter/html/htmltabw.cxx b/sw/source/filter/html/htmltabw.cxx index af5f67922bed..b1ef282396a0 100644 --- a/sw/source/filter/html/htmltabw.cxx +++ b/sw/source/filter/html/htmltabw.cxx @@ -63,12 +63,20 @@ class SwHTMLWrtTable : public SwWriteTable static void Pixelize( sal_uInt16& rValue ); void PixelizeBorders(); + /// Writes a single table cell. + /// + /// bCellRowSpan decides if the cell's row span should be written or not. void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const; + bool bOutVAlign, + bool bCellRowSpan ) const; + /// Writes a single table row. + /// + /// rSkipRows decides if the next N rows should be skipped or written. void OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const; + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const; virtual bool ShouldExpandSub( const SwTableBox *pBox, bool bExpandedBefore, sal_uInt16 nDepth ) const override; @@ -111,14 +119,9 @@ SwHTMLWrtTable::SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo ) void SwHTMLWrtTable::Pixelize( sal_uInt16& rValue ) { - if( rValue && Application::GetDefaultDevice() ) + if( rValue ) { - Size aSz( rValue, 0 ); - aSz = Application::GetDefaultDevice()->LogicToPixel( aSz, MapMode(MapUnit::MapTwip) ); - if( !aSz.Width() ) - aSz.setWidth( 1 ); - aSz = Application::GetDefaultDevice()->PixelToLogic( aSz, MapMode(MapUnit::MapTwip) ); - rValue = static_cast<sal_uInt16>(aSz.Width()); + rValue = o3tl::convert(SwHTMLWriter::ToPixel(rValue), o3tl::Length::px, o3tl::Length::twip); } } @@ -143,8 +146,8 @@ bool SwHTMLWrtTable::HasTabBackground( const SwTableBox& rBox, /// The table box has a background, if its background color is not "no fill"/ /// "auto fill" or it has a background graphic. - bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT || - !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic()); + bRet = aBrushItem->GetColor() != COL_TRANSPARENT || + !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic(); } else { @@ -172,8 +175,8 @@ bool SwHTMLWrtTable::HasTabBackground( const SwTableLine& rLine, std::unique_ptr<SvxBrushItem> aBrushItem = rLine.GetFrameFormat()->makeBackgroundBrushItem(); /// The table line has a background, if its background color is not "no fill"/ /// "auto fill" or it has a background graphic. - bool bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT || - !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic()); + bool bRet = aBrushItem->GetColor() != COL_TRANSPARENT || + !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic(); if( !bRet ) { @@ -254,7 +257,8 @@ bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox, // Write a box as single cell void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const + bool bOutVAlign, + bool bCellRowSpan ) const { const SwTableBox *pBox = pCell->GetBox(); sal_uInt16 nRow = pCell->GetRow(); @@ -269,7 +273,7 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, bool bHead = false; if( pSttNd ) { - sal_uLong nNdPos = pSttNd->GetIndex()+1; + SwNodeOffset nNdPos = pSttNd->GetIndex()+1; // determine the type of cell (TD/TH) SwNode* pNd; @@ -301,13 +305,12 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, } rWrt.OutNewLine(); // <TH>/<TD> in new line - OStringBuffer sOut; - sOut.append('<'); + OStringBuffer sOut("<"); OString aTag(bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata); sOut.append(rWrt.GetNamespace() + aTag); // output ROW- and COLSPAN - if( nRowSpan>1 ) + if (nRowSpan > 1 && bCellRowSpan) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan "=\"" + OString::number(nRowSpan) + "\""); @@ -350,19 +353,7 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, tools::Long nHeight = pCell->GetHeight() > 0 ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan ) : 0; - Size aPixelSz( nWidth, nHeight ); - - // output WIDTH (Argh: only for Netscape) - if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() ) - { - Size aOldSz( aPixelSz ); - aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz, - MapMode(MapUnit::MapTwip) ); - if( aOldSz.Width() && !aPixelSz.Width() ) - aPixelSz.setWidth( 1 ); - if( aOldSz.Height() && !aPixelSz.Height() ) - aPixelSz.setHeight( 1 ); - } + Size aPixelSz(SwHTMLWriter::ToPixel(nWidth), SwHTMLWriter::ToPixel(nHeight)); // output WIDTH: from layout or calculated if( bOutWidth ) @@ -370,7 +361,7 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\""); if( nPercentWidth != SAL_MAX_UINT32 ) { - sOut.append(static_cast<sal_Int32>(nPercentWidth)).append('%'); + sOut.append(OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%"); } else { @@ -392,7 +383,6 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, } const SfxItemSet& rItemSet = pBox->GetFrameFormat()->GetAttrSet(); - const SfxPoolItem *pItem; // ALIGN is only outputted at the paragraphs from now on @@ -410,15 +400,12 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, } } - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.m_bTextAttr = false; rWrt.m_bOutOpts = true; - const SvxBrushItem *pBrushItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) - { - pBrushItem = static_cast<const SvxBrushItem *>(pItem); - } + const SvxBrushItem *pBrushItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ); if( !pBrushItem ) pBrushItem = pCell->GetBackground(); @@ -429,37 +416,40 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, // Avoid non-CSS version in the ReqIF case. rWrt.OutBackground( pBrushItem, false ); - if( rWrt.m_bCfgOutStyles ) - OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem ); + if (!rWrt.m_bCfgOutStyles) + pBrushItem = nullptr; } - rWrt.OutCSS1_TableCellBorderHack(*pBox->GetFrameFormat()); + // tdf#132739 with rWrt.m_bCfgOutStyles of true bundle the brush item css + // properties into the same "style" tag as the borders so there is only one + // style tag + rWrt.OutCSS1_TableCellBordersAndBG(*pBox->GetFrameFormat(), pBrushItem); sal_uInt32 nNumFormat = 0; double nValue = 0.0; bool bNumFormat = false, bValue = false; - if( SfxItemState::SET==rItemSet.GetItemState( RES_BOXATR_FORMAT, false, &pItem ) ) + if( const SwTableBoxNumFormat* pItem = rItemSet.GetItemIfSet( RES_BOXATR_FORMAT, false ) ) { - nNumFormat = static_cast<const SwTableBoxNumFormat *>(pItem)->GetValue(); + nNumFormat = pItem->GetValue(); bNumFormat = true; } - if( SfxItemState::SET==rItemSet.GetItemState( RES_BOXATR_VALUE, false, &pItem ) ) + if( const SwTableBoxValue* pItem = rItemSet.GetItemIfSet( RES_BOXATR_VALUE, false ) ) { - nValue = static_cast<const SwTableBoxValue *>(pItem)->GetValue(); + nValue = pItem->GetValue(); bValue = true; if( !bNumFormat ) nNumFormat = pBox->GetFrameFormat()->GetTableBoxNumFormat().GetValue(); } - if( bNumFormat || bValue ) + if ((bNumFormat || bValue) && !rWrt.mbXHTML) { sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValue, nValue, - nNumFormat, *rWrt.m_pDoc->GetNumberFormatter(), rWrt.m_eDestEnc, - &rWrt.m_aNonConvertableCharacters)); + nNumFormat, *rWrt.m_pDoc->GetNumberFormatter())); } sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - rWrt.m_bLFPossible = true; + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + rWrt.SetLFPossible(true); rWrt.IncIndentLevel(); // indent the content of <TD>...</TD> @@ -496,17 +486,18 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, rWrt.DecIndentLevel(); // indent the content of <TD>...</TD> - if( rWrt.m_bLFPossible ) + if (rWrt.IsLFPossible()) rWrt.OutNewLine(); aTag = bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rWrt.GetNamespace() + aTag), false); - rWrt.m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); + rWrt.SetLFPossible(true); } // output a line as lines void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const { // If the line contains more the one cell and all cells have the same // alignment, then output the VALIGN at the line instead of the cell. @@ -529,14 +520,17 @@ void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, } rWrt.OutNewLine(); // <TR> in new line - rWrt.Strm().WriteChar( '<' ).WriteOString( OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow) ); + rWrt.Strm().WriteChar( '<' ).WriteOString( Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow) ); if( pBrushItem ) { - rWrt.OutBackground( pBrushItem, false ); + if (!rWrt.mbXHTML) + { + rWrt.OutBackground(pBrushItem, false); + } rWrt.m_bTextAttr = false; rWrt.m_bOutOpts = true; - if( rWrt.m_bCfgOutStyles ) + if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML) OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem ); } @@ -546,22 +540,40 @@ void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign "=\"").append(text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) .append("\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); } rWrt.Strm().WriteChar( '>' ); rWrt.IncIndentLevel(); // indent content of <TR>...</TR> + bool bCellRowSpan = true; + if (!rCells.empty() && rCells[0]->GetRowSpan() > 1) + { + // Skip the rowspan attrs of <td> elements if they are the same for every cell of this row. + bCellRowSpan = std::adjacent_find(rCells.begin(), rCells.end(), + [](const std::unique_ptr<SwWriteTableCell>& pA, + const std::unique_ptr<SwWriteTableCell>& pB) + { return pA->GetRowSpan() != pB->GetRowSpan(); }) + != rCells.end(); + if (!bCellRowSpan) + { + // If no rowspan is written, then skip rows which would only contain covered cells, but + // not the current row. + rSkipRows = rCells[0]->GetRowSpan() - 1; + } + } + for (const auto &rpCell : rCells) { - OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri); + OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri, bCellRowSpan); } rWrt.DecIndentLevel(); // indent content of <TR>...</TR> rWrt.OutNewLine(); // </TR> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), false ); } void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, @@ -572,55 +584,47 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, // determine value of RULES bool bRowsHaveBorder = false; bool bRowsHaveBorderOnly = true; - SwWriteTableRow *pRow = m_aRows[0].get(); - for( SwWriteTableRows::size_type nRow=1; nRow < m_aRows.size(); ++nRow ) + assert(m_aRows.begin() != m_aRows.end()); + for (auto row = m_aRows.begin(), next = std::next(row); next < m_aRows.end(); ++row, ++next) { - SwWriteTableRow *pNextRow = m_aRows[nRow].get(); - bool bBorder = ( pRow->bBottomBorder || pNextRow->bTopBorder ); + SwWriteTableRow* pRow = row->get(); + SwWriteTableRow* pNextRow = next->get(); + bool bBorder = ( pRow->HasBottomBorder() || pNextRow->HasTopBorder() ); bRowsHaveBorder |= bBorder; bRowsHaveBorderOnly &= bBorder; - sal_uInt16 nBorder2 = pRow->bBottomBorder ? pRow->nBottomBorder : USHRT_MAX; - if( pNextRow->bTopBorder && pNextRow->nTopBorder < nBorder2 ) - nBorder2 = pNextRow->nTopBorder; - - pRow->bBottomBorder = bBorder; - pRow->nBottomBorder = nBorder2; - - pNextRow->bTopBorder = bBorder; - pNextRow->nTopBorder = nBorder2; - - pRow = pNextRow; + pRow->SetBottomBorder(bBorder); + pNextRow->SetTopBorder(bBorder); } bool bColsHaveBorder = false; bool bColsHaveBorderOnly = true; - SwWriteTableCol *pCol = m_aCols[0].get(); - for( SwWriteTableCols::size_type nCol=1; nCol<m_aCols.size(); ++nCol ) + assert(m_aCols.begin() != m_aCols.end()); + for (auto col = m_aCols.begin(), next = std::next(col); next < m_aCols.end(); ++col, ++next) { - SwWriteTableCol *pNextCol = m_aCols[nCol].get(); - bool bBorder = ( pCol->bRightBorder || pNextCol->bLeftBorder ); + SwWriteTableCol* pCol = col->get(); + SwWriteTableCol* pNextCol = next->get(); + bool bBorder = ( pCol->m_bRightBorder || pNextCol->m_bLeftBorder ); bColsHaveBorder |= bBorder; bColsHaveBorderOnly &= bBorder; - pCol->bRightBorder = bBorder; - pNextCol->bLeftBorder = bBorder; - pCol = pNextCol; + pCol->m_bRightBorder = bBorder; + pNextCol->m_bLeftBorder = bBorder; } // close previous numbering, etc rWrt.ChangeParaToken( HtmlTokenId::NONE ); - if( rWrt.m_bLFPossible ) + if (rWrt.IsLFPossible()) rWrt.OutNewLine(); // <TABLE> in new line - OStringBuffer sOut; - sOut.append('<').append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table); + OStringBuffer sOut("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table); const SvxFrameDirection nOldDirection = rWrt.m_nDirection; if( pFrameFormat ) rWrt.m_nDirection = rWrt.GetHTMLDirection( pFrameFormat->GetAttrSet() ); if( rWrt.m_bOutFlyFrame || nOldDirection != rWrt.m_nDirection ) { - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.OutDirection( rWrt.m_nDirection ); } @@ -646,68 +650,58 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\""); if( HasRelWidths() ) - sOut.append(static_cast<sal_Int32>(m_nTabWidth)).append('%'); - else if( Application::GetDefaultDevice() ) - { - sal_Int32 nPixWidth = Application::GetDefaultDevice()->LogicToPixel( - Size(m_nTabWidth,0), MapMode(MapUnit::MapTwip) ).Width(); - if( !nPixWidth ) - nPixWidth = 1; - - sOut.append(nPixWidth); - } + sOut.append(OString::number(static_cast<sal_Int32>(m_nTabWidth)) + "%"); else { - OSL_ENSURE( Application::GetDefaultDevice(), "no Application-Window!?" ); - sOut.append("100%"); + sal_Int32 nPixWidth = SwHTMLWriter::ToPixel(m_nTabWidth); + sOut.append(nPixWidth); } sOut.append("\""); } - if( (nHSpace || nVSpace) && Application::GetDefaultDevice()) + if( (nHSpace || nVSpace) && !rWrt.mbReqIF) { - Size aPixelSpc = - Application::GetDefaultDevice()->LogicToPixel( Size(nHSpace,nVSpace), - MapMode(MapUnit::MapTwip) ); - if( !aPixelSpc.Width() && nHSpace ) - aPixelSpc.setWidth( 1 ); - if( !aPixelSpc.Height() && nVSpace ) - aPixelSpc.setHeight( 1 ); - - if( aPixelSpc.Width() ) + if (auto nPixHSpace = SwHTMLWriter::ToPixel(nHSpace)) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_hspace - "=\"" + OString::number(aPixelSpc.Width()) + "\""); + "=\"" + OString::number(nPixHSpace) + "\""); } - if( aPixelSpc.Height() ) + if (auto nPixVSpace = SwHTMLWriter::ToPixel(nVSpace)) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_vspace - "=\"" + OString::number(aPixelSpc.Height()) + "\""); + "=\"" + OString::number(nPixVSpace) + "\""); } } // output CELLPADDING: from layout or calculated sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellpadding - "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellPadding,false)) + "\""); + "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellPadding)) + "\""); // output CELLSPACING: from layout or calculated sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing - "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellSpacing,false)) + "\""); + "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellSpacing)) + "\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); // output background if( pFrameFormat ) { - rWrt.OutBackground( pFrameFormat->GetAttrSet(), false ); + if (!rWrt.mbXHTML) + { + rWrt.OutBackground(pFrameFormat->GetAttrSet(), false); + } - if (rWrt.m_bCfgOutStyles) + if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML) + { rWrt.OutCSS1_TableFrameFormatOptions( *pFrameFormat ); + } } sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.IncIndentLevel(); // indent content of table @@ -719,13 +713,11 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, sOutStr.append(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"") .append(bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) .append("\""); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + sOutStr) ); - HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption, rWrt.m_eDestEnc, &rWrt.m_aNonConvertableCharacters ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption), false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOutStr) ); + HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption), false ); } - const SwWriteTableCols::size_type nCols = m_aCols.size(); - // output <COLGRP>/<COL>: If exporting via layout only when during import // some were there, otherwise always. bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly); @@ -734,11 +726,12 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, if( bColGroups ) { rWrt.OutNewLine(); // <COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); rWrt.IncIndentLevel(); // indent content of <COLGRP> } + const SwWriteTableCols::size_type nCols = m_aCols.size(); for( SwWriteTableCols::size_type nCol=0; nCol<nCols; ++nCol ) { rWrt.OutNewLine(); // </COL> in new line @@ -746,7 +739,8 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, const SwWriteTableCol *pColumn = m_aCols[nCol].get(); HtmlWriter html(rWrt.Strm(), rWrt.maNamespace); - html.start(OOO_STRING_SVTOOLS_HTML_col); + html.prettyPrint(false); // We add newlines ourself + html.start(OOO_STRING_SVTOOLS_HTML_col ""_ostr); sal_uInt32 nWidth; bool bRel; @@ -762,19 +756,19 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, } if( bRel ) - html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString(OString::number(nWidth) + "*")); + html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, Concat2View(OString::number(nWidth) + "*")); else - html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth,false))); + html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth))); html.end(); - if( bColGroups && pColumn->bRightBorder && nCol<nCols-1 ) + if( bColGroups && pColumn->m_bRightBorder && nCol<nCols-1 ) { rWrt.DecIndentLevel(); // indent content of <COLGRP> rWrt.OutNewLine(); // </COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), false ); rWrt.OutNewLine(); // <COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); rWrt.IncIndentLevel(); // indent content of <COLGRP> } } @@ -783,7 +777,7 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, rWrt.DecIndentLevel(); // indent content of <COLGRP> rWrt.OutNewLine(); // </COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), false ); } } @@ -798,7 +792,7 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, // can be outputted if there is a line below the cell. if( bTHead && (bTSections || bColGroups) && - m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->bBottomBorder ) + m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->HasBottomBorder() ) bTHead = false; // Output <TBODY> only if <THEAD> is outputted. @@ -808,42 +802,39 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, { rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rWrt.GetNamespace() + aTag)); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag)); rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA> } + sal_uInt16 nSkipRows = 0; for( SwWriteTableRows::size_type nRow = 0; nRow < m_aRows.size(); ++nRow ) { - const SwWriteTableRow *pRow2 = m_aRows[nRow].get(); + const SwWriteTableRow *pRow = m_aRows[nRow].get(); - OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() ); - if( !m_nCellSpacing && nRow < m_aRows.size()-1 && pRow2->bBottomBorder && - pRow2->nBottomBorder > DEF_LINE_WIDTH_1 ) + if (nSkipRows == 0) { - for( auto nCnt = (pRow2->nBottomBorder / DEF_LINE_WIDTH_1) - 1; nCnt; --nCnt ) - { - rWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow )); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), - false ); - } + OutTableCells(rWrt, pRow->GetCells(), pRow->GetBackground(), nSkipRows); + } + else + { + --nSkipRows; } if( ( (bTHead && nRow==m_nHeadEndRow) || - (bTBody && pRow2->bBottomBorder) ) && + (bTBody && pRow->HasBottomBorder()) ) && nRow < m_aRows.size()-1 ) { rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA> rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rWrt.GetNamespace() + aTag), false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line if( bTHead && nRow==m_nHeadEndRow ) bTHead = false; aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rWrt.GetNamespace() + aTag)); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag)); rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA> } } @@ -854,26 +845,25 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rWrt.GetNamespace() + aTag), false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); } rWrt.DecIndentLevel(); // indent content of <TABLE> rWrt.OutNewLine(); // </TABLE> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table), false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table), false ); rWrt.m_nDirection = nOldDirection; } -Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, +SwHTMLWriter& OutHTML_SwTableNode( SwHTMLWriter& rWrt, SwTableNode & rNode, const SwFrameFormat *pFlyFrameFormat, const OUString *pCaption, bool bTopCaption ) { SwTable& rTable = rNode.GetTable(); - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - rHTMLWrt.m_bOutTable = true; + rWrt.m_bOutTable = true; // The horizontal alignment of the frame (if exists) has priority. // NONE means that no horizontal alignment was outputted. @@ -903,11 +893,11 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, // maybe open a FORM bool bPreserveForm = false; - if( !rHTMLWrt.m_bPreserveForm ) + if( !rWrt.m_bPreserveForm ) { - rHTMLWrt.OutForm( true, &rNode ); - bPreserveForm = rHTMLWrt.mxFormComps.is(); - rHTMLWrt.m_bPreserveForm = bPreserveForm; + rWrt.OutForm( true, &rNode ); + bPreserveForm = rWrt.mxFormComps.is(); + rWrt.m_bPreserveForm = bPreserveForm; } SwFrameFormat *pFormat = rTable.GetFrameFormat(); @@ -915,7 +905,7 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize(); tools::Long nWidth = rFrameSize.GetSize().Width(); sal_uInt8 nPercentWidth = rFrameSize.GetWidthPercent(); - sal_uInt16 nBaseWidth = static_cast<sal_uInt16>(nWidth); + sal_uInt16 nBaseWidth = o3tl::narrowing<sal_uInt16>(nWidth); sal_Int16 eTabHoriOri = pFormat->GetHoriOrient().GetHoriOrient(); @@ -980,38 +970,31 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, break; } - if( bCheckDefList ) + // In ReqIF case, do not emulate indentation with fake description list + if( bCheckDefList && !rWrt.mbReqIF ) { - OSL_ENSURE( !rHTMLWrt.GetNumInfo().GetNumRule() || - rHTMLWrt.GetNextNumInfo(), + OSL_ENSURE( !rWrt.GetNumInfo().GetNumRule() || + rWrt.GetNextNumInfo(), "NumInfo for next paragraph is missing!" ); const SvxLRSpaceItem& aLRItem = pFormat->GetLRSpace(); - if( aLRItem.GetLeft() > 0 && rHTMLWrt.m_nDefListMargin > 0 && - ( !rHTMLWrt.GetNumInfo().GetNumRule() || - ( rHTMLWrt.GetNextNumInfo() && - (rHTMLWrt.GetNextNumInfo()->IsRestart() || - rHTMLWrt.GetNumInfo().GetNumRule() != - rHTMLWrt.GetNextNumInfo()->GetNumRule()) ) ) ) + if( aLRItem.GetLeft() > 0 && rWrt.m_nDefListMargin > 0 && + ( !rWrt.GetNumInfo().GetNumRule() || + ( rWrt.GetNextNumInfo() && + (rWrt.GetNumInfo().GetNumRule() != rWrt.GetNextNumInfo()->GetNumRule() || + rWrt.GetNextNumInfo()->IsRestart(rWrt.GetNumInfo())) ) ) ) { // If the paragraph before the table is not numbered or the // paragraph after the table starts with a new numbering or with // a different rule, we can maintain the indentation with a DL. // Otherwise we keep the indentation of the numbering. nNewDefListLvl = static_cast< sal_uInt16 >( - (aLRItem.GetLeft() + (rHTMLWrt.m_nDefListMargin/2)) / - rHTMLWrt.m_nDefListMargin ); + (aLRItem.GetLeft() + (rWrt.m_nDefListMargin/2)) / + rWrt.m_nDefListMargin ); } } - if( !pFlyFrameFormat && nNewDefListLvl != rHTMLWrt.m_nDefListLvl ) - rHTMLWrt.OutAndSetDefList( nNewDefListLvl ); - - if( nNewDefListLvl ) - { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd) ); - } + if( !pFlyFrameFormat && !rWrt.mbReqIF && nNewDefListLvl != rWrt.m_nDefListLvl ) + rWrt.OutAndSetDefList( nNewDefListLvl ); // eFlyHoriOri and eTabHoriOri now only contain the values of // LEFT/CENTER and RIGHT! @@ -1060,28 +1043,44 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, nFlyHSpace = nFlyVSpace = 0; if( !pFormat->GetName().isEmpty() ) - rHTMLWrt.OutImplicitMark( pFormat->GetName(), "table" ); + rWrt.OutImplicitMark( pFormat->GetName(), "table" ); if( text::HoriOrientation::NONE!=eDivHoriOri ) { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); // <CENTER> in new line + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); // <CENTER> in new line if( text::HoriOrientation::CENTER==eDivHoriOri ) - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_center) ); + { + if (!rWrt.mbXHTML) + { + // Not XHTML's css center: start <center>. + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_center) ); + } + } else { - OStringLiteral sOut = OOO_STRING_SVTOOLS_HTML_division - " " OOO_STRING_SVTOOLS_HTML_O_align "=\"" - OOO_STRING_SVTOOLS_HTML_AL_right "\""; - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + sOut) ); + if (rWrt.mbReqIF) + { + // In ReqIF, div cannot have an 'align' attribute. For now, use 'style' only + // for ReqIF; maybe it makes sense to use it in both cases? + static constexpr char sOut[] = OOO_STRING_SVTOOLS_HTML_division + " style=\"display: flex; flex-direction: column; align-items: flex-end\""; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut)); + } + else + { + static constexpr char sOut[] = OOO_STRING_SVTOOLS_HTML_division + " " OOO_STRING_SVTOOLS_HTML_O_align "=\"" OOO_STRING_SVTOOLS_HTML_AL_right "\""; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut)); + } } - rHTMLWrt.IncIndentLevel(); // indent content of <CENTER> - rHTMLWrt.m_bLFPossible = true; + rWrt.IncIndentLevel(); // indent content of <CENTER> + rWrt.SetLFPossible(true); } // If the table isn't in a frame, then you always can output a LF. if( text::HoriOrientation::NONE==eTabHoriOri ) - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); const SwHTMLTableLayout *pLayout = rTable.GetHTMLTableLayout(); @@ -1096,7 +1095,7 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, if( pLayout && pLayout->IsExportable() ) { SwHTMLWrtTable aTableWrt( pLayout ); - aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, + aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, pFormat, pCaption, bTopCaption, nFlyHSpace, nFlyVSpace ); } @@ -1104,49 +1103,52 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, { SwHTMLWrtTable aTableWrt( rTable.GetTabLines(), nWidth, nBaseWidth, bRelWidths, 0, 0, rTable.GetRowsToRepeat() ); - aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, + aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, pFormat, pCaption, bTopCaption, nFlyHSpace, nFlyVSpace ); } // If the table wasn't in a frame, then you always can output a LF. if( text::HoriOrientation::NONE==eTabHoriOri ) - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); if( text::HoriOrientation::NONE!=eDivHoriOri ) { - rHTMLWrt.DecIndentLevel(); // indent content of <CENTER> - rHTMLWrt.OutNewLine(); // </CENTER> in new line + rWrt.DecIndentLevel(); // indent content of <CENTER> + rWrt.OutNewLine(); // </CENTER> in new line OString aTag = text::HoriOrientation::CENTER == eDivHoriOri ? OOO_STRING_SVTOOLS_HTML_center : OOO_STRING_SVTOOLS_HTML_division; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + aTag), false); - rHTMLWrt.m_bLFPossible = true; + if (!rWrt.mbXHTML || eDivHoriOri != text::HoriOrientation::CENTER) + { + // Not XHTML's css center: end <center>. + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); + } + rWrt.SetLFPossible(true); } // move Pam behind the table - rHTMLWrt.m_pCurrentPam->GetPoint()->nNode = *rNode.EndOfSectionNode(); + rWrt.m_pCurrentPam->GetPoint()->Assign( *rNode.EndOfSectionNode() ); if( bPreserveForm ) { - rHTMLWrt.m_bPreserveForm = false; - rHTMLWrt.OutForm( false ); + rWrt.m_bPreserveForm = false; + rWrt.OutForm( false ); } - rHTMLWrt.m_bOutTable = false; + rWrt.m_bOutTable = false; - if( rHTMLWrt.GetNextNumInfo() && - !rHTMLWrt.GetNextNumInfo()->IsRestart() && - rHTMLWrt.GetNextNumInfo()->GetNumRule() == - rHTMLWrt.GetNumInfo().GetNumRule() ) + if( rWrt.GetNextNumInfo() && + rWrt.GetNextNumInfo()->GetNumRule() == rWrt.GetNumInfo().GetNumRule() && + !rWrt.GetNextNumInfo()->IsRestart(rWrt.GetNumInfo()) ) { // If the paragraph after the table is numbered with the same rule as the // one before, then the NumInfo of the next paragraph holds the level of // paragraph before the table. Therefore NumInfo must be fetched again // to maybe close the Num list. - rHTMLWrt.ClearNextNumInfo(); - rHTMLWrt.FillNextNumInfo(); - OutHTML_NumberBulletListEnd( rHTMLWrt, *rHTMLWrt.GetNextNumInfo() ); + rWrt.ClearNextNumInfo(); + rWrt.FillNextNumInfo(); + OutHTML_NumberBulletListEnd( rWrt, *rWrt.GetNextNumInfo() ); } return rWrt; } |