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