LibreOffice Module sw (master) 1
xmltbli.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
22#include <com/sun/star/frame/XModel.hpp>
23#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
24#include <com/sun/star/lang/XMultiServiceFactory.hpp>
25#include <com/sun/star/text/XTextTable.hpp>
26#include <com/sun/star/table/XCellRange.hpp>
28#include <o3tl/numeric.hxx>
29#include <o3tl/safeint.hxx>
30#include <sal/log.hxx>
31#include <svl/itemset.hxx>
32#include <svl/numformat.hxx>
33#include <svl/zformat.hxx>
36#include <utility>
39
40#include <xmloff/families.hxx>
41#include <xmloff/xmluconv.hxx>
42#include <xmloff/i18nmap.hxx>
43#include <editeng/protitem.hxx>
44#include <editeng/lrspitem.hxx>
45#include <poolfmt.hxx>
46#include <fmtfsize.hxx>
47#include <fmtornt.hxx>
48#include <fmtfordr.hxx>
49#include <doc.hxx>
53#include <swtable.hxx>
54#include <swtblfmt.hxx>
55#include <pam.hxx>
56#include <unotbl.hxx>
57#include <unotextrange.hxx>
58#include <cellatr.hxx>
59#include <swddetbl.hxx>
60#include <ddefld.hxx>
61#include <sfx2/linkmgr.hxx>
62#include "xmlimp.hxx"
63#include "xmltbli.hxx"
64#include <vcl/svapp.hxx>
65#include <ndtxt.hxx>
66#include <unotextcursor.hxx>
67#include <SwStyleNameMapper.hxx>
68
69#include <algorithm>
70#include <vector>
71#include <memory>
72
73#include <limits.h>
74
75
76using namespace ::com::sun::star;
77using namespace ::com::sun::star::uno;
78using namespace ::com::sun::star::lang;
79using namespace ::com::sun::star::text;
80using namespace ::com::sun::star::table;
81using namespace ::com::sun::star::xml::sax;
82using namespace ::xmloff::token;
83
85{
86 OUString m_aStyleName;
87
88 OUString m_StringValue;
89
90 OUString m_sFormula; // cell formula; valid if length > 0
91 double m_dValue; // formula value
92
94
96 sal_uInt32 m_nRowSpan;
97 sal_uInt32 m_nColSpan;
98
99 bool m_bProtected : 1;
100 bool m_bHasValue; // determines whether dValue attribute is valid
103
104public:
105
106 SwXMLTableCell_Impl( sal_uInt32 nRSpan=1, sal_uInt32 nCSpan=1 ) :
107 m_dValue( 0.0 ),
108 m_pStartNode( nullptr ),
109 m_nRowSpan( nRSpan ),
110 m_nColSpan( nCSpan ),
111 m_bProtected( false ),
112 m_bHasValue( false ),
113 mbCovered( false )
114 , m_bHasStringValue(false)
115 {}
116
117 inline void Set( const OUString& rStyleName,
118 sal_uInt32 nRSpan, sal_uInt32 nCSpan,
119 const SwStartNode *pStNd, SwXMLTableContext *pTable,
120 bool bProtect,
121 const OUString* pFormula,
122 bool bHasValue,
123 bool bCovered,
124 double dVal,
125 OUString const*const pStringValue);
126
127 bool IsUsed() const { return m_pStartNode!=nullptr ||
128 m_xSubTable.is() || m_bProtected;}
129
130 sal_uInt32 GetRowSpan() const { return m_nRowSpan; }
131 void SetRowSpan( sal_uInt32 nSet ) { m_nRowSpan = nSet; }
132 sal_uInt32 GetColSpan() const { return m_nColSpan; }
133 void SetStyleName(const OUString& rStyleName) { m_aStyleName = rStyleName; }
134 const OUString& GetStyleName() const { return m_aStyleName; }
135 const OUString& GetFormula() const { return m_sFormula; }
136 double GetValue() const { return m_dValue; }
137 bool HasValue() const { return m_bHasValue; }
138 bool IsProtected() const { return m_bProtected; }
139 bool IsCovered() const { return mbCovered; }
140 bool HasStringValue() const { return m_bHasStringValue; }
141 OUString const* GetStringValue() const {
142 return m_bHasStringValue ? &m_StringValue : nullptr;
143 }
144
145 const SwStartNode *GetStartNode() const { return m_pStartNode; }
146 inline void SetStartNode( const SwStartNode *pSttNd );
147
148 inline SwXMLTableContext *GetSubTable() const;
149
150 inline void Dispose();
151};
152
153inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName,
154 sal_uInt32 nRSpan, sal_uInt32 nCSpan,
155 const SwStartNode *pStNd,
156 SwXMLTableContext *pTable,
157 bool bProtect,
158 const OUString* pFormula,
159 bool bHasVal,
160 bool bCov,
161 double dVal,
162 OUString const*const pStringValue )
163{
164 m_aStyleName = rStyleName;
165 m_nRowSpan = nRSpan;
166 m_nColSpan = nCSpan;
167 m_pStartNode = pStNd;
168 m_xSubTable = pTable;
169 m_dValue = dVal;
170 m_bHasValue = bHasVal;
171 mbCovered = bCov;
172 if (pStringValue)
173 {
174 m_StringValue = *pStringValue;
175 }
176 m_bHasStringValue = (pStringValue != nullptr);
177 m_bProtected = bProtect;
178
179 // set formula, if valid
180 if (pFormula != nullptr)
181 {
182 m_sFormula = *pFormula;
183 }
184}
185
187{
188 m_pStartNode = pSttNd;
189 m_xSubTable = nullptr;
190}
191
193{
194 return static_cast<SwXMLTableContext *>(m_xSubTable.get());
195}
196
198{
199 if( m_xSubTable.is() )
200 m_xSubTable = nullptr;
201}
202
204{
205 OUString m_aStyleName;
207 std::vector<std::unique_ptr<SwXMLTableCell_Impl>> m_Cells;
209
210public:
211
212 SwXMLTableRow_Impl( OUString aStyleName, sal_uInt32 nCells,
213 const OUString *pDfltCellStyleName = nullptr );
214
215 inline SwXMLTableCell_Impl *GetCell( sal_uInt32 nCol );
216
217 inline void Set( const OUString& rStyleName,
218 const OUString& rDfltCellStyleName );
219
220 void Expand( sal_uInt32 nCells, bool bOneCell );
221
222 void SetSplitable( bool bSet ) { m_bSplitable = bSet; }
223 bool IsSplitable() const { return m_bSplitable; }
224
225 const OUString& GetStyleName() const { return m_aStyleName; }
226 const OUString& GetDefaultCellStyleName() const { return m_aDefaultCellStyleName; }
227
228 void Dispose();
229};
230
232 sal_uInt32 nCells,
233 const OUString *pDfltCellStyleName ) :
234 m_aStyleName(std::move( aStyleName )),
235 m_bSplitable( false )
236{
237 if( pDfltCellStyleName )
238 m_aDefaultCellStyleName = *pDfltCellStyleName;
239 OSL_ENSURE( nCells <= USHRT_MAX,
240 "SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" );
241 if( nCells > USHRT_MAX )
242 nCells = USHRT_MAX;
243
244 for( sal_uInt32 i=0U; i<nCells; ++i )
245 {
246 m_Cells.push_back(std::make_unique<SwXMLTableCell_Impl>());
247 }
248}
249
251{
252 OSL_ENSURE( nCol < USHRT_MAX,
253 "SwXMLTableRow_Impl::GetCell: column number is too big" );
254 // #i95726# - some fault tolerance
255 OSL_ENSURE( nCol < m_Cells.size(),
256 "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
257 return nCol < m_Cells.size() ? m_Cells[nCol].get() : nullptr;
258}
259
260void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells, bool bOneCell )
261{
262 OSL_ENSURE( nCells <= USHRT_MAX,
263 "SwXMLTableRow_Impl::Expand: too many cells" );
264 if( nCells > USHRT_MAX )
265 nCells = USHRT_MAX;
266
267 sal_uInt32 nColSpan = nCells - m_Cells.size();
268 for (size_t i = m_Cells.size(); i < nCells; ++i)
269 {
270 m_Cells.push_back(std::make_unique<SwXMLTableCell_Impl>(
271 1UL, bOneCell ? nColSpan : 1UL));
272 nColSpan--;
273 }
274
275 OSL_ENSURE( nCells <= m_Cells.size(),
276 "SwXMLTableRow_Impl::Expand: wrong number of cells" );
277}
278
279inline void SwXMLTableRow_Impl::Set( const OUString& rStyleName,
280 const OUString& rDfltCellStyleName )
281{
282 m_aStyleName = rStyleName;
283 m_aDefaultCellStyleName = rDfltCellStyleName;
284}
285
287{
288 for (auto & pCell : m_Cells)
289 {
290 pCell->Dispose();
291 }
292}
293
294namespace {
295
296class SwXMLTableCellContext_Impl : public SvXMLImportContext
297{
298 OUString m_aStyleName;
299 OUString m_sFormula;
300 OUString m_sSaveParaDefault;
301 OUString m_StringValue;
302
303 SvXMLImportContextRef m_xMyTable;
304
305 double m_fValue;
306 bool m_bHasValue;
307 bool m_bHasStringValue;
308 bool m_bValueTypeIsString;
309 bool m_bProtect;
310
311 sal_uInt32 m_nRowSpan;
312 sal_uInt32 m_nColSpan;
313 sal_uInt32 m_nColRepeat;
314
315 bool m_bHasTextContent : 1;
316 bool m_bHasTableContent : 1;
317
318 SwXMLTableContext *GetTable() { return static_cast<SwXMLTableContext *>(m_xMyTable.get()); }
319
320 bool HasContent() const { return m_bHasTextContent || m_bHasTableContent; }
321 inline void InsertContent_();
322 inline void InsertContent();
323 inline void InsertContent( SwXMLTableContext *pTable );
324
325public:
326
327 SwXMLTableCellContext_Impl(
328 SwXMLImport& rImport, sal_Int32 nElement,
329 const Reference< xml::sax::XFastAttributeList > & xAttrList,
330 SwXMLTableContext *pTable );
331
332 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
333 sal_Int32 nElement,
334 const Reference< xml::sax::XFastAttributeList > & xAttrList ) override;
335 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
336
337 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
338};
339
341class SwXMLCoveredTableCellContext : public SvXMLImportContext
342{
343public:
344 SwXMLCoveredTableCellContext(SwXMLImport& rImport,
345 const Reference<xml::sax::XFastAttributeList>& xAttrList,
346 SwXMLTableContext& rTable);
347};
348
349SwXMLCoveredTableCellContext::SwXMLCoveredTableCellContext(
350 SwXMLImport& rImport, const Reference<xml::sax::XFastAttributeList>& xAttrList,
351 SwXMLTableContext& rTable)
352 : SvXMLImportContext(rImport)
353{
354 OUString aStyleName;
355 for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
356 {
357 switch (rIter.getToken())
358 {
359 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
360 aStyleName = rIter.toString();
361 break;
362 }
363 }
364
365 if (!aStyleName.isEmpty())
366 {
367 rTable.InsertCoveredCell(aStyleName);
368 }
369}
370}
371
372SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
373 SwXMLImport& rImport, sal_Int32 /*nElement*/,
374 const Reference< xml::sax::XFastAttributeList > & xAttrList,
375 SwXMLTableContext *pTable ) :
376 SvXMLImportContext( rImport ),
377 m_xMyTable( pTable ),
378 m_fValue( 0.0 ),
379 m_bHasValue( false ),
380 m_bHasStringValue(false),
381 m_bValueTypeIsString(false),
382 m_bProtect( false ),
383 m_nRowSpan( 1 ),
384 m_nColSpan( 1 ),
385 m_nColRepeat( 1 ),
386 m_bHasTextContent( false ),
387 m_bHasTableContent( false )
388{
389 m_sSaveParaDefault = GetImport().GetTextImport()->GetCellParaStyleDefault();
390 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
391 {
392 switch( aIter.getToken() )
393 {
394 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
395 m_aStyleName = aIter.toString();
396 GetImport().GetTextImport()->SetCellParaStyleDefault(m_aStyleName);
397 break;
398 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_SPANNED):
399 m_nColSpan = static_cast<sal_uInt32>(std::max<sal_Int32>(1, aIter.toInt32()));
400 if (m_nColSpan > 256)
401 {
402 SAL_INFO("sw.xml", "ignoring huge table:number-columns-spanned " << m_nColSpan);
403 m_nColSpan = 1;
404 }
405 break;
406 case XML_ELEMENT(TABLE, XML_NUMBER_ROWS_SPANNED):
407 m_nRowSpan = static_cast<sal_uInt32>(std::max<sal_Int32>(1, aIter.toInt32()));
408 if (m_nRowSpan > 8192 || (m_nRowSpan > 256 && utl::ConfigManager::IsFuzzing()))
409 {
410 SAL_INFO("sw.xml", "ignoring huge table:number-rows-spanned " << m_nRowSpan);
411 m_nRowSpan = 1;
412 }
413 break;
414 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED):
415 m_nColRepeat = static_cast<sal_uInt32>(std::max<sal_Int32>(1, aIter.toInt32()));
416 if (m_nColRepeat > 256)
417 {
418 SAL_INFO("sw.xml", "ignoring huge table:number-columns-repeated " << m_nColRepeat);
419 m_nColRepeat = 1;
420 }
421 break;
422 case XML_ELEMENT(TABLE, XML_FORMULA):
423 {
424 OUString sTmp;
425 const sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().
426 GetKeyByAttrValueQName(aIter.toString(), &sTmp);
427 m_sFormula = XML_NAMESPACE_OOOW == nPrefix2 ? sTmp : aIter.toString();
428 }
429 break;
430 case XML_ELEMENT(OFFICE, XML_VALUE):
431 {
432 // Writer wrongly uses DBL_MAX to flag error but fails to
433 // check for it after import, so check that here, tdf#139126.
434 double fTmp;
435 if (::sax::Converter::convertDouble(fTmp, aIter.toView()) && fTmp < DBL_MAX)
436 {
437 m_fValue = fTmp;
438 m_bHasValue = true;
439 }
440 }
441 break;
442 case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
443 {
444 double fTmp;
445 if (::sax::Converter::convertDuration(fTmp, aIter.toView()))
446 {
447 m_fValue = fTmp;
448 m_bHasValue = true;
449 }
450 }
451 break;
452 case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
453 {
454 double fTmp;
455 if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp,
456 aIter.toView()))
457 {
458 m_fValue = fTmp;
459 m_bHasValue = true;
460 }
461 }
462 break;
463 case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE):
464 {
465 bool bTmp(false);
466 if (::sax::Converter::convertBool(bTmp, aIter.toView()))
467 {
468 m_fValue = (bTmp ? 1.0 : 0.0);
469 m_bHasValue = true;
470 }
471 }
472 break;
473 case XML_ELEMENT(TABLE, XML_PROTECT): // for backwards compatibility with SRC629 (and before)
475 {
476 bool bTmp(false);
477 if (::sax::Converter::convertBool(bTmp, aIter.toView()))
478 {
479 m_bProtect = bTmp;
480 }
481 }
482 break;
483 case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
484 {
485 m_StringValue = aIter.toString();
486 m_bHasStringValue = true;
487 }
488 break;
489 case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
490 {
491 if ("string" == aIter.toView())
492 {
493 m_bValueTypeIsString = true;
494 }
495 // ignore other types - it would be correct to require
496 // matching value-type and $type-value attributes,
497 // but we've been reading those without checking forever.
498 }
499 break;
500 default:
501 SAL_WARN("sw", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << "=" << aIter.toString());
502 }
503 }
504}
505
506inline void SwXMLTableCellContext_Impl::InsertContent_()
507{
508 SwStartNode const*const pStartNode( GetTable()->InsertTableSection(nullptr,
509 (m_bHasStringValue && m_bValueTypeIsString &&
510 !m_aStyleName.isEmpty()) ? & m_aStyleName : nullptr) );
511 GetTable()->InsertCell( m_aStyleName, m_nRowSpan, m_nColSpan,
512 pStartNode,
513 nullptr, m_bProtect, &m_sFormula, m_bHasValue, m_fValue,
514 (m_bHasStringValue && m_bValueTypeIsString) ? &m_StringValue : nullptr);
515}
516
517inline void SwXMLTableCellContext_Impl::InsertContent()
518{
519 OSL_ENSURE( !HasContent(), "content already there" );
520 m_bHasTextContent = true;
521 InsertContent_();
522}
523
524inline void SwXMLTableCellContext_Impl::InsertContent(
525 SwXMLTableContext *pTable )
526{
527 GetTable()->InsertCell( m_aStyleName, m_nRowSpan, m_nColSpan, nullptr, pTable, m_bProtect );
528 m_bHasTableContent = true;
529}
530
531css::uno::Reference<css::xml::sax::XFastContextHandler> SwXMLTableCellContext_Impl::createFastChildContext(
532 sal_Int32 nElement,
533 const Reference< xml::sax::XFastAttributeList > & xAttrList )
534{
535 SvXMLImportContext *pContext = nullptr;
536
537 bool bSubTable = false;
538 if( nElement == XML_ELEMENT(TABLE, XML_TABLE) )
539 {
540 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
541 {
542 if( aIter.getToken() == XML_ELEMENT(TABLE, XML_IS_SUB_TABLE) )
543 {
544 if ( IsXMLToken( aIter, XML_TRUE ) )
545 bSubTable = true;
546 }
547 else
548 XMLOFF_WARN_UNKNOWN("sw", aIter);
549 //FIXME: RDFa
550 }
551 }
552
553 if( bSubTable )
554 {
555 if( !HasContent() )
556 {
557 SwXMLTableContext *pTableContext =
558 new SwXMLTableContext( GetSwImport(), GetTable() );
559 pContext = pTableContext;
560 if( GetTable()->IsValid() )
561 InsertContent( pTableContext );
562
563 GetTable()->SetHasSubTables( true );
564 }
565 }
566 else
567 {
568 if( GetTable()->IsValid() && !HasContent() )
569 InsertContent();
570 // fdo#60842: "office:string-value" overrides text content -> no import
571 if (!(m_bValueTypeIsString && m_bHasStringValue))
572 {
573 pContext = GetImport().GetTextImport()->CreateTextChildContext(
574 GetImport(), nElement, xAttrList,
575 XMLTextType::Cell );
576 }
577 }
578
579 return pContext;
580}
581
582void SwXMLTableCellContext_Impl::endFastElement(sal_Int32 )
583{
584 if( GetTable()->IsValid() )
585 {
586 if( m_bHasTextContent )
587 {
588 GetImport().GetTextImport()->DeleteParagraph();
589 if( m_nColRepeat > 1 && m_nColSpan == 1 )
590 {
591 // The original text is invalid after deleting the last
592 // paragraph
593 Reference < XTextCursor > xSrcTextCursor =
594 GetImport().GetTextImport()->GetText()->createTextCursor();
595 xSrcTextCursor->gotoEnd( true );
596
597 // Until we have an API for copying we have to use the core.
598 OTextCursorHelper *pSrcTextCursor = dynamic_cast<OTextCursorHelper*>(xSrcTextCursor.get());
599 assert(pSrcTextCursor && "SwXTextCursor missing");
600 SwDoc *pDoc = pSrcTextCursor->GetDoc();
601 const SwPaM *pSrcPaM = pSrcTextCursor->GetPaM();
602
603 while( m_nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
604 {
605 InsertContent_();
606
607 OTextCursorHelper *pDstTextCursor = dynamic_cast<OTextCursorHelper*>(GetImport().GetTextImport()->GetCursor().get());
608 assert(pDstTextCursor && "SwXTextCursor missing");
609 SwPaM aSrcPaM(*pSrcPaM->GetMark(), *pSrcPaM->GetPoint());
610 SwPosition aDstPos( *pDstTextCursor->GetPaM()->GetPoint() );
612
613 m_nColRepeat--;
614 }
615 }
616 }
617 else if( !m_bHasTableContent )
618 {
619 InsertContent();
620 if( m_nColRepeat > 1 && m_nColSpan == 1 )
621 {
622 while( m_nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
623 {
624 InsertContent_();
625 m_nColRepeat--;
626 }
627 }
628 }
629 }
630 GetImport().GetTextImport()->SetCellParaStyleDefault(m_sSaveParaDefault);
631}
632
633namespace {
634
635class SwXMLTableColContext_Impl : public SvXMLImportContext
636{
637 SvXMLImportContextRef m_xMyTable;
638
639 SwXMLTableContext *GetTable() { return static_cast<SwXMLTableContext *>(m_xMyTable.get()); }
640
641public:
642
643 SwXMLTableColContext_Impl(
644 SwXMLImport& rImport,
645 const Reference< xml::sax::XFastAttributeList > & xAttrList,
646 SwXMLTableContext *pTable );
647
648 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
649};
650
651}
652
653SwXMLTableColContext_Impl::SwXMLTableColContext_Impl(
654 SwXMLImport& rImport,
655 const Reference< xml::sax::XFastAttributeList > & xAttrList,
656 SwXMLTableContext *pTable ) :
657 SvXMLImportContext( rImport ),
658 m_xMyTable( pTable )
659{
660 sal_uInt32 nColRep = 1;
661 OUString aStyleName, aDfltCellStyleName;
662
663 for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
664 {
665 switch (aIter.getToken())
666 {
667 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
668 aStyleName = aIter.toString();
669 break;
670 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED):
671 {
672 nColRep = static_cast<sal_uInt32>(std::max<sal_Int32>(1, aIter.toInt32()));
673 if (nColRep > 256)
674 {
675 SAL_INFO("sw.xml", "ignoring huge table:number-columns-repeated " << nColRep);
676 nColRep = 1;
677 }
678 break;
679 }
680 case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME):
681 aDfltCellStyleName = aIter.toString();
682 break;
683 case XML_ELEMENT(XML, XML_ID):
684 {
685 //FIXME where to put this??? columns do not actually exist in writer...
686 break;
687 }
688 default:
689 XMLOFF_WARN_UNKNOWN("sw", aIter);
690 }
691 }
692
693 sal_Int32 nWidth = MINLAY;
694 bool bRelWidth = true;
695 if( !aStyleName.isEmpty() )
696 {
697 const SwFormatFrameSize *pSize;
698 const SfxItemSet *pAutoItemSet = nullptr;
699 if( GetSwImport().FindAutomaticStyle(
700 XmlStyleFamily::TABLE_COLUMN,
701 aStyleName, &pAutoItemSet ) &&
702 pAutoItemSet &&
703 (pSize = pAutoItemSet->GetItemIfSet( RES_FRM_SIZE, false )) )
704 {
705 nWidth = pSize->GetWidth();
706 bRelWidth = SwFrameSize::Variable == pSize->GetHeightSizeType();
707 }
708 }
709
710 if( nWidth )
711 {
712 while( nColRep-- && GetTable()->IsInsertColPossible() )
713 GetTable()->InsertColumn( nWidth, bRelWidth, &aDfltCellStyleName );
714 }
715}
716
717namespace {
718
719class SwXMLTableColsContext_Impl : public SvXMLImportContext
720{
721 SvXMLImportContextRef m_xMyTable;
722
723 SwXMLTableContext *GetTable() { return static_cast<SwXMLTableContext *>(m_xMyTable.get()); }
724
725public:
726
727 SwXMLTableColsContext_Impl(
728 SwXMLImport& rImport,
729 SwXMLTableContext *pTable );
730
731 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
732 sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
733
734 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
735};
736
737}
738
739SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl(
740 SwXMLImport& rImport,
741 SwXMLTableContext *pTable ) :
742 SvXMLImportContext( rImport ),
743 m_xMyTable( pTable )
744{
745}
746
747css::uno::Reference< css::xml::sax::XFastContextHandler > SwXMLTableColsContext_Impl::createFastChildContext(
748 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList )
749{
750 SvXMLImportContext *pContext = nullptr;
751
752 if( nElement == XML_ELEMENT(TABLE, XML_TABLE_COLUMN) &&
753 GetTable()->IsInsertColPossible() )
754 pContext = new SwXMLTableColContext_Impl( GetSwImport(), xAttrList, GetTable() );
755 else
756 XMLOFF_WARN_UNKNOWN_ELEMENT("sw", nElement);
757
758 return pContext;
759}
760
761namespace {
762
763class SwXMLTableRowContext_Impl : public SvXMLImportContext
764{
765 SvXMLImportContextRef m_xMyTable;
766
767 sal_uInt32 m_nRowRepeat;
768
769 SwXMLTableContext *GetTable() { return static_cast<SwXMLTableContext *>(m_xMyTable.get()); }
770
771public:
772
773 SwXMLTableRowContext_Impl(
774 SwXMLImport& rImport, sal_Int32 nElement,
775 const Reference< xml::sax::XFastAttributeList > & xAttrList,
776 SwXMLTableContext *pTable, bool bInHead=false );
777
778 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext( sal_Int32 nElement,
779 const Reference< xml::sax::XFastAttributeList > & xAttrList ) override;
780
781 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
782
783 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
784};
785
786}
787
788SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport& rImport,
789 sal_Int32 /*nElement*/,
790 const Reference< xml::sax::XFastAttributeList > & xAttrList,
791 SwXMLTableContext *pTable,
792 bool bInHead ) :
793 SvXMLImportContext( rImport ),
794 m_xMyTable( pTable ),
795 m_nRowRepeat( 1 )
796{
797 OUString aStyleName, aDfltCellStyleName;
798
799 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
800 {
801 switch(aIter.getToken())
802 {
803 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
804 aStyleName = aIter.toString();
805 break;
806 case XML_ELEMENT(STYLE, XML_NUMBER_ROWS_REPEATED):
807 {
808 m_nRowRepeat = static_cast<sal_uInt32>(std::max<sal_Int32>(1, aIter.toInt32()));
809 if (m_nRowRepeat > 8192 || (m_nRowRepeat > 256 && utl::ConfigManager::IsFuzzing()))
810 {
811 SAL_INFO("sw.xml", "ignoring huge table:number-rows-repeated " << m_nRowRepeat);
812 m_nRowRepeat = 1;
813 }
814 break;
815 }
816 case XML_ELEMENT(STYLE, XML_DEFAULT_CELL_STYLE_NAME):
817 aDfltCellStyleName = aIter.toString();
818 break;
819 case XML_ELEMENT(XML, XML_ID):
820 break;
821 default:
822 XMLOFF_WARN_UNKNOWN("sw", aIter);
823 }
824 }
825 if( GetTable()->IsValid() )
826 GetTable()->InsertRow( aStyleName, aDfltCellStyleName, bInHead );
827}
828
829void SwXMLTableRowContext_Impl::endFastElement(sal_Int32 )
830{
831 if( GetTable()->IsValid() )
832 {
833 GetTable()->FinishRow();
834
835 if( m_nRowRepeat > 1 )
836 GetTable()->InsertRepRows( m_nRowRepeat );
837 }
838}
839
840css::uno::Reference<css::xml::sax::XFastContextHandler> SwXMLTableRowContext_Impl::createFastChildContext(
841 sal_Int32 nElement,
842 const Reference< xml::sax::XFastAttributeList > & xAttrList )
843{
844 SvXMLImportContext *pContext = nullptr;
845
846 if( nElement == XML_ELEMENT(TABLE, XML_TABLE_CELL) ||
847 nElement == XML_ELEMENT(LO_EXT, XML_TABLE_CELL) )
848 {
849 if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() )
850 pContext = new SwXMLTableCellContext_Impl( GetSwImport(), nElement,
851 xAttrList,
852 GetTable() );
853 }
854 else if( nElement == XML_ELEMENT(TABLE, XML_COVERED_TABLE_CELL) ||
855 nElement == XML_ELEMENT(LO_EXT, XML_COVERED_TABLE_CELL) )
856 {
857 if (GetTable()->IsValid() && GetTable()->IsInsertCoveredCellPossible())
858 {
859 pContext = new SwXMLCoveredTableCellContext(GetSwImport(), xAttrList, *GetTable());
860 }
861 else
862 {
863 pContext = new SvXMLImportContext(GetImport());
864 }
865 }
866 else
867 SAL_WARN("sw", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
868
869 return pContext;
870}
871
872namespace {
873
874class SwXMLTableRowsContext_Impl : public SvXMLImportContext
875{
876 SvXMLImportContextRef m_xMyTable;
877
878 bool m_bHeader;
879
880 SwXMLTableContext *GetTable() { return static_cast<SwXMLTableContext *>(m_xMyTable.get()); }
881
882public:
883
884 SwXMLTableRowsContext_Impl( SwXMLImport& rImport,
885 SwXMLTableContext *pTable,
886 bool bHead );
887
888 virtual css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
889 sal_Int32 nElement,
890 const Reference< xml::sax::XFastAttributeList > & xAttrList ) override;
891
892 SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
893};
894
895}
896
897SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport& rImport,
898 SwXMLTableContext *pTable,
899 bool bHead ) :
900 SvXMLImportContext( rImport ),
901 m_xMyTable( pTable ),
902 m_bHeader( bHead )
903{
904}
905
906css::uno::Reference<css::xml::sax::XFastContextHandler> SwXMLTableRowsContext_Impl::createFastChildContext(
907 sal_Int32 nElement,
908 const Reference< xml::sax::XFastAttributeList > & xAttrList )
909{
910 if( nElement== XML_ELEMENT(TABLE, XML_TABLE_ROW ) &&
911 GetTable()->IsInsertRowPossible() )
912 return new SwXMLTableRowContext_Impl( GetSwImport(), nElement,
913 xAttrList,
914 GetTable(),
915 m_bHeader );
916 SAL_WARN("sw", "unknown element " << SvXMLImport::getPrefixAndNameFromToken(nElement));
917 return nullptr;
918}
919
921{
924 OUString m_sDDEItem;
925 OUString m_sDDETopic;
927
928public:
929
930
932
933 virtual void SAL_CALL startFastElement(
934 sal_Int32 nElement,
935 const Reference<xml::sax::XFastAttributeList> & xAttrList) override;
936
937 OUString& GetConnectionName() { return m_sConnectionName; }
938 OUString& GetDDEApplication() { return m_sDDEApplication; }
939 OUString& GetDDEItem() { return m_sDDEItem; }
940 OUString& GetDDETopic() { return m_sDDETopic; }
942};
943
944
946 SvXMLImportContext(rImport),
947 m_bIsAutomaticUpdate(false)
948{
949}
950
952 sal_Int32 /*nElement*/,
953 const Reference<xml::sax::XFastAttributeList> & xAttrList)
954{
955 for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
956 {
957 switch (aIter.getToken())
958 {
960 m_sDDEApplication = aIter.toString();
961 break;
963 m_sDDETopic = aIter.toString();
964 break;
966 m_sDDEItem = aIter.toString();
967 break;
969 m_sConnectionName = aIter.toString();
970 break;
972 {
973 bool bTmp(false);
974 if (::sax::Converter::convertBool(bTmp, aIter.toView()))
975 {
977 }
978 break;
979 }
980 default:
981 XMLOFF_WARN_UNKNOWN("sw", aIter);
982 }
983 // else: unknown attribute namespace
984 }
985}
986
987// generate a new name for DDE field type (called by lcl_GetDDEFieldType below)
988static OUString lcl_GenerateFieldTypeName(const OUString& sPrefix, SwTableNode* pTableNode)
989{
990 const OUString sPrefixStr(sPrefix.isEmpty() ? OUString("_") : sPrefix);
991
992 // increase count until we find a name that is not yet taken
993 OUString sName;
994 sal_Int32 nCount = 0;
995 do
996 {
997 // this is crazy, but just in case all names are taken: exit gracefully
998 if (nCount == SAL_MAX_INT32)
999 return sName;
1000
1001 ++nCount;
1002 sName = sPrefixStr + OUString::number(nCount);
1003 }
1004 while (nullptr != pTableNode->GetDoc().getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Dde, sName, false));
1005
1006 return sName;
1007}
1008
1009// set table properties
1011 SwTableNode* pTableNode)
1012{
1013 // make command string
1014 const OUString sCommand(pContext->GetDDEApplication()
1015 + OUStringChar(sfx2::cTokenSeparator)
1016 + pContext->GetDDEItem()
1017 + OUStringChar(sfx2::cTokenSeparator)
1018 + pContext->GetDDETopic());
1019
1020 const SfxLinkUpdateMode nType = pContext->GetIsAutomaticUpdate()
1021 ? SfxLinkUpdateMode::ALWAYS
1022 : SfxLinkUpdateMode::ONCALL;
1023
1024 OUString sName(pContext->GetConnectionName());
1025
1026 // field type to be returned
1027 SwDDEFieldType* pType = nullptr;
1028
1029 // valid name?
1030 if (sName.isEmpty())
1031 {
1033 pTableNode);
1034 }
1035 else
1036 {
1037 // check for existing DDE field type with the same name
1038 SwDDEFieldType* pOldType = static_cast<SwDDEFieldType*>(pTableNode->GetDoc().getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Dde, sName, false));
1039 if (nullptr != pOldType)
1040 {
1041 // same values -> return old type
1042 if ( (pOldType->GetCmd() == sCommand) &&
1043 (pOldType->GetType() == nType) )
1044 {
1045 // same name, same values -> return old type!
1046 pType = pOldType;
1047 }
1048 else
1049 {
1050 // same name, different values -> think of new name
1052 pTableNode);
1053 }
1054 }
1055 // no old type -> create new one
1056 }
1057
1058 // create new field type (unless we already have one)
1059 if (nullptr == pType)
1060 {
1061 // create new field type and return
1062 SwDDEFieldType aDDEFieldType(sName, sCommand, nType);
1063 pType = static_cast<SwDDEFieldType*>(pTableNode->
1064 GetDoc().getIDocumentFieldsAccess().InsertFieldType(aDDEFieldType));
1065 }
1066
1067 OSL_ENSURE(nullptr != pType, "We really want a SwDDEFieldType here!");
1068 return pType;
1069}
1070
1072{
1073public:
1074 OUString msName;
1075 sal_Int32 mnWidth;
1077
1078 TableBoxIndex( OUString aName, sal_Int32 nWidth,
1079 bool bProtected ) :
1080 msName(std::move( aName )),
1081 mnWidth( nWidth ),
1082 mbProtected( bProtected )
1083 { }
1084
1085 bool operator== ( const TableBoxIndex& rArg ) const
1086 {
1087 return (rArg.mnWidth == mnWidth) &&
1088 (rArg.mbProtected == mbProtected) &&
1089 (rArg.msName == msName);
1090 }
1091};
1092
1094{
1095public:
1096 size_t operator() (const TableBoxIndex& rArg) const
1097 {
1098 return rArg.msName.hashCode() + rArg.mnWidth + (rArg.mbProtected ? 1 : 0);
1099 }
1100};
1101
1103 sal_uInt32 nCol ) const
1104{
1105 return (*m_pRows)[nRow]->GetCell( nCol );
1106}
1107
1109 sal_uInt32 nCol )
1110{
1111 return (*m_pRows)[nRow]->GetCell( nCol );
1112}
1113
1114
1116 const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
1117 XMLTextTableContext( rImport ),
1118 m_pRows( new SwXMLTableRows_Impl ),
1119 m_pTableNode( nullptr ),
1120 m_pBox1( nullptr ),
1121 m_bOwnsBox1( false ),
1122 m_pSttNd1( nullptr ),
1123 m_pBoxFormat( nullptr ),
1124 m_pLineFormat( nullptr ),
1125 m_bFirstSection( true ),
1126 m_bRelWidth( true ),
1127 m_bHasSubTables( false ),
1128 m_nHeaderRows( 0 ),
1129 m_nCurRow( 0 ),
1130 m_nCurCol( 0 ),
1131 m_nNonMergedCurCol( 0 ),
1132 m_nWidth( 0 )
1133{
1134 OUString aName;
1135 OUString sXmlId;
1136
1137 // this method will modify the document directly -> lock SolarMutex
1138 SolarMutexGuard aGuard;
1139
1140 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1141 {
1142 const OUString sValue = aIter.toString();
1143 switch(aIter.getToken())
1144 {
1145 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
1146 m_aStyleName = sValue;
1147 break;
1148 case XML_ELEMENT(TABLE, XML_NAME):
1149 aName = sValue;
1150 break;
1151 case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME):
1152 m_aDfltCellStyleName = sValue;
1153 break;
1154 case XML_ELEMENT(TABLE, XML_TEMPLATE_NAME):
1155 m_aTemplateName = sValue;
1156 break;
1157 case XML_ELEMENT(XML, XML_ID):
1158 sXmlId = sValue;
1159 break;
1160 default:
1161 XMLOFF_WARN_UNKNOWN("sw", aIter);
1162 }
1163 }
1164
1165 SwDoc *pDoc = GetSwImport().getDoc();
1166
1167 OUString sTableName;
1168 if( !aName.isEmpty() )
1169 {
1170 const SwTableFormat *pTableFormat = pDoc->FindTableFormatByName( aName );
1171 if( !pTableFormat )
1172 sTableName = aName;
1173 }
1174 if( sTableName.isEmpty() )
1175 {
1176 sTableName = pDoc->GetUniqueTableName();
1177 GetImport().GetTextImport()
1178 ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, sTableName );
1179 }
1180
1181 Reference< XTextTable > xTable;
1182 SwXTextTable *pXTable = nullptr;
1183 Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
1184 UNO_QUERY );
1185 OSL_ENSURE( xFactory.is(), "factory missing" );
1186 if( xFactory.is() )
1187 {
1188 Reference<XInterface> xIfc = xFactory->createInstance( "com.sun.star.text.TextTable" );
1189 OSL_ENSURE( xIfc.is(), "Couldn't create a table" );
1190
1191 if( xIfc.is() )
1192 xTable.set( xIfc, UNO_QUERY );
1193 }
1194
1195 if( xTable.is() )
1196 {
1197 xTable->initialize( 1, 1 );
1198
1199 try
1200 {
1201 m_xTextContent = xTable;
1202 GetImport().GetTextImport()->InsertTextContent( m_xTextContent );
1203 }
1204 catch( IllegalArgumentException& )
1205 {
1206 xTable = nullptr;
1207 }
1208 }
1209
1210 if( xTable.is() )
1211 {
1212 //FIXME
1213 // xml:id for RDF metadata
1214 GetImport().SetXmlId(xTable, sXmlId);
1215
1216 pXTable = dynamic_cast<SwXTextTable*>(xTable.get());
1217
1218 Reference < XCellRange > xCellRange( xTable, UNO_QUERY );
1219 Reference < XCell > xCell = xCellRange->getCellByPosition( 0, 0 );
1220 Reference < XText> xText( xCell, UNO_QUERY );
1221 m_xOldCursor = GetImport().GetTextImport()->GetCursor();
1222 GetImport().GetTextImport()->SetCursor( xText->createTextCursor() );
1223
1224 // take care of open redlines for tables
1225 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
1226 }
1227 if( !pXTable )
1228 return;
1229
1230 SwFrameFormat *const pTableFrameFormat = pXTable->GetFrameFormat();
1231 OSL_ENSURE( pTableFrameFormat, "table format missing" );
1232 SwTable *pTable = SwTable::FindTable( pTableFrameFormat );
1233 OSL_ENSURE( pTable, "table missing" );
1234 m_pTableNode = pTable->GetTableNode();
1235 OSL_ENSURE( m_pTableNode, "table node missing" );
1236
1237 pTableFrameFormat->SetFormatName( sTableName );
1238
1240 m_pBox1 = pLine1->GetTabBoxes()[0U];
1242}
1243
1245 SwXMLTableContext *pTable ) :
1246 XMLTextTableContext( rImport ),
1247 m_pRows( new SwXMLTableRows_Impl ),
1248 m_pTableNode( pTable->m_pTableNode ),
1249 m_pBox1( nullptr ),
1250 m_bOwnsBox1( false ),
1251 m_pSttNd1( nullptr ),
1252 m_pBoxFormat( nullptr ),
1253 m_pLineFormat( nullptr ),
1254 m_xParentTable( pTable ),
1255 m_bFirstSection( false ),
1256 m_bRelWidth( true ),
1257 m_bHasSubTables( false ),
1258 m_nHeaderRows( 0 ),
1259 m_nCurRow( 0 ),
1260 m_nCurCol( 0 ),
1261 m_nNonMergedCurCol( 0 ),
1262 m_nWidth( 0 )
1263{
1264}
1265
1267{
1268 if (m_bOwnsBox1)
1269 delete m_pBox1;
1271 m_pSharedBoxFormats.reset();
1272 m_pRows.reset();
1273
1274 // close redlines on table end nodes
1275 GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
1276}
1277
1278css::uno::Reference<css::xml::sax::XFastContextHandler> SwXMLTableContext::createFastChildContext(
1279 sal_Int32 nElement,
1280 const Reference< xml::sax::XFastAttributeList > & xAttrList )
1281{
1282 bool bHeader = false;
1283 switch (nElement)
1284 {
1286 case XML_ELEMENT(LO_EXT, XML_TABLE_ROW):
1287 if( IsInsertRowPossible() )
1288 return new SwXMLTableRowContext_Impl( GetSwImport(), nElement, xAttrList, this );
1289 break;
1291 bHeader = true;
1292 [[fallthrough]];
1294 return new SwXMLTableRowsContext_Impl( GetSwImport(), this, bHeader );
1297 // There are slight differences between <table:table-columns> and
1298 // <table:table-columns-groups>. However, none of these are
1299 // supported in Writer (they are Calc-only features), so we
1300 // support column groups by simply using the <table:table-columns>
1301 // token for column groups, too.
1303 if( IsValid() )
1304 return new SwXMLTableColsContext_Impl( GetSwImport(), this );
1305 break;
1307 case XML_ELEMENT(LO_EXT, XML_TABLE_COLUMN):
1308 if( IsValid() && IsInsertColPossible() )
1309 return new SwXMLTableColContext_Impl( GetSwImport(), xAttrList,
1310 this );
1311 break;
1313 // save context for later processing (discard old context, if approp.)
1314 if( IsValid() )
1315 {
1317 return m_xDDESource;
1318 }
1319 break;
1320 }
1321 return nullptr;
1322}
1323
1324void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2, bool bRelWidth2,
1325 const OUString *pDfltCellStyleName )
1326{
1327 OSL_ENSURE( m_nCurCol < USHRT_MAX,
1328 "SwXMLTableContext::InsertColumn: no space left" );
1329 if( m_nCurCol >= USHRT_MAX )
1330 return;
1331
1332 if( nWidth2 < MINLAY )
1333 nWidth2 = MINLAY;
1334 else if( nWidth2 > MAX_WIDTH )
1335 nWidth2 = MAX_WIDTH;
1336 m_aColumnWidths.emplace_back(nWidth2, bRelWidth2 );
1337 if( !((pDfltCellStyleName && !pDfltCellStyleName->isEmpty()) ||
1339 return;
1340
1342 {
1344 sal_uLong nCount = m_aColumnWidths.size() - 1;
1345 while( nCount-- )
1346 m_xColumnDefaultCellStyleNames->push_back(OUString());
1347 }
1348
1349 if(pDfltCellStyleName)
1350 m_xColumnDefaultCellStyleNames->push_back(*pDfltCellStyleName);
1351 else
1352 m_xColumnDefaultCellStyleNames->push_back(OUString());
1353}
1354
1355sal_Int32 SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol,
1356 sal_uInt32 nColSpan ) const
1357{
1358 sal_uInt32 nLast = nCol+nColSpan;
1359 if( nLast > m_aColumnWidths.size() )
1360 nLast = m_aColumnWidths.size();
1361
1362 sal_Int32 nWidth2 = 0;
1363 for( sal_uInt32 i=nCol; i < nLast; ++i )
1364 nWidth2 += m_aColumnWidths[i].width;
1365
1366 return nWidth2;
1367}
1368
1370{
1371 if( m_xColumnDefaultCellStyleNames && nCol < m_xColumnDefaultCellStyleNames->size())
1372 return (*m_xColumnDefaultCellStyleNames)[static_cast<size_t>(nCol)];
1373
1374 return OUString();
1375}
1376
1377void SwXMLTableContext::InsertCell( const OUString& rStyleName,
1378 sal_uInt32 nRowSpan, sal_uInt32 nColSpan,
1379 const SwStartNode *pStartNode,
1380 SwXMLTableContext *pTable,
1381 bool bProtect,
1382 const OUString* pFormula,
1383 bool bHasValue,
1384 double fValue,
1385 OUString const*const pStringValue )
1386{
1387 OSL_ENSURE( m_nCurCol < GetColumnCount(),
1388 "SwXMLTableContext::InsertCell: row is full" );
1389 OSL_ENSURE( m_nCurRow < USHRT_MAX,
1390 "SwXMLTableContext::InsertCell: table is full" );
1391 if( m_nCurCol >= USHRT_MAX || m_nCurRow > USHRT_MAX )
1392 return;
1393
1394 OSL_ENSURE( nRowSpan >=1, "SwXMLTableContext::InsertCell: row span is 0" );
1395 if( 0 == nRowSpan )
1396 nRowSpan = 1;
1397 OSL_ENSURE( nColSpan >=1, "SwXMLTableContext::InsertCell: col span is 0" );
1398 if( 0 == nColSpan )
1399 nColSpan = 1;
1400
1401 // Until it is possible to add columns here, fix the column span.
1402 sal_uInt32 nColsReq = m_nCurCol + nColSpan;
1403 if( nColsReq > GetColumnCount() )
1404 {
1405 nColSpan = GetColumnCount() - m_nCurCol;
1406 nColsReq = GetColumnCount();
1407 }
1408
1409 // Check whether there are cells from a previous line already that reach
1410 // into the current row.
1411 if( m_nCurRow > 0 && nColSpan > 1 )
1412 {
1413 SwXMLTableRow_Impl *pCurRow = (*m_pRows)[m_nCurRow].get();
1414 sal_uInt32 nLastCol = GetColumnCount() < nColsReq ? GetColumnCount()
1415 : nColsReq;
1416 for( sal_uInt32 i=m_nCurCol+1; i<nLastCol; ++i )
1417 {
1418 if( pCurRow->GetCell(i)->IsUsed() )
1419 {
1420 // If this cell is used, the column span is truncated
1421 nColSpan = i - m_nCurCol;
1422 nColsReq = i;
1423 break;
1424 }
1425 }
1426 }
1427
1428 sal_uInt32 nRowsReq = m_nCurRow + nRowSpan;
1429 if( nRowsReq > USHRT_MAX )
1430 {
1431 nRowSpan = USHRT_MAX - m_nCurRow;
1432 nRowsReq = USHRT_MAX;
1433 }
1434
1435 // Add columns (if # required columns greater than # columns):
1436 // This should never happen, since we require column definitions!
1437 if ( nColsReq > GetColumnCount() )
1438 {
1439 for( sal_uInt32 i=GetColumnCount(); i<nColsReq; ++i )
1440 {
1441 m_aColumnWidths.emplace_back(MINLAY, true );
1442 }
1443 // adjust columns in *all* rows, if columns must be inserted
1444 for (size_t i = 0; i < m_pRows->size(); ++i)
1445 (*m_pRows)[i]->Expand( nColsReq, i<m_nCurRow );
1446 }
1447
1448 // Add rows
1449 if (m_pRows->size() < nRowsReq)
1450 {
1451 for (size_t i = m_pRows->size(); i < nRowsReq; ++i)
1452 m_pRows->push_back(std::make_unique<SwXMLTableRow_Impl>(
1453 "", GetColumnCount()));
1454 }
1455
1456 OUString sStyleName( rStyleName );
1457 if( sStyleName.isEmpty() )
1458 {
1459 sStyleName = (*m_pRows)[m_nCurRow]->GetDefaultCellStyleName();
1460 if( sStyleName.isEmpty() && m_xColumnDefaultCellStyleNames )
1461 {
1463 if( sStyleName.isEmpty() )
1464 sStyleName = m_aDfltCellStyleName;
1465 }
1466 }
1467
1468 // Fill the cells
1469 for( sal_uInt32 i=nColSpan; i>0; --i )
1470 {
1471 for( sal_uInt32 j=nRowSpan; j>0; --j )
1472 {
1473 const bool bCovered = i != nColSpan || j != nRowSpan;
1474 SwXMLTableCell_Impl *pCell = GetCell( nRowsReq-j, nColsReq-i );
1475 if (!pCell)
1476 throw css::lang::IndexOutOfBoundsException();
1477 pCell->Set( sStyleName, j, i, pStartNode,
1478 pTable, bProtect, pFormula, bHasValue, bCovered, fValue,
1479 pStringValue );
1480 }
1481 }
1482
1483 // Set current col to the next (free) column
1484 m_nCurCol = nColsReq;
1485 m_nNonMergedCurCol = nColsReq;
1486 while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() )
1487 m_nCurCol++;
1488}
1489
1490void SwXMLTableContext::InsertCoveredCell(const OUString& rStyleName)
1491{
1494 if (!pCell)
1495 {
1496 return;
1497 }
1498
1499 pCell->SetStyleName(rStyleName);
1500}
1501
1502void SwXMLTableContext::InsertRow( const OUString& rStyleName,
1503 const OUString& rDfltCellStyleName,
1504 bool bInHead )
1505{
1506 OSL_ENSURE( m_nCurRow < USHRT_MAX,
1507 "SwXMLTableContext::InsertRow: no space left" );
1508 if( m_nCurRow >= USHRT_MAX )
1509 return;
1510
1511 // Make sure there is at least one column.
1512 if( 0==m_nCurRow && 0 == GetColumnCount() )
1513 InsertColumn( USHRT_MAX, true );
1514
1515 if (m_nCurRow < m_pRows->size())
1516 {
1517 // The current row has already been inserted because of a row span
1518 // of a previous row.
1519 (*m_pRows)[m_nCurRow]->Set(
1520 rStyleName, rDfltCellStyleName );
1521 }
1522 else
1523 {
1524 // add a new row
1525 m_pRows->push_back(std::make_unique<SwXMLTableRow_Impl>(
1526 rStyleName, GetColumnCount(),
1527 &rDfltCellStyleName));
1528 }
1529
1530 // We start at the first column ...
1531 m_nCurCol=0;
1533
1534 // ... but this cell may be occupied already.
1535 while( m_nCurCol<GetColumnCount() && GetCell(m_nCurRow,m_nCurCol)->IsUsed() )
1536 m_nCurCol++;
1537
1538 if( bInHead && m_nHeaderRows == m_nCurRow )
1539 m_nHeaderRows++;
1540}
1541
1542void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount )
1543{
1544 const SwXMLTableRow_Impl *pSrcRow = (*m_pRows)[m_nCurRow-1].get();
1545 while( nCount > 1 && IsInsertRowPossible() )
1546 {
1547 InsertRow( pSrcRow->GetStyleName(), pSrcRow->GetDefaultCellStyleName(),
1548 false );
1549 while( m_nCurCol < GetColumnCount() )
1550 {
1551 if( !GetCell(m_nCurRow,m_nCurCol)->IsUsed() )
1552 {
1553 const SwXMLTableCell_Impl *pSrcCell =
1555 InsertCell( pSrcCell->GetStyleName(), 1U,
1556 pSrcCell->GetColSpan(),
1558 nullptr, pSrcCell->IsProtected(),
1559 &pSrcCell->GetFormula(),
1560 pSrcCell->HasValue(), pSrcCell->GetValue(),
1561 pSrcCell->GetStringValue() );
1562 }
1563 }
1564 FinishRow();
1565 nCount--;
1566 }
1567}
1568
1570{
1571 // Insert an empty cell at the end of the line if the row is not complete
1572 if( m_nCurCol < GetColumnCount() )
1573 {
1574 InsertCell( "", 1U, GetColumnCount() - m_nCurCol,
1576 }
1577
1578 // Move to the next row.
1579 m_nCurRow++;
1580}
1581
1583 sal_uInt32 nCol ) const
1584{
1585 const SwXMLTableCell_Impl *pPrevCell = nullptr;
1586 if( GetColumnCount() == nCol )
1587 {
1588 // The last cell is the right one here.
1589 pPrevCell = GetCell( m_pRows->size() - 1U, GetColumnCount() - 1 );
1590 }
1591 else if( nCol > 0 )
1592 {
1593 // The previous cell in this row.
1594 pPrevCell = GetCell( nRow, nCol-1 );
1595 }
1596 else if( nRow > 0 )
1597 {
1598 // The last cell from the previous row.
1599 pPrevCell = GetCell( nRow-1, GetColumnCount()-1 );
1600 }
1601
1602 const SwStartNode *pSttNd = nullptr;
1603 if( pPrevCell )
1604 {
1605 if( pPrevCell->GetStartNode() )
1606 pSttNd = pPrevCell->GetStartNode();
1607 // #i95726# - Some fault tolerance
1608// else
1609 else if ( pPrevCell->GetSubTable() )
1610 pSttNd = pPrevCell->GetSubTable()->GetLastStartNode();
1611
1612 OSL_ENSURE( pSttNd != nullptr,
1613 "table corrupt" );
1614 }
1615
1616 return pSttNd;
1617}
1618
1619void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol,
1620 sal_uInt32 nColSpan )
1621{
1622 sal_uInt32 nLastCol = nCol + nColSpan;
1623 for( sal_uInt32 i = nCol; i < nLastCol; i++ )
1624 {
1625 sal_uInt32 j = nRow;
1626 sal_uInt32 nRowSpan = 1;
1627 SwXMLTableCell_Impl *pCell = GetCell( j, i );
1628 while( pCell && pCell->GetRowSpan() > 1 )
1629 {
1630 pCell->SetRowSpan( nRowSpan++ );
1631 pCell = j > 0 ? GetCell( --j, i ) : nullptr;
1632 }
1633 }
1634}
1635
1636void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows )
1637{
1638 const SwStartNode *pPrevSttNd = GetPrevStartNode( nRow, nCol );
1639 const SwStartNode *pSttNd = InsertTableSection( pPrevSttNd );
1640
1641 const SwXMLTableCell_Impl *pCell = GetCell( nRow, nCol );
1642 sal_uInt32 nLastRow = bRows ? nRow + pCell->GetRowSpan() : nRow + 1;
1643 sal_uInt32 nLastCol = nCol + pCell->GetColSpan();
1644
1645 for( sal_uInt32 i=nRow; i<nLastRow; i++ )
1646 {
1647 SwXMLTableRow_Impl *pRow = (*m_pRows)[i].get();
1648 for( sal_uInt32 j=nCol; j<nLastCol; j++ )
1649 pRow->GetCell( j )->SetStartNode( pSttNd );
1650 }
1651
1652}
1653
1655 SwTableLine *pUpper )
1656{
1657 // The topmost table is the only table that maintains the two members
1658 // pBox1 and bFirstSection.
1659 if( m_xParentTable.is() )
1660 return static_cast<SwXMLTableContext *>(m_xParentTable.get())->NewTableBox( pStNd,
1661 pUpper );
1662
1663 SwTableBox *pBox;
1664
1665 if( m_pBox1 &&
1666 m_pBox1->GetSttNd() == pStNd )
1667 {
1668 // if the StartNode is equal to the StartNode of the initially
1669 // created box, we use this box
1670 pBox = m_pBox1;
1671 pBox->SetUpper( pUpper );
1672 m_pBox1 = nullptr;
1673 m_bOwnsBox1 = false;
1674 }
1675 else
1676 pBox = new SwTableBox( m_pBoxFormat, *pStNd, pUpper );
1677
1678 return pBox;
1679}
1680
1682 SwTableBox* pBox,
1683 const OUString& rStyleName,
1684 sal_Int32 nColumnWidth,
1685 bool bProtected,
1686 bool bMayShare,
1687 bool& bNew,
1688 bool* pModifyLocked )
1689{
1690 if ( m_pSharedBoxFormats == nullptr )
1692
1693 SwTableBoxFormat* pBoxFormat2;
1694
1695 TableBoxIndex aKey( rStyleName, nColumnWidth, bProtected );
1696 map_BoxFormat::iterator aIter = m_pSharedBoxFormats->find( aKey );
1697 if ( aIter == m_pSharedBoxFormats->end() )
1698 {
1699 // unknown format so far -> construct a new one
1700
1701 // get the old format, and reset all attributes
1702 // (but preserve FillOrder)
1703 pBoxFormat2 = static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat());
1704 SwFormatFillOrder aFillOrder( pBoxFormat2->GetFillOrder() );
1705 pBoxFormat2->ResetAllFormatAttr(); // #i73790# - method renamed
1706 pBoxFormat2->SetFormatAttr( aFillOrder );
1707 bNew = true; // it's a new format now
1708
1709 // share this format, if allowed
1710 if ( bMayShare )
1711 (*m_pSharedBoxFormats)[ aKey ] = pBoxFormat2;
1712 }
1713 else
1714 {
1715 // set the shared format
1716 pBoxFormat2 = aIter->second;
1717 pBox->ChgFrameFormat( pBoxFormat2, /*bNeedToReregister*/false );
1718 bNew = false; // copied from an existing format
1719
1720 // claim it, if we are not allowed to share
1721 if ( !bMayShare )
1722 pBoxFormat2 = static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat());
1723 }
1724
1725 // lock format (if so desired)
1726 if ( pModifyLocked != nullptr )
1727 {
1728 (*pModifyLocked) = pBoxFormat2->IsModifyLocked();
1729 pBoxFormat2->LockModify();
1730 }
1731
1732 return pBoxFormat2;
1733}
1734
1736 sal_uInt32 nTopRow,
1737 sal_uInt32 nLeftCol,
1738 sal_uInt32 nBottomRow,
1739 sal_uInt32 nRightCol )
1740{
1741 //FIXME: here would be a great place to handle XmlId for cell
1742 SwTableBox *pBox = new SwTableBox( m_pBoxFormat, 0, pUpper );
1743
1744 sal_uInt32 nColSpan = nRightCol - nLeftCol;
1745 sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
1746
1747 // TODO: Share formats!
1748 SwFrameFormat *pFrameFormat = pBox->ClaimFrameFormat();
1749 SwFormatFillOrder aFillOrder( pFrameFormat->GetFillOrder() );
1750 pFrameFormat->ResetAllFormatAttr(); // #i73790# - method renamed
1751 pFrameFormat->SetFormatAttr( aFillOrder );
1752
1753 pFrameFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nColWidth ) );
1754
1755 SwTableLines& rLines = pBox->GetTabLines();
1756 bool bSplitted = false;
1757
1758 while( !bSplitted )
1759 {
1760 sal_uInt32 nStartRow = nTopRow;
1761 sal_uInt32 i;
1762
1763 for( i = nTopRow; i < nBottomRow; i++ )
1764 {
1765 // Could the table be split behind the current row?
1766 bool bSplit = true;
1767 SwXMLTableRow_Impl *pRow = (*m_pRows)[i].get();
1768 for( sal_uInt32 j=nLeftCol; j<nRightCol; j++ )
1769 {
1770 bSplit = ( 1 == pRow->GetCell(j)->GetRowSpan() );
1771 if( !bSplit )
1772 break;
1773 }
1774 if( bSplit && (nStartRow>nTopRow || i+1<nBottomRow) )
1775 {
1776 SwTableLine *pLine =
1777 MakeTableLine( pBox, nStartRow, nLeftCol, i+1,
1778 nRightCol );
1779
1780 rLines.push_back( pLine );
1781
1782 nStartRow = i+1;
1783 bSplitted = true;
1784 }
1785 }
1786 if( !bSplitted )
1787 {
1788 // No splitting was possible. That for, we have to force it.
1789 // Ruthless!
1790
1791 nStartRow = nTopRow;
1792 while( nStartRow < nBottomRow )
1793 {
1794 sal_uInt32 nMaxRowSpan = 0;
1795 SwXMLTableRow_Impl *pStartRow = (*m_pRows)[nStartRow].get();
1796 const SwXMLTableCell_Impl *pCell;
1797 for( i=nLeftCol; i<nRightCol; i++ )
1798 {
1799 pCell = pStartRow->GetCell(i);
1800 if( pCell->GetRowSpan() > nMaxRowSpan )
1801 nMaxRowSpan = pCell->GetRowSpan();
1802 }
1803
1804 nStartRow += nMaxRowSpan;
1805 if( nStartRow<nBottomRow )
1806 {
1807 SwXMLTableRow_Impl *pPrevRow = (*m_pRows)[nStartRow - 1U].get();
1808 i = nLeftCol;
1809 while( i < nRightCol )
1810 {
1811 if( pPrevRow->GetCell(i)->GetRowSpan() > 1 )
1812 {
1813 const SwXMLTableCell_Impl *pCell2 =
1814 GetCell( nStartRow, i );
1815 const sal_uInt32 nColSpan2 = pCell2->GetColSpan();
1816 FixRowSpan( nStartRow-1, i, nColSpan2 );
1817 ReplaceWithEmptyCell( nStartRow, i, true );
1818 i += nColSpan2;
1819 }
1820 else
1821 {
1822 i++;
1823 }
1824 }
1825 }
1826 }
1827 // and now start over again...
1828 }
1829 }
1830
1831 return pBox;
1832}
1833
1835 SwTableLine *pUpper, const SwXMLTableCell_Impl *pCell,
1836 sal_uInt32 nLeftCol, sal_uInt32 nRightCol )
1837{
1838 //FIXME: here would be a great place to handle XmlId for cell
1839 SwTableBox *pBox;
1840 sal_uInt32 nColSpan = nRightCol - nLeftCol;
1841 sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
1842
1843 if( pCell->GetStartNode() )
1844 {
1845 pBox = NewTableBox( pCell->GetStartNode(), pUpper );
1846 }
1847 else
1848 {
1849 // and it is a table: therefore we build a new box and
1850 // put the rows of the table into the rows of the box
1851 pBox = new SwTableBox( m_pBoxFormat, 0, pUpper );
1852 pCell->GetSubTable()->MakeTable( pBox, nColWidth );
1853 }
1854
1855 // Share formats!
1856 const OUString sStyleName = pCell->GetStyleName();
1857 bool bModifyLocked;
1858 bool bNew;
1859 SwTableBoxFormat *pBoxFormat2 = GetSharedBoxFormat(
1860 pBox, sStyleName, nColWidth, pCell->IsProtected(),
1861 pCell->GetStartNode() && pCell->GetFormula().isEmpty() &&
1862 ! pCell->HasValue(),
1863 bNew, &bModifyLocked );
1864
1865 // if a new format was created, then we need to set the style
1866 if ( bNew )
1867 {
1868 // set style
1869 const SfxItemSet *pAutoItemSet = nullptr;
1870 if( pCell->GetStartNode() && !sStyleName.isEmpty() &&
1871 GetSwImport().FindAutomaticStyle(
1872 XmlStyleFamily::TABLE_CELL, sStyleName, &pAutoItemSet ) )
1873 {
1874 if( pAutoItemSet )
1875 pBoxFormat2->SetFormatAttr( *pAutoItemSet );
1876 }
1877 }
1878
1879 if( pCell->GetStartNode() )
1880 {
1881 if (pCell->HasStringValue())
1882 {
1883 SwNodeIndex const aNodeIndex(*(pCell->GetStartNode()), 1);
1884 SwTextNode *const pTextNode(aNodeIndex.GetNode().GetTextNode());
1885 SAL_WARN_IF(!pTextNode, "sw", "Should have a text node in cell?");
1886 if (pTextNode)
1887 {
1888 SAL_WARN_IF(!pTextNode->GetText().isEmpty(), "sw",
1889 "why text here?");
1890 pTextNode->InsertText(*pCell->GetStringValue(),
1891 SwContentIndex(pTextNode, 0));
1892 }
1893 }
1894
1895 // try to rescue broken documents with a certain pattern
1896 // if: 1) the cell has a default number format (number 0)
1897 // 2) the call has no formula
1898 // 3) the value is 0.0
1899 // 4) the text doesn't look anything like 0.0
1900 // [read: length > 10, or length smaller 10 and no 0 in it]
1901 // then make it a text cell!
1902 bool bSuppressNumericContent = false;
1903 if( pCell->HasValue() && (pCell->GetValue() == 0.0) &&
1904 pCell->GetFormula().isEmpty() &&
1905 !sStyleName.isEmpty() )
1906 {
1907 // default num format?
1908 if( const SwTableBoxNumFormat* pNumFormat = pBoxFormat2->GetItemIfSet( RES_BOXATR_FORMAT, false ) )
1909 {
1910 if (pNumFormat && (pNumFormat->GetValue() % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
1911 {
1912 // only one text node?
1913 SwNodeIndex aNodeIndex( *(pCell->GetStartNode()), 1 );
1914 if( ( aNodeIndex.GetNode().EndOfSectionIndex() -
1915 aNodeIndex.GetNode().StartOfSectionIndex() ) == SwNodeOffset(2) )
1916 {
1917 SwTextNode* pTextNode= aNodeIndex.GetNode().GetTextNode();
1918 if( pTextNode != nullptr )
1919 {
1920 // check text: does it look like some form of 0.0?
1921 const OUString& rText = pTextNode->GetText();
1922 if( ( rText.getLength() > 10 ) ||
1923 ( rText.indexOf( '0' ) == -1 ) )
1924 {
1925 bSuppressNumericContent = true;
1926 }
1927 }
1928 }
1929 else
1930 bSuppressNumericContent = true; // several nodes
1931 }
1932 }
1933 }
1934
1935 if( bSuppressNumericContent )
1936 {
1937 // suppress numeric content? Then reset number format!
1938 pBoxFormat2->ResetFormatAttr( RES_BOXATR_FORMULA );
1939 pBoxFormat2->ResetFormatAttr( RES_BOXATR_FORMAT );
1940 pBoxFormat2->ResetFormatAttr( RES_BOXATR_VALUE );
1941 }
1942 else
1943 {
1944 // the normal case: set formula and value (if available)
1945
1946 const OUString& rFormula = pCell->GetFormula();
1947 if (!rFormula.isEmpty())
1948 {
1949 // formula cell: insert formula if valid
1950 SwTableBoxFormula aFormulaItem( rFormula );
1951 pBoxFormat2->SetFormatAttr( aFormulaItem );
1952 }
1953 else if (!pCell->HasValue() && pCell->HasStringValue())
1954 {
1955 // Check for another inconsistency:
1956 // No value but a non-textual format, i.e. a number format
1957 // Solution: the number format will be removed,
1958 // the cell gets the default text format.
1959 if( const SwTableBoxNumFormat* pNumFormat = m_pBoxFormat->GetItemIfSet( RES_BOXATR_FORMAT, false ) )
1960 {
1961 const SwDoc* pDoc = m_pBoxFormat->GetDoc();
1962 const SvNumberFormatter* pNumberFormatter = pDoc ?
1963 pDoc->GetNumberFormatter() : nullptr;
1964 if( pNumFormat != nullptr && pNumberFormatter &&
1965 !pNumberFormatter->GetEntry( pNumFormat->GetValue() )->IsTextFormat() )
1967 }
1968 }
1969 // always insert value, even if default
1970 if( pCell->HasValue() )
1971 {
1972 SwTableBoxValue aValueItem( pCell->GetValue() );
1973 pBoxFormat2->SetFormatAttr( aValueItem );
1974 }
1975 }
1976
1977 // update cell content depend on the default language
1978 pBox->ActualiseValueBox();
1979 }
1980
1981 // table cell protection
1982 if( pCell->IsProtected() )
1983 {
1984 SvxProtectItem aProtectItem( RES_PROTECT );
1985 aProtectItem.SetContentProtect( true );
1986 pBoxFormat2->SetFormatAttr( aProtectItem );
1987 }
1988
1989 // restore old modify-lock state
1990 if (! bModifyLocked)
1991 pBoxFormat2->UnlockModify();
1992
1993 pBoxFormat2->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nColWidth ) );
1994
1995 return pBox;
1996}
1997
1999 sal_uInt32 nTopRow,
2000 sal_uInt32 nLeftCol,
2001 sal_uInt32 nBottomRow,
2002 sal_uInt32 nRightCol )
2003{
2004 //FIXME: here would be a great place to handle XmlId for row
2005 SwTableLine *pLine;
2006 if( !pUpper && 0UL==nTopRow )
2007 {
2008 pLine = m_pTableNode->GetTable().GetTabLines()[0U];
2009 }
2010 else
2011 {
2012 pLine = new SwTableLine( m_pLineFormat, 0, pUpper );
2013 }
2014
2015 // TODO: Share formats!
2016 SwFrameFormat *pFrameFormat = pLine->ClaimFrameFormat();
2017 SwFormatFillOrder aFillOrder( pFrameFormat->GetFillOrder() );
2018 pFrameFormat->ResetAllFormatAttr(); // #i73790# - method renamed
2019 pFrameFormat->SetFormatAttr( aFillOrder );
2020
2021 const SfxItemSet *pAutoItemSet = nullptr;
2022 const OUString& rStyleName = (*m_pRows)[nTopRow]->GetStyleName();
2023 if( 1 == (nBottomRow - nTopRow) &&
2024 !rStyleName.isEmpty() &&
2025 GetSwImport().FindAutomaticStyle(
2026 XmlStyleFamily::TABLE_ROW, rStyleName, &pAutoItemSet ) )
2027 {
2028 if( pAutoItemSet )
2029 pFrameFormat->SetFormatAttr( *pAutoItemSet );
2030 }
2031
2032 SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2033
2034 sal_uInt32 nStartCol = nLeftCol;
2035 while( nStartCol < nRightCol )
2036 {
2037 for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
2038 (*m_pRows)[nRow]->SetSplitable( true );
2039
2040 sal_uInt32 nCol = nStartCol;
2041 sal_uInt32 nSplitCol = nRightCol;
2042 bool bSplitted = false;
2043 while( !bSplitted )
2044 {
2045 OSL_ENSURE( nCol < nRightCol, "Ran too far" );
2046
2047 // Can be split after current HTML table column?
2048 // If yes, can the created region still be split to
2049 // rows if the next column is added to it?
2050 bool bSplit = true;
2051 bool bHoriSplitMayContinue = false;
2052 bool bHoriSplitPossible = false;
2053
2054 if ( m_bHasSubTables )
2055 {
2056 // Convert row spans if the table has subtables:
2057 for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
2058 {
2059 SwXMLTableCell_Impl *pCell = GetCell(nRow,nCol);
2060 // Could the table fragment be split horizontally behind
2061 // the current line?
2062 bool bHoriSplit = (*m_pRows)[nRow]->IsSplitable() &&
2063 nRow+1 < nBottomRow &&
2064 1 == pCell->GetRowSpan();
2065 (*m_pRows)[nRow]->SetSplitable( bHoriSplit );
2066
2067 // Could the table fragment be split vertically behind the
2068 // current column (uptp the current line?
2069 bSplit &= ( 1 == pCell->GetColSpan() );
2070 if( bSplit )
2071 {
2072 bHoriSplitPossible |= bHoriSplit;
2073
2074 // Could the current table fragment be split
2075 // horizontally behind the next column, too?
2076 bHoriSplit &= (nCol+1 < nRightCol &&
2077 1 == GetCell(nRow,nCol+1)->GetRowSpan());
2078 bHoriSplitMayContinue |= bHoriSplit;
2079 }
2080 }
2081 }
2082 else
2083 {
2084 // No subtables: we use the new table model.
2085 SwXMLTableCell_Impl *pCell = GetCell(nTopRow,nCol);
2086
2087 // #i95726# - some fault tolerance
2088 if ( pCell == nullptr )
2089 {
2090 OSL_FAIL( "table seems to be corrupt." );
2091 break;
2092 }
2093
2094 // Could the table fragment be split vertically behind the
2095 // current column (uptp the current line?
2096 bSplit = 1 == pCell->GetColSpan();
2097 }
2098
2099#if OSL_DEBUG_LEVEL > 0
2100 if( nCol == nRightCol-1 )
2101 {
2102 OSL_ENSURE( bSplit, "Split-Flag wrong" );
2103 if ( m_bHasSubTables )
2104 {
2105 OSL_ENSURE( !bHoriSplitMayContinue,
2106 "HoriSplitMayContinue-Flag wrong" );
2107 SwXMLTableCell_Impl *pTmpCell = GetCell( nTopRow, nStartCol );
2108 OSL_ENSURE( pTmpCell->GetRowSpan() != (nBottomRow-nTopRow) ||
2109 !bHoriSplitPossible, "HoriSplitPossible-Flag wrong" );
2110 }
2111 }
2112#endif
2113
2114 OSL_ENSURE( !m_bHasSubTables || !bHoriSplitMayContinue || bHoriSplitPossible,
2115 "bHoriSplitMayContinue, but not bHoriSplitPossible" );
2116
2117 if( bSplit )
2118 {
2119 SwTableBox* pBox = nullptr;
2120 SwXMLTableCell_Impl *pCell = GetCell( nTopRow, nStartCol );
2121 // #i95726# - some fault tolerance
2122 if( ( !m_bHasSubTables || ( pCell->GetRowSpan() == (nBottomRow-nTopRow) ) ) &&
2123 pCell->GetColSpan() == (nCol+1-nStartCol) &&
2124 ( pCell->GetStartNode() || pCell->GetSubTable() ) )
2125 {
2126 // insert new empty cell for covered cells:
2127 sal_Int32 nBoxRowSpan = 1;
2128 if ( !m_bHasSubTables )
2129 {
2130 nBoxRowSpan = pCell->GetRowSpan();
2131 if ( pCell->IsCovered() )
2132 {
2133 nBoxRowSpan = -1 * nBoxRowSpan;
2134 ReplaceWithEmptyCell( nTopRow, nStartCol, false );
2135 }
2136 }
2137
2138 // The remaining box neither contains lines nor rows (i.e.
2139 // is a content box
2140 nSplitCol = nCol + 1;
2141
2142 pBox = MakeTableBox( pLine, pCell, nStartCol, nSplitCol );
2143
2144 if ( 1 != nBoxRowSpan )
2145 pBox->setRowSpan( nBoxRowSpan );
2146
2147 bSplitted = true;
2148 }
2149 else if( m_bHasSubTables && bHoriSplitPossible && bHoriSplitMayContinue )
2150 {
2151 // The table fragment could be split behind the current
2152 // column, and the remaining fragment could be divided
2153 // into lines. Anyway, it could be that this applies to
2154 // the next column, too. That for, we check the next
2155 // column but remember the current one as a good place to
2156 // split.
2157 nSplitCol = nCol + 1;
2158 }
2159 else if ( m_bHasSubTables )
2160 {
2161 // If the table resulting table fragment could be divided
2162 // into lines if splitting behind the current column, but
2163 // this doesn't apply for thr next column, we split begind
2164 // the current column. This applies for the last column,
2165 // too.
2166 // If the resulting box cannot be split into rows,
2167 // the split at the last split position we remembered.
2168 if( bHoriSplitPossible || nSplitCol > nCol+1 )
2169 {
2170 OSL_ENSURE( !bHoriSplitMayContinue,
2171 "bHoriSplitMayContinue==true" );
2172 OSL_ENSURE( bHoriSplitPossible || nSplitCol == nRightCol,
2173 "bHoriSplitPossible flag should be set" );
2174
2175 nSplitCol = nCol + 1;
2176 }
2177
2178 pBox = MakeTableBox( pLine, nTopRow, nStartCol,
2179 nBottomRow, nSplitCol );
2180 bSplitted = true;
2181 }
2182
2183 OSL_ENSURE( m_bHasSubTables || pBox, "Colspan trouble" );
2184
2185 if( pBox )
2186 rBoxes.push_back( pBox );
2187 }
2188 nCol++;
2189 }
2190 nStartCol = nSplitCol;
2191 }
2192
2193 return pLine;
2194}
2195
2197{
2198 // fix column widths
2199 std::vector<ColumnWidthInfo>::iterator colIter;
2200 sal_uInt32 nCols = GetColumnCount();
2201
2202 // If there are empty rows (because of some row span of previous rows)
2203 // the have to be deleted. The previous rows have to be truncated.
2204
2205 if (m_pRows->size() > m_nCurRow)
2206 {
2207 SwXMLTableRow_Impl *pPrevRow = (*m_pRows)[m_nCurRow - 1U].get();
2208 const SwXMLTableCell_Impl *pCell;
2209 for( size_t i = 0; i < m_aColumnWidths.size(); ++i )
2210 {
2211 pCell = pPrevRow->GetCell(i);
2212 if( pCell->GetRowSpan() > 1 )
2213 {
2214 FixRowSpan( m_nCurRow-1, i, 1UL );
2215 }
2216 }
2217 for (size_t i = m_pRows->size() - 1; i >= m_nCurRow; --i)
2218 m_pRows->pop_back();
2219 }
2220
2221 if (m_pRows->empty())
2222 {
2223 InsertCell( "", 1U, nCols, InsertTableSection() );
2224 }
2225
2226 // TODO: Do we have to keep both values, the relative and the absolute
2227 // width?
2228 sal_Int32 nAbsWidth = 0;
2229 sal_Int32 nMinAbsColWidth = 0;
2230 sal_Int32 nRelWidth = 0;
2231 sal_Int32 nMinRelColWidth = 0;
2232 sal_uInt32 nRelCols = 0;
2233 for( const auto& rCol : m_aColumnWidths)
2234 {
2235 if( rCol.isRelative )
2236 {
2237 nRelWidth += rCol.width;
2238 if( 0 == nMinRelColWidth || rCol.width < nMinRelColWidth )
2239 nMinRelColWidth = rCol.width;
2240 nRelCols++;
2241 }
2242 else
2243 {
2244 nAbsWidth += rCol.width;
2245 if( 0 == nMinAbsColWidth || rCol.width < nMinAbsColWidth )
2246 nMinAbsColWidth = rCol.width;
2247 }
2248 }
2249 sal_uInt32 nAbsCols = nCols - nRelCols;
2250
2251 if( m_bRelWidth )
2252 {
2253 // If there a columns that have an absolute width, we have to
2254 // calculate a relative one for them.
2255 if( nAbsCols > 0 )
2256 {
2257 // All column that have absolute widths get relative widths;
2258 // these widths relate to each over like the original absolute
2259 // widths. The smallest column gets a width that has the same
2260 // value as the smallest column that has a relative width
2261 // already.
2262 if( 0 == nMinRelColWidth )
2263 nMinRelColWidth = nMinAbsColWidth;
2264
2265 for( auto& rCol : m_aColumnWidths)
2266 {
2267 if( !rCol.isRelative )
2268 {
2269 if (nMinAbsColWidth == 0)
2270 throw o3tl::divide_by_zero();
2271 sal_Int32 nVal;
2272 if (o3tl::checked_multiply<sal_Int32>(rCol.width, nMinRelColWidth, nVal))
2273 throw std::overflow_error("overflow in multiply");
2274 sal_Int32 nRelCol = nVal / nMinAbsColWidth;
2275 rCol.width = nRelCol;
2276 rCol.isRelative = true;
2277 nRelWidth += nRelCol;
2278 nAbsCols--;
2279 if (nAbsCols <= 0)
2280 break;
2281 }
2282 }
2283 }
2284
2285 if( !m_nWidth )
2286 {
2287 // This happens only for percentage values for the table itself.
2288 // In this case, the columns get the correct width even if
2289 // the sum of the relative widths is smaller than the available
2290 // width in TWIP. Therefore, we can use the relative width.
2291 m_nWidth = std::min(nRelWidth, MAX_WIDTH);
2292 }
2293 if( nRelWidth != m_nWidth && nRelWidth && nCols )
2294 {
2295 double n = static_cast<double>(m_nWidth) / static_cast<double>(nRelWidth);
2296 nRelWidth = 0;
2297 for( colIter = m_aColumnWidths.begin(); colIter < m_aColumnWidths.end() - 1; ++colIter)
2298 {
2299 sal_Int32 nW = static_cast<sal_Int32>( colIter->width * n);
2300 colIter->width = o3tl::narrowing<sal_uInt16>(nW);
2301 nRelWidth += nW;
2302 }
2303 m_aColumnWidths.back().width = (m_nWidth-nRelWidth);
2304 }
2305 }
2306 else
2307 {
2308 // If there are columns that have relative widths, we have to
2309 // calculate an absolute widths for them.
2310 if( nRelCols > 0 )
2311 {
2312 // The absolute space that is available for all columns with a
2313 // relative width.
2314 sal_Int32 nAbsForRelWidth =
2315 m_nWidth > nAbsWidth ? m_nWidth - nAbsWidth : sal_Int32(0L);
2316
2317 // The relative width that has to be distributed in addition to
2318 // equally widthed columns.
2319 sal_Int32 nExtraRel = nRelWidth - (nRelCols * nMinRelColWidth);
2320
2321 // The absolute space that may be distributed in addition to
2322 // minimum widthed columns.
2323 sal_Int32 nMinAbs = nRelCols * MINLAY;
2324 sal_Int32 nExtraAbs =
2325 nAbsForRelWidth > nMinAbs ? nAbsForRelWidth - nMinAbs : sal_Int32(0L);
2326
2327 bool bMin = false; // Do all columns get the minimum width?
2328 bool bMinExtra = false; // Do all columns get the minimum width plus
2329 // some extra space?
2330
2331 if( nAbsForRelWidth <= nMinAbs )
2332 {
2333 // If there is not enough space left for all columns to
2334 // get the minimum width, they get the minimum width, anyway.
2335 nAbsForRelWidth = nMinAbs;
2336 bMin = true;
2337 }
2338 else if( nAbsForRelWidth <= (nRelWidth * MINLAY) /
2339 nMinRelColWidth )
2340 {
2341 // If there is enough space for all columns to get the
2342 // minimum width, but not to get a width that takes the
2343 // relative width into account, each column gets the minimum
2344 // width plus some extra space that is based on the additional
2345 // space that is available.
2346 bMinExtra = true;
2347 }
2348 // Otherwise, if there is enough space for every column, every
2349 // column gets this space.
2350
2351 for( auto& rCol : m_aColumnWidths )
2352 {
2353 if( rCol.isRelative )
2354 {
2355 sal_Int32 nAbsCol;
2356 if( 1 == nRelCols )
2357 {
2358 // The last column that has a relative width gets
2359 // all absolute space that is left.
2360 nAbsCol = nAbsForRelWidth;
2361 }
2362 else
2363 {
2364 if( bMin )
2365 {
2366 nAbsCol = MINLAY;
2367 }
2368 else if( bMinExtra )
2369 {
2370 sal_Int32 nExtraRelCol = rCol.width - nMinRelColWidth;
2371 nAbsCol = MINLAY + (nExtraRelCol * nExtraAbs) /
2372 nExtraRel;
2373 }
2374 else
2375 {
2376 nAbsCol = ( rCol.width * nAbsForRelWidth) / nRelWidth;
2377 }
2378 }
2379 rCol.width = nAbsCol;
2380 rCol.isRelative = false;
2381 nAbsForRelWidth -= nAbsCol;
2382 nAbsWidth += nAbsCol;
2383 nRelCols--;
2384 if (nRelCols <= 0)
2385 break;
2386 }
2387 }
2388 }
2389
2390 if( nCols && nAbsWidth )
2391 {
2392 if( nAbsWidth < m_nWidth )
2393 {
2394 // If the table's width is larger than the sum of the absolute
2395 // column widths, every column get some extra width.
2396 sal_Int32 nExtraAbs = m_nWidth - nAbsWidth;
2397 sal_Int32 nAbsLastCol = m_aColumnWidths.back().width + nExtraAbs;
2398 for( colIter = m_aColumnWidths.begin(); colIter < m_aColumnWidths.end()-1; ++colIter )
2399 {
2400 sal_Int32 nAbsCol = colIter->width;
2401 sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
2402 nAbsWidth;
2403 nAbsCol += nExtraAbsCol;
2404 colIter->width = nAbsCol;
2405 nAbsLastCol -= nExtraAbsCol;
2406 }
2407 m_aColumnWidths.back().width = nAbsLastCol;
2408 }
2409 else if( nAbsWidth > m_nWidth )
2410 {
2411 // If the table's width is smaller than the sum of the absolute
2412 // column widths, every column needs to shrink.
2413 // Every column gets the minimum width plus some extra width.
2414 sal_Int32 nExtraAbs = m_nWidth - (nCols * MINLAY);
2415 sal_Int32 nAbsLastCol = MINLAY + nExtraAbs;
2416 for( colIter = m_aColumnWidths.begin(); colIter < m_aColumnWidths.end()-1; ++colIter )
2417 {
2418 sal_Int32 nAbsCol = colIter->width;
2419 sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
2420 nAbsWidth;
2421 nAbsCol = MINLAY + nExtraAbsCol;
2422 colIter->width = nAbsCol;
2423 nAbsLastCol -= nExtraAbsCol;
2424 }
2425 m_aColumnWidths.back().width = nAbsLastCol;
2426 }
2427 }
2428 }
2429
2430 SwTableLines& rLines =
2431 pBox ? pBox->GetTabLines()
2433
2434 sal_uInt32 nStartRow = 0;
2435 sal_uInt32 nRows = m_pRows->size();
2436 for(sal_uInt32 i=0; i<nRows; ++i )
2437 {
2438 // Could we split the table behind the current line?
2439 bool bSplit = true;
2440 if ( m_bHasSubTables )
2441 {
2442 SwXMLTableRow_Impl *pRow = (*m_pRows)[i].get();
2443 for( sal_uInt32 j=0; j<nCols; j++ )
2444 {
2445 bSplit = ( 1 == pRow->GetCell(j)->GetRowSpan() );
2446 if( !bSplit )
2447 break;
2448 }
2449 }
2450
2451 if( bSplit )
2452 {
2453 SwTableLine *pLine =
2454 MakeTableLine( pBox, nStartRow, 0UL, i+1, nCols );
2455 if( pBox || nStartRow>0 )
2456 rLines.push_back( pLine );
2457 nStartRow = i+1;
2458 }
2459 }
2460}
2461
2463{
2464 // this method will modify the document directly -> lock SolarMutex
2465 // This will call all other MakeTable*(..) methods, so
2466 // those don't need to be locked separately.
2467 SolarMutexGuard aGuard;
2468
2469 // #i97274# handle invalid tables
2470 if (!m_pRows || m_pRows->empty() || !GetColumnCount())
2471 {
2472 OSL_FAIL("invalid table: no cells; deleting...");
2474 m_pTableNode = nullptr;
2475 m_pBox1 = nullptr;
2476 m_bOwnsBox1 = false;
2477 m_pSttNd1 = nullptr;
2478 return;
2479 }
2480
2481 SwXMLImport& rSwImport = GetSwImport();
2482
2484
2485 sal_Int16 eHoriOrient = text::HoriOrientation::FULL;
2486 bool bSetHoriOrient = false;
2487
2488 sal_uInt8 nPercentWidth = 0U;
2489
2490 OUString sStyleName;
2492 m_pTableNode->GetTable().SetTableStyleName( sStyleName );
2495
2496 const SfxItemSet *pAutoItemSet = nullptr;
2497 if( !m_aStyleName.isEmpty() &&
2498 rSwImport.FindAutomaticStyle(
2499 XmlStyleFamily::TABLE_TABLE, m_aStyleName, &pAutoItemSet ) &&
2500 pAutoItemSet )
2501 {
2502 const SvxLRSpaceItem *pLRSpace =
2503 pAutoItemSet->GetItemIfSet( RES_LR_SPACE, false );
2504
2505 if( const SwFormatHoriOrient* pItem = pAutoItemSet->GetItemIfSet( RES_HORI_ORIENT, false ) )
2506 {
2507 eHoriOrient = pItem->GetHoriOrient();
2508 switch( eHoriOrient )
2509 {
2510 case text::HoriOrientation::FULL:
2511 if( pLRSpace )
2512 {
2513 eHoriOrient = text::HoriOrientation::NONE;
2514 bSetHoriOrient = true;
2515 }
2516 break;
2517 case text::HoriOrientation::LEFT:
2518 if( pLRSpace )
2519 {
2520 eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
2521 bSetHoriOrient = true;
2522 }
2523 break;
2524 default:
2525 ;
2526 }
2527 }
2528 else
2529 {
2530 bSetHoriOrient = true;
2531 }
2532
2533 const SwFormatFrameSize *pSize =
2534 pAutoItemSet->GetItemIfSet( RES_FRM_SIZE, false );
2535
2536 switch( eHoriOrient )
2537 {
2538 case text::HoriOrientation::FULL:
2540 // For text::HoriOrientation::NONE we would prefer to use the sum
2541 // of the relative column widths as reference width.
2542 // Unfortunately this works only if this sum interpreted as
2543 // twip value is larger than the space that is available.
2544 // We don't know that space, so we have to use MAX_WIDTH, too.
2545 // Even if a size is specified, it will be ignored!
2547 break;
2548 default:
2549 if( pSize )
2550 {
2551 if( pSize->GetWidthPercent() )
2552 {
2553 // The width will be set in MakeTable_
2554 nPercentWidth = pSize->GetWidthPercent();
2555 }
2556 else
2557 {
2558 m_nWidth = pSize->GetWidth();
2559 sal_Int32 const min = static_cast<sal_Int32>(
2560 std::min<sal_uInt32>(GetColumnCount() * MINLAY, MAX_WIDTH));
2561 if( m_nWidth < min )
2562 {
2563 m_nWidth = min;
2564 }
2565 else if( m_nWidth > MAX_WIDTH )
2566 {
2568 }
2569 m_bRelWidth = false;
2570 }
2571 }
2572 else
2573 {
2574 eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH == eHoriOrient
2575 ? text::HoriOrientation::NONE : text::HoriOrientation::FULL;
2576 bSetHoriOrient = true;
2578 }
2579 break;
2580 }
2581
2582 pFrameFormat->SetFormatAttr( *pAutoItemSet );
2583 }
2584 else
2585 {
2586 bSetHoriOrient = true;
2588 }
2589
2591 assert(m_pBox1 == pLine1->GetTabBoxes()[0] && !m_bOwnsBox1 && "Why is box 1 change?");
2593 pLine1->GetTabBoxes().erase( pLine1->GetTabBoxes().begin() );
2594 m_bOwnsBox1 = true;
2595
2596 m_pLineFormat = static_cast<SwTableLineFormat*>(pLine1->GetFrameFormat());
2598
2599 MakeTable_();
2600
2601 if( bSetHoriOrient )
2602 pFrameFormat->SetFormatAttr( SwFormatHoriOrient( 0, eHoriOrient ) );
2603
2604 // This must be after the call to MakeTable_, because nWidth might be
2605 // changed there.
2606 pFrameFormat->LockModify();
2608 aSize.SetWidthPercent( nPercentWidth );
2609 pFrameFormat->SetFormatAttr( aSize );
2610 pFrameFormat->UnlockModify();
2611
2612 for (std::unique_ptr<SwXMLTableRow_Impl> & rRow : *m_pRows)
2613 rRow->Dispose();
2614
2615 // now that table is complete, change into DDE table (if appropriate)
2616 if (m_xDDESource.is())
2617 {
2618 // change existing table into DDE table:
2619 // 1) Get DDE field type (get data from dde-source context),
2620 SwDDEFieldType* pFieldType = lcl_GetDDEFieldType( m_xDDESource.get(),
2621 m_pTableNode );
2622
2623 // 2) release the DDE source context,
2624 m_xDDESource.set(nullptr);
2625
2626 // 3) create new DDE table, and
2627 std::unique_ptr<SwDDETable> pDDETable( new SwDDETable( m_pTableNode->GetTable(),
2628 pFieldType, false ) );
2629
2630 // 4) set new (DDE)table at node.
2631 m_pTableNode->SetNewTable(std::move(pDDETable), false);
2632 }
2633
2634 // ??? this is always false: root frame is only created in SwViewShell::Init
2636 {
2639 }
2640}
2641
2642void SwXMLTableContext::MakeTable( SwTableBox *pBox, sal_Int32 nW )
2643{
2644 //FIXME: here would be a great place to handle XmlId for subtable
2647 m_nWidth = nW;
2649
2650 MakeTable_( pBox );
2651
2652 for (std::unique_ptr<SwXMLTableRow_Impl> & rpRow : *m_pRows)
2653 {
2654 // i#113600, to break the cyclic reference to SwXMLTableContext object
2655 rpRow->Dispose();
2656 }
2657}
2658
2660 const SwStartNode *const pPrevSttNd,
2661 OUString const*const pStringValueStyleName)
2662{
2663 // The topmost table is the only table that maintains the two members
2664 // pBox1 and bFirstSection.
2665 if( m_xParentTable.is() )
2666 return static_cast<SwXMLTableContext *>(m_xParentTable.get())
2667 ->InsertTableSection(pPrevSttNd, pStringValueStyleName);
2668
2669 const SwStartNode *pStNd;
2670
2671 if( m_bFirstSection )
2672 {
2673 Reference<XInterface> xCursorTunnel( GetImport().GetTextImport()->GetCursor(),
2674 UNO_QUERY);
2675 OSL_ENSURE( xCursorTunnel.is(), "missing XUnoTunnel for Cursor" );
2676 OTextCursorHelper *pTextCursor = dynamic_cast<OTextCursorHelper*>(xCursorTunnel.get());
2677 assert(pTextCursor && "SwXTextCursor missing");
2678
2679 // The Cursor already is in the first section
2680 pStNd = pTextCursor->GetPaM()->GetPointNode().FindTableBoxStartNode();
2681 m_bFirstSection = false;
2682 GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2683 GetImport().GetTextImport()->GetCursor(), "Standard", true );
2684 }
2685 else
2686 {
2687 SwDoc* pDoc = GetSwImport().getDoc();
2688 const SwEndNode *pEndNd = pPrevSttNd ? pPrevSttNd->EndOfSectionNode()
2690 // #i78921# - make code robust
2691 OSL_ENSURE( pDoc, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCursor> instance." );
2692 if ( !pDoc )
2693 {
2694 pDoc = &const_cast<SwDoc&>(pEndNd->GetDoc());
2695 }
2696 SwNodeOffset nOffset(pPrevSttNd ? 1 : 0);
2697 SwNodeIndex aIdx( *pEndNd, nOffset );
2698 SwTextFormatColl *pColl =
2700 pStNd = pDoc->GetNodes().MakeTextSection( aIdx.GetNode(), SwTableBoxStartNode,
2701 pColl );
2702 // Consider the case that a table is defined without a row.
2703 if( !pPrevSttNd && m_pBox1 != nullptr )
2704 {
2705 m_pBox1->m_pStartNode = pStNd;
2706 SwContentNode *pCNd = pDoc->GetNodes()[ pStNd->GetIndex() + 1 ]
2707 ->GetContentNode();
2708 SwFrameFormat *const pTableFormat = m_pTableNode->GetTable().GetFrameFormat();
2709 rtl::Reference<SwXCell> xParent = SwXCell::CreateXCell( pTableFormat, m_pBox1 );
2711 SwPaM aPam(*pCNd, *pCNd);
2712 rtl::Reference<SwXTextCursor> xTextCursor =
2713 new SwXTextCursor(*pDoc, xParent, CursorType::TableText,
2714 *aPam.GetPoint(), aPam.GetMark());
2715 GetImport().GetTextImport()->SetCursor( static_cast<XWordCursor*>(xTextCursor.get()) );
2716 }
2717 }
2718
2719 if (pStringValueStyleName)
2720 { // fdo#62147: apply style to paragraph on string-value cell
2721 GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
2722 GetImport().GetTextImport()->GetCursor(), *pStringValueStyleName,
2723 true, false, -1, false); // parameters same as sCellParaStyleName
2724 }
2725
2726 return pStNd;
2727}
2728
2730{
2731 if( IsValid() && !m_xParentTable.is() )
2732 {
2733 MakeTable();
2734 GetImport().GetTextImport()->SetCursor( m_xOldCursor );
2735 }
2736}
2737
2738/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ CheckPosInFly
check if target position is in fly anchored at source range
virtual bool CopyRange(SwPaM &rPam, SwPosition &rPos, SwCopyFlags flags) const =0
Copy a selected content range to a position.
virtual void DeleteSection(SwNode *pNode)=0
Delete section containing the node.
virtual SwFieldType * GetFieldType(SwFieldIds nResId, const OUString &rName, bool bDbFieldMatching) const =0
virtual SwFieldType * InsertFieldType(const SwFieldType &)=0
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
bool IsTextFormat() const
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
SvXMLImport & GetImport()
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
void SetContentProtect(bool bNew)
tools::Long GetWidth() const
Marks a character position inside a document model content node (SwContentNode)
OUString const & GetCmd() const
Definition: ddefld.cxx:194
SfxLinkUpdateMode GetType() const
Definition: ddefld.hxx:82
Definition: doc.hxx:195
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:323
SwNodes & GetNodes()
Definition: doc.hxx:420
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:365
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:413
SwTableFormat * FindTableFormatByName(const OUString &rName, bool bAll=false) const
Definition: ndtbl.cxx:3924
OUString GetUniqueTableName() const
Definition: ndtbl.cxx:3872
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:434
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1423
Ends a section of nodes in the document model.
Definition: node.hxx:378
void SetWidthPercent(sal_uInt8 n)
Definition: fmtfsize.hxx:95
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
SwFrameSize GetHeightSizeType() const
Definition: fmtfsize.hxx:80
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:618
const SwFormatFillOrder & GetFillOrder(bool=true) const
Frame-attributes - implemented in frmatr.hxx.
Definition: fmtfordr.hxx:49
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
virtual sal_uInt16 ResetAllFormatAttr()
Takes all hints from Delta-Array,.
Definition: format.cxx:646
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Templatized version of GetItemState() to directly return the correct type.
Definition: format.hxx:111
Style of a layout element.
Definition: frmfmt.hxx:62
virtual void SetFormatName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2593
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:903
SwNodeOffset GetIndex() const
Definition: node.hxx:312
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:218
SwDoc & GetDoc()
Definition: node.hxx:233
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:724
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:728
const IDocumentFieldsAccess & getIDocumentFieldsAccess() const
Provides access to the document fields administration interface.
Definition: node.cxx:2157
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:733
SwStartNode * MakeTextSection(const SwNode &rWhere, SwStartNodeType eSttNdTyp, SwTextFormatColl *pColl)
Definition: nodes.cxx:1925
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
const SwPosition * GetPoint() const
Definition: pam.hxx:261
Starts a section of nodes in the document model.
Definition: node.hxx:348
static void FillUIName(const OUString &rName, OUString &rFillName, SwGetPoolIdFromName)
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:436
void SetUpper(SwTableLine *pNew)
Definition: swtable.hxx:472
void ActualiseValueBox()
Definition: swtable.cxx:2859
void setRowSpan(sal_Int32 nNewRowSpan)
Definition: swtable.cxx:80
const SwStartNode * m_pStartNode
Definition: swtable.hxx:445
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:474
SwTableLines & GetTabLines()
Definition: swtable.hxx:467
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:488
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:2026
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1990
SwTableLine is one table row in the document model.
Definition: swtable.hxx:374
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:396
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1481
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:384
void push_back(SwTableLine *pLine)
Definition: swtable.hxx:92
void SetNewTable(std::unique_ptr< SwTable >, bool bNewFrames=true)
Definition: ndtbl.cxx:2456
const SwTable & GetTable() const
Definition: node.hxx:542
void MakeOwnFrames(SwPosition *pIdxBehind=nullptr)
Creates the frms for the table node (i.e.
Definition: ndtbl.cxx:2363
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2410
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableNode * GetTableNode() const
Definition: swtable.cxx:2215
void SetTableModel(bool bNew)
Definition: swtable.hxx:192
void SetRowsToRepeat(sal_uInt16 nNumOfRows)
Definition: swtable.hxx:202
SwTableLines & GetTabLines()
Definition: swtable.hxx:206
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
void SetTableStyleName(const OUString &rName)
Set the new table style name for this table.
Definition: swtable.hxx:199
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:2208
Represents the style of a paragraph.
Definition: fmtcol.hxx:61
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
OUString InsertText(const OUString &rStr, const SwContentIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2370
const OUString & GetText() const
Definition: ndtxt.hxx:244
static rtl::Reference< SwXCell > CreateXCell(SwFrameFormat *pTableFormat, SwTableBox *pBox, SwTable *pTable=nullptr)
Definition: unotbl.cxx:1122
OUString & GetDDEItem()
Definition: xmltbli.cxx:939
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const Reference< xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmltbli.cxx:951
SwXMLDDETableContext_Impl(SwXMLImport &rImport)
Definition: xmltbli.cxx:945
bool GetIsAutomaticUpdate() const
Definition: xmltbli.cxx:941
OUString & GetDDEApplication()
Definition: xmltbli.cxx:938
OUString & GetConnectionName()
Definition: xmltbli.cxx:937
OUString & GetDDETopic()
Definition: xmltbli.cxx:940
const SwDoc * getDoc() const
Definition: xmlimp.cxx:1665
bool FindAutomaticStyle(XmlStyleFamily nFamily, const OUString &rName, const SfxItemSet **ppItemSet) const
Definition: xmlfmt.cxx:1043
bool IsProtected() const
Definition: xmltbli.cxx:138
void SetRowSpan(sal_uInt32 nSet)
Definition: xmltbli.cxx:131
bool IsCovered() const
Definition: xmltbli.cxx:139
void SetStyleName(const OUString &rStyleName)
Definition: xmltbli.cxx:133
OUString m_StringValue
Definition: xmltbli.cxx:88
bool HasStringValue() const
Definition: xmltbli.cxx:140
bool HasValue() const
Definition: xmltbli.cxx:137
const SwStartNode * m_pStartNode
Definition: xmltbli.cxx:95
sal_uInt32 m_nRowSpan
Definition: xmltbli.cxx:96
sal_uInt32 GetColSpan() const
Definition: xmltbli.cxx:132
void SetStartNode(const SwStartNode *pSttNd)
Definition: xmltbli.cxx:186
sal_uInt32 GetRowSpan() const
Definition: xmltbli.cxx:130
SwXMLTableCell_Impl(sal_uInt32 nRSpan=1, sal_uInt32 nCSpan=1)
Definition: xmltbli.cxx:106
SwXMLTableContext * GetSubTable() const
Definition: xmltbli.cxx:192
double GetValue() const
Definition: xmltbli.cxx:136
OUString m_sFormula
Definition: xmltbli.cxx:90
const OUString & GetStyleName() const
Definition: xmltbli.cxx:134
OUString m_aStyleName
Definition: xmltbli.cxx:86
OUString const * GetStringValue() const
Definition: xmltbli.cxx:141
const SwStartNode * GetStartNode() const
Definition: xmltbli.cxx:145
void Set(const OUString &rStyleName, sal_uInt32 nRSpan, sal_uInt32 nCSpan, const SwStartNode *pStNd, SwXMLTableContext *pTable, bool bProtect, const OUString *pFormula, bool bHasValue, bool bCovered, double dVal, OUString const *const pStringValue)
Definition: xmltbli.cxx:153
const OUString & GetFormula() const
Definition: xmltbli.cxx:135
SvXMLImportContextRef m_xSubTable
Definition: xmltbli.cxx:93
sal_uInt32 m_nColSpan
Definition: xmltbli.cxx:97
bool IsUsed() const
Definition: xmltbli.cxx:127
std::unique_ptr< SwXMLTableRows_Impl > m_pRows
Definition: xmltbli.hxx:68
const SwXMLTableCell_Impl * GetCell(sal_uInt32 nRow, sal_uInt32 nCol) const
Definition: xmltbli.cxx:1102
sal_uInt32 GetColumnCount() const
Definition: xmltbli.hxx:202
std::unique_ptr< map_BoxFormat > m_pSharedBoxFormats
Definition: xmltbli.hxx:82
std::vector< ColumnWidthInfo > m_aColumnWidths
Definition: xmltbli.hxx:62
bool IsValid() const
Definition: xmltbli.hxx:167
void InsertCoveredCell(const OUString &rStyleName)
Sets formatting of an already created covered cell.
Definition: xmltbli.cxx:1490
void FixRowSpan(sal_uInt32 nRow, sal_uInt32 nCol, sal_uInt32 nColSpan)
Definition: xmltbli.cxx:1619
sal_uInt32 m_nCurRow
Definition: xmltbli.hxx:93
bool m_bFirstSection
Definition: xmltbli.hxx:88
SwTableBoxFormat * m_pBoxFormat
Definition: xmltbli.hxx:75
void InsertColumn(sal_Int32 nWidth, bool bRelWidth, const OUString *pDfltCellStyleName=nullptr)
Definition: xmltbli.cxx:1324
sal_uInt32 m_nNonMergedCurCol
Same as m_nCurCol, but not incremented multiple times for table cells with row span.
Definition: xmltbli.hxx:96
SwTableBox * NewTableBox(const SwStartNode *pStNd, SwTableLine *pUpper)
Definition: xmltbli.cxx:1654
void InsertCell(const OUString &rStyleName, sal_uInt32 nRowSpan, sal_uInt32 nColSpan, const SwStartNode *pStNd, SwXMLTableContext *pTable=nullptr, bool bIsProtected=false, const OUString *pFormula=nullptr, bool bHasValue=false, double fValue=0.0, OUString const *const pStringValue=nullptr)
Definition: xmltbli.cxx:1377
std::optional< std::vector< OUString > > m_xColumnDefaultCellStyleNames
Definition: xmltbli.hxx:63
const SwStartNode * GetPrevStartNode(sal_uInt32 nRow, sal_uInt32 nCol) const
Definition: xmltbli.cxx:1582
css::uno::Reference< css::text::XTextContent > m_xTextContent
Definition: xmltbli.hxx:66
SwTableBoxFormat * GetSharedBoxFormat(SwTableBox *pBox, const OUString &rStyleName, sal_Int32 nColumnWidth, bool bProtected, bool bMayShare, bool &bNew, bool *pModifyLocked)
sets the appropriate SwTableBoxFormat at pBox.
Definition: xmltbli.cxx:1681
const SwStartNode * InsertTableSection(const SwStartNode *pPrevSttNd=nullptr, OUString const *pStringValueStyleName=nullptr)
Definition: xmltbli.cxx:2659
void ReplaceWithEmptyCell(sal_uInt32 nRow, sal_uInt32 nCol, bool bRows)
Definition: xmltbli.cxx:1636
sal_uInt16 m_nHeaderRows
Definition: xmltbli.hxx:92
const SwStartNode * GetLastStartNode() const
Definition: xmltbli.hxx:207
SwXMLImport & GetSwImport()
Definition: xmltbli.hxx:152
void MakeTable(SwTableBox *pBox, sal_Int32 nWidth)
Definition: xmltbli.cxx:2642
void MakeTable_(SwTableBox *pBox=nullptr)
Definition: xmltbli.cxx:2196
SvXMLImportContextRef m_xParentTable
Definition: xmltbli.hxx:84
OUString m_aStyleName
Definition: xmltbli.hxx:52
std::unordered_map< TableBoxIndex, SwTableBoxFormat *, TableBoxIndexHasher > map_BoxFormat
Definition: xmltbli.hxx:81
SwTableBox * m_pBox1
Definition: xmltbli.hxx:71
virtual ~SwXMLTableContext() override
Definition: xmltbli.cxx:1266
rtl::Reference< SwXMLDDETableContext_Impl > m_xDDESource
Definition: xmltbli.hxx:86
SwXMLTableContext * GetParentTable() const
Definition: xmltbli.hxx:197
css::uno::Reference< css::text::XTextCursor > m_xOldCursor
Definition: xmltbli.hxx:65
sal_Int32 m_nWidth
Definition: xmltbli.hxx:97
bool IsInsertColPossible() const
Definition: xmltbli.hxx:165
SwTableLine * MakeTableLine(SwTableBox *pUpper, sal_uInt32 nTopRow, sal_uInt32 nLeftCol, sal_uInt32 nBottomRow, sal_uInt32 nRightCol)
Definition: xmltbli.cxx:1998
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: xmltbli.cxx:1278
sal_Int32 GetColumnWidth(sal_uInt32 nCol, sal_uInt32 nColSpan) const
Definition: xmltbli.cxx:1355
bool IsInsertRowPossible() const
Definition: xmltbli.hxx:166
SwTableNode * m_pTableNode
Definition: xmltbli.hxx:70
OUString m_aTemplateName
Definition: xmltbli.hxx:54
void InsertRepRows(sal_uInt32 nCount)
Definition: xmltbli.cxx:1542
const SwStartNode * m_pSttNd1
Definition: xmltbli.hxx:73
bool m_bHasSubTables
Definition: xmltbli.hxx:90
sal_uInt32 m_nCurCol
Definition: xmltbli.hxx:94
OUString m_aDfltCellStyleName
Definition: xmltbli.hxx:53
void InsertRow(const OUString &rStyleName, const OUString &rDfltCellStyleName, bool bInHead)
Definition: xmltbli.cxx:1502
SwXMLTableContext(SwXMLImport &rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
if set, call pBox->LockModify() and return old lock status
SwTableLineFormat * m_pLineFormat
Definition: xmltbli.hxx:76
OUString GetColumnDefaultCellStyleName(sal_uInt32 nCol) const
Definition: xmltbli.cxx:1369
static constexpr sal_Int32 MAX_WIDTH
Definition: xmltbli.hxx:102
SwTableBox * MakeTableBox(SwTableLine *pUpper, const SwXMLTableCell_Impl *pStartNode, sal_uInt32 nLeftCol, sal_uInt32 nRightCol)
Definition: xmltbli.cxx:1834
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
Definition: xmltbli.cxx:2729
std::vector< std::unique_ptr< SwXMLTableCell_Impl > > m_Cells
Definition: xmltbli.cxx:207
const OUString & GetStyleName() const
Definition: xmltbli.cxx:225
OUString m_aDefaultCellStyleName
Definition: xmltbli.cxx:206
bool IsSplitable() const
Definition: xmltbli.cxx:223
void Set(const OUString &rStyleName, const OUString &rDfltCellStyleName)
Definition: xmltbli.cxx:279
OUString m_aStyleName
Definition: xmltbli.cxx:205
SwXMLTableCell_Impl * GetCell(sal_uInt32 nCol)
Definition: xmltbli.cxx:250
const OUString & GetDefaultCellStyleName() const
Definition: xmltbli.cxx:226
void Expand(sal_uInt32 nCells, bool bOneCell)
Definition: xmltbli.cxx:260
SwXMLTableRow_Impl(OUString aStyleName, sal_uInt32 nCells, const OUString *pDfltCellStyleName=nullptr)
Definition: xmltbli.cxx:231
void SetSplitable(bool bSet)
Definition: xmltbli.cxx:222
SwFrameFormat * GetFrameFormat()
Definition: unotbl.cxx:1979
size_t operator()(const TableBoxIndex &rArg) const
Definition: xmltbli.cxx:1096
bool mbProtected
Definition: xmltbli.cxx:1076
TableBoxIndex(OUString aName, sal_Int32 nWidth, bool bProtected)
Definition: xmltbli.cxx:1078
sal_Int32 mnWidth
Definition: xmltbli.cxx:1075
OUString msName
Definition: xmltbli.cxx:1074
bool operator==(const TableBoxIndex &rArg) const
Definition: xmltbli.cxx:1085
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
static void convertDuration(OUStringBuffer &rBuffer, const double fTime)
static bool convertBool(bool &rBool, std::u16string_view rString)
static bool IsFuzzing()
int nCount
#define DBG_TESTSOLARMUTEX()
#define max(a, b)
Reference< XSingleServiceFactory > xFactory
@ Variable
Frame is variable in Var-direction.
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(158)
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
constexpr TypedWhichId< SwFormatHoriOrient > RES_HORI_ORIENT(109)
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(157)
constexpr TypedWhichId< SvxProtectItem > RES_PROTECT(106)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(97)
OUString aName
sal_Int64 n
SfxLinkUpdateMode
OUString sPrefix
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
const char * sName
size
int i
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
const sal_Unicode cTokenSeparator
OUString toString(OptionInfo const *info)
XML_TABLE_ROW
XML_TABLE_COLUMN_GROUP
XML_TABLE_COLUMNS
XML_DDE_SOURCE
XML_AUTOMATIC_UPDATE
XML_TABLE_COLUMN
XML_DDE_APPLICATION
XML_TABLE_HEADER_COLUMNS
XML_NAME
XML_TABLE_HEADER_ROWS
XML_TABLE_ROWS
XML_PROTECTED
XML_DDE_TOPIC
XML_DDE_ITEM
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
sal_Int32 toInt32(std::u16string_view rStr)
@ SwTableBoxStartNode
Definition: ndtyp.hxx:53
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
@ RES_POOLCOLL_STANDARD
Standard.
Definition: poolfmt.hxx:250
QPRO_FUNC_TYPE nType
sal_uIntPtr sal_uLong
Marks a position in the document model.
Definition: pam.hxx:37
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
#define MINLAY
Definition: swtypes.hxx:62
unsigned char sal_uInt8
#define SAL_MAX_INT32
TABLE
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
#define XMLOFF_WARN_UNKNOWN(area, rIter)
#define XML_ELEMENT(prefix, name)
constexpr sal_uInt16 XML_NAMESPACE_OOOW
static OUString lcl_GenerateFieldTypeName(const OUString &sPrefix, SwTableNode *pTableNode)
Definition: xmltbli.cxx:988
static SwDDEFieldType * lcl_GetDDEFieldType(SwXMLDDETableContext_Impl *pContext, SwTableNode *pTableNode)
Definition: xmltbli.cxx:1010
std::vector< std::unique_ptr< SwXMLTableRow_Impl > > SwXMLTableRows_Impl
Definition: xmltbli.hxx:39
#define SV_COUNTRY_LANGUAGE_OFFSET