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