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