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