LibreOffice Module sw (master)  1
tblsel.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 <editeng/boxitem.hxx>
21 #include <editeng/protitem.hxx>
22 
23 #include <hintids.hxx>
24 #include <fmtanchr.hxx>
25 #include <fmtfsize.hxx>
26 #include <frmatr.hxx>
27 #include <tblsel.hxx>
28 #include <crsrsh.hxx>
29 #include <doc.hxx>
30 #include <IDocumentUndoRedo.hxx>
32 #include <docary.hxx>
33 #include <pam.hxx>
34 #include <ndtxt.hxx>
35 #include <swtable.hxx>
36 #include <cntfrm.hxx>
37 #include <tabfrm.hxx>
38 #include <rowfrm.hxx>
39 #include <cellfrm.hxx>
40 #include <rootfrm.hxx>
41 #include <viscrs.hxx>
42 #include <swtblfmt.hxx>
43 #include <UndoTable.hxx>
44 #include <sectfrm.hxx>
45 #include <frmtool.hxx>
46 #include <calbck.hxx>
47 #include <frameformats.hxx>
48 #include <deque>
49 #include <memory>
50 
51 // see also swtable.cxx
52 #define COLFUZZY 20L
53 
54 // macros, determining how table boxes are merged:
55 // - 1. remove empty lines, all boxes separated with blanks,
56 // all lines separated with ParaBreak
57 // - 2. remove all empty lines and remove all empty boxes at beginning and end,
58 // all boxes separated with Blank,
59 // all lines separated with ParaBreak
60 // - 3. remove all empty boxes, all boxes separated with blanks,
61 // all lines separated with ParaBreak
62 
63 #undef DEL_ONLY_EMPTY_LINES
64 #undef DEL_EMPTY_BOXES_AT_START_AND_END
65 
66 namespace {
67 
68 struct CmpLPt
69 {
70  Point aPos;
71  const SwTableBox* pSelBox;
72  bool bVert;
73 
74  CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical );
75 
76  bool operator<( const CmpLPt& rCmp ) const
77  {
78  if ( bVert )
79  return X() > rCmp.X() || ( X() == rCmp.X() && Y() < rCmp.Y() );
80  else
81  return Y() < rCmp.Y() || ( Y() == rCmp.Y() && X() < rCmp.X() );
82  }
83 
84  long X() const { return aPos.X(); }
85  long Y() const { return aPos.Y(); }
86 };
87 
88 }
89 
91 
92 namespace {
93 
94 struct Sort_CellFrame
95 {
96  const SwCellFrame* pFrame;
97 
98  explicit Sort_CellFrame( const SwCellFrame& rCFrame )
99  : pFrame( &rCFrame ) {}
100 };
101 
102 }
103 
104 static const SwLayoutFrame *lcl_FindCellFrame( const SwLayoutFrame *pLay )
105 {
106  while ( pLay && !pLay->IsCellFrame() )
107  pLay = pLay->GetUpper();
108  return pLay;
109 }
110 
112 {
113  // ensure we leave the cell (sections)
114  const SwLayoutFrame *pTmp = pLay;
115  do {
116  pTmp = pTmp->GetNextLayoutLeaf();
117  } while( pLay->IsAnLower( pTmp ) );
118 
119  while( pTmp && !pTmp->IsCellFrame() )
120  pTmp = pTmp->GetUpper();
121  return pTmp;
122 }
123 
124 void GetTableSelCrs( const SwCursorShell &rShell, SwSelBoxes& rBoxes )
125 {
126  rBoxes.clear();
127  if( rShell.IsTableMode() && const_cast<SwCursorShell&>(rShell).UpdateTableSelBoxes())
128  {
129  rBoxes.insert(rShell.GetTableCursor()->GetSelectedBoxes());
130  }
131 }
132 
133 void GetTableSelCrs( const SwTableCursor& rTableCursor, SwSelBoxes& rBoxes )
134 {
135  rBoxes.clear();
136 
137  if (rTableCursor.IsChgd() || !rTableCursor.GetSelectedBoxesCount())
138  {
139  SwTableCursor* pTCursor = const_cast<SwTableCursor*>(&rTableCursor);
140  pTCursor->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout()->MakeTableCursors( *pTCursor );
141  }
142 
143  if (rTableCursor.GetSelectedBoxesCount())
144  {
145  rBoxes.insert(rTableCursor.GetSelectedBoxes());
146  }
147 }
148 
149 void GetTableSel( const SwCursorShell& rShell, SwSelBoxes& rBoxes,
150  const SwTableSearchType eSearchType )
151 {
152  // get start and end cell
153  if ( !rShell.IsTableMode() )
154  rShell.GetCursor();
155 
156  GetTableSel( *rShell.getShellCursor(false), rBoxes, eSearchType );
157 }
158 
159 void GetTableSel( const SwCursor& rCursor, SwSelBoxes& rBoxes,
160  const SwTableSearchType eSearchType )
161 {
162  // get start and end cell
163  OSL_ENSURE( rCursor.GetContentNode() && rCursor.GetContentNode( false ),
164  "Tabselection not on Cnt." );
165 
166  // Row-selection:
167  // Check for complex tables. If Yes, search selected boxes via
168  // the layout. Otherwise via the table structure (for macros !!)
169  const SwContentNode* pContentNd = rCursor.GetNode().GetContentNode();
170  const SwTableNode* pTableNd = pContentNd ? pContentNd->FindTableNode() : nullptr;
171  if( pTableNd && pTableNd->GetTable().IsNewModel() )
172  {
173  SwTable::SearchType eSearch;
174  switch( SwTableSearchType::Col & eSearchType )
175  {
176  case SwTableSearchType::Row: eSearch = SwTable::SEARCH_ROW; break;
177  case SwTableSearchType::Col: eSearch = SwTable::SEARCH_COL; break;
178  default: eSearch = SwTable::SEARCH_NONE; break;
179  }
180  const bool bChkP( SwTableSearchType::Protect & eSearchType );
181  pTableNd->GetTable().CreateSelection( rCursor, rBoxes, eSearch, bChkP );
182  return;
183  }
184  if( SwTableSearchType::Row == ((~SwTableSearchType::Protect ) & eSearchType ) &&
185  pTableNd && !pTableNd->GetTable().IsTableComplex() )
186  {
187  const SwTable& rTable = pTableNd->GetTable();
188  const SwTableLines& rLines = rTable.GetTabLines();
189 
190  const SwNode& rMarkNode = rCursor.GetNode( false );
191  const sal_uLong nMarkSectionStart = rMarkNode.StartOfSectionIndex();
192  const SwTableBox* pMarkBox = rTable.GetTableBox( nMarkSectionStart );
193 
194  OSL_ENSURE( pMarkBox, "Point in table, mark outside?" );
195 
196  const SwTableLine* pLine = pMarkBox ? pMarkBox->GetUpper() : nullptr;
197  sal_uInt16 nSttPos = rLines.GetPos( pLine );
198  OSL_ENSURE( USHRT_MAX != nSttPos, "Where is my row in the table?" );
199  pLine = rTable.GetTableBox( rCursor.GetNode().StartOfSectionIndex() )->GetUpper();
200  sal_uInt16 nEndPos = rLines.GetPos( pLine );
201  OSL_ENSURE( USHRT_MAX != nEndPos, "Where is my row in the table?" );
202  // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX
203  if ( nSttPos != USHRT_MAX && nEndPos != USHRT_MAX )
204  {
205  if( nEndPos < nSttPos ) // exchange
206  {
207  sal_uInt16 nTmp = nSttPos; nSttPos = nEndPos; nEndPos = nTmp;
208  }
209 
210  bool bChkProtected( SwTableSearchType::Protect & eSearchType );
211  for( ; nSttPos <= nEndPos; ++nSttPos )
212  {
213  pLine = rLines[ nSttPos ];
214  for( auto n = pLine->GetTabBoxes().size(); n ; )
215  {
216  SwTableBox* pBox = pLine->GetTabBoxes()[ --n ];
217  // check for cell protection??
218  if( !bChkProtected ||
220  rBoxes.insert( pBox );
221  }
222  }
223  }
224  }
225  else
226  {
227  Point aPtPos, aMkPos;
228  const SwShellCursor* pShCursor = dynamic_cast<const SwShellCursor*>(&rCursor);
229  if( pShCursor )
230  {
231  aPtPos = pShCursor->GetPtPos();
232  aMkPos = pShCursor->GetMkPos();
233  }
234  const SwContentNode *pCntNd = rCursor.GetContentNode();
235  std::pair<Point, bool> tmp(aPtPos, true);
236  const SwLayoutFrame *pStart = pCntNd ?
237  pCntNd->getLayoutFrame(pCntNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp)->GetUpper() : nullptr;
238  pCntNd = rCursor.GetContentNode(false);
239  tmp.first = aMkPos;
240  const SwLayoutFrame *pEnd = pCntNd ?
241  pCntNd->getLayoutFrame(pCntNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp)->GetUpper() : nullptr;
242  if( pStart && pEnd )
243  GetTableSel( pStart, pEnd, rBoxes, nullptr, eSearchType );
244  }
245 }
246 
247 void GetTableSel( const SwLayoutFrame* pStart, const SwLayoutFrame* pEnd,
248  SwSelBoxes& rBoxes, SwCellFrames* pCells,
249  const SwTableSearchType eSearchType )
250 {
251  const SwTabFrame* pStartTab = pStart->FindTabFrame();
252  if ( !pStartTab )
253  {
254  OSL_FAIL( "GetTableSel without start table" );
255  return;
256  }
257 
258  bool bChkProtected( SwTableSearchType::Protect & eSearchType );
259 
260  // #i55421# Reduced value 10
261  int nLoopMax = 10;
262 
263  do {
264  bool bTableIsValid = true;
265 
266  // First, compute tables and rectangles
267  SwSelUnions aUnions;
268  ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
269 
270  Point aCurrentTopLeft( LONG_MAX, LONG_MAX );
271  Point aCurrentTopRight( 0, LONG_MAX );
272  Point aCurrentBottomLeft( LONG_MAX, 0 );
273  Point aCurrentBottomRight( 0, 0 );
274  const SwCellFrame* pCurrentTopLeftFrame = nullptr;
275  const SwCellFrame* pCurrentTopRightFrame = nullptr;
276  const SwCellFrame* pCurrentBottomLeftFrame = nullptr;
277  const SwCellFrame* pCurrentBottomRightFrame = nullptr;
278 
279  // Now find boxes for each entry and emit
280  for (size_t i = 0; i < aUnions.size() && bTableIsValid; ++i)
281  {
282  SwSelUnion *pUnion = &aUnions[i];
283  const SwTabFrame *pTable = pUnion->GetTable();
284 
285  if( !pTable->isFrameAreaDefinitionValid() && nLoopMax )
286  {
287  bTableIsValid = false;
288  break;
289  }
290 
291  // Skip any repeated headlines in the follow:
292  const SwLayoutFrame* pRow = pTable->IsFollow() ?
293  pTable->GetFirstNonHeadlineRow() :
294  static_cast<const SwLayoutFrame*>(pTable->Lower());
295 
296  while( pRow && bTableIsValid )
297  {
298  if( !pRow->isFrameAreaDefinitionValid() && nLoopMax )
299  {
300  bTableIsValid = false;
301  break;
302  }
303 
304  if ( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
305  {
306  const SwLayoutFrame *pCell = pRow->FirstCell();
307 
308  while (pCell && pRow->IsAnLower(pCell))
309  {
310  if( !pCell->isFrameAreaDefinitionValid() && nLoopMax )
311  {
312  bTableIsValid = false;
313  break;
314  }
315 
316  OSL_ENSURE( pCell->IsCellFrame(), "Frame without Cell" );
317  if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
318  {
319  SwTableBox* pBox = const_cast<SwTableBox*>(
320  static_cast<const SwCellFrame*>(pCell)->GetTabBox());
321  // check for cell protection??
322  if( !bChkProtected ||
324  rBoxes.insert( pBox );
325 
326  if ( pCells )
327  {
328  const Point aTopLeft( pCell->getFrameArea().TopLeft() );
329  const Point aTopRight( pCell->getFrameArea().TopRight() );
330  const Point aBottomLeft( pCell->getFrameArea().BottomLeft() );
331  const Point aBottomRight( pCell->getFrameArea().BottomRight() );
332 
333  if ( aTopLeft.getY() < aCurrentTopLeft.getY() ||
334  ( aTopLeft.getY() == aCurrentTopLeft.getY() &&
335  aTopLeft.getX() < aCurrentTopLeft.getX() ) )
336  {
337  aCurrentTopLeft = aTopLeft;
338  pCurrentTopLeftFrame = static_cast<const SwCellFrame*>( pCell );
339  }
340 
341  if ( aTopRight.getY() < aCurrentTopRight.getY() ||
342  ( aTopRight.getY() == aCurrentTopRight.getY() &&
343  aTopRight.getX() > aCurrentTopRight.getX() ) )
344  {
345  aCurrentTopRight = aTopRight;
346  pCurrentTopRightFrame = static_cast<const SwCellFrame*>( pCell );
347  }
348 
349  if ( aBottomLeft.getY() > aCurrentBottomLeft.getY() ||
350  ( aBottomLeft.getY() == aCurrentBottomLeft.getY() &&
351  aBottomLeft.getX() < aCurrentBottomLeft.getX() ) )
352  {
353  aCurrentBottomLeft = aBottomLeft;
354  pCurrentBottomLeftFrame = static_cast<const SwCellFrame*>( pCell );
355  }
356 
357  if ( aBottomRight.getY() > aCurrentBottomRight.getY() ||
358  ( aBottomRight.getY() == aCurrentBottomRight.getY() &&
359  aBottomRight.getX() > aCurrentBottomRight.getX() ) )
360  {
361  aCurrentBottomRight = aBottomRight;
362  pCurrentBottomRightFrame = static_cast<const SwCellFrame*>( pCell );
363  }
364 
365  }
366  }
367  if ( pCell->GetNext() )
368  {
369  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
370  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
371  pCell = pCell->FirstCell();
372  }
373  else
374  pCell = ::lcl_FindNextCellFrame( pCell );
375  }
376  }
377  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
378  }
379  }
380 
381  if ( pCells )
382  {
383  pCells->clear();
384  pCells->push_back( const_cast< SwCellFrame* >(pCurrentTopLeftFrame) );
385  pCells->push_back( const_cast< SwCellFrame* >(pCurrentTopRightFrame) );
386  pCells->push_back( const_cast< SwCellFrame* >(pCurrentBottomLeftFrame) );
387  pCells->push_back( const_cast< SwCellFrame* >(pCurrentBottomRightFrame) );
388  }
389 
390  if( bTableIsValid )
391  break;
392 
393  SwDeletionChecker aDelCheck( pStart );
394 
395  // otherwise quickly "calculate" the table layout and start over
396  SwTabFrame *pTable = aUnions.front().GetTable();
397  while( pTable )
398  {
399  if( pTable->isFrameAreaDefinitionValid() )
400  {
401  pTable->InvalidatePos();
402  }
403 
404  pTable->SetONECalcLowers();
405  pTable->Calc(pTable->getRootFrame()->GetCurrShell()->GetOut());
406  pTable->SetCompletePaint();
407 
408  pTable = pTable->GetFollow();
409  if( nullptr == pTable )
410  break;
411  }
412 
413  // --> Make code robust, check if pStart has
414  // been deleted due to the formatting of the table:
415  if ( aDelCheck.HasBeenDeleted() )
416  {
417  OSL_FAIL( "Current box has been deleted during GetTableSel()" );
418  break;
419  }
420 
421  rBoxes.clear();
422  --nLoopMax;
423 
424  } while( true );
425  OSL_ENSURE( nLoopMax, "Table layout is still invalid!" );
426 }
427 
428 bool ChkChartSel( const SwNode& rSttNd, const SwNode& rEndNd )
429 {
430  const SwTableNode* pTNd = rSttNd.FindTableNode();
431  if( !pTNd )
432  return false;
433 
434  Point aNullPos;
435  SwNodeIndex aIdx( rSttNd );
436  const SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
437  if( !pCNd )
438  pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
439 
440  // if table is invisible, return
441  // (layout needed for forming table selection further down, so we can't
442  // continue with invisible tables)
443  // #i22135# - Also the content of the table could be
444  // invisible - e.g. in a hidden section
445  // Robust: check, if content was found (e.g. empty table cells)
446  if ( !pCNd || pCNd->getLayoutFrame( pCNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() ) == nullptr )
447  return false;
448 
449  std::pair<Point, bool> tmp(aNullPos, true);
450  const SwLayoutFrame *const pStart = pCNd->getLayoutFrame(
452  nullptr, &tmp)->GetUpper();
453  OSL_ENSURE( pStart, "without frame nothing works" );
454 
455  aIdx = rEndNd;
456  pCNd = aIdx.GetNode().GetContentNode();
457  if( !pCNd )
458  pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
459 
460  // #i22135# - Robust: check, if content was found and if it's visible
461  if ( !pCNd || pCNd->getLayoutFrame( pCNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() ) == nullptr )
462  {
463  return false;
464  }
465 
466  const SwLayoutFrame *const pEnd = pCNd->getLayoutFrame(
468  nullptr, &tmp)->GetUpper();
469  OSL_ENSURE( pEnd, "without frame nothing works" );
470 
471  bool bValidChartSel;
472  // #i55421# Reduced value 10
473  int nLoopMax = 10; //JP 28.06.99: max 100 loops - Bug 67292
474 
475  do {
476  bool bTableIsValid = true;
477  bValidChartSel = true;
478 
479  sal_uInt16 nRowCells = USHRT_MAX;
480 
481  // First, compute tables and rectangles
482  SwSelUnions aUnions;
483  ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::NoUnionCorrect );
484 
485  // find boxes for each entry and emit
486  for( auto & rSelUnion : aUnions )
487  {
488  if (!bTableIsValid || !bValidChartSel)
489  break;
490 
491  SwSelUnion *pUnion = &rSelUnion;
492  const SwTabFrame *pTable = pUnion->GetTable();
493 
494  SwRectFnSet aRectFnSet(pTable);
495  bool bRTL = pTable->IsRightToLeft();
496 
497  if( !pTable->isFrameAreaDefinitionValid() && nLoopMax )
498  {
499  bTableIsValid = false;
500  break;
501  }
502 
503  std::deque< Sort_CellFrame > aCellFrames;
504 
505  // Skip any repeated headlines in the follow:
506  const SwLayoutFrame* pRow = pTable->IsFollow() ?
507  pTable->GetFirstNonHeadlineRow() :
508  static_cast<const SwLayoutFrame*>(pTable->Lower());
509 
510  while( pRow && bTableIsValid && bValidChartSel )
511  {
512  if( !pRow->isFrameAreaDefinitionValid() && nLoopMax )
513  {
514  bTableIsValid = false;
515  break;
516  }
517 
518  if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
519  {
520  const SwLayoutFrame *pCell = pRow->FirstCell();
521 
522  while (pCell && pRow->IsAnLower(pCell))
523  {
524  if( !pCell->isFrameAreaDefinitionValid() && nLoopMax )
525  {
526  bTableIsValid = false;
527  break;
528  }
529 
530  OSL_ENSURE( pCell->IsCellFrame(), "Frame without Cell" );
531  const SwRect& rUnion = pUnion->GetUnion(),
532  & rFrameRect = pCell->getFrameArea();
533 
534  const long nUnionRight = rUnion.Right();
535  const long nUnionBottom = rUnion.Bottom();
536  const long nFrameRight = rFrameRect.Right();
537  const long nFrameBottom = rFrameRect.Bottom();
538 
539  // ignore if FrameRect is outside the union
540 
541  const long nXFuzzy = aRectFnSet.IsVert() ? 0 : 20;
542  const long nYFuzzy = aRectFnSet.IsVert() ? 20 : 0;
543 
544  if( !( rUnion.Top() + nYFuzzy > nFrameBottom ||
545  nUnionBottom < rFrameRect.Top() + nYFuzzy ||
546  rUnion.Left() + nXFuzzy > nFrameRight ||
547  nUnionRight < rFrameRect.Left() + nXFuzzy ))
548  {
549  // ok, rUnion is _not_ completely outside of rFrameRect
550 
551  // if not completely inside the union, then
552  // for Chart it is an invalid selection
553  if( rUnion.Left() <= rFrameRect.Left() + nXFuzzy &&
554  rFrameRect.Left() <= nUnionRight &&
555  rUnion.Left() <= nFrameRight &&
556  nFrameRight <= nUnionRight + nXFuzzy &&
557  rUnion.Top() <= rFrameRect.Top() + nYFuzzy &&
558  rFrameRect.Top() <= nUnionBottom &&
559  rUnion.Top() <= nFrameBottom &&
560  nFrameBottom <= nUnionBottom+ nYFuzzy )
561 
562  aCellFrames.emplace_back( *static_cast<const SwCellFrame*>(pCell) );
563  else
564  {
565  bValidChartSel = false;
566  break;
567  }
568  }
569  if ( pCell->GetNext() )
570  {
571  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
572  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
573  pCell = pCell->FirstCell();
574  }
575  else
576  pCell = ::lcl_FindNextCellFrame( pCell );
577  }
578  }
579  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
580  }
581 
582  if( !bValidChartSel )
583  break;
584 
585  // all cells of the (part) table together. Now check if
586  // they're all adjacent
587  size_t n;
588  sal_uInt16 nCellCnt = 0;
589  long nYPos = LONG_MAX;
590  long nXPos = 0;
591  long nHeight = 0;
592 
593  for( n = 0 ; n < aCellFrames.size(); ++n )
594  {
595  const Sort_CellFrame& rCF = aCellFrames[ n ];
596  if( aRectFnSet.GetTop(rCF.pFrame->getFrameArea()) != nYPos )
597  {
598  // new row
599  if( n )
600  {
601  if( USHRT_MAX == nRowCells ) // 1. row change
602  nRowCells = nCellCnt;
603  else if( nRowCells != nCellCnt )
604  {
605  bValidChartSel = false;
606  break;
607  }
608  }
609  nCellCnt = 1;
610  nYPos = aRectFnSet.GetTop(rCF.pFrame->getFrameArea());
611  nHeight = aRectFnSet.GetHeight(rCF.pFrame->getFrameArea());
612 
613  nXPos = bRTL ?
614  aRectFnSet.GetLeft(rCF.pFrame->getFrameArea()) :
615  aRectFnSet.GetRight(rCF.pFrame->getFrameArea());
616  }
617  else if( nXPos == ( bRTL ?
618  aRectFnSet.GetRight(rCF.pFrame->getFrameArea()) :
619  aRectFnSet.GetLeft(rCF.pFrame->getFrameArea()) ) &&
620  nHeight == aRectFnSet.GetHeight(rCF.pFrame->getFrameArea()) )
621  {
622  nXPos += ( bRTL ? -1 : 1 ) *
623  aRectFnSet.GetWidth(rCF.pFrame->getFrameArea());
624  ++nCellCnt;
625  }
626  else
627  {
628  bValidChartSel = false;
629  break;
630  }
631  }
632  if( bValidChartSel )
633  {
634  if( USHRT_MAX == nRowCells )
635  nRowCells = nCellCnt;
636  else if( nRowCells != nCellCnt )
637  bValidChartSel = false;
638  }
639  }
640 
641  if( bTableIsValid )
642  break;
643 
644  // otherwise quickly "calculate" table layout and start over
645  SwTabFrame *pTable = aUnions.front().GetTable();
646 
647  for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
648  {
649  if( pTable->isFrameAreaDefinitionValid() )
650  {
651  pTable->InvalidatePos();
652  }
653 
654  pTable->SetONECalcLowers();
655  pTable->Calc(pTable->getRootFrame()->GetCurrShell()->GetOut());
656  pTable->SetCompletePaint();
657 
658  pTable = pTable->GetFollow();
659  if( nullptr == pTable )
660  break;
661  }
662  --nLoopMax;
663  } while( true );
664 
665  OSL_ENSURE( nLoopMax, "table layout is still invalid!" );
666 
667  return bValidChartSel;
668 }
669 
670 bool IsFrameInTableSel( const SwRect& rUnion, const SwFrame* pCell )
671 {
672  OSL_ENSURE( pCell->IsCellFrame(), "Frame without Gazelle" );
673 
674  if( pCell->FindTabFrame()->IsVertical() )
675  return rUnion.Right() >= pCell->getFrameArea().Right() &&
676  rUnion.Left() <= pCell->getFrameArea().Left() &&
677  (( rUnion.Top() <= pCell->getFrameArea().Top()+20 &&
678  rUnion.Bottom() > pCell->getFrameArea().Top() ) ||
679  ( rUnion.Top() >= pCell->getFrameArea().Top() &&
680  rUnion.Bottom() < pCell->getFrameArea().Bottom() ));
681 
682  return
683  rUnion.Top() <= pCell->getFrameArea().Top() &&
684  rUnion.Bottom() >= pCell->getFrameArea().Bottom() &&
685 
686  (( rUnion.Left() <= pCell->getFrameArea().Left()+20 &&
687  rUnion.Right() > pCell->getFrameArea().Left() ) ||
688 
689  ( rUnion.Left() >= pCell->getFrameArea().Left() &&
690  rUnion.Right() < pCell->getFrameArea().Right() ));
691 }
692 
693 bool GetAutoSumSel( const SwCursorShell& rShell, SwCellFrames& rBoxes )
694 {
695  SwShellCursor* pCursor = rShell.m_pCurrentCursor;
696  if ( rShell.IsTableMode() )
697  pCursor = rShell.m_pTableCursor;
698 
699  std::pair<Point, bool> tmp(pCursor->GetPtPos(), true);
700  const SwLayoutFrame *const pStart = pCursor->GetContentNode()->getLayoutFrame(
701  rShell.GetLayout(), nullptr, &tmp)->GetUpper();
702  tmp.first = pCursor->GetMkPos();
703  const SwLayoutFrame *const pEnd = pCursor->GetContentNode(false)->getLayoutFrame(
704  rShell.GetLayout(), nullptr, &tmp)->GetUpper();
705 
706  const SwLayoutFrame* pSttCell = pStart;
707  while( pSttCell && !pSttCell->IsCellFrame() )
708  pSttCell = pSttCell->GetUpper();
709 
710  // First, compute tables and rectangles
711  SwSelUnions aUnions;
712 
713  // by default, first test above and then to the left
714  ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::Col );
715 
716  bool bTstRow = true, bFound = false;
717 
718  // 1. check if box above contains value/formula
719  for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
720  {
721  SwSelUnion *pUnion = &aUnions[i];
722  const SwTabFrame *pTable = pUnion->GetTable();
723 
724  // Skip any repeated headlines in the follow:
725  const SwLayoutFrame* pRow = pTable->IsFollow() ?
726  pTable->GetFirstNonHeadlineRow() :
727  static_cast<const SwLayoutFrame*>(pTable->Lower());
728 
729  while( pRow )
730  {
731  if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
732  {
733  const SwCellFrame* pUpperCell = nullptr;
734  const SwLayoutFrame *pCell = pRow->FirstCell();
735 
736  while( pCell && pRow->IsAnLower( pCell ) )
737  {
738  if( pCell == pSttCell )
739  {
740  sal_uInt16 nWhichId = 0;
741  for( size_t n = rBoxes.size(); n; )
742  {
743  nWhichId = rBoxes[ --n ]->GetTabBox()->IsFormulaOrValueBox();
744  if( USHRT_MAX != nWhichId )
745  break;
746  }
747 
748  // all boxes together, do not check the
749  // row, if a formula or value was found
750  bTstRow = 0 == nWhichId || USHRT_MAX == nWhichId;
751  bFound = true;
752  break;
753  }
754 
755  OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" );
756  if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
757  pUpperCell = static_cast<const SwCellFrame*>(pCell);
758 
759  if( pCell->GetNext() )
760  {
761  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
762  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
763  pCell = pCell->FirstCell();
764  }
765  else
766  pCell = ::lcl_FindNextCellFrame( pCell );
767  }
768 
769  if( pUpperCell )
770  rBoxes.push_back( const_cast< SwCellFrame* >(pUpperCell) );
771  }
772  if( bFound )
773  {
774  i = aUnions.size();
775  break;
776  }
777  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
778  }
779  }
780 
781  // 2. check if box on left contains value/formula
782  if( bTstRow )
783  {
784  bFound = false;
785 
786  rBoxes.clear();
787  aUnions.clear();
788  ::MakeSelUnions( aUnions, pStart, pEnd, SwTableSearchType::Row );
789 
790  for( SwSelUnions::size_type i = 0; i < aUnions.size(); ++i )
791  {
792  SwSelUnion *pUnion = &aUnions[i];
793  const SwTabFrame *pTable = pUnion->GetTable();
794 
795  // Skip any repeated headlines in the follow:
796  const SwLayoutFrame* pRow = pTable->IsFollow() ?
797  pTable->GetFirstNonHeadlineRow() :
798  static_cast<const SwLayoutFrame*>(pTable->Lower());
799 
800  while( pRow )
801  {
802  if( pRow->getFrameArea().IsOver( pUnion->GetUnion() ) )
803  {
804  const SwLayoutFrame *pCell = pRow->FirstCell();
805 
806  while( pCell && pRow->IsAnLower( pCell ) )
807  {
808  if( pCell == pSttCell )
809  {
810  sal_uInt16 nWhichId = 0;
811  for( size_t n = rBoxes.size(); n; )
812  {
813  nWhichId = rBoxes[ --n ]
815  if( USHRT_MAX != nWhichId )
816  break;
817  }
818 
819  // all boxes together, do not check the
820  // row if a formula or value was found
821  bFound = 0 != nWhichId && USHRT_MAX != nWhichId;
822  bTstRow = false;
823  break;
824  }
825 
826  OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" );
827  if( ::IsFrameInTableSel( pUnion->GetUnion(), pCell ) )
828  {
829  SwCellFrame* pC = const_cast<SwCellFrame*>(static_cast<const SwCellFrame*>(pCell));
830  rBoxes.push_back( pC );
831  }
832  if( pCell->GetNext() )
833  {
834  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
835  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
836  pCell = pCell->FirstCell();
837  }
838  else
839  pCell = ::lcl_FindNextCellFrame( pCell );
840  }
841  }
842  if( !bTstRow )
843  {
844  i = aUnions.size();
845  break;
846  }
847 
848  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
849  }
850  }
851  }
852 
853  return bFound;
854 }
855 
856 bool HasProtectedCells( const SwSelBoxes& rBoxes )
857 {
858  bool bRet = false;
859  for (size_t n = 0; n < rBoxes.size(); ++n)
860  {
861  if( rBoxes[ n ]->GetFrameFormat()->GetProtect().IsContentProtected() )
862  {
863  bRet = true;
864  break;
865  }
866  }
867  return bRet;
868 }
869 
870 CmpLPt::CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical )
871  : aPos( rPt ), pSelBox( pBox ), bVert( bVertical )
872 {}
873 
874 static void lcl_InsTableBox( SwTableNode* pTableNd, SwDoc* pDoc, SwTableBox* pBox,
875  sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 )
876 {
877  OSL_ENSURE( pBox->GetSttNd(), "Box without Start-Node" );
878  SwContentNode* pCNd = pDoc->GetNodes()[ pBox->GetSttIdx() + 1 ]
879  ->GetContentNode();
880  if( pCNd && pCNd->IsTextNode() )
881  pDoc->GetNodes().InsBoxen( pTableNd, pBox->GetUpper(),
882  static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat()),
883  static_cast<SwTextNode*>(pCNd)->GetTextColl(),
884  pCNd->GetpSwAttrSet(),
885  nInsPos, nCnt );
886  else
887  pDoc->GetNodes().InsBoxen( pTableNd, pBox->GetUpper(),
888  static_cast<SwTableBoxFormat*>(pBox->GetFrameFormat()),
889  pDoc->GetDfltTextFormatColl(), nullptr,
890  nInsPos, nCnt );
891 }
892 
893 bool IsEmptyBox( const SwTableBox& rBox, SwPaM& rPam )
894 {
895  rPam.GetPoint()->nNode = *rBox.GetSttNd()->EndOfSectionNode();
897  rPam.SetMark();
898  rPam.GetPoint()->nNode = *rBox.GetSttNd();
899  rPam.Move( fnMoveForward, GoInContent );
900  bool bRet = *rPam.GetMark() == *rPam.GetPoint()
901  && ( rBox.GetSttNd()->GetIndex() + 1 == rPam.GetPoint()->nNode.GetIndex() );
902 
903  if( bRet )
904  {
905  // now check for paragraph bound flies
906  const SwFrameFormats& rFormats = *rPam.GetDoc()->GetSpzFrameFormats();
907  sal_uLong nSttIdx = rPam.GetPoint()->nNode.GetIndex(),
908  nEndIdx = rBox.GetSttNd()->EndOfSectionIndex(),
909  nIdx;
910 
911  for( auto pFormat : rFormats )
912  {
913  const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
914  const SwPosition* pAPos = rAnchor.GetContentAnchor();
915  if (pAPos &&
916  ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) ||
917  (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
918  nSttIdx <= ( nIdx = pAPos->nNode.GetIndex() ) &&
919  nIdx < nEndIdx )
920  {
921  bRet = false;
922  break;
923  }
924  }
925  }
926  return bRet;
927 }
928 
929 void GetMergeSel( const SwPaM& rPam, SwSelBoxes& rBoxes,
930  SwTableBox** ppMergeBox, SwUndoTableMerge* pUndo )
931 {
932  rBoxes.clear();
933 
934  OSL_ENSURE( rPam.GetContentNode() && rPam.GetContentNode( false ),
935  "Tabselection not on Cnt." );
936 
937 //JP 24.09.96: Merge with repeating TableHeadLines does not work properly.
938 // Why not use point 0,0? Then it is assured the first
939 // headline is contained.
940  Point aPt( 0, 0 );
941 
942  const SwContentNode* pCntNd = rPam.GetContentNode();
943  std::pair<Point, bool> const tmp(aPt, true);
944  const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
946  nullptr, &tmp)->GetUpper();
947  pCntNd = rPam.GetContentNode(false);
948  const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
950  nullptr, &tmp)->GetUpper();
951 
952  // First, compute tables and rectangles
953  SwSelUnions aUnions;
954  ::MakeSelUnions( aUnions, pStart, pEnd );
955  if( aUnions.empty() )
956  return;
957 
958  const SwTable *pTable = aUnions.front().GetTable()->GetTable();
959  SwDoc* pDoc = const_cast<SwDoc*>(pStart->GetFormat()->GetDoc());
960  SwTableNode* pTableNd = const_cast<SwTableNode*>(pTable->GetTabSortBoxes()[ 0 ]->
961  GetSttNd()->FindTableNode());
962 
963  MergePos aPosArr; // Sort-Array with the frame positions
964  long nWidth;
965  SwTableBox* pLastBox = nullptr;
966 
967  SwRectFnSet aRectFnSet(pStart->GetUpper());
968 
969  for ( auto & rSelUnion : aUnions )
970  {
971  const SwTabFrame *pTabFrame = rSelUnion.GetTable();
972 
973  SwRect &rUnion = rSelUnion.GetUnion();
974 
975  // Skip any repeated headlines in the follow:
976  const SwLayoutFrame* pRow = pTabFrame->IsFollow() ?
977  pTabFrame->GetFirstNonHeadlineRow() :
978  static_cast<const SwLayoutFrame*>(pTabFrame->Lower());
979 
980  while ( pRow )
981  {
982  if ( pRow->getFrameArea().IsOver( rUnion ) )
983  {
984  const SwLayoutFrame *pCell = pRow->FirstCell();
985 
986  while ( pCell && pRow->IsAnLower( pCell ) )
987  {
988  OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" );
989  // overlap in full width?
990  if( rUnion.Top() <= pCell->getFrameArea().Top() &&
991  rUnion.Bottom() >= pCell->getFrameArea().Bottom() )
992  {
993  SwTableBox* pBox = const_cast<SwTableBox*>(static_cast<const SwCellFrame*>(pCell)->GetTabBox());
994 
995  // only overlap to the right?
996  if( ( rUnion.Left() - COLFUZZY ) <= pCell->getFrameArea().Left() &&
997  ( rUnion.Right() - COLFUZZY ) > pCell->getFrameArea().Left() )
998  {
999  if( ( rUnion.Right() + COLFUZZY ) < pCell->getFrameArea().Right() )
1000  {
1001  sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1002  lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos );
1003  pBox->ClaimFrameFormat();
1004  SwFormatFrameSize aNew(
1005  pBox->GetFrameFormat()->GetFrameSize() );
1006  nWidth = rUnion.Right() - pCell->getFrameArea().Left();
1007  nWidth = nWidth * aNew.GetWidth() /
1008  pCell->getFrameArea().Width();
1009  long nTmpWidth = aNew.GetWidth() - nWidth;
1010  aNew.SetWidth( nWidth );
1011  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1012  // this box is selected
1013  pLastBox = pBox;
1014  rBoxes.insert( pBox );
1015  aPosArr.insert(
1016  CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1017  pBox, aRectFnSet.IsVert() ) );
1018 
1019  pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1020  aNew.SetWidth( nTmpWidth );
1021  pBox->ClaimFrameFormat();
1022  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1023 
1024  if( pUndo )
1025  pUndo->AddNewBox( pBox->GetSttIdx() );
1026  }
1027  else
1028  {
1029  // this box is selected
1030  pLastBox = pBox;
1031  rBoxes.insert( pBox );
1032  aPosArr.insert(
1033  CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1034  pBox, aRectFnSet.IsVert() ) );
1035  }
1036  }
1037  // overlapping on left- or right-side
1038  else if( ( rUnion.Left() - COLFUZZY ) >= pCell->getFrameArea().Left() &&
1039  ( rUnion.Right() + COLFUZZY ) < pCell->getFrameArea().Right() )
1040  {
1041  sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1042  lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos, 2 );
1043  pBox->ClaimFrameFormat();
1044  SwFormatFrameSize aNew(
1045  pBox->GetFrameFormat()->GetFrameSize() );
1046  long nLeft = rUnion.Left() - pCell->getFrameArea().Left();
1047  nLeft = nLeft * aNew.GetWidth() /
1048  pCell->getFrameArea().Width();
1049  long nRight = pCell->getFrameArea().Right() - rUnion.Right();
1050  nRight = nRight * aNew.GetWidth() /
1051  pCell->getFrameArea().Width();
1052  nWidth = aNew.GetWidth() - nLeft - nRight;
1053 
1054  aNew.SetWidth( nLeft );
1055  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1056 
1057  {
1058  const SfxPoolItem* pItem;
1059  if( SfxItemState::SET == pBox->GetFrameFormat()->GetAttrSet()
1060  .GetItemState( RES_BOX, false, &pItem ))
1061  {
1062  SvxBoxItem aBox( *static_cast<const SvxBoxItem*>(pItem) );
1063  aBox.SetLine( nullptr, SvxBoxItemLine::RIGHT );
1064  pBox->GetFrameFormat()->SetFormatAttr( aBox );
1065  }
1066  }
1067 
1068  pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1069  aNew.SetWidth( nWidth );
1070  pBox->ClaimFrameFormat();
1071  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1072 
1073  if( pUndo )
1074  pUndo->AddNewBox( pBox->GetSttIdx() );
1075 
1076  // this box is selected
1077  pLastBox = pBox;
1078  rBoxes.insert( pBox );
1079  aPosArr.insert(
1080  CmpLPt( aRectFnSet.GetPos(pCell->getFrameArea()),
1081  pBox, aRectFnSet.IsVert() ) );
1082 
1083  pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos+1 ];
1084  aNew.SetWidth( nRight );
1085  pBox->ClaimFrameFormat();
1086  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1087 
1088  if( pUndo )
1089  pUndo->AddNewBox( pBox->GetSttIdx() );
1090  }
1091  // is right side of box part of the selected area?
1092  else if( ( pCell->getFrameArea().Right() - COLFUZZY ) < rUnion.Right() &&
1093  ( pCell->getFrameArea().Right() - COLFUZZY ) > rUnion.Left() &&
1094  ( pCell->getFrameArea().Left() + COLFUZZY ) < rUnion.Left() )
1095  {
1096  // then we should insert a new box and adjust the widths
1097  sal_uInt16 nInsPos = pBox->GetUpper()->GetBoxPos( pBox )+1;
1098  lcl_InsTableBox( pTableNd, pDoc, pBox, nInsPos );
1099 
1100  SwFormatFrameSize aNew(pBox->GetFrameFormat()->GetFrameSize() );
1101  long nLeft = rUnion.Left() - pCell->getFrameArea().Left(),
1102  nRight = pCell->getFrameArea().Right() - rUnion.Left();
1103 
1104  nLeft = nLeft * aNew.GetWidth() /
1105  pCell->getFrameArea().Width();
1106  nRight = nRight * aNew.GetWidth() /
1107  pCell->getFrameArea().Width();
1108 
1109  aNew.SetWidth( nLeft );
1110  pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
1111 
1112  // this box is selected
1113  pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
1114  aNew.SetWidth( nRight );
1115  pBox->ClaimFrameFormat();
1116  pBox->GetFrameFormat()->SetFormatAttr( aNew );
1117 
1118  pLastBox = pBox;
1119  rBoxes.insert( pBox );
1120  aPosArr.insert( CmpLPt( Point( rUnion.Left(),
1121  pCell->getFrameArea().Top()), pBox, aRectFnSet.IsVert() ));
1122 
1123  if( pUndo )
1124  pUndo->AddNewBox( pBox->GetSttIdx() );
1125  }
1126  }
1127  if ( pCell->GetNext() )
1128  {
1129  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
1130  // --> Check if table cell is not empty
1131  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
1132  pCell = pCell->FirstCell();
1133  }
1134  else
1135  pCell = ::lcl_FindNextCellFrame( pCell );
1136  }
1137  }
1138  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
1139  }
1140  }
1141 
1142  // no SSelection / no boxes found
1143  if( 1 >= rBoxes.size() )
1144  return;
1145 
1146  // now search all horizontally adjacent boxes and connect
1147  // their contents with blanks. All vertically adjacent will be tied
1148  // together as paragraphs
1149 
1150  // 1. Solution: map array and all on same Y-level
1151  // are separated with blanks
1152  // all others are separated with paragraphs
1153  bool bCalcWidth = true;
1154  const SwTableBox* pFirstBox = aPosArr[ 0 ].pSelBox;
1155 
1156  // JP 27.03.98: Optimise - if boxes on one row are empty,
1157  // then do not insert blanks or carriage returns
1158  //Block to assure SwPaM, SwPosition are deleted from stack
1159  {
1160  SwPaM aPam( pDoc->GetNodes() );
1161 
1162 #if defined( DEL_ONLY_EMPTY_LINES )
1163  nWidth = pFirstBox->GetFrameFormat()->GetFrameSize().GetWidth();
1164  bool bEmptyLine = sal_True;
1165  sal_uInt16 n, nSttPos = 0;
1166 
1167  for( n = 0; n < aPosArr.Count(); ++n )
1168  {
1169  const CmpLPt& rPt = aPosArr[ n ];
1170  if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // same Y level?
1171  {
1172  if( bEmptyLine && !IsEmptyBox( *rPt.pSelBox, aPam ))
1173  bEmptyLine = sal_False;
1174  if( bCalcWidth )
1175  nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1176  }
1177  else
1178  {
1179  if( bCalcWidth && n )
1180  bCalcWidth = false; // one line is ready
1181 
1182  if( bEmptyLine && nSttPos < n )
1183  {
1184  // now complete line is empty and should not
1185  // be filled with blanks and be inserted as paragraph
1186  if( pUndo )
1187  for( sal_uInt16 i = nSttPos; i < n; ++i )
1188  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1189 
1190  aPosArr.Remove( nSttPos, n - nSttPos );
1191  n = nSttPos;
1192  }
1193  else
1194  nSttPos = n;
1195 
1196  bEmptyLine = IsEmptyBox( *aPosArr[n].pSelBox, aPam );
1197  }
1198  }
1199  if( bEmptyLine && nSttPos < n )
1200  {
1201  if( pUndo )
1202  for( sal_uInt16 i = nSttPos; i < n; ++i )
1203  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1204  aPosArr.Remove( nSttPos, n - nSttPos );
1205  }
1206 #elif defined( DEL_EMPTY_BOXES_AT_START_AND_END )
1207 
1208  nWidth = pFirstBox->GetFrameFormat()->GetFrameSize().GetWidth();
1209  sal_uInt16 n, nSttPos = 0, nSEndPos = 0, nESttPos = 0;
1210 
1211  for( n = 0; n < aPosArr.Count(); ++n )
1212  {
1213  const CmpLPt& rPt = aPosArr[ n ];
1214  if( n && aPosArr[ n - 1 ].Y() == rPt.Y() ) // same Y level?
1215  {
1216  bool bEmptyBox = IsEmptyBox( *rPt.pSelBox, aPam );
1217  if( bEmptyBox )
1218  {
1219  if( nSEndPos == n ) // beginning is empty
1220  nESttPos = ++nSEndPos;
1221  }
1222  else // end could be empty
1223  nESttPos = n+1;
1224 
1225  if( bCalcWidth )
1226  nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1227  }
1228  else
1229  {
1230  if( bCalcWidth && n )
1231  bCalcWidth = false; // one line ready
1232 
1233  // first those at the beginning
1234  if( nSttPos < nSEndPos )
1235  {
1236  // now the beginning of the line is empty and should
1237  // not be filled with blanks
1238  if( pUndo )
1239  for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
1240  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1241 
1242  sal_uInt16 nCnt = nSEndPos - nSttPos;
1243  aPosArr.Remove( nSttPos, nCnt );
1244  nESttPos -= nCnt;
1245  n -= nCnt;
1246  }
1247 
1248  if( nESttPos < n )
1249  {
1250  // now the beginning of the line is empty and should
1251  // not be filled with blanks
1252  if( pUndo )
1253  for( sal_uInt16 i = nESttPos; i < n; ++i )
1254  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1255 
1256  sal_uInt16 nCnt = n - nESttPos;
1257  aPosArr.Remove( nESttPos, nCnt );
1258  n -= nCnt;
1259  }
1260 
1261  nSttPos = nSEndPos = nESttPos = n;
1262  if( IsEmptyBox( *aPosArr[n].pSelBox, aPam ))
1263  ++nSEndPos;
1264  else
1265  ++nESttPos;
1266  }
1267  }
1268 
1269  // first those at the beginning
1270  if( nSttPos < nSEndPos )
1271  {
1272  // now the beginning of the line is empty and should
1273  // not be filled with blanks
1274  if( pUndo )
1275  for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
1276  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1277 
1278  sal_uInt16 nCnt = nSEndPos - nSttPos;
1279  aPosArr.Remove( nSttPos, nCnt );
1280  nESttPos -= nCnt;
1281  n -= nCnt;
1282  }
1283  if( nESttPos < n )
1284  {
1285  // now the beginning of the line is empty and should
1286  // not be filled with blanks
1287  if( pUndo )
1288  for( sal_uInt16 i = nESttPos; i < n; ++i )
1289  pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
1290 
1291  sal_uInt16 nCnt = n - nESttPos;
1292  aPosArr.Remove( nESttPos, nCnt );
1293  }
1294 #else
1295 // DEL_ALL_EMPTY_BOXES
1296 
1297  nWidth = 0;
1298  long nY = !aPosArr.empty() ?
1299  ( aRectFnSet.IsVert() ?
1300  aPosArr[ 0 ].X() :
1301  aPosArr[ 0 ].Y() ) :
1302  0;
1303 
1304  for( MergePos::size_type n = 0; n < aPosArr.size(); ++n )
1305  {
1306  const CmpLPt& rPt = aPosArr[ n ];
1307  if( bCalcWidth )
1308  {
1309  if( nY == ( aRectFnSet.IsVert() ? rPt.X() : rPt.Y() ) ) // same Y level?
1310  nWidth += rPt.pSelBox->GetFrameFormat()->GetFrameSize().GetWidth();
1311  else
1312  bCalcWidth = false; // one line ready
1313  }
1314 
1315  if( IsEmptyBox( *rPt.pSelBox, aPam ) )
1316  {
1317  if( pUndo )
1318  pUndo->SaveCollection( *rPt.pSelBox );
1319 
1320  aPosArr.erase( aPosArr.begin() + n );
1321  --n;
1322  }
1323  }
1324 #endif
1325  }
1326 
1327  // first create new box
1328  {
1329  SwTableBox* pTmpBox = rBoxes[0];
1330  SwTableLine* pInsLine = pTmpBox->GetUpper();
1331  sal_uInt16 nInsPos = pInsLine->GetBoxPos( pTmpBox );
1332 
1333  lcl_InsTableBox( pTableNd, pDoc, pTmpBox, nInsPos );
1334  (*ppMergeBox) = pInsLine->GetTabBoxes()[ nInsPos ];
1335  pInsLine->GetTabBoxes().erase( pInsLine->GetTabBoxes().begin() + nInsPos ); // remove again
1336  (*ppMergeBox)->SetUpper( nullptr );
1337  (*ppMergeBox)->ClaimFrameFormat();
1338 
1339  // define the border: the upper/left side of the first box,
1340  // the lower/right side of the last box:
1341  if( pLastBox && pFirstBox )
1342  {
1343  SvxBoxItem aBox( pFirstBox->GetFrameFormat()->GetBox() );
1344  const SvxBoxItem& rBox = pLastBox->GetFrameFormat()->GetBox();
1345  aBox.SetLine( rBox.GetRight(), SvxBoxItemLine::RIGHT );
1346  aBox.SetLine( rBox.GetBottom(), SvxBoxItemLine::BOTTOM );
1347  if( aBox.GetLeft() || aBox.GetTop() ||
1348  aBox.GetRight() || aBox.GetBottom() )
1349  (*ppMergeBox)->GetFrameFormat()->SetFormatAttr( aBox );
1350  }
1351  }
1352 
1353  //Block to delete SwPaM, SwPosition from stack
1354  if( !aPosArr.empty() )
1355  {
1356  SwPosition aInsPos( *(*ppMergeBox)->GetSttNd() );
1357  SwNodeIndex& rInsPosNd = aInsPos.nNode;
1358 
1359  SwPaM aPam( aInsPos );
1360 
1361  for( const auto &rPt : aPosArr )
1362  {
1363  aPam.GetPoint()->nNode.Assign( *rPt.pSelBox->GetSttNd()->
1364  EndOfSectionNode(), -1 );
1365  SwContentNode* pCNd = aPam.GetContentNode();
1366  aPam.GetPoint()->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
1367 
1368  SwNodeIndex aSttNdIdx( *rPt.pSelBox->GetSttNd(), 1 );
1369  // one node should be kept in the box (otherwise the
1370  // section would be deleted during a move)
1371  bool const bUndo(pDoc->GetIDocumentUndoRedo().DoesUndo());
1372  if( pUndo )
1373  {
1374  pDoc->GetIDocumentUndoRedo().DoUndo(false);
1375  }
1377  if( pUndo )
1378  {
1379  pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
1380  }
1381  SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
1382  ++rInsPosNd;
1383  if( pUndo )
1384  pUndo->MoveBoxContent( pDoc, aRg, rInsPosNd );
1385  else
1386  {
1387  pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, rInsPosNd,
1389  }
1390  // where is now aInsPos ??
1391 
1392  if( bCalcWidth )
1393  bCalcWidth = false; // one line is ready
1394 
1395  // skip the first TextNode
1396  rInsPosNd.Assign( pDoc->GetNodes(),
1397  rInsPosNd.GetNode().EndOfSectionIndex() - 2 );
1398  SwTextNode* pTextNd = rInsPosNd.GetNode().GetTextNode();
1399  if( pTextNd )
1400  aInsPos.nContent.Assign(pTextNd, pTextNd->GetText().getLength());
1401  }
1402 
1403  // the MergeBox should contain the complete text
1404  // now erase the initial TextNode
1405  OSL_ENSURE( (*ppMergeBox)->GetSttIdx()+2 <
1406  (*ppMergeBox)->GetSttNd()->EndOfSectionIndex(),
1407  "empty box" );
1408  SwNodeIndex aIdx( *(*ppMergeBox)->GetSttNd()->EndOfSectionNode(), -1 );
1409  pDoc->GetNodes().Delete( aIdx );
1410  }
1411 
1412  // set width of the box
1413  (*ppMergeBox)->GetFrameFormat()->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth, 0 ));
1414  if( pUndo )
1415  pUndo->AddNewBox( (*ppMergeBox)->GetSttIdx() );
1416 }
1417 
1418 static bool lcl_CheckCol(FndBox_ const&, bool* pPara);
1419 
1420 static bool lcl_CheckRow( const FndLine_& rFndLine, bool* pPara )
1421 {
1422  for (auto const& it : rFndLine.GetBoxes())
1423  {
1424  lcl_CheckCol(*it, pPara);
1425  }
1426  return *pPara;
1427 }
1428 
1429 static bool lcl_CheckCol( FndBox_ const& rFndBox, bool* pPara )
1430 {
1431  if (!rFndBox.GetBox()->GetSttNd())
1432  {
1433  if (rFndBox.GetLines().size() !=
1434  rFndBox.GetBox()->GetTabLines().size())
1435  {
1436  *pPara = false;
1437  }
1438  else
1439  {
1440  for (auto const& rpFndLine : rFndBox.GetLines())
1441  {
1442  lcl_CheckRow( *rpFndLine, pPara );
1443  }
1444  }
1445  }
1446  // is box protected ??
1447  else if (rFndBox.GetBox()->GetFrameFormat()->GetProtect().IsContentProtected())
1448  *pPara = false;
1449  return *pPara;
1450 }
1451 
1453 {
1454  SwSelBoxes aBoxes;
1455 //JP 24.09.96: Merge with repeating TableHeadLines does not work properly.
1456 // Why not use point 0,0? Then it is assured the first
1457 // headline is contained.
1458 
1459  Point aPt;
1460  const SwContentNode* pCntNd = rPam.GetContentNode();
1461  std::pair<Point, bool> tmp(aPt, true);
1462  const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
1464  nullptr, &tmp)->GetUpper();
1465  pCntNd = rPam.GetContentNode(false);
1466  const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
1468  nullptr, &tmp)->GetUpper();
1469  GetTableSel( pStart, pEnd, aBoxes, nullptr );
1470  return CheckMergeSel( aBoxes );
1471 }
1472 
1474 {
1476  if( !rBoxes.empty() )
1477  {
1478  eRet = TableMergeErr::Ok;
1479 
1480  FndBox_ aFndBox( nullptr, nullptr );
1481  FndPara aPara( rBoxes, &aFndBox );
1482  const SwTableNode* pTableNd = aPara.rBoxes[0]->GetSttNd()->FindTableNode();
1483  ForEach_FndLineCopyCol( const_cast<SwTableLines&>(pTableNd->GetTable().GetTabLines()), &aPara );
1484  if( !aFndBox.GetLines().empty() )
1485  {
1486  bool bMergeSelOk = true;
1487  FndBox_* pFndBox = &aFndBox;
1488  FndLine_* pFndLine = nullptr;
1489  while( pFndBox && 1 == pFndBox->GetLines().size() )
1490  {
1491  pFndLine = pFndBox->GetLines().front().get();
1492  if( 1 == pFndLine->GetBoxes().size() )
1493  pFndBox = pFndLine->GetBoxes().front().get();
1494  else
1495  pFndBox = nullptr;
1496  }
1497  if( pFndBox )
1498  {
1499  for (auto const& it : pFndBox->GetLines())
1500  {
1501  lcl_CheckRow(*it, &bMergeSelOk);
1502  }
1503  }
1504  else if( pFndLine )
1505  {
1506  for (auto const& it : pFndLine->GetBoxes())
1507  {
1508  lcl_CheckCol(*it, &bMergeSelOk);
1509  }
1510  }
1511  if( !bMergeSelOk )
1513  }
1514  else
1516  }
1517  return eRet;
1518 }
1519 
1520 static SwTwips lcl_CalcWish( const SwLayoutFrame *pCell, long nWish,
1521  const long nAct )
1522 {
1523  const SwLayoutFrame *pTmp = pCell;
1524  if ( !nWish )
1525  nWish = 1;
1526 
1527  const bool bRTL = pCell->IsRightToLeft();
1528  SwTwips nRet = bRTL ?
1529  nAct - pCell->getFrameArea().Width() :
1530  0;
1531 
1532  while ( pTmp )
1533  {
1534  while ( pTmp->GetPrev() )
1535  {
1536  pTmp = static_cast<const SwLayoutFrame*>(pTmp->GetPrev());
1537  sal_Int64 nTmp = pTmp->GetFormat()->GetFrameSize().GetWidth();
1538  // multiply in 64-bit to avoid overflow here!
1539  nRet += ( bRTL ? -1 : 1 ) * nTmp * nAct / nWish;
1540  }
1541  pTmp = pTmp->GetUpper()->GetUpper();
1542  if ( pTmp && !pTmp->IsCellFrame() )
1543  pTmp = nullptr;
1544  }
1545  return nRet;
1546 }
1547 
1548 static void lcl_FindStartEndRow( const SwLayoutFrame *&rpStart,
1549  const SwLayoutFrame *&rpEnd,
1550  const bool bChkProtected )
1551 {
1552  // Put Start at beginning of a row.
1553  // Put End at the end of its row.
1554  rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetUpper()->Lower());
1555  while ( rpEnd->GetNext() )
1556  rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetNext());
1557 
1558  std::deque<const SwLayoutFrame *> aSttArr, aEndArr;
1559  const SwLayoutFrame *pTmp;
1560  for( pTmp = rpStart; (SwFrameType::Cell|SwFrameType::Row) & pTmp->GetType();
1561  pTmp = pTmp->GetUpper() )
1562  {
1563  aSttArr.push_front( pTmp );
1564  }
1565  for( pTmp = rpEnd; (SwFrameType::Cell|SwFrameType::Row) & pTmp->GetType();
1566  pTmp = pTmp->GetUpper() )
1567  {
1568  aEndArr.push_front( pTmp );
1569  }
1570 
1571  for( std::deque<const SwLayoutFrame *>::size_type n = 0; n < aEndArr.size() && n < aSttArr.size(); ++n )
1572  if( aSttArr[ n ] != aEndArr[ n ] )
1573  {
1574  // first unequal line or box - all odds are
1575  if( n & 1 ) // 1, 3, 5, ... are boxes
1576  {
1577  rpStart = aSttArr[ n ];
1578  rpEnd = aEndArr[ n ];
1579  }
1580  else // 0, 2, 4, ... are lines
1581  {
1582  // check if start & end line are the first & last Line of the
1583  // box. If not return these cells.
1584  // Else the whole line with all Boxes has to be deleted.
1585  rpStart = aSttArr[ n+1 ];
1586  rpEnd = aEndArr[ n+1 ];
1587  if( n )
1588  {
1589  const SwCellFrame* pCellFrame = static_cast<const SwCellFrame*>(aSttArr[ n-1 ]);
1590  const SwTableLines& rLns = pCellFrame->
1591  GetTabBox()->GetTabLines();
1592  if( rLns[ 0 ] == static_cast<const SwRowFrame*>(aSttArr[ n ])->GetTabLine() &&
1593  rLns[ rLns.size() - 1 ] ==
1594  static_cast<const SwRowFrame*>(aEndArr[ n ])->GetTabLine() )
1595  {
1596  rpStart = rpEnd = pCellFrame;
1597  while ( rpStart->GetPrev() )
1598  rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetPrev());
1599  while ( rpEnd->GetNext() )
1600  rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetNext());
1601  }
1602  }
1603  }
1604  break;
1605  }
1606 
1607  if( !bChkProtected ) // protected cell ?
1608  return;
1609 
1610  // Beginning and end should not be in protected cells
1611  while ( rpStart->GetFormat()->GetProtect().IsContentProtected() )
1612  rpStart = static_cast<const SwLayoutFrame*>(rpStart->GetNext());
1613  while ( rpEnd->GetFormat()->GetProtect().IsContentProtected() )
1614  rpEnd = static_cast<const SwLayoutFrame*>(rpEnd->GetPrev());
1615 }
1616 
1617 static void lcl_FindStartEndCol( const SwLayoutFrame *&rpStart,
1618  const SwLayoutFrame *&rpEnd,
1619  const bool bChkProtected )
1620 {
1621  // Beginning and end vertical till the border of the table;
1622  // Consider the whole table, including master and follows.
1623  // In order to start we need the mother-tableFrame
1624  if( !rpStart )
1625  return;
1626  const SwTabFrame *pOrg = rpStart->FindTabFrame();
1627  const SwTabFrame *pTab = pOrg;
1628 
1629  SwRectFnSet aRectFnSet(pTab);
1630 
1631  bool bRTL = pTab->IsRightToLeft();
1632  const long nTmpWish = pOrg->GetFormat()->GetFrameSize().GetWidth();
1633  const long nWish = ( nTmpWish > 0 ) ? nTmpWish : 1;
1634 
1635  while ( pTab->IsFollow() )
1636  {
1637  const SwFrame *pTmp = pTab->FindPrev();
1638  OSL_ENSURE( pTmp->IsTabFrame(), "Predecessor of Follow is not Master." );
1639  pTab = static_cast<const SwTabFrame*>(pTmp);
1640  }
1641 
1642  SwTwips nSX = 0;
1643  SwTwips nSX2 = 0;
1644 
1645  if ( pTab->GetTable()->IsNewModel() )
1646  {
1647  nSX = aRectFnSet.GetLeft(rpStart->getFrameArea());
1648  nSX2 = aRectFnSet.GetRight(rpStart->getFrameArea());
1649  }
1650  else
1651  {
1652  const SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
1653  nSX = ::lcl_CalcWish( rpStart, nWish, nPrtWidth ) + aRectFnSet.GetPrtLeft(*pTab);
1654  nSX2 = nSX + (rpStart->GetFormat()->GetFrameSize().GetWidth() * nPrtWidth / nWish);
1655  }
1656 
1657  const SwLayoutFrame *pTmp = pTab->FirstCell();
1658 
1659  while ( pTmp &&
1660  (!pTmp->IsCellFrame() ||
1661  ( ( ! bRTL && aRectFnSet.GetLeft(pTmp->getFrameArea()) < nSX &&
1662  aRectFnSet.GetRight(pTmp->getFrameArea())< nSX2 ) ||
1663  ( bRTL && aRectFnSet.GetLeft(pTmp->getFrameArea()) > nSX &&
1664  aRectFnSet.GetRight(pTmp->getFrameArea())> nSX2 ) ) ) )
1665  pTmp = pTmp->GetNextLayoutLeaf();
1666 
1667  if ( pTmp )
1668  rpStart = pTmp;
1669 
1670  pTab = pOrg;
1671 
1672  const SwTabFrame* pLastValidTab = pTab;
1673  while ( pTab->GetFollow() )
1674  {
1675 
1676  // Check if pTab->GetFollow() is a valid follow table:
1677  // Only follow tables with at least on non-FollowFlowLine
1678  // should be considered.
1679 
1680  if ( pTab->HasFollowFlowLine() )
1681  {
1682  pTab = pTab->GetFollow();
1683  const SwFrame* pTmpRow = pTab->GetFirstNonHeadlineRow();
1684  if ( pTmpRow && pTmpRow->GetNext() )
1685  pLastValidTab = pTab;
1686  }
1687  else
1688  pLastValidTab = pTab = pTab->GetFollow();
1689  }
1690  pTab = pLastValidTab;
1691 
1692  SwTwips nEX = 0;
1693 
1694  if ( pTab->GetTable()->IsNewModel() )
1695  {
1696  nEX = aRectFnSet.GetLeft(rpEnd->getFrameArea());
1697  }
1698  else
1699  {
1700  const SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
1701  nEX = ::lcl_CalcWish( rpEnd, nWish, nPrtWidth ) + aRectFnSet.GetPrtLeft(*pTab);
1702  }
1703 
1704  SwFrame const*const pLastContent = pTab->FindLastContentOrTable();
1705  rpEnd = pLastContent ? pLastContent->GetUpper() : nullptr;
1706  // --> Made code robust. If pTab does not have a lower,
1707  // we would crash here.
1708  if ( !pLastContent ) return;
1709 
1710  while( !rpEnd->IsCellFrame() )
1711  rpEnd = rpEnd->GetUpper();
1712 
1713  while ( ( bRTL && aRectFnSet.GetLeft(rpEnd->getFrameArea()) < nEX ) ||
1714  ( ! bRTL && aRectFnSet.GetLeft(rpEnd->getFrameArea()) > nEX ) )
1715  {
1716  const SwLayoutFrame* pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
1717  if( !pTmpLeaf || !pTab->IsAnLower( pTmpLeaf ) )
1718  break;
1719  rpEnd = pTmpLeaf;
1720  }
1721 
1722  if( !bChkProtected ) // check for protected cell ?
1723  return;
1724 
1725  // Beginning and end should not be in protected cells.
1726  // If necessary we should search backwards again
1727  while ( rpStart->GetFormat()->GetProtect().IsContentProtected() )
1728  {
1729  const SwLayoutFrame *pTmpLeaf = rpStart->GetNextLayoutLeaf();
1730  while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) > nEX ) // first skip line
1731  pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
1732  while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) < nSX &&
1733  aRectFnSet.GetRight(pTmpLeaf->getFrameArea())< nSX2 )
1734  pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
1735  const SwTabFrame *pTmpTab = rpStart->FindTabFrame();
1736  if ( !pTmpTab->IsAnLower( pTmpLeaf ) )
1737  {
1738  pTmpTab = pTmpTab->GetFollow();
1739  rpStart = pTmpTab->FirstCell();
1740  while ( rpStart &&
1741  aRectFnSet.GetLeft(rpStart->getFrameArea()) < nSX &&
1742  aRectFnSet.GetRight(rpStart->getFrameArea())< nSX2 )
1743  rpStart = rpStart->GetNextLayoutLeaf();
1744  }
1745  else
1746  rpStart = pTmpLeaf;
1747  }
1748  while ( rpEnd->GetFormat()->GetProtect().IsContentProtected() )
1749  {
1750  const SwLayoutFrame *pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
1751  while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) < nEX ) // skip the line for now
1752  pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
1753  while ( pTmpLeaf && aRectFnSet.GetLeft(pTmpLeaf->getFrameArea()) > nEX )
1754  pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
1755  const SwTabFrame *pTmpTab = rpEnd->FindTabFrame();
1756  if ( !pTmpLeaf || !pTmpTab->IsAnLower( pTmpLeaf ) )
1757  {
1758  pTmpTab = static_cast<const SwTabFrame*>(pTmpTab->FindPrev());
1759  OSL_ENSURE( pTmpTab->IsTabFrame(), "Predecessor of Follow not Master.");
1760  rpEnd = pTmpTab->FindLastContentOrTable()->GetUpper();
1761  while( !rpEnd->IsCellFrame() )
1762  rpEnd = rpEnd->GetUpper();
1763  while ( aRectFnSet.GetLeft(rpEnd->getFrameArea()) > nEX )
1764  rpEnd = rpEnd->GetPrevLayoutLeaf();
1765  }
1766  else
1767  rpEnd = pTmpLeaf;
1768  }
1769 }
1770 
1771 void MakeSelUnions( SwSelUnions& rUnions, const SwLayoutFrame *pStart,
1772  const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType )
1773 {
1774  while ( pStart && !pStart->IsCellFrame() )
1775  pStart = pStart->GetUpper();
1776  while ( pEnd && !pEnd->IsCellFrame() )
1777  pEnd = pEnd->GetUpper();
1778 
1779  if ( !pStart || !pEnd )
1780  {
1781  OSL_FAIL( "MakeSelUnions with pStart or pEnd not in CellFrame" );
1782  return;
1783  }
1784 
1785  const SwTabFrame *pTable = pStart->FindTabFrame();
1786  const SwTabFrame *pEndTable = pEnd->FindTabFrame();
1787  if( !pTable || !pEndTable )
1788  return;
1789  bool bExchange = false;
1790 
1791  if ( pTable != pEndTable )
1792  {
1793  if ( !pTable->IsAnFollow( pEndTable ) )
1794  {
1795  OSL_ENSURE( pEndTable->IsAnFollow( pTable ), "Tabchain in knots." );
1796  bExchange = true;
1797  }
1798  }
1799  else
1800  {
1801  SwRectFnSet aRectFnSet(pTable);
1802  long nSttTop = aRectFnSet.GetTop(pStart->getFrameArea());
1803  long nEndTop = aRectFnSet.GetTop(pEnd->getFrameArea());
1804  if( nSttTop == nEndTop )
1805  {
1806  if( aRectFnSet.GetLeft(pStart->getFrameArea()) >
1807  aRectFnSet.GetLeft(pEnd->getFrameArea()) )
1808  bExchange = true;
1809  }
1810  else if( aRectFnSet.IsVert() == ( nSttTop < nEndTop ) )
1811  bExchange = true;
1812  }
1813  if ( bExchange )
1814  {
1815  const SwLayoutFrame *pTmp = pStart;
1816  pStart = pEnd;
1817  pEnd = pTmp;
1818  // do no resort pTable and pEndTable, set new below
1819  // MA: 28. Dec. 93 Bug: 5190
1820  }
1821 
1822  // Beginning and end now nicely sorted, if required we
1823  // should move them
1824  if( SwTableSearchType::Row == ((~SwTableSearchType::Protect ) & eSearchType ) )
1825  ::lcl_FindStartEndRow( pStart, pEnd, bool(SwTableSearchType::Protect & eSearchType) );
1826  else if( SwTableSearchType::Col == ((~SwTableSearchType::Protect ) & eSearchType ) )
1827  ::lcl_FindStartEndCol( pStart, pEnd, bool(SwTableSearchType::Protect & eSearchType) );
1828 
1829  if ( !pEnd || !pStart ) return; // Made code robust.
1830 
1831  // retrieve again, as they have been moved
1832  pTable = pStart->FindTabFrame();
1833  pEndTable = pEnd->FindTabFrame();
1834 
1835  const long nStSz = pStart->GetFormat()->GetFrameSize().GetWidth();
1836  const long nEdSz = pEnd->GetFormat()->GetFrameSize().GetWidth();
1837  const long nWish = std::max( 1L, pTable->GetFormat()->GetFrameSize().GetWidth() );
1838  while ( pTable )
1839  {
1840  SwRectFnSet aRectFnSet(pTable);
1841  const long nOfst = aRectFnSet.GetPrtLeft(*pTable);
1842  const long nPrtWidth = aRectFnSet.GetWidth(pTable->getFramePrintArea());
1843  long nSt1 = ::lcl_CalcWish( pStart, nWish, nPrtWidth ) + nOfst;
1844  long nEd1 = ::lcl_CalcWish( pEnd, nWish, nPrtWidth ) + nOfst;
1845 
1846  if ( nSt1 <= nEd1 )
1847  nEd1 += static_cast<long>((nEdSz * nPrtWidth) / nWish) - 1;
1848  else
1849  nSt1 += static_cast<long>((nStSz * nPrtWidth) / nWish) - 1;
1850 
1851  long nSt2;
1852  long nEd2;
1853  if( pTable->IsAnLower( pStart ) )
1854  nSt2 = aRectFnSet.GetTop(pStart->getFrameArea());
1855  else
1856  nSt2 = aRectFnSet.GetTop(pTable->getFrameArea());
1857  if( pTable->IsAnLower( pEnd ) )
1858  nEd2 = aRectFnSet.GetBottom(pEnd->getFrameArea());
1859  else
1860  nEd2 = aRectFnSet.GetBottom(pTable->getFrameArea());
1861  Point aSt, aEd;
1862  if( nSt1 > nEd1 )
1863  {
1864  long nTmp = nSt1;
1865  nSt1 = nEd1;
1866  nEd1 = nTmp;
1867  }
1868  if( nSt2 > nEd2 )
1869  {
1870  long nTmp = nSt2;
1871  nSt2 = nEd2;
1872  nEd2 = nTmp;
1873  }
1874  if( aRectFnSet.IsVert() )
1875  {
1876  aSt = Point( nSt2, nSt1 );
1877  aEd = Point( nEd2, nEd1 );
1878  }
1879  else
1880  {
1881  aSt = Point( nSt1, nSt2 );
1882  aEd = Point( nEd1, nEd2 );
1883  }
1884 
1885  const Point aDiff( aEd - aSt );
1886  SwRect aUnion( aSt, Size( aDiff.X(), aDiff.Y() ) );
1887  aUnion.Justify();
1888 
1889  if( !(SwTableSearchType::NoUnionCorrect & eSearchType ))
1890  {
1891  // Unfortunately the union contains rounding errors now, therefore
1892  // erroneous results could occur during split/merge.
1893  // To prevent these we will determine the first and last row
1894  // within the union and use their values for a new union
1895  const SwLayoutFrame* pRow = pTable->IsFollow() ?
1896  pTable->GetFirstNonHeadlineRow() :
1897  static_cast<const SwLayoutFrame*>(pTable->Lower());
1898 
1899  while ( pRow && !pRow->getFrameArea().IsOver( aUnion ) )
1900  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
1901 
1902  // #i31976#
1903  // A follow flow row may contain empty cells. These are not
1904  // considered by FirstCell(). Therefore we have to find
1905  // the first cell manually:
1906  const SwFrame* pTmpCell = nullptr;
1907  if ( pTable->IsFollow() && pRow && pRow->IsInFollowFlowRow() )
1908  {
1909  const SwFrame* pTmpRow = pRow;
1910  while ( pTmpRow && pTmpRow->IsRowFrame() )
1911  {
1912  pTmpCell = static_cast<const SwRowFrame*>(pTmpRow)->Lower();
1913  pTmpRow = static_cast<const SwCellFrame*>(pTmpCell)->Lower();
1914  }
1915  OSL_ENSURE( !pTmpCell || pTmpCell->IsCellFrame(), "Lower of rowframe != cellframe?!" );
1916  }
1917 
1918  const SwLayoutFrame* pFirst = pTmpCell ?
1919  static_cast<const SwLayoutFrame*>(pTmpCell) :
1920  pRow ?
1921  pRow->FirstCell() :
1922  nullptr;
1923 
1924  while ( pFirst && !::IsFrameInTableSel( aUnion, pFirst ) )
1925  {
1926  if ( pFirst->GetNext() )
1927  {
1928  pFirst = static_cast<const SwLayoutFrame*>(pFirst->GetNext());
1929  if ( pFirst->Lower() && pFirst->Lower()->IsRowFrame() )
1930  pFirst = pFirst->FirstCell();
1931  }
1932  else
1933  pFirst = ::lcl_FindNextCellFrame( pFirst );
1934  }
1935  const SwLayoutFrame* pLast = nullptr;
1936  SwFrame const*const pLastContent = pTable->FindLastContentOrTable();
1937  if ( pLastContent )
1938  pLast = ::lcl_FindCellFrame( pLastContent->GetUpper() );
1939 
1940  while ( pLast && !::IsFrameInTableSel( aUnion, pLast ) )
1941  pLast = ::lcl_FindCellFrame( pLast->GetPrevLayoutLeaf() );
1942 
1943  if ( pFirst && pLast ) //Robust
1944  {
1945  aUnion = pFirst->getFrameArea();
1946  aUnion.Union( pLast->getFrameArea() );
1947  }
1948  else
1949  aUnion.Width( 0 );
1950  }
1951 
1952  if( aRectFnSet.GetWidth(aUnion) )
1953  {
1954  rUnions.emplace_back(aUnion, const_cast<SwTabFrame*>(pTable));
1955  }
1956 
1957  pTable = pTable->GetFollow();
1958  if ( pTable != pEndTable && pEndTable->IsAnFollow( pTable ) )
1959  pTable = nullptr;
1960  }
1961 }
1962 
1963 bool CheckSplitCells( const SwCursorShell& rShell, sal_uInt16 nDiv,
1964  const SwTableSearchType eSearchType )
1965 {
1966  if( !rShell.IsTableMode() )
1967  rShell.GetCursor();
1968 
1969  return CheckSplitCells( *rShell.getShellCursor(false), nDiv, eSearchType );
1970 }
1971 
1972 bool CheckSplitCells( const SwCursor& rCursor, sal_uInt16 nDiv,
1973  const SwTableSearchType eSearchType )
1974 {
1975  if( 1 >= nDiv )
1976  return false;
1977 
1978  sal_uInt16 nMinValue = nDiv * MINLAY;
1979 
1980  // Get start and end cell
1981  Point aPtPos, aMkPos;
1982  const SwShellCursor* pShCursor = dynamic_cast<const SwShellCursor*>(&rCursor);
1983  if( pShCursor )
1984  {
1985  aPtPos = pShCursor->GetPtPos();
1986  aMkPos = pShCursor->GetMkPos();
1987  }
1988 
1989  const SwContentNode* pCntNd = rCursor.GetContentNode();
1990  std::pair<Point, bool> tmp(aPtPos, true);
1991  const SwLayoutFrame *const pStart = pCntNd->getLayoutFrame(
1993  nullptr, &tmp)->GetUpper();
1994  pCntNd = rCursor.GetContentNode(false);
1995  tmp.first = aMkPos;
1996  const SwLayoutFrame *const pEnd = pCntNd->getLayoutFrame(
1998  nullptr, &tmp)->GetUpper();
1999 
2000  SwRectFnSet aRectFnSet(pStart->GetUpper());
2001 
2002  // First, compute tables and rectangles
2003  SwSelUnions aUnions;
2004 
2005  ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
2006 
2007  // now search boxes for each entry and emit
2008  for ( const auto& rSelUnion : aUnions )
2009  {
2010  const SwTabFrame *pTable = rSelUnion.GetTable();
2011 
2012  // Skip any repeated headlines in the follow:
2013  const SwLayoutFrame* pRow = pTable->IsFollow() ?
2014  pTable->GetFirstNonHeadlineRow() :
2015  static_cast<const SwLayoutFrame*>(pTable->Lower());
2016 
2017  while ( pRow )
2018  {
2019  if ( pRow->getFrameArea().IsOver( rSelUnion.GetUnion() ) )
2020  {
2021  const SwLayoutFrame *pCell = pRow->FirstCell();
2022 
2023  while ( pCell && pRow->IsAnLower( pCell ) )
2024  {
2025  OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" );
2026  if( ::IsFrameInTableSel( rSelUnion.GetUnion(), pCell ) )
2027  {
2028  if( aRectFnSet.GetWidth(pCell->getFrameArea()) < nMinValue )
2029  return false;
2030  }
2031 
2032  if ( pCell->GetNext() )
2033  {
2034  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
2035  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
2036  pCell = pCell->FirstCell();
2037  }
2038  else
2039  pCell = ::lcl_FindNextCellFrame( pCell );
2040  }
2041  }
2042  pRow = static_cast<const SwLayoutFrame*>(pRow->GetNext());
2043  }
2044  }
2045  return true;
2046 }
2047 
2048 // These Classes copy the current table selections (rBoxes),
2049 // into a new structure, retaining the table structure
2050 // new: SS for targeted erasing/restoring of the layout
2051 
2052 static void lcl_InsertRow( SwTableLine const &rLine, SwLayoutFrame *pUpper, SwFrame *pSibling )
2053 {
2054  SwRowFrame *pRow = new SwRowFrame( rLine, pUpper );
2055  if ( pUpper->IsTabFrame() && static_cast<SwTabFrame*>(pUpper)->IsFollow() )
2056  {
2057  SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pUpper);
2058  pTabFrame->FindMaster()->InvalidatePos(); //can absorb the line
2059 
2060  if ( pSibling && pTabFrame->IsInHeadline( *pSibling ) )
2061  {
2062  // Skip any repeated headlines in the follow:
2063  pSibling = pTabFrame->GetFirstNonHeadlineRow();
2064  }
2065  }
2066  pRow->Paste( pUpper, pSibling );
2067  pRow->RegistFlys();
2068 }
2069 
2070 static void FndBoxCopyCol( SwTableBox* pBox, FndPara* pFndPara )
2071 {
2072  std::unique_ptr<FndBox_> pFndBox(new FndBox_( pBox, pFndPara->pFndLine ));
2073  if( !pBox->GetTabLines().empty() )
2074  {
2075  FndPara aPara( *pFndPara, pFndBox.get() );
2076  ForEach_FndLineCopyCol( pFndBox->GetBox()->GetTabLines(), &aPara );
2077  if( pFndBox->GetLines().empty() )
2078  {
2079  return;
2080  }
2081  }
2082  else
2083  {
2084  if( pFndPara->rBoxes.find( pBox ) == pFndPara->rBoxes.end())
2085  {
2086  return;
2087  }
2088  }
2089  pFndPara->pFndLine->GetBoxes().push_back( std::move(pFndBox) );
2090 }
2091 
2092 static void FndLineCopyCol( SwTableLine* pLine, FndPara* pFndPara )
2093 {
2094  std::unique_ptr<FndLine_> pFndLine(new FndLine_(pLine, pFndPara->pFndBox));
2095  FndPara aPara(*pFndPara, pFndLine.get());
2096  for( auto& rpBox : pFndLine->GetLine()->GetTabBoxes() )
2097  FndBoxCopyCol(rpBox, &aPara );
2098  if( !pFndLine->GetBoxes().empty() )
2099  {
2100  pFndPara->pFndBox->GetLines().push_back( std::move(pFndLine) );
2101  }
2102 }
2103 
2105 {
2106  for( SwTableLines::iterator it = rLines.begin(); it != rLines.end(); ++it )
2107  FndLineCopyCol( *it, pFndPara );
2108 }
2109 
2110 void FndBox_::SetTableLines( const SwSelBoxes &rBoxes, const SwTable &rTable )
2111 {
2112  // Set pointers to lines before and after the area to process.
2113  // If the first/last lines are contained in the area, then the pointers
2114  // are 0. We first search for the positions of the first/last affected
2115  // lines in array of the SwTable. In order to use 0 for 'no line'
2116  // we adjust the positions by 1.
2117 
2118  sal_uInt16 nStPos = USHRT_MAX;
2119  sal_uInt16 nEndPos= 0;
2120 
2121  for (size_t i = 0; i < rBoxes.size(); ++i)
2122  {
2123  SwTableLine *pLine = rBoxes[i]->GetUpper();
2124  while ( pLine->GetUpper() )
2125  pLine = pLine->GetUpper()->GetUpper();
2126  const sal_uInt16 nPos = rTable.GetTabLines().GetPos(
2127  const_cast<const SwTableLine*&>(pLine) ) + 1;
2128 
2129  OSL_ENSURE( nPos != USHRT_MAX, "TableLine not found." );
2130 
2131  if( nStPos > nPos )
2132  nStPos = nPos;
2133 
2134  if( nEndPos < nPos )
2135  nEndPos = nPos;
2136  }
2137  if (USHRT_MAX != nStPos && nStPos > 1)
2138  m_pLineBefore = rTable.GetTabLines()[nStPos - 2];
2139  if ( nEndPos < rTable.GetTabLines().size() )
2140  m_pLineBehind = rTable.GetTabLines()[nEndPos];
2141 }
2142 
2143 void FndBox_::SetTableLines( const SwTable &rTable )
2144 {
2145  // Set pointers to lines before and after the area to process.
2146  // If the first/last lines are contained in the area, then the pointers
2147  // are 0. The positions of the first/last affected lines in the array
2148  // of the SwTable are in FndBox. In order to use 0 for 'no line'
2149  // we adjust the positions by 1.
2150 
2151  if( GetLines().empty() )
2152  return;
2153 
2154  SwTableLine* pTmpLine = GetLines().front()->GetLine();
2155  sal_uInt16 nPos = rTable.GetTabLines().GetPos( pTmpLine );
2156  OSL_ENSURE( USHRT_MAX != nPos, "Line is not in table" );
2157  if( nPos )
2158  m_pLineBefore = rTable.GetTabLines()[ nPos - 1 ];
2159 
2160  pTmpLine = GetLines().back()->GetLine();
2161  nPos = rTable.GetTabLines().GetPos( pTmpLine );
2162  OSL_ENSURE( USHRT_MAX != nPos, "Line is not in the table" );
2163  if( ++nPos < rTable.GetTabLines().size() )
2164  m_pLineBehind = rTable.GetTabLines()[nPos];
2165 }
2166 
2167 inline void UnsetFollow( SwFlowFrame *pTab )
2168 {
2169  pTab->m_pPrecede = nullptr;
2170 }
2171 
2173 {
2174  // All lines between pLineBefore and pLineBehind should be cut
2175  // from the layout and erased.
2176  // If this creates empty Follows we should destroy these.
2177  // If a master is destroyed, the follow should become master.
2178  // Always a TabFrame should remain.
2179 
2180  sal_uInt16 nStPos = 0;
2181  sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
2182  if( rTable.IsNewModel() && m_pLineBefore )
2183  rTable.CheckRowSpan( m_pLineBefore, true );
2184  if ( m_pLineBefore )
2185  {
2186  nStPos = rTable.GetTabLines().GetPos(
2187  const_cast<const SwTableLine*&>(m_pLineBefore) );
2188  OSL_ENSURE( nStPos != USHRT_MAX, "The fox stole the line!" );
2189  ++nStPos;
2190  }
2191  if( rTable.IsNewModel() && m_pLineBehind )
2192  rTable.CheckRowSpan( m_pLineBehind, false );
2193  if ( m_pLineBehind )
2194  {
2195  nEndPos = rTable.GetTabLines().GetPos(
2196  const_cast<const SwTableLine*&>(m_pLineBehind) );
2197  OSL_ENSURE( nEndPos != USHRT_MAX, "The fox stole the line!" );
2198  if (nEndPos != 0)
2199  --nEndPos;
2200  }
2201 
2202  for ( sal_uInt16 i = nStPos; i <= nEndPos; ++i)
2203  {
2204  SwFrameFormat *pFormat = rTable.GetTabLines()[i]->GetFrameFormat();
2205  SwIterator<SwRowFrame,SwFormat> aIter( *pFormat );
2206  for ( SwRowFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
2207  {
2208  if ( pFrame->GetTabLine() == rTable.GetTabLines()[i] )
2209  {
2210  bool bDel = true;
2211  SwTabFrame *pUp = !pFrame->GetPrev() && !pFrame->GetNext() ?
2212  static_cast<SwTabFrame*>(pFrame->GetUpper()) : nullptr;
2213  if ( !pUp )
2214  {
2215  const sal_uInt16 nRepeat =
2216  static_cast<SwTabFrame*>(pFrame->GetUpper())->GetTable()->GetRowsToRepeat();
2217  if ( nRepeat > 0 &&
2218  static_cast<SwTabFrame*>(pFrame->GetUpper())->IsFollow() )
2219  {
2220  if ( !pFrame->GetNext() )
2221  {
2222  SwRowFrame* pFirstNonHeadline =
2223  static_cast<SwTabFrame*>(pFrame->GetUpper())->GetFirstNonHeadlineRow();
2224  if ( pFirstNonHeadline == pFrame )
2225  {
2226  pUp = static_cast<SwTabFrame*>(pFrame->GetUpper());
2227  }
2228  }
2229  }
2230  }
2231  if ( pUp )
2232  {
2233  SwTabFrame *pFollow = pUp->GetFollow();
2234  SwTabFrame *pPrev = pUp->IsFollow() ? pUp : nullptr;
2235  if ( pPrev )
2236  {
2237  SwFrame *pTmp = pPrev->FindPrev();
2238  OSL_ENSURE( pTmp->IsTabFrame(),
2239  "Predecessor of Follow is no Master.");
2240  pPrev = static_cast<SwTabFrame*>(pTmp);
2241  }
2242  if ( pPrev )
2243  {
2244  pPrev->SetFollow( pFollow );
2245  // #i60340# Do not transfer the
2246  // flag from pUp to pPrev. pUp may still have the
2247  // flag set although there is not more follow flow
2248  // line associated with pUp.
2249  pPrev->SetFollowFlowLine( false );
2250  }
2251  else if ( pFollow )
2252  ::UnsetFollow( pFollow );
2253 
2254  // A TableFrame should always remain!
2255  if ( pPrev || pFollow )
2256  {
2257  // OD 26.08.2003 #i18103# - if table is in a section,
2258  // lock the section, to avoid its delete.
2259  {
2260  SwSectionFrame* pSctFrame = pUp->FindSctFrame();
2261  bool bOldSectLock = false;
2262  if ( pSctFrame )
2263  {
2264  bOldSectLock = pSctFrame->IsColLocked();
2265  pSctFrame->ColLock();
2266  }
2267  pUp->Cut();
2268  if ( pSctFrame && !bOldSectLock )
2269  {
2270  pSctFrame->ColUnlock();
2271  }
2272  }
2273  SwFrame::DestroyFrame(pUp);
2274  bDel = false; // Row goes to /dev/null.
2275  }
2276  }
2277  if ( bDel )
2278  {
2279  SwFrame* pTabFrame = pFrame->GetUpper();
2280  if ( pTabFrame->IsTabFrame() &&
2281  !pFrame->GetNext() &&
2282  static_cast<SwTabFrame*>(pTabFrame)->GetFollow() )
2283  {
2284  // We do not delete the follow flow line,
2285  // this will be done automatically in the
2286  // next turn.
2287  static_cast<SwTabFrame*>(pTabFrame)->SetFollowFlowLine( false );
2288  }
2289  pFrame->Cut();
2290  SwFrame::DestroyFrame(pFrame);
2291  }
2292  }
2293  }
2294  }
2295 }
2296 
2297 static bool lcl_IsLineOfTableFrame( const SwTabFrame& rTable, const SwFrame& rChk )
2298 {
2299  const SwTabFrame* pTableFrame = rChk.FindTabFrame();
2300  if( pTableFrame->IsFollow() )
2301  pTableFrame = pTableFrame->FindMaster( true );
2302  return &rTable == pTableFrame;
2303 }
2304 
2305 static void lcl_UpdateRepeatedHeadlines( SwTabFrame& rTabFrame, bool bCalcLowers )
2306 {
2307  OSL_ENSURE( rTabFrame.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" );
2308 
2309  // Delete remaining headlines:
2310  SwRowFrame* pLower = nullptr;
2311  while ( nullptr != ( pLower = static_cast<SwRowFrame*>(rTabFrame.Lower()) ) && pLower->IsRepeatedHeadline() )
2312  {
2313  pLower->Cut();
2314  SwFrame::DestroyFrame(pLower);
2315  }
2316 
2317  // Insert fresh set of headlines:
2318  pLower = static_cast<SwRowFrame*>(rTabFrame.Lower());
2319  SwTable& rTable = *rTabFrame.GetTable();
2320  const sal_uInt16 nRepeat = rTable.GetRowsToRepeat();
2321  for ( sal_uInt16 nIdx = 0; nIdx < nRepeat; ++nIdx )
2322  {
2323  SwRowFrame* pHeadline = new SwRowFrame( *rTable.GetTabLines()[ nIdx ], &rTabFrame );
2324  pHeadline->SetRepeatedHeadline( true );
2325  pHeadline->Paste( &rTabFrame, pLower );
2326  pHeadline->RegistFlys();
2327  }
2328 
2329  if ( bCalcLowers )
2330  rTabFrame.SetCalcLowers();
2331 }
2332 
2334 {
2335  // All lines between pLineBefore and pLineBehind should be re-generated in layout.
2336  // And this for all instances of a table (for example in header/footer).
2337  sal_uInt16 nStPos = 0;
2338  sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
2339  if ( m_pLineBefore )
2340  {
2341  nStPos = rTable.GetTabLines().GetPos(
2342  const_cast<const SwTableLine*&>(m_pLineBefore) );
2343  OSL_ENSURE( nStPos != USHRT_MAX, "Fox stole the line!" );
2344  ++nStPos;
2345 
2346  }
2347  if ( m_pLineBehind )
2348  {
2349  nEndPos = rTable.GetTabLines().GetPos(
2350  const_cast<const SwTableLine*&>(m_pLineBehind) );
2351  OSL_ENSURE( nEndPos != USHRT_MAX, "Fox stole the line!" );
2352  --nEndPos;
2353  }
2354  // now big insert operation for all tables.
2355  SwIterator<SwTabFrame,SwFormat> aTabIter( *rTable.GetFrameFormat() );
2356  for ( SwTabFrame *pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2357  {
2358  if ( !pTable->IsFollow() )
2359  {
2360  SwRowFrame *pSibling = nullptr;
2361  SwFrame *pUpperFrame = nullptr;
2362  int i;
2363  for ( i = rTable.GetTabLines().size()-1;
2364  i >= 0 && !pSibling; --i )
2365  {
2367  rTable.GetTabLines()[static_cast<sal_uInt16>(i)];
2369  pSibling = aIter.First();
2370  while ( pSibling && (
2371  pSibling->GetTabLine() != pLine ||
2372  !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2373  pSibling->IsRepeatedHeadline() ||
2374  // #i53647# If !pLineBehind,
2375  // IsInSplitTableRow() should be checked.
2376  ( m_pLineBehind && pSibling->IsInFollowFlowRow() ) ||
2377  (!m_pLineBehind && pSibling->IsInSplitTableRow() ) ) )
2378  {
2379  pSibling = aIter.Next();
2380  }
2381  }
2382  if ( pSibling )
2383  {
2384  pUpperFrame = pSibling->GetUpper();
2385  if ( !m_pLineBehind )
2386  pSibling = nullptr;
2387  }
2388  else
2389 // ???? or is this the last Follow of the table ????
2390  pUpperFrame = pTable;
2391 
2392  for ( sal_uInt16 j = nStPos; j <= nEndPos; ++j )
2393  ::lcl_InsertRow( *rTable.GetTabLines()[j],
2394  static_cast<SwLayoutFrame*>(pUpperFrame), pSibling );
2395  if ( pUpperFrame->IsTabFrame() )
2396  static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2397  }
2398  else if ( rTable.GetRowsToRepeat() > 0 )
2399  {
2400  // Insert new headlines:
2401  lcl_UpdateRepeatedHeadlines( *pTable, true );
2402  }
2403  }
2404 }
2405 
2406 void FndBox_::MakeNewFrames( SwTable &rTable, const sal_uInt16 nNumber,
2407  const bool bBehind )
2408 {
2409  // Create Frames for newly inserted lines
2410  // bBehind == true: before pLineBehind
2411  // == false: after pLineBefore
2412  const sal_uInt16 nBfPos = m_pLineBefore ?
2413  rTable.GetTabLines().GetPos( const_cast<const SwTableLine*&>(m_pLineBefore) ) :
2414  USHRT_MAX;
2415  const sal_uInt16 nBhPos = m_pLineBehind ?
2416  rTable.GetTabLines().GetPos( const_cast<const SwTableLine*&>(m_pLineBehind) ) :
2417  USHRT_MAX;
2418 
2419  //nNumber: how often did we insert
2420  //nCnt: how many were inserted nNumber times
2421 
2422  const sal_uInt16 nCnt =
2423  ((nBhPos != USHRT_MAX ? nBhPos : rTable.GetTabLines().size()) -
2424  (nBfPos != USHRT_MAX ? nBfPos + 1 : 0)) / (nNumber + 1);
2425 
2426  // search the Master-TabFrame
2427  SwIterator<SwTabFrame,SwFormat> aTabIter( *rTable.GetFrameFormat() );
2428  SwTabFrame *pTable;
2429  for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2430  {
2431  if( !pTable->IsFollow() )
2432  {
2433  SwRowFrame* pSibling = nullptr;
2434  SwLayoutFrame *pUpperFrame = nullptr;
2435  if ( bBehind )
2436  {
2437  if ( m_pLineBehind )
2438  {
2440  pSibling = aIter.First();
2441  while ( pSibling && (
2442  // only consider row frames associated with pLineBehind:
2443  pSibling->GetTabLine() != m_pLineBehind ||
2444  // only consider row frames that are in pTables Master-Follow chain:
2445  !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2446  // only consider row frames that are not repeated headlines:
2447  pSibling->IsRepeatedHeadline() ||
2448  // only consider row frames that are not follow flow rows
2449  pSibling->IsInFollowFlowRow() ) )
2450  {
2451  pSibling = aIter.Next();
2452  }
2453  }
2454  if ( pSibling )
2455  pUpperFrame = pSibling->GetUpper();
2456  else
2457  {
2458  while( pTable->GetFollow() )
2459  pTable = pTable->GetFollow();
2460  pUpperFrame = pTable;
2461  }
2462  const sal_uInt16 nMax = nBhPos != USHRT_MAX ?
2463  nBhPos : rTable.GetTabLines().size();
2464 
2465  sal_uInt16 i = nBfPos != USHRT_MAX ? nBfPos + 1 + nCnt : nCnt;
2466 
2467  for ( ; i < nMax; ++i )
2468  ::lcl_InsertRow( *rTable.GetTabLines()[i], pUpperFrame, pSibling );
2469  if ( pUpperFrame->IsTabFrame() )
2470  static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2471  }
2472  else // insert before
2473  {
2474  sal_uInt16 i;
2475 
2476  // We are looking for the frame that is behind the row frame
2477  // that should be inserted.
2478  for ( i = 0; !pSibling; ++i )
2479  {
2480  SwTableLine* pLine = m_pLineBefore ? m_pLineBefore : rTable.GetTabLines()[i];
2481 
2483  pSibling = aIter.First();
2484 
2485  while ( pSibling && (
2486  // only consider row frames associated with pLineBefore:
2487  pSibling->GetTabLine() != pLine ||
2488  // only consider row frames that are in pTables Master-Follow chain:
2489  !lcl_IsLineOfTableFrame( *pTable, *pSibling ) ||
2490  // only consider row frames that are not repeated headlines:
2491  pSibling->IsRepeatedHeadline() ||
2492  // 1. case: pLineBefore == 0:
2493  // only consider row frames that are not follow flow rows
2494  // 2. case: pLineBefore != 0:
2495  // only consider row frames that are not split table rows
2496  // #i37476# If !pLineBefore,
2497  // check IsInFollowFlowRow instead of IsInSplitTableRow.
2498  ( ( !m_pLineBefore && pSibling->IsInFollowFlowRow() ) ||
2499  ( m_pLineBefore && pSibling->IsInSplitTableRow() ) ) ) )
2500  {
2501  pSibling = aIter.Next();
2502  }
2503  }
2504 
2505  pUpperFrame = pSibling->GetUpper();
2506  if ( m_pLineBefore )
2507  pSibling = static_cast<SwRowFrame*>( pSibling->GetNext() );
2508 
2509  sal_uInt16 nMax = nBhPos != USHRT_MAX ?
2510  nBhPos - nCnt :
2511  rTable.GetTabLines().size() - nCnt;
2512 
2513  i = nBfPos != USHRT_MAX ? nBfPos + 1 : 0;
2514  for ( ; i < nMax; ++i )
2515  ::lcl_InsertRow( *rTable.GetTabLines()[i],
2516  pUpperFrame, pSibling );
2517  if ( pUpperFrame->IsTabFrame() )
2518  static_cast<SwTabFrame*>(pUpperFrame)->SetCalcLowers();
2519  }
2520  }
2521  }
2522 
2523  // If necessary headlines should be processed. In order to
2524  // not to fragment good code, we iterate once more.
2525  const sal_uInt16 nRowsToRepeat = rTable.GetRowsToRepeat();
2526  if ( !(nRowsToRepeat > 0 &&
2527  ( ( !bBehind && ( nBfPos == USHRT_MAX || nBfPos + 1 < nRowsToRepeat ) ) ||
2528  ( bBehind && ( ( nBfPos == USHRT_MAX && nRowsToRepeat > 1 ) || nBfPos + 2 < nRowsToRepeat ) ) )) )
2529  return;
2530 
2531  for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
2532  {
2533  if ( pTable->Lower() )
2534  {
2535  if ( pTable->IsFollow() )
2536  {
2537  lcl_UpdateRepeatedHeadlines( *pTable, true );
2538  }
2539 
2540  OSL_ENSURE( static_cast<SwRowFrame*>(pTable->Lower())->GetTabLine() ==
2541  rTable.GetTabLines()[0], "MakeNewFrames: Table corruption!" );
2542  }
2543  }
2544 }
2545 
2546 bool FndBox_::AreLinesToRestore( const SwTable &rTable ) const
2547 {
2548  // Should we call MakeFrames here?
2549 
2550  if ( !m_pLineBefore && !m_pLineBehind && !rTable.GetTabLines().empty() )
2551  return true;
2552 
2553  sal_uInt16 nBfPos;
2554  if(m_pLineBefore)
2555  {
2556  const SwTableLine* rLBefore = const_cast<const SwTableLine*>(m_pLineBefore);
2557  nBfPos = rTable.GetTabLines().GetPos( rLBefore );
2558  }
2559  else
2560  nBfPos = USHRT_MAX;
2561 
2562  sal_uInt16 nBhPos;
2563  if(m_pLineBehind)
2564  {
2565  const SwTableLine* rLBehind = const_cast<const SwTableLine*>(m_pLineBehind);
2566  nBhPos = rTable.GetTabLines().GetPos( rLBehind );
2567  }
2568  else
2569  nBhPos = USHRT_MAX;
2570 
2571  if ( nBfPos == nBhPos ) // Should never occur.
2572  {
2573  OSL_FAIL( "Table, erase but not on any area !?!" );
2574  return false;
2575  }
2576 
2577  if ( rTable.GetRowsToRepeat() > 0 )
2578  {
2579  // oops: should the repeated headline have been deleted??
2581  for( SwTabFrame* pTable = aIter.First(); pTable; pTable = aIter.Next() )
2582  {
2583  if( pTable->IsFollow() )
2584  {
2585  // Insert new headlines:
2586  lcl_UpdateRepeatedHeadlines( *pTable, false );
2587  }
2588  }
2589  }
2590 
2591  // Some adjacent lines at the beginning of the table have been deleted:
2592  if ( nBfPos == USHRT_MAX && nBhPos == 0 )
2593  return false;
2594 
2595  // Some adjacent lines at the end of the table have been deleted:
2596  if ( nBhPos == USHRT_MAX && nBfPos == (rTable.GetTabLines().size() - 1) )
2597  return false;
2598 
2599  // Some adjacent lines in the middle of the table have been deleted:
2600  if ( nBfPos != USHRT_MAX && nBhPos != USHRT_MAX && (nBfPos + 1) == nBhPos )
2601  return false;
2602 
2603  // The structure of the deleted lines is more complex due to split lines.
2604  // A call of MakeFrames() is necessary.
2605  return true;
2606 }
2607 
2608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:339
bool IsTableComplex() const
Definition: swtable.cxx:1446
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
Base class of the Writer layout elements.
Definition: frame.hxx:297
Base class that provides the general functionalities for frames that are allowed at page breaks (flow...
Definition: flowfrm.hxx:58
const FndLines_t & GetLines() const
Definition: tblsel.hxx:173
virtual sal_Int32 Len() const
Definition: node.cxx:1223
virtual void Cut() override
Definition: tabfrm.cxx:3599
void CreateSelection(const SwPaM &rPam, SwSelBoxes &rBoxes, const SearchType eSearchType, bool bProtect) const
void SwTable::CreateSelection(..) fills the selection structure with table cells for a given SwPaM...
sal_uLong GetIndex() const
Definition: node.hxx:282
bool operator<(const SwTextGlyphsKey &l, const SwTextGlyphsKey &r)
Definition: fntcache.cxx:128
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
const SwSelBoxes & rBoxes
Definition: tblsel.hxx:215
SwShellCursor * m_pCurrentCursor
current cursor
Definition: crsrsh.hxx:175
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:963
bool IsFollow() const
Definition: flowfrm.hxx:166
void SetCalcLowers()
Definition: tabfrm.hxx:154
const SwSelBoxes & GetSelectedBoxes() const
Definition: swcrsr.hxx:278
Marks a position in the document model.
Definition: pam.hxx:35
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:41
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:189
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1345
sal_uLong StartOfSectionIndex() const
Definition: node.hxx:673
const OUString & GetText() const
Definition: ndtxt.hxx:211
virtual const SwRootFrame * GetCurrentLayout() const =0
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1883
void ColLock()
Definition: sectfrm.hxx:86
bool IsColLocked() const
Definition: frame.hxx:864
const SwTable * GetTable() const
Definition: tabfrm.hxx:144
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:643
void SetCompletePaint() const
Definition: frame.hxx:972
long GetWidth() const
SwFrameType GetType() const
Definition: frame.hxx:500
SwShellCursor * getShellCursor(bool bBlock)
Delivers the current shell cursor.
Definition: crsrsh.cxx:3025
sal_uIntPtr sal_uLong
static void lcl_InsertRow(SwTableLine const &rLine, SwLayoutFrame *pUpper, SwFrame *pSibling)
Definition: tblsel.cxx:2052
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
#define MINLAY
Definition: swtypes.hxx:66
const SwPosition * GetMark() const
Definition: pam.hxx:209
bool AreLinesToRestore(const SwTable &rTable) const
Definition: tblsel.cxx:2546
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1190
sal_Int64 n
SwFrame * FindPrev()
Definition: frame.hxx:1133
Definition: doc.hxx:184
static void lcl_UpdateRepeatedHeadlines(SwTabFrame &rTabFrame, bool bCalcLowers)
Definition: tblsel.cxx:2305
bool ChkChartSel(const SwNode &rSttNd, const SwNode &rEndNd)
Definition: tblsel.cxx:428
const SwShellTableCursor * GetTableCursor() const
Definition: crsrsh.hxx:645
TElementType * Next()
Definition: calbck.hxx:351
void DelFrames(SwTable &rTable)
Definition: tblsel.cxx:2172
void InvalidatePos()
Definition: frame.hxx:1021
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1356
void GetMergeSel(const SwPaM &rPam, SwSelBoxes &rBoxes, SwTableBox **ppMergeBox, SwUndoTableMerge *pUndo)
Definition: tblsel.cxx:929
const_iterator find(const Value &x) const
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: wsfrm.cxx:1303
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
bool HasProtectedCells(const SwSelBoxes &rBoxes)
Definition: tblsel.cxx:856
bool IsVert() const
Definition: frame.hxx:1345
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:193
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:382
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
bool IsCellFrame() const
Definition: frame.hxx:1204
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
iterator begin()
Definition: swtable.hxx:75
void UnsetFollow(SwFlowFrame *pTab)
Definition: tblsel.cxx:2167
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
void CheckRowSpan(SwTableLine *&rpLine, bool bUp) const
SwTable::CheckRowSpan(..) looks for the next line without an overlapping to the previous line...
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:739
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:169
size_type size() const
Definition: swtable.hxx:74
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
Definition: tblsel.cxx:2104
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
void GetTableSelCrs(const SwCursorShell &rShell, SwSelBoxes &rBoxes)
Definition: tblsel.cxx:124
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
static const SwLayoutFrame * lcl_FindNextCellFrame(const SwLayoutFrame *pLay)
Definition: tblsel.cxx:111
std::deque< SwCellFrame * > SwCellFrames
Definition: tblsel.hxx:41
Point TopLeft() const
Definition: swrect.cxx:174
void Delete(const SwNodeIndex &rPos, sal_uLong nNodes=1)
delete nodes
Definition: nodes.cxx:1071
sal_uInt16 IsFormulaOrValueBox() const
Definition: swtable.cxx:2551
TableMergeErr
Definition: tblenum.hxx:62
static bool lcl_IsLineOfTableFrame(const SwTabFrame &rTable, const SwFrame &rChk)
Definition: tblsel.cxx:2297
bool IsEmptyBox(const SwTableBox &rBox, SwPaM &rPam)
Definition: tblsel.cxx:893
void Top(const long nTop)
Definition: swrect.hxx:204
const SwLayoutFrame * GetPrevLayoutLeaf() const
Definition: frame.hxx:1002
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:177
#define X
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:773
bool InsBoxen(SwTableNode *, SwTableLine *, SwTableBoxFormat *, SwTextFormatColl *, const SfxItemSet *pAutoAttr, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Insert a new box in the line before InsPos.
Definition: ndtbl.cxx:230
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
virtual void DoUndo(bool const bDoUndo)=0
Enable/Disable Undo.
void SetONECalcLowers()
Definition: tabfrm.hxx:156
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:203
const SwTable & GetTable() const
Definition: node.hxx:497
long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1357
long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1358
void Right(const long nRight)
Definition: swrect.hxx:200
size_type size() const
SwShellTableCursor * m_pTableCursor
table Cursor; only in tables when the selection lays over 2 columns
Definition: crsrsh.hxx:181
virtual bool DoesUndo() const =0
Is Undo enabled?
helper class to check if a frame has been deleted during an operation WARNING! This should only be us...
Definition: frmtool.hxx:594
Specific frame formats (frames, DrawObjects).
void MakeFrames(SwTable &rTable)
Definition: tblsel.cxx:2333
Point BottomRight() const
Definition: swrect.cxx:177
std::vector< SwTableLine * >::iterator iterator
Definition: swtable.hxx:67
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:259
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:501
SwFrame * FindLastContentOrTable()
Definition: tabfrm.cxx:3411
Style of a layout element.
Definition: frmfmt.hxx:57
SwTableSearchType
Definition: tblsel.hxx:58
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:717
void SetFollowFlowLine(bool bNew)
Definition: tabfrm.hxx:161
SwTableLine * m_pLineBehind
Definition: tblsel.hxx:164
virtual void Cut() override
Definition: tabfrm.cxx:4540
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void SetTableLines(const SwSelBoxes &rBoxes, const SwTable &rTable)
Definition: tblsel.cxx:2110
int i
void GetTableSel(const SwCursorShell &rShell, SwSelBoxes &rBoxes, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:149
const SwPosition * GetPoint() const
Definition: pam.hxx:207
bool empty() const
Definition: swtable.hxx:73
const SwRect & GetUnion() const
Definition: tblsel.hxx:130
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
static void lcl_FindStartEndCol(const SwLayoutFrame *&rpStart, const SwLayoutFrame *&rpEnd, const bool bChkProtected)
Definition: tblsel.cxx:1617
const SwTabFrame * GetTable() const
Definition: tblsel.hxx:132
const SwFrame * Lower() const
Definition: layfrm.hxx:101
TElementType * First()
Definition: calbck.hxx:343
SwContentNode * GetContentNode()
Definition: node.hxx:615
FlyAnchors.
Definition: fmtanchr.hxx:34
void SetFollow(SwFlowFrame *const pFollow)
Definition: flowfrm.cxx:91
bool IsChgd() const
Definition: swcrsr.hxx:296
SwDoc * GetDoc()
Definition: node.hxx:702
SwDoc * GetDoc() const
Definition: pam.hxx:243
SwLayoutFrame * GetUpper()
Definition: frame.hxx:658
void RegistFlys(SwPageFrame *pPage=nullptr)
Register Flys after a line was created AND inserted Must be called by the creator; the Fly is inserte...
Definition: tabfrm.cxx:3818
#define sal_True
bool IsRowFrame() const
Definition: frame.hxx:1200
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:366
SwFrame * GetPrev()
Definition: frame.hxx:657
const Point & GetMkPos() const
Definition: viscrs.hxx:144
bool IsContentProtected() const
const SwRowFrame * IsInFollowFlowRow() const
Definition: findfrm.cxx:1785
SwFlowFrame * m_pPrecede
Definition: flowfrm.hxx:118
void SetRepeatedHeadline(bool bNew)
Definition: rowfrm.hxx:90
Marks a node in the document model.
Definition: ndindex.hxx:31
void MakeSelUnions(SwSelUnions &rUnions, const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:1771
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:425
const_iterator end() const
void MoveBoxContent(SwDoc *pDoc, SwNodeRange &rRg, SwNodeIndex &rPos)
Definition: untbl.cxx:2005
bool empty() const
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:356
virtual bool MoveNodeRange(SwNodeRange &, SwNodeIndex &, SwMoveFlags)=0
bool MakeTableCursors(SwTableCursor &)
Calculates the cells included from the current selection.
Definition: trvlfrm.cxx:1859
SwTableLines & GetTabLines()
Definition: swtable.hxx:198
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:404
const long LONG_MAX
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:110
#define Y
SwTableLines & GetTabLines()
Definition: swtable.hxx:418
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1093
const SwCellFrame * FirstCell() const
Calls ContainsAny first to reach the innermost cell.
Definition: findfrm.cxx:112
const_iterator begin() const
SwTableLine * m_pLineBefore
Definition: tblsel.hxx:163
long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1389
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:458
bool GetAutoSumSel(const SwCursorShell &rShell, SwCellFrames &rBoxes)
Definition: tblsel.cxx:693
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1359
static const SwLayoutFrame * lcl_FindCellFrame(const SwLayoutFrame *pLay)
Definition: tblsel.cxx:104
static void lcl_InsTableBox(SwTableNode *pTableNd, SwDoc *pDoc, SwTableBox *pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Definition: tblsel.cxx:874
void Left(const long nLeft)
Definition: swrect.hxx:195
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
void Bottom(const long nBottom)
Definition: swrect.hxx:209
void MakeNewFrames(SwTable &rTable, const sal_uInt16 nNumber, const bool bBehind)
Definition: tblsel.cxx:2406
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:354
bool CheckSplitCells(const SwCursorShell &rShell, sal_uInt16 nDiv, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:1963
void Justify()
Definition: swrect.cxx:131
SwRowFrame * GetFirstNonHeadlineRow() const
Definition: tabfrm.cxx:5463
static bool lcl_CheckRow(const FndLine_ &rFndLine, bool *pPara)
Definition: tblsel.cxx:1420
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:439
bool IsTabFrame() const
Definition: frame.hxx:1196
bool IsFrameInTableSel(const SwRect &rUnion, const SwFrame *pCell)
Definition: tblsel.cxx:670
void ColUnlock()
Definition: sectfrm.hxx:87
const SwNodes & GetNodes() const
Definition: ndindex.hxx:156
void Width(long nNew)
Definition: swrect.hxx:187
FndBox_ * pFndBox
Definition: tblsel.hxx:217
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:254
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
std::vector< SwSelUnion > SwSelUnions
Definition: tblsel.hxx:138
const SwTableBox * GetBox() const
Definition: tblsel.hxx:175
static bool lcl_CheckCol(FndBox_ const &, bool *pPara)
Definition: tblsel.cxx:1429
void SaveCollection(const SwTableBox &rBox)
Definition: untbl.cxx:2037
SwNodes & GetNodes()
Definition: doc.hxx:403
size_t GetSelectedBoxesCount() const
Definition: swcrsr.hxx:277
bool IsRightToLeft() const
Definition: frame.hxx:965
#define sal_False
bool HasBeenDeleted() const
return true if mpFrame != 0 and mpFrame is not client of pRegIn false otherwise
Definition: frmtool.cxx:3867
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
const Point & GetPtPos() const
Definition: viscrs.hxx:142
long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1360
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1707
bool IsAnFollow(const SwFlowFrame *pFlow) const
Definition: flowfrm.cxx:670
virtual bool AppendTextNode(SwPosition &rPos)=0
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:352
SwTableBox * GetUpper()
Definition: swtable.hxx:362
const SwTabFrame * GetFollow() const
Definition: tabfrm.hxx:243
Point TopRight() const
Definition: swrect.cxx:175
bool IsVertical() const
Definition: frame.hxx:951
long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1355
SwContentNode * GoNextSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true) const
Go to next content-node that is not protected or hidden (Both set FALSE ==> GoNext/GoPrevious!!!).
Definition: nodes.cxx:1906
static SwTwips lcl_CalcWish(const SwLayoutFrame *pCell, long nWish, const long nAct)
Definition: tblsel.cxx:1520
const SvxProtectItem & GetProtect(bool=true) const
Definition: frmatr.hxx:82
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:96
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
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:475
const SwLayoutFrame * GetNextLayoutLeaf() const
Definition: frame.hxx:998
iterator end()
Definition: swtable.hxx:77
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
Frame is variable in Var-direction.
std::pair< const_iterator, bool > insert(Value &&x)
#define COLFUZZY
Definition: tblsel.cxx:52
std::vector< Value >::size_type size_type
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:123
FndLine_ * pFndLine
Definition: tblsel.hxx:216
bool IsNewModel() const
Definition: swtable.hxx:185
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2069
SwTableLine * GetUpper()
Definition: swtable.hxx:421
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:205
bool HasFollowFlowLine() const
Definition: tabfrm.hxx:160
static void lcl_FindStartEndRow(const SwLayoutFrame *&rpStart, const SwLayoutFrame *&rpEnd, const bool bChkProtected)
Definition: tblsel.cxx:1548
SwRootFrame * getRootFrame()
Definition: frame.hxx:659
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
sal_uInt16 nPos
static void FndLineCopyCol(SwTableLine *pLine, FndPara *pFndPara)
Definition: tblsel.cxx:2092
o3tl::sorted_vector< CmpLPt > MergePos
Definition: tblsel.cxx:90
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:844
size_type erase(const Value &x)
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5444
SwNodeIndex & Assign(SwNodes const &rNds, sal_uLong)
Definition: ndindex.hxx:272
Point BottomLeft() const
Definition: swrect.cxx:176
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:393
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1077
void SetLine(const editeng::SvxBorderLine *pNew, SvxBoxItemLine nLine)
SwFrame * GetNext()
Definition: frame.hxx:656
static void FndBoxCopyCol(SwTableBox *pBox, FndPara *pFndPara)
Definition: tblsel.cxx:2070
TableMergeErr CheckMergeSel(const SwPaM &rPam)
Definition: tblsel.cxx:1452
Base class of the Writer document model elements.
Definition: node.hxx:79