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