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