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