LibreOffice Module sw (master)  1
tblrwcl.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 <memory>
21 #include <com/sun/star/text/HoriOrientation.hpp>
22 #include <osl/diagnose.h>
23 #include <hintids.hxx>
24 
25 #include <editeng/lrspitem.hxx>
26 #include <editeng/boxitem.hxx>
27 #include <tools/fract.hxx>
28 #include <fmtfsize.hxx>
29 #include <fmtornt.hxx>
30 #include <doc.hxx>
37 #include <docsh.hxx>
38 #include <fesh.hxx>
39 #include <tabfrm.hxx>
40 #include <frmatr.hxx>
41 #include <frmtool.hxx>
42 #include <pam.hxx>
43 #include <swtable.hxx>
44 #include <tblsel.hxx>
45 #include <fldbas.hxx>
46 #include <rowfrm.hxx>
47 #include <ddefld.hxx>
48 #include <hints.hxx>
49 #include <UndoTable.hxx>
50 #include <cellatr.hxx>
51 #include <mvsave.hxx>
52 #include <swtblfmt.hxx>
53 #include <swddetbl.hxx>
54 #include <poolfmt.hxx>
55 #include <tblrwcl.hxx>
56 #include <unochart.hxx>
57 #include <o3tl/numeric.hxx>
58 #include <calbck.hxx>
59 #include <docary.hxx>
60 
61 using namespace com::sun::star;
62 using namespace com::sun::star::uno;
63 
64 #define COLFUZZY 20
65 #define ROWFUZZY 10
66 
67 #ifdef DBG_UTIL
68 #define CHECK_TABLE(t) (t).CheckConsistency();
69 #else
70 #define CHECK_TABLE(t)
71 #endif
72 
73 namespace {
74 
75 // In order to set the Frame Formats for the Boxes, it's enough to look
76 // up the current one in the array. If it's already there return the new one.
77 struct CpyTabFrame
78 {
79  SwFrameFormat* pFrameFormat;
80  SwTableBoxFormat *pNewFrameFormat;
81 
82  explicit CpyTabFrame(SwFrameFormat* pCurrentFrameFormat) : pNewFrameFormat( nullptr )
83  { pFrameFormat = pCurrentFrameFormat; }
84 
85  bool operator==( const CpyTabFrame& rCpyTabFrame ) const
86  { return pFrameFormat == rCpyTabFrame.pFrameFormat; }
87  bool operator<( const CpyTabFrame& rCpyTabFrame ) const
88  { return pFrameFormat < rCpyTabFrame.pFrameFormat; }
89 };
90 
91 struct CR_SetBoxWidth
92 {
93  SwShareBoxFormats aShareFormats;
94  SwTableNode* pTableNd;
95  SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
96  TableChgMode nMode;
97  bool bBigger, bLeft;
98 
99  CR_SetBoxWidth( TableChgWidthHeightType eType, SwTwips nDif, SwTwips nSid,
100  SwTwips nMax, SwTableNode* pTNd )
101  : pTableNd( pTNd ),
102  nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 )
103  {
106  bBigger = bool(eType & TableChgWidthHeightType::BiggerMode );
107  nMode = pTableNd->GetTable().GetTableChgMode();
108  }
109  CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
110  : pTableNd( rCpy.pTableNd ),
111  nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
112  nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
113  nMode( rCpy.nMode ),
114  bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft )
115  {
116  }
117 
118  void LoopClear()
119  {
120  nLowerDiff = 0;
121  }
122 };
123 
124 }
125 
126 static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
127  SwTwips nDist, bool bCheck );
128 static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
129  SwTwips nDist, bool bCheck );
130 
131 typedef bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, bool );
132 
133 #ifdef DBG_UTIL
134 
135 #define CHECKBOXWIDTH \
136  { \
137  SwTwips nSize = GetFrameFormat()->GetFrameSize().GetWidth(); \
138  for (size_t nTmp = 0; nTmp < m_aLines.size(); ++nTmp) \
139  ::CheckBoxWidth( *m_aLines[ nTmp ], nSize ); \
140  }
141 
142 #define CHECKTABLELAYOUT \
143  { \
144  for ( size_t i = 0; i < GetTabLines().size(); ++i ) \
145  { \
146  SwFrameFormat* pFormat = GetTabLines()[i]->GetFrameFormat(); \
147  SwIterator<SwRowFrame,SwFormat> aIter( *pFormat ); \
148  for (SwRowFrame* pFrame=aIter.First(); pFrame; pFrame=aIter.Next())\
149  { \
150  if ( pFrame->GetTabLine() == GetTabLines()[i] ) \
151  { \
152  OSL_ENSURE( pFrame->GetUpper()->IsTabFrame(), \
153  "Table layout does not match table structure" ); \
154  } \
155  } \
156  } \
157  }
158 
159 #else
160 
161 #define CHECKBOXWIDTH
162 #define CHECKTABLELAYOUT
163 
164 #endif // DBG_UTIL
165 
166 namespace {
167 
168 struct CR_SetLineHeight
169 {
170  SwTableNode* pTableNd;
171  SwTwips nMaxSpace, nMaxHeight;
172  TableChgMode nMode;
173  bool bBigger;
174 
175  CR_SetLineHeight( TableChgWidthHeightType eType, SwTableNode* pTNd )
176  : pTableNd( pTNd ),
177  nMaxSpace( 0 ), nMaxHeight( 0 )
178  {
179  bBigger = bool(eType & TableChgWidthHeightType::BiggerMode );
180  nMode = pTableNd->GetTable().GetTableChgMode();
181  }
182  CR_SetLineHeight( const CR_SetLineHeight& rCpy )
183  : pTableNd( rCpy.pTableNd ),
184  nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
185  nMode( rCpy.nMode ),
186  bBigger( rCpy.bBigger )
187  {}
188 };
189 
190 }
191 
192 static bool lcl_SetSelLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
193  SwTwips nDist, bool bCheck );
194 static bool lcl_SetOtherLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
195  SwTwips nDist, bool bCheck );
196 
197 typedef bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, bool );
198 
200 
201 namespace {
202 
203 struct CpyPara
204 {
205  std::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
206  SwDoc& rDoc;
207  SwTableNode* pTableNd;
208  CpyTabFrames& rTabFrameArr;
209  SwTableLine* pInsLine;
210  SwTableBox* pInsBox;
211  sal_uLong nOldSize, nNewSize; // in order to correct the size attributes
212  sal_uLong nMinLeft, nMaxRight;
213  sal_uInt16 nCpyCnt, nInsPos;
214  sal_uInt16 nLnIdx, nBoxIdx;
215  sal_uInt8 nDelBorderFlag;
216  bool bCpyContent;
217 
218  CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, CpyTabFrames& rFrameArr )
219  : rDoc( pNd->GetDoc() ), pTableNd( pNd ), rTabFrameArr(rFrameArr),
220  pInsLine(nullptr), pInsBox(nullptr), nOldSize(0), nNewSize(0),
221  nMinLeft(ULONG_MAX), nMaxRight(0),
222  nCpyCnt(nCopies), nInsPos(0),
223  nLnIdx(0), nBoxIdx(0),
224  nDelBorderFlag(0), bCpyContent( true )
225  {}
226  CpyPara( const CpyPara& rPara, SwTableLine* pLine )
227  : pWidths( rPara.pWidths ), rDoc(rPara.rDoc), pTableNd(rPara.pTableNd),
228  rTabFrameArr(rPara.rTabFrameArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
229  nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
230  nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
231  nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
232  nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
233  {}
234  CpyPara( const CpyPara& rPara, SwTableBox* pBox )
235  : pWidths( rPara.pWidths ), rDoc(rPara.rDoc), pTableNd(rPara.pTableNd),
236  rTabFrameArr(rPara.rTabFrameArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
237  nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
238  nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
239  nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
240  nDelBorderFlag( rPara.nDelBorderFlag ), bCpyContent( rPara.bCpyContent )
241  {}
242 };
243 
244 }
245 
246 static void lcl_CopyRow(FndLine_ & rFndLine, CpyPara *const pCpyPara);
247 
248 static void lcl_CopyCol( FndBox_ & rFndBox, CpyPara *const pCpyPara)
249 {
250  // Look up the Frame Format in the Frame Format Array
251  SwTableBox* pBox = rFndBox.GetBox();
252  CpyTabFrame aFindFrame(pBox->GetFrameFormat());
253 
254  if( pCpyPara->nCpyCnt )
255  {
256  sal_uInt16 nFndPos;
257  CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.lower_bound( aFindFrame );
258  nFndPos = itFind - pCpyPara->rTabFrameArr.begin();
259  if( itFind == pCpyPara->rTabFrameArr.end() || !(*itFind == aFindFrame) )
260  {
261  // For nested copying, also save the new Format as an old one.
262  SwTableBoxFormat* pNewFormat = static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat());
263 
264  // Find the selected Boxes in the Line:
265  FndLine_ const* pCmpLine = nullptr;
266  SwFormatFrameSize aFrameSz( pNewFormat->GetFrameSize() );
267 
268  bool bDiffCount = false;
269  if( !pBox->GetTabLines().empty() )
270  {
271  pCmpLine = rFndBox.GetLines().front().get();
272  if ( pCmpLine->GetBoxes().size() != pCmpLine->GetLine()->GetTabBoxes().size() )
273  bDiffCount = true;
274  }
275 
276  if( bDiffCount )
277  {
278  // The first Line should be enough
279  FndBoxes_t const& rFndBoxes = pCmpLine->GetBoxes();
280  tools::Long nSz = 0;
281  for( auto n = rFndBoxes.size(); n; )
282  {
283  nSz += rFndBoxes[--n]->GetBox()->
284  GetFrameFormat()->GetFrameSize().GetWidth();
285  }
286  aFrameSz.SetWidth( aFrameSz.GetWidth() -
287  nSz / ( pCpyPara->nCpyCnt + 1 ) );
288  pNewFormat->SetFormatAttr( aFrameSz );
289  aFrameSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
290 
291  // Create a new Format for the new Box, specifying its size.
292  aFindFrame.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pNewFormat->GetDoc()->
293  MakeTableLineFormat());
294  *aFindFrame.pNewFrameFormat = *pNewFormat;
295  aFindFrame.pNewFrameFormat->SetFormatAttr( aFrameSz );
296  }
297  else
298  {
299  aFrameSz.SetWidth( aFrameSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
300  pNewFormat->SetFormatAttr( aFrameSz );
301 
302  aFindFrame.pNewFrameFormat = pNewFormat;
303  pCpyPara->rTabFrameArr.insert( aFindFrame );
304  aFindFrame.pFrameFormat = pNewFormat;
305  pCpyPara->rTabFrameArr.insert( aFindFrame );
306  }
307  }
308  else
309  {
310  aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ];
311  pBox->ChgFrameFormat( aFindFrame.pNewFrameFormat );
312  }
313  }
314  else
315  {
316  CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.find( aFindFrame );
317  if( pCpyPara->nDelBorderFlag &&
318  itFind != pCpyPara->rTabFrameArr.end() )
319  aFindFrame = *itFind;
320  else
321  aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
322  }
323 
324  if (!rFndBox.GetLines().empty())
325  {
326  pBox = new SwTableBox( aFindFrame.pNewFrameFormat,
327  rFndBox.GetLines().size(), pCpyPara->pInsLine );
328  pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
329  CpyPara aPara( *pCpyPara, pBox );
330  aPara.nDelBorderFlag &= 7;
331 
332  for (auto const& pFndLine : rFndBox.GetLines())
333  {
334  lcl_CopyRow(*pFndLine, &aPara);
335  }
336  }
337  else
338  {
339  ::InsTableBox( pCpyPara->rDoc, pCpyPara->pTableNd, pCpyPara->pInsLine,
340  aFindFrame.pNewFrameFormat, pBox, pCpyPara->nInsPos++ );
341 
342  const FndBoxes_t& rFndBxs = rFndBox.GetUpper()->GetBoxes();
343  if( 8 > pCpyPara->nDelBorderFlag
344  ? pCpyPara->nDelBorderFlag != 0
345  : &rFndBox == rFndBxs[rFndBxs.size() - 1].get())
346  {
347  const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
348  if( 8 > pCpyPara->nDelBorderFlag
349  ? rBoxItem.GetTop()
350  : rBoxItem.GetRight() )
351  {
352  aFindFrame.pFrameFormat = pBox->GetFrameFormat();
353 
354  SvxBoxItem aNew( rBoxItem );
355  if( 8 > pCpyPara->nDelBorderFlag )
356  aNew.SetLine( nullptr, SvxBoxItemLine::TOP );
357  else
358  aNew.SetLine( nullptr, SvxBoxItemLine::RIGHT );
359 
360  if( 1 == pCpyPara->nDelBorderFlag ||
361  8 == pCpyPara->nDelBorderFlag )
362  {
363  // For all Boxes that delete TopBorderLine, we copy after that
364  pBox = pCpyPara->pInsLine->GetTabBoxes()[
365  pCpyPara->nInsPos - 1 ];
366  }
367 
368  aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat());
369 
370  // Else we copy before that and the first Line keeps the TopLine
371  // and we remove it at the original
372  pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
373 
374  if( !pCpyPara->nCpyCnt )
375  pCpyPara->rTabFrameArr.insert( aFindFrame );
376  }
377  }
378  }
379 }
380 
381 static void lcl_CopyRow(FndLine_& rFndLine, CpyPara *const pCpyPara)
382 {
383  SwTableLine* pNewLine = new SwTableLine(
384  static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()),
385  rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
386  if( pCpyPara->pInsBox )
387  {
388  SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
389  rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
390  }
391  else
392  {
393  SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
394  rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
395  }
396 
397  CpyPara aPara( *pCpyPara, pNewLine );
398  for (auto const& it : rFndLine.GetBoxes())
399  {
400  lcl_CopyCol(*it, &aPara);
401  }
402 
403  pCpyPara->nDelBorderFlag &= 0xf8;
404 }
405 
406 static void lcl_InsCol( FndLine_* pFndLn, CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
407  bool bBehind )
408 {
409  // Bug 29124: Not only copy in the BaseLines. If possible, we go down as far as possible
410  FndBox_* pFBox;
411  if( 1 == pFndLn->GetBoxes().size() &&
412  !( pFBox = pFndLn->GetBoxes()[0].get() )->GetBox()->GetSttNd() )
413  {
414  // A Box with multiple Lines, so insert into these Lines
415  for (auto &rpLine : pFBox->GetLines())
416  {
417  lcl_InsCol( rpLine.get(), rCpyPara, nCpyCnt, bBehind );
418  }
419  }
420  else
421  {
422  rCpyPara.pInsLine = pFndLn->GetLine();
423  SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
424  pFndLn->GetBoxes().size()-1 : 0 ]->GetBox();
425  rCpyPara.nInsPos = pFndLn->GetLine()->GetBoxPos( pBox );
426  if( bBehind )
427  ++rCpyPara.nInsPos;
428 
429  for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
430  {
431  if( n + 1 == nCpyCnt && bBehind )
432  rCpyPara.nDelBorderFlag = 9;
433  else
434  rCpyPara.nDelBorderFlag = 8;
435  for (auto const& it : pFndLn->GetBoxes())
436  {
437  lcl_CopyCol(*it, &rCpyPara);
438  }
439  }
440  }
441 }
442 
444 {
446  for( SwRowFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
447  if( pFrame->GetTabLine() == &rLine )
448  return pFrame;
449  return nullptr;
450 }
451 
452 bool SwTable::InsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
453 {
454  OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box List" );
455  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
456  if( !pTableNd )
457  return false;
458 
459  bool bRes = true;
460  if( IsNewModel() )
461  bRes = NewInsertCol( rDoc, rBoxes, nCnt, bBehind );
462  else
463  {
464  // Find all Boxes/Lines
465  FndBox_ aFndBox( nullptr, nullptr );
466  {
467  FndPara aPara( rBoxes, &aFndBox );
468  ForEach_FndLineCopyCol( GetTabLines(), &aPara );
469  }
470  if( aFndBox.GetLines().empty() )
471  return false;
472 
473  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
474 
475  // Find Lines for the layout update
476  aFndBox.SetTableLines( *this );
477  aFndBox.DelFrames( *this );
478 
479  // TL_CHART2: nothing to be done since chart2 currently does not want to
480  // get notified about new rows/cols.
481 
482  CpyTabFrames aTabFrameArr;
483  CpyPara aCpyPara( pTableNd, nCnt, aTabFrameArr );
484 
485  for (auto & rpLine : aFndBox.GetLines())
486  {
487  lcl_InsCol( rpLine.get(), aCpyPara, nCnt, bBehind );
488  }
489 
490  // clean up this Line's structure once again, generally all of them
491  GCLines();
492 
493  // Update Layout
494  aFndBox.MakeFrames( *this );
495 
498  bRes = true;
499  }
500 
502  if (pPCD && nCnt)
503  pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
504  rDoc.UpdateCharts( GetFrameFormat()->GetName() );
505 
507 
508  return bRes;
509 }
510 
511 bool SwTable::InsertRow_( SwDoc* pDoc, const SwSelBoxes& rBoxes,
512  sal_uInt16 nCnt, bool bBehind )
513 {
514  OSL_ENSURE( pDoc && !rBoxes.empty() && nCnt, "No valid Box List" );
515  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
516  if( !pTableNd )
517  return false;
518 
519  // Find all Boxes/Lines
520  FndBox_ aFndBox( nullptr, nullptr );
521  {
522  FndPara aPara( rBoxes, &aFndBox );
523  ForEach_FndLineCopyCol( GetTabLines(), &aPara );
524  }
525  if( aFndBox.GetLines().empty() )
526  return false;
527 
528  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
529 
530  FndBox_* pFndBox = &aFndBox;
531  {
532  FndLine_* pFndLine;
533  while( 1 == pFndBox->GetLines().size() )
534  {
535  pFndLine = pFndBox->GetLines()[0].get();
536  if( 1 != pFndLine->GetBoxes().size() )
537  break;
538  // Don't go down too far! One Line with Box needs to remain!
539  FndBox_ *const pTmpBox = pFndLine->GetBoxes().front().get();
540  if( !pTmpBox->GetLines().empty() )
541  pFndBox = pTmpBox;
542  else
543  break;
544  }
545  }
546 
547  // Find Lines for the layout update
548  const bool bLayout = !IsNewModel() &&
549  nullptr != SwIterator<SwTabFrame,SwFormat>( *GetFrameFormat() ).First();
550 
551  if ( bLayout )
552  {
553  aFndBox.SetTableLines( *this );
554  if( pFndBox != &aFndBox )
555  aFndBox.DelFrames( *this );
556  // TL_CHART2: nothing to be done since chart2 currently does not want to
557  // get notified about new rows/cols.
558  }
559 
560  CpyTabFrames aTabFrameArr;
561  CpyPara aCpyPara( pTableNd, 0, aTabFrameArr );
562 
563  SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
564  pFndBox->GetLines().size()-1 : 0 ]->GetLine();
565  if( &aFndBox == pFndBox )
566  aCpyPara.nInsPos = GetTabLines().GetPos( pLine );
567  else
568  {
569  aCpyPara.pInsBox = pFndBox->GetBox();
570  aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().GetPos( pLine );
571  }
572 
573  if( bBehind )
574  {
575  ++aCpyPara.nInsPos;
576  aCpyPara.nDelBorderFlag = 1;
577  }
578  else
579  aCpyPara.nDelBorderFlag = 2;
580 
581  for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
582  {
583  if( bBehind )
584  aCpyPara.nDelBorderFlag = 1;
585  for (auto & rpFndLine : pFndBox->GetLines())
586  lcl_CopyRow( *rpFndLine, &aCpyPara );
587  }
588 
589  // clean up this Line's structure once again, generally all of them
590  if( !pDoc->IsInReading() )
591  GCLines();
592 
593  // Update Layout
594  if ( bLayout )
595  {
596  if( pFndBox != &aFndBox )
597  aFndBox.MakeFrames( *this );
598  else
599  aFndBox.MakeNewFrames( *this, nCnt, bBehind );
600  }
601 
604 
606  if (pPCD && nCnt)
607  pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
608  pDoc->UpdateCharts( GetFrameFormat()->GetName() );
609 
611 
612  return true;
613 }
614 
615 static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const tools::Long nOffset,
616  bool bFirst, SwShareBoxFormats& rShareFormats );
617 
618 static void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const tools::Long nOffset,
619  bool bFirst, SwShareBoxFormats& rShareFormats )
620 {
621  for ( auto pLine : rLines )
622  ::lcl_LastBoxSetWidth( pLine->GetTabBoxes(), nOffset, bFirst, rShareFormats );
623 }
624 
625 static void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const tools::Long nOffset,
626  bool bFirst, SwShareBoxFormats& rShareFormats )
627 {
628  SwTableBox& rBox = *(bFirst ? rBoxes.front() : rBoxes.back());
629  if( !rBox.GetSttNd() )
630  ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
631  bFirst, rShareFormats );
632 
633  // Adapt the Box
634  const SwFrameFormat *pBoxFormat = rBox.GetFrameFormat();
635  SwFormatFrameSize aNew( pBoxFormat->GetFrameSize() );
636  aNew.SetWidth( aNew.GetWidth() + nOffset );
637  SwFrameFormat *pFormat = rShareFormats.GetFormat( *pBoxFormat, aNew );
638  if( pFormat )
639  rBox.ChgFrameFormat( static_cast<SwTableBoxFormat*>(pFormat) );
640  else
641  {
642  pFormat = rBox.ClaimFrameFormat();
643 
644  pFormat->LockModify();
645  pFormat->SetFormatAttr( aNew );
646  pFormat->UnlockModify();
647 
648  rShareFormats.AddFormat( *pBoxFormat, *pFormat );
649  }
650 }
651 
652 void DeleteBox_( SwTable& rTable, SwTableBox* pBox, SwUndo* pUndo,
653  bool bCalcNewSize, const bool bCorrBorder,
654  SwShareBoxFormats* pShareFormats )
655 {
656  do {
657  SwTwips nBoxSz = bCalcNewSize ?
658  pBox->GetFrameFormat()->GetFrameSize().GetWidth() : 0;
659  SwTableLine* pLine = pBox->GetUpper();
660  SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
661  sal_uInt16 nDelPos = pLine->GetBoxPos( pBox );
662  SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
663 
664  // Special treatment for the border:
665  if( bCorrBorder && 1 < rTableBoxes.size() )
666  {
667  const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
668 
669  if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
670  {
671  bool bChgd = false;
672 
673  // JP 02.04.97: 1st part for Bug 36271
674  // First the left/right edges
675  if( nDelPos + 1 < static_cast<sal_uInt16>(rTableBoxes.size()) )
676  {
677  SwTableBox* pNxtBox = rTableBoxes[ nDelPos + 1 ];
678  const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
679 
680  SwTableBox* pPrvBox = nDelPos ? rTableBoxes[ nDelPos - 1 ] : nullptr;
681 
682  if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
683  ( !pPrvBox || !pPrvBox->GetFrameFormat()->GetBox().GetRight()) )
684  {
685  SvxBoxItem aTmp( rNxtBoxItem );
686  aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
687  : rBoxItem.GetRight(),
688  SvxBoxItemLine::LEFT );
689  if( pShareFormats )
690  pShareFormats->SetAttr( *pNxtBox, aTmp );
691  else
692  pNxtBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
693  bChgd = true;
694  }
695  }
696  if( !bChgd && nDelPos )
697  {
698  SwTableBox* pPrvBox = rTableBoxes[ nDelPos - 1 ];
699  const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
700 
701  SwTableBox* pNxtBox = nDelPos + 1 < static_cast<sal_uInt16>(rTableBoxes.size())
702  ? rTableBoxes[ nDelPos + 1 ] : nullptr;
703 
704  if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
705  ( !pNxtBox || !pNxtBox->GetFrameFormat()->GetBox().GetLeft()) )
706  {
707  SvxBoxItem aTmp( rPrvBoxItem );
708  aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
709  : rBoxItem.GetRight(),
710  SvxBoxItemLine::RIGHT );
711  if( pShareFormats )
712  pShareFormats->SetAttr( *pPrvBox, aTmp );
713  else
714  pPrvBox->ClaimFrameFormat()->SetFormatAttr( aTmp );
715  }
716  }
717  }
718  }
719 
720  // Delete the Box first, then the Nodes!
721  SwStartNode* pSttNd = const_cast<SwStartNode*>(pBox->GetSttNd());
722  if( pShareFormats )
723  pShareFormats->RemoveFormat( *rTableBoxes[ nDelPos ]->GetFrameFormat() );
724 
725  // Before deleting the 'Table Box' from memory - delete any redlines attached to it
727  rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableCellRedline( rTable.GetFrameFormat()->GetDoc(), *(rTableBoxes[nDelPos]), true, RedlineType::Any );
728  delete rTableBoxes[nDelPos];
729  rTableBoxes.erase( rTableBoxes.begin() + nDelPos );
730 
731  if( pSttNd )
732  {
733  // Has the UndoObject been prepared to save the Section?
734  if( pUndo && pUndo->IsDelBox() )
735  static_cast<SwUndoTableNdsChg*>(pUndo)->SaveSection( pSttNd );
736  else
737  pSttNd->GetDoc().getIDocumentContentOperations().DeleteSection( pSttNd );
738  }
739 
740  // Also delete the Line?
741  if( !rTableBoxes.empty() )
742  {
743  // Then adapt the Frame-SSize
744  bool bLastBox = nDelPos == rTableBoxes.size();
745  if( bLastBox )
746  --nDelPos;
747  pBox = rTableBoxes[nDelPos];
748  if( bCalcNewSize )
749  {
750  SwFormatFrameSize aNew( pBox->GetFrameFormat()->GetFrameSize() );
751  aNew.SetWidth( aNew.GetWidth() + nBoxSz );
752  if( pShareFormats )
753  pShareFormats->SetSize( *pBox, aNew );
754  else
755  pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
756 
757  if( !pBox->GetSttNd() )
758  {
759  // We need to this recursively in all Lines in all Cells!
760  SwShareBoxFormats aShareFormats;
761  ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
762  !bLastBox,
763  pShareFormats ? *pShareFormats
764  : aShareFormats );
765  }
766  }
767  break; // Stop deleting
768  }
769  // Delete the Line from the Table/Box
770  if( !pUpperBox )
771  {
772  // Also delete the Line from the Table
773  nDelPos = rTable.GetTabLines().GetPos( pLine );
774  if( pShareFormats )
775  pShareFormats->RemoveFormat( *rTable.GetTabLines()[ nDelPos ]->GetFrameFormat() );
776 
777  SwTableLine* pTabLineToDelete = rTable.GetTabLines()[ nDelPos ];
778  // Before deleting the 'Table Line' from memory - delete any redlines attached to it
780  rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, RedlineType::Any );
781  delete pTabLineToDelete;
782  rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nDelPos );
783  break; // we cannot delete more
784  }
785 
786  // finally also delete the Line
787  pBox = pUpperBox;
788  nDelPos = pBox->GetTabLines().GetPos( pLine );
789  if( pShareFormats )
790  pShareFormats->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrameFormat() );
791 
792  SwTableLine* pTabLineToDelete = pBox->GetTabLines()[ nDelPos ];
793  // Before deleting the 'Table Line' from memory - delete any redlines attached to it
795  rTable.GetFrameFormat()->GetDoc()->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteTableRowRedline( rTable.GetFrameFormat()->GetDoc(), *pTabLineToDelete, true, RedlineType::Any );
796  delete pTabLineToDelete;
797  pBox->GetTabLines().erase( pBox->GetTabLines().begin() + nDelPos );
798  } while( pBox->GetTabLines().empty() );
799 }
800 
801 static SwTableBox*
803  SwTwips nBoxStt, SwTwips nBoxWidth,
804  sal_uInt16 nLinePos, bool bNxt,
805  SwSelBoxes* pAllDelBoxes, size_t *const pCurPos)
806 {
807  SwTableBox* pFndBox = nullptr;
808  do {
809  if( bNxt )
810  ++nLinePos;
811  else
812  --nLinePos;
813  SwTableLine* pLine = rTableLns[ nLinePos ];
814  SwTwips nFndBoxWidth = 0;
815  SwTwips nFndWidth = nBoxStt + nBoxWidth;
816 
817  pFndBox = pLine->GetTabBoxes()[ 0 ];
818  for( auto pBox : pLine->GetTabBoxes() )
819  {
820  if ( nFndWidth <= 0 )
821  {
822  break;
823  }
824  pFndBox = pBox;
825  nFndBoxWidth = pFndBox->GetFrameFormat()->GetFrameSize().GetWidth();
826  nFndWidth -= nFndBoxWidth;
827  }
828 
829  // Find the first ContentBox
830  while( !pFndBox->GetSttNd() )
831  {
832  const SwTableLines& rLowLns = pFndBox->GetTabLines();
833  if( bNxt )
834  pFndBox = rLowLns.front()->GetTabBoxes().front();
835  else
836  pFndBox = rLowLns.back()->GetTabBoxes().front();
837  }
838 
839  if( std::abs( nFndWidth ) > COLFUZZY ||
840  std::abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
841  pFndBox = nullptr;
842  else if( pAllDelBoxes )
843  {
844  // If the predecessor will also be deleted, there's nothing to do
845  SwSelBoxes::const_iterator aFndIt = pAllDelBoxes->find( pFndBox);
846  if( aFndIt == pAllDelBoxes->end() )
847  break;
848  size_t const nFndPos = aFndIt - pAllDelBoxes->begin() ;
849 
850  // else, we keep on searching.
851  // We do not need to recheck the Box, however
852  pFndBox = nullptr;
853  if( nFndPos <= *pCurPos )
854  --*pCurPos;
855  pAllDelBoxes->erase( pAllDelBoxes->begin() + nFndPos );
856  }
857  } while( bNxt ? ( nLinePos + 1 < static_cast<sal_uInt16>(rTableLns.size()) ) : nLinePos != 0 );
858  return pFndBox;
859 }
860 
861 static void
863  SwShareBoxFormats& rShareFormats,
864  SwSelBoxes* pAllDelBoxes = nullptr,
865  size_t *const pCurPos = nullptr )
866 {
867 //JP 16.04.97: 2. part for Bug 36271
868  const SwTableLine* pLine = rBox.GetUpper();
869  const SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
870  const SwTableBox* pUpperBox = &rBox;
871  sal_uInt16 nDelPos = pLine->GetBoxPos( pUpperBox );
872  pUpperBox = rBox.GetUpper()->GetUpper();
873  const SvxBoxItem& rBoxItem = rBox.GetFrameFormat()->GetBox();
874 
875  // then the top/bottom edges
876  if( !rBoxItem.GetTop() && !rBoxItem.GetBottom() )
877  return;
878 
879  bool bChgd = false;
880  const SwTableLines* pTableLns;
881  if( pUpperBox )
882  pTableLns = &pUpperBox->GetTabLines();
883  else
884  pTableLns = &rTable.GetTabLines();
885 
886  sal_uInt16 nLnPos = pTableLns->GetPos( pLine );
887 
888  // Calculate the attribute position of the top-be-deleted Box and then
889  // search in the top/bottom Line of the respective counterparts.
890  SwTwips nBoxStt = 0;
891  for( sal_uInt16 n = 0; n < nDelPos; ++n )
892  nBoxStt += rTableBoxes[ n ]->GetFrameFormat()->GetFrameSize().GetWidth();
893  SwTwips nBoxWidth = rBox.GetFrameFormat()->GetFrameSize().GetWidth();
894 
895  SwTableBox *pPrvBox = nullptr, *pNxtBox = nullptr;
896  if( nLnPos ) // Predecessor?
897  pPrvBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
898  nLnPos, false, pAllDelBoxes, pCurPos );
899 
900  if( nLnPos + 1 < static_cast<sal_uInt16>(pTableLns->size()) ) // Successor?
901  pNxtBox = ::lcl_FndNxtPrvDelBox( *pTableLns, nBoxStt, nBoxWidth,
902  nLnPos, true, pAllDelBoxes, pCurPos );
903 
904  if( pNxtBox && pNxtBox->GetSttNd() )
905  {
906  const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrameFormat()->GetBox();
907  if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
908  !pPrvBox->GetFrameFormat()->GetBox().GetBottom()) )
909  {
910  SvxBoxItem aTmp( rNxtBoxItem );
911  aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
912  : rBoxItem.GetBottom(),
913  SvxBoxItemLine::TOP );
914  rShareFormats.SetAttr( *pNxtBox, aTmp );
915  bChgd = true;
916  }
917  }
918  if( !(!bChgd && pPrvBox && pPrvBox->GetSttNd()) )
919  return;
920 
921  const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrameFormat()->GetBox();
922  if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
923  !pNxtBox->GetFrameFormat()->GetBox().GetTop()) )
924  {
925  SvxBoxItem aTmp( rPrvBoxItem );
926  aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
927  : rBoxItem.GetBottom(),
928  SvxBoxItemLine::BOTTOM );
929  rShareFormats.SetAttr( *pPrvBox, aTmp );
930  }
931 
932 }
933 
935  SwDoc* pDoc
936  ,
937  const SwSelBoxes& rBoxes,
938  const SwSelBoxes* pMerged, SwUndo* pUndo,
939  const bool bDelMakeFrames, const bool bCorrBorder )
940 {
941  OSL_ENSURE( pDoc, "No doc?" );
942  SwTableNode* pTableNd = nullptr;
943  if( !rBoxes.empty() )
944  {
945  pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
946  if( !pTableNd )
947  return false;
948  }
949 
950  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
951 
952  // Find Lines for the Layout update
953  FndBox_ aFndBox( nullptr, nullptr );
954  if ( bDelMakeFrames )
955  {
956  if( pMerged && !pMerged->empty() )
957  aFndBox.SetTableLines( *pMerged, *this );
958  else if( !rBoxes.empty() )
959  aFndBox.SetTableLines( rBoxes, *this );
960  aFndBox.DelFrames( *this );
961  }
962 
963  SwShareBoxFormats aShareFormats;
964 
965  // First switch the Border, then delete
966  if( bCorrBorder )
967  {
968  SwSelBoxes aBoxes( rBoxes );
969  for (size_t n = 0; n < aBoxes.size(); ++n)
970  {
971  ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFormats,
972  &aBoxes, &n );
973  }
974  }
975 
976  PrepareDelBoxes( rBoxes );
977 
979  // Delete boxes from last to first
980  for (size_t n = 0; n < rBoxes.size(); ++n)
981  {
982  size_t const nIdx = rBoxes.size() - 1 - n;
983 
984  // First adapt the data-sequence for chart if necessary
985  // (needed to move the implementation cursor properly to its new
986  // position which can't be done properly if the cell is already gone)
987  if (pPCD && pTableNd)
988  pPCD->DeleteBox( &pTableNd->GetTable(), *rBoxes[nIdx] );
989 
990  // ... then delete the boxes
991  DeleteBox_( *this, rBoxes[nIdx], pUndo, true, bCorrBorder, &aShareFormats );
992  }
993 
994  // then clean up the structure of all Lines
995  GCLines();
996 
997  if( bDelMakeFrames && aFndBox.AreLinesToRestore( *this ) )
998  aFndBox.MakeFrames( *this );
999 
1000  // TL_CHART2: now inform chart that sth has changed
1001  pDoc->UpdateCharts( GetFrameFormat()->GetName() );
1002 
1004  CHECK_TABLE( *this );
1005 
1006  return true;
1007 }
1008 
1009 bool SwTable::OldSplitRow( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
1010  bool bSameHeight )
1011 {
1012  OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid values" );
1013  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1014  if( !pTableNd )
1015  return false;
1016 
1017  // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1018  // the table too complex to be handled with chart.
1019  // Thus we tell the charts to use their own data provider and forget about this table
1021 
1022  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1023 
1024  // If the rows should get the same (min) height, we first have
1025  // to store the old row heights before deleting the frames
1026  std::unique_ptr<tools::Long[]> pRowHeights;
1027  if ( bSameHeight )
1028  {
1029  pRowHeights.reset(new tools::Long[ rBoxes.size() ]);
1030  for (size_t n = 0; n < rBoxes.size(); ++n)
1031  {
1032  SwTableBox* pSelBox = rBoxes[n];
1033  const SwRowFrame* pRow = GetRowFrame( *pSelBox->GetUpper() );
1034  OSL_ENSURE( pRow, "Where is the SwTableLine's Frame?" );
1035  SwRectFnSet aRectFnSet(pRow);
1036  pRowHeights[ n ] = aRectFnSet.GetHeight(pRow->getFrameArea());
1037  }
1038  }
1039 
1040  // Find Lines for the Layout update
1041  FndBox_ aFndBox( nullptr, nullptr );
1042  aFndBox.SetTableLines( rBoxes, *this );
1043  aFndBox.DelFrames( *this );
1044 
1045  for (size_t n = 0; n < rBoxes.size(); ++n)
1046  {
1047  SwTableBox* pSelBox = rBoxes[n];
1048  OSL_ENSURE( pSelBox, "Box is not within the Table" );
1049 
1050  // Insert nCnt new Lines into the Box
1051  SwTableLine* pInsLine = pSelBox->GetUpper();
1052  SwTableBoxFormat* pFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1053 
1054  // Respect the Line's height, reset if needed
1055  SwFormatFrameSize aFSz( pInsLine->GetFrameFormat()->GetFrameSize() );
1056  if ( bSameHeight && SwFrameSize::Variable == aFSz.GetHeightSizeType() )
1058 
1059  bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
1060  if ( bChgLineSz )
1061  aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
1062  (nCnt + 1) );
1063 
1064  SwTableBox* pNewBox = new SwTableBox( pFrameFormat, nCnt, pInsLine );
1065  sal_uInt16 nBoxPos = pInsLine->GetBoxPos( pSelBox );
1066  pInsLine->GetTabBoxes()[nBoxPos] = pNewBox; // overwrite old one
1067 
1068  // Delete background/border attribute
1069  SwTableBox* pLastBox = pSelBox; // To distribute the TextNodes!
1070  // If Areas are contained in the Box, it stays as is
1071  // !! If this is changed we need to adapt the Undo, too !!!
1072  bool bMoveNodes = true;
1073  {
1074  sal_uLong nSttNd = pLastBox->GetSttIdx() + 1,
1075  nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
1076  while( nSttNd < nEndNd )
1077  if( !rDoc.GetNodes()[ nSttNd++ ]->IsTextNode() )
1078  {
1079  bMoveNodes = false;
1080  break;
1081  }
1082  }
1083 
1084  SwTableBoxFormat* pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat());
1085  bool bChkBorder = nullptr != pCpyBoxFrameFormat->GetBox().GetTop();
1086  if( bChkBorder )
1087  pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1088 
1089  for( sal_uInt16 i = 0; i <= nCnt; ++i )
1090  {
1091  // Create a new Line in the new Box
1092  SwTableLine* pNewLine = new SwTableLine(
1093  static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 1, pNewBox );
1094  if( bChgLineSz )
1095  {
1096  pNewLine->ClaimFrameFormat()->SetFormatAttr( aFSz );
1097  }
1098 
1099  pNewBox->GetTabLines().insert( pNewBox->GetTabLines().begin() + i, pNewLine );
1100  // then a new Box in the Line
1101  if( !i ) // hang up the original Box
1102  {
1103  pSelBox->SetUpper( pNewLine );
1104  pNewLine->GetTabBoxes().insert( pNewLine->GetTabBoxes().begin(), pSelBox );
1105  }
1106  else
1107  {
1108  ::InsTableBox( rDoc, pTableNd, pNewLine, pCpyBoxFrameFormat,
1109  pLastBox, 0 );
1110 
1111  if( bChkBorder )
1112  {
1113  pCpyBoxFrameFormat = static_cast<SwTableBoxFormat*>(pNewLine->GetTabBoxes()[ 0 ]->ClaimFrameFormat());
1114  SvxBoxItem aTmp( pCpyBoxFrameFormat->GetBox() );
1115  aTmp.SetLine( nullptr, SvxBoxItemLine::TOP );
1116  pCpyBoxFrameFormat->SetFormatAttr( aTmp );
1117  bChkBorder = false;
1118  }
1119 
1120  if( bMoveNodes )
1121  {
1122  const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
1123  if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
1124  {
1125  // Move TextNodes
1126  SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
1127  pLastBox = pNewLine->GetTabBoxes()[0]; // reset
1128  SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
1129  rDoc.GetNodes().MoveNodes(aRg, rDoc.GetNodes(), aInsPos, false);
1130  rDoc.GetNodes().Delete( aInsPos ); // delete the empty one
1131  }
1132  }
1133  }
1134  }
1135  // In Boxes with Lines, we can only have Size/Fillorder
1136  pFrameFormat = static_cast<SwTableBoxFormat*>(pNewBox->ClaimFrameFormat());
1137  pFrameFormat->ResetFormatAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1138  pFrameFormat->ResetFormatAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
1139  }
1140 
1141  pRowHeights.reset();
1142 
1143  GCLines();
1144 
1145  aFndBox.MakeFrames( *this );
1146 
1149  return true;
1150 }
1151 
1152 bool SwTable::SplitCol(SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt)
1153 {
1154  OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid values" );
1155  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1156  if( !pTableNd )
1157  return false;
1158 
1159  // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1160  // the table too complex to be handled with chart.
1161  // Thus we tell the charts to use their own data provider and forget about this table
1163 
1164  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1165  SwSelBoxes aSelBoxes(rBoxes);
1166  ExpandSelection( aSelBoxes );
1167 
1168  // Find Lines for the Layout update
1169  FndBox_ aFndBox( nullptr, nullptr );
1170  aFndBox.SetTableLines( aSelBoxes, *this );
1171  aFndBox.DelFrames( *this );
1172 
1173  CpyTabFrames aFrameArr;
1174  std::vector<SwTableBoxFormat*> aLastBoxArr;
1175  for (size_t n = 0; n < aSelBoxes.size(); ++n)
1176  {
1177  SwTableBox* pSelBox = aSelBoxes[n];
1178  OSL_ENSURE( pSelBox, "Box is not in the table" );
1179 
1180  // We don't want to split small table cells into very very small cells
1181  if( pSelBox->GetFrameFormat()->GetFrameSize().GetWidth()/( nCnt + 1 ) < 10 )
1182  continue;
1183 
1184  // Then split the nCnt Box up into nCnt Boxes
1185  SwTableLine* pInsLine = pSelBox->GetUpper();
1186  sal_uInt16 nBoxPos = pInsLine->GetBoxPos( pSelBox );
1187 
1188  // Find the Frame Format in the Frame Format Array
1189  SwTableBoxFormat* pLastBoxFormat;
1190  CpyTabFrame aFindFrame( static_cast<SwTableBoxFormat*>(pSelBox->GetFrameFormat()) );
1191  CpyTabFrames::const_iterator itFind = aFrameArr.lower_bound( aFindFrame );
1192  const size_t nFndPos = itFind - aFrameArr.begin();
1193  if( itFind == aFrameArr.end() || !(*itFind == aFindFrame) )
1194  {
1195  // Change the FrameFormat
1196  aFindFrame.pNewFrameFormat = static_cast<SwTableBoxFormat*>(pSelBox->ClaimFrameFormat());
1197  SwTwips nBoxSz = aFindFrame.pNewFrameFormat->GetFrameSize().GetWidth();
1198  SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
1199  aFindFrame.pNewFrameFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable,
1200  nNewBoxSz, 0 ) );
1201  aFrameArr.insert( aFindFrame );
1202 
1203  pLastBoxFormat = aFindFrame.pNewFrameFormat;
1204  if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
1205  {
1206  // We have a remainder, so we need to define an own Format
1207  // for the last Box.
1208  pLastBoxFormat = new SwTableBoxFormat( *aFindFrame.pNewFrameFormat );
1210  nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
1211  }
1212  aLastBoxArr.insert( aLastBoxArr.begin() + nFndPos, pLastBoxFormat );
1213  }
1214  else
1215  {
1216  aFindFrame = aFrameArr[ nFndPos ];
1217  pSelBox->ChgFrameFormat( aFindFrame.pNewFrameFormat );
1218  pLastBoxFormat = aLastBoxArr[ nFndPos ];
1219  }
1220 
1221  // Insert the Boxes at the Position
1222  for( sal_uInt16 i = 1; i < nCnt; ++i )
1223  ::InsTableBox( rDoc, pTableNd, pInsLine, aFindFrame.pNewFrameFormat,
1224  pSelBox, nBoxPos + i ); // insert after
1225 
1226  ::InsTableBox( rDoc, pTableNd, pInsLine, pLastBoxFormat,
1227  pSelBox, nBoxPos + nCnt ); // insert after
1228 
1229  // Special treatment for the Border:
1230  const SvxBoxItem& aSelBoxItem = aFindFrame.pNewFrameFormat->GetBox();
1231  if( aSelBoxItem.GetRight() )
1232  {
1233  pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrameFormat();
1234 
1235  SvxBoxItem aTmp( aSelBoxItem );
1236  aTmp.SetLine( nullptr, SvxBoxItemLine::RIGHT );
1237  aFindFrame.pNewFrameFormat->SetFormatAttr( aTmp );
1238 
1239  // Remove the Format from the "cache"
1240  for( auto i = aFrameArr.size(); i; )
1241  {
1242  const CpyTabFrame& rCTF = aFrameArr[ --i ];
1243  if( rCTF.pNewFrameFormat == aFindFrame.pNewFrameFormat ||
1244  rCTF.pFrameFormat == aFindFrame.pNewFrameFormat )
1245  {
1246  aFrameArr.erase( aFrameArr.begin() + i );
1247  aLastBoxArr.erase( aLastBoxArr.begin() + i );
1248  }
1249  }
1250  }
1251  }
1252 
1253  // Update Layout
1254  aFndBox.MakeFrames( *this );
1255 
1258  return true;
1259 }
1260 
1261 /*
1262  * >> MERGE <<
1263  * Algorithm:
1264  * If we only have one Line in the FndBox_, take this Line and test
1265  * the Box count:
1266  * If we have more than one Box, we merge on Box level, meaning
1267  * the new Box will be as wide as the old ones.
1268  * All Lines that are above/under the Area, are inserted into
1269  * the Box as Line + Box.
1270  * All Lines that come before/after the Area, are inserted into
1271  * the Boxes Left/Right.
1272  *
1273  * >> MERGE <<
1274  */
1275 static void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
1276  SwTableLines& rLines,
1277  SwTableBox* pInsBox,
1278  sal_uInt16 nPos = USHRT_MAX )
1279 {
1280  for( sal_uInt16 n = nStt; n < nEnd; ++n )
1281  rLines[n]->SetUpper( pInsBox );
1282  if( USHRT_MAX == nPos )
1283  nPos = pInsBox->GetTabLines().size();
1284  pInsBox->GetTabLines().insert( pInsBox->GetTabLines().begin() + nPos,
1285  rLines.begin() + nStt, rLines.begin() + nEnd );
1286  rLines.erase( rLines.begin() + nStt, rLines.begin() + nEnd );
1287 }
1288 
1289 static void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
1290  SwTableBoxes& rBoxes,
1291  SwTableLine* pInsLine )
1292 {
1293  for( sal_uInt16 n = nStt; n < nEnd; ++n )
1294  rBoxes[n]->SetUpper( pInsLine );
1295  sal_uInt16 nPos = pInsLine->GetTabBoxes().size();
1296  pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + nPos,
1297  rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1298  rBoxes.erase( rBoxes.begin() + nStt, rBoxes.begin() + nEnd );
1299 }
1300 
1301 static void lcl_CalcWidth( SwTableBox* pBox )
1302 {
1303  // Assertion: Every Line in the Box is as large
1304  SwFrameFormat* pFormat = pBox->ClaimFrameFormat();
1305  OSL_ENSURE( pBox->GetTabLines().size(), "Box does not have any Lines" );
1306 
1307  SwTableLine* pLine = pBox->GetTabLines()[0];
1308  OSL_ENSURE( pLine, "Box is not within a Line" );
1309 
1310  tools::Long nWidth = 0;
1311  for( auto pTabBox : pLine->GetTabBoxes() )
1312  nWidth += pTabBox->GetFrameFormat()->GetFrameSize().GetWidth();
1313 
1314  pFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
1315 
1316  // Boxes with Lines can only have Size/Fillorder
1317  pFormat->ResetFormatAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
1319 }
1320 
1321 namespace {
1322 
1323 struct InsULPara
1324 {
1325  SwTableNode* pTableNd;
1326  SwTableLine* pInsLine;
1327  SwTableBox* pInsBox;
1328  bool bUL_LR : 1; // Upper-Lower(true) or Left-Right(false) ?
1329  bool bUL : 1; // Upper-Left(true) or Lower-Right(false) ?
1330 
1331  SwTableBox* pLeftBox;
1332 
1333  InsULPara( SwTableNode* pTNd,
1334  SwTableBox* pLeft,
1335  SwTableLine* pLine )
1336  : pTableNd( pTNd ), pInsLine( pLine ), pInsBox( nullptr ),
1337  pLeftBox( pLeft )
1338  { bUL_LR = true; bUL = true; }
1339 
1340  void SetLeft( SwTableBox* pBox )
1341  { bUL_LR = false; bUL = true; if( pBox ) pInsBox = pBox; }
1342  void SetRight( SwTableBox* pBox )
1343  { bUL_LR = false; bUL = false; if( pBox ) pInsBox = pBox; }
1344  void SetLower( SwTableLine* pLine )
1345  { bUL_LR = true; bUL = false; if( pLine ) pInsLine = pLine; }
1346 };
1347 
1348 }
1349 
1350 static void lcl_Merge_MoveLine(FndLine_ & rFndLine, InsULPara *const pULPara);
1351 
1352 static void lcl_Merge_MoveBox(FndBox_ & rFndBox, InsULPara *const pULPara)
1353 {
1354  SwTableBoxes* pBoxes;
1355 
1356  sal_uInt16 nStt = 0, nEnd = rFndBox.GetLines().size();
1357  sal_uInt16 nInsPos = USHRT_MAX;
1358  if( !pULPara->bUL_LR ) // Left/Right
1359  {
1360  sal_uInt16 nPos;
1361  SwTableBox* pFndTableBox = rFndBox.GetBox();
1362  pBoxes = &pFndTableBox->GetUpper()->GetTabBoxes();
1363  if( pULPara->bUL ) // Left ?
1364  {
1365  // if there are Boxes before it, move them
1366  nPos = pFndTableBox->GetUpper()->GetBoxPos( pFndTableBox );
1367  if( 0 != nPos )
1368  lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
1369  }
1370  else // Right
1371  {
1372  // if there are Boxes behind it, move them
1373  nPos = pFndTableBox->GetUpper()->GetBoxPos( pFndTableBox );
1374  if( nPos +1 < static_cast<sal_uInt16>(pBoxes->size()) )
1375  {
1376  nInsPos = pULPara->pInsLine->GetTabBoxes().size();
1377  lcl_CpyBoxes( nPos+1, pBoxes->size(),
1378  *pBoxes, pULPara->pInsLine );
1379  }
1380  }
1381  }
1382  // Upper/Lower and still deeper?
1383  else if (!rFndBox.GetLines().empty())
1384  {
1385  // Only search the Line from which we need to move
1386  nStt = pULPara->bUL ? 0 : rFndBox.GetLines().size()-1;
1387  nEnd = nStt+1;
1388  }
1389 
1390  pBoxes = &pULPara->pInsLine->GetTabBoxes();
1391 
1392  // Is there still a level to step down to?
1393  if (rFndBox.GetBox()->GetTabLines().empty())
1394  return;
1395 
1396  SwTableBox* pBox = new SwTableBox(
1397  static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()),
1398  0, pULPara->pInsLine );
1399  InsULPara aPara( *pULPara );
1400  aPara.pInsBox = pBox;
1401  for (FndLines_t::iterator it = rFndBox.GetLines().begin() + nStt;
1402  it != rFndBox.GetLines().begin() + nEnd; ++it )
1403  {
1404  lcl_Merge_MoveLine(**it, &aPara);
1405  }
1406  if( !pBox->GetTabLines().empty() )
1407  {
1408  if( USHRT_MAX == nInsPos )
1409  nInsPos = pBoxes->size();
1410  pBoxes->insert( pBoxes->begin() + nInsPos, pBox );
1411  lcl_CalcWidth( pBox ); // calculate the Box's width
1412  }
1413  else
1414  delete pBox;
1415 }
1416 
1417 static void lcl_Merge_MoveLine(FndLine_& rFndLine, InsULPara *const pULPara)
1418 {
1419  SwTableLines* pLines;
1420 
1421  sal_uInt16 nStt = 0, nEnd = rFndLine.GetBoxes().size();
1422  sal_uInt16 nInsPos = USHRT_MAX;
1423  if( pULPara->bUL_LR ) // UpperLower ?
1424  {
1425  sal_uInt16 nPos;
1426  SwTableLine* pFndLn = rFndLine.GetLine();
1427  pLines = pFndLn->GetUpper() ?
1428  &pFndLn->GetUpper()->GetTabLines() :
1429  &pULPara->pTableNd->GetTable().GetTabLines();
1430 
1431  SwTableBox* pLBx = rFndLine.GetBoxes().front()->GetBox();
1432  SwTableBox* pRBx = rFndLine.GetBoxes().back()->GetBox();
1433  sal_uInt16 nLeft = pFndLn->GetBoxPos( pLBx );
1434  sal_uInt16 nRight = pFndLn->GetBoxPos( pRBx );
1435 
1436  if( !nLeft || nRight == pFndLn->GetTabBoxes().size() )
1437  {
1438  if( pULPara->bUL ) // Upper ?
1439  {
1440  // If there are Lines before it, move them
1441  nPos = pLines->GetPos( pFndLn );
1442  if( 0 != nPos )
1443  lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
1444  }
1445  else
1446  // If there are Lines after it, move them
1447  if( (nPos = pLines->GetPos( pFndLn )) + 1 < static_cast<sal_uInt16>(pLines->size()) )
1448  {
1449  nInsPos = pULPara->pInsBox->GetTabLines().size();
1450  lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1451  pULPara->pInsBox );
1452  }
1453  }
1454  else
1455  {
1456  // There are still Boxes on the left side, so put the Left-
1457  // and Merge-Box into one Box and Line, insert before/after
1458  // a Line with a Box, into which the upper/lower Lines are
1459  // inserted
1460  SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
1461  SwTableBox* pLMBox = new SwTableBox(
1462  static_cast<SwTableBoxFormat*>(pULPara->pLeftBox->GetFrameFormat()), 0, pInsLine );
1463  SwTableLine* pLMLn = new SwTableLine(
1464  static_cast<SwTableLineFormat*>(pInsLine->GetFrameFormat()), 2, pLMBox );
1466 
1467  pLMBox->GetTabLines().insert( pLMBox->GetTabLines().begin(), pLMLn );
1468 
1469  lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
1470 
1471  pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLMBox );
1472 
1473  if( pULPara->bUL ) // Upper ?
1474  {
1475  // If there are Lines before it, move them
1476  nPos = pLines->GetPos( pFndLn );
1477  if( 0 != nPos )
1478  lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
1479  }
1480  else
1481  // If there are Lines after it, move them
1482  if( (nPos = pLines->GetPos( pFndLn )) + 1 < static_cast<sal_uInt16>(pLines->size()) )
1483  lcl_CpyLines( nPos+1, pLines->size(), *pLines,
1484  pLMBox );
1485  lcl_CalcWidth( pLMBox ); // calculate the Box's width
1486  }
1487  }
1488  // Left/Right
1489  else
1490  {
1491  // Find only the Line from which we need to move
1492  nStt = pULPara->bUL ? 0 : rFndLine.GetBoxes().size()-1;
1493  nEnd = nStt+1;
1494  }
1495  pLines = &pULPara->pInsBox->GetTabLines();
1496 
1497  SwTableLine* pNewLine = new SwTableLine(
1498  static_cast<SwTableLineFormat*>(rFndLine.GetLine()->GetFrameFormat()), 0, pULPara->pInsBox );
1499  InsULPara aPara( *pULPara ); // copying
1500  aPara.pInsLine = pNewLine;
1501  FndBoxes_t & rLineBoxes = rFndLine.GetBoxes();
1502  for (FndBoxes_t::iterator it = rLineBoxes.begin() + nStt;
1503  it != rLineBoxes.begin() + nEnd; ++it)
1504  {
1505  lcl_Merge_MoveBox(**it, &aPara);
1506  }
1507 
1508  if( !pNewLine->GetTabBoxes().empty() )
1509  {
1510  if( USHRT_MAX == nInsPos )
1511  nInsPos = pLines->size();
1512  pLines->insert( pLines->begin() + nInsPos, pNewLine );
1513  }
1514  else
1515  delete pNewLine;
1516 }
1517 
1518 static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox );
1519 
1520 bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
1521  SwTableBox* pMergeBox, SwUndoTableMerge* pUndo )
1522 {
1523  OSL_ENSURE( !rBoxes.empty() && pMergeBox, "no valid values" );
1524  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1525  if( !pTableNd )
1526  return false;
1527 
1528  // Find all Boxes/Lines
1529  FndBox_ aFndBox( nullptr, nullptr );
1530  {
1531  FndPara aPara( rBoxes, &aFndBox );
1532  ForEach_FndLineCopyCol( GetTabLines(), &aPara );
1533  }
1534  if( aFndBox.GetLines().empty() )
1535  return false;
1536 
1537  // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1538  // the table too complex to be handled with chart.
1539  // Thus we tell the charts to use their own data provider and forget about this table
1541 
1542  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
1543 
1544  if( pUndo )
1545  pUndo->SetSelBoxes( rBoxes );
1546 
1547  // Find Lines for the Layout update
1548  aFndBox.SetTableLines( *this );
1549  aFndBox.DelFrames( *this );
1550 
1551  FndBox_* pFndBox = &aFndBox;
1552  while( 1 == pFndBox->GetLines().size() &&
1553  1 == pFndBox->GetLines().front()->GetBoxes().size() )
1554  {
1555  pFndBox = pFndBox->GetLines().front()->GetBoxes().front().get();
1556  }
1557 
1558  SwTableLine* pInsLine = new SwTableLine(
1559  static_cast<SwTableLineFormat*>(pFndBox->GetLines().front()->GetLine()->GetFrameFormat()), 0,
1560  !pFndBox->GetUpper() ? nullptr : pFndBox->GetBox() );
1562 
1563  // Add the new Line
1564  SwTableLines* pLines = pFndBox->GetUpper() ?
1565  &pFndBox->GetBox()->GetTabLines() : &GetTabLines();
1566 
1567  SwTableLine* pNewLine = pFndBox->GetLines().front()->GetLine();
1568  sal_uInt16 nInsPos = pLines->GetPos( pNewLine );
1569  pLines->insert( pLines->begin() + nInsPos, pInsLine );
1570 
1571  SwTableBox* pLeftBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1572  SwTableBox* pRightBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pMergeBox->GetFrameFormat()), 0, pInsLine );
1573  pMergeBox->SetUpper( pInsLine );
1574  pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin(), pLeftBox );
1575  pLeftBox->ClaimFrameFormat();
1576  pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 1, pMergeBox);
1577  pInsLine->GetTabBoxes().insert( pInsLine->GetTabBoxes().begin() + 2, pRightBox );
1578  pRightBox->ClaimFrameFormat();
1579 
1580  // This contains all Lines that are above the selected Area,
1581  // thus they form a Upper/Lower Line
1582  InsULPara aPara( pTableNd, pLeftBox, pInsLine );
1583 
1584  // Move the overlapping upper/lower Lines of the selected Area
1585  for (auto & it : pFndBox->GetLines().front()->GetBoxes())
1586  {
1587  lcl_Merge_MoveBox(*it, &aPara);
1588  }
1589  aPara.SetLower( pInsLine );
1590  const auto nEnd = pFndBox->GetLines().size()-1;
1591  for (auto & it : pFndBox->GetLines()[nEnd]->GetBoxes())
1592  {
1593  lcl_Merge_MoveBox(*it, &aPara);
1594  }
1595 
1596  // Move the Boxes extending into the selected Area from left/right
1597  aPara.SetLeft( pLeftBox );
1598  for (auto & rpFndLine : pFndBox->GetLines())
1599  {
1600  lcl_Merge_MoveLine( *rpFndLine, &aPara );
1601  }
1602 
1603  aPara.SetRight( pRightBox );
1604  for (auto & rpFndLine : pFndBox->GetLines())
1605  {
1606  lcl_Merge_MoveLine( *rpFndLine, &aPara );
1607  }
1608 
1609  if( pLeftBox->GetTabLines().empty() )
1610  DeleteBox_( *this, pLeftBox, nullptr, false, false );
1611  else
1612  {
1613  lcl_CalcWidth( pLeftBox ); // calculate the Box's width
1614  if( pUndo && pLeftBox->GetSttNd() )
1615  pUndo->AddNewBox( pLeftBox->GetSttIdx() );
1616  }
1617  if( pRightBox->GetTabLines().empty() )
1618  DeleteBox_( *this, pRightBox, nullptr, false, false );
1619  else
1620  {
1621  lcl_CalcWidth( pRightBox ); // calculate the Box's width
1622  if( pUndo && pRightBox->GetSttNd() )
1623  pUndo->AddNewBox( pRightBox->GetSttIdx() );
1624  }
1625 
1626  DeleteSel( pDoc, rBoxes, nullptr, nullptr, false, false );
1627 
1628  // Clean up this Line's structure once again, generally all of them
1629  GCLines();
1630 
1631  for( const auto& rpBox : GetTabLines()[0]->GetTabBoxes() )
1632  lcl_BoxSetHeadCondColl(rpBox);
1633 
1634  aFndBox.MakeFrames( *this );
1635 
1638 
1639  return true;
1640 }
1641 
1642 static void lcl_CheckRowSpan( SwTable &rTable )
1643 {
1644  const tools::Long nLineCount = static_cast<tools::Long>(rTable.GetTabLines().size());
1645  tools::Long nMaxSpan = nLineCount;
1646  tools::Long nMinSpan = 1;
1647  while( nMaxSpan )
1648  {
1649  SwTableLine* pLine = rTable.GetTabLines()[ nLineCount - nMaxSpan ];
1650  for( auto pBox : pLine->GetTabBoxes() )
1651  {
1652  sal_Int32 nRowSpan = pBox->getRowSpan();
1653  if( nRowSpan > nMaxSpan )
1654  pBox->setRowSpan( nMaxSpan );
1655  else if( nRowSpan < nMinSpan )
1656  pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
1657  }
1658  --nMaxSpan;
1659  nMinSpan = -nMaxSpan;
1660  }
1661 }
1662 
1663 static sal_uInt16 lcl_GetBoxOffset( const FndBox_& rBox )
1664 {
1665  // Find the first Box
1666  const FndBox_* pFirstBox = &rBox;
1667  while (!pFirstBox->GetLines().empty())
1668  {
1669  pFirstBox = pFirstBox->GetLines().front()->GetBoxes().front().get();
1670  }
1671 
1672  sal_uInt16 nRet = 0;
1673  // Calculate the position relative to above via the Lines
1674  const SwTableBox* pBox = pFirstBox->GetBox();
1675  do {
1676  const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
1677  for( auto pCmp : rBoxes )
1678  {
1679  if (pBox==pCmp)
1680  break;
1681  nRet = nRet + static_cast<sal_uInt16>(pCmp->GetFrameFormat()->GetFrameSize().GetWidth());
1682  }
1683  pBox = pBox->GetUpper()->GetUpper();
1684  } while( pBox );
1685  return nRet;
1686 }
1687 
1688 static sal_uInt16 lcl_GetLineWidth( const FndLine_& rLine )
1689 {
1690  sal_uInt16 nRet = 0;
1691  for( auto n = rLine.GetBoxes().size(); n; )
1692  {
1693  nRet = nRet + static_cast<sal_uInt16>(rLine.GetBoxes()[--n]->GetBox()
1694  ->GetFrameFormat()->GetFrameSize().GetWidth());
1695  }
1696  return nRet;
1697 }
1698 
1699 static void lcl_CalcNewWidths(const FndLines_t& rFndLines, CpyPara& rPara)
1700 {
1701  rPara.pWidths.reset();
1702  const size_t nLineCount = rFndLines.size();
1703  if( nLineCount )
1704  {
1705  rPara.pWidths = std::make_shared< std::vector< std::vector< sal_uLong > > >
1706  ( nLineCount );
1707  // First we collect information about the left/right borders of all
1708  // selected cells
1709  for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1710  {
1711  std::vector< sal_uLong > &rWidth = (*rPara.pWidths)[ nLine ];
1712  const FndLine_ *pFndLine = rFndLines[ nLine ].get();
1713  if( pFndLine && !pFndLine->GetBoxes().empty() )
1714  {
1715  const SwTableLine *pLine = pFndLine->GetLine();
1716  if( pLine && !pLine->GetTabBoxes().empty() )
1717  {
1718  size_t nBoxCount = pLine->GetTabBoxes().size();
1719  sal_uLong nPos = 0;
1720  // The first selected box...
1721  const SwTableBox *const pSel =
1722  pFndLine->GetBoxes().front()->GetBox();
1723  size_t nBox = 0;
1724  // Sum up the width of all boxes before the first selected box
1725  while( nBox < nBoxCount )
1726  {
1727  SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
1728  if( pBox != pSel )
1729  nPos += pBox->GetFrameFormat()->GetFrameSize().GetWidth();
1730  else
1731  break;
1732  }
1733  // nPos is now the left border of the first selected box
1734  if( rPara.nMinLeft > nPos )
1735  rPara.nMinLeft = nPos;
1736  nBoxCount = pFndLine->GetBoxes().size();
1737  rWidth = std::vector< sal_uLong >( nBoxCount+2 );
1738  rWidth[ 0 ] = nPos;
1739  // Add now the widths of all selected boxes and store
1740  // the positions in the vector
1741  for( nBox = 0; nBox < nBoxCount; )
1742  {
1743  nPos += pFndLine->GetBoxes()[nBox]
1744  ->GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
1745  rWidth[ ++nBox ] = nPos;
1746  }
1747  // nPos: The right border of the last selected box
1748  if( rPara.nMaxRight < nPos )
1749  rPara.nMaxRight = nPos;
1750  if( nPos <= rWidth[ 0 ] )
1751  rWidth.clear();
1752  }
1753  }
1754  }
1755  }
1756  // Second step: calculate the new widths for the copied cells
1757  sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
1758  if( !nSelSize )
1759  return;
1760 
1761  for( size_t nLine = 0; nLine < nLineCount; ++nLine )
1762  {
1763  std::vector< sal_uLong > &rWidth = (*rPara.pWidths)[ nLine ];
1764  const size_t nCount = rWidth.size();
1765  if( nCount > 2 )
1766  {
1767  rWidth[ nCount - 1 ] = rPara.nMaxRight;
1768  sal_uLong nLastPos = 0;
1769  for( size_t nBox = 0; nBox < nCount; ++nBox )
1770  {
1771  sal_uInt64 nNextPos = rWidth[ nBox ];
1772  nNextPos -= rPara.nMinLeft;
1773  nNextPos *= rPara.nNewSize;
1774  nNextPos /= nSelSize;
1775  rWidth[ nBox ] = static_cast<sal_uLong>(nNextPos - nLastPos);
1776  nLastPos = static_cast<sal_uLong>(nNextPos);
1777  }
1778  }
1779  }
1780 }
1781 
1782 static void
1783 lcl_CopyLineToDoc(FndLine_ const& rpFndLn, CpyPara *const pCpyPara);
1784 
1785 static void lcl_CopyBoxToDoc(FndBox_ const& rFndBox, CpyPara *const pCpyPara)
1786 {
1787  // Calculation of new size
1788  sal_uLong nRealSize;
1789  sal_uLong nDummy1 = 0;
1790  sal_uLong nDummy2 = 0;
1791  if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1792  {
1793  if( pCpyPara->nBoxIdx == 1 )
1794  nDummy1 = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][0];
1795  nRealSize = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
1796  if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths)[pCpyPara->nLnIdx].size()-1 )
1797  nDummy2 = (*pCpyPara->pWidths)[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
1798  }
1799  else
1800  {
1801  nRealSize = pCpyPara->nNewSize;
1802  nRealSize *= rFndBox.GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
1803  if (pCpyPara->nOldSize == 0)
1804  throw o3tl::divide_by_zero();
1805  nRealSize /= pCpyPara->nOldSize;
1806  }
1807 
1808  sal_uLong nSize;
1809  bool bDummy = nDummy1 > 0;
1810  if( bDummy )
1811  nSize = nDummy1;
1812  else
1813  {
1814  nSize = nRealSize;
1815  nRealSize = 0;
1816  }
1817  do
1818  {
1819  // Find the Frame Format in the list of all Frame Formats
1820  CpyTabFrame aFindFrame(static_cast<SwTableBoxFormat*>(rFndBox.GetBox()->GetFrameFormat()));
1821 
1822  std::shared_ptr<SwFormatFrameSize> aFrameSz(std::make_shared<SwFormatFrameSize>());
1823  CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.lower_bound( aFindFrame );
1824  const CpyTabFrames::size_type nFndPos = itFind - pCpyPara->rTabFrameArr.begin();
1825 
1826  // It *is* sometimes cool to have multiple tests/if's and assignments
1827  // in a single statement, and it is technically possible. But it is definitely
1828  // not simply readable - where from my POV reading code is done 1000 times
1829  // more often than writing it. Thus I dismantled the expression in smaller
1830  // chunks to keep it handy/understandable/changeable (hopefully without error)
1831  // The original for reference:
1832  // if( itFind == pCpyPara->rTabFrameArr.end() || !(*itFind == aFindFrame) ||
1833  // ( aFrameSz = ( aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ]).pNewFrameFormat->
1834  // GetFrameSize()).GetWidth() != static_cast<SwTwips>(nSize) )
1835 
1836  bool DoCopyIt(itFind == pCpyPara->rTabFrameArr.end());
1837 
1838  if(!DoCopyIt)
1839  {
1840  DoCopyIt = !(*itFind == aFindFrame);
1841  }
1842 
1843  if(!DoCopyIt)
1844  {
1845  aFindFrame = pCpyPara->rTabFrameArr[ nFndPos ];
1846  aFrameSz.reset(aFindFrame.pNewFrameFormat->GetFrameSize().Clone());
1847  DoCopyIt = aFrameSz->GetWidth() != static_cast<SwTwips>(nSize);
1848  }
1849 
1850  if(DoCopyIt)
1851  {
1852  // It doesn't exist yet, so copy it
1853  aFindFrame.pNewFrameFormat = pCpyPara->rDoc.MakeTableBoxFormat();
1854  aFindFrame.pNewFrameFormat->CopyAttrs( *rFndBox.GetBox()->GetFrameFormat() );
1855  if( !pCpyPara->bCpyContent )
1856  aFindFrame.pNewFrameFormat->ResetFormatAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
1857  aFrameSz->SetWidth( nSize );
1858  aFindFrame.pNewFrameFormat->SetFormatAttr( *aFrameSz );
1859  pCpyPara->rTabFrameArr.insert( aFindFrame );
1860  }
1861 
1862  SwTableBox* pBox;
1863  if (!rFndBox.GetLines().empty())
1864  {
1865  pBox = new SwTableBox( aFindFrame.pNewFrameFormat,
1866  rFndBox.GetLines().size(), pCpyPara->pInsLine );
1867  pCpyPara->pInsLine->GetTabBoxes().insert( pCpyPara->pInsLine->GetTabBoxes().begin() + pCpyPara->nInsPos++, pBox );
1868  CpyPara aPara( *pCpyPara, pBox );
1869  aPara.nNewSize = nSize; // get the size
1870  for (auto const& rpFndLine : rFndBox.GetLines())
1871  {
1872  lcl_CopyLineToDoc( *rpFndLine, &aPara );
1873  }
1874  }
1875  else
1876  {
1877  // Create an empty Box
1878  pCpyPara->rDoc.GetNodes().InsBoxen( pCpyPara->pTableNd, pCpyPara->pInsLine,
1879  aFindFrame.pNewFrameFormat,
1880  pCpyPara->rDoc.GetDfltTextFormatColl(),
1881  nullptr, pCpyPara->nInsPos );
1882  pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
1883  if( bDummy )
1884  pBox->setDummyFlag( true );
1885  else if( pCpyPara->bCpyContent )
1886  {
1887  // Copy the content into this empty Box
1888  pBox->setRowSpan(rFndBox.GetBox()->getRowSpan());
1889 
1890  // We can also copy formulas and values, if we copy the content
1891  {
1892  SfxItemSet aBoxAttrSet( pCpyPara->rDoc.GetAttrPool(),
1894  aBoxAttrSet.Put(rFndBox.GetBox()->GetFrameFormat()->GetAttrSet());
1895  if( aBoxAttrSet.Count() )
1896  {
1897  const SfxPoolItem* pItem;
1898  SvNumberFormatter* pN = pCpyPara->rDoc.GetNumberFormatter( false );
1899  if( pN && pN->HasMergeFormatTable() && SfxItemState::SET == aBoxAttrSet.
1900  GetItemState( RES_BOXATR_FORMAT, false, &pItem ) )
1901  {
1902  sal_uLong nOldIdx = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
1903  sal_uLong nNewIdx = pN->GetMergeFormatIndex( nOldIdx );
1904  if( nNewIdx != nOldIdx )
1905  aBoxAttrSet.Put( SwTableBoxNumFormat( nNewIdx ));
1906  }
1907  pBox->ClaimFrameFormat()->SetFormatAttr( aBoxAttrSet );
1908  }
1909  }
1910  SwDoc* pFromDoc = rFndBox.GetBox()->GetFrameFormat()->GetDoc();
1911  SwNodeRange aCpyRg( *rFndBox.GetBox()->GetSttNd(), 1,
1912  *rFndBox.GetBox()->GetSttNd()->EndOfSectionNode() );
1913  SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
1914 
1915  pFromDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly(aCpyRg, aInsIdx, nullptr, false);
1916  // Delete the initial TextNode
1917  pCpyPara->rDoc.GetNodes().Delete( aInsIdx );
1918  }
1919  ++pCpyPara->nInsPos;
1920  }
1921  if( nRealSize )
1922  {
1923  bDummy = false;
1924  nSize = nRealSize;
1925  nRealSize = 0;
1926  }
1927  else
1928  {
1929  bDummy = true;
1930  nSize = nDummy2;
1931  nDummy2 = 0;
1932  }
1933  }
1934  while( nSize );
1935 }
1936 
1937 static void
1938 lcl_CopyLineToDoc(const FndLine_& rFndLine, CpyPara *const pCpyPara)
1939 {
1940  // Find the Frame Format in the list of all Frame Formats
1941  CpyTabFrame aFindFrame( rFndLine.GetLine()->GetFrameFormat() );
1942  CpyTabFrames::const_iterator itFind = pCpyPara->rTabFrameArr.find( aFindFrame );
1943  if( itFind == pCpyPara->rTabFrameArr.end() )
1944  {
1945  // It doesn't exist yet, so copy it
1946  aFindFrame.pNewFrameFormat = reinterpret_cast<SwTableBoxFormat*>(pCpyPara->rDoc.MakeTableLineFormat());
1947  aFindFrame.pNewFrameFormat->CopyAttrs( *rFndLine.GetLine()->GetFrameFormat() );
1948  pCpyPara->rTabFrameArr.insert( aFindFrame );
1949  }
1950  else
1951  aFindFrame = *itFind;
1952 
1953  SwTableLine* pNewLine = new SwTableLine( reinterpret_cast<SwTableLineFormat*>(aFindFrame.pNewFrameFormat),
1954  rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
1955  if( pCpyPara->pInsBox )
1956  {
1957  SwTableLines& rLines = pCpyPara->pInsBox->GetTabLines();
1958  rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine );
1959  }
1960  else
1961  {
1962  SwTableLines& rLines = pCpyPara->pTableNd->GetTable().GetTabLines();
1963  rLines.insert( rLines.begin() + pCpyPara->nInsPos++, pNewLine);
1964  }
1965 
1966  CpyPara aPara( *pCpyPara, pNewLine );
1967 
1968  if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1969  {
1970  aPara.nOldSize = 0; // will not be used
1971  aPara.nBoxIdx = 1;
1972  }
1973  else if( rFndLine.GetBoxes().size() ==
1974  rFndLine.GetLine()->GetTabBoxes().size() )
1975  {
1976  // Get the Parent's size
1977  const SwFrameFormat* pFormat;
1978 
1979  if( rFndLine.GetLine()->GetUpper() )
1980  pFormat = rFndLine.GetLine()->GetUpper()->GetFrameFormat();
1981  else
1982  pFormat = pCpyPara->pTableNd->GetTable().GetFrameFormat();
1983  aPara.nOldSize = pFormat->GetFrameSize().GetWidth();
1984  }
1985  else
1986  // Calculate it
1987  for (auto &rpBox : rFndLine.GetBoxes())
1988  {
1989  aPara.nOldSize += rpBox->GetBox()->GetFrameFormat()->GetFrameSize().GetWidth();
1990  }
1991 
1992  const FndBoxes_t& rBoxes = rFndLine.GetBoxes();
1993  for (auto const& it : rBoxes)
1994  {
1995  lcl_CopyBoxToDoc(*it, &aPara);
1996  }
1997  if( pCpyPara->pTableNd->GetTable().IsNewModel() )
1998  ++pCpyPara->nLnIdx;
1999 }
2000 
2002 {
2003  // Find all Boxes/Lines
2004  SwSelBoxes aSelBoxes;
2005  SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
2006  pBox = GetTableBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
2007  SelLineFromBox( pBox, aSelBoxes );
2008 
2009  FndBox_ aFndBox( nullptr, nullptr );
2010  {
2011  FndPara aPara( aSelBoxes, &aFndBox );
2012  ForEach_FndLineCopyCol( GetTabLines(), &aPara );
2013  }
2014  if( aFndBox.GetLines().empty() )
2015  return;
2016 
2017  {
2018  // Convert Table formulas to their relative representation
2019  SwTableFormulaUpdate aMsgHint( this );
2020  aMsgHint.m_eFlags = TBL_RELBOXNAME;
2021  GetFrameFormat()->GetDoc()->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2022  }
2023 
2024  CpyTabFrames aCpyFormat;
2025  CpyPara aPara( &rTableNd, 1, aCpyFormat );
2026  aPara.nNewSize = aPara.nOldSize = rTableNd.GetTable().GetFrameFormat()->GetFrameSize().GetWidth();
2027  // Copy
2028  if( IsNewModel() )
2029  lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2030  for (const auto & rpFndLine : aFndBox.GetLines())
2031  {
2032  lcl_CopyLineToDoc( *rpFndLine, &aPara );
2033  }
2034  if( rTableNd.GetTable().IsNewModel() )
2035  { // The copied line must not contain any row span attributes > 1
2036  SwTableLine* pLine = rTableNd.GetTable().GetTabLines()[0];
2037  OSL_ENSURE( !pLine->GetTabBoxes().empty(), "Empty Table Line" );
2038  for( auto pTableBox : pLine->GetTabBoxes() )
2039  {
2040  OSL_ENSURE( pTableBox, "Missing Table Box" );
2041  pTableBox->setRowSpan( 1 );
2042  }
2043  }
2044 }
2045 
2046 bool SwTable::MakeCopy( SwDoc& rInsDoc, const SwPosition& rPos,
2047  const SwSelBoxes& rSelBoxes,
2048  bool bCpyName ) const
2049 {
2050  // Find all Boxes/Lines
2051  FndBox_ aFndBox( nullptr, nullptr );
2052  {
2053  FndPara aPara( rSelBoxes, &aFndBox );
2054  ForEach_FndLineCopyCol( const_cast<SwTableLines&>(GetTabLines()), &aPara );
2055  }
2056  if( aFndBox.GetLines().empty() )
2057  return false;
2058 
2059  // First copy the PoolTemplates for the Table, so that the Tables are
2060  // actually copied and have valid values.
2061  SwDoc* pSrcDoc = GetFrameFormat()->GetDoc();
2062  if( pSrcDoc != &rInsDoc )
2063  {
2066  }
2067 
2068  SwTable* pNewTable = const_cast<SwTable*>(rInsDoc.InsertTable(
2070  rPos, 1, 1, GetFrameFormat()->GetHoriOrient().GetHoriOrient(),
2071  nullptr, nullptr, false, IsNewModel() ));
2072  if( !pNewTable )
2073  return false;
2074 
2075  SwNodeIndex aIdx( rPos.nNode, -1 );
2076  SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
2077  ++aIdx;
2078  OSL_ENSURE( pTableNd, "Where is the TableNode now?" );
2079 
2080  pTableNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2081 
2082  pNewTable->SetTableStyleName(pTableNd->GetTable().GetTableStyleName());
2083 
2084  if( auto pSwDDETable = dynamic_cast<const SwDDETable*>(this) )
2085  {
2086  // A DDE-Table is being copied
2087  // Does the new Document actually have it's FieldType?
2088  SwFieldType* pFieldType = rInsDoc.getIDocumentFieldsAccess().InsertFieldType(
2089  *pSwDDETable->GetDDEFieldType() );
2090  OSL_ENSURE( pFieldType, "unknown FieldType" );
2091 
2092  // Change the Table Pointer at the Node
2093  pNewTable = new SwDDETable( *pNewTable,
2094  static_cast<SwDDEFieldType*>(pFieldType) );
2095  pTableNd->SetNewTable( std::unique_ptr<SwTable>(pNewTable), false );
2096  }
2097 
2098  pNewTable->GetFrameFormat()->CopyAttrs( *GetFrameFormat() );
2099  pNewTable->SetTableChgMode( GetTableChgMode() );
2100 
2101  // Destroy the already created Frames
2102  pTableNd->DelFrames();
2103 
2104  {
2105  // Convert the Table formulas to their relative representation
2106  SwTableFormulaUpdate aMsgHint( this );
2107  aMsgHint.m_eFlags = TBL_RELBOXNAME;
2108  pSrcDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2109  }
2110 
2111  SwTableNumFormatMerge aTNFM(*pSrcDoc, rInsDoc);
2112 
2113  // Also copy Names or enforce a new unique one
2114  if( bCpyName )
2115  pNewTable->GetFrameFormat()->SetName( GetFrameFormat()->GetName() );
2116 
2117  CpyTabFrames aCpyFormat;
2118  CpyPara aPara( pTableNd, 1, aCpyFormat );
2119  aPara.nNewSize = aPara.nOldSize = GetFrameFormat()->GetFrameSize().GetWidth();
2120 
2121  if( IsNewModel() )
2122  lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2123  // Copy
2124  for (const auto & rpFndLine : aFndBox.GetLines())
2125  {
2126  lcl_CopyLineToDoc( *rpFndLine, &aPara );
2127  }
2128 
2129  // Set the "right" margin above/below
2130  {
2131  FndLine_* pFndLn = aFndBox.GetLines().front().get();
2132  SwTableLine* pLn = pFndLn->GetLine();
2133  const SwTableLine* pTmp = pLn;
2134  sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
2135  if( USHRT_MAX != nLnPos && nLnPos )
2136  {
2137  // There is a Line before it
2139 
2140  pLn = GetTabLines()[ nLnPos - 1 ];
2141  for( const auto& rpBox : pLn->GetTabBoxes() )
2142  sw_Box_CollectBox( rpBox, &aLnPara );
2143 
2144  if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2145  lcl_GetLineWidth( *pFndLn )) )
2146  {
2147  aLnPara.SetValues( true );
2148  pLn = pNewTable->GetTabLines()[ 0 ];
2149  for( const auto& rpBox : pLn->GetTabBoxes() )
2150  sw_BoxSetSplitBoxFormats(rpBox, &aLnPara );
2151  }
2152  }
2153 
2154  pFndLn = aFndBox.GetLines().back().get();
2155  pLn = pFndLn->GetLine();
2156  pTmp = pLn;
2157  nLnPos = GetTabLines().GetPos( pTmp );
2158  if( nLnPos < GetTabLines().size() - 1 )
2159  {
2160  // There is a Line following it
2162 
2163  pLn = GetTabLines()[ nLnPos + 1 ];
2164  for( const auto& rpBox : pLn->GetTabBoxes() )
2165  sw_Box_CollectBox( rpBox, &aLnPara );
2166 
2167  if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
2168  lcl_GetLineWidth( *pFndLn )) )
2169  {
2170  aLnPara.SetValues( false );
2171  pLn = pNewTable->GetTabLines().back();
2172  for( const auto& rpBox : pLn->GetTabBoxes() )
2173  sw_BoxSetSplitBoxFormats(rpBox, &aLnPara );
2174  }
2175  }
2176  }
2177 
2178  // We need to delete the initial Box
2179  DeleteBox_( *pNewTable, pNewTable->GetTabLines().back()->GetTabBoxes()[0],
2180  nullptr, false, false );
2181 
2182  if( pNewTable->IsNewModel() )
2183  lcl_CheckRowSpan( *pNewTable );
2184  // Clean up
2185  pNewTable->GCLines();
2186 
2187  pTableNd->MakeOwnFrames( &aIdx ); // re-generate the Frames
2188 
2190 
2191  return true;
2192 }
2193 
2194 // Find the next Box with content from this Line
2196  const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2197 {
2198  const SwTableLine* pLine = this; // for M800
2199  SwTableBox* pBox;
2200  sal_uInt16 nFndPos;
2201  if( !GetTabBoxes().empty() && pSrchBox )
2202  {
2203  nFndPos = GetBoxPos( pSrchBox );
2204  if( USHRT_MAX != nFndPos &&
2205  nFndPos + 1 != static_cast<sal_uInt16>(GetTabBoxes().size()) )
2206  {
2207  pBox = GetTabBoxes()[ nFndPos + 1 ];
2208  while( !pBox->GetTabLines().empty() )
2209  pBox = pBox->GetTabLines().front()->GetTabBoxes()[0];
2210  return pBox;
2211  }
2212  }
2213 
2214  if( GetUpper() )
2215  {
2216  nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2217  OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2218  // Is there another Line?
2219  if( nFndPos+1 >= static_cast<sal_uInt16>(GetUpper()->GetTabLines().size()) )
2220  return GetUpper()->GetUpper()->FindNextBox( rTable, GetUpper(), bOvrTableLns );
2221  pLine = GetUpper()->GetTabLines()[nFndPos+1];
2222  }
2223  else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2224  {
2225  // Search for the next Line in the Table
2226  nFndPos = rTable.GetTabLines().GetPos( pLine );
2227  if( nFndPos + 1 >= static_cast<sal_uInt16>(rTable.GetTabLines().size()) )
2228  return nullptr; // there are no more Boxes
2229 
2230  pLine = rTable.GetTabLines()[ nFndPos+1 ];
2231  }
2232  else
2233  return nullptr;
2234 
2235  if( !pLine->GetTabBoxes().empty() )
2236  {
2237  pBox = pLine->GetTabBoxes().front();
2238  while( !pBox->GetTabLines().empty() )
2239  pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
2240  return pBox;
2241  }
2242  return pLine->FindNextBox( rTable, nullptr, bOvrTableLns );
2243 }
2244 
2245 // Find the previous Box from this Line
2247  const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2248 {
2249  const SwTableLine* pLine = this; // for M800
2250  SwTableBox* pBox;
2251  sal_uInt16 nFndPos;
2252  if( !GetTabBoxes().empty() && pSrchBox )
2253  {
2254  nFndPos = GetBoxPos( pSrchBox );
2255  if( USHRT_MAX != nFndPos && nFndPos )
2256  {
2257  pBox = GetTabBoxes()[ nFndPos - 1 ];
2258  while( !pBox->GetTabLines().empty() )
2259  {
2260  pLine = pBox->GetTabLines().back();
2261  pBox = pLine->GetTabBoxes().back();
2262  }
2263  return pBox;
2264  }
2265  }
2266 
2267  if( GetUpper() )
2268  {
2269  nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2270  OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
2271  // Is there another Line?
2272  if( !nFndPos )
2273  return GetUpper()->GetUpper()->FindPreviousBox( rTable, GetUpper(), bOvrTableLns );
2274  pLine = GetUpper()->GetTabLines()[nFndPos-1];
2275  }
2276  else if( bOvrTableLns ) // Over a Table's the "BaseLines"??
2277  {
2278  // Search for the next Line in the Table
2279  nFndPos = rTable.GetTabLines().GetPos( pLine );
2280  if( !nFndPos )
2281  return nullptr; // there are no more Boxes
2282 
2283  pLine = rTable.GetTabLines()[ nFndPos-1 ];
2284  }
2285  else
2286  return nullptr;
2287 
2288  if( !pLine->GetTabBoxes().empty() )
2289  {
2290  pBox = pLine->GetTabBoxes().back();
2291  while( !pBox->GetTabLines().empty() )
2292  {
2293  pLine = pBox->GetTabLines().back();
2294  pBox = pLine->GetTabBoxes().back();
2295  }
2296  return pBox;
2297  }
2298  return pLine->FindPreviousBox( rTable, nullptr, bOvrTableLns );
2299 }
2300 
2301 // Find the next Box with content from this Line
2303  const SwTableBox* pSrchBox, bool bOvrTableLns ) const
2304 {
2305  if( !pSrchBox && GetTabLines().empty() )
2306  return const_cast<SwTableBox*>(this);
2307  return GetUpper()->FindNextBox( rTable, pSrchBox ? pSrchBox : this,
2308  bOvrTableLns );
2309 
2310 }
2311 
2312 // Find the next Box with content from this Line
2314  const SwTableBox* pSrchBox ) const
2315 {
2316  if( !pSrchBox && GetTabLines().empty() )
2317  return const_cast<SwTableBox*>(this);
2318  return GetUpper()->FindPreviousBox( rTable, pSrchBox ? pSrchBox : this );
2319 }
2320 
2321 static void lcl_BoxSetHeadCondColl( const SwTableBox* pBox )
2322 {
2323  // We need to adapt the paragraphs with conditional templates in the HeadLine
2324  const SwStartNode* pSttNd = pBox->GetSttNd();
2325  if( pSttNd )
2326  pSttNd->CheckSectionCondColl();
2327  else
2328  for( const SwTableLine* pLine : pBox->GetTabLines() )
2329  sw_LineSetHeadCondColl( pLine );
2330 }
2331 
2333 {
2334  for( const SwTableBox* pBox : pLine->GetTabBoxes() )
2335  lcl_BoxSetHeadCondColl(pBox);
2336 }
2337 
2338 static SwTwips lcl_GetDistance( SwTableBox* pBox, bool bLeft )
2339 {
2340  bool bFirst = true;
2341  SwTwips nRet = 0;
2342  SwTableLine* pLine;
2343  while( pBox )
2344  {
2345  pLine = pBox->GetUpper();
2346  if( !pLine )
2347  break;
2348  sal_uInt16 nStt = 0, nPos = pLine->GetBoxPos( pBox );
2349 
2350  if( bFirst && !bLeft )
2351  ++nPos;
2352  bFirst = false;
2353 
2354  while( nStt < nPos )
2355  nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrameFormat()
2356  ->GetFrameSize().GetWidth();
2357  pBox = pLine->GetUpper();
2358  }
2359  return nRet;
2360 }
2361 
2362 static bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2363  SwTwips nDist, bool bCheck )
2364 {
2365  SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2366  for( auto pBox : rBoxes )
2367  {
2368  SwFrameFormat* pFormat = pBox->GetFrameFormat();
2369  const SwFormatFrameSize& rSz = pFormat->GetFrameSize();
2370  SwTwips nWidth = rSz.GetWidth();
2371  bool bGreaterBox = false;
2372 
2373  if( bCheck )
2374  {
2375  for( auto pLn : pBox->GetTabLines() )
2376  if( !::lcl_SetSelBoxWidth( pLn, rParam, nDist, true ))
2377  return false;
2378 
2379  // Collect all "ContentBoxes"
2380  bGreaterBox = (TableChgMode::FixedWidthChangeAbs != rParam.nMode)
2381  && ((nDist + (rParam.bLeft ? 0 : nWidth)) >= rParam.nSide);
2382  if (bGreaterBox
2383  || (!rParam.bBigger
2384  && (std::abs(nDist + ((rParam.nMode != TableChgMode::FixedWidthChangeAbs && rParam.bLeft) ? 0 : nWidth) - rParam.nSide) < COLFUZZY)))
2385  {
2386  SwTwips nLowerDiff;
2387  if( bGreaterBox && TableChgMode::FixedWidthChangeProp == rParam.nMode )
2388  {
2389  // The "other Boxes" have been adapted, so change by this value
2390  nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2391  nLowerDiff *= rParam.nDiff;
2392  nLowerDiff /= rParam.nMaxSize;
2393  nLowerDiff = rParam.nDiff - nLowerDiff;
2394  }
2395  else
2396  nLowerDiff = rParam.nDiff;
2397 
2398  if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
2399  return false;
2400  }
2401  }
2402  else
2403  {
2404  SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2405  for( auto pLn : pBox->GetTabLines() )
2406  {
2407  rParam.nLowerDiff = 0;
2408  lcl_SetSelBoxWidth( pLn, rParam, nDist, false );
2409 
2410  if( nLowerDiff < rParam.nLowerDiff )
2411  nLowerDiff = rParam.nLowerDiff;
2412  }
2413  rParam.nLowerDiff = nOldLower;
2414 
2415  if( nLowerDiff ||
2416  (bGreaterBox = !nOldLower && TableChgMode::FixedWidthChangeAbs != rParam.nMode &&
2417  ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide) ||
2418  ( std::abs( nDist + ( (rParam.nMode != TableChgMode::FixedWidthChangeAbs && rParam.bLeft) ? 0 : nWidth )
2419  - rParam.nSide ) < COLFUZZY ))
2420  {
2421  // This column contains the Cursor - so decrease/increase
2422  SwFormatFrameSize aNew( rSz );
2423 
2424  if( !nLowerDiff )
2425  {
2426  if( bGreaterBox && TableChgMode::FixedWidthChangeProp == rParam.nMode )
2427  {
2428  // The "other Boxes" have been adapted, so change by this value
2429  nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
2430  nLowerDiff *= rParam.nDiff;
2431  nLowerDiff /= rParam.nMaxSize;
2432  nLowerDiff = rParam.nDiff - nLowerDiff;
2433  }
2434  else
2435  nLowerDiff = rParam.nDiff;
2436  }
2437 
2438  rParam.nLowerDiff += nLowerDiff;
2439 
2440  if( rParam.bBigger )
2441  aNew.SetWidth( nWidth + nLowerDiff );
2442  else
2443  aNew.SetWidth( nWidth - nLowerDiff );
2444  rParam.aShareFormats.SetSize( *pBox, aNew );
2445  break;
2446  }
2447  }
2448 
2449  if( rParam.bLeft && rParam.nMode != TableChgMode::FixedWidthChangeAbs && nDist >= rParam.nSide )
2450  break;
2451 
2452  nDist += nWidth;
2453 
2454  // If it gets bigger, then that's it
2455  if( ( TableChgMode::FixedWidthChangeAbs == rParam.nMode || !rParam.bLeft ) &&
2456  nDist >= rParam.nSide )
2457  break;
2458  }
2459  return true;
2460 }
2461 
2462 static bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
2463  SwTwips nDist, bool bCheck )
2464 {
2465  SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2466  for( auto pBox : rBoxes )
2467  {
2468  SwFrameFormat* pFormat = pBox->GetFrameFormat();
2469  const SwFormatFrameSize& rSz = pFormat->GetFrameSize();
2470  SwTwips nWidth = rSz.GetWidth();
2471 
2472  if( bCheck )
2473  {
2474  for( auto pLn : pBox->GetTabLines() )
2475  if( !::lcl_SetOtherBoxWidth( pLn, rParam, nDist, true ))
2476  return false;
2477 
2478  if( rParam.bBigger && ( TableChgMode::FixedWidthChangeAbs == rParam.nMode
2479  ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2480  : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2481  : nDist >= rParam.nSide - COLFUZZY )) )
2482  {
2483  SwTwips nDiff;
2484  if( TableChgMode::FixedWidthChangeProp == rParam.nMode ) // Table fixed, proportional
2485  {
2486  // calculate relative
2487  nDiff = nWidth;
2488  nDiff *= rParam.nDiff;
2489  nDiff /= rParam.nMaxSize;
2490  }
2491  else
2492  nDiff = rParam.nDiff;
2493 
2494  if( nWidth < nDiff || nWidth - nDiff < MINLAY )
2495  return false;
2496  }
2497  }
2498  else
2499  {
2500  SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
2501  for( auto pLn : pBox->GetTabLines() )
2502  {
2503  rParam.nLowerDiff = 0;
2504  lcl_SetOtherBoxWidth( pLn, rParam, nDist, false );
2505 
2506  if( nLowerDiff < rParam.nLowerDiff )
2507  nLowerDiff = rParam.nLowerDiff;
2508  }
2509  rParam.nLowerDiff = nOldLower;
2510 
2511  if( nLowerDiff ||
2512  ( TableChgMode::FixedWidthChangeAbs == rParam.nMode
2513  ? std::abs( nDist - rParam.nSide ) < COLFUZZY
2514  : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
2515  : nDist >= rParam.nSide - COLFUZZY)
2516  ) )
2517  {
2518  SwFormatFrameSize aNew( rSz );
2519 
2520  if( !nLowerDiff )
2521  {
2522  if( TableChgMode::FixedWidthChangeProp == rParam.nMode ) // Table fixed, proportional
2523  {
2524  // calculate relative
2525  nLowerDiff = nWidth;
2526  nLowerDiff *= rParam.nDiff;
2527  nLowerDiff /= rParam.nMaxSize;
2528  }
2529  else
2530  nLowerDiff = rParam.nDiff;
2531  }
2532 
2533  rParam.nLowerDiff += nLowerDiff;
2534 
2535  if( rParam.bBigger )
2536  aNew.SetWidth( nWidth - nLowerDiff );
2537  else
2538  aNew.SetWidth( nWidth + nLowerDiff );
2539 
2540  rParam.aShareFormats.SetSize( *pBox, aNew );
2541  }
2542  }
2543 
2544  nDist += nWidth;
2545  if( ( TableChgMode::FixedWidthChangeAbs == rParam.nMode || rParam.bLeft ) &&
2546  nDist > rParam.nSide )
2547  break;
2548  }
2549  return true;
2550 }
2551 
2552 static void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
2553 {
2554  SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2555  for( auto pBox : rBoxes )
2556  {
2557  SwFormatFrameSize aSz( pBox->GetFrameFormat()->GetFrameSize() );
2558  SwTwips nWidth = aSz.GetWidth();
2559  nWidth *= rParam.nDiff;
2560  nWidth /= rParam.nMaxSize;
2561  aSz.SetWidth( nWidth );
2562  rParam.aShareFormats.SetSize( *pBox, aSz );
2563 
2564  for( auto pLn : pBox->GetTabLines() )
2565  ::lcl_AjustLines( pLn, rParam );
2566  }
2567 }
2568 
2569 #ifdef DBG_UTIL
2570 void CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
2571 {
2572  const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
2573 
2574  SwTwips nCurrentSize = 0;
2575  // See if the tables have a correct width
2576  for (const SwTableBox* pBox : rBoxes)
2577  {
2578  const SwTwips nBoxW = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
2579  nCurrentSize += nBoxW;
2580 
2581  for( auto pLn : pBox->GetTabLines() )
2582  CheckBoxWidth( *pLn, nBoxW );
2583  }
2584 
2585  if (sal::static_int_cast< tools::ULong >(std::abs(nCurrentSize - nSize)) >
2586  (COLFUZZY * rBoxes.size()))
2587  {
2588  OSL_FAIL( "Line's Boxes are too small or too large" );
2589  }
2590 }
2591 #endif
2592 
2594  SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr<SwUndo>* ppUndo )
2595 {
2596  SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
2597 
2598  const SwFormatFrameSize& rSz = GetFrameFormat()->GetFrameSize();
2599  const SvxLRSpaceItem& rLR = GetFrameFormat()->GetLRSpace();
2600 
2601  std::unique_ptr<FndBox_> xFndBox; // for insertion/deletion
2602  bool bBigger,
2603  bRet = false,
2604  bLeft = TableChgWidthHeightType::ColLeft == extractPosition( eType ) ||
2606 
2607  // Get the current Box's edge
2608  // Only needed for manipulating the width
2609  const SwTwips nDist = ::lcl_GetDistance( &rCurrentBox, bLeft );
2610  SwTwips nDistStt = 0;
2611  CR_SetBoxWidth aParam( eType, nRelDiff, nDist,
2612  bLeft ? nDist : rSz.GetWidth() - nDist,
2613  const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode()) );
2614  bBigger = aParam.bBigger;
2615 
2616  FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
2617  fnSelBox = lcl_SetSelBoxWidth;
2618  fnOtherBox = lcl_SetOtherBoxWidth;
2619 
2620  switch( extractPosition(eType) )
2621  {
2624  if( TableChgMode::VarWidthChangeAbs == m_eTableChgMode )
2625  {
2626  // First test if we have room at all
2627  bool bChgLRSpace = true;
2628  if( bBigger )
2629  {
2630  if( GetFrameFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
2631  !rSz.GetWidthPercent() )
2632  {
2633  // silence -Wsign-compare on Android with the static cast
2634  bRet = rSz.GetWidth() < static_cast<unsigned short>(USHRT_MAX) - nRelDiff;
2635  bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
2636  : rLR.GetRight() >= nAbsDiff;
2637  }
2638  else
2639  bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
2640  : rLR.GetRight() >= nAbsDiff;
2641 
2642  if( !bRet )
2643  {
2644  // Then call itself recursively; only with another mode (proportional)
2645  TableChgMode eOld = m_eTableChgMode;
2646  m_eTableChgMode = TableChgMode::FixedWidthChangeProp;
2647 
2648  bRet = SetColWidth( rCurrentBox, eType, nAbsDiff, nRelDiff,
2649  ppUndo );
2650  m_eTableChgMode = eOld;
2651  return bRet;
2652  }
2653  }
2654  else
2655  {
2656  bRet = true;
2657  for( auto const & n: m_aLines )
2658  {
2659  aParam.LoopClear();
2660  if( !(*fnSelBox)( n, aParam, nDistStt, true ))
2661  {
2662  bRet = false;
2663  break;
2664  }
2665  }
2666  }
2667 
2668  if( bRet )
2669  {
2670  if( ppUndo )
2671  ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2672 
2673  tools::Long nFrameWidth = LONG_MAX;
2674  LockModify();
2675  SwFormatFrameSize aSz( rSz );
2676  SvxLRSpaceItem aLR( rLR );
2677  if( bBigger )
2678  {
2679  // If the Table does not have any room to grow, we need to create some!
2680  // silence -Wsign-compare on Android with the static cast
2681  if( aSz.GetWidth() + nRelDiff > static_cast<unsigned short>(USHRT_MAX) )
2682  {
2683  // Break down to USHRT_MAX / 2
2684  CR_SetBoxWidth aTmpPara( TableChgWidthHeightType::ColLeft, aSz.GetWidth() / 2,
2685  0, aSz.GetWidth(), aParam.pTableNd );
2686  for( size_t nLn = 0; nLn < m_aLines.size(); ++nLn )
2687  ::lcl_AjustLines( m_aLines[ nLn ], aTmpPara );
2688  aSz.SetWidth( aSz.GetWidth() / 2 );
2689  aParam.nDiff = nRelDiff /= 2;
2690  aParam.nSide /= 2;
2691  aParam.nMaxSize /= 2;
2692  }
2693 
2694  if( bLeft )
2695  aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
2696  else
2697  aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
2698  }
2699  else if( bLeft )
2700  aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
2701  else
2702  aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
2703 
2704  if( bChgLRSpace )
2705  GetFrameFormat()->SetFormatAttr( aLR );
2706  const SwFormatHoriOrient& rHOri = GetFrameFormat()->GetHoriOrient();
2707  if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
2708  (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
2709  (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
2710  {
2711  SwFormatHoriOrient aHOri( rHOri );
2713  GetFrameFormat()->SetFormatAttr( aHOri );
2714 
2715  // If the Table happens to contain relative values (USHORT_MAX),
2716  // we need to convert them to absolute ones now.
2717  // Bug 61494
2718  if( GetFrameFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE) &&
2719  !rSz.GetWidthPercent() )
2720  {
2721  SwTabFrame* pTabFrame = SwIterator<SwTabFrame,SwFormat>( *GetFrameFormat() ).First();
2722  if( pTabFrame &&
2723  pTabFrame->getFramePrintArea().Width() != rSz.GetWidth() )
2724  {
2725  nFrameWidth = pTabFrame->getFramePrintArea().Width();
2726  if( bBigger )
2727  nFrameWidth += nAbsDiff;
2728  else
2729  nFrameWidth -= nAbsDiff;
2730  }
2731  }
2732  }
2733 
2734  if( bBigger )
2735  aSz.SetWidth( aSz.GetWidth() + nRelDiff );
2736  else
2737  aSz.SetWidth( aSz.GetWidth() - nRelDiff );
2738 
2739  if( rSz.GetWidthPercent() )
2740  aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
2741  ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
2742 
2743  GetFrameFormat()->SetFormatAttr( aSz );
2744 
2745  UnlockModify();
2746 
2747  for( sal_uInt16 n = m_aLines.size(); n; )
2748  {
2749  --n;
2750  aParam.LoopClear();
2751  (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2752  }
2753 
2754  // If the Table happens to contain relative values (USHORT_MAX),
2755  // we need to convert them to absolute ones now.
2756  // Bug 61494
2757  if( LONG_MAX != nFrameWidth )
2758  {
2759  SwFormatFrameSize aAbsSz( aSz );
2760  aAbsSz.SetWidth( nFrameWidth );
2761  GetFrameFormat()->SetFormatAttr( aAbsSz );
2762  }
2763  }
2764  }
2765  else if( bLeft ? nDist != 0 : std::abs( rSz.GetWidth() - nDist ) > COLFUZZY )
2766  {
2767  bRet = true;
2768  if( bLeft && TableChgMode::FixedWidthChangeAbs == m_eTableChgMode )
2769  aParam.bBigger = !bBigger;
2770 
2771  // First test if we have room at all
2772  if( aParam.bBigger )
2773  {
2774  for( auto const & n: m_aLines )
2775  {
2776  aParam.LoopClear();
2777  if( !(*fnOtherBox)( n, aParam, 0, true ))
2778  {
2779  bRet = false;
2780  break;
2781  }
2782  }
2783  }
2784  else
2785  {
2786  for( auto const & n: m_aLines )
2787  {
2788  aParam.LoopClear();
2789  if( !(*fnSelBox)( n, aParam, nDistStt, true ))
2790  {
2791  bRet = false;
2792  break;
2793  }
2794  }
2795  }
2796 
2797  // If true, set it
2798  if( bRet )
2799  {
2800  CR_SetBoxWidth aParam1( aParam );
2801  if( ppUndo )
2802  ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2803 
2804  if( TableChgMode::FixedWidthChangeAbs != m_eTableChgMode && bLeft )
2805  {
2806  for( sal_uInt16 n = m_aLines.size(); n; )
2807  {
2808  --n;
2809  aParam.LoopClear();
2810  aParam1.LoopClear();
2811  (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2812  (*fnOtherBox)( m_aLines[ n ], aParam1, nDistStt, false );
2813  }
2814  }
2815  else
2816  {
2817  for( sal_uInt16 n = m_aLines.size(); n; )
2818  {
2819  --n;
2820  aParam.LoopClear();
2821  aParam1.LoopClear();
2822  (*fnOtherBox)( m_aLines[ n ], aParam1, nDistStt, false );
2823  (*fnSelBox)( m_aLines[ n ], aParam, nDistStt, false );
2824  }
2825  }
2826  }
2827  }
2828  break;
2829 
2832  if( TableChgMode::VarWidthChangeAbs == m_eTableChgMode )
2833  {
2834  // Then call itself recursively; only with another mode (proportional)
2835  TableChgMode eOld = m_eTableChgMode;
2836  m_eTableChgMode = TableChgMode::FixedWidthChangeAbs;
2837 
2838  bRet = SetColWidth( rCurrentBox, eType, nAbsDiff, nRelDiff,
2839  ppUndo );
2840  m_eTableChgMode = eOld;
2841  return bRet;
2842  }
2843  else if( bLeft ? nDist != 0 : (rSz.GetWidth() - nDist) > COLFUZZY )
2844  {
2845  if( bLeft && TableChgMode::FixedWidthChangeAbs == m_eTableChgMode )
2846  aParam.bBigger = !bBigger;
2847 
2848  // First, see if there is enough room at all
2849  SwTableBox* pBox = &rCurrentBox;
2850  SwTableLine* pLine = rCurrentBox.GetUpper();
2851  while( pLine->GetUpper() )
2852  {
2853  const SwTableBoxes::size_type nPos = pLine->GetBoxPos( pBox );
2854  if( bLeft ? nPos != 0 : nPos + 1 != pLine->GetTabBoxes().size() )
2855  break;
2856 
2857  pBox = pLine->GetUpper();
2858  pLine = pBox->GetUpper();
2859  }
2860 
2861  if( pLine->GetUpper() )
2862  {
2863  // We need to correct the distance once again!
2864  aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), true );
2865 
2866  if( bLeft )
2867  aParam.nMaxSize = aParam.nSide;
2868  else
2869  aParam.nMaxSize = pLine->GetUpper()->GetFrameFormat()->
2870  GetFrameSize().GetWidth() - aParam.nSide;
2871  }
2872 
2873  // First, see if there is enough room at all
2874  FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
2875  bRet = (*fnTmp)( pLine, aParam, nDistStt, true );
2876 
2877  // If true, set it
2878  if( bRet )
2879  {
2880  CR_SetBoxWidth aParam1( aParam );
2881  if( ppUndo )
2882  ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
2883 
2884  if( TableChgMode::FixedWidthChangeAbs != m_eTableChgMode && bLeft )
2885  {
2886  (*fnSelBox)( pLine, aParam, nDistStt, false );
2887  (*fnOtherBox)( pLine, aParam1, nDistStt, false );
2888  }
2889  else
2890  {
2891  (*fnOtherBox)( pLine, aParam1, nDistStt, false );
2892  (*fnSelBox)( pLine, aParam, nDistStt, false );
2893  }
2894  }
2895  }
2896  break;
2897  default: break;
2898  }
2899 
2900  if( xFndBox )
2901  {
2902  // Clean up the structure of all Lines
2903  GCLines();
2904 
2905  // Update Layout
2906  if( !bBigger || xFndBox->AreLinesToRestore( *this ) )
2907  xFndBox->MakeFrames( *this );
2908 
2909  // TL_CHART2: it is currently unclear if sth has to be done here.
2910  // The function name hints that nothing needs to be done, on the other
2911  // hand there is a case where sth gets deleted. :-(
2912 
2913  xFndBox.reset();
2914  }
2915 
2916 #if defined DBG_UTIL
2917  if( bRet )
2918  {
2921  }
2922 #endif
2923 
2924  return bRet;
2925 }
2926 
2927 static void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
2928  bool bMinSize )
2929 {
2930  SwLayoutFrame* pLineFrame = GetRowFrame( rLine );
2931  OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2932 
2933  SwFrameFormat* pFormat = rLine.ClaimFrameFormat();
2934 
2935  SwTwips nMyNewH, nMyOldH = pLineFrame->getFrameArea().Height();
2936  if( !nOldHeight ) // the BaseLine and absolute
2937  nMyNewH = nMyOldH + nNewHeight;
2938  else
2939  {
2940  // Calculate as exactly as possible
2941  Fraction aTmp( nMyOldH );
2942  aTmp *= Fraction( nNewHeight, nOldHeight );
2943  aTmp += Fraction( 1, 2 ); // round up if needed
2944  nMyNewH = tools::Long(aTmp);
2945  }
2946 
2948  if( !bMinSize &&
2949  ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrame ) + ROWFUZZY ))
2950  eSize = SwFrameSize::Fixed;
2951 
2952  pFormat->SetFormatAttr( SwFormatFrameSize( eSize, 0, nMyNewH ) );
2953 
2954  // First adapt all internal ones
2955  for( auto pBox : rLine.GetTabBoxes() )
2956  {
2957  for( auto pLine : pBox->GetTabLines() )
2958  SetLineHeight( *pLine, nMyOldH, nMyNewH, bMinSize );
2959  }
2960 }
2961 
2962 static bool lcl_SetSelLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
2963  SwTwips nDist, bool bCheck )
2964 {
2965  bool bRet = true;
2966  if( !bCheck )
2967  {
2968  // Set line height
2969  SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
2970  rParam.bBigger );
2971  }
2972  else if( !rParam.bBigger )
2973  {
2974  // Calculate the new relative size by means of the old one
2975  SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
2976  OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2977  SwTwips nRstHeight = CalcRowRstHeight( pLineFrame );
2978  if( (nRstHeight + ROWFUZZY) < nDist )
2979  bRet = false;
2980  }
2981  return bRet;
2982 }
2983 
2984 static bool lcl_SetOtherLineHeight( SwTableLine* pLine, const CR_SetLineHeight& rParam,
2985  SwTwips nDist, bool bCheck )
2986 {
2987  bool bRet = true;
2988  if( bCheck )
2989  {
2990  if( rParam.bBigger )
2991  {
2992  // Calculate the new relative size by means of the old one
2993  SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
2994  OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine?" );
2995 
2996  if( TableChgMode::FixedWidthChangeProp == rParam.nMode )
2997  {
2998  nDist *= pLineFrame->getFrameArea().Height();
2999  nDist /= rParam.nMaxHeight;
3000  }
3001  bRet = nDist <= CalcRowRstHeight( pLineFrame );
3002  }
3003  }
3004  else
3005  {
3006  // Set line height
3007  // pLine is the following/preceding, thus adjust it
3008  if( TableChgMode::FixedWidthChangeProp == rParam.nMode )
3009  {
3010  SwLayoutFrame* pLineFrame = GetRowFrame( *pLine );
3011  OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine??" );
3012 
3013  // Calculate the new relative size by means of the old one
3014  // If the selected Box get bigger, adjust via the max space else
3015  // via the max height.
3016  if( (true) )
3017  {
3018  nDist *= pLineFrame->getFrameArea().Height();
3019  nDist /= rParam.nMaxHeight;
3020  }
3021  else
3022  {
3023  // Calculate the new relative size by means of the old one
3024  nDist *= CalcRowRstHeight( pLineFrame );
3025  nDist /= rParam.nMaxSpace;
3026  }
3027  }
3028  SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
3029  !rParam.bBigger );
3030  }
3031  return bRet;
3032 }
3033 
3035  SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr<SwUndo>* ppUndo )
3036 {
3037  SwTableLine* pLine = rCurrentBox.GetUpper();
3038 
3039  SwTableLine* pBaseLine = pLine;
3040  while( pBaseLine->GetUpper() )
3041  pBaseLine = pBaseLine->GetUpper()->GetUpper();
3042 
3043  std::unique_ptr<FndBox_> xFndBox; // for insertion/deletion
3044  bool bBigger,
3045  bRet = false,
3047  sal_uInt16 nBaseLinePos = GetTabLines().GetPos( pBaseLine );
3048 
3049  CR_SetLineHeight aParam( eType,
3050  const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode()) );
3051  bBigger = aParam.bBigger;
3052 
3053  SwTableLines* pLines = &m_aLines;
3054 
3055  // How do we get to the height?
3056  switch( extractPosition(eType) )
3057  {
3060  if( pLine == pBaseLine )
3061  break; // it doesn't work then!
3062 
3063  // Is a nested Line (Box!)
3064  pLines = &pLine->GetUpper()->GetTabLines();
3065  nBaseLinePos = pLines->GetPos( pLine );
3066  [[fallthrough]];
3067 
3069  {
3070  if( TableChgMode::VarWidthChangeAbs == m_eTableChgMode )
3071  {
3072  // First test if we have room at all
3073  if( bBigger )
3074  bRet = true;
3075  else
3076  bRet = lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3077  nAbsDiff, true );
3078 
3079  if( bRet )
3080  {
3081  if( ppUndo )
3082  ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
3083 
3084  lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3085  nAbsDiff, false );
3086  }
3087  }
3088  else
3089  {
3090  bRet = true;
3093  if( bTop )
3094  {
3095  nStt = 0;
3096  nEnd = nBaseLinePos;
3097  }
3098  else
3099  {
3100  nStt = nBaseLinePos + 1;
3101  nEnd = pLines->size();
3102  }
3103 
3104  // Get the current Lines' height
3105  if( TableChgMode::FixedWidthChangeProp == m_eTableChgMode )
3106  {
3107  for( auto n = nStt; n < nEnd; ++n )
3108  {
3109  SwLayoutFrame* pLineFrame = GetRowFrame( *(*pLines)[ n ] );
3110  OSL_ENSURE( pLineFrame, "Where is the Frame from the SwTableLine??" );
3111  aParam.nMaxSpace += CalcRowRstHeight( pLineFrame );
3112  aParam.nMaxHeight += pLineFrame->getFrameArea().Height();
3113  }
3114  if( bBigger && aParam.nMaxSpace < nAbsDiff )
3115  bRet = false;
3116  }
3117  else
3118  {
3119  if( bTop ? nEnd != 0 : nStt < nEnd )
3120  {
3121  if( bTop )
3122  nStt = nEnd - 1;
3123  else
3124  nEnd = nStt + 1;
3125  }
3126  else
3127  bRet = false;
3128  }
3129 
3130  if( bRet )
3131  {
3132  if( bBigger )
3133  {
3134  for( auto n = nStt; n < nEnd; ++n )
3135  {
3136  if( !lcl_SetOtherLineHeight( (*pLines)[ n ], aParam,
3137  nAbsDiff, true ))
3138  {
3139  bRet = false;
3140  break;
3141  }
3142  }
3143  }
3144  else
3145  bRet = lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3146  nAbsDiff, true );
3147  }
3148 
3149  if( bRet )
3150  {
3151  // Adjust
3152  if( ppUndo )
3153  ppUndo->reset(new SwUndoAttrTable( *aParam.pTableNd, true ));
3154 
3155  CR_SetLineHeight aParam1( aParam );
3156 
3157  if( bTop )
3158  {
3159  lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3160  nAbsDiff, false );
3161  for( auto n = nStt; n < nEnd; ++n )
3162  lcl_SetOtherLineHeight( (*pLines)[ n ], aParam1,
3163  nAbsDiff, false );
3164  }
3165  else
3166  {
3167  for( auto n = nStt; n < nEnd; ++n )
3168  lcl_SetOtherLineHeight( (*pLines)[ n ], aParam1,
3169  nAbsDiff, false );
3170  lcl_SetSelLineHeight( (*pLines)[ nBaseLinePos ], aParam,
3171  nAbsDiff, false );
3172  }
3173  }
3174  else
3175  {
3176  // Then call itself recursively; only with another mode (proportional)
3177  TableChgMode eOld = m_eTableChgMode;
3178  m_eTableChgMode = TableChgMode::VarWidthChangeAbs;
3179 
3180  bRet = SetRowHeight( rCurrentBox, eType, nAbsDiff,
3181  nRelDiff, ppUndo );
3182 
3183  m_eTableChgMode = eOld;
3184  xFndBox.reset();
3185  }
3186  }
3187  }
3188  break;
3189  default: break;
3190  }
3191 
3192  if( xFndBox )
3193  {
3194  // then clean up the structure of all Lines
3195  GCLines();
3196 
3197  // Update Layout
3198  if( bBigger || xFndBox->AreLinesToRestore( *this ) )
3199  xFndBox->MakeFrames( *this );
3200 
3201  // TL_CHART2: it is currently unclear if sth has to be done here.
3202 
3203  xFndBox.reset();
3204  }
3205 
3207 
3208  return bRet;
3209 }
3210 
3212 {
3213  SwFrameFormat *pRet = nullptr, *pTmp;
3214  for( auto n = m_aNewFormats.size(); n; )
3215  if( ( pTmp = m_aNewFormats[ --n ])->GetFrameSize().GetWidth()
3216  == nWidth )
3217  {
3218  pRet = pTmp;
3219  break;
3220  }
3221  return pRet;
3222 }
3223 
3225 {
3226  const SfxPoolItem* pItem;
3227  sal_uInt16 nWhich = rItem.Which();
3228  SwFrameFormat *pRet = nullptr, *pTmp;
3229  const SfxPoolItem& rFrameSz = m_pOldFormat->GetFormatAttr( RES_FRM_SIZE, false );
3230  for( auto n = m_aNewFormats.size(); n; )
3231  if( SfxItemState::SET == ( pTmp = m_aNewFormats[ --n ])->
3232  GetItemState( nWhich, false, &pItem ) && *pItem == rItem &&
3233  pTmp->GetFormatAttr( RES_FRM_SIZE, false ) == rFrameSz )
3234  {
3235  pRet = pTmp;
3236  break;
3237  }
3238  return pRet;
3239 }
3240 
3242 {
3243  m_aNewFormats.push_back( &rNew );
3244 }
3245 
3247 {
3248  // returns true, if we can delete
3249  if( m_pOldFormat == &rFormat )
3250  return true;
3251 
3252  std::vector<SwFrameFormat*>::iterator it = std::find( m_aNewFormats.begin(), m_aNewFormats.end(), &rFormat );
3253  if( m_aNewFormats.end() != it )
3254  m_aNewFormats.erase( it );
3255  return m_aNewFormats.empty();
3256 }
3257 
3259 {
3260 }
3261 
3263 {
3264  sal_uInt16 nPos;
3265  return Seek_Entry( rFormat, &nPos )
3266  ? m_ShareArr[ nPos ]->GetFormat(nWidth)
3267  : nullptr;
3268 }
3270  const SfxPoolItem& rItem ) const
3271 {
3272  sal_uInt16 nPos;
3273  return Seek_Entry( rFormat, &nPos )
3274  ? m_ShareArr[ nPos ]->GetFormat(rItem)
3275  : nullptr;
3276 }
3277 
3279 {
3280  sal_uInt16 nPos;
3281  SwShareBoxFormat* pEntry;
3282  if( !Seek_Entry( rOld, &nPos ))
3283  {
3284  pEntry = new SwShareBoxFormat( rOld );
3285  m_ShareArr.insert(m_ShareArr.begin() + nPos, std::unique_ptr<SwShareBoxFormat>(pEntry));
3286  }
3287  else
3288  pEntry = m_ShareArr[ nPos ].get();
3289 
3290  pEntry->AddFormat( rNew );
3291 }
3292 
3294  SwFrameFormat& rFormat )
3295 {
3296  SwClient aCl;
3297  SwFrameFormat* pOld = nullptr;
3298  if( pBox )
3299  {
3300  pOld = pBox->GetFrameFormat();
3301  pOld->Add( &aCl );
3302  pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(&rFormat) );
3303  }
3304  else if( pLn )
3305  {
3306  pOld = pLn->GetFrameFormat();
3307  pOld->Add( &aCl );
3308  pLn->ChgFrameFormat( static_cast<SwTableLineFormat*>(&rFormat) );
3309  }
3310  if( pOld && pOld->HasOnlyOneListener() )
3311  {
3312  RemoveFormat( *pOld );
3313  delete pOld;
3314  }
3315 }
3316 
3318 {
3319  SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
3320  *pRet = GetFormat( *pBoxFormat, rSz.GetWidth() );
3321  if( pRet )
3322  ChangeFrameFormat( &rBox, nullptr, *pRet );
3323  else
3324  {
3325  pRet = rBox.ClaimFrameFormat();
3326  pRet->SetFormatAttr( rSz );
3327  AddFormat( *pBoxFormat, *pRet );
3328  }
3329 }
3330 
3332 {
3333  SwFrameFormat *pBoxFormat = rBox.GetFrameFormat(),
3334  *pRet = GetFormat( *pBoxFormat, rItem );
3335  if( pRet )
3336  ChangeFrameFormat( &rBox, nullptr, *pRet );
3337  else
3338  {
3339  pRet = rBox.ClaimFrameFormat();
3340  pRet->SetFormatAttr( rItem );
3341  AddFormat( *pBoxFormat, *pRet );
3342  }
3343 }
3344 
3346 {
3347  SwFrameFormat *pLineFormat = rLine.GetFrameFormat(),
3348  *pRet = GetFormat( *pLineFormat, rItem );
3349  if( pRet )
3350  ChangeFrameFormat( nullptr, &rLine, *pRet );
3351  else
3352  {
3353  pRet = rLine.ClaimFrameFormat();
3354  pRet->SetFormatAttr( rItem );
3355  AddFormat( *pLineFormat, *pRet );
3356  }
3357 }
3358 
3360 {
3361  for (auto i = m_ShareArr.size(); i; )
3362  {
3363  if (m_ShareArr[ --i ]->RemoveFormat(rFormat))
3364  {
3365  m_ShareArr.erase( m_ShareArr.begin() + i );
3366  }
3367  }
3368 }
3369 
3370 bool SwShareBoxFormats::Seek_Entry( const SwFrameFormat& rFormat, sal_uInt16* pPos ) const
3371 {
3372  sal_uIntPtr nIdx = reinterpret_cast<sal_uIntPtr>(&rFormat);
3373  auto nO = m_ShareArr.size();
3374  decltype(nO) nU = 0;
3375  if( nO > 0 )
3376  {
3377  nO--;
3378  while( nU <= nO )
3379  {
3380  const auto nM = nU + ( nO - nU ) / 2;
3381  sal_uIntPtr nFormat = reinterpret_cast<sal_uIntPtr>(&m_ShareArr[ nM ]->GetOldFormat());
3382  if( nFormat == nIdx )
3383  {
3384  if( pPos )
3385  *pPos = nM;
3386  return true;
3387  }
3388  else if( nFormat < nIdx )
3389  nU = nM + 1;
3390  else if( nM == 0 )
3391  {
3392  if( pPos )
3393  *pPos = nU;
3394  return false;
3395  }
3396  else
3397  nO = nM - 1;
3398  }
3399  }
3400  if( pPos )
3401  *pPos = nU;
3402  return false;
3403 }
3404 
3405 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void AddRowCols(const SwTable &rTable, const SwSelBoxes &rBoxes, sal_uInt16 nLines, bool bBehind)
SwChartDataProvider::AddRowCols tries to notify charts of added columns or rows and extends the value...
Definition: unochart.cxx:1548
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:240
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:686
Starts a section of nodes in the document model.
Definition: node.hxx:312
std::vector< SwTableLine * >::size_type size_type
Definition: swtable.hxx:67
const FndLines_t & GetLines() const
Definition: tblsel.hxx:173
tools::Long GetWidth() const
const SwTableLine * GetLine() const
Definition: tblsel.hxx:205
const_iterator lower_bound(const Value &x) const
sal_uLong GetIndex() const
Definition: node.hxx:291
void Add(SwClient *pDepend)
Definition: calbck.cxx:171
void SetRight(const tools::Long nR, const sal_uInt16 nProp=100)
void SetRowsToRepeat(sal_uInt16 nNumOfRows)
Definition: swtable.hxx:196
Marks a position in the document model.
Definition: pam.hxx:35
static SwTwips lcl_GetDistance(SwTableBox *pBox, bool bLeft)
Definition: tblrwcl.cxx:2338
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2443
static void lcl_CopyLineToDoc(FndLine_ const &rpFndLn, CpyPara *const pCpyPara)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1866
SwDocShell * GetDocShell()
Definition: doc.hxx:1353
std::string GetValue
static void lcl_CopyCol(FndBox_ &rFndBox, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:248
static void lcl_CpyLines(sal_uInt16 nStt, sal_uInt16 nEnd, SwTableLines &rLines, SwTableBox *pInsBox, sal_uInt16 nPos=USHRT_MAX)
Definition: tblrwcl.cxx:1275
static void lcl_LastBoxSetWidth(SwTableBoxes &rBoxes, const tools::Long nOffset, bool bFirst, SwShareBoxFormats &rShareFormats)
Definition: tblrwcl.cxx:625
SwNodeIndex nNode
Definition: pam.hxx:37
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
sal_uIntPtr sal_uLong
#define ROWFUZZY
Definition: tblrwcl.cxx:65
long Long
tools::Long GetRight() const
const SwRect & getFramePrintArea() const
Definition: frame.hxx:179
#define MINLAY
Definition: swtypes.hxx:66
bool AreLinesToRestore(const SwTable &rTable) const
Definition: tblsel.cxx:2546
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
virtual void CreateChartInternalDataProviders(const SwTable *pTable)=0
calls createInternalDataProvider for all charts using the specified table
SwFrameFormat * GetFormat(tools::Long nWidth) const
Definition: tblrwcl.cxx:3211
sal_Int64 n
Definition: doc.hxx:187
constexpr sal_uInt16 RES_FRMATR_END(133)
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1466
constexpr sal_uInt16 RES_BOXATR_END(153)
void setDummyFlag(bool bDummy)
Definition: swtable.cxx:90
void DelFrames(SwTable &rTable)
Definition: tblsel.cxx:2172
bool OldSplitRow(SwDoc &, const SwSelBoxes &, sal_uInt16, bool)
Definition: tblrwcl.cxx:1009
TableChgWidthHeightType
Definition: tblenum.hxx:25
const_iterator find(const Value &x) const
virtual bool HasExtraRedlineTable() const =0
SwTableLine is one table row in the document model.
Definition: swtable.hxx:351
SwNode & GetNode() const
Definition: ndindex.hxx:119
SwFrameFormat * GetFormat(const SwFrameFormat &rFormat, tools::Long nWidth) const
Definition: tblrwcl.cxx:3262
static sal_uInt16 lcl_GetLineWidth(const FndLine_ &rLine)
Definition: tblrwcl.cxx:1688
iterator begin()
Definition: swtable.hxx:76
void CheckSectionCondColl() const
Call ChkCondcoll to all ContentNodes of section.
Definition: node.cxx:975
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(152)
const editeng::SvxBorderLine * GetRight() const
SwTableLine * front() const
Definition: swtable.hxx:80
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
bool OldMerge(SwDoc *, const SwSelBoxes &, SwTableBox *, SwUndoTableMerge *)
Definition: tblrwcl.cxx:1520
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:203
void SetValues(bool bFlag)
Definition: tblrwcl.hxx:97
Value in Var-direction gives minimum (can be exceeded but not be less).
static bool lcl_SetOtherLineHeight(SwTableLine *pLine, const CR_SetLineHeight &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2984
size_type size() const
Definition: swtable.hxx:75
void UpdateCharts(std::u16string_view rName) const
Definition: docchart.cxx:120
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
This creates a structure mirroring the SwTable structure that contains all rows and non-leaf boxes (a...
Definition: tblsel.cxx:2104
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
sal_Int32 getRowSpan() const
Definition: swtable.cxx:75
SwTableBox * FindNextBox(const SwTable &, const SwTableBox *=nullptr, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2195
SwTableLine * back() const
Definition: swtable.hxx:81
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
void Delete(const SwNodeIndex &rPos, sal_uLong nNodes=1)
delete nodes
Definition: nodes.cxx:1078
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1499
void SetHoriOrient(sal_Int16 eNew)
Definition: fmtornt.hxx:89
bool UpdateTableStyleFormatting(SwTableNode *pTableNode=nullptr, bool bResetDirect=false, OUString const *pStyleName=nullptr)
Update the direct formatting according to the current table style.
Definition: fetab.cxx:1201
const SwRect & getFrameArea() const
Definition: frame.hxx:178
void AddFormat(SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3241
static void lcl_CheckRowSpan(SwTable &rTable)
Definition: tblrwcl.cxx:1642
void sw_LineSetHeadCondColl(const SwTableLine *pLine)
Definition: tblrwcl.cxx:2332
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
static void SetLineHeight(SwTableLine &rLine, SwTwips nOldHeight, SwTwips nNewHeight, bool bMinSize)
Definition: tblrwcl.cxx:2927
int nCount
virtual void UpdateTableFields(SfxPoolItem *pHt)=0
static void lcl_Merge_MoveBox(FndBox_ &rFndBox, InsULPara *const pULPara)
Definition: tblrwcl.cxx:1352
virtual void SetName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2471
void Width(tools::Long nNew)
Definition: swrect.hxx:187
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:203
iterator insert(iterator aIt, SwTableLine *pLine)
Definition: swtable.hxx:85
SwTextFormatColl * CopyTextColl(const SwTextFormatColl &rColl)
copy TextNodes
Definition: docfmt.cxx:1164
void CopyHeadlineIntoTable(SwTableNode &rTableNd)
Definition: tblrwcl.cxx:2001
const SwTable & GetTable() const
Definition: node.hxx:501
virtual void DeleteSection(SwNode *pNode)=0
Delete section containing the node.
static void lcl_Merge_MoveLine(FndLine_ &rFndLine, InsULPara *const pULPara)
Definition: tblrwcl.cxx:1417
o3tl::sorted_vector< CpyTabFrame > CpyTabFrames
Definition: tblrwcl.cxx:199
const OUString & GetTableStyleName() const
Return the table style name of this table.
Definition: swtable.hxx:190
bool Seek_Entry(const SwFrameFormat &rFormat, sal_uInt16 *pPos) const
Definition: tblrwcl.cxx:3370
SwTableBox * FindPreviousBox(const SwTable &, const SwTableBox *) const
Definition: tblrwcl.cxx:2313
static void lcl_CalcWidth(SwTableBox *pBox)
Definition: tblrwcl.cxx:1301
bool HasOnlyOneListener() const
Definition: calbck.hxx:198
bool SplitCol(SwDoc &rDoc, const SwSelBoxes &rBoxes, sal_uInt16 nCnt)
Definition: tblrwcl.cxx:1152
size_type size() const
void sw_BoxSetSplitBoxFormats(SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3022
void MakeFrames(SwTable &rTable)
Definition: tblsel.cxx:2333
static void lcl_CpyBoxes(sal_uInt16 nStt, sal_uInt16 nEnd, SwTableBoxes &rBoxes, SwTableLine *pInsLine)
Definition: tblrwcl.cxx:1289
static void lcl_LastBoxSetWidthLine(SwTableLines &rLines, const tools::Long nOffset, bool bFirst, SwShareBoxFormats &rShareFormats)
Definition: tblrwcl.cxx:618
DocumentType eType
Class for SplitTable Collects the uppermost or lowermost Lines of a Box from a Line in an array...
Definition: tblrwcl.hxx:61
void InsTableBox(SwDoc &rDoc, SwTableNode *pTableNd, SwTableLine *pLine, SwTableBoxFormat *pBoxFrameFormat, SwTableBox *pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Definition: swtable.cxx:130
#define CHECKTABLELAYOUT
Definition: tblrwcl.cxx:142
Table of Contents - heading.
Definition: poolfmt.hxx:342
const editeng::SvxBorderLine * GetTop() const
void SetSize(SwTableBox &rBox, const SwFormatFrameSize &rSz)
Definition: tblrwcl.cxx:3317
bool SetColWidth(SwTableBox &rCurrentBox, TableChgWidthHeightType eType, SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr< SwUndo > *ppUndo)
Definition: tblrwcl.cxx:2593
Style of a layout element.
Definition: frmfmt.hxx:58
bool(* FN_lcl_SetBoxWidth)(SwTableLine *, CR_SetBoxWidth &, SwTwips, bool)
Definition: tblrwcl.cxx:131
virtual const SwExtraRedlineTable & GetExtraRedlineTable() const =0
const editeng::SvxBorderLine * GetLeft() const
static SwRowFrame * GetRowFrame(SwTableLine &rLine)
Definition: tblrwcl.cxx:443
void SetTableLines(const SwSelBoxes &rBoxes, const SwTable &rTable)
Definition: tblsel.cxx:2110
int i
void RemoveFormat(const SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3359
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:132
SwDoc & GetDoc()
Definition: node.hxx:212
bool empty() const
Definition: swtable.hxx:74
bool DeleteSel(SwDoc *, const SwSelBoxes &rBoxes, const SwSelBoxes *pMerged, SwUndo *pUndo, const bool bDelMakeFrames, const bool bCorrBorder)
Definition: tblrwcl.cxx:934
void CheckBoxWidth(const SwTableLine &rLine, SwTwips nSize)
Definition: tblrwcl.cxx:2570
virtual SwChartDataProvider * GetChartDataProvider(bool bCreate=false) const =0
returns or creates the data-provider for chart
::sw::DocumentContentOperationsManager const & GetDocumentContentOperationsManager() const
Definition: doc.cxx:325
void AddFormat(const SwFrameFormat &rOld, SwFrameFormat &rNew)
Definition: tblrwcl.cxx:3278
static void lcl_BoxSetHeadCondColl(const SwTableBox *pBox)
Definition: tblrwcl.cxx:2321
tools::Long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1378
void SetSelBoxes(const SwSelBoxes &rBoxes)
Definition: untbl.cxx:2002
tools::Long GetLeft() const
bool DeleteTableRowRedline(SwDoc *pDoc, const SwTableLine &rTableLine, bool bSaveInUndo, RedlineType nRedlineTypeToDelete)
Definition: docredln.cxx:209
static bool lcl_SetSelLineHeight(SwTableLine *pLine, const CR_SetLineHeight &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2962
static SwTableBox * lcl_FndNxtPrvDelBox(const SwTableLines &rTableLns, SwTwips nBoxStt, SwTwips nBoxWidth, sal_uInt16 nLinePos, bool bNxt, SwSelBoxes *pAllDelBoxes, size_t *const pCurPos)
Definition: tblrwcl.cxx:802
void UnlockModify()
Definition: calbck.hxx:204
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:87
void LockModify()
Definition: calbck.hxx:203
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:373
bool SetRowHeight(SwTableBox &rCurrentBox, TableChgWidthHeightType eType, SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr< SwUndo > *ppUndo)
Definition: tblrwcl.cxx:3034
size
void MakeOwnFrames(SwNodeIndex *pIdxBehind)
Creates the frms for the table node (i.e. the TabFrames).
Definition: ndtbl.cxx:2404
constexpr sal_uInt16 RES_BOXATR_BEGIN(RES_GRFATR_END)
SwFrameSize
Definition: fmtfsize.hxx:35
Marks a node in the document model.
Definition: ndindex.hxx:31
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:431
const_iterator end() const
bool HasMergeFormatTable() const
bool empty() const
static bool lcl_SetSelBoxWidth(SwTableLine *pLine, CR_SetBoxWidth &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2362
#define CHECK_TABLE(t)
Definition: tblrwcl.cxx:68
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:123
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
IDocumentChartDataProviderAccess const & getIDocumentChartDataProviderAccess() const
Definition: doc.cxx:227
SwTableBox * FindPreviousBox(const SwTable &, const SwTableBox *=nullptr, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2246
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:363
bool IsInReading() const
Definition: doc.hxx:955
Frame cannot be moved in Var-direction.
SwTableLines & GetTabLines()
Definition: swtable.hxx:200
tools::Long SwTwips
Definition: swtypes.hxx:49
static void lcl_AjustLines(SwTableLine *pLine, CR_SetBoxWidth &rParam)
Definition: tblrwcl.cxx:2552
const long LONG_MAX
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:111
void SetWidth(tools::Long n)
SwTableLines & GetTabLines()
Definition: swtable.hxx:424
static sal_uInt16 lcl_GetBoxOffset(const FndBox_ &rBox)
Definition: tblrwcl.cxx:1663
const_iterator begin() const
#define COLFUZZY
Definition: tblrwcl.cxx:64
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:450
void SetTableChgMode(TableChgMode eMode)
Definition: swtable.hxx:333
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:681
void MakeNewFrames(SwTable &rTable, const sal_uInt16 nNumber, const bool bBehind)
Definition: tblsel.cxx:2406
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:361
static void lcl_InsCol(FndLine_ *pFndLn, CpyPara &rCpyPara, sal_uInt16 nCpyCnt, bool bBehind)
Definition: tblrwcl.cxx:406
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:104
static void lcl_SaveUpperLowerBorder(SwTable &rTable, const SwTableBox &rBox, SwShareBoxFormats &rShareFormats, SwSelBoxes *pAllDelBoxes=nullptr, size_t *const pCurPos=nullptr)
Definition: tblrwcl.cxx:862
std::vector< std::unique_ptr< FndBox_ > > FndBoxes_t
Definition: tblsel.hxx:152
void sw_Box_CollectBox(const SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3004
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:445
static void lcl_CopyBoxToDoc(FndBox_ const &rFndBox, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:1785
bool operator<(TypeDescription const &left, TypeDescription const &right)
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:1726
void GCLines()
Definition: gctable.cxx:454
bool(* FN_lcl_SetLineHeight)(SwTableLine *, CR_SetLineHeight &, SwTwips, bool)
Definition: tblrwcl.cxx:197
void SetLeft(const tools::Long nL, const sal_uInt16 nProp=100)
void CopyAttrs(const SwFormat &)
Copy attributes even among documents.
Definition: format.cxx:174
void ChangeFrameFormat(SwTableBox *pBox, SwTableLine *pLn, SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3293
unsigned char sal_uInt8
void CopyWithFlyInFly(const SwNodeRange &rRg, const SwNodeIndex &rInsPos, const std::pair< const SwPaM &, const SwPosition & > *pCopiedPaM=nullptr, bool bMakeNewFrames=true, bool bDelRedlines=true, bool bCopyFlyAtFly=false, SwCopyFlags flags=SwCopyFlags::Default) const
note: rRg/rInsPos exclude a partially selected start text node; pCopiedPaM includes a partially selec...
sal_uInt32 GetMergeFormatIndex(sal_uInt32 nOldFmt) const
virtual SwFieldType * InsertFieldType(const SwFieldType &)=0
void SetWidthPercent(sal_uInt8 n)
Definition: fmtfsize.hxx:95
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
void SetTableStyleName(const OUString &rName)
Set the new table style name for this table.
Definition: swtable.hxx:193
const SwTableBox * GetBox() const
Definition: tblsel.hxx:175
bool InsertCol(SwDoc &, const SwSelBoxes &rBoxes, sal_uInt16 nCnt, bool bBehind)
Definition: tblrwcl.cxx:452
SwNodes & GetNodes()
Definition: doc.hxx:408
virtual SwTextFormatColl * GetTextCollFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return "Auto-Collection with ID.
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(151)
static bool lcl_SetOtherBoxWidth(SwTableLine *pLine, CR_SetBoxWidth &rParam, SwTwips nDist, bool bCheck)
Definition: tblrwcl.cxx:2462
bool MakeCopy(SwDoc &, const SwPosition &, const SwSelBoxes &, bool bCpyName=false) const
Definition: tblrwcl.cxx:2046
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:392
void SetAttr(SwTableBox &rBox, const SfxPoolItem &rItem)
Definition: tblrwcl.cxx:3331
static void lcl_CopyRow(FndLine_ &rFndLine, CpyPara *const pCpyPara)
Definition: tblrwcl.cxx:381
constexpr TableChgWidthHeightType extractPosition(TableChgWidthHeightType e)
Definition: tblenum.hxx:42
constexpr TypedWhichId< SvxLRSpaceItem > RES_LR_SPACE(91)
bool Resize(sal_uInt16 nOffset, sal_uInt16 nWidth)
Definition: ndtbl.cxx:2953
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1690
SvxBoxItem & rBoxItem
#define CHECKBOXWIDTH
Definition: tblrwcl.cxx:135
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
SwFEShell * GetFEShell()
For Core - it knows the DocShell but not the WrtShell!
Definition: docsh.cxx:1211
std::vector< std::unique_ptr< FndLine_ > > FndLines_t
Definition: tblsel.hxx:155
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:357
SwTableBox * GetUpper()
Definition: swtable.hxx:369
bool RemoveFormat(const SwFrameFormat &rFormat)
Definition: tblrwcl.cxx:3246
void DeleteBox_(SwTable &rTable, SwTableBox *pBox, SwUndo *pUndo, bool bCalcNewSize, const bool bCorrBorder, SwShareBoxFormats *pShareFormats)
Definition: tblrwcl.cxx:652
void SetUpper(SwTableLine *pNew)
Definition: swtable.hxx:429
SwTableBox * FindNextBox(const SwTable &, const SwTableBox *, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2302
static void lcl_CalcNewWidths(const FndLines_t &rFndLines, CpyPara &rPara)
Definition: tblrwcl.cxx:1699
void setRowSpan(sal_Int32 nNewRowSpan)
Definition: swtable.cxx:80
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:97
TableChgMode
Definition: tblenum.hxx:46
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
void AddNewBox(sal_uLong nSttNdIdx)
Definition: UndoTable.hxx:232
bool DeleteTableCellRedline(SwDoc *pDoc, const SwTableBox &rTableBox, bool bSaveInUndo, RedlineType nRedlineTypeToDelete)
Definition: docredln.cxx:253
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:120
TableFormulaUpdateFlags m_eFlags
Definition: hints.hxx:250
Frame is variable in Var-direction.
const FndLine_ * GetUpper() const
Definition: tblsel.hxx:177
void SetNewTable(std::unique_ptr< SwTable >, bool bNewFrames=true)
Definition: ndtbl.cxx:2483
std::pair< const_iterator, bool > insert(Value &&x)
void DeleteBox(const SwTable *pTable, const SwTableBox &rBox)
Definition: unochart.cxx:1447
std::vector< Value >::size_type size_type
Subgroup table.
Definition: poolfmt.hxx:341
bool IsNewModel() const
Definition: swtable.hxx:187
SwTableLine * GetUpper()
Definition: swtable.hxx:427
const SwTable * InsertTable(const SwInsertTableOptions &rInsTableOpts, const SwPosition &rPos, sal_uInt16 nRows, sal_uInt16 nCols, sal_Int16 eAdjust, const SwTableAutoFormat *pTAFormat=nullptr, const std::vector< sal_uInt16 > *pColArr=nullptr, bool bCalledFromShell=false, bool bNewModel=true)
Insert new table at position.
Definition: ndtbl.cxx:337
void SetHeightSizeType(SwFrameSize eSize)
Definition: fmtfsize.hxx:81
void Height(tools::Long nNew)
Definition: swrect.hxx:191
bool operator==(const ScCsvLayoutData &rData1, const ScCsvLayoutData &rData2)
bool InsertRow_(SwDoc *, const SwSelBoxes &, sal_uInt16 nCnt, bool bBehind)
Definition: tblrwcl.cxx:511
const editeng::SvxBorderLine * GetBottom() const
bool IsDelBox() const
Definition: undobj.cxx:182
TableChgMode GetTableChgMode() const
Definition: swtable.hxx:332
sal_uInt16 Which() const
sal_uInt16 nPos
iterator erase(iterator aIt)
Definition: swtable.hxx:83
std::vector< Value >::const_iterator const_iterator
size_type erase(const Value &x)
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, const SwNodeIndex &, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:400
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)
SwTwips CalcRowRstHeight(SwLayoutFrame *pRow)
Definition: frmtool.cxx:3646
Base class of the Writer document model elements.
Definition: node.hxx:80