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