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