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