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