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