LibreOffice Module sw (master)  1
swtable.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 #include <hints.hxx>
22 #include <editeng/lrspitem.hxx>
23 #include <editeng/shaditem.hxx>
24 #include <editeng/adjustitem.hxx>
25 #include <editeng/colritem.hxx>
26 #include <osl/diagnose.h>
27 #include <sfx2/linkmgr.hxx>
28 #include <fmtfsize.hxx>
29 #include <fmtornt.hxx>
30 #include <fmtpdsc.hxx>
31 #include <fldbas.hxx>
32 #include <fmtfld.hxx>
33 #include <frmatr.hxx>
34 #include <doc.hxx>
38 #include <docary.hxx>
39 #include <frame.hxx>
40 #include <swtable.hxx>
41 #include <ndtxt.hxx>
42 #include <tabcol.hxx>
43 #include <tabfrm.hxx>
44 #include <cellfrm.hxx>
45 #include <rowfrm.hxx>
46 #include <swserv.hxx>
47 #include <expfld.hxx>
48 #include <mdiexp.hxx>
49 #include <cellatr.hxx>
50 #include <txatbase.hxx>
51 #include <htmltbl.hxx>
52 #include <swtblfmt.hxx>
53 #include <ndindex.hxx>
54 #include <tblrwcl.hxx>
55 #include <shellres.hxx>
56 #include <viewsh.hxx>
57 #include <redline.hxx>
58 #include <vector>
59 #include <calbck.hxx>
60 
61 #ifdef DBG_UTIL
62 #define CHECK_TABLE(t) (t).CheckConsistency();
63 #else
64 #define CHECK_TABLE(t)
65 #endif
66 
67 using namespace com::sun::star;
68 
69 
70 #define COLFUZZY 20
71 
72 static void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
73  bool bChgAlign, sal_uLong nNdPos );
74 
75 sal_Int32 SwTableBox::getRowSpan() const
76 {
77  return mnRowSpan;
78 }
79 
80 void SwTableBox::setRowSpan( sal_Int32 nNewRowSpan )
81 {
82  mnRowSpan = nNewRowSpan;
83 }
84 
86 {
87  return mbDummyFlag;
88 }
89 
90 void SwTableBox::setDummyFlag( bool bDummy )
91 {
92  mbDummyFlag = bDummy;
93 }
94 
95 //JP 15.09.98: Bug 55741 - Keep tabs (front and rear)
96 static OUString& lcl_TabToBlankAtSttEnd( OUString& rText )
97 {
98  sal_Unicode c;
99  sal_Int32 n;
100 
101  for( n = 0; n < rText.getLength() && ' ' >= ( c = rText[n] ); ++n )
102  if( '\x9' == c )
103  rText = rText.replaceAt( n, 1, " " );
104  for( n = rText.getLength(); n && ' ' >= ( c = rText[--n] ); )
105  if( '\x9' == c )
106  rText = rText.replaceAt( n, 1, " " );
107  return rText;
108 }
109 
110 static OUString& lcl_DelTabsAtSttEnd( OUString& rText )
111 {
112  sal_Unicode c;
113  sal_Int32 n;
114  OUStringBuffer sBuff(rText);
115 
116  for( n = 0; n < sBuff.getLength() && ' ' >= ( c = sBuff[ n ]); ++n )
117  {
118  if( '\x9' == c )
119  sBuff.remove( n--, 1 );
120  }
121  for( n = sBuff.getLength(); n && ' ' >= ( c = sBuff[ --n ]); )
122  {
123  if( '\x9' == c )
124  sBuff.remove( n, 1 );
125  }
126  rText = sBuff.makeStringAndClear();
127  return rText;
128 }
129 
130 void InsTableBox( SwDoc& rDoc, SwTableNode* pTableNd,
131  SwTableLine* pLine, SwTableBoxFormat* pBoxFrameFormat,
132  SwTableBox* pBox,
133  sal_uInt16 nInsPos, sal_uInt16 nCnt )
134 {
135  OSL_ENSURE( pBox->GetSttNd(), "Box with no start node" );
136  SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
137  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
138  if( !pCNd )
139  pCNd = rDoc.GetNodes().GoNext( &aIdx );
140  OSL_ENSURE( pCNd, "Box with no content node" );
141 
142  if( pCNd->IsTextNode() )
143  {
144  if( pBox->GetSaveNumFormatColor() && pCNd->GetpSwAttrSet() )
145  {
146  SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
147  if( pBox->GetSaveUserColor() )
148  aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
149  else
150  aAttrSet.ClearItem( RES_CHRATR_COLOR );
151  rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
152  static_cast<SwTextNode*>(pCNd)->GetTextColl(),
153  &aAttrSet, nInsPos, nCnt );
154  }
155  else
156  rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
157  static_cast<SwTextNode*>(pCNd)->GetTextColl(),
158  pCNd->GetpSwAttrSet(),
159  nInsPos, nCnt );
160  }
161  else
162  rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
163  rDoc.GetDfltTextFormatColl(), nullptr,
164  nInsPos, nCnt );
165 
166  sal_Int32 nRowSpan = pBox->getRowSpan();
167  if( nRowSpan != 1 )
168  {
169  SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
170  for( sal_uInt16 i = 0; i < nCnt; ++i )
171  {
172  pBox = rTableBoxes[ i + nInsPos ];
173  pBox->setRowSpan( nRowSpan );
174  }
175  }
176 }
177 
179  : SwClient( nullptr ),
180  m_pTableNode( nullptr ),
181  m_nGraphicsThatResize( 0 ),
182  m_nRowsToRepeat( 1 ),
183  m_bModifyLocked( false ),
184  m_bNewModel( true )
185 {
186  // default value set in the options
188 }
189 
190 SwTable::SwTable( const SwTable& rTable )
191  : SwClient( rTable.GetFrameFormat() ),
192  m_pTableNode( nullptr ),
193  m_eTableChgMode( rTable.m_eTableChgMode ),
194  m_nGraphicsThatResize( 0 ),
195  m_nRowsToRepeat( rTable.GetRowsToRepeat() ),
196  maTableStyleName(rTable.maTableStyleName),
197  m_bModifyLocked( false ),
198  m_bNewModel( rTable.m_bNewModel )
199 {
200 }
201 
202 void DelBoxNode( SwTableSortBoxes const & rSortCntBoxes )
203 {
204  for (size_t n = 0; n < rSortCntBoxes.size(); ++n)
205  {
206  rSortCntBoxes[ n ]->m_pStartNode = nullptr;
207  }
208 }
209 
211 {
212  if( m_xRefObj.is() )
213  {
214  SwDoc* pDoc = GetFrameFormat()->GetDoc();
215  if( !pDoc->IsInDtor() ) // then remove from the list
217 
218  m_xRefObj->Closed();
219  }
220 
221  // the table can be deleted if it's the last client of the FrameFormat
222  SwTableFormat* pFormat = GetFrameFormat();
223  pFormat->Remove( this ); // remove
224 
225  if( !pFormat->HasWriterListeners() )
226  pFormat->GetDoc()->DelTableFrameFormat( pFormat ); // and delete
227 
228  // Delete the pointers from the SortArray of the boxes. The objects
229  // are preserved and are deleted by the lines/boxes arrays dtor.
230  // Note: unfortunately not enough, pointers to the StartNode of the
231  // section need deletion.
234 }
235 
236 namespace
237 {
238 
239 template<class T>
240 T lcl_MulDiv64(sal_uInt64 nA, sal_uInt64 nM, sal_uInt64 nD)
241 {
242  return static_cast<T>((nA*nM)/nD);
243 }
244 
245 }
246 
247 static void FormatInArr( std::vector<SwFormat*>& rFormatArr, SwFormat* pBoxFormat )
248 {
249  std::vector<SwFormat*>::const_iterator it = std::find( rFormatArr.begin(), rFormatArr.end(), pBoxFormat );
250  if ( it == rFormatArr.end() )
251  rFormatArr.push_back( pBoxFormat );
252 }
253 
254 static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const tools::Long nOld,
255  const tools::Long nNew, std::vector<SwFormat*>& rFormatArr );
256 
257 static void lcl_ModifyLines( SwTableLines &rLines, const tools::Long nOld,
258  const tools::Long nNew, std::vector<SwFormat*>& rFormatArr, const bool bCheckSum )
259 {
260  for ( size_t i = 0; i < rLines.size(); ++i )
261  ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFormatArr );
262  if( bCheckSum )
263  {
264  for(SwFormat* pFormat : rFormatArr)
265  {
266  const SwTwips nBox = lcl_MulDiv64<SwTwips>(pFormat->GetFrameSize().GetWidth(), nNew, nOld);
267  SwFormatFrameSize aNewBox( SwFrameSize::Variable, nBox, 0 );
268  pFormat->LockModify();
269  pFormat->SetFormatAttr( aNewBox );
270  pFormat->UnlockModify();
271  }
272  }
273 }
274 
275 static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const tools::Long nOld,
276  const tools::Long nNew, std::vector<SwFormat*>& rFormatArr )
277 {
278  sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
279  sal_uInt64 nOriginalSum = 0; // Sum of original widths
280  for ( size_t i = 0; i < rBoxes.size(); ++i )
281  {
282  SwTableBox &rBox = *rBoxes[i];
283  if ( !rBox.GetTabLines().empty() )
284  {
285  // For SubTables the rounding problem will not be solved :-(
286  ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFormatArr, false );
287  }
288  // Adjust the box
289  SwFrameFormat *pFormat = rBox.GetFrameFormat();
290  sal_uInt64 nBox = pFormat->GetFrameSize().GetWidth();
291  nOriginalSum += nBox;
292  nBox *= nNew;
293  nBox /= nOld;
294  const sal_uInt64 nWishedSum = lcl_MulDiv64<sal_uInt64>(nOriginalSum, nNew, nOld) - nSum;
295  if( nWishedSum > 0 )
296  {
297  if( nBox == nWishedSum )
298  FormatInArr( rFormatArr, pFormat );
299  else
300  {
301  nBox = nWishedSum;
302  pFormat = rBox.ClaimFrameFormat();
303  SwFormatFrameSize aNewBox( SwFrameSize::Variable, static_cast< SwTwips >(nBox), 0 );
304  pFormat->LockModify();
305  pFormat->SetFormatAttr( aNewBox );
306  pFormat->UnlockModify();
307  }
308  }
309  else {
310  OSL_FAIL( "Rounding error" );
311  }
312  nSum += nBox;
313  }
314 }
315 
316 void SwTable::SwClientNotify(const SwModify&, const SfxHint& rHint)
317 {
318  auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint);
319  if(!pLegacy)
320  return;
321  // catch SSize changes, to adjust the lines/boxes
322  const sal_uInt16 nWhich = pLegacy->GetWhich();
323  const SwFormatFrameSize* pNewSize = nullptr, *pOldSize = nullptr;
324  switch(nWhich)
325  {
326  case RES_ATTRSET_CHG:
327  {
328  if (pLegacy->m_pOld && pLegacy->m_pNew
329  && SfxItemState::SET == static_cast<const SwAttrSetChg*>(pLegacy->m_pNew)->GetChgSet()->GetItemState(
330  RES_FRM_SIZE,
331  false,
332  reinterpret_cast<const SfxPoolItem**>(&pNewSize)))
333  {
334  pOldSize = &static_cast<const SwAttrSetChg*>(pLegacy->m_pOld)->GetChgSet()->GetFrameSize();
335  }
336  }
337  break;
338  case RES_FRM_SIZE:
339  {
340  pOldSize = static_cast<const SwFormatFrameSize*>(pLegacy->m_pOld);
341  pNewSize = static_cast<const SwFormatFrameSize*>(pLegacy->m_pNew);
342  }
343  break;
344  default:
345  CheckRegistration(pLegacy->m_pOld);
346  }
347  if (pOldSize && pNewSize && !m_bModifyLocked)
348  AdjustWidths(pOldSize->GetWidth(), pNewSize->GetWidth());
349 }
350 
351 void SwTable::AdjustWidths( const tools::Long nOld, const tools::Long nNew )
352 {
353  std::vector<SwFormat*> aFormatArr;
354  aFormatArr.reserve( m_aLines[0]->GetTabBoxes().size() );
355  ::lcl_ModifyLines( m_aLines, nOld, nNew, aFormatArr, true );
356 }
357 
358 static void lcl_RefreshHidden( SwTabCols &rToFill, size_t nPos )
359 {
360  for ( size_t i = 0; i < rToFill.Count(); ++i )
361  {
362  if ( std::abs(static_cast<tools::Long>(nPos) - rToFill[i]) <= COLFUZZY )
363  {
364  rToFill.SetHidden( i, false );
365  break;
366  }
367  }
368 }
369 
370 static void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
371  const SwFrameFormat *pTabFormat, const bool bHidden,
372  const bool bRefreshHidden )
373 {
374  const tools::Long nWish = pTabFormat->GetFrameSize().GetWidth();
375  OSL_ENSURE(nWish, "weird <= 0 width frmfrm");
376 
377  // The value for the left edge of the box is calculated from the
378  // widths of the previous boxes.
379  tools::Long nPos = 0;
380  tools::Long nLeftMin = 0;
381  tools::Long nRightMax = 0;
382  if (nWish != 0) //fdo#33012 0 width frmfmt
383  {
384  SwTwips nSum = 0;
385  const SwTableBox *pCur = pBox;
386  const SwTableLine *pLine = pBox->GetUpper();
387  const tools::Long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why?
388 
389  while ( pLine )
390  {
391  const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
392  for ( size_t i = 0; i < rBoxes.size(); ++i )
393  {
394  const SwTwips nWidth = rBoxes[i]->GetFrameFormat()->GetFrameSize().GetWidth();
395  nSum += nWidth;
396  const tools::Long nTmp = lcl_MulDiv64<tools::Long>(nSum, nAct, nWish);
397 
398  if (rBoxes[i] != pCur)
399  {
400  if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
401  nLeftMin = nTmp - nPos;
402  nPos = nTmp;
403  }
404  else
405  {
406  nSum -= nWidth;
407  if ( 0 == nRightMax )
408  nRightMax = nTmp - nPos;
409  break;
410  }
411  }
412  pCur = pLine->GetUpper();
413  pLine = pCur ? pCur->GetUpper() : nullptr;
414  }
415  }
416 
417  bool bInsert = !bRefreshHidden;
418  for ( size_t j = 0; bInsert && (j < rToFill.Count()); ++j )
419  {
420  tools::Long nCmp = rToFill[j];
421  if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
422  (nPos <= (nCmp + COLFUZZY)) )
423  {
424  bInsert = false; // Already has it.
425  }
426  else if ( nPos < nCmp )
427  {
428  bInsert = false;
429  rToFill.Insert( nPos, bHidden, j );
430  }
431  }
432  if ( bInsert )
433  rToFill.Insert( nPos, bHidden, rToFill.Count() );
434  else if ( bRefreshHidden )
435  ::lcl_RefreshHidden( rToFill, nPos );
436 
437  if ( !bHidden || bRefreshHidden )
438  return;
439 
440  // calculate minimum/maximum values for the existing entries:
441  nLeftMin = nPos - nLeftMin;
442  nRightMax = nPos + nRightMax;
443 
444  // check if nPos is entry:
445  bool bFoundPos = false;
446  bool bFoundMax = false;
447  for ( size_t j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
448  {
449  SwTabColsEntry& rEntry = rToFill.GetEntry( j );
450  tools::Long nCmp = rToFill[j];
451 
452  if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
453  (nPos <= (nCmp + COLFUZZY)) )
454  {
455  // check if nLeftMin is > old minimum for entry nPos:
456  const tools::Long nOldMin = rEntry.nMin;
457  if ( nLeftMin > nOldMin )
458  rEntry.nMin = nLeftMin;
459  // check if nRightMin is < old maximum for entry nPos:
460  const tools::Long nOldMax = rEntry.nMax;
461  if ( nRightMax < nOldMax )
462  rEntry.nMax = nRightMax;
463 
464  bFoundPos = true;
465  }
466  else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
467  (nRightMax <= (nCmp + COLFUZZY)) )
468  {
469  // check if nPos is > old minimum for entry nRightMax:
470  const tools::Long nOldMin = rEntry.nMin;
471  if ( nPos > nOldMin )
472  rEntry.nMin = nPos;
473 
474  bFoundMax = true;
475  }
476  }
477 }
478 
479 static void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
480  const SwFrameFormat *pTabFormat, bool bRefreshHidden )
481 {
482  if ( !pBox->GetTabLines().empty() )
483  {
484  const SwTableLines &rLines = pBox->GetTabLines();
485  for ( size_t i = 0; i < rLines.size(); ++i )
486  {
487  const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
488  for ( size_t j = 0; j < rBoxes.size(); ++j )
489  ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFormat, bRefreshHidden);
490  }
491  }
492  else
493  ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, false, bRefreshHidden );
494 }
495 
496 static void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
497  const SwFrameFormat *pTabFormat )
498 {
499  for ( size_t i = 0; i < pLine->GetTabBoxes().size(); ++i )
500  {
501  const SwTableBox *pBox = pLine->GetTabBoxes()[i];
502  if ( pBox->GetSttNd() )
503  ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, true, false );
504  else
505  for ( size_t j = 0; j < pBox->GetTabLines().size(); ++j )
506  ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFormat );
507  }
508 }
509 
510 void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
511  bool bRefreshHidden, bool bCurRowOnly ) const
512 {
513  // Optimization: if bHidden is set, we only update the Hidden Array.
514  if ( bRefreshHidden )
515  {
516  // remove corrections
517  for ( size_t i = 0; i < rToFill.Count(); ++i )
518  {
519  SwTabColsEntry& rEntry = rToFill.GetEntry( i );
520  rEntry.nPos -= rToFill.GetLeft();
521  rEntry.nMin -= rToFill.GetLeft();
522  rEntry.nMax -= rToFill.GetLeft();
523  }
524 
525  // All are hidden, so add the visible ones.
526  for ( size_t i = 0; i < rToFill.Count(); ++i )
527  rToFill.SetHidden( i, true );
528  }
529  else
530  {
531  rToFill.Remove( 0, rToFill.Count() );
532  }
533 
534  // Insertion cases:
535  // 1. All boxes which are inferior to Line which is superior to the Start,
536  // as well as their inferior boxes if present.
537  // 2. Starting from the Line, the superior box plus its neighbours; but no inferiors.
538  // 3. Apply 2. to the Line superior to the chain of boxes,
539  // until the Line's superior is not a box but the table.
540  // Only those boxes are inserted that don't contain further rows. The insertion
541  // function takes care to avoid duplicates. In order to achieve this, we work
542  // with some degree of fuzzyness (to avoid rounding errors).
543  // Only the left edge of the boxes are inserted.
544  // Finally, the first entry is removed again, because it's already
545  // covered by the border.
546  // 4. Scan the table again and insert _all_ boxes, this time as hidden.
547 
548  const SwFrameFormat *pTabFormat = GetFrameFormat();
549 
550  // 1.
551  const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
552 
553  for ( size_t i = 0; i < rBoxes.size(); ++i )
554  ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFormat, bRefreshHidden );
555 
556  // 2. and 3.
557  const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
558  pStart->GetUpper()->GetUpper()->GetUpper() : nullptr;
559  while ( pLine )
560  {
561  const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
562  for ( size_t k = 0; k < rBoxes2.size(); ++k )
563  ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
564  pTabFormat, false, bRefreshHidden );
565  pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : nullptr;
566  }
567 
568  if ( !bRefreshHidden )
569  {
570  // 4.
571  if ( !bCurRowOnly )
572  {
573  for ( size_t i = 0; i < m_aLines.size(); ++i )
574  ::lcl_ProcessLineGet( m_aLines[i], rToFill, pTabFormat );
575  }
576 
577  rToFill.Remove( 0 );
578  }
579 
580  // Now the coordinates are relative to the left table border - i.e.
581  // relative to SwTabCols.nLeft. However, they are expected
582  // relative to the left document border, i.e. SwTabCols.nLeftMin.
583  // So all values need to be extended by nLeft.
584  for ( size_t i = 0; i < rToFill.Count(); ++i )
585  {
586  SwTabColsEntry& rEntry = rToFill.GetEntry( i );
587  rEntry.nPos += rToFill.GetLeft();
588  rEntry.nMin += rToFill.GetLeft();
589  rEntry.nMax += rToFill.GetLeft();
590  }
591 }
592 
593 // Structure for parameter passing
594 struct Parm
595 {
596  const SwTabCols &rNew;
597  const SwTabCols &rOld;
599  nOldWish;
600  std::deque<SwTableBox*> aBoxArr;
602 
603  Parm( const SwTabCols &rN, const SwTabCols &rO )
604  : rNew( rN ), rOld( rO ), nNewWish(0), nOldWish(0)
605  {}
606 };
607 
608 static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
609 
610 static void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
611 {
612  SwTableBoxes &rBoxes = pLine->GetTabBoxes();
613  for ( size_t i = rBoxes.size(); i > 0; )
614  {
615  --i;
616  ::lcl_ProcessBoxSet( rBoxes[i], rParm );
617  }
618 }
619 
620 static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
621 {
622  if ( !pBox->GetTabLines().empty() )
623  {
624  SwTableLines &rLines = pBox->GetTabLines();
625  for ( size_t i = rLines.size(); i > 0; )
626  {
627  --i;
628  lcl_ProcessLine( rLines[i], rParm );
629  }
630  }
631  else
632  {
633  // Search the old TabCols for the current position (calculate from
634  // left and right edge). Adjust the box if the values differ from
635  // the new TabCols. If the adjusted edge has no neighbour we also
636  // adjust all superior boxes.
637 
638  const tools::Long nOldAct = rParm.rOld.GetRight() -
639  rParm.rOld.GetLeft(); // +1 why?
640 
641  // The value for the left edge of the box is calculated from the
642  // widths of the previous boxes plus the left edge.
643  tools::Long nLeft = rParm.rOld.GetLeft();
644  const SwTableBox *pCur = pBox;
645  const SwTableLine *pLine = pBox->GetUpper();
646 
647  while ( pLine )
648  {
649  const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
650  for ( size_t i = 0; (i < rBoxes.size()) && (rBoxes[i] != pCur); ++i)
651  {
652  nLeft += lcl_MulDiv64<tools::Long>(
653  rBoxes[i]->GetFrameFormat()->GetFrameSize().GetWidth(),
654  nOldAct, rParm.nOldWish);
655  }
656  pCur = pLine->GetUpper();
657  pLine = pCur ? pCur->GetUpper() : nullptr;
658  }
659  tools::Long nLeftDiff = 0;
660  tools::Long nRightDiff = 0;
661  if ( nLeft != rParm.rOld.GetLeft() ) // There are still boxes before this.
662  {
663  // Right edge is left edge plus width.
664  const tools::Long nWidth = lcl_MulDiv64<tools::Long>(
665  pBox->GetFrameFormat()->GetFrameSize().GetWidth(),
666  nOldAct, rParm.nOldWish);
667  const tools::Long nRight = nLeft + nWidth;
668  size_t nLeftPos = 0;
669  size_t nRightPos = 0;
670  bool bFoundLeftPos = false;
671  bool bFoundRightPos = false;
672  for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
673  {
674  if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
675  nLeft <= (rParm.rOld[i] + COLFUZZY) )
676  {
677  nLeftPos = i;
678  bFoundLeftPos = true;
679  }
680  else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
681  nRight <= (rParm.rOld[i] + COLFUZZY) )
682  {
683  nRightPos = i;
684  bFoundRightPos = true;
685  }
686  }
687  nLeftDiff = bFoundLeftPos ?
688  rParm.rOld[nLeftPos] - rParm.rNew[nLeftPos] : 0;
689  nRightDiff= bFoundRightPos ?
690  rParm.rNew[nRightPos] - rParm.rOld[nRightPos] : 0;
691  }
692  else // The first box.
693  {
694  nLeftDiff = rParm.rOld.GetLeft() - rParm.rNew.GetLeft();
695  if ( rParm.rOld.Count() )
696  {
697  // Calculate the difference to the edge touching the first box.
698  const tools::Long nWidth = lcl_MulDiv64<tools::Long>(
699  pBox->GetFrameFormat()->GetFrameSize().GetWidth(),
700  nOldAct, rParm.nOldWish);
701  const tools::Long nTmp = nWidth + rParm.rOld.GetLeft();
702  for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
703  {
704  if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
705  nTmp <= (rParm.rOld[i] + COLFUZZY) )
706  {
707  nRightDiff = rParm.rNew[i] - rParm.rOld[i];
708  break;
709  }
710  }
711  }
712  }
713 
714  if( pBox->getRowSpan() == 1 )
715  {
716  const sal_uInt16 nPos = pBox->GetUpper()->GetBoxPos( pBox );
717  SwTableBoxes& rTableBoxes = pBox->GetUpper()->GetTabBoxes();
718  if( nPos && rTableBoxes[ nPos - 1 ]->getRowSpan() != 1 )
719  nLeftDiff = 0;
720  if( nPos + 1 < static_cast<sal_uInt16>(rTableBoxes.size()) &&
721  rTableBoxes[ nPos + 1 ]->getRowSpan() != 1 )
722  nRightDiff = 0;
723  }
724  else
725  nLeftDiff = nRightDiff = 0;
726 
727  if ( nLeftDiff || nRightDiff )
728  {
729  // The difference is the actual difference amount. For stretched
730  // tables, it does not make sense to adjust the attributes of the
731  // boxes by this amount. The difference amount needs to be converted
732  // accordingly.
733  tools::Long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
734  nLeftDiff *= rParm.nNewWish;
735  nLeftDiff /= nTmp;
736  nRightDiff *= rParm.nNewWish;
737  nRightDiff /= nTmp;
738  tools::Long nDiff = nLeftDiff + nRightDiff;
739 
740  // Adjust the box and all superiors by the difference amount.
741  while ( pBox )
742  {
743  SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
744  aFormatFrameSize.SetWidth( aFormatFrameSize.GetWidth() + nDiff );
745  if ( aFormatFrameSize.GetWidth() < 0 )
746  aFormatFrameSize.SetWidth( -aFormatFrameSize.GetWidth() );
747  rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
748 
749  // The outer cells of the last row are responsible to adjust a surrounding cell.
750  // Last line check:
751  if ( pBox->GetUpper()->GetUpper() &&
752  pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines().back())
753  {
754  pBox = nullptr;
755  }
756  else
757  {
758  // Middle cell check:
759  if ( pBox != pBox->GetUpper()->GetTabBoxes().front() )
760  nDiff = nRightDiff;
761 
762  if ( pBox != pBox->GetUpper()->GetTabBoxes().back() )
763  nDiff -= nRightDiff;
764 
765  pBox = nDiff ? pBox->GetUpper()->GetUpper() : nullptr;
766  }
767  }
768  }
769  }
770 }
771 
772 static void lcl_ProcessBoxPtr( SwTableBox *pBox, std::deque<SwTableBox*> &rBoxArr,
773  bool bBefore )
774 {
775  if ( !pBox->GetTabLines().empty() )
776  {
777  const SwTableLines &rLines = pBox->GetTabLines();
778  for ( size_t i = 0; i < rLines.size(); ++i )
779  {
780  const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
781  for ( size_t j = 0; j < rBoxes.size(); ++j )
782  ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
783  }
784  }
785  else if ( bBefore )
786  rBoxArr.push_front( pBox );
787  else
788  rBoxArr.push_back( pBox );
789 }
790 
791 static void lcl_AdjustBox( SwTableBox *pBox, const tools::Long nDiff, Parm &rParm );
792 
793 static void lcl_AdjustLines( SwTableLines &rLines, const tools::Long nDiff, Parm &rParm )
794 {
795  for ( size_t i = 0; i < rLines.size(); ++i )
796  {
797  SwTableBox *pBox = rLines[i]->GetTabBoxes()
798  [rLines[i]->GetTabBoxes().size()-1];
799  lcl_AdjustBox( pBox, nDiff, rParm );
800  }
801 }
802 
803 static void lcl_AdjustBox( SwTableBox *pBox, const tools::Long nDiff, Parm &rParm )
804 {
805  if ( !pBox->GetTabLines().empty() )
806  ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
807 
808  // Adjust the size of the box.
809  SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
810  aFormatFrameSize.SetWidth( aFormatFrameSize.GetWidth() + nDiff );
811 
812  rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
813 }
814 
815 void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
816  const SwTableBox *pStart, bool bCurRowOnly )
817 {
818  CHECK_TABLE( *this )
819 
820  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // delete HTML-Layout
821 
822  // FME: Made rOld const. The caller is responsible for passing correct
823  // values of rOld. Therefore we do not have to call GetTabCols anymore:
824  //GetTabCols( rOld, pStart );
825 
826  Parm aParm( rNew, rOld );
827 
828  OSL_ENSURE( rOld.Count() == rNew.Count(), "Number of columns changed.");
829 
830  // Convert the edges. We need to adjust the size of the table and some boxes.
831  // For the size adjustment, we must not make use of the Modify, since that'd
832  // adjust all boxes, which we really don't want.
833  SwFrameFormat *pFormat = GetFrameFormat();
834  aParm.nOldWish = aParm.nNewWish = pFormat->GetFrameSize().GetWidth();
835  if ( (rOld.GetLeft() != rNew.GetLeft()) ||
836  (rOld.GetRight()!= rNew.GetRight()) )
837  {
838  LockModify();
839  {
840  SvxLRSpaceItem aLR( pFormat->GetLRSpace() );
841  SvxShadowItem aSh( pFormat->GetShadow() );
842 
843  SwTwips nShRight = aSh.CalcShadowSpace( SvxShadowItemSide::RIGHT );
844  SwTwips nShLeft = aSh.CalcShadowSpace( SvxShadowItemSide::LEFT );
845 
846  aLR.SetLeft ( rNew.GetLeft() - nShLeft );
847  aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
848  pFormat->SetFormatAttr( aLR );
849 
850  // The alignment of the table needs to be adjusted accordingly.
851  // This is done by preserving the exact positions that have been
852  // set by the user.
853  SwFormatHoriOrient aOri( pFormat->GetHoriOrient() );
854  if( text::HoriOrientation::NONE != aOri.GetHoriOrient() &&
855  text::HoriOrientation::CENTER != aOri.GetHoriOrient() )
856  {
857  const bool bLeftDist = rNew.GetLeft() != nShLeft;
858  const bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
859  if(!bLeftDist && !bRightDist)
860  aOri.SetHoriOrient( text::HoriOrientation::FULL );
861  else if(!bRightDist && rNew.GetLeft() > nShLeft )
862  aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
863  else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
864  aOri.SetHoriOrient( text::HoriOrientation::LEFT );
865  else
866  aOri.SetHoriOrient( text::HoriOrientation::LEFT_AND_WIDTH );
867  }
868  pFormat->SetFormatAttr( aOri );
869  }
870  const tools::Long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
871  tools::Long nTabDiff = 0;
872 
873  if ( rOld.GetLeft() != rNew.GetLeft() )
874  {
875  nTabDiff = rOld.GetLeft() - rNew.GetLeft();
876  nTabDiff *= aParm.nOldWish;
877  nTabDiff /= nAct;
878  }
879  if ( rOld.GetRight() != rNew.GetRight() )
880  {
881  tools::Long nDiff = rNew.GetRight() - rOld.GetRight();
882  nDiff *= aParm.nOldWish;
883  nDiff /= nAct;
884  nTabDiff += nDiff;
885  if( !IsNewModel() )
886  ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
887  }
888 
889  // Adjust the size of the table, watch out for stretched tables.
890  if ( nTabDiff )
891  {
892  aParm.nNewWish += nTabDiff;
893  if ( aParm.nNewWish < 0 )
894  aParm.nNewWish = USHRT_MAX; // Oops! Have to roll back.
895  SwFormatFrameSize aSz( pFormat->GetFrameSize() );
896  if ( aSz.GetWidth() != aParm.nNewWish )
897  {
898  aSz.SetWidth( aParm.nNewWish );
899  aSz.SetWidthPercent( 0 );
900  pFormat->SetFormatAttr( aSz );
901  }
902  }
903  UnlockModify();
904  }
905 
906  if( IsNewModel() )
907  NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
908  else
909  {
910  if ( bCurRowOnly )
911  {
912  // To adjust the current row, we need to process all its boxes,
913  // similar to the filling of the TabCols (see GetTabCols()).
914  // Unfortunately we again have to take care to adjust the boxes
915  // from back to front, respectively from outer to inner.
916  // The best way to achieve this is probably to track the boxes
917  // in a PtrArray.
918  const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
919  for ( size_t i = 0; i < rBoxes.size(); ++i )
920  ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, false );
921 
922  const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
923  pStart->GetUpper()->GetUpper()->GetUpper() : nullptr;
924  const SwTableBox *pExcl = pStart->GetUpper()->GetUpper();
925  while ( pLine )
926  {
927  const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
928  bool bBefore = true;
929  for ( size_t i = 0; i < rBoxes2.size(); ++i )
930  {
931  if ( rBoxes2[i] != pExcl )
932  ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
933  else
934  bBefore = false;
935  }
936  pExcl = pLine->GetUpper();
937  pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : nullptr;
938  }
939  // After we've inserted a bunch of boxes (hopefully all and in
940  // correct order), we just need to process them in reverse order.
941  for ( int j = aParm.aBoxArr.size()-1; j >= 0; --j )
942  {
943  SwTableBox *pBox = aParm.aBoxArr[j];
944  ::lcl_ProcessBoxSet( pBox, aParm );
945  }
946  }
947  else
948  {
949  // Adjusting the entire table is 'easy'. All boxes without lines are
950  // adjusted, as are their superiors. Of course we need to process
951  // in reverse order to prevent fooling ourselves!
952  SwTableLines &rLines = GetTabLines();
953  for ( size_t i = rLines.size(); i > 0; )
954  {
955  --i;
956  ::lcl_ProcessLine( rLines[i], aParm );
957  }
958  }
959  }
960 
961 #ifdef DBG_UTIL
962  {
963  // do some checking for correct table widths
965  for (size_t n = 0; n < m_aLines.size(); ++n)
966  {
967  CheckBoxWidth( *m_aLines[ n ], nSize );
968  }
969  }
970 #endif
971 }
972 
973 typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
974 typedef std::list< ColChange > ChangeList;
975 
976 static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
977  Parm& rParm, sal_uInt16 nColFuzzy )
978 {
979  ChangeList::iterator pCurr = rOldNew.begin();
980  if( pCurr == rOldNew.end() )
981  return;
982  const size_t nCount = pLine->GetTabBoxes().size();
983  SwTwips nBorder = 0;
984  SwTwips nRest = 0;
985  for( size_t i = 0; i < nCount; ++i )
986  {
987  SwTableBox* pBox = pLine->GetTabBoxes()[i];
988  SwTwips nWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
989  SwTwips nNewWidth = nWidth - nRest;
990  nRest = 0;
991  nBorder += nWidth;
992  if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
993  {
994  nBorder -= nColFuzzy;
995  while( pCurr != rOldNew.end() && nBorder > pCurr->first )
996  ++pCurr;
997  if( pCurr != rOldNew.end() )
998  {
999  nBorder += nColFuzzy;
1000  if( nBorder + nColFuzzy >= pCurr->first )
1001  {
1002  if( pCurr->second == pCurr->first )
1003  nRest = 0;
1004  else
1005  nRest = pCurr->second - nBorder;
1006  nNewWidth += nRest;
1007  ++pCurr;
1008  }
1009  }
1010  }
1011  if( nNewWidth != nWidth )
1012  {
1013  if( nNewWidth < 0 )
1014  {
1015  nRest += 1 - nNewWidth;
1016  nNewWidth = 1;
1017  }
1018  SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
1019  aFormatFrameSize.SetWidth( nNewWidth );
1020  rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
1021  }
1022  }
1023 }
1024 
1025 static void lcl_CalcNewWidths( std::vector<sal_uInt16> &rSpanPos, ChangeList& rChanges,
1026  SwTableLine* pLine, tools::Long nWish, tools::Long nWidth, bool bTop )
1027 {
1028  if( rChanges.empty() )
1029  {
1030  rSpanPos.clear();
1031  return;
1032  }
1033  if( rSpanPos.empty() )
1034  {
1035  rChanges.clear();
1036  return;
1037  }
1038  std::vector<sal_uInt16> aNewSpanPos;
1039  ChangeList aNewChanges;
1040  ChangeList::iterator pCurr = rChanges.begin();
1041  aNewChanges.push_back( *pCurr ); // Nullposition
1042  std::vector<sal_uInt16>::iterator pSpan = rSpanPos.begin();
1043  sal_uInt16 nCurr = 0;
1044  SwTwips nOrgSum = 0;
1045  bool bRowSpan = false;
1046  sal_uInt16 nRowSpanCount = 0;
1047  const size_t nCount = pLine->GetTabBoxes().size();
1048  for( size_t nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1049  {
1050  SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1051  SwTwips nCurrWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
1052  const sal_Int32 nRowSpan = pBox->getRowSpan();
1053  const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
1054  ( nRowSpan > 1 || nRowSpan < -1 );
1055  if( bRowSpan || bCurrRowSpan )
1056  aNewSpanPos.push_back( nRowSpanCount );
1057  bRowSpan = bCurrRowSpan;
1058  nOrgSum += nCurrWidth;
1059  const sal_uInt16 nPos = lcl_MulDiv64<sal_uInt16>(
1060  lcl_MulDiv64<sal_uInt64>(nOrgSum, nWidth, nWish),
1061  nWish, nWidth);
1062  while( pCurr != rChanges.end() && pCurr->first < nPos )
1063  {
1064  ++nCurr;
1065  ++pCurr;
1066  }
1067  bool bNew = true;
1068  if( pCurr != rChanges.end() && pCurr->first <= nPos &&
1069  pCurr->first != pCurr->second )
1070  {
1071  pSpan = std::find_if(pSpan, rSpanPos.end(),
1072  [nCurr](const sal_uInt16 nSpan) { return nSpan >= nCurr; });
1073  if( pSpan != rSpanPos.end() && *pSpan == nCurr )
1074  {
1075  aNewChanges.push_back( *pCurr );
1076  ++nRowSpanCount;
1077  bNew = false;
1078  }
1079  }
1080  if( bNew )
1081  {
1082  ColChange aTmp( nPos, nPos );
1083  aNewChanges.push_back( aTmp );
1084  ++nRowSpanCount;
1085  }
1086  }
1087 
1088  pCurr = aNewChanges.begin();
1089  ChangeList::iterator pLast = pCurr;
1090  ChangeList::iterator pLeftMove = pCurr;
1091  while( pCurr != aNewChanges.end() )
1092  {
1093  if( pLeftMove == pCurr )
1094  {
1095  while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
1096  ;
1097  }
1098  if( pCurr->second == pCurr->first )
1099  {
1100  if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
1101  {
1102  if( pLeftMove->first == pLast->first )
1103  pCurr->second = pLeftMove->second;
1104  else
1105  {
1106  pCurr->second = lcl_MulDiv64<sal_uInt16>(
1107  pCurr->first - pLast->first,
1108  pLeftMove->second - pLast->second,
1109  pLeftMove->first - pLast->first) + pLast->second;
1110  }
1111  }
1112  pLast = pCurr;
1113  ++pCurr;
1114  }
1115  else if( pCurr->second > pCurr->first )
1116  {
1117  pLast = pCurr;
1118  ++pCurr;
1119  ChangeList::iterator pNext = pCurr;
1120  while( pNext != pLeftMove && pNext->second == pNext->first &&
1121  pNext->second < pLast->second )
1122  ++pNext;
1123  while( pCurr != pNext )
1124  {
1125  if( pNext == aNewChanges.end() || pNext->first == pLast->first )
1126  pCurr->second = pLast->second;
1127  else
1128  {
1129  pCurr->second = lcl_MulDiv64<sal_uInt16>(
1130  pCurr->first - pLast->first,
1131  pNext->second - pLast->second,
1132  pNext->first - pLast->first) + pLast->second;
1133  }
1134  ++pCurr;
1135  }
1136  pLast = pCurr;
1137  }
1138  else
1139  {
1140  pLast = pCurr;
1141  ++pCurr;
1142  }
1143  }
1144 
1145  rChanges.swap(aNewChanges);
1146  rSpanPos.swap(aNewSpanPos);
1147 }
1148 
1149 void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
1150  const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly )
1151 {
1152 #if OSL_DEBUG_LEVEL > 1
1153  static int nCallCount = 0;
1154  ++nCallCount;
1155 #endif
1156  // First step: evaluate which lines have been moved/which widths changed
1157  ChangeList aOldNew;
1158  const tools::Long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1159  const tools::Long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1160  if( nNewWidth < 1 || nOldWidth < 1 )
1161  return;
1162  for( size_t i = 0; i <= rOld.Count(); ++i )
1163  {
1164  tools::Long nNewPos;
1165  tools::Long nOldPos;
1166  if( i == rOld.Count() )
1167  {
1168  nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1169  nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1170  }
1171  else
1172  {
1173  nOldPos = rOld[i] - rParm.rOld.GetLeft();
1174  nNewPos = rNew[i] - rParm.rNew.GetLeft();
1175  }
1176  nNewPos = lcl_MulDiv64<tools::Long>(nNewPos, rParm.nNewWish, nNewWidth);
1177  nOldPos = lcl_MulDiv64<tools::Long>(nOldPos, rParm.nOldWish, nOldWidth);
1178  if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
1179  {
1180  ColChange aChg( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
1181  aOldNew.push_back( aChg );
1182  }
1183  }
1184  // Finished first step
1185  int nCount = aOldNew.size();
1186  if( !nCount )
1187  return; // no change, nothing to do
1188  SwTableLines &rLines = GetTabLines();
1189  if( bCurRowOnly )
1190  {
1191  const SwTableLine* pCurrLine = pStart->GetUpper();
1192  sal_uInt16 nCurr = rLines.GetPos( pCurrLine );
1193  if( nCurr >= USHRT_MAX )
1194  return;
1195 
1196  ColChange aChg( 0, 0 );
1197  aOldNew.push_front( aChg );
1198  std::vector<sal_uInt16> aRowSpanPos;
1199  if( nCurr )
1200  {
1201  ChangeList aCopy;
1202  sal_uInt16 nPos = 0;
1203  for( const auto& rCop : aOldNew )
1204  {
1205  aCopy.push_back( rCop );
1206  aRowSpanPos.push_back( nPos++ );
1207  }
1208  lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1209  rParm.nOldWish, nOldWidth, true );
1210  bool bGoOn = !aRowSpanPos.empty();
1211  sal_uInt16 j = nCurr;
1212  while( bGoOn )
1213  {
1214  lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
1215  rParm.nOldWish, nOldWidth, true );
1216  lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1217  bGoOn = !aRowSpanPos.empty() && j > 0;
1218  }
1219  aRowSpanPos.clear();
1220  }
1221  if( nCurr+1 < static_cast<sal_uInt16>(rLines.size()) )
1222  {
1223  ChangeList aCopy;
1224  sal_uInt16 nPos = 0;
1225  for( const auto& rCop : aOldNew )
1226  {
1227  aCopy.push_back( rCop );
1228  aRowSpanPos.push_back( nPos++ );
1229  }
1230  lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1231  rParm.nOldWish, nOldWidth, false );
1232  bool bGoOn = !aRowSpanPos.empty();
1233  sal_uInt16 j = nCurr;
1234  while( bGoOn )
1235  {
1236  lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
1237  rParm.nOldWish, nOldWidth, false );
1238  lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1239  bGoOn = !aRowSpanPos.empty() && j+1 < static_cast<sal_uInt16>(rLines.size());
1240  }
1241  }
1242  ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, COLFUZZY );
1243  }
1244  else
1245  {
1246  for( size_t i = 0; i < rLines.size(); ++i )
1247  ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
1248  }
1249  CHECK_TABLE( *this )
1250 }
1251 
1252 // return the pointer of the box specified.
1253 static bool lcl_IsValidRowName( const OUString& rStr )
1254 {
1255  bool bIsValid = true;
1256  sal_Int32 nLen = rStr.getLength();
1257  for( sal_Int32 i = 0; i < nLen && bIsValid; ++i )
1258  {
1259  const sal_Unicode cChar = rStr[i];
1260  if (cChar < '0' || cChar > '9')
1261  bIsValid = false;
1262  }
1263  return bIsValid;
1264 }
1265 
1266 // #i80314#
1267 // add 3rd parameter and its handling
1268 sal_uInt16 SwTable::GetBoxNum( OUString& rStr, bool bFirstPart,
1269  const bool bPerformValidCheck )
1270 {
1271  sal_uInt16 nRet = 0;
1272  if( bFirstPart ) // true == column; false == row
1273  {
1274  sal_Int32 nPos = 0;
1275  // the first one uses letters for addressing!
1276  bool bFirst = true;
1277  sal_uInt32 num = 0;
1278  bool overflow = false;
1279  while (nPos<rStr.getLength())
1280  {
1281  sal_Unicode cChar = rStr[nPos];
1282  if ((cChar<'A' || cChar>'Z') && (cChar<'a' || cChar>'z'))
1283  break;
1284  cChar -= 'A';
1285  if( cChar >= 26 )
1286  cChar -= 'a' - '[';
1287  if( bFirst )
1288  bFirst = false;
1289  else
1290  ++num;
1291  num = num * 52 + cChar;
1292  if (num > SAL_MAX_UINT16) {
1293  overflow = true;
1294  }
1295  ++nPos;
1296  }
1297  nRet = overflow ? SAL_MAX_UINT16 : num;
1298  rStr = rStr.copy( nPos ); // Remove char from String
1299  }
1300  else
1301  {
1302  const sal_Int32 nPos = rStr.indexOf( "." );
1303  if ( nPos<0 )
1304  {
1305  nRet = 0;
1306  if ( !bPerformValidCheck || lcl_IsValidRowName( rStr ) )
1307  {
1308  nRet = static_cast<sal_uInt16>(rStr.toInt32());
1309  }
1310  rStr.clear();
1311  }
1312  else
1313  {
1314  nRet = 0;
1315  const OUString aText( rStr.copy( 0, nPos ) );
1316  if ( !bPerformValidCheck || lcl_IsValidRowName( aText ) )
1317  {
1318  nRet = static_cast<sal_uInt16>(aText.toInt32());
1319  }
1320  rStr = rStr.copy( nPos+1 );
1321  }
1322  }
1323  return nRet;
1324 }
1325 
1326 // #i80314#
1327 // add 2nd parameter and its handling
1328 const SwTableBox* SwTable::GetTableBox( const OUString& rName,
1329  const bool bPerformValidCheck ) const
1330 {
1331  const SwTableBox* pBox = nullptr;
1332  const SwTableLine* pLine;
1333  const SwTableLines* pLines;
1334 
1335  sal_uInt16 nLine, nBox;
1336  OUString aNm( rName );
1337  while( !aNm.isEmpty() )
1338  {
1339  nBox = SwTable::GetBoxNum( aNm, nullptr == pBox, bPerformValidCheck );
1340  // first box ?
1341  if( !pBox )
1342  pLines = &GetTabLines();
1343  else
1344  {
1345  pLines = &pBox->GetTabLines();
1346  if( nBox )
1347  --nBox;
1348  }
1349 
1350  nLine = SwTable::GetBoxNum( aNm, false, bPerformValidCheck );
1351 
1352  // determine line
1353  if( !nLine || nLine > pLines->size() )
1354  return nullptr;
1355  pLine = (*pLines)[ nLine-1 ];
1356 
1357  // determine box
1358  const SwTableBoxes* pBoxes = &pLine->GetTabBoxes();
1359  if( nBox >= pBoxes->size() )
1360  return nullptr;
1361  pBox = (*pBoxes)[ nBox ];
1362  }
1363 
1364  // check if the box found has any contents
1365  if( pBox && !pBox->GetSttNd() )
1366  {
1367  OSL_FAIL( "Box without content, looking for the next one!" );
1368  // "drop this" until the first box
1369  while( !pBox->GetTabLines().empty() )
1370  pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
1371  }
1372  return pBox;
1373 }
1374 
1376 {
1377  // For optimizations, don't always process the entire SortArray.
1378  // Converting text to table, tries certain conditions
1379  // to ask for a table box of a table that is not yet having a format
1380  if(!GetFrameFormat())
1381  return nullptr;
1382  SwTableBox* pRet = nullptr;
1383  SwNodes& rNds = GetFrameFormat()->GetDoc()->GetNodes();
1384  sal_uLong nIndex = nSttIdx + 1;
1385  SwContentNode* pCNd = nullptr;
1386  SwTableNode* pTableNd = nullptr;
1387 
1388  while ( nIndex < rNds.Count() )
1389  {
1390  pTableNd = rNds[ nIndex ]->GetTableNode();
1391  if ( pTableNd )
1392  break;
1393 
1394  pCNd = rNds[ nIndex ]->GetContentNode();
1395  if ( pCNd )
1396  break;
1397 
1398  ++nIndex;
1399  }
1400 
1401  if ( pCNd || pTableNd )
1402  {
1403  sw::BroadcastingModify* pModify = pCNd;
1404  // #144862# Better handling of table in table
1405  if ( pTableNd && pTableNd->GetTable().GetFrameFormat() )
1406  pModify = pTableNd->GetTable().GetFrameFormat();
1407 
1408  SwFrame* pFrame = pModify ? SwIterator<SwFrame,sw::BroadcastingModify>(*pModify).First() : nullptr;
1409  while ( pFrame && !pFrame->IsCellFrame() )
1410  pFrame = pFrame->GetUpper();
1411  if ( pFrame )
1412  pRet = const_cast<SwTableBox*>(static_cast<SwCellFrame*>(pFrame)->GetTabBox());
1413  }
1414 
1415  // In case the layout doesn't exist yet or anything else goes wrong.
1416  if ( !pRet )
1417  {
1418  for (size_t n = m_TabSortContentBoxes.size(); n; )
1419  {
1420  if (m_TabSortContentBoxes[ --n ]->GetSttIdx() == nSttIdx)
1421  {
1422  return m_TabSortContentBoxes[ n ];
1423  }
1424  }
1425  }
1426  return pRet;
1427 }
1428 
1430 {
1431  // Returns true for complex tables, i.e. tables that contain nestings,
1432  // like containing boxes not part of the first line, e.g. results of
1433  // splits/merges which lead to more complex structures.
1434  for (size_t n = 0; n < m_TabSortContentBoxes.size(); ++n)
1435  {
1436  if (m_TabSortContentBoxes[ n ]->GetUpper()->GetUpper())
1437  {
1438  return true;
1439  }
1440  }
1441  return false;
1442 }
1443 
1444 SwTableLine::SwTableLine( SwTableLineFormat *pFormat, sal_uInt16 nBoxes,
1445  SwTableBox *pUp )
1446  : SwClient( pFormat ),
1447  m_aBoxes(),
1448  m_pUpper( pUp )
1449 {
1450  m_aBoxes.reserve( nBoxes );
1451 }
1452 
1454 {
1455  for (size_t i = 0; i < m_aBoxes.size(); ++i)
1456  {
1457  delete m_aBoxes[i];
1458  }
1459  // the TabelleLine can be deleted if it's the last client of the FrameFormat
1461  pMod->Remove( this ); // remove,
1462  if( !pMod->HasWriterListeners() )
1463  delete pMod; // and delete
1464 }
1465 
1467 {
1468  // This method makes sure that this object is an exclusive SwTableLine client
1469  // of an SwTableLineFormat object
1470  // If other SwTableLine objects currently listen to the same SwTableLineFormat as
1471  // this one, something needs to be done
1472  SwTableLineFormat *pRet = static_cast<SwTableLineFormat*>(GetFrameFormat());
1473  SwIterator<SwTableLine,SwFormat> aIter( *pRet );
1474  for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1475  {
1476  if ( pLast != this )
1477  {
1478  // found another SwTableLine that is a client of the current Format
1479  // create a new Format as a copy and use it for this object
1480  SwTableLineFormat *pNewFormat = pRet->GetDoc()->MakeTableLineFormat();
1481  *pNewFormat = *pRet;
1482 
1483  // register SwRowFrames that know me as clients at the new Format
1484  SwIterator<SwRowFrame,SwFormat> aFrameIter( *pRet );
1485  for( SwRowFrame* pFrame = aFrameIter.First(); pFrame; pFrame = aFrameIter.Next() )
1486  if( pFrame->GetTabLine() == this )
1487  pFrame->RegisterToFormat( *pNewFormat );
1488 
1489  // register myself
1490  pNewFormat->Add( this );
1491  pRet = pNewFormat;
1492  break;
1493  }
1494  }
1495 
1496  return pRet;
1497 }
1498 
1500 {
1501  SwFrameFormat *pOld = GetFrameFormat();
1502  SwIterator<SwRowFrame,SwFormat> aIter( *pOld );
1503 
1504  // First, re-register the Frames.
1505  for( SwRowFrame* pRow = aIter.First(); pRow; pRow = aIter.Next() )
1506  {
1507  if( pRow->GetTabLine() == this )
1508  {
1509  pRow->RegisterToFormat( *pNewFormat );
1510 
1511  pRow->InvalidateSize();
1512  pRow->InvalidatePrt_();
1513  pRow->SetCompletePaint();
1514  pRow->ReinitializeFrameSizeAttrFlags();
1515 
1516  // #i35063#
1517  // consider 'split row allowed' attribute
1518  SwTabFrame* pTab = pRow->FindTabFrame();
1519  bool bInFollowFlowRow = false;
1520  const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
1521  pRow == pTab->GetFirstNonHeadlineRow();
1522  if ( bInFirstNonHeadlineRow ||
1523  !pRow->GetNext() ||
1524  ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) ||
1525  nullptr != pRow->IsInSplitTableRow() )
1526  {
1527  if ( bInFirstNonHeadlineRow || bInFollowFlowRow )
1528  pTab = pTab->FindMaster();
1529 
1530  pTab->SetRemoveFollowFlowLinePending( true );
1531  pTab->InvalidatePos();
1532  }
1533  }
1534  }
1535 
1536  // Now, re-register self.
1537  pNewFormat->Add( this );
1538 
1539  if ( !pOld->HasWriterListeners() )
1540  delete pOld;
1541 }
1542 
1543 SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
1544 {
1545  SwTwips nRet = 0;
1546  bLayoutAvailable = false;
1548  // A row could appear several times in headers/footers so only one chain of master/follow tables
1549  // will be accepted...
1550  const SwTabFrame* pChain = nullptr; // My chain
1551  for( SwRowFrame* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1552  {
1553  if( pLast->GetTabLine() == this )
1554  {
1555  const SwTabFrame* pTab = pLast->FindTabFrame();
1556  bLayoutAvailable = ( pTab && pTab->IsVertical() ) ?
1557  ( 0 < pTab->getFrameArea().Height() ) :
1558  ( 0 < pTab->getFrameArea().Width() );
1559 
1560  // The first one defines the chain, if a chain is defined, only members of the chain
1561  // will be added.
1562  if (pTab && (!pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow(pChain)))
1563  {
1564  pChain = pTab; // defines my chain (even it is already)
1565  if( pTab->IsVertical() )
1566  nRet += pLast->getFrameArea().Width();
1567  else
1568  nRet += pLast->getFrameArea().Height();
1569  // Optimization, if there are no master/follows in my chain, nothing more to add
1570  if( !pTab->HasFollow() && !pTab->IsFollow() )
1571  break;
1572  // This is not an optimization, this is necessary to avoid double additions of
1573  // repeating rows
1574  if( pTab->IsInHeadline(*pLast) )
1575  break;
1576  }
1577  }
1578  }
1579  return nRet;
1580 }
1581 
1582 SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, sal_uInt16 nLines, SwTableLine *pUp )
1583  : SwClient(nullptr)
1584  , m_aLines()
1585  , m_pStartNode(nullptr)
1586  , m_pUpper(pUp)
1587  , mnRowSpan(1)
1588  , mbDummyFlag(false)
1589  , mbDirectFormatting(false)
1590 {
1591  m_aLines.reserve( nLines );
1592  CheckBoxFormat( pFormat )->Add( this );
1593 }
1594 
1596  SwTableLine *pUp )
1597  : SwClient(nullptr)
1598  , m_aLines()
1599  , m_pUpper(pUp)
1600  , mnRowSpan(1)
1601  , mbDummyFlag(false)
1602  , mbDirectFormatting(false)
1603 {
1604  CheckBoxFormat( pFormat )->Add( this );
1605 
1606  m_pStartNode = rIdx.GetNode().GetStartNode();
1607 
1608  // insert into the table
1609  const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1610  assert(pTableNd && "In which table is that box?");
1611  SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1612  GetTabSortBoxes());
1613  SwTableBox* p = this; // error: &this
1614  rSrtArr.insert( p ); // insert
1615 }
1616 
1618  : SwClient(nullptr)
1619  , m_aLines()
1620  , m_pStartNode(&rSttNd)
1621  , m_pUpper(pUp)
1622  , mnRowSpan(1)
1623  , mbDummyFlag(false)
1624  , mbDirectFormatting(false)
1625 {
1626  CheckBoxFormat( pFormat )->Add( this );
1627 
1628  // insert into the table
1629  const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1630  OSL_ENSURE( pTableNd, "In which table is the box?" );
1631  SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1632  GetTabSortBoxes());
1633  SwTableBox* p = this; // error: &this
1634  rSrtArr.insert( p ); // insert
1635 }
1636 
1638 {
1639  if (m_pStartNode) // box containing contents?
1640  {
1641  // remove from table
1642  const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1643  assert(pTableNd && "In which table is that box?");
1644  SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1645  GetTabSortBoxes());
1646  SwTableBox *p = this; // error: &this
1647  rSrtArr.erase( p ); // remove
1648  m_pStartNode = nullptr; // clear it so this is only run once
1649  }
1650 }
1651 
1653 {
1654  if (!GetFrameFormat()->GetDoc()->IsInDtor())
1655  {
1656  RemoveFromTable();
1657  }
1658 
1659  // the TabelleBox can be deleted if it's the last client of the FrameFormat
1661  pMod->Remove( this ); // remove,
1662  if( !pMod->HasWriterListeners() )
1663  delete pMod; // and delete
1664 }
1665 
1667 {
1668  // We might need to create a new format here, because the box must be
1669  // added to the format solely if pFormat has a value or form.
1670  if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) ||
1671  SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ) )
1672  {
1673  SwTableBox* pOther = SwIterator<SwTableBox,SwFormat>( *pFormat ).First();
1674  if( pOther )
1675  {
1676  SwTableBoxFormat* pNewFormat = pFormat->GetDoc()->MakeTableBoxFormat();
1677  pNewFormat->LockModify();
1678  *pNewFormat = *pFormat;
1679 
1680  // Remove values and formulas
1682  pNewFormat->UnlockModify();
1683 
1684  pFormat = pNewFormat;
1685  }
1686  }
1687  return pFormat;
1688 }
1689 
1691 {
1692  // This method makes sure that this object is an exclusive SwTableBox client
1693  // of an SwTableBoxFormat object
1694  // If other SwTableBox objects currently listen to the same SwTableBoxFormat as
1695  // this one, something needs to be done
1696  SwTableBoxFormat *pRet = static_cast<SwTableBoxFormat*>(GetFrameFormat());
1697  SwIterator<SwTableBox,SwFormat> aIter( *pRet );
1698  for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1699  {
1700  if ( pLast != this )
1701  {
1702  // Found another SwTableBox object
1703  // create a new Format as a copy and assign me to it
1704  // don't copy values and formulas
1705  SwTableBoxFormat* pNewFormat = pRet->GetDoc()->MakeTableBoxFormat();
1706  pNewFormat->LockModify();
1707  *pNewFormat = *pRet;
1709  pNewFormat->UnlockModify();
1710 
1711  // re-register SwCellFrame objects that know me
1712  SwIterator<SwCellFrame,SwFormat> aFrameIter( *pRet );
1713  for( SwCellFrame* pCell = aFrameIter.First(); pCell; pCell = aFrameIter.Next() )
1714  if( pCell->GetTabBox() == this )
1715  pCell->RegisterToFormat( *pNewFormat );
1716 
1717  // re-register myself
1718  pNewFormat->Add( this );
1719  pRet = pNewFormat;
1720  break;
1721  }
1722  }
1723  return pRet;
1724 }
1725 
1726 void SwTableBox::ChgFrameFormat( SwTableBoxFormat* pNewFormat, bool bNeedToReregister )
1727 {
1728  SwFrameFormat *pOld = GetFrameFormat();
1729  SwIterator<SwCellFrame,SwFormat> aIter( *pOld );
1730 
1731  // tdf#84635 We set bNeedToReregister=false to avoid a quadratic slowdown on loading large tables,
1732  // and since we are creating the table for the first time, no re-registration is necessary.
1733 
1734  // First, re-register the Frames.
1735  if (bNeedToReregister)
1736  for( SwCellFrame* pCell = aIter.First(); pCell; pCell = aIter.Next() )
1737  {
1738  if( pCell->GetTabBox() == this )
1739  {
1740  pCell->RegisterToFormat( *pNewFormat );
1741  pCell->InvalidateSize();
1742  pCell->InvalidatePrt_();
1743  pCell->SetCompletePaint();
1744  pCell->SetDerivedVert( false );
1745  pCell->CheckDirChange();
1746 
1747  // #i47489#
1748  // make sure that the row will be formatted, in order
1749  // to have the correct Get(Top|Bottom)MarginForLowers values
1750  // set at the row.
1751  const SwTabFrame* pTab = pCell->FindTabFrame();
1752  if ( pTab && pTab->IsCollapsingBorders() )
1753  {
1754  SwFrame* pRow = pCell->GetUpper();
1755  pRow->InvalidateSize_();
1756  pRow->InvalidatePrt_();
1757  }
1758  }
1759  }
1760 
1761  // Now, re-register self.
1762  pNewFormat->Add( this );
1763 
1764  if( !pOld->HasWriterListeners() )
1765  delete pOld;
1766 }
1767 
1768 // Return the name of this box. This is determined dynamically
1769 // resulting from the position in the lines/boxes/tables.
1770 void sw_GetTableBoxColStr( sal_uInt16 nCol, OUString& rNm )
1771 {
1772  const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z'
1773 
1774  do {
1775  const sal_uInt16 nCalc = nCol % coDiff;
1776  if( nCalc >= 26 )
1777  rNm = OUStringChar( sal_Unicode('a' - 26 + nCalc) ) + rNm;
1778  else
1779  rNm = OUStringChar( sal_Unicode('A' + nCalc) ) + rNm;
1780 
1781  nCol = nCol - nCalc;
1782  if( 0 == nCol )
1783  break;
1784  nCol /= coDiff;
1785  --nCol;
1786  } while( true );
1787 }
1788 
1790 {
1791  if( !m_pStartNode ) // box without content?
1792  {
1793  // search for the next first box?
1794  return Point( 0, 0 );
1795  }
1796 
1797  const SwTable& rTable = m_pStartNode->FindTableNode()->GetTable();
1798  sal_uInt16 nX, nY;
1799  const SwTableBox* pBox = this;
1800  do {
1801  const SwTableLine* pLine = pBox->GetUpper();
1802  // at the first level?
1803  const SwTableLines* pLines = pLine->GetUpper()
1804  ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
1805 
1806  nY = pLines->GetPos( pLine ) + 1 ;
1807  nX = pBox->GetUpper()->GetBoxPos( pBox ) + 1;
1808  pBox = pLine->GetUpper();
1809  } while( pBox );
1810  return Point( nX, nY );
1811 }
1812 
1813 OUString SwTableBox::GetName() const
1814 {
1815  if( !m_pStartNode ) // box without content?
1816  {
1817  // search for the next first box?
1818  return OUString();
1819  }
1820 
1821  const SwTable& rTable = m_pStartNode->FindTableNode()->GetTable();
1822  sal_uInt16 nPos;
1823  OUString sNm, sTmp;
1824  const SwTableBox* pBox = this;
1825  do {
1826  const SwTableLine* pLine = pBox->GetUpper();
1827  // at the first level?
1828  const SwTableLines* pLines = pLine->GetUpper()
1829  ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
1830 
1831  nPos = pLines->GetPos( pLine ) + 1;
1832  sTmp = OUString::number( nPos );
1833  if( !sNm.isEmpty() )
1834  sNm = sTmp + "." + sNm;
1835  else
1836  sNm = sTmp;
1837 
1838  nPos = pBox->GetUpper()->GetBoxPos( pBox );
1839  sTmp = OUString::number(nPos + 1);
1840  pBox = pLine->GetUpper();
1841  if( nullptr != pBox )
1842  sNm = sTmp + "." + sNm;
1843  else
1844  sw_GetTableBoxColStr( nPos, sNm );
1845 
1846  } while( pBox );
1847  return sNm;
1848 }
1849 
1850 bool SwTableBox::IsInHeadline( const SwTable* pTable ) const
1851 {
1852  if( !GetUpper() ) // should only happen upon merge.
1853  return false;
1854 
1855  if( !pTable )
1856  pTable = &m_pStartNode->FindTableNode()->GetTable();
1857 
1858  const SwTableLine* pLine = GetUpper();
1859  while( pLine->GetUpper() )
1860  pLine = pLine->GetUpper()->GetUpper();
1861 
1862  // Headerline?
1863  return pTable->GetTabLines()[ 0 ] == pLine;
1864 }
1865 
1867 {
1868  return m_pStartNode ? m_pStartNode->GetIndex() : 0;
1869 }
1870 
1871  // retrieve information from the client
1872 bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
1873 {
1874  switch( rInfo.Which() )
1875  {
1876  case RES_AUTOFMT_DOCNODE:
1877  {
1878  const SwTableNode* pNode = GetTableNode();
1879  if (pNode && &pNode->GetNodes() == static_cast<SwAutoFormatGetDocNode&>(rInfo).pNodes)
1880  {
1882  {
1883  SwNodeIndex aIdx( *m_TabSortContentBoxes[0]->GetSttNd() );
1884  GetFrameFormat()->GetDoc()->GetNodes().GoNext( &aIdx );
1885  }
1886  return false;
1887  }
1888  break;
1889  }
1890  case RES_FINDNEARESTNODE:
1891  if( GetFrameFormat() &&
1892  GetFrameFormat()->GetFormatAttr( RES_PAGEDESC ).GetPageDesc() &&
1894  m_TabSortContentBoxes[0]->GetSttNd()->GetNodes().IsDocNodes() )
1895  static_cast<SwFindNearestNode&>(rInfo).CheckNode( *
1896  m_TabSortContentBoxes[0]->GetSttNd()->FindTableNode() );
1897  break;
1898 
1899  case RES_CONTENT_VISIBLE:
1901  return false;
1902  }
1903  return true;
1904 }
1905 
1906 SwTable * SwTable::FindTable( SwFrameFormat const*const pFormat )
1907 {
1908  return pFormat
1909  ? SwIterator<SwTable,SwFormat>(*pFormat).First()
1910  : nullptr;
1911 }
1912 
1914 {
1915  return !GetTabSortBoxes().empty() ?
1916  const_cast<SwTableNode*>(GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode()) :
1917  m_pTableNode;
1918 }
1919 
1921 {
1922  if( m_xRefObj.is() )
1923  m_xRefObj->Closed();
1924 
1925  m_xRefObj = pObj;
1926 }
1927 
1928 void SwTable::SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout> const& r)
1929 {
1930  m_xHTMLLayout = r;
1931 }
1932 
1933 static void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
1934  bool bChgAlign )
1935 {
1936  sal_uLong nNdPos = rBox.IsValidNumTextNd();
1937  ChgTextToNum( rBox,rText,pCol,bChgAlign,nNdPos);
1938 }
1939 void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
1940  bool bChgAlign,sal_uLong nNdPos )
1941 {
1942 
1943  if( ULONG_MAX == nNdPos )
1944  return;
1945 
1946  SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
1947  SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
1948  const SfxPoolItem* pItem;
1949 
1950  // assign adjustment
1951  if( bChgAlign )
1952  {
1953  pItem = &pTNd->SwContentNode::GetAttr( RES_PARATR_ADJUST );
1954  SvxAdjust eAdjust = static_cast<const SvxAdjustItem*>(pItem)->GetAdjust();
1955  if( SvxAdjust::Left == eAdjust || SvxAdjust::Block == eAdjust )
1956  {
1957  SvxAdjustItem aAdjust( *static_cast<const SvxAdjustItem*>(pItem) );
1958  aAdjust.SetAdjust( SvxAdjust::Right );
1959  pTNd->SetAttr( aAdjust );
1960  }
1961  }
1962 
1963  // assign color or save "user color"
1964  if( !pTNd->GetpSwAttrSet() || SfxItemState::SET != pTNd->GetpSwAttrSet()->
1965  GetItemState( RES_CHRATR_COLOR, false, &pItem ))
1966  pItem = nullptr;
1967 
1968  const std::optional<Color>& pOldNumFormatColor = rBox.GetSaveNumFormatColor();
1969  std::optional<Color> pNewUserColor;
1970  if (pItem)
1971  pNewUserColor = static_cast<const SvxColorItem*>(pItem)->GetValue();
1972 
1973  if( ( pNewUserColor && pOldNumFormatColor &&
1974  *pNewUserColor == *pOldNumFormatColor ) ||
1975  ( !pNewUserColor && !pOldNumFormatColor ))
1976  {
1977  // Keep the user color, set updated values, delete old NumFormatColor if needed
1978  if( pCol )
1979  // if needed, set the color
1980  pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
1981  else if( pItem )
1982  {
1983  pNewUserColor = rBox.GetSaveUserColor();
1984  if( pNewUserColor )
1985  pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
1986  else
1987  pTNd->ResetAttr( RES_CHRATR_COLOR );
1988  }
1989  }
1990  else
1991  {
1992  // Save user color, set NumFormat color if needed, but never reset the color
1993  rBox.SetSaveUserColor( pNewUserColor ? *pNewUserColor : std::optional<Color>() );
1994 
1995  if( pCol )
1996  // if needed, set the color
1997  pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
1998 
1999  }
2000  rBox.SetSaveNumFormatColor( pCol ? *pCol : std::optional<Color>() );
2001 
2002  if( pTNd->GetText() != rText )
2003  {
2004  // Exchange text. Bugfix to keep Tabs (front and back!) and annotations (inword comment anchors)
2005  const OUString& rOrig = pTNd->GetText();
2006  sal_Int32 n;
2007 
2008  for( n = 0; n < rOrig.getLength() && ('\x9' == rOrig[n] || CH_TXTATR_INWORD == rOrig[n]); ++n )
2009  ;
2010  for( ; n < rOrig.getLength() && '\x01' == rOrig[n]; ++n )
2011  ;
2012  SwIndex aIdx( pTNd, n );
2013  for( n = rOrig.getLength(); n && ('\x9' == rOrig[--n] || CH_TXTATR_INWORD == rOrig[n]); )
2014  ;
2015  sal_Int32 nEndPos = n;
2016  n -= aIdx.GetIndex() - 1;
2017 
2018  // Reset DontExpand-Flags before exchange, to retrigger expansion
2019  {
2020  SwIndex aResetIdx( aIdx, n );
2021  pTNd->DontExpandFormat( aResetIdx, false, false );
2022  }
2023 
2025  {
2026  SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.getLength());
2027  pDoc->getIDocumentRedlineAccess().DeleteRedline(aTemp, true, RedlineType::Any);
2028  }
2029 
2030  // preserve comments inside of the number by deleting number portions starting from the back
2031  sal_Int32 nCommentPos = pTNd->GetText().lastIndexOf( CH_TXTATR_INWORD, nEndPos );
2032  while( nCommentPos > aIdx.GetIndex() )
2033  {
2034  pTNd->EraseText( SwIndex(pTNd, nCommentPos+1), nEndPos - nCommentPos, SwInsertFlags::EMPTYEXPAND );
2035  // find the next non-sequential comment anchor
2036  do
2037  {
2038  nEndPos = nCommentPos;
2039  n = nEndPos - aIdx.GetIndex();
2040  nCommentPos = pTNd->GetText().lastIndexOf( CH_TXTATR_INWORD, nEndPos );
2041  --nEndPos;
2042  }
2043  while( nCommentPos > aIdx.GetIndex() && nCommentPos == nEndPos );
2044  }
2045 
2046  pTNd->EraseText( aIdx, n, SwInsertFlags::EMPTYEXPAND );
2047  pTNd->InsertText( rText, aIdx, SwInsertFlags::EMPTYEXPAND );
2048 
2049  if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
2050  {
2051  SwPaM aTemp(*pTNd, 0, *pTNd, rText.getLength());
2052  pDoc->getIDocumentRedlineAccess().AppendRedline(new SwRangeRedline(RedlineType::Insert, aTemp), true);
2053  }
2054  }
2055 
2056  // assign vertical orientation
2057  if( bChgAlign &&
2058  ( SfxItemState::SET != rBox.GetFrameFormat()->GetItemState(
2059  RES_VERT_ORIENT, true, &pItem ) ||
2060  text::VertOrientation::TOP == static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() ))
2061  {
2062  rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::BOTTOM ));
2063  }
2064 
2065 }
2066 
2067 static void ChgNumToText( SwTableBox& rBox, sal_uLong nFormat )
2068 {
2069  sal_uLong nNdPos = rBox.IsValidNumTextNd( false );
2070  if( ULONG_MAX == nNdPos )
2071  return;
2072 
2073  SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2074  SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
2075  bool bChgAlign = pDoc->IsInsTableAlignNum();
2076  const SfxPoolItem* pItem;
2077 
2078  const Color * pCol = nullptr;
2079  if( getSwDefaultTextFormat() != nFormat )
2080  {
2081  // special text format:
2082  OUString sTmp;
2083  const OUString sText( pTNd->GetText() );
2084  pDoc->GetNumberFormatter()->GetOutputString( sText, nFormat, sTmp, &pCol );
2085  if( sText != sTmp )
2086  {
2087  // exchange text
2088  SwIndex aIdx( pTNd, sText.getLength() );
2089  // Reset DontExpand-Flags before exchange, to retrigger expansion
2090  pTNd->DontExpandFormat( aIdx, false, false );
2091  aIdx = 0;
2093  pTNd->InsertText( sTmp, aIdx, SwInsertFlags::EMPTYEXPAND );
2094  }
2095  }
2096 
2097  const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
2098 
2099  // assign adjustment
2100  if( bChgAlign && pAttrSet && SfxItemState::SET == pAttrSet->GetItemState(
2101  RES_PARATR_ADJUST, false, &pItem ) &&
2102  SvxAdjust::Right == static_cast<const SvxAdjustItem*>(pItem)->GetAdjust() )
2103  {
2104  pTNd->SetAttr( SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST ) );
2105  }
2106 
2107  // assign color or save "user color"
2108  if( !pAttrSet || SfxItemState::SET != pAttrSet->
2109  GetItemState( RES_CHRATR_COLOR, false, &pItem ))
2110  pItem = nullptr;
2111 
2112  const std::optional<Color>& pOldNumFormatColor = rBox.GetSaveNumFormatColor();
2113  std::optional<Color> pNewUserColor;
2114  if (pItem)
2115  pNewUserColor = static_cast<const SvxColorItem*>(pItem)->GetValue();
2116 
2117  if( ( pNewUserColor && pOldNumFormatColor &&
2118  *pNewUserColor == *pOldNumFormatColor ) ||
2119  ( !pNewUserColor && !pOldNumFormatColor ))
2120  {
2121  // Keep the user color, set updated values, delete old NumFormatColor if needed
2122  if( pCol )
2123  // if needed, set the color
2124  pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2125  else if( pItem )
2126  {
2127  pNewUserColor = rBox.GetSaveUserColor();
2128  if( pNewUserColor )
2129  pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2130  else
2131  pTNd->ResetAttr( RES_CHRATR_COLOR );
2132  }
2133  }
2134  else
2135  {
2136  // Save user color, set NumFormat color if needed, but never reset the color
2137  rBox.SetSaveUserColor( pNewUserColor );
2138 
2139  if( pCol )
2140  // if needed, set the color
2141  pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2142 
2143  }
2144  rBox.SetSaveNumFormatColor( pCol ? *pCol : std::optional<Color>() );
2145 
2146  // assign vertical orientation
2147  if( bChgAlign &&
2148  SfxItemState::SET == rBox.GetFrameFormat()->GetItemState(
2149  RES_VERT_ORIENT, false, &pItem ) &&
2150  text::VertOrientation::BOTTOM == static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() )
2151  {
2152  rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::TOP ));
2153  }
2154 
2155 }
2156 
2157 // for detection of modifications (mainly TableBoxAttribute)
2158 void SwTableBoxFormat::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
2159 {
2160  auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint);
2161  if(!pLegacy)
2162  return;
2163  if(IsModifyLocked() || !GetDoc() || GetDoc()->IsInDtor())
2164  {
2165  SwFrameFormat::SwClientNotify(rMod, rHint);
2166  return;
2167  }
2168  const SwTableBoxNumFormat* pNewFormat = nullptr;
2169  const SwTableBoxFormula* pNewFormula = nullptr;
2170  const SwTableBoxValue* pNewVal = nullptr;
2171  sal_uLong nOldFormat = getSwDefaultTextFormat();
2172 
2173  switch(pLegacy->m_pNew ? pLegacy->m_pNew->Which() : 0)
2174  {
2175  case RES_ATTRSET_CHG:
2176  {
2177  const SfxItemSet& rSet = *static_cast<const SwAttrSetChg*>(pLegacy->m_pNew)->GetChgSet();
2178  if(SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT, false, reinterpret_cast<const SfxPoolItem**>(&pNewFormat)))
2179  nOldFormat = static_cast<const SwAttrSetChg*>(pLegacy->m_pOld)->GetChgSet()->Get(RES_BOXATR_FORMAT).GetValue();
2180  rSet.GetItemState(RES_BOXATR_FORMULA, false, reinterpret_cast<const SfxPoolItem**>(&pNewFormula));
2181  rSet.GetItemState(RES_BOXATR_VALUE, false, reinterpret_cast<const SfxPoolItem**>(&pNewVal));
2182  break;
2183  }
2184  case RES_BOXATR_FORMAT:
2185  pNewFormat = static_cast<const SwTableBoxNumFormat*>(pLegacy->m_pNew);
2186  nOldFormat = static_cast<const SwTableBoxNumFormat*>(pLegacy->m_pOld)->GetValue();
2187  break;
2188  case RES_BOXATR_FORMULA:
2189  pNewFormula = static_cast<const SwTableBoxFormula*>(pLegacy->m_pNew);
2190  break;
2191  case RES_BOXATR_VALUE:
2192  pNewVal = static_cast<const SwTableBoxValue*>(pLegacy->m_pNew);
2193  break;
2194  }
2195 
2196  // something changed and some BoxAttribut remained in the set!
2197  if( pNewFormat || pNewFormula || pNewVal )
2198  {
2199  GetDoc()->getIDocumentFieldsAccess().SetFieldsDirty(true, nullptr, 0);
2200 
2201  if( SfxItemState::SET == GetItemState( RES_BOXATR_FORMAT, false ) ||
2202  SfxItemState::SET == GetItemState( RES_BOXATR_VALUE, false ) ||
2203  SfxItemState::SET == GetItemState( RES_BOXATR_FORMULA, false ) )
2204  {
2205  // fetch the box
2206  SwIterator<SwTableBox,SwFormat> aIter( *this );
2207  SwTableBox* pBox = aIter.First();
2208  if( pBox )
2209  {
2210  OSL_ENSURE( !aIter.Next(), "zero or more than one box at format" );
2211 
2212  sal_uLong nNewFormat;
2213  if( pNewFormat )
2214  {
2215  nNewFormat = pNewFormat->GetValue();
2216  // new formatting
2217  // is it newer or has the current been removed?
2218  if( SfxItemState::SET != GetItemState( RES_BOXATR_VALUE, false ))
2219  pNewFormat = nullptr;
2220  }
2221  else
2222  {
2223  // fetch the current Item
2224  (void)GetItemState(RES_BOXATR_FORMAT, false, reinterpret_cast<const SfxPoolItem**>(&pNewFormat));
2225  nOldFormat = GetTableBoxNumFormat().GetValue();
2226  nNewFormat = pNewFormat ? pNewFormat->GetValue() : nOldFormat;
2227  }
2228 
2229  // is it newer or has the current been removed?
2230  if( pNewVal )
2231  {
2232  if( GetDoc()->GetNumberFormatter()->IsTextFormat(nNewFormat) )
2233  nOldFormat = 0;
2234  else
2235  {
2236  if( SfxItemState::SET == GetItemState( RES_BOXATR_VALUE, false ))
2237  nOldFormat = getSwDefaultTextFormat();
2238  else
2239  nNewFormat = getSwDefaultTextFormat();
2240  }
2241  }
2242 
2243  // Logic:
2244  // Value change: -> "simulate" a format change!
2245  // Format change:
2246  // Text -> !Text or format change:
2247  // - align right for horizontal alignment, if LEFT or JUSTIFIED
2248  // - align bottom for vertical alignment, if TOP is set, or default
2249  // - replace text (color? negative numbers RED?)
2250  // !Text -> Text:
2251  // - align left for horizontal alignment, if RIGHT
2252  // - align top for vertical alignment, if BOTTOM is set
2253  SvNumberFormatter* pNumFormatr = GetDoc()->GetNumberFormatter();
2254  bool bNewIsTextFormat = pNumFormatr->IsTextFormat( nNewFormat );
2255 
2256  if( (!bNewIsTextFormat && nOldFormat != nNewFormat) || pNewFormula )
2257  {
2258  bool bIsNumFormat = false;
2259  OUString aOrigText;
2260  bool bChgText = true;
2261  double fVal = 0;
2262  if( !pNewVal && SfxItemState::SET != GetItemState(
2263  RES_BOXATR_VALUE, false, reinterpret_cast<const SfxPoolItem**>(&pNewVal) ))
2264  {
2265  // so far, no value has been set, so try to evaluate the content
2266  sal_uLong nNdPos = pBox->IsValidNumTextNd();
2267  if( ULONG_MAX != nNdPos )
2268  {
2269  sal_uInt32 nTmpFormatIdx = nNewFormat;
2270  OUString aText( GetDoc()->GetNodes()[ nNdPos ]
2271  ->GetTextNode()->GetRedlineText());
2272  aOrigText = aText;
2273  if( aText.isEmpty() )
2274  bChgText = false;
2275  else
2276  {
2277  // Keep Tabs
2278  lcl_TabToBlankAtSttEnd( aText );
2279 
2280  // JP 22.04.98: Bug 49659 -
2281  // Special casing for percent
2282  if( SvNumFormatType::PERCENT ==
2283  pNumFormatr->GetType( nNewFormat ))
2284  {
2285  sal_uInt32 nTmpFormat = 0;
2286  if( GetDoc()->IsNumberFormat(
2287  aText, nTmpFormat, fVal ))
2288  {
2289  if( SvNumFormatType::NUMBER ==
2290  pNumFormatr->GetType( nTmpFormat ))
2291  aText += "%";
2292 
2293  bIsNumFormat = GetDoc()->IsNumberFormat(
2294  aText, nTmpFormatIdx, fVal );
2295  }
2296  }
2297  else
2298  bIsNumFormat = GetDoc()->IsNumberFormat(
2299  aText, nTmpFormatIdx, fVal );
2300 
2301  if( bIsNumFormat )
2302  {
2303  // directly assign value - without Modify
2304  bool bIsLockMod = IsModifyLocked();
2305  LockModify();
2306  SetFormatAttr( SwTableBoxValue( fVal ));
2307  if( !bIsLockMod )
2308  UnlockModify();
2309  }
2310  }
2311  }
2312  }
2313  else
2314  {
2315  fVal = pNewVal->GetValue();
2316  bIsNumFormat = true;
2317  }
2318 
2319  // format contents with the new value assigned and write to paragraph
2320  const Color* pCol = nullptr;
2321  OUString sNewText;
2322  if( DBL_MAX == fVal )
2323  {
2324  sNewText = SwViewShell::GetShellRes()->aCalc_Error;
2325  }
2326  else
2327  {
2328  if (bIsNumFormat)
2329  pNumFormatr->GetOutputString( fVal, nNewFormat, sNewText, &pCol );
2330  else
2331  {
2332  // Original text could not be parsed as
2333  // number/date/time/..., so keep the text.
2334 #if 0
2335  // Actually the text should be formatted
2336  // according to the format, which may include
2337  // additional text from the format, for example
2338  // in {0;-0;"BAD: "@}. But other places when
2339  // entering a new value or changing text or
2340  // changing to a different format of type Text
2341  // don't do this (yet?).
2342  pNumFormatr->GetOutputString( aOrigText, nNewFormat, sNewText, &pCol );
2343 #else
2344  sNewText = aOrigText;
2345 #endif
2346  }
2347 
2348  if( !bChgText )
2349  {
2350  sNewText.clear();
2351  }
2352  }
2353 
2354  // across all boxes
2355  ChgTextToNum( *pBox, sNewText, pCol,
2356  GetDoc()->IsInsTableAlignNum() );
2357 
2358  }
2359  else if( bNewIsTextFormat && nOldFormat != nNewFormat )
2360  {
2361  ChgNumToText( *pBox, nNewFormat );
2362  }
2363  }
2364  }
2365  }
2366  // call base class
2367  SwFrameFormat::SwClientNotify(rMod, rHint);
2368 }
2369 
2371 {
2372  return false;
2373 }
2374 
2376 {
2377  return false;
2378 }
2379 
2381 {
2382  return false;
2383 }
2384 
2385 bool SwTableBox::HasNumContent( double& rNum, sal_uInt32& rFormatIndex,
2386  bool& rIsEmptyTextNd ) const
2387 {
2388  bool bRet = false;
2389  sal_uLong nNdPos = IsValidNumTextNd();
2390  if( ULONG_MAX != nNdPos )
2391  {
2392  OUString aText( m_pStartNode->GetNodes()[ nNdPos ]->GetTextNode()->GetRedlineText() );
2393  // Keep Tabs
2394  lcl_TabToBlankAtSttEnd( aText );
2395  rIsEmptyTextNd = aText.isEmpty();
2397 
2398  const SfxPoolItem* pItem;
2399  if( SfxItemState::SET == GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT, false, &pItem ))
2400  {
2401  rFormatIndex = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
2402  // Special casing for percent
2403  if( !rIsEmptyTextNd && SvNumFormatType::PERCENT == pNumFormatr->GetType( rFormatIndex ))
2404  {
2405  sal_uInt32 nTmpFormat = 0;
2406  if( GetFrameFormat()->GetDoc()->IsNumberFormat( aText, nTmpFormat, rNum ) &&
2407  SvNumFormatType::NUMBER == pNumFormatr->GetType( nTmpFormat ))
2408  aText += "%";
2409  }
2410  }
2411  else
2412  rFormatIndex = 0;
2413 
2414  bRet = GetFrameFormat()->GetDoc()->IsNumberFormat( aText, rFormatIndex, rNum );
2415  }
2416  else
2417  rIsEmptyTextNd = false;
2418  return bRet;
2419 }
2420 
2422 {
2423  bool bRet = true;
2424 
2425  if( SfxItemState::SET == GetFrameFormat()->GetItemState( RES_BOXATR_FORMULA, false ))
2426  {
2427  const SwTableBoxNumFormat *pNumFormat;
2428  const SwTableBoxValue *pValue;
2429 
2430  if( SfxItemState::SET != GetFrameFormat()->GetItemState( RES_BOXATR_VALUE, false,
2431  reinterpret_cast<const SfxPoolItem**>(&pValue) ))
2432  pValue = nullptr;
2433  if( SfxItemState::SET != GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT, false,
2434  reinterpret_cast<const SfxPoolItem**>(&pNumFormat) ))
2435  pNumFormat = nullptr;
2436 
2437  sal_uLong nNdPos;
2438  if( pNumFormat && pValue && ULONG_MAX != ( nNdPos = IsValidNumTextNd() ) )
2439  {
2440  OUString sNewText, sOldText( m_pStartNode->GetNodes()[ nNdPos ]->
2441  GetTextNode()->GetRedlineText() );
2442  lcl_DelTabsAtSttEnd( sOldText );
2443 
2444  const Color* pCol = nullptr;
2446  pValue->GetValue(), pNumFormat->GetValue(), sNewText, &pCol );
2447 
2448  bRet = sNewText != sOldText ||
2449  !( ( !pCol && !GetSaveNumFormatColor() ) ||
2450  ( pCol && GetSaveNumFormatColor() &&
2451  *pCol == *GetSaveNumFormatColor() ));
2452  }
2453  }
2454  return bRet;
2455 }
2456 
2457 sal_uLong SwTableBox::IsValidNumTextNd( bool bCheckAttr ) const
2458 {
2459  sal_uLong nPos = ULONG_MAX;
2460  if( m_pStartNode )
2461  {
2462  SwNodeIndex aIdx( *m_pStartNode );
2463  sal_uLong nIndex = aIdx.GetIndex();
2464  const sal_uLong nIndexEnd = m_pStartNode->GetNodes()[ nIndex ]->EndOfSectionIndex();
2465  const SwTextNode *pTextNode = nullptr;
2466  while( ++nIndex < nIndexEnd )
2467  {
2468  const SwNode* pNode = m_pStartNode->GetNodes()[nIndex];
2469  if( pNode->IsTableNode() )
2470  {
2471  pTextNode = nullptr;
2472  break;
2473  }
2474  if( pNode->IsTextNode() )
2475  {
2476  if( pTextNode )
2477  {
2478  pTextNode = nullptr;
2479  break;
2480  }
2481  else
2482  {
2483  pTextNode = pNode->GetTextNode();
2484  nPos = nIndex;
2485  }
2486  }
2487  }
2488  if( pTextNode )
2489  {
2490  if( bCheckAttr )
2491  {
2492  const SwpHints* pHts = pTextNode->GetpSwpHints();
2493  // do some tests if there's only text in the node!
2494  // Flys/fields/...
2495  if( pHts )
2496  {
2497  sal_Int32 nNextSetField = 0;
2498  for( size_t n = 0; n < pHts->Count(); ++n )
2499  {
2500  const SwTextAttr* pAttr = pHts->Get(n);
2501  if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() )
2502  {
2503  if ( (pAttr->GetStart() == nNextSetField)
2504  && (pAttr->Which() == RES_TXTATR_FIELD))
2505  {
2506  // #i104949# hideous hack for report builder:
2507  // it inserts hidden variable-set fields at
2508  // the beginning of para in cell, but they
2509  // should not turn cell into text cell
2510  const SwField* pField = pAttr->GetFormatField().GetField();
2511  if (pField &&
2512  (pField->GetTypeId() == SwFieldTypesEnum::Set) &&
2513  (0 != (static_cast<SwSetExpField const*>
2514  (pField)->GetSubType() &
2516  {
2517  nNextSetField = pAttr->GetStart() + 1;
2518  continue;
2519  }
2520  }
2521  else if( RES_TXTATR_ANNOTATION == pAttr->Which() )
2522  {
2523  continue;
2524  }
2525  nPos = ULONG_MAX;
2526  break;
2527  }
2528  }
2529  }
2530  }
2531  }
2532  else
2533  nPos = ULONG_MAX;
2534  }
2535  return nPos;
2536 }
2537 
2538 // is this a Formula box or one with numeric content (AutoSum)
2540 {
2541  sal_uInt16 nWhich = 0;
2542  const SwTextNode* pTNd;
2543  SwFrameFormat* pFormat = GetFrameFormat();
2544  if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ))
2545  nWhich = RES_BOXATR_FORMULA;
2546  else if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) &&
2547  !pFormat->GetDoc()->GetNumberFormatter()->IsTextFormat(
2548  pFormat->GetTableBoxNumFormat().GetValue() ))
2549  nWhich = RES_BOXATR_VALUE;
2551  && nullptr != ( pTNd = m_pStartNode->GetNodes()[ m_pStartNode->GetIndex() + 1 ]
2552  ->GetTextNode() ) && pTNd->GetText().isEmpty())
2553  nWhich = USHRT_MAX;
2554 
2555  return nWhich;
2556 }
2557 
2559 {
2560  const SfxPoolItem *pFormatItem, *pValItem;
2561  SwFrameFormat* pFormat = GetFrameFormat();
2562  if( SfxItemState::SET != pFormat->GetItemState( RES_BOXATR_FORMAT, true, &pFormatItem )
2563  || SfxItemState::SET != pFormat->GetItemState( RES_BOXATR_VALUE, true, &pValItem ))
2564  return;
2565 
2566  const sal_uLong nFormatId = static_cast<const SwTableBoxNumFormat*>(pFormatItem)->GetValue();
2567  sal_uLong nNdPos = ULONG_MAX;
2568  SvNumberFormatter* pNumFormatr = pFormat->GetDoc()->GetNumberFormatter();
2569 
2570  if( !pNumFormatr->IsTextFormat( nFormatId ) &&
2571  ULONG_MAX != (nNdPos = IsValidNumTextNd()) )
2572  {
2573  double fVal = static_cast<const SwTableBoxValue*>(pValItem)->GetValue();
2574  const Color* pCol = nullptr;
2575  OUString sNewText;
2576  pNumFormatr->GetOutputString( fVal, nFormatId, sNewText, &pCol );
2577 
2578  const OUString& rText = m_pStartNode->GetNodes()[ nNdPos ]->GetTextNode()->GetText();
2579  if( rText != sNewText )
2580  ChgTextToNum( *this, sNewText, pCol, false ,nNdPos);
2581  }
2582 }
2583 
2585 {
2590  TableBoxes_t m_HandledTableBoxes;
2591 
2592 public:
2594  : m_pTable(nullptr), m_pCellFrame(nullptr), m_pTabFrame(nullptr)
2595  {
2596  }
2597 
2598  void setTable(const SwTable * pTable)
2599  {
2600  m_pTable = pTable;
2601  SwFrameFormat * pFrameFormat = m_pTable->GetFrameFormat();
2602  m_pTabFrame = SwIterator<SwTabFrame,SwFormat>(*pFrameFormat).First();
2603  if (m_pTabFrame && m_pTabFrame->IsFollow())
2604  m_pTabFrame = m_pTabFrame->FindMaster(true);
2605  }
2606 
2607  const SwCellFrame * getCellFrame() const { return m_pCellFrame; }
2608 
2609  const SwFrame * getNextFrameInTable(const SwFrame * pFrame);
2610  const SwCellFrame * getNextCellFrame(const SwFrame * pFrame);
2611  const SwCellFrame * getNextTableBoxsCellFrame(const SwFrame * pFrame);
2612  bool getNext();
2613 };
2614 
2616 {
2617  const SwFrame * pResult = nullptr;
2618 
2619  if (((! pFrame->IsTabFrame()) || pFrame == m_pTabFrame) && pFrame->GetLower())
2620  pResult = pFrame->GetLower();
2621  else if (pFrame->GetNext())
2622  pResult = pFrame->GetNext();
2623  else
2624  {
2625  while (pFrame->GetUpper() != nullptr)
2626  {
2627  pFrame = pFrame->GetUpper();
2628 
2629  if (pFrame->IsTabFrame())
2630  {
2631  m_pTabFrame = static_cast<const SwTabFrame *>(pFrame)->GetFollow();
2632  pResult = m_pTabFrame;
2633  break;
2634  }
2635  else if (pFrame->GetNext())
2636  {
2637  pResult = pFrame->GetNext();
2638  break;
2639  }
2640  }
2641  }
2642 
2643  return pResult;
2644 }
2645 
2647 {
2648  const SwCellFrame * pResult = nullptr;
2649 
2650  while ((pFrame = getNextFrameInTable(pFrame)) != nullptr)
2651  {
2652  if (pFrame->IsCellFrame())
2653  {
2654  pResult = static_cast<const SwCellFrame *>(pFrame);
2655  break;
2656  }
2657  }
2658 
2659  return pResult;
2660 }
2661 
2663 {
2664  const SwCellFrame * pResult = nullptr;
2665 
2666  while ((pFrame = getNextCellFrame(pFrame)) != nullptr)
2667  {
2668  const SwCellFrame * pCellFrame = static_cast<const SwCellFrame *>(pFrame);
2669  const SwTableBox * pTabBox = pCellFrame->GetTabBox();
2670  auto aIt = m_HandledTableBoxes.insert(pTabBox);
2671  if (aIt.second)
2672  {
2673  pResult = pCellFrame;
2674  break;
2675  }
2676  }
2677 
2678  return pResult;
2679 }
2680 
2682 {
2683  return m_pImpl->getCellFrame();
2684 }
2685 
2687 {
2688  if (m_pCellFrame == nullptr)
2689  {
2690  if (m_pTabFrame != nullptr)
2691  m_pCellFrame = Impl::getNextTableBoxsCellFrame(m_pTabFrame);
2692  }
2693  else
2694  m_pCellFrame = Impl::getNextTableBoxsCellFrame(m_pCellFrame);
2695 
2696  return m_pCellFrame != nullptr;
2697 }
2698 
2700  : m_pImpl(std::make_unique<Impl>())
2701 {
2702  m_pImpl->setTable(pTable);
2703 }
2704 
2706 {
2707 }
2708 
2710 {
2711  return m_pImpl->getNext();
2712 }
2713 
2715 {
2716  SwRect aRet;
2717 
2718  if (getCellFrame() != nullptr)
2719  aRet = getCellFrame()->getFrameArea();
2720 
2721  return aRet;
2722 }
2723 
2725 {
2726  const SwTableBox * pRet = nullptr;
2727 
2728  if (getCellFrame() != nullptr)
2729  pRet = getCellFrame()->GetTabBox();
2730 
2731  return pRet;
2732 }
2733 
2735 {
2736  rFormat.Add( this );
2737 }
2738 
2740 {
2741  const SwFrameFormat* pFrameFormat = GetFrameFormat();
2742  //a table in a clipboard document doesn't have any layout information
2743  return pFrameFormat && SwIterator<SwTabFrame,SwFormat>(*pFrameFormat).First();
2744 }
2745 
2747 {
2748  rFormat.Add( this );
2749 }
2750 
2751 // free's any remaining child objects
2753 {
2754  for ( const_iterator it = begin(); it != end(); ++it )
2755  delete *it;
2756 }
2757 
2758 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwTableLine(SwTableLineFormat *, sal_uInt16 nBoxes, SwTableBox *pUp)
Definition: swtable.cxx:1444
std::list< ColChange > ChangeList
Definition: swtable.cxx:974
const std::optional< Color > & GetSaveNumFormatColor() const
Definition: swtable.hxx:482
SwTableNode * m_pTableNode
Definition: swtable.hxx:125
const SwAttrSet * GetChgSet() const
What has changed.
Definition: hints.hxx:281
virtual ~SwTable() override
Definition: swtable.cxx:210
bool IsTableComplex() const
Definition: swtable.cxx:1429
const SwTableBoxNumFormat & GetTableBoxNumFormat(bool=true) const
TableBox attributes - implemented in cellatr.hxx.
Definition: cellatr.hxx:105
bool is() const
Starts a section of nodes in the document model.
Definition: node.hxx:312
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: atrfrm.cxx:2537
Base class of the Writer layout elements.
Definition: frame.hxx:298
SwTwips GetTableLineHeight(bool &bLayoutAvailable) const
Definition: swtable.cxx:1543
tools::Long GetWidth() const
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
sal_uLong GetIndex() const
Definition: node.hxx:291
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: swtable.cxx:316
const SwTabCols & rOld
Definition: swtable.cxx:597
SwTableLineFormat * MakeTableLineFormat()
Definition: docfmt.cxx:1712
sal_Int32 nIndex
void Add(SwClient *pDepend)
Definition: calbck.cxx:171
bool IsFollow() const
Definition: flowfrm.hxx:166
sal_uLong Count() const
Definition: ndarr.hxx:142
void RegisterToFormat(SwFormat &rFormat)
Definition: swtable.cxx:2734
static OUString & lcl_DelTabsAtSttEnd(OUString &rText)
Definition: swtable.cxx:110
sal_uInt16 GetWhich() const
Definition: calbck.hxx:71
const SwField * GetField() const
Definition: fmtfld.hxx:110
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1328
bool HasLayout() const
Definition: swtable.cxx:2739
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
const OUString & GetText() const
Definition: ndtxt.hxx:211
static ShellResource * GetShellRes()
Definition: viewsh.cxx:2552
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1866
o3tl::sorted_vector< const SwTableBox * > TableBoxes_t
Definition: swtable.cxx:2589
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:4897
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:219
std::string GetValue
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1413
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(150)
const SwExtendedSubType SUB_INVISIBLE
Invisible.
Definition: fldbas.hxx:212
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
const SwTabCols & rNew
Definition: swtable.cxx:596
bool IsInsTableAlignNum() const
Definition: doc.cxx:1689
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
static void lcl_CalcNewWidths(std::vector< sal_uInt16 > &rSpanPos, ChangeList &rChanges, SwTableLine *pLine, tools::Long nWish, tools::Long nWidth, bool bTop)
Definition: swtable.cxx:1025
sal_uIntPtr sal_uLong
long Long
Base class of all fields.
Definition: fldbas.hxx:289
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
tools::Long GetLeft() const
Definition: tabcol.hxx:78
tools::Long GetRightMax() const
Definition: tabcol.hxx:80
bool DontExpandFormat(const SwIndex &rIdx, bool bFlag=true, bool bFormatToTextAttributes=true)
When appropriate set DontExpand-flag at INet or character styles respectively.
Definition: ndtxt.cxx:1609
sal_Int64 n
bool IsCollapsingBorders() const
Definition: tabfrm.cxx:5603
void InvalidateSize_()
Definition: frame.hxx:754
Definition: doc.hxx:187
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1466
TElementType * Next()
Definition: calbck.hxx:333
bool HasFollow() const
Definition: flowfrm.hxx:165
IDocumentLinksAdministration const & getIDocumentLinksAdministration() const
Definition: doc.cxx:260
void setDummyFlag(bool bDummy)
Definition: swtable.cxx:90
SvNumFormatType GetType(sal_uInt32 nFIndex) const
void InvalidatePos()
Definition: frame.hxx:1024
SwTableLine is one table row in the document model.
Definition: swtable.hxx:351
SwNode & GetNode() const
Definition: ndindex.hxx:119
void SetRefObject(SwServerObject *)
Definition: swtable.cxx:1920
OUString aCalc_Error
Definition: shellres.hxx:40
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2375
double GetValue() const
Definition: cellatr.hxx:95
bool IsInHeadline(const SwTable *pTable) const
Definition: swtable.cxx:1850
bool IsCellFrame() const
Definition: frame.hxx:1207
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
iterator begin()
Definition: swtable.hxx:76
sal_uInt16 Which() const
Definition: txatbase.hxx:114
SwClient * Remove(SwClient *pDepend)
Definition: calbck.cxx:224
SwTableLine * front() const
Definition: swtable.hxx:80
bool HasWriterListeners() const
Definition: calbck.hxx:197
EmbeddedObjectRef * pObject
static void lcl_RefreshHidden(SwTabCols &rToFill, size_t nPos)
Definition: swtable.cxx:358
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(59)
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:203
void RemoveFromTable()
Definition: swtable.cxx:1637
const SwTabColsEntry & GetEntry(size_t nPos) const
Definition: tabcol.hxx:74
size_type size() const
Definition: swtable.hxx:75
const SwCellFrame * getCellFrame() const
Definition: swtable.cxx:2681
void RegisterToFormat(SwFormat &rFormat)
Definition: swtable.cxx:2746
sal_Int32 getRowSpan() const
Definition: swtable.cxx:75
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_CONTENT_VISIBLE(183)
SwTableBoxes m_aBoxes
Definition: swtable.hxx:353
void DelTableFrameFormat(SwTableFormat *pFormat)
Definition: docfmt.cxx:726
SwTableLine * back() const
Definition: swtable.hxx:81
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
constexpr TypedWhichId< SwFormatVertOrient > RES_VERT_ORIENT(102)
void sw_GetTableBoxColStr(sal_uInt16 nCol, OUString &rNm)
Definition: swtable.cxx:1770
SwTableLines m_aLines
Definition: swtable.hxx:115
sal_uInt16 IsFormulaOrValueBox() const
Definition: swtable.cxx:2539
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1499
SwShareBoxFormats aShareFormats
Definition: swtable.cxx:601
sal_uInt16 sal_Unicode
void SetSaveUserColor(std::optional< Color > p)
Definition: swtable.hxx:483
void GetTabCols(SwTabCols &rToFill, const SwTableBox *pStart, bool bHidden=false, bool bCurRowOnly=false) const
Definition: swtable.cxx:510
#define CH_TXTATR_INWORD
Definition: hintids.hxx:170
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
static void lcl_ProcessBoxSet(SwTableBox *pBox, Parm &rParm)
Definition: swtable.cxx:620
bool empty() const
Definition: docary.hxx:265
const SwRect & getFrameArea() const
Definition: frame.hxx:178
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:41
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:778
static bool IsRedlineOn(const RedlineFlags eM)
const SwTabFrame * m_pTabFrame
Definition: swtable.cxx:2588
bool InsBoxen(SwTableNode *, SwTableLine *, SwTableBoxFormat *, SwTextFormatColl *, const SfxItemSet *pAutoAttr, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Insert a new box in the line before InsPos.
Definition: ndtbl.cxx:230
virtual ~SwTableBox() override
Definition: swtable.cxx:1652
void AdjustWidths(const tools::Long nOld, const tools::Long nNew)
Definition: swtable.cxx:351
int nCount
void RemoveServer(SvLinkSource *rObj)
void UnlockModify()
Definition: swtable.hxx:184
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
TableChgMode m_eTableChgMode
Definition: swtable.hxx:128
SwTableBox(const SwTableBox &)=delete
void SetTabCols(const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:815
constexpr TypedWhichId< SwAttrSetChg > RES_ATTRSET_CHG(161)
void Width(tools::Long nNew)
Definition: swrect.hxx:187
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, sal_uLong nLen)=0
void SetHTMLTableLayout(std::shared_ptr< SwHTMLTableLayout > const &r)
Definition: swtable.cxx:1928
const SwTable & GetTable() const
Definition: node.hxx:501
SwTableCellInfo(SwTableCellInfo const &)=delete
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:195
SwTable()
Definition: swtable.cxx:178
void NewSetTabCols(Parm &rP, const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:1149
size_type size() const
constexpr TypedWhichId< SwFindNearestNode > RES_FINDNEARESTNODE(182)
virtual bool GetInfo(SfxPoolItem &) const override
Definition: swtable.cxx:1872
std::vector< SwTableLine * >::const_iterator const_iterator
Definition: swtable.hxx:69
sal_uLong IsValidNumTextNd(bool bCheckAttr=true) const
Definition: swtable.cxx:2457
void ActualiseValueBox()
Definition: swtable.cxx:2558
static void ChgNumToText(SwTableBox &rBox, sal_uLong nFormat)
Definition: swtable.cxx:2067
const SwCellFrame * getCellFrame() const
Definition: swtable.cxx:2607
const SwStartNode * m_pStartNode
Definition: swtable.hxx:402
tools::SvRef< SwServerObject > m_xRefObj
Definition: swtable.hxx:117
Base class for various Writer styles.
Definition: format.hxx:46
SwTableSortBoxes m_TabSortContentBoxes
Definition: swtable.hxx:116
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:261
double GetValue(SwTableCalcPara &rPara) const
Get value of this box.
Definition: cellfml.cxx:80
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:452
OUString GetName() const
Definition: swtable.cxx:1813
static void lcl_AdjustLines(SwTableLines &rLines, const tools::Long nDiff, Parm &rParm)
Definition: swtable.cxx:793
TableChgMode GetTableChgDefaultMode()
Definition: edtwin3.cxx:103
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:1906
T * get() const
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
void SetSize(SwTableBox &rBox, const SwFormatFrameSize &rSz)
Definition: tblrwcl.cxx:3316
Style of a layout element.
Definition: frmfmt.hxx:58
size_t Count() const
Definition: ndhints.hxx:142
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:773
#define SAL_MAX_INT32
std::unique_ptr< sw::ModifyChangedHint > CheckRegistration(const SfxPoolItem *pOldValue)
Definition: calbck.cxx:78
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void SetRemoveFollowFlowLinePending(bool bNew)
Definition: tabfrm.hxx:169
SvxAdjust
int i
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2370
bool empty() const
Definition: swtable.hxx:74
void CheckBoxWidth(const SwTableLine &rLine, SwTwips nSize)
Definition: tblrwcl.cxx:2569
const std::optional< Color > & GetSaveUserColor() const
Definition: swtable.hxx:481
sal_uInt16 CalcShadowSpace(SvxShadowItemSide nShadow) const
void LockModify()
Definition: swtable.hxx:183
bool IsTextFormat(sal_uInt32 nFIndex) const
TElementType * First()
Definition: calbck.hxx:325
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType)=0
SwContentNode * GetContentNode()
Definition: node.hxx:619
SwLayoutFrame * GetUpper()
Definition: frame.hxx:661
bool getDummyFlag() const
Definition: swtable.cxx:85
static void lcl_ModifyBoxes(SwTableBoxes &rBoxes, const tools::Long nOld, const tools::Long nNew, std::vector< SwFormat * > &rFormatArr)
Definition: swtable.cxx:275
Marks a character position inside a document model node.
Definition: index.hxx:33
void UnlockModify()
Definition: calbck.hxx:204
std::deque< SwTableBox * > aBoxArr
Definition: swtable.cxx:600
std::pair< sal_uInt16, sal_uInt16 > ColChange
Definition: swtable.cxx:973
void LockModify()
Definition: calbck.hxx:203
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:373
static void lcl_AdjustBox(SwTableBox *pBox, const tools::Long nDiff, Parm &rParm)
Definition: swtable.cxx:803
void SetSaveNumFormatColor(std::optional< Color > p)
Definition: swtable.hxx:484
size
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:387
SwTableLines m_aLines
Definition: swtable.hxx:401
Marks a node in the document model.
Definition: ndindex.hxx:31
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:431
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:697
std::shared_ptr< SwHTMLTableLayout > m_xHTMLLayout
Definition: swtable.hxx:119
bool empty() const
void SetAdjust(const SvxAdjust eType)
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:123
static sal_uInt16 GetBoxNum(OUString &rStr, bool bFirst=false, const bool bPerformValidCheck=false)
Definition: swtable.cxx:1268
void Remove(size_t nPos, size_t nCount=1)
Definition: tabcol.cxx:86
SwStartNode * GetStartNode()
Definition: node.hxx:595
void InsTableBox(SwDoc &rDoc, SwTableNode *pTableNd, SwTableLine *pLine, SwTableBoxFormat *pBoxFrameFormat, SwTableBox *pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt)
Definition: swtable.cxx:130
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:363
const SwTableBox * getTableBox() const
Definition: swtable.cxx:2724
void DelBoxNode(SwTableSortBoxes const &rSortCntBoxes)
Definition: swtable.cxx:202
SwTableLines & GetTabLines()
Definition: swtable.hxx:200
tools::Long SwTwips
Definition: swtypes.hxx:49
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:111
void SetWidth(tools::Long n)
SwTableLines & GetTabLines()
Definition: swtable.hxx:424
void reserve(size_type nSize)
Definition: swtable.hxx:92
virtual bool IsIgnoreRedline() const =0
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: swtable.cxx:2158
Parm(const SwTabCols &rN, const SwTabCols &rO)
Definition: swtable.cxx:603
tools::Long const nBorder
TableBoxes_t m_HandledTableBoxes
Definition: swtable.cxx:2590
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:449
#define CHECK_TABLE(t)
Definition: swtable.cxx:62
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
static OUString & lcl_TabToBlankAtSttEnd(OUString &rText)
Definition: swtable.cxx:96
void EraseText(const SwIndex &rIdx, const sal_Int32 nCount=SAL_MAX_INT32, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
delete text content ATTENTION: must not be called with a range that overlaps the start of an attribut...
Definition: ndtxt.cxx:2667
Point GetCoordinates() const
Definition: swtable.cxx:1789
OUString InsertText(const OUString &rStr, const SwIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2282
static void lcl_ProcessLineGet(const SwTableLine *pLine, SwTabCols &rToFill, const SwFrameFormat *pTabFormat)
Definition: swtable.cxx:496
bool IsModifyLocked() const
Definition: calbck.hxx:205
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2380
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:681
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
tools::Long nNewWish
Definition: swtable.cxx:598
SwFieldTypesEnum GetTypeId() const
Definition: fldbas.cxx:250
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
static SwTableBoxFormat * CheckBoxFormat(SwTableBoxFormat *)
Definition: swtable.cxx:1666
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:361
static void lcl_SortedTabColInsert(SwTabCols &rToFill, const SwTableBox *pBox, const SwFrameFormat *pTabFormat, const bool bHidden, const bool bRefreshHidden)
Definition: swtable.cxx:370
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:623
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:104
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(149)
sal_Int32 mnRowSpan
SwRowFrame * GetFirstNonHeadlineRow() const
Definition: tabfrm.cxx:5548
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:445
static void lcl_ProcessLine(SwTableLine *pLine, Parm &rParm)
Definition: swtable.cxx:610
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:67
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:1726
bool IsTabFrame() const
Definition: frame.hxx:1199
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
tools::Long nMin
Definition: tabcol.hxx:31
void SetHidden(size_t nPos, bool bValue)
Definition: tabcol.hxx:68
const SwFrame * getNextFrameInTable(const SwFrame *pFrame)
Definition: swtable.cxx:2615
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
tools::Long nMax
Definition: tabcol.hxx:32
SwRect getRect() const
Definition: swtable.cxx:2714
tools::Long nOldWish
Definition: swtable.cxx:598
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwNodes & GetNodes()
Definition: doc.hxx:408
static void lcl_ProcessBoxGet(const SwTableBox *pBox, SwTabCols &rToFill, const SwFrameFormat *pTabFormat, bool bRefreshHidden)
Definition: swtable.cxx:479
void Insert(tools::Long nValue, bool bValue, size_t nPos)
Definition: tabcol.cxx:69
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:392
SwFrame * GetLower()
Definition: findfrm.cxx:170
void * p
constexpr TypedWhichId< SwAutoFormatGetDocNode > RES_AUTOFMT_DOCNODE(171)
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1690
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:726
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:357
SwTableBox * GetUpper()
Definition: swtable.hxx:369
bool IsNumberFormat(const OUString &rString, sal_uInt32 &F_Index, double &fOutNumber)
Definition: ndtbl.cxx:4022
virtual sfx2::LinkManager & GetLinkManager()=0
sal_uInt32 GetValue() const
const SwCellFrame * m_pCellFrame
Definition: swtable.cxx:2587
bool IsVertical() const
Definition: frame.hxx:954
bool IsInDtor() const
Definition: doc.hxx:403
#define COLFUZZY
Definition: swtable.cxx:70
void InvalidatePrt_()
Definition: frame.hxx:762
bool IsTableNode() const
Definition: node.hxx:644
void setRowSpan(sal_Int32 nNewRowSpan)
Definition: swtable.cxx:80
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:97
static bool lcl_IsValidRowName(const OUString &rStr)
Definition: swtable.cxx:1253
const SwCellFrame * getNextTableBoxsCellFrame(const SwFrame *pFrame)
Definition: swtable.cxx:2662
void setTable(const SwTable *pTable)
Definition: swtable.cxx:2598
iterator end()
Definition: swtable.hxx:78
tools::Long nPos
Definition: tabcol.hxx:30
Frame is variable in Var-direction.
virtual const SwRedlineTable & GetRedlineTable() const =0
bool HasNumContent(double &rNum, sal_uInt32 &rFormatIndex, bool &rIsEmptyTextNd) const
Definition: swtable.cxx:2385
std::pair< const_iterator, bool > insert(Value &&x)
static void ChgTextToNum(SwTableBox &rBox, const OUString &rText, const Color *pCol, bool bChgAlign, sal_uLong nNdPos)
Definition: swtable.cxx:1939
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5127
bool IsNewModel() const
Definition: swtable.hxx:187
static void lcl_AdjustWidthsInLine(SwTableLine *pLine, ChangeList &rOldNew, Parm &rParm, sal_uInt16 nColFuzzy)
Definition: swtable.cxx:976
SwTableLine * GetUpper()
Definition: swtable.hxx:427
const SwCellFrame * getNextCellFrame(const SwFrame *pFrame)
Definition: swtable.cxx:2646
static void lcl_ProcessBoxPtr(SwTableBox *pBox, std::deque< SwTableBox * > &rBoxArr, bool bBefore)
Definition: swtable.cxx:772
bool IsTextNode() const
Definition: node.hxx:640
void Height(tools::Long nNew)
Definition: swrect.hxx:191
tools::Long GetRight() const
Definition: tabcol.hxx:79
static void lcl_ModifyLines(SwTableLines &rLines, const tools::Long nOld, const tools::Long nNew, std::vector< SwFormat * > &rFormatArr, const bool bCheckSum)
Definition: swtable.cxx:257
bool IsNumberChanged() const
Definition: swtable.cxx:2421
bool m_bModifyLocked
Definition: swtable.hxx:137
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1293
virtual ~SwTableLine() override
Definition: swtable.cxx:1453
constexpr sal_uInt32 getSwDefaultTextFormat()
The number formatter's default locale's @ Text format.
Definition: cellatr.hxx:34
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
sal_uInt16 Which() const
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
static void FormatInArr(std::vector< SwFormat * > &rFormatArr, SwFormat *pBoxFormat)
Definition: swtable.cxx:247
const SwTable * m_pTable
Definition: swtable.cxx:2586
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
SwTableBoxFormat * MakeTableBoxFormat()
Definition: docfmt.cxx:1704
sal_uInt16 nPos
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:846
size_type erase(const Value &x)
size_t Count() const
Definition: tabcol.hxx:65
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5529
std::unique_ptr< Impl > m_pImpl
Definition: swtable.hxx:506
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1080
SwTableNode * GetTableNode() const
Definition: swtable.cxx:1913
SwFrame * GetNext()
Definition: frame.hxx:659
Base class of the Writer document model elements.
Definition: node.hxx:80
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo