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