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