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