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