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