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