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