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