LibreOffice Module sw (master)  1
htmltabw.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <hintids.hxx>
21 #include <vcl/svapp.hxx>
22 #include <svtools/htmlout.hxx>
23 #include <svtools/htmltokn.h>
24 #include <svtools/htmlkywd.hxx>
25 #include <svtools/HtmlWriter.hxx>
26 #include <editeng/ulspitem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <editeng/boxitem.hxx>
30 #include <fmtornt.hxx>
31 #include <frmfmt.hxx>
32 #include <fmtfsize.hxx>
33 #include <fmtsrnd.hxx>
34 #include <frmatr.hxx>
35 #include <doc.hxx>
37 #include <pam.hxx>
38 #include <ndtxt.hxx>
39 #include <swrect.hxx>
40 #include <cellatr.hxx>
41 #include <poolfmt.hxx>
42 #include <swtable.hxx>
43 #include <htmltbl.hxx>
44 #include "htmlnum.hxx"
45 #include "wrthtml.hxx"
46 #include <wrtswtbl.hxx>
47 #ifdef DBG_UTIL
48 #include <viewsh.hxx>
49 #include <viewopt.hxx>
50 #endif
51 #include <rtl/strbuf.hxx>
52 #include <sal/types.h>
53 #include <osl/diagnose.h>
54 
55 #define MAX_DEPTH (3)
56 
57 using namespace ::com::sun::star;
58 
59 namespace {
60 
61 class SwHTMLWrtTable : public SwWriteTable
62 {
63  static void Pixelize( sal_uInt16& rValue );
64  void PixelizeBorders();
65 
66  void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell,
67  bool bOutVAlign ) const;
68 
69  void OutTableCells( SwHTMLWriter& rWrt,
70  const SwWriteTableCells& rCells,
71  const SvxBrushItem *pBrushItem ) const;
72 
73  virtual bool ShouldExpandSub( const SwTableBox *pBox,
74  bool bExpandedBefore, sal_uInt16 nDepth ) const override;
75 
76  static bool HasTabBackground( const SwTableLine& rLine,
77  bool bTop, bool bBottom, bool bLeft, bool bRight );
78  static bool HasTabBackground( const SwTableBox& rBox,
79  bool bTop, bool bBottom, bool bLeft, bool bRight );
80 
81 public:
82  SwHTMLWrtTable( const SwTableLines& rLines, tools::Long nWidth, sal_uInt32 nBWidth,
83  bool bRel, sal_uInt16 nLeftSub, sal_uInt16 nRightSub,
84  sal_uInt16 nNumOfRowsToRepeat );
85  explicit SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo );
86 
87  void Write( SwHTMLWriter& rWrt, sal_Int16 eAlign=text::HoriOrientation::NONE,
88  bool bTHead=false, const SwFrameFormat *pFrameFormat=nullptr,
89  const OUString *pCaption=nullptr, bool bTopCaption=false,
90  sal_uInt16 nHSpace=0, sal_uInt16 nVSpace=0 ) const;
91 };
92 
93 }
94 
95 SwHTMLWrtTable::SwHTMLWrtTable( const SwTableLines& rLines, tools::Long nWidth,
96  sal_uInt32 nBWidth, bool bRel,
97  sal_uInt16 nLSub, sal_uInt16 nRSub,
98  sal_uInt16 nNumOfRowsToRepeat )
99  : SwWriteTable(nullptr, rLines, nWidth, nBWidth, bRel, MAX_DEPTH, nLSub, nRSub, nNumOfRowsToRepeat)
100 {
101  PixelizeBorders();
102 }
103 
104 SwHTMLWrtTable::SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo )
105  : SwWriteTable(nullptr, pLayoutInfo)
106 {
107  // Adjust some Twip values to pixel limits
108  if( m_bCollectBorderWidth )
109  PixelizeBorders();
110 }
111 
112 void SwHTMLWrtTable::Pixelize( sal_uInt16& rValue )
113 {
114  if( rValue && Application::GetDefaultDevice() )
115  {
116  Size aSz( rValue, 0 );
117  aSz = Application::GetDefaultDevice()->LogicToPixel( aSz, MapMode(MapUnit::MapTwip) );
118  if( !aSz.Width() )
119  aSz.setWidth( 1 );
120  aSz = Application::GetDefaultDevice()->PixelToLogic( aSz, MapMode(MapUnit::MapTwip) );
121  rValue = o3tl::narrowing<sal_uInt16>(aSz.Width());
122  }
123 }
124 
125 void SwHTMLWrtTable::PixelizeBorders()
126 {
127  Pixelize( m_nBorder );
128  Pixelize( m_nCellSpacing );
129  Pixelize( m_nCellPadding );
130 }
131 
132 bool SwHTMLWrtTable::HasTabBackground( const SwTableBox& rBox,
133  bool bTop, bool bBottom, bool bLeft, bool bRight )
134 {
135  OSL_ENSURE( bTop || bBottom || bLeft || bRight,
136  "HasTabBackground: cannot be called" );
137 
138  bool bRet = false;
139  if( rBox.GetSttNd() )
140  {
141  std::unique_ptr<SvxBrushItem> aBrushItem =
143 
146  bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT ||
147  !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic());
148  }
149  else
150  {
151  const SwTableLines& rLines = rBox.GetTabLines();
152  const SwTableLines::size_type nCount = rLines.size();
153  bool bLeftRight = bLeft || bRight;
154  for( SwTableLines::size_type i=0; !bRet && i<nCount; ++i )
155  {
156  bool bT = bTop && 0 == i;
157  bool bB = bBottom && nCount-1 == i;
158  if( bT || bB || bLeftRight )
159  bRet = HasTabBackground( *rLines[i], bT, bB, bLeft, bRight);
160  }
161  }
162 
163  return bRet;
164 }
165 
166 bool SwHTMLWrtTable::HasTabBackground( const SwTableLine& rLine,
167  bool bTop, bool bBottom, bool bLeft, bool bRight )
168 {
169  OSL_ENSURE( bTop || bBottom || bLeft || bRight,
170  "HasTabBackground: cannot be called" );
171 
172  std::unique_ptr<SvxBrushItem> aBrushItem = rLine.GetFrameFormat()->makeBackgroundBrushItem();
175  bool bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT ||
176  !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic());
177 
178  if( !bRet )
179  {
180  const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
181  const SwTableBoxes::size_type nCount = rBoxes.size();
182  bool bTopBottom = bTop || bBottom;
183  for( SwTableBoxes::size_type i=0; !bRet && i<nCount; ++i )
184  {
185  bool bL = bLeft && 0 == i;
186  bool bR = bRight && nCount-1 == i;
187  if( bTopBottom || bL || bR )
188  bRet = HasTabBackground( *rBoxes[i], bTop, bBottom, bL, bR );
189  }
190  }
191 
192  return bRet;
193 }
194 
195 static bool lcl_TableLine_HasTabBorders( const SwTableLine* pLine, bool *pBorders );
196 
197 static bool lcl_TableBox_HasTabBorders( const SwTableBox* pBox, bool *pBorders )
198 {
199  if( *pBorders )
200  return false;
201 
202  if( !pBox->GetSttNd() )
203  {
204  for( const auto& rpLine : pBox->GetTabLines() )
205  {
206  if ( lcl_TableLine_HasTabBorders( rpLine, pBorders ) )
207  break;
208  }
209  }
210  else
211  {
212  const SvxBoxItem& rBoxItem =
214 
215  *pBorders = rBoxItem.GetTop() || rBoxItem.GetBottom() ||
216  rBoxItem.GetLeft() || rBoxItem.GetRight();
217  }
218 
219  return !*pBorders;
220 }
221 
222 static bool lcl_TableLine_HasTabBorders( const SwTableLine* pLine, bool *pBorders )
223 {
224  if( *pBorders )
225  return false;
226 
227  for( const auto& rpBox : pLine->GetTabBoxes() )
228  {
229  if ( lcl_TableBox_HasTabBorders( rpBox, pBorders ) )
230  break;
231  }
232  return !*pBorders;
233 }
234 
235 bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox,
236  bool bExpandedBefore,
237  sal_uInt16 nDepth ) const
238 {
239  bool bExpand = !pBox->GetSttNd() && nDepth>0;
240  if( bExpand && bExpandedBefore )
241  {
242  // MIB 30.6.97: If a box was already expanded, another one is only
243  // expanded when it has a border.
244  bool bBorders = false;
245  lcl_TableBox_HasTabBorders( pBox, &bBorders );
246  if( !bBorders )
247  bBorders = HasTabBackground( *pBox, true, true, true, true );
248  bExpand = bBorders;
249  }
250 
251  return bExpand;
252 }
253 
254 // Write a box as single cell
255 void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt,
256  const SwWriteTableCell *pCell,
257  bool bOutVAlign ) const
258 {
259  const SwTableBox *pBox = pCell->GetBox();
260  sal_uInt16 nRow = pCell->GetRow();
261  sal_uInt16 nCol = pCell->GetCol();
262  sal_uInt16 nRowSpan = pCell->GetRowSpan();
263  sal_uInt16 nColSpan = pCell->GetColSpan();
264 
265  if ( !nRowSpan )
266  return;
267 
268  const SwStartNode* pSttNd = pBox->GetSttNd();
269  bool bHead = false;
270  if( pSttNd )
271  {
272  SwNodeOffset nNdPos = pSttNd->GetIndex()+1;
273 
274  // determine the type of cell (TD/TH)
275  SwNode* pNd;
276  while( !( pNd = rWrt.m_pDoc->GetNodes()[nNdPos])->IsEndNode() )
277  {
278  if( pNd->IsTextNode() )
279  {
280  // The only paragraphs relevant for the distinction are those
281  // where the style is one of the two table related styles
282  // or inherits from one of these.
283  const SwFormat *pFormat = &static_cast<SwTextNode*>(pNd)->GetAnyFormatColl();
284  sal_uInt16 nPoolId = pFormat->GetPoolFormatId();
285  while( !pFormat->IsDefault() &&
286  RES_POOLCOLL_TABLE_HDLN!=nPoolId &&
287  RES_POOLCOLL_TABLE!=nPoolId )
288  {
289  pFormat = pFormat->DerivedFrom();
290  nPoolId = pFormat->GetPoolFormatId();
291  }
292 
293  if( !pFormat->IsDefault() )
294  {
295  bHead = (RES_POOLCOLL_TABLE_HDLN==nPoolId);
296  break;
297  }
298  }
299  nNdPos++;
300  }
301  }
302 
303  rWrt.OutNewLine(); // <TH>/<TD> in new line
304  OStringBuffer sOut;
305  sOut.append('<');
306  OString aTag(bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata);
307  sOut.append(rWrt.GetNamespace() + aTag);
308 
309  // output ROW- and COLSPAN
310  if( nRowSpan>1 )
311  {
312  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan
313  "=\"" + OString::number(nRowSpan) + "\"");
314  }
315  if( nColSpan > 1 )
316  {
317  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_colspan
318  "=\"" + OString::number(nColSpan) + "\"");
319  }
320 
321  tools::Long nWidth = 0;
322  bool bOutWidth = true;
323  sal_uInt32 nPercentWidth = SAL_MAX_UINT32;
324 
325  if( m_bLayoutExport )
326  {
327  if( pCell->HasPercentWidthOpt() )
328  {
329  nPercentWidth = pCell->GetWidthOpt();
330  }
331  else
332  {
333  nWidth = pCell->GetWidthOpt();
334  if( !nWidth )
335  bOutWidth = false;
336  }
337  }
338  else
339  {
340  if( HasRelWidths() )
341  nPercentWidth = GetPercentWidth(nCol, nColSpan);
342  else
343  nWidth = GetAbsWidth( nCol, nColSpan );
344  }
345 
346  if (rWrt.mbReqIF)
347  // ReqIF implies strict XHTML: no width for <td>.
348  bOutWidth = false;
349 
350  tools::Long nHeight = pCell->GetHeight() > 0
351  ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan )
352  : 0;
353  Size aPixelSz( nWidth, nHeight );
354 
355  // output WIDTH (Argh: only for Netscape)
356  if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() )
357  {
358  Size aOldSz( aPixelSz );
359  aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz,
360  MapMode(MapUnit::MapTwip) );
361  if( aOldSz.Width() && !aPixelSz.Width() )
362  aPixelSz.setWidth( 1 );
363  if( aOldSz.Height() && !aPixelSz.Height() )
364  aPixelSz.setHeight( 1 );
365  }
366 
367  // output WIDTH: from layout or calculated
368  if( bOutWidth )
369  {
370  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\"");
371  if( nPercentWidth != SAL_MAX_UINT32 )
372  {
373  sOut.append(static_cast<sal_Int32>(nPercentWidth)).append('%');
374  }
375  else
376  {
377  sOut.append(static_cast<sal_Int32>(aPixelSz.Width()));
378  }
379  sOut.append("\"");
380  }
381 
382  if (rWrt.mbReqIF)
383  {
384  // ReqIF implies strict XHTML: no height for <td>.
385  nHeight = 0;
386  }
387 
388  if( nHeight )
389  {
390  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_height
391  "=\"" + OString::number(aPixelSz.Height()) + "\"");
392  }
393 
394  const SfxItemSet& rItemSet = pBox->GetFrameFormat()->GetAttrSet();
395 
396  // ALIGN is only outputted at the paragraphs from now on
397 
398  // output VALIGN
399  if( bOutVAlign )
400  {
401  sal_Int16 eVertOri = pCell->GetVertOri();
402  if( text::VertOrientation::TOP==eVertOri || text::VertOrientation::BOTTOM==eVertOri )
403  {
404  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign
405  "=\"").append(text::VertOrientation::TOP==eVertOri ?
406  OOO_STRING_SVTOOLS_HTML_VA_top :
407  OOO_STRING_SVTOOLS_HTML_VA_bottom)
408  .append("\"");
409  }
410  }
411 
412  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
413 
414  rWrt.m_bTextAttr = false;
415  rWrt.m_bOutOpts = true;
416  const SvxBrushItem *pBrushItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false );
417  if( !pBrushItem )
418  pBrushItem = pCell->GetBackground();
419 
420  if( pBrushItem )
421  {
422  // output background
423  if (!rWrt.mbReqIF)
424  // Avoid non-CSS version in the ReqIF case.
425  rWrt.OutBackground( pBrushItem, false );
426 
427  if (!rWrt.m_bCfgOutStyles)
428  pBrushItem = nullptr;
429  }
430 
431  // tdf#132739 with rWrt.m_bCfgOutStyles of true bundle the brush item css
432  // properties into the same "style" tag as the borders so there is only one
433  // style tag
434  rWrt.OutCSS1_TableCellBordersAndBG(*pBox->GetFrameFormat(), pBrushItem);
435 
436  sal_uInt32 nNumFormat = 0;
437  double nValue = 0.0;
438  bool bNumFormat = false, bValue = false;
439  if( const SwTableBoxNumFormat* pItem = rItemSet.GetItemIfSet( RES_BOXATR_FORMAT, false ) )
440  {
441  nNumFormat = pItem->GetValue();
442  bNumFormat = true;
443  }
444  if( const SwTableBoxValue* pItem = rItemSet.GetItemIfSet( RES_BOXATR_VALUE, false ) )
445  {
446  nValue = pItem->GetValue();
447  bValue = true;
448  if( !bNumFormat )
449  nNumFormat = pBox->GetFrameFormat()->GetTableBoxNumFormat().GetValue();
450  }
451 
452  if( bNumFormat || bValue )
453  {
454  sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValue, nValue,
455  nNumFormat, *rWrt.m_pDoc->GetNumberFormatter()));
456  }
457  sOut.append('>');
458  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
459  rWrt.m_bLFPossible = true;
460 
461  rWrt.IncIndentLevel(); // indent the content of <TD>...</TD>
462 
463  if( pSttNd )
464  {
465  HTMLSaveData aSaveData( rWrt, pSttNd->GetIndex()+1,
466  pSttNd->EndOfSectionIndex() );
467  rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() );
468  }
469  else
470  {
471  sal_uInt16 nTWidth;
472  sal_uInt32 nBWidth;
473  sal_uInt16 nLSub, nRSub;
474  if( HasRelWidths() )
475  {
476  nTWidth = 100;
477  nBWidth = GetRawWidth( nCol, nColSpan );
478  nLSub = 0;
479  nRSub = 0;
480  }
481  else
482  {
483  nTWidth = GetAbsWidth( nCol, nColSpan );
484  nBWidth = nTWidth;
485  nLSub = GetLeftSpace( nCol );
486  nRSub = GetRightSpace( nCol, nColSpan );
487  }
488 
489  SwHTMLWrtTable aTableWrt( pBox->GetTabLines(), nTWidth,
490  nBWidth, HasRelWidths(), nLSub, nRSub, /*nNumOfRowsToRepeat*/0 );
491  aTableWrt.Write( rWrt );
492  }
493 
494  rWrt.DecIndentLevel(); // indent the content of <TD>...</TD>
495 
496  if( rWrt.m_bLFPossible )
497  rWrt.OutNewLine();
499  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + aTag), false);
500  rWrt.m_bLFPossible = true;
501 }
502 
503 // output a line as lines
504 void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt,
505  const SwWriteTableCells& rCells,
506  const SvxBrushItem *pBrushItem ) const
507 {
508  // If the line contains more the one cell and all cells have the same
509  // alignment, then output the VALIGN at the line instead of the cell.
510  sal_Int16 eRowVertOri = text::VertOrientation::NONE;
511  if( rCells.size() > 1 )
512  {
513  for (SwWriteTableCells::size_type nCell = 0; nCell < rCells.size(); ++nCell)
514  {
515  sal_Int16 eCellVertOri = rCells[nCell]->GetVertOri();
516  if( 0==nCell )
517  {
518  eRowVertOri = eCellVertOri;
519  }
520  else if( eRowVertOri != eCellVertOri )
521  {
522  eRowVertOri = text::VertOrientation::NONE;
523  break;
524  }
525  }
526  }
527 
528  rWrt.OutNewLine(); // <TR> in new line
529  rWrt.Strm().WriteChar( '<' ).WriteOString( OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow) );
530  if( pBrushItem )
531  {
532  if (!rWrt.mbXHTML)
533  {
534  rWrt.OutBackground(pBrushItem, false);
535  }
536 
537  rWrt.m_bTextAttr = false;
538  rWrt.m_bOutOpts = true;
539  if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML)
540  OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
541  }
542 
543  if( text::VertOrientation::TOP==eRowVertOri || text::VertOrientation::BOTTOM==eRowVertOri )
544  {
545  OStringBuffer sOut;
546  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign
547  "=\"").append(text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom)
548  .append("\"");
549  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
550  }
551 
552  rWrt.Strm().WriteChar( '>' );
553 
554  rWrt.IncIndentLevel(); // indent content of <TR>...</TR>
555 
556  for (const auto &rpCell : rCells)
557  {
558  OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri);
559  }
560 
561  rWrt.DecIndentLevel(); // indent content of <TR>...</TR>
562 
563  rWrt.OutNewLine(); // </TR> in new line
564  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), false );
565 }
566 
567 void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign,
568  bool bTHead, const SwFrameFormat *pFrameFormat,
569  const OUString *pCaption, bool bTopCaption,
570  sal_uInt16 nHSpace, sal_uInt16 nVSpace ) const
571 {
572  // determine value of RULES
573  bool bRowsHaveBorder = false;
574  bool bRowsHaveBorderOnly = true;
575  SwWriteTableRow *pRow = m_aRows[0].get();
576  for( SwWriteTableRows::size_type nRow=1; nRow < m_aRows.size(); ++nRow )
577  {
578  SwWriteTableRow *pNextRow = m_aRows[nRow].get();
579  bool bBorder = ( pRow->m_bBottomBorder || pNextRow->m_bTopBorder );
580  bRowsHaveBorder |= bBorder;
581  bRowsHaveBorderOnly &= bBorder;
582 
583  sal_uInt16 nBorder2 = pRow->m_bBottomBorder ? pRow->m_nBottomBorder : USHRT_MAX;
584  if( pNextRow->m_bTopBorder && pNextRow->m_nTopBorder < nBorder2 )
585  nBorder2 = pNextRow->m_nTopBorder;
586 
587  pRow->m_bBottomBorder = bBorder;
588  pRow->m_nBottomBorder = nBorder2;
589 
590  pNextRow->m_bTopBorder = bBorder;
591  pNextRow->m_nTopBorder = nBorder2;
592 
593  pRow = pNextRow;
594  }
595 
596  bool bColsHaveBorder = false;
597  bool bColsHaveBorderOnly = true;
598  SwWriteTableCol *pCol = m_aCols[0].get();
599  for( SwWriteTableCols::size_type nCol=1; nCol<m_aCols.size(); ++nCol )
600  {
601  SwWriteTableCol *pNextCol = m_aCols[nCol].get();
602  bool bBorder = ( pCol->m_bRightBorder || pNextCol->m_bLeftBorder );
603  bColsHaveBorder |= bBorder;
604  bColsHaveBorderOnly &= bBorder;
605  pCol->m_bRightBorder = bBorder;
606  pNextCol->m_bLeftBorder = bBorder;
607  pCol = pNextCol;
608  }
609 
610  // close previous numbering, etc
611  rWrt.ChangeParaToken( HtmlTokenId::NONE );
612 
613  if( rWrt.m_bLFPossible )
614  rWrt.OutNewLine(); // <TABLE> in new line
615  OStringBuffer sOut;
616  sOut.append('<').append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table);
617 
618  const SvxFrameDirection nOldDirection = rWrt.m_nDirection;
619  if( pFrameFormat )
620  rWrt.m_nDirection = rWrt.GetHTMLDirection( pFrameFormat->GetAttrSet() );
621  if( rWrt.m_bOutFlyFrame || nOldDirection != rWrt.m_nDirection )
622  {
623  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
624  rWrt.OutDirection( rWrt.m_nDirection );
625  }
626 
627  // output ALIGN=
628  if( text::HoriOrientation::RIGHT == eAlign )
629  {
630  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
631  "=\"" OOO_STRING_SVTOOLS_HTML_AL_right "\"");
632  }
633  else if( text::HoriOrientation::CENTER == eAlign )
634  {
635  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
636  "=\"" OOO_STRING_SVTOOLS_HTML_AL_center "\"");
637  }
638  else if( text::HoriOrientation::LEFT == eAlign )
639  {
640  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
641  "=\"" OOO_STRING_SVTOOLS_HTML_AL_left "\"");
642  }
643 
644  // output WIDTH: from layout or calculated
645  if( m_nTabWidth )
646  {
647  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\"");
648  if( HasRelWidths() )
649  sOut.append(static_cast<sal_Int32>(m_nTabWidth)).append('%');
650  else if( Application::GetDefaultDevice() )
651  {
652  sal_Int32 nPixWidth = Application::GetDefaultDevice()->LogicToPixel(
653  Size(m_nTabWidth,0), MapMode(MapUnit::MapTwip) ).Width();
654  if( !nPixWidth )
655  nPixWidth = 1;
656 
657  sOut.append(nPixWidth);
658  }
659  else
660  {
661  OSL_ENSURE( Application::GetDefaultDevice(), "no Application-Window!?" );
662  sOut.append("100%");
663  }
664  sOut.append("\"");
665  }
666 
667  if( (nHSpace || nVSpace) && Application::GetDefaultDevice())
668  {
669  Size aPixelSpc =
670  Application::GetDefaultDevice()->LogicToPixel( Size(nHSpace,nVSpace),
671  MapMode(MapUnit::MapTwip) );
672  if( !aPixelSpc.Width() && nHSpace )
673  aPixelSpc.setWidth( 1 );
674  if( !aPixelSpc.Height() && nVSpace )
675  aPixelSpc.setHeight( 1 );
676 
677  if( aPixelSpc.Width() )
678  {
679  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_hspace
680  "=\"" + OString::number(aPixelSpc.Width()) + "\"");
681  }
682 
683  if( aPixelSpc.Height() )
684  {
685  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_vspace
686  "=\"" + OString::number(aPixelSpc.Height()) + "\"");
687  }
688  }
689 
690  // output CELLPADDING: from layout or calculated
691  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellpadding
692  "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellPadding,false)) + "\"");
693 
694  // output CELLSPACING: from layout or calculated
695  sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing
696  "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellSpacing,false)) + "\"");
697 
698  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
699 
700  // output background
701  if( pFrameFormat )
702  {
703  if (!rWrt.mbXHTML)
704  {
705  rWrt.OutBackground(pFrameFormat->GetAttrSet(), false);
706  }
707 
708  if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML)
709  {
710  rWrt.OutCSS1_TableFrameFormatOptions( *pFrameFormat );
711  }
712  }
713 
714  sOut.append('>');
715  rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
716 
717  rWrt.IncIndentLevel(); // indent content of table
718 
719  // output caption
720  if( pCaption && !pCaption->isEmpty() )
721  {
722  rWrt.OutNewLine(); // <CAPTION> in new line
723  OStringBuffer sOutStr(OOO_STRING_SVTOOLS_HTML_caption);
724  sOutStr.append(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"")
725  .append(bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom)
726  .append("\"");
727  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + sOutStr) );
728  HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption );
729  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption), false );
730  }
731 
732  const SwWriteTableCols::size_type nCols = m_aCols.size();
733 
734  // output <COLGRP>/<COL>: If exporting via layout only when during import
735  // some were there, otherwise always.
736  bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly);
737  if( m_bColTags )
738  {
739  if( bColGroups )
740  {
741  rWrt.OutNewLine(); // <COLGRP> in new line
742  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) );
743 
744  rWrt.IncIndentLevel(); // indent content of <COLGRP>
745  }
746 
747  for( SwWriteTableCols::size_type nCol=0; nCol<nCols; ++nCol )
748  {
749  rWrt.OutNewLine(); // </COL> in new line
750 
751  const SwWriteTableCol *pColumn = m_aCols[nCol].get();
752 
753  HtmlWriter html(rWrt.Strm(), rWrt.maNamespace);
754  html.start(OOO_STRING_SVTOOLS_HTML_col);
755 
756  sal_uInt32 nWidth;
757  bool bRel;
758  if( m_bLayoutExport )
759  {
760  bRel = pColumn->HasRelWidthOpt();
761  nWidth = pColumn->GetWidthOpt();
762  }
763  else
764  {
765  bRel = HasRelWidths();
766  nWidth = bRel ? GetRelWidth(nCol,1) : GetAbsWidth(nCol,1);
767  }
768 
769  if( bRel )
770  html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OStringConcatenation(OString::number(nWidth) + "*"));
771  else
772  html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth,false)));
773  html.end();
774 
775  if( bColGroups && pColumn->m_bRightBorder && nCol<nCols-1 )
776  {
777  rWrt.DecIndentLevel(); // indent content of <COLGRP>
778  rWrt.OutNewLine(); // </COLGRP> in new line
779  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup),
780  false );
781  rWrt.OutNewLine(); // <COLGRP> in new line
782  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) );
783  rWrt.IncIndentLevel(); // indent content of <COLGRP>
784  }
785  }
786  if( bColGroups )
787  {
788  rWrt.DecIndentLevel(); // indent content of <COLGRP>
789 
790  rWrt.OutNewLine(); // </COLGRP> in new line
791  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup),
792  false );
793  }
794  }
795 
796  // output the lines as table lines
797 
798  // Output <TBODY>?
799  bool bTSections = (bRowsHaveBorder && !bRowsHaveBorderOnly);
800  bool bTBody = bTSections;
801 
802  // If sections must be outputted, then a THEAD around the first line only
803  // can be outputted if there is a line below the cell.
804  if( bTHead &&
805  (bTSections || bColGroups) &&
806  m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->m_bBottomBorder )
807  bTHead = false;
808 
809  // Output <TBODY> only if <THEAD> is outputted.
810  bTSections |= bTHead;
811 
812  if( bTSections )
813  {
814  rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line
816  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + aTag));
817 
818  rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA>
819  }
820 
821  for( SwWriteTableRows::size_type nRow = 0; nRow < m_aRows.size(); ++nRow )
822  {
823  const SwWriteTableRow *pRow2 = m_aRows[nRow].get();
824 
825  OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() );
826  if( !m_nCellSpacing && nRow < m_aRows.size()-1 && pRow2->m_bBottomBorder &&
828  {
829  for( auto nCnt = (pRow2->m_nBottomBorder / SvxBorderLineWidth::Thin) - 1; nCnt; --nCnt )
830  {
831  rWrt.OutNewLine();
832  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow ));
833  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow),
834  false );
835  }
836  }
837  if( ( (bTHead && nRow==m_nHeadEndRow) ||
838  (bTBody && pRow2->m_bBottomBorder) ) &&
839  nRow < m_aRows.size()-1 )
840  {
841  rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA>
842  rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line
844  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + aTag), false);
845  rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line
846 
847  if( bTHead && nRow==m_nHeadEndRow )
848  bTHead = false;
849 
851  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + aTag));
852  rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA>
853  }
854  }
855 
856  if( bTSections )
857  {
858  rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA>
859 
860  rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line
862  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + aTag), false);
863  }
864 
865  rWrt.DecIndentLevel(); // indent content of <TABLE>
866 
867  rWrt.OutNewLine(); // </TABLE> in new line
868  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table), false );
869 
870  rWrt.m_nDirection = nOldDirection;
871 }
872 
874  const SwFrameFormat *pFlyFrameFormat,
875  const OUString *pCaption, bool bTopCaption )
876 {
877 
878  SwTable& rTable = rNode.GetTable();
879 
880  SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
881  rHTMLWrt.m_bOutTable = true;
882 
883  // The horizontal alignment of the frame (if exists) has priority.
884  // NONE means that no horizontal alignment was outputted.
885  sal_Int16 eFlyHoriOri = text::HoriOrientation::NONE;
886  css::text::WrapTextMode eSurround = css::text::WrapTextMode_NONE;
887  sal_uInt8 nFlyPercentWidth = 0;
888  tools::Long nFlyWidth = 0;
889  sal_uInt16 nFlyHSpace = 0;
890  sal_uInt16 nFlyVSpace = 0;
891  if( pFlyFrameFormat )
892  {
893  eSurround = pFlyFrameFormat->GetSurround().GetSurround();
894  const SwFormatFrameSize& rFrameSize = pFlyFrameFormat->GetFrameSize();
895  nFlyPercentWidth = rFrameSize.GetWidthPercent();
896  nFlyWidth = rFrameSize.GetSize().Width();
897 
898  eFlyHoriOri = pFlyFrameFormat->GetHoriOrient().GetHoriOrient();
899  if( text::HoriOrientation::NONE == eFlyHoriOri )
900  eFlyHoriOri = text::HoriOrientation::LEFT;
901 
902  const SvxLRSpaceItem& rLRSpace = pFlyFrameFormat->GetLRSpace();
903  nFlyHSpace = static_cast< sal_uInt16 >((rLRSpace.GetLeft() + rLRSpace.GetRight()) / 2);
904 
905  const SvxULSpaceItem& rULSpace = pFlyFrameFormat->GetULSpace();
906  nFlyVSpace = (rULSpace.GetUpper() + rULSpace.GetLower()) / 2;
907  }
908 
909  // maybe open a FORM
910  bool bPreserveForm = false;
911  if( !rHTMLWrt.m_bPreserveForm )
912  {
913  rHTMLWrt.OutForm( true, &rNode );
914  bPreserveForm = rHTMLWrt.mxFormComps.is();
915  rHTMLWrt.m_bPreserveForm = bPreserveForm;
916  }
917 
918  SwFrameFormat *pFormat = rTable.GetFrameFormat();
919 
920  const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize();
921  tools::Long nWidth = rFrameSize.GetSize().Width();
922  sal_uInt8 nPercentWidth = rFrameSize.GetWidthPercent();
923  sal_uInt16 nBaseWidth = o3tl::narrowing<sal_uInt16>(nWidth);
924 
925  sal_Int16 eTabHoriOri = pFormat->GetHoriOrient().GetHoriOrient();
926 
927  // text::HoriOrientation::NONE and text::HoriOrientation::FULL tables need relative widths
928  sal_uInt16 nNewDefListLvl = 0;
929  bool bRelWidths = false;
930  bool bCheckDefList = false;
931  switch( eTabHoriOri )
932  {
933  case text::HoriOrientation::FULL:
934  // Tables with automatic alignment become tables with 100% width.
935  bRelWidths = true;
936  nWidth = 100;
937  eTabHoriOri = text::HoriOrientation::LEFT;
938  break;
940  {
941  const SvxLRSpaceItem& aLRItem = pFormat->GetLRSpace();
942  if( aLRItem.GetRight() )
943  {
944  // The table width is defined on the basis of the left and
945  // right margin. Therefore we try to define the actual
946  // width of the table. If that's not possible we transform
947  // it to a table with width 100%.
948  nWidth = pFormat->FindLayoutRect(true).Width();
949  if( !nWidth )
950  {
951  bRelWidths = true;
952  nWidth = 100;
953  }
954 
955  }
956  else if( nPercentWidth )
957  {
958  // Without a right border the %-width is maintained.
959  nWidth = nPercentWidth;
960  bRelWidths = true;
961  }
962  else
963  {
964  // Without a right margin also an absolute width is maintained.
965  // We still try to define the actual width via the layout.
966  tools::Long nRealWidth = pFormat->FindLayoutRect(true).Width();
967  if( nRealWidth )
968  nWidth = nRealWidth;
969  }
970  bCheckDefList = true;
971  }
972  break;
973  case text::HoriOrientation::LEFT_AND_WIDTH:
974  eTabHoriOri = text::HoriOrientation::LEFT;
975  bCheckDefList = true;
976  [[fallthrough]];
977  default:
978  // In all other case it's possible to use directly an absolute
979  // or relative width.
980  if( nPercentWidth )
981  {
982  bRelWidths = true;
983  nWidth = nPercentWidth;
984  }
985  break;
986  }
987 
988  if( bCheckDefList )
989  {
990  OSL_ENSURE( !rHTMLWrt.GetNumInfo().GetNumRule() ||
991  rHTMLWrt.GetNextNumInfo(),
992  "NumInfo for next paragraph is missing!" );
993  const SvxLRSpaceItem& aLRItem = pFormat->GetLRSpace();
994  if( aLRItem.GetLeft() > 0 && rHTMLWrt.m_nDefListMargin > 0 &&
995  ( !rHTMLWrt.GetNumInfo().GetNumRule() ||
996  ( rHTMLWrt.GetNextNumInfo() &&
997  (rHTMLWrt.GetNextNumInfo()->IsRestart() ||
998  rHTMLWrt.GetNumInfo().GetNumRule() !=
999  rHTMLWrt.GetNextNumInfo()->GetNumRule()) ) ) )
1000  {
1001  // If the paragraph before the table is not numbered or the
1002  // paragraph after the table starts with a new numbering or with
1003  // a different rule, we can maintain the indentation with a DL.
1004  // Otherwise we keep the indentation of the numbering.
1005  nNewDefListLvl = static_cast< sal_uInt16 >(
1006  (aLRItem.GetLeft() + (rHTMLWrt.m_nDefListMargin/2)) /
1007  rHTMLWrt.m_nDefListMargin );
1008  }
1009  }
1010 
1011  if( !pFlyFrameFormat && nNewDefListLvl != rHTMLWrt.m_nDefListLvl )
1012  rHTMLWrt.OutAndSetDefList( nNewDefListLvl );
1013 
1014  if( nNewDefListLvl )
1015  {
1016  if( rHTMLWrt.m_bLFPossible )
1017  rHTMLWrt.OutNewLine();
1018  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd) );
1019  }
1020 
1021  // eFlyHoriOri and eTabHoriOri now only contain the values of
1022  // LEFT/CENTER and RIGHT!
1023  if( eFlyHoriOri!=text::HoriOrientation::NONE )
1024  {
1025  eTabHoriOri = eFlyHoriOri;
1026  // MIB 4.7.97: If the table has a relative width, then the width is
1027  // adjusted to the width of the frame, therefore we export its width.
1028  // If fixed width, the table width is relevant. Whoever puts tables with
1029  // relative width <100% into frames is to blame when the result looks bad.
1030  if( bRelWidths )
1031  {
1032  nWidth = nFlyPercentWidth ? nFlyPercentWidth : nFlyWidth;
1033  bRelWidths = nFlyPercentWidth > 0;
1034  }
1035  }
1036 
1037  sal_Int16 eDivHoriOri = text::HoriOrientation::NONE;
1038  switch( eTabHoriOri )
1039  {
1040  case text::HoriOrientation::LEFT:
1041  // If a left-aligned table has no right sided flow, then we don't need
1042  // an ALIGN=LEFT in the table.
1043  if( eSurround==css::text::WrapTextMode_NONE || eSurround==css::text::WrapTextMode_LEFT )
1044  eTabHoriOri = text::HoriOrientation::NONE;
1045  break;
1046  case text::HoriOrientation::RIGHT:
1047  // Something like that also applies to right-aligned tables,
1048  // here we use a <DIV ALIGN=RIGHT> instead.
1049  if( eSurround==css::text::WrapTextMode_NONE || eSurround==css::text::WrapTextMode_RIGHT )
1050  {
1051  eDivHoriOri = text::HoriOrientation::RIGHT;
1052  eTabHoriOri = text::HoriOrientation::NONE;
1053  }
1054  break;
1055  case text::HoriOrientation::CENTER:
1056  // Almost nobody understands ALIGN=CENTER, therefore we abstain
1057  // from it and use a <CENTER>.
1058  eDivHoriOri = text::HoriOrientation::CENTER;
1059  eTabHoriOri = text::HoriOrientation::NONE;
1060  break;
1061  default:
1062  ;
1063  }
1064  if( text::HoriOrientation::NONE==eTabHoriOri )
1065  nFlyHSpace = nFlyVSpace = 0;
1066 
1067  if( !pFormat->GetName().isEmpty() )
1068  rHTMLWrt.OutImplicitMark( pFormat->GetName(), "table" );
1069 
1070  if( text::HoriOrientation::NONE!=eDivHoriOri )
1071  {
1072  if( rHTMLWrt.m_bLFPossible )
1073  rHTMLWrt.OutNewLine(); // <CENTER> in new line
1074  if( text::HoriOrientation::CENTER==eDivHoriOri )
1075  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_center) );
1076  else
1077  {
1078  OStringLiteral sOut = OOO_STRING_SVTOOLS_HTML_division
1081  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + sOut) );
1082  }
1083  rHTMLWrt.IncIndentLevel(); // indent content of <CENTER>
1084  rHTMLWrt.m_bLFPossible = true;
1085  }
1086 
1087  // If the table isn't in a frame, then you always can output a LF.
1088  if( text::HoriOrientation::NONE==eTabHoriOri )
1089  rHTMLWrt.m_bLFPossible = true;
1090 
1091  const SwHTMLTableLayout *pLayout = rTable.GetHTMLTableLayout();
1092 
1093 #ifdef DBG_UTIL
1094  {
1096  if ( pSh && pSh->GetViewOptions()->IsTest1() )
1097  pLayout = nullptr;
1098  }
1099 #endif
1100 
1101  if( pLayout && pLayout->IsExportable() )
1102  {
1103  SwHTMLWrtTable aTableWrt( pLayout );
1104  aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0,
1105  pFormat, pCaption, bTopCaption,
1106  nFlyHSpace, nFlyVSpace );
1107  }
1108  else
1109  {
1110  SwHTMLWrtTable aTableWrt( rTable.GetTabLines(), nWidth,
1111  nBaseWidth, bRelWidths, 0, 0, rTable.GetRowsToRepeat() );
1112  aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0,
1113  pFormat, pCaption, bTopCaption,
1114  nFlyHSpace, nFlyVSpace );
1115  }
1116 
1117  // If the table wasn't in a frame, then you always can output a LF.
1118  if( text::HoriOrientation::NONE==eTabHoriOri )
1119  rHTMLWrt.m_bLFPossible = true;
1120 
1121  if( text::HoriOrientation::NONE!=eDivHoriOri )
1122  {
1123  rHTMLWrt.DecIndentLevel(); // indent content of <CENTER>
1124  rHTMLWrt.OutNewLine(); // </CENTER> in new line
1125  OString aTag = text::HoriOrientation::CENTER == eDivHoriOri
1128  HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + aTag), false);
1129  rHTMLWrt.m_bLFPossible = true;
1130  }
1131 
1132  // move Pam behind the table
1133  rHTMLWrt.m_pCurrentPam->GetPoint()->nNode = *rNode.EndOfSectionNode();
1134 
1135  if( bPreserveForm )
1136  {
1137  rHTMLWrt.m_bPreserveForm = false;
1138  rHTMLWrt.OutForm( false );
1139  }
1140 
1141  rHTMLWrt.m_bOutTable = false;
1142 
1143  if( rHTMLWrt.GetNextNumInfo() &&
1144  !rHTMLWrt.GetNextNumInfo()->IsRestart() &&
1145  rHTMLWrt.GetNextNumInfo()->GetNumRule() ==
1146  rHTMLWrt.GetNumInfo().GetNumRule() )
1147  {
1148  // If the paragraph after the table is numbered with the same rule as the
1149  // one before, then the NumInfo of the next paragraph holds the level of
1150  // paragraph before the table. Therefore NumInfo must be fetched again
1151  // to maybe close the Num list.
1152  rHTMLWrt.ClearNextNumInfo();
1153  rHTMLWrt.FillNextNumInfo();
1154  OutHTML_NumberBulletListEnd( rHTMLWrt, *rHTMLWrt.GetNextNumInfo() );
1155  }
1156  return rWrt;
1157 }
1158 
1159 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool HasPercentWidthOpt() const
Definition: wrtswtbl.hxx:92
const SwTableBoxNumFormat & GetTableBoxNumFormat(bool=true) const
TableBox attributes - implemented in cellatr.hxx.
Definition: cellatr.hxx:105
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:692
Starts a section of nodes in the document model.
Definition: node.hxx:313
bool HasRelWidthOpt() const
Definition: wrtswtbl.hxx:186
std::vector< SwTableLine * >::size_type size_type
Definition: swtable.hxx:68
SwHTMLNumRuleInfo & GetNumInfo()
Definition: wrthtml.hxx:538
virtual bool ShouldExpandSub(const SwTableBox *pBox, bool bExpandedBefore, sal_uInt16 nDepth) const
Definition: wrtswtbl.cxx:384
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:687
bool mbXHTML
If XHTML markup should be written instead of HTML.
Definition: wrthtml.hxx:396
sal_uInt16 GetRowSpan() const
Definition: wrtswtbl.hxx:78
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
bool m_bPreserveForm
Definition: wrthtml.hxx:385
sal_uInt16 GetLower() const
bool IsDefault() const
Definition: format.hxx:129
void setWidth(tools::Long nWidth)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
void FillNextNumInfo()
#define OOO_STRING_SVTOOLS_HTML_caption
SwHTMLNumRuleInfo * GetNextNumInfo()
Definition: wrthtml.hxx:542
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1410
#define OOO_STRING_SVTOOLS_HTML_tableheader
long Long
tools::Long GetRight() const
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2710
bool IsRestart() const
Definition: htmlnum.hxx:78
#define OOO_STRING_SVTOOLS_HTML_tablerow
void DecIndentLevel()
Definition: wrthtml.hxx:511
SwTableLine is one table row in the document model.
Definition: swtable.hxx:357
SvxFrameDirection
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:196
static SVT_DLLPUBLIC SvStream & Out_AsciiTag(SvStream &, std::string_view rStr, bool bOn=true)
sal_Int32 m_nDefListMargin
Definition: wrthtml.hxx:328
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(152)
const editeng::SvxBorderLine * GetRight() const
#define OOO_STRING_SVTOOLS_HTML_thead
bool m_bOutTable
Definition: wrthtml.hxx:363
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
OString maNamespace
XML namespace, in case of XHTML.
Definition: wrthtml.hxx:398
sal_uInt32 GetWidthOpt() const
Definition: wrtswtbl.hxx:185
size_type size() const
Definition: swtable.hxx:76
#define OOO_STRING_SVTOOLS_HTML_tbody
void OutBackground(const SvxBrushItem *pBrushItem, bool bGraphic)
Definition: wrthtml.cxx:1345
static OutputDevice * GetDefaultDevice()
const SwTableBox * GetBox() const
Definition: wrtswtbl.hxx:73
#define SAL_MAX_UINT32
constexpr tools::Long Width() const
void OutNewLine(bool bCheck=false)
Definition: wrthtml.cxx:1503
#define OOO_STRING_SVTOOLS_HTML_tabledata
bool m_bLFPossible
Definition: wrthtml.hxx:381
std::unique_ptr< SvxBrushItem > makeBackgroundBrushItem(bool=true) const
Definition: format.cxx:737
bool mbReqIF
If the ReqIF subset of XHTML should be written.
Definition: wrthtml.hxx:400
sal_uInt16 m_nBottomBorder
Definition: wrtswtbl.hxx:113
const SvxBrushItem * GetBackground() const
Definition: wrtswtbl.hxx:130
const OUString & GetName() const
Definition: format.hxx:131
int nCount
const SwWriteTableCells & GetCells() const
Definition: wrtswtbl.hxx:135
void Width(tools::Long nNew)
Definition: swrect.hxx:189
const SwTable & GetTable() const
Definition: node.hxx:506
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
sal_uInt32 GetWidthOpt() const
Definition: wrtswtbl.hxx:91
static SVT_DLLPUBLIC OString CreateTableDataOptionsValNum(bool bValue, double fVal, sal_uInt32 nFormat, SvNumberFormatter &rFormatter, OUString *pNonConvertableChars=nullptr)
#define MAX_DEPTH
Definition: htmltabw.cxx:55
tools::Long GetHeight() const
Definition: wrtswtbl.hxx:81
Writer & OutCSS1_TableBGStyleOpt(Writer &rWrt, const SfxPoolItem &rHt)
Definition: css1atr.cxx:1794
sal_uInt16 GetPoolFormatId() const
Get and set Pool style IDs.
Definition: format.hxx:163
sal_Int16 GetVertOri() const
Definition: wrtswtbl.cxx:38
void ChangeParaToken(HtmlTokenId nNew)
Definition: htmlatr.cxx:158
Base class for various Writer styles.
Definition: format.hxx:46
#define OOO_STRING_SVTOOLS_HTML_colgroup
sal_uInt16 m_nTopBorder
Definition: wrtswtbl.hxx:112
Table of Contents - heading.
Definition: poolfmt.hxx:342
void OutImplicitMark(std::u16string_view rMark, const char *pMarkType)
Definition: wrthtml.cxx:1298
const editeng::SvxBorderLine * GetTop() const
Style of a layout element.
Definition: frmfmt.hxx:59
css::uno::Reference< css::container::XIndexContainer > mxFormComps
Definition: wrthtml.hxx:299
const editeng::SvxBorderLine * GetLeft() const
int i
Writer & OutHTML_SwTableNode(Writer &rWrt, SwTableNode &rNode, const SwFrameFormat *pFlyFrameFormat, const OUString *pCaption, bool bTopCaption)
Definition: htmltabw.cxx:873
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:108
#define OOO_STRING_SVTOOLS_HTML_table
SwNodeOffset GetIndex() const
Definition: node.hxx:292
tools::Long GetLeft() const
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:87
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:380
const SvxBrushItem * GetBackground() const
Definition: wrtswtbl.hxx:84
sal_uInt16 GetCol() const
Definition: wrtswtbl.hxx:76
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:457
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
sal_uInt16 GetRow() const
Definition: wrtswtbl.hxx:75
void Out_SwDoc(SwPaM *)
Definition: wrthtml.cxx:885
SwTableLines & GetTabLines()
Definition: swtable.hxx:201
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:112
std::vector< std::unique_ptr< SwWriteTableCell > > SwWriteTableCells
Definition: wrtswtbl.hxx:95
static sal_uInt32 ToPixel(sal_uInt32 nVal, const bool bVert)
Definition: htmlatr.cxx:2597
SwTableLines & GetTabLines()
Definition: swtable.hxx:450
void ClearNextNumInfo()
bool m_bOutOpts
Definition: wrthtml.hxx:361
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
#define OOO_STRING_SVTOOLS_HTML_O_align
#define OOO_STRING_SVTOOLS_HTML_division
SwFormat * DerivedFrom() const
Definition: format.hxx:128
void OutCSS1_TableFrameFormatOptions(const SwFrameFormat &rFrameFormat)
Definition: css1atr.cxx:2040
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:368
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
static bool lcl_TableBox_HasTabBorders(const SwTableBox *pBox, bool *pBorders)
Definition: htmltabw.cxx:197
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:471
constexpr TypedWhichId< SvxBrushItem > RES_BACKGROUND(105)
#define OOO_STRING_SVTOOLS_HTML_AL_right
static SVT_DLLPUBLIC SvStream & Out_String(SvStream &, const OUString &, OUString *pNonConvertableChars=nullptr)
void start(const OString &aElement)
bool IsTest1() const
Definition: viewopt.hxx:494
void OutCSS1_TableCellBordersAndBG(const SwFrameFormat &rFrameFormat, const SvxBrushItem *pBrushItem)
Definition: css1atr.cxx:2061
SvStream & WriteOString(std::string_view rStr)
constexpr tools::Long Height() const
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
unsigned char sal_uInt8
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:428
static const sal_Int16 Thin
void OutForm(bool bTagOn=true, const SwStartNode *pStNd=nullptr)
Definition: htmlforw.cxx:224
void IncIndentLevel()
Definition: wrthtml.hxx:507
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:177
#define OOO_STRING_SVTOOLS_HTML_center
sal_uInt16 GetColSpan() const
Definition: wrtswtbl.hxx:79
SwNodes & GetNodes()
Definition: doc.hxx:408
SvxFrameDirection GetHTMLDirection(SvxFrameDirection nDir) const
Definition: wrthtml.cxx:1437
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:418
OString GetNamespace() const
Determines the prefix string needed to respect the requested namespace alias.
Definition: wrthtml.cxx:1552
const SfxPoolItem & GetFormatAttr(sal_uInt16 nWhich, bool bInParents=true) const
If bInParents is FALSE, search only in this format for attribute.
Definition: format.cxx:367
SvStream & WriteChar(char nChar)
SvxBoxItem & rBoxItem
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
std::shared_ptr< SwUnoCursor > m_pCurrentPam
Definition: shellio.hxx:410
bool IsExportable() const
Definition: htmltbl.hxx:333
void setHeight(tools::Long nHeight)
Writer & OutHTML_NumberBulletListEnd(SwHTMLWriter &rWrt, const SwHTMLNumRuleInfo &rNextInfo)
SvStream & Strm()
Definition: writer.cxx:215
sal_uInt32 GetValue() const
bool m_bTextAttr
Definition: wrthtml.hxx:359
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
bool m_bCfgOutStyles
Definition: wrthtml.hxx:341
void OutDirection(SvxFrameDirection nDir)
Definition: wrthtml.cxx:1456
void OutAndSetDefList(sal_uInt16 nNewLvl)
Definition: htmlatr.cxx:120
Subgroup table.
Definition: poolfmt.hxx:341
SvxFrameDirection m_nDirection
Definition: wrthtml.hxx:335
#define OOO_STRING_SVTOOLS_HTML_dd
bool IsTextNode() const
Definition: node.hxx:646
static void Write(const OUString &rString, SvStream &rStream)
Definition: ww8scan.cxx:6713
SwNumRule * GetNumRule()
Definition: htmlnum.hxx:69
const editeng::SvxBorderLine * GetBottom() const
sal_uInt16 m_nDefListLvl
Definition: wrthtml.hxx:327
SwDoc * m_pDoc
Definition: shellio.hxx:408
const Size & GetSize() const
static bool lcl_TableLine_HasTabBorders(const SwTableLine *pLine, bool *pBorders)
Definition: htmltabw.cxx:222
bool m_bOutFlyFrame
Definition: wrthtml.hxx:366
sal_Int16 nValue
sal_uInt16 GetUpper() const
bool m_bBottomBorder
Definition: wrtswtbl.hxx:116
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74
Base class of the Writer document model elements.
Definition: node.hxx:81