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