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 sOut.append('<');
315 OString aTag(bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata);
316 sOut.append(rWrt.GetNamespace() + aTag);
317
318 // output ROW- and COLSPAN
319 if (nRowSpan > 1 && bCellRowSpan)
320 {
321 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan
322 "=\"" + OString::number(nRowSpan) + "\"");
323 }
324 if( nColSpan > 1 )
325 {
326 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_colspan
327 "=\"" + OString::number(nColSpan) + "\"");
328 }
329
330 tools::Long nWidth = 0;
331 bool bOutWidth = true;
332 sal_uInt32 nPercentWidth = SAL_MAX_UINT32;
333
334 if( m_bLayoutExport )
335 {
336 if( pCell->HasPercentWidthOpt() )
337 {
338 nPercentWidth = pCell->GetWidthOpt();
339 }
340 else
341 {
342 nWidth = pCell->GetWidthOpt();
343 if( !nWidth )
344 bOutWidth = false;
345 }
346 }
347 else
348 {
349 if( HasRelWidths() )
350 nPercentWidth = GetPercentWidth(nCol, nColSpan);
351 else
352 nWidth = GetAbsWidth( nCol, nColSpan );
353 }
354
355 if (rWrt.mbReqIF)
356 // ReqIF implies strict XHTML: no width for <td>.
357 bOutWidth = false;
358
359 tools::Long nHeight = pCell->GetHeight() > 0
360 ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan )
361 : 0;
362 Size aPixelSz( nWidth, nHeight );
363
364 // output WIDTH (Argh: only for Netscape)
365 if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() )
366 {
367 Size aOldSz( aPixelSz );
368 aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz,
369 MapMode(MapUnit::MapTwip) );
370 if( aOldSz.Width() && !aPixelSz.Width() )
371 aPixelSz.setWidth( 1 );
372 if( aOldSz.Height() && !aPixelSz.Height() )
373 aPixelSz.setHeight( 1 );
374 }
375
376 // output WIDTH: from layout or calculated
377 if( bOutWidth )
378 {
379 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\"");
380 if( nPercentWidth != SAL_MAX_UINT32 )
381 {
382 sOut.append(OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%");
383 }
384 else
385 {
386 sOut.append(static_cast<sal_Int32>(aPixelSz.Width()));
387 }
388 sOut.append("\"");
389 }
390
391 if (rWrt.mbReqIF)
392 {
393 // ReqIF implies strict XHTML: no height for <td>.
394 nHeight = 0;
395 }
396
397 if( nHeight )
398 {
399 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_height
400 "=\"" + OString::number(aPixelSz.Height()) + "\"");
401 }
402
403 const SfxItemSet& rItemSet = pBox->GetFrameFormat()->GetAttrSet();
404
405 // ALIGN is only outputted at the paragraphs from now on
406
407 // output VALIGN
408 if( bOutVAlign )
409 {
410 sal_Int16 eVertOri = pCell->GetVertOri();
411 if( text::VertOrientation::TOP==eVertOri || text::VertOrientation::BOTTOM==eVertOri )
412 {
413 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign
414 "=\"").append(text::VertOrientation::TOP==eVertOri ?
415 OOO_STRING_SVTOOLS_HTML_VA_top :
416 OOO_STRING_SVTOOLS_HTML_VA_bottom)
417 .append("\"");
418 }
419 }
420
421 rWrt.Strm().WriteOString( sOut );
422 sOut.setLength(0);
423
424 rWrt.m_bTextAttr = false;
425 rWrt.m_bOutOpts = true;
426 const SvxBrushItem *pBrushItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false );
427 if( !pBrushItem )
428 pBrushItem = pCell->GetBackground();
429
430 if( pBrushItem )
431 {
432 // output background
433 if (!rWrt.mbReqIF)
434 // Avoid non-CSS version in the ReqIF case.
435 rWrt.OutBackground( pBrushItem, false );
436
437 if (!rWrt.m_bCfgOutStyles)
438 pBrushItem = nullptr;
439 }
440
441 // tdf#132739 with rWrt.m_bCfgOutStyles of true bundle the brush item css
442 // properties into the same "style" tag as the borders so there is only one
443 // style tag
444 rWrt.OutCSS1_TableCellBordersAndBG(*pBox->GetFrameFormat(), pBrushItem);
445
446 sal_uInt32 nNumFormat = 0;
447 double nValue = 0.0;
448 bool bNumFormat = false, bValue = false;
449 if( const SwTableBoxNumFormat* pItem = rItemSet.GetItemIfSet( RES_BOXATR_FORMAT, false ) )
450 {
451 nNumFormat = pItem->GetValue();
452 bNumFormat = true;
453 }
454 if( const SwTableBoxValue* pItem = rItemSet.GetItemIfSet( RES_BOXATR_VALUE, false ) )
455 {
456 nValue = pItem->GetValue();
457 bValue = true;
458 if( !bNumFormat )
459 nNumFormat = pBox->GetFrameFormat()->GetTableBoxNumFormat().GetValue();
460 }
461
462 if ((bNumFormat || bValue) && !rWrt.mbXHTML)
463 {
464 sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValue, nValue,
465 nNumFormat, *rWrt.m_pDoc->GetNumberFormatter()));
466 }
467 sOut.append('>');
468 rWrt.Strm().WriteOString( sOut );
469 sOut.setLength(0);
470 rWrt.m_bLFPossible = true;
471
472 rWrt.IncIndentLevel(); // indent the content of <TD>...</TD>
473
474 if( pSttNd )
475 {
476 HTMLSaveData aSaveData( rWrt, pSttNd->GetIndex()+1,
477 pSttNd->EndOfSectionIndex() );
478 rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() );
479 }
480 else
481 {
482 sal_uInt16 nTWidth;
483 sal_uInt32 nBWidth;
484 sal_uInt16 nLSub, nRSub;
485 if( HasRelWidths() )
486 {
487 nTWidth = 100;
488 nBWidth = GetRawWidth( nCol, nColSpan );
489 nLSub = 0;
490 nRSub = 0;
491 }
492 else
493 {
494 nTWidth = GetAbsWidth( nCol, nColSpan );
495 nBWidth = nTWidth;
496 nLSub = GetLeftSpace( nCol );
497 nRSub = GetRightSpace( nCol, nColSpan );
498 }
499
500 SwHTMLWrtTable aTableWrt( pBox->GetTabLines(), nTWidth,
501 nBWidth, HasRelWidths(), nLSub, nRSub, /*nNumOfRowsToRepeat*/0 );
502 aTableWrt.Write( rWrt );
503 }
504
505 rWrt.DecIndentLevel(); // indent the content of <TD>...</TD>
506
507 if( rWrt.m_bLFPossible )
508 rWrt.OutNewLine();
510 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false);
511 rWrt.m_bLFPossible = true;
512}
513
514// output a line as lines
515void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt,
516 const SwWriteTableCells& rCells,
517 const SvxBrushItem *pBrushItem,
518 sal_uInt16& rSkipRows ) const
519{
520 // If the line contains more the one cell and all cells have the same
521 // alignment, then output the VALIGN at the line instead of the cell.
522 sal_Int16 eRowVertOri = text::VertOrientation::NONE;
523 if( rCells.size() > 1 )
524 {
525 for (SwWriteTableCells::size_type nCell = 0; nCell < rCells.size(); ++nCell)
526 {
527 sal_Int16 eCellVertOri = rCells[nCell]->GetVertOri();
528 if( 0==nCell )
529 {
530 eRowVertOri = eCellVertOri;
531 }
532 else if( eRowVertOri != eCellVertOri )
533 {
534 eRowVertOri = text::VertOrientation::NONE;
535 break;
536 }
537 }
538 }
539
540 rWrt.OutNewLine(); // <TR> in new line
541 rWrt.Strm().WriteChar( '<' ).WriteOString( Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow) );
542 if( pBrushItem )
543 {
544 if (!rWrt.mbXHTML)
545 {
546 rWrt.OutBackground(pBrushItem, false);
547 }
548
549 rWrt.m_bTextAttr = false;
550 rWrt.m_bOutOpts = true;
551 if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML)
552 OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
553 }
554
555 if( text::VertOrientation::TOP==eRowVertOri || text::VertOrientation::BOTTOM==eRowVertOri )
556 {
557 OStringBuffer sOut;
558 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign
559 "=\"").append(text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom)
560 .append("\"");
561 rWrt.Strm().WriteOString( sOut );
562 sOut.setLength(0);
563 }
564
565 rWrt.Strm().WriteChar( '>' );
566
567 rWrt.IncIndentLevel(); // indent content of <TR>...</TR>
568
569 bool bCellRowSpan = true;
570 if (!rCells.empty() && rCells[0]->GetRowSpan() > 1)
571 {
572 // Skip the rowspan attrs of <td> elements if they are the same for every cell of this row.
573 bCellRowSpan = std::adjacent_find(rCells.begin(), rCells.end(),
574 [](const std::unique_ptr<SwWriteTableCell>& pA,
575 const std::unique_ptr<SwWriteTableCell>& pB)
576 { return pA->GetRowSpan() != pB->GetRowSpan(); })
577 != rCells.end();
578 if (!bCellRowSpan)
579 {
580 // If no rowspan is written, then skip rows which would only contain covered cells, but
581 // not the current row.
582 rSkipRows = rCells[0]->GetRowSpan() - 1;
583 }
584 }
585
586 for (const auto &rpCell : rCells)
587 {
588 OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri, bCellRowSpan);
589 }
590
591 rWrt.DecIndentLevel(); // indent content of <TR>...</TR>
592
593 rWrt.OutNewLine(); // </TR> in new line
594 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), false );
595}
596
597void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign,
598 bool bTHead, const SwFrameFormat *pFrameFormat,
599 const OUString *pCaption, bool bTopCaption,
600 sal_uInt16 nHSpace, sal_uInt16 nVSpace ) const
601{
602 // determine value of RULES
603 bool bRowsHaveBorder = false;
604 bool bRowsHaveBorderOnly = true;
605 SwWriteTableRow *pRow = m_aRows[0].get();
606 for( SwWriteTableRows::size_type nRow=1; nRow < m_aRows.size(); ++nRow )
607 {
608 SwWriteTableRow *pNextRow = m_aRows[nRow].get();
609 bool bBorder = ( pRow->m_bBottomBorder || pNextRow->m_bTopBorder );
610 bRowsHaveBorder |= bBorder;
611 bRowsHaveBorderOnly &= bBorder;
612
613 sal_uInt16 nBorder2 = pRow->m_bBottomBorder ? pRow->m_nBottomBorder : USHRT_MAX;
614 if( pNextRow->m_bTopBorder && pNextRow->m_nTopBorder < nBorder2 )
615 nBorder2 = pNextRow->m_nTopBorder;
616
617 pRow->m_bBottomBorder = bBorder;
618 pRow->m_nBottomBorder = nBorder2;
619
620 pNextRow->m_bTopBorder = bBorder;
621 pNextRow->m_nTopBorder = nBorder2;
622
623 pRow = pNextRow;
624 }
625
626 bool bColsHaveBorder = false;
627 bool bColsHaveBorderOnly = true;
628 SwWriteTableCol *pCol = m_aCols[0].get();
629 for( SwWriteTableCols::size_type nCol=1; nCol<m_aCols.size(); ++nCol )
630 {
631 SwWriteTableCol *pNextCol = m_aCols[nCol].get();
632 bool bBorder = ( pCol->m_bRightBorder || pNextCol->m_bLeftBorder );
633 bColsHaveBorder |= bBorder;
634 bColsHaveBorderOnly &= bBorder;
635 pCol->m_bRightBorder = bBorder;
636 pNextCol->m_bLeftBorder = bBorder;
637 pCol = pNextCol;
638 }
639
640 // close previous numbering, etc
641 rWrt.ChangeParaToken( HtmlTokenId::NONE );
642
643 if( rWrt.m_bLFPossible )
644 rWrt.OutNewLine(); // <TABLE> in new line
645 OStringBuffer sOut("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table);
646
647 const SvxFrameDirection nOldDirection = rWrt.m_nDirection;
648 if( pFrameFormat )
649 rWrt.m_nDirection = rWrt.GetHTMLDirection( pFrameFormat->GetAttrSet() );
650 if( rWrt.m_bOutFlyFrame || nOldDirection != rWrt.m_nDirection )
651 {
652 rWrt.Strm().WriteOString( sOut );
653 sOut.setLength(0);
654 rWrt.OutDirection( rWrt.m_nDirection );
655 }
656
657 // output ALIGN=
658 if( text::HoriOrientation::RIGHT == eAlign )
659 {
660 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
661 "=\"" OOO_STRING_SVTOOLS_HTML_AL_right "\"");
662 }
663 else if( text::HoriOrientation::CENTER == eAlign )
664 {
665 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
666 "=\"" OOO_STRING_SVTOOLS_HTML_AL_center "\"");
667 }
668 else if( text::HoriOrientation::LEFT == eAlign )
669 {
670 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align
671 "=\"" OOO_STRING_SVTOOLS_HTML_AL_left "\"");
672 }
673
674 // output WIDTH: from layout or calculated
675 if( m_nTabWidth )
676 {
677 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\"");
678 if( HasRelWidths() )
679 sOut.append(OString::number(static_cast<sal_Int32>(m_nTabWidth)) + "%");
681 {
682 sal_Int32 nPixWidth = Application::GetDefaultDevice()->LogicToPixel(
683 Size(m_nTabWidth,0), MapMode(MapUnit::MapTwip) ).Width();
684 if( !nPixWidth )
685 nPixWidth = 1;
686
687 sOut.append(nPixWidth);
688 }
689 else
690 {
691 OSL_ENSURE( Application::GetDefaultDevice(), "no Application-Window!?" );
692 sOut.append("100%");
693 }
694 sOut.append("\"");
695 }
696
697 if( (nHSpace || nVSpace) && Application::GetDefaultDevice() && !rWrt.mbReqIF)
698 {
699 Size aPixelSpc =
701 MapMode(MapUnit::MapTwip) );
702 if( !aPixelSpc.Width() && nHSpace )
703 aPixelSpc.setWidth( 1 );
704 if( !aPixelSpc.Height() && nVSpace )
705 aPixelSpc.setHeight( 1 );
706
707 if( aPixelSpc.Width() )
708 {
709 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_hspace
710 "=\"" + OString::number(aPixelSpc.Width()) + "\"");
711 }
712
713 if( aPixelSpc.Height() )
714 {
715 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_vspace
716 "=\"" + OString::number(aPixelSpc.Height()) + "\"");
717 }
718 }
719
720 // output CELLPADDING: from layout or calculated
721 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellpadding
722 "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellPadding,false)) + "\"");
723
724 // output CELLSPACING: from layout or calculated
725 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing
726 "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellSpacing,false)) + "\"");
727
728 rWrt.Strm().WriteOString( sOut );
729 sOut.setLength(0);
730
731 // output background
732 if( pFrameFormat )
733 {
734 if (!rWrt.mbXHTML)
735 {
736 rWrt.OutBackground(pFrameFormat->GetAttrSet(), false);
737 }
738
739 if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML)
740 {
741 rWrt.OutCSS1_TableFrameFormatOptions( *pFrameFormat );
742 }
743 }
744
745 sOut.append('>');
746 rWrt.Strm().WriteOString( sOut );
747 sOut.setLength(0);
748
749 rWrt.IncIndentLevel(); // indent content of table
750
751 // output caption
752 if( pCaption && !pCaption->isEmpty() )
753 {
754 rWrt.OutNewLine(); // <CAPTION> in new line
755 OStringBuffer sOutStr(OOO_STRING_SVTOOLS_HTML_caption);
756 sOutStr.append(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"")
757 .append(bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom)
758 .append("\"");
759 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOutStr) );
760 HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption );
761 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption), false );
762 }
763
764 const SwWriteTableCols::size_type nCols = m_aCols.size();
765
766 // output <COLGRP>/<COL>: If exporting via layout only when during import
767 // some were there, otherwise always.
768 bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly);
769 if( m_bColTags )
770 {
771 if( bColGroups )
772 {
773 rWrt.OutNewLine(); // <COLGRP> in new line
774 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) );
775
776 rWrt.IncIndentLevel(); // indent content of <COLGRP>
777 }
778
779 for( SwWriteTableCols::size_type nCol=0; nCol<nCols; ++nCol )
780 {
781 rWrt.OutNewLine(); // </COL> in new line
782
783 const SwWriteTableCol *pColumn = m_aCols[nCol].get();
784
785 HtmlWriter html(rWrt.Strm(), rWrt.maNamespace);
786 html.prettyPrint(false); // We add newlines ourself
787 html.start(OOO_STRING_SVTOOLS_HTML_col);
788
789 sal_uInt32 nWidth;
790 bool bRel;
791 if( m_bLayoutExport )
792 {
793 bRel = pColumn->HasRelWidthOpt();
794 nWidth = pColumn->GetWidthOpt();
795 }
796 else
797 {
798 bRel = HasRelWidths();
799 nWidth = bRel ? GetRelWidth(nCol,1) : GetAbsWidth(nCol,1);
800 }
801
802 if( bRel )
803 html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, Concat2View(OString::number(nWidth) + "*"));
804 else
805 html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth,false)));
806 html.end();
807
808 if( bColGroups && pColumn->m_bRightBorder && nCol<nCols-1 )
809 {
810 rWrt.DecIndentLevel(); // indent content of <COLGRP>
811 rWrt.OutNewLine(); // </COLGRP> in new line
812 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup),
813 false );
814 rWrt.OutNewLine(); // <COLGRP> in new line
815 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) );
816 rWrt.IncIndentLevel(); // indent content of <COLGRP>
817 }
818 }
819 if( bColGroups )
820 {
821 rWrt.DecIndentLevel(); // indent content of <COLGRP>
822
823 rWrt.OutNewLine(); // </COLGRP> in new line
824 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup),
825 false );
826 }
827 }
828
829 // output the lines as table lines
830
831 // Output <TBODY>?
832 bool bTSections = (bRowsHaveBorder && !bRowsHaveBorderOnly);
833 bool bTBody = bTSections;
834
835 // If sections must be outputted, then a THEAD around the first line only
836 // can be outputted if there is a line below the cell.
837 if( bTHead &&
838 (bTSections || bColGroups) &&
839 m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->m_bBottomBorder )
840 bTHead = false;
841
842 // Output <TBODY> only if <THEAD> is outputted.
843 bTSections |= bTHead;
844
845 if( bTSections )
846 {
847 rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line
849 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag));
850
851 rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA>
852 }
853
854 sal_uInt16 nSkipRows = 0;
855 for( SwWriteTableRows::size_type nRow = 0; nRow < m_aRows.size(); ++nRow )
856 {
857 const SwWriteTableRow *pRow2 = m_aRows[nRow].get();
858
859 if (nSkipRows == 0)
860 {
861 OutTableCells(rWrt, pRow2->GetCells(), pRow2->GetBackground(), nSkipRows);
862 }
863 else
864 {
865 --nSkipRows;
866 }
867 if( !m_nCellSpacing && nRow < m_aRows.size()-1 && pRow2->m_bBottomBorder &&
869 {
870 for( auto nCnt = (pRow2->m_nBottomBorder / SvxBorderLineWidth::Thin) - 1; nCnt; --nCnt )
871 {
872 rWrt.OutNewLine();
873 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow ));
874 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow),
875 false );
876 }
877 }
878 if( ( (bTHead && nRow==m_nHeadEndRow) ||
879 (bTBody && pRow2->m_bBottomBorder) ) &&
880 nRow < m_aRows.size()-1 )
881 {
882 rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA>
883 rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line
885 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false);
886 rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line
887
888 if( bTHead && nRow==m_nHeadEndRow )
889 bTHead = false;
890
892 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag));
893 rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA>
894 }
895 }
896
897 if( bTSections )
898 {
899 rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA>
900
901 rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line
903 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false);
904 }
905
906 rWrt.DecIndentLevel(); // indent content of <TABLE>
907
908 rWrt.OutNewLine(); // </TABLE> in new line
909 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table), false );
910
911 rWrt.m_nDirection = nOldDirection;
912}
913
915 const SwFrameFormat *pFlyFrameFormat,
916 const OUString *pCaption, bool bTopCaption )
917{
918
919 SwTable& rTable = rNode.GetTable();
920
921 rWrt.m_bOutTable = true;
922
923 // The horizontal alignment of the frame (if exists) has priority.
924 // NONE means that no horizontal alignment was outputted.
925 sal_Int16 eFlyHoriOri = text::HoriOrientation::NONE;
926 css::text::WrapTextMode eSurround = css::text::WrapTextMode_NONE;
927 sal_uInt8 nFlyPercentWidth = 0;
928 tools::Long nFlyWidth = 0;
929 sal_uInt16 nFlyHSpace = 0;
930 sal_uInt16 nFlyVSpace = 0;
931 if( pFlyFrameFormat )
932 {
933 eSurround = pFlyFrameFormat->GetSurround().GetSurround();
934 const SwFormatFrameSize& rFrameSize = pFlyFrameFormat->GetFrameSize();
935 nFlyPercentWidth = rFrameSize.GetWidthPercent();
936 nFlyWidth = rFrameSize.GetSize().Width();
937
938 eFlyHoriOri = pFlyFrameFormat->GetHoriOrient().GetHoriOrient();
939 if( text::HoriOrientation::NONE == eFlyHoriOri )
940 eFlyHoriOri = text::HoriOrientation::LEFT;
941
942 const SvxLRSpaceItem& rLRSpace = pFlyFrameFormat->GetLRSpace();
943 nFlyHSpace = static_cast< sal_uInt16 >((rLRSpace.GetLeft() + rLRSpace.GetRight()) / 2);
944
945 const SvxULSpaceItem& rULSpace = pFlyFrameFormat->GetULSpace();
946 nFlyVSpace = (rULSpace.GetUpper() + rULSpace.GetLower()) / 2;
947 }
948
949 // maybe open a FORM
950 bool bPreserveForm = false;
951 if( !rWrt.m_bPreserveForm )
952 {
953 rWrt.OutForm( true, &rNode );
954 bPreserveForm = rWrt.mxFormComps.is();
955 rWrt.m_bPreserveForm = bPreserveForm;
956 }
957
958 SwFrameFormat *pFormat = rTable.GetFrameFormat();
959
960 const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize();
961 tools::Long nWidth = rFrameSize.GetSize().Width();
962 sal_uInt8 nPercentWidth = rFrameSize.GetWidthPercent();
963 sal_uInt16 nBaseWidth = o3tl::narrowing<sal_uInt16>(nWidth);
964
965 sal_Int16 eTabHoriOri = pFormat->GetHoriOrient().GetHoriOrient();
966
967 // text::HoriOrientation::NONE and text::HoriOrientation::FULL tables need relative widths
968 sal_uInt16 nNewDefListLvl = 0;
969 bool bRelWidths = false;
970 bool bCheckDefList = false;
971 switch( eTabHoriOri )
972 {
973 case text::HoriOrientation::FULL:
974 // Tables with automatic alignment become tables with 100% width.
975 bRelWidths = true;
976 nWidth = 100;
977 eTabHoriOri = text::HoriOrientation::LEFT;
978 break;
980 {
981 const SvxLRSpaceItem& aLRItem = pFormat->GetLRSpace();
982 if( aLRItem.GetRight() )
983 {
984 // The table width is defined on the basis of the left and
985 // right margin. Therefore we try to define the actual
986 // width of the table. If that's not possible we transform
987 // it to a table with width 100%.
988 nWidth = pFormat->FindLayoutRect(true).Width();
989 if( !nWidth )
990 {
991 bRelWidths = true;
992 nWidth = 100;
993 }
994
995 }
996 else if( nPercentWidth )
997 {
998 // Without a right border the %-width is maintained.
999 nWidth = nPercentWidth;
1000 bRelWidths = true;
1001 }
1002 else
1003 {
1004 // Without a right margin also an absolute width is maintained.
1005 // We still try to define the actual width via the layout.
1006 tools::Long nRealWidth = pFormat->FindLayoutRect(true).Width();
1007 if( nRealWidth )
1008 nWidth = nRealWidth;
1009 }
1010 bCheckDefList = true;
1011 }
1012 break;
1013 case text::HoriOrientation::LEFT_AND_WIDTH:
1014 eTabHoriOri = text::HoriOrientation::LEFT;
1015 bCheckDefList = true;
1016 [[fallthrough]];
1017 default:
1018 // In all other case it's possible to use directly an absolute
1019 // or relative width.
1020 if( nPercentWidth )
1021 {
1022 bRelWidths = true;
1023 nWidth = nPercentWidth;
1024 }
1025 break;
1026 }
1027
1028 if( bCheckDefList )
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.GetNextNumInfo()->IsRestart() ||
1038 rWrt.GetNumInfo().GetNumRule() !=
1039 rWrt.GetNextNumInfo()->GetNumRule()) ) ) )
1040 {
1041 // If the paragraph before the table is not numbered or the
1042 // paragraph after the table starts with a new numbering or with
1043 // a different rule, we can maintain the indentation with a DL.
1044 // Otherwise we keep the indentation of the numbering.
1045 nNewDefListLvl = static_cast< sal_uInt16 >(
1046 (aLRItem.GetLeft() + (rWrt.m_nDefListMargin/2)) /
1047 rWrt.m_nDefListMargin );
1048 }
1049 }
1050
1051 if( !pFlyFrameFormat && nNewDefListLvl != rWrt.m_nDefListLvl )
1052 rWrt.OutAndSetDefList( nNewDefListLvl );
1053
1054 if( nNewDefListLvl )
1055 {
1056 if( rWrt.m_bLFPossible )
1057 rWrt.OutNewLine();
1059 rWrt.IncIndentLevel();
1060 }
1061
1062 // eFlyHoriOri and eTabHoriOri now only contain the values of
1063 // LEFT/CENTER and RIGHT!
1064 if( eFlyHoriOri!=text::HoriOrientation::NONE )
1065 {
1066 eTabHoriOri = eFlyHoriOri;
1067 // MIB 4.7.97: If the table has a relative width, then the width is
1068 // adjusted to the width of the frame, therefore we export its width.
1069 // If fixed width, the table width is relevant. Whoever puts tables with
1070 // relative width <100% into frames is to blame when the result looks bad.
1071 if( bRelWidths )
1072 {
1073 nWidth = nFlyPercentWidth ? nFlyPercentWidth : nFlyWidth;
1074 bRelWidths = nFlyPercentWidth > 0;
1075 }
1076 }
1077
1078 sal_Int16 eDivHoriOri = text::HoriOrientation::NONE;
1079 switch( eTabHoriOri )
1080 {
1081 case text::HoriOrientation::LEFT:
1082 // If a left-aligned table has no right sided flow, then we don't need
1083 // an ALIGN=LEFT in the table.
1084 if( eSurround==css::text::WrapTextMode_NONE || eSurround==css::text::WrapTextMode_LEFT )
1085 eTabHoriOri = text::HoriOrientation::NONE;
1086 break;
1087 case text::HoriOrientation::RIGHT:
1088 // Something like that also applies to right-aligned tables,
1089 // here we use a <DIV ALIGN=RIGHT> instead.
1090 if( eSurround==css::text::WrapTextMode_NONE || eSurround==css::text::WrapTextMode_RIGHT )
1091 {
1092 eDivHoriOri = text::HoriOrientation::RIGHT;
1093 eTabHoriOri = text::HoriOrientation::NONE;
1094 }
1095 break;
1096 case text::HoriOrientation::CENTER:
1097 // Almost nobody understands ALIGN=CENTER, therefore we abstain
1098 // from it and use a <CENTER>.
1099 eDivHoriOri = text::HoriOrientation::CENTER;
1100 eTabHoriOri = text::HoriOrientation::NONE;
1101 break;
1102 default:
1103 ;
1104 }
1105 if( text::HoriOrientation::NONE==eTabHoriOri )
1106 nFlyHSpace = nFlyVSpace = 0;
1107
1108 if( !pFormat->GetName().isEmpty() )
1109 rWrt.OutImplicitMark( pFormat->GetName(), "table" );
1110
1111 if( text::HoriOrientation::NONE!=eDivHoriOri )
1112 {
1113 if( rWrt.m_bLFPossible )
1114 rWrt.OutNewLine(); // <CENTER> in new line
1115 if( text::HoriOrientation::CENTER==eDivHoriOri )
1116 {
1117 if (!rWrt.mbXHTML)
1118 {
1119 // Not XHTML's css center: start <center>.
1121 }
1122 }
1123 else
1124 {
1125 OStringLiteral sOut = OOO_STRING_SVTOOLS_HTML_division
1128 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut) );
1129 }
1130 rWrt.IncIndentLevel(); // indent content of <CENTER>
1131 rWrt.m_bLFPossible = true;
1132 }
1133
1134 // If the table isn't in a frame, then you always can output a LF.
1135 if( text::HoriOrientation::NONE==eTabHoriOri )
1136 rWrt.m_bLFPossible = true;
1137
1138 const SwHTMLTableLayout *pLayout = rTable.GetHTMLTableLayout();
1139
1140#ifdef DBG_UTIL
1141 {
1143 if ( pSh && pSh->GetViewOptions()->IsTest1() )
1144 pLayout = nullptr;
1145 }
1146#endif
1147
1148 if( pLayout && pLayout->IsExportable() )
1149 {
1150 SwHTMLWrtTable aTableWrt( pLayout );
1151 aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0,
1152 pFormat, pCaption, bTopCaption,
1153 nFlyHSpace, nFlyVSpace );
1154 }
1155 else
1156 {
1157 SwHTMLWrtTable aTableWrt( rTable.GetTabLines(), nWidth,
1158 nBaseWidth, bRelWidths, 0, 0, rTable.GetRowsToRepeat() );
1159 aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0,
1160 pFormat, pCaption, bTopCaption,
1161 nFlyHSpace, nFlyVSpace );
1162 }
1163
1164 // If the table wasn't in a frame, then you always can output a LF.
1165 if( text::HoriOrientation::NONE==eTabHoriOri )
1166 rWrt.m_bLFPossible = true;
1167
1168 if( text::HoriOrientation::NONE!=eDivHoriOri )
1169 {
1170 rWrt.DecIndentLevel(); // indent content of <CENTER>
1171 rWrt.OutNewLine(); // </CENTER> in new line
1172 OString aTag = text::HoriOrientation::CENTER == eDivHoriOri
1175 if (!rWrt.mbXHTML || eDivHoriOri != text::HoriOrientation::CENTER)
1176 {
1177 // Not XHTML's css center: end <center>.
1178 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false);
1179 }
1180 rWrt.m_bLFPossible = true;
1181 }
1182
1183 // move Pam behind the table
1184 rWrt.m_pCurrentPam->GetPoint()->Assign( *rNode.EndOfSectionNode() );
1185
1186 if (nNewDefListLvl)
1187 {
1188 rWrt.DecIndentLevel();
1189 if (rWrt.m_bLFPossible)
1190 rWrt.OutNewLine();
1191 // close the dd element
1192 HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd), false);
1193 }
1194
1195 if( bPreserveForm )
1196 {
1197 rWrt.m_bPreserveForm = false;
1198 rWrt.OutForm( false );
1199 }
1200
1201 rWrt.m_bOutTable = false;
1202
1203 if( rWrt.GetNextNumInfo() &&
1204 !rWrt.GetNextNumInfo()->IsRestart() &&
1205 rWrt.GetNextNumInfo()->GetNumRule() ==
1206 rWrt.GetNumInfo().GetNumRule() )
1207 {
1208 // If the paragraph after the table is numbered with the same rule as the
1209 // one before, then the NumInfo of the next paragraph holds the level of
1210 // paragraph before the table. Therefore NumInfo must be fetched again
1211 // to maybe close the Num list.
1212 rWrt.ClearNextNumInfo();
1213 rWrt.FillNextNumInfo();
1215 }
1216 return rWrt;
1217}
1218
1219/* 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:420
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:413
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1423
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:106
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:62
SwRect FindLayoutRect(const bool bPrtArea=false, const Point *pPoint=nullptr) const
Definition: atrfrm.cxx:2742
bool IsRestart() const
Definition: htmlnum.hxx:78
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:158
sal_Int32 m_nDefListMargin
Definition: wrthtml.hxx:342
void IncIndentLevel()
Definition: wrthtml.hxx:526
void OutDirection(SvxFrameDirection nDir)
Definition: wrthtml.cxx:1487
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:2039
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:530
OString GetNamespace() const
Determines the prefix string needed to respect the requested namespace alias.
Definition: wrthtml.cxx:1583
void Out_SwDoc(SwPaM *)
Definition: wrthtml.cxx:895
void FillNextNumInfo()
bool mbReqIF
If the ReqIF subset of XHTML should be written.
Definition: wrthtml.hxx:414
SwHTMLNumRuleInfo & GetNumInfo()
Definition: wrthtml.hxx:557
void OutNewLine(bool bCheck=false)
Definition: wrthtml.cxx:1534
static sal_uInt32 ToPixel(sal_uInt32 nVal, const bool bVert)
Definition: htmlatr.cxx:2619
OString maNamespace
XML namespace, in case of XHTML.
Definition: wrthtml.hxx:412
void ClearNextNumInfo()
SwHTMLNumRuleInfo * GetNextNumInfo()
Definition: wrthtml.hxx:561
SvxFrameDirection GetHTMLDirection(SvxFrameDirection nDir) const
Definition: wrthtml.cxx:1468
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:1327
void OutCSS1_TableCellBordersAndBG(const SwFrameFormat &rFrameFormat, const SvxBrushItem *pBrushItem)
Writes the borders and background for table cells.
Definition: css1atr.cxx:2071
void OutBackground(const SvxBrushItem *pBrushItem, bool bGraphic)
Definition: wrthtml.cxx:1375
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:687
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:728
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:733
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:436
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:474
SwTableLines & GetTabLines()
Definition: swtable.hxx:467
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:488
SwTableLine is one table row in the document model.
Definition: swtable.hxx:374
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:396
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:384
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:660
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:434
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:214
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:1797
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_dd
#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:914
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