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