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