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