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 "pagefrm.hxx"
21 : #include "rootfrm.hxx"
22 : #include <IDocumentFieldsAccess.hxx>
23 : #include "viewimp.hxx"
24 : #include "swtable.hxx"
25 : #include "dflyobj.hxx"
26 : #include <anchoreddrawobject.hxx>
27 : #include <fmtanchr.hxx>
28 : #include "viewopt.hxx"
29 : #include "hints.hxx"
30 : #include "dbg_lay.hxx"
31 : #include <ftnidx.hxx>
32 : #include <svl/itemiter.hxx>
33 : #include <editeng/keepitem.hxx>
34 : #include <editeng/ulspitem.hxx>
35 : #include <editeng/brushitem.hxx>
36 : #include <editeng/boxitem.hxx>
37 : #include <fmtlsplt.hxx>
38 : #include <fmtrowsplt.hxx>
39 : #include <fmtsrnd.hxx>
40 : #include <fmtornt.hxx>
41 : #include <fmtpdsc.hxx>
42 : #include <fmtfsize.hxx>
43 : #include <swtblfmt.hxx>
44 : #include "tabfrm.hxx"
45 : #include "rowfrm.hxx"
46 : #include "cellfrm.hxx"
47 : #include "flyfrms.hxx"
48 : #include "txtfrm.hxx"
49 : #include "htmltbl.hxx"
50 : #include "sectfrm.hxx"
51 : #include <fmtfollowtextflow.hxx>
52 : #include <sortedobjs.hxx>
53 : #include <objectformatter.hxx>
54 : #include <layouter.hxx>
55 : #include <switerator.hxx>
56 : #include <DocumentSettingManager.hxx>
57 :
58 : using namespace ::com::sun::star;
59 :
60 1312 : SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ):
61 : SwLayoutFrm( rTab.GetFrmFmt(), pSib ),
62 : SwFlowFrm( (SwFrm&)*this ),
63 1312 : pTable( &rTab )
64 : {
65 : bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove =
66 : bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
67 1312 : bRestrictTableGrowth = bRemoveFollowFlowLinePending = false;
68 : // #i26945#
69 1312 : bConsiderObjsForMinCellHeight = true;
70 1312 : bObjsDoesFit = true;
71 1312 : mbInRecalcLowerRow = false;
72 1312 : mbFixSize = false; //Don't fall for import filter again.
73 1312 : mnType = FRMC_TAB;
74 :
75 : //Create the lines and insert them.
76 1312 : const SwTableLines &rLines = rTab.GetTabLines();
77 1312 : SwFrm *pTmpPrev = 0;
78 7520 : for ( size_t i = 0; i < rLines.size(); ++i )
79 : {
80 6208 : SwRowFrm *pNew = new SwRowFrm( *rLines[i], this );
81 6208 : if( pNew->Lower() )
82 : {
83 6208 : pNew->InsertBehind( this, pTmpPrev );
84 6208 : pTmpPrev = pNew;
85 : }
86 : else
87 0 : delete pNew;
88 : }
89 : OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
90 1312 : }
91 :
92 256 : SwTabFrm::SwTabFrm( SwTabFrm &rTab ) :
93 256 : SwLayoutFrm( rTab.GetFmt(), &rTab ),
94 : SwFlowFrm( (SwFrm&)*this ),
95 512 : pTable( rTab.GetTable() )
96 : {
97 : bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove =
98 : bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
99 256 : bRestrictTableGrowth = bRemoveFollowFlowLinePending = false;
100 : // #i26945#
101 256 : bConsiderObjsForMinCellHeight = true;
102 256 : bObjsDoesFit = true;
103 256 : mbInRecalcLowerRow = false;
104 256 : mbFixSize = false; //Don't fall for import filter again.
105 256 : mnType = FRMC_TAB;
106 :
107 256 : SetFollow( rTab.GetFollow() );
108 256 : rTab.SetFollow( this );
109 256 : }
110 :
111 : extern const SwTable *pColumnCacheLastTable;
112 : extern const SwTabFrm *pColumnCacheLastTabFrm;
113 : extern const SwFrm *pColumnCacheLastCellFrm;
114 : extern const SwTable *pRowCacheLastTable;
115 : extern const SwTabFrm *pRowCacheLastTabFrm;
116 : extern const SwFrm *pRowCacheLastCellFrm;
117 :
118 : //return the SwTabFrm (if any) that this SwTabFrm is a follow flow line for
119 1568 : SwTabFrm* SwTabFrm::GetFollowFlowLineFor()
120 : {
121 1568 : SwFlowFrm *pPrec = GetPrecede();
122 1568 : if (pPrec && pPrec->GetFrm().IsTabFrm())
123 : {
124 0 : SwTabFrm *pPrevTabFrm = (SwTabFrm*)pPrec;
125 : assert(this == pPrevTabFrm->GetFollow());
126 0 : if (pPrevTabFrm->HasFollowFlowLine() && pPrevTabFrm->GetFollow() == this)
127 0 : return pPrevTabFrm;
128 : }
129 1568 : return NULL;
130 : }
131 :
132 4704 : SwTabFrm::~SwTabFrm()
133 : {
134 : //rhbz#907933, we are a follow flow line for something and have been
135 : //deleted, remove ourself as a follow flowline
136 1568 : SwTabFrm* pFlowFrameFor = GetFollowFlowLineFor();
137 1568 : if (pFlowFrameFor)
138 0 : pFlowFrameFor->RemoveFollowFlowLine();
139 :
140 : // There is some terrible code in fetab.cxx, that
141 : // makes use of these global pointers. Obviously
142 : // this code did not consider that a TabFrm can be
143 : // deleted.
144 1568 : if ( this == pColumnCacheLastTabFrm )
145 : {
146 2 : pColumnCacheLastTable = NULL;
147 2 : pColumnCacheLastTabFrm = NULL;
148 2 : pColumnCacheLastCellFrm= NULL;
149 2 : pRowCacheLastTable = NULL;
150 2 : pRowCacheLastTabFrm = NULL;
151 2 : pRowCacheLastCellFrm= NULL;
152 : }
153 3136 : }
154 :
155 0 : void SwTabFrm::JoinAndDelFollows()
156 : {
157 0 : SwTabFrm *pFoll = GetFollow();
158 0 : if ( pFoll->HasFollow() )
159 0 : pFoll->JoinAndDelFollows();
160 0 : pFoll->Cut();
161 0 : SetFollow( pFoll->GetFollow() );
162 0 : delete pFoll;
163 0 : }
164 :
165 414 : void SwTabFrm::RegistFlys()
166 : {
167 : OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "No rows." );
168 :
169 414 : SwPageFrm *pPage = FindPageFrm();
170 414 : if ( pPage )
171 : {
172 258 : SwRowFrm *pRow = (SwRowFrm*)Lower();
173 1306 : do
174 : {
175 1306 : pRow->RegistFlys( pPage );
176 1306 : pRow = (SwRowFrm*)pRow->GetNext();
177 : } while ( pRow );
178 : }
179 414 : }
180 :
181 : void SwInvalidateAll( SwFrm *pFrm, long nBottom );
182 : static void lcl_RecalcRow( SwRowFrm& rRow, long nBottom );
183 : static bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, bool bInva );
184 : // #i26945# - add parameter <_bOnlyRowsAndCells> to control
185 : // that only row and cell frames are formatted.
186 : static bool lcl_InnerCalcLayout( SwFrm *pFrm,
187 : long nBottom,
188 : bool _bOnlyRowsAndCells = false );
189 : // OD 2004-02-18 #106629# - correct type of 1st parameter
190 : // #i26945# - add parameter <_bConsiderObjs> in order to
191 : // control, if floating screen objects have to be considered for the minimal
192 : // cell height.
193 : static SwTwips lcl_CalcMinRowHeight( const SwRowFrm *pRow,
194 : const bool _bConsiderObjs );
195 : static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& );
196 :
197 532 : static SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount )
198 : {
199 532 : if ( !nCount || !pStart)
200 304 : return 0;
201 :
202 228 : SwTwips nRet = 0;
203 228 : SWRECTFN( pStart )
204 704 : while ( pStart && nCount > 0 )
205 : {
206 248 : nRet += (pStart->Frm().*fnRect->fnGetHeight)();
207 248 : pStart = pStart->GetNext();
208 248 : --nCount;
209 : }
210 :
211 228 : return nRet;
212 : }
213 :
214 : // Local helper function to insert a new follow flow line
215 312 : static SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine )
216 : {
217 : OSL_ENSURE( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" );
218 312 : const SwRowFrm& rRow = (SwRowFrm&)rTmpRow;
219 :
220 312 : rTab.SetFollowFlowLine( true );
221 312 : SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false );
222 312 : pFollowFlowLine->SetRowSpanLine( bRowSpanLine );
223 312 : SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow();
224 312 : pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow );
225 312 : return pFollowFlowLine;
226 : }
227 :
228 : // #i26945# - local helper function to invalidate all lower
229 : // objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
230 : // additionally the objects are moved 'out of range'.
231 5540 : static void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm,
232 : const bool _bMoveObjsOutOfRange = false,
233 : SwPageFrm* _pPageFrm = 0L )
234 : {
235 : // determine page frame, if needed
236 5540 : if ( !_pPageFrm )
237 : {
238 1756 : _pPageFrm = _rLayoutFrm.FindPageFrm();
239 : OSL_ENSURE( _pPageFrm,
240 : "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
241 1756 : if ( !_pPageFrm )
242 : {
243 5540 : return;
244 : }
245 : }
246 :
247 : // loop on lower frames
248 5540 : SwFrm* pLowerFrm = _rLayoutFrm.Lower();
249 20232 : while ( pLowerFrm )
250 : {
251 9152 : if ( pLowerFrm->IsLayoutFrm() )
252 : {
253 : ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)),
254 3778 : _bMoveObjsOutOfRange, _pPageFrm );
255 : }
256 9152 : if ( pLowerFrm->GetDrawObjs() )
257 : {
258 222 : for ( size_t i = 0; i < pLowerFrm->GetDrawObjs()->size(); ++i )
259 : {
260 134 : SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i];
261 :
262 : // invalidate position of anchored object
263 134 : pAnchoredObj->SetTmpConsiderWrapInfluence( false );
264 134 : pAnchoredObj->SetConsiderForTextWrap( false );
265 134 : pAnchoredObj->UnlockPosition();
266 134 : pAnchoredObj->InvalidateObjPos();
267 :
268 : // move anchored object 'out of range'
269 134 : if ( _bMoveObjsOutOfRange )
270 : {
271 : // indicate, that positioning is progress to avoid
272 : // modification of the anchored object resp. its attributes
273 : // due to the movement
274 98 : SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
275 98 : pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() );
276 : // #115759# - reset character rectangle,
277 : // top of line and relative position in order to assure,
278 : // that anchored object is correctly positioned.
279 98 : pAnchoredObj->ClearCharRectAndTopOfLine();
280 98 : pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
281 98 : if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
282 : == FLY_AS_CHAR )
283 : {
284 92 : pAnchoredObj->AnchorFrm()
285 : ->Prepare( PREP_FLY_ATTR_CHG,
286 92 : &(pAnchoredObj->GetFrmFmt()) );
287 : }
288 98 : if ( pAnchoredObj->ISA(SwFlyFrm) )
289 : {
290 6 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
291 6 : pFly->GetVirtDrawObj()->SetRectsDirty();
292 6 : pFly->GetVirtDrawObj()->SetChanged();
293 98 : }
294 : }
295 :
296 : // If anchored object is a fly frame, invalidate its lower objects
297 134 : if ( pAnchoredObj->ISA(SwFlyFrm) )
298 : {
299 6 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
300 6 : ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm );
301 : }
302 : }
303 : }
304 9152 : pLowerFrm = pLowerFrm->GetNext();
305 : }
306 : }
307 :
308 : // Local helper function to shrink all lowers of rRow to 0 height
309 918 : static void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow )
310 : {
311 918 : SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower());
312 918 : SWRECTFN( pCurrMasterCell )
313 :
314 3876 : while ( pCurrMasterCell )
315 : {
316 : // NEW TABLES
317 2040 : SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ?
318 : const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) :
319 2040 : *pCurrMasterCell;
320 :
321 : // #i26945#
322 : // all lowers should have the correct position
323 : lcl_ArrangeLowers( &rToAdjust,
324 4080 : (rToAdjust.*fnRect->fnGetPrtTop)(),
325 4080 : false );
326 : // TODO: Optimize number of frames which are set to 0 height
327 : // we have to start with the last lower frame, otherwise
328 : // the shrink will not shrink the current cell
329 2040 : SwFrm* pTmp = rToAdjust.GetLastLower();
330 :
331 2040 : if ( pTmp && pTmp->IsRowFrm() )
332 : {
333 0 : SwRowFrm* pTmpRow = (SwRowFrm*)pTmp;
334 0 : lcl_ShrinkCellsAndAllContent( *pTmpRow );
335 : }
336 : else
337 : {
338 : // TODO: Optimize number of frames which are set to 0 height
339 6950 : while ( pTmp )
340 : {
341 : // the frames have to be shrunk
342 2870 : if ( pTmp->IsTabFrm() )
343 : {
344 66 : SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower();
345 738 : while ( pTmpRow )
346 : {
347 606 : lcl_ShrinkCellsAndAllContent( *pTmpRow );
348 606 : pTmpRow = (SwRowFrm*)pTmpRow->GetNext();
349 : }
350 : }
351 : else
352 : {
353 2804 : pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() );
354 2804 : (pTmp->Prt().*fnRect->fnSetTop)( 0 );
355 2804 : (pTmp->Prt().*fnRect->fnSetHeight)( 0 );
356 : }
357 :
358 2870 : pTmp = pTmp->GetPrev();
359 : }
360 :
361 : // all lowers should have the correct position
362 : lcl_ArrangeLowers( &rToAdjust,
363 4080 : (rToAdjust.*fnRect->fnGetPrtTop)(),
364 4080 : false );
365 : }
366 :
367 2040 : pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext());
368 : }
369 918 : }
370 :
371 : // Local helper function to move the content from rSourceLine to rDestLine
372 : // The content is inserted behind the last content in the corresponding
373 : // cell in rDestLine.
374 254 : static void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine )
375 : {
376 254 : SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower();
377 254 : SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
378 :
379 : // Move content of follow cells into master cells
380 1084 : while ( pCurrSourceCell )
381 : {
382 576 : if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() )
383 : {
384 0 : SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
385 0 : while ( pTmpSourceRow )
386 : {
387 : // #125926# Achtung! It is possible,
388 : // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
389 : // cannot be found. In this case, we have to move the complete
390 : // row.
391 0 : SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower();
392 :
393 0 : if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow )
394 : {
395 : // move content from follow flow row to pTmpDestRow:
396 0 : while ( pTmpDestRow->GetNext() )
397 0 : pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext();
398 :
399 : OSL_ENSURE( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Table contains node" );
400 :
401 0 : lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow );
402 0 : pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() );
403 0 : pTmpSourceRow->Remove();
404 0 : delete pTmpSourceRow;
405 : }
406 : else
407 : {
408 : // move complete row:
409 0 : pTmpSourceRow->Remove();
410 0 : pTmpSourceRow->InsertBefore( pCurrDestCell, 0 );
411 : }
412 :
413 0 : pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
414 : }
415 : }
416 : else
417 : {
418 576 : SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell );
419 576 : if ( pTmp )
420 : {
421 : // NEW TABLES
422 278 : SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell);
423 278 : if ( pDestCell->GetTabBox()->getRowSpan() < 1 )
424 0 : pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true ));
425 :
426 : // Find last content
427 278 : SwFrm* pFrm = pDestCell->GetLastLower();
428 278 : ::RestoreCntnt( pTmp, pDestCell, pFrm, true );
429 : }
430 : }
431 576 : pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext();
432 576 : pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
433 : }
434 254 : }
435 :
436 : // Local helper function to move all footnotes in rRowFrm from
437 : // the footnote boss of rSource to the footnote boss of rDest.
438 210 : static void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm )
439 : {
440 210 : if ( !rSource.GetFmt()->GetDoc()->GetFtnIdxs().empty() )
441 : {
442 0 : SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( true );
443 0 : SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( true );
444 0 : rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, true );
445 : }
446 210 : }
447 :
448 : // Local helper function to handle nested table cells before the split process
449 312 : static void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine,
450 : SwRowFrm& rFollowFlowLine, SwTwips nRemain )
451 : {
452 312 : SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower();
453 312 : SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower();
454 :
455 312 : SWRECTFN( pCurrLastLineCell )
456 :
457 : // Move content of follow cells into master cells
458 1290 : while ( pCurrLastLineCell )
459 : {
460 666 : if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() )
461 : {
462 0 : SwTwips nTmpCut = nRemain;
463 0 : SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower();
464 :
465 : // #i26945#
466 : SwTwips nCurrentHeight =
467 : lcl_CalcMinRowHeight( pTmpLastLineRow,
468 0 : rTab.IsConsiderObjsForMinCellHeight() );
469 0 : while ( pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight )
470 : {
471 0 : nTmpCut -= nCurrentHeight;
472 0 : pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
473 : // #i26945#
474 : nCurrentHeight =
475 : lcl_CalcMinRowHeight( pTmpLastLineRow,
476 0 : rTab.IsConsiderObjsForMinCellHeight() );
477 : }
478 :
479 : // pTmpLastLineRow does not fit to the line or it is the last line
480 : // Check if we can move pTmpLastLineRow to the follow table,
481 : // or if we have to split the line:
482 0 : SwFrm* pCell = pTmpLastLineRow->Lower();
483 0 : bool bTableLayoutToComplex = false;
484 0 : long nMinHeight = 0;
485 :
486 : // We have to take into account:
487 : // 1. The fixed height of the row
488 : // 2. The borders of the cells inside the row
489 : // 3. The minimum height of the row
490 0 : if ( pTmpLastLineRow->HasFixSize() )
491 0 : nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)();
492 : else
493 : {
494 0 : while ( pCell )
495 : {
496 0 : if ( ((SwCellFrm*)pCell)->Lower() &&
497 0 : ((SwCellFrm*)pCell)->Lower()->IsRowFrm() )
498 : {
499 0 : bTableLayoutToComplex = true;
500 0 : break;
501 : }
502 :
503 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
504 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
505 0 : nMinHeight = std::max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) );
506 0 : pCell = pCell->GetNext();
507 0 : }
508 :
509 0 : const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize();
510 0 : if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
511 0 : nMinHeight = std::max( nMinHeight, rSz.GetHeight() );
512 : }
513 :
514 : // 1. Case:
515 : // The line completely fits into the master table.
516 : // Nevertheless, we build a follow (otherwise painting problems
517 : // with empty cell).
518 :
519 : // 2. Case:
520 : // The line has to be split, the minimum height still fits into
521 : // the master table, and the table structure is not to complex.
522 0 : if ( nTmpCut > nCurrentHeight ||
523 0 : ( pTmpLastLineRow->IsRowSplitAllowed() &&
524 0 : !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
525 : {
526 : // The line has to be split:
527 0 : SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false );
528 0 : pNewRow->SetFollowFlowRow( true );
529 0 : pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() );
530 0 : pTmpLastLineRow->SetFollowRow( pNewRow );
531 0 : pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 );
532 0 : pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
533 : }
534 :
535 : // The following lines have to be moved:
536 0 : while ( pTmpLastLineRow )
537 : {
538 0 : SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext();
539 0 : lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow );
540 0 : pTmpLastLineRow->Remove();
541 0 : pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 );
542 0 : pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
543 0 : pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
544 0 : pTmpLastLineRow = pTmp;
545 : }
546 : }
547 :
548 666 : pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext();
549 666 : pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext();
550 : }
551 312 : }
552 :
553 : // Local helper function to handle nested table cells after the split process
554 312 : static void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine )
555 : {
556 312 : SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
557 1290 : while ( pCurrMasterCell )
558 : {
559 1254 : if ( pCurrMasterCell->Lower() &&
560 588 : pCurrMasterCell->Lower()->IsRowFrm() )
561 : {
562 0 : SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower());
563 :
564 0 : if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() )
565 : {
566 : OSL_ENSURE( pRowFrm->GetFollowRow(), "Deleting row frame without follow" );
567 :
568 : // The footnotes have to be moved:
569 0 : lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm );
570 0 : pRowFrm->Cut();
571 0 : SwRowFrm* pFollowRow = pRowFrm->GetFollowRow();
572 0 : pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow );
573 0 : pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() );
574 0 : lcl_MoveRowContent( *pFollowRow, *pRowFrm );
575 0 : pFollowRow->Cut();
576 0 : delete pFollowRow;
577 0 : ::SwInvalidateAll( pCurrMasterCell, LONG_MAX );
578 : }
579 : }
580 :
581 666 : pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
582 : }
583 312 : }
584 :
585 : // Local helper function to re-calculate the split line.
586 386 : inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); }
587 386 : inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); }
588 :
589 312 : static bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine,
590 : SwTwips nRemainingSpaceForLastRow )
591 : {
592 312 : bool bRet = true;
593 :
594 312 : SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper();
595 :
596 : // If there are nested cells in rLastLine, the recalculation of the last
597 : // line needs some preprocessing.
598 312 : lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow );
599 :
600 : // Here the recalculation process starts:
601 312 : rTab.SetRebuildLastLine( true );
602 : // #i26945#
603 312 : rTab.SetDoesObjsFit( true );
604 312 : SWRECTFN( rTab.GetUpper() )
605 :
606 : // #i26945# - invalidate and move floating screen
607 : // objects 'out of range'
608 312 : ::lcl_InvalidateLowerObjs( rLastLine, true );
609 :
610 : // manipulate row and cell sizes
611 :
612 : // #i26945# - Do *not* consider floating screen objects
613 : // for the minimal cell height.
614 312 : rTab.SetConsiderObjsForMinCellHeight( false );
615 312 : ::lcl_ShrinkCellsAndAllContent( rLastLine );
616 312 : rTab.SetConsiderObjsForMinCellHeight( true );
617 :
618 : // invalidate last line
619 312 : ::SwInvalidateAll( &rLastLine, LONG_MAX );
620 :
621 : // Lock this tab frame and its follow
622 312 : bool bUnlockMaster = false;
623 312 : bool bUnlockFollow = false;
624 312 : SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0;
625 312 : if ( pMaster && !pMaster->IsJoinLocked() )
626 : {
627 74 : bUnlockMaster = true;
628 74 : ::TableSplitRecalcLock( pMaster );
629 : }
630 312 : if ( !rTab.GetFollow()->IsJoinLocked() )
631 : {
632 312 : bUnlockFollow = true;
633 312 : ::TableSplitRecalcLock( rTab.GetFollow() );
634 : }
635 :
636 : // Do the recalculation
637 312 : lcl_RecalcRow( rLastLine, LONG_MAX );
638 : // #115759# - force a format of the last line in order to
639 : // get the correct height.
640 312 : rLastLine.InvalidateSize();
641 312 : rLastLine.Calc();
642 :
643 : // Unlock this tab frame and its follow
644 312 : if ( bUnlockFollow )
645 312 : ::TableSplitRecalcUnlock( rTab.GetFollow() );
646 312 : if ( bUnlockMaster )
647 74 : ::TableSplitRecalcUnlock( pMaster );
648 :
649 : // If there are nested cells in rLastLine, the recalculation of the last
650 : // line needs some postprocessing.
651 312 : lcl_PostprocessRowsInCells( rTab, rLastLine );
652 :
653 : // Do a couple of checks on the current situation.
654 :
655 : // If we are not happy with the current situation we return false.
656 : // This will start a new try to split the table, this time we do not
657 : // try to split the table rows.
658 :
659 : // 1. Check if table fits to its upper.
660 : // #i26945# - include check, if objects fit
661 : const SwTwips nDistanceToUpperPrtBottom =
662 312 : (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
663 312 : if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() )
664 172 : bRet = false;
665 :
666 : // 2. Check if each cell in the last line has at least one content frame.
667 :
668 : // Note: a FollowFlowRow may contains empty cells!
669 312 : if ( bRet )
670 : {
671 140 : if ( !rLastLine.IsInFollowFlowRow() )
672 : {
673 134 : SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
674 444 : while ( pCurrMasterCell )
675 : {
676 210 : if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 )
677 : {
678 34 : bRet = false;
679 34 : break;
680 : }
681 176 : pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
682 : }
683 : }
684 : }
685 :
686 : // 3. Check if last line does not contain any content:
687 312 : if ( bRet )
688 : {
689 106 : if ( !rLastLine.ContainsCntnt() )
690 : {
691 0 : bRet = false;
692 : }
693 : }
694 :
695 : // 4. Check if follow flow line does not contain content:
696 312 : if ( bRet )
697 : {
698 106 : if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() )
699 : {
700 0 : bRet = false;
701 : }
702 : }
703 :
704 312 : if ( bRet )
705 : {
706 : // Everything looks fine. Splitting seems to be successful. We invalidate
707 : // rFollowLine to force a new formatting.
708 106 : ::SwInvalidateAll( &rFollowLine, LONG_MAX );
709 : }
710 : else
711 : {
712 : // Splitting the table row gave us an unexpected result.
713 : // Everything has to be prepared for a second try to split
714 : // the table, this time without splitting the row.
715 206 : ::SwInvalidateAll( &rLastLine, LONG_MAX );
716 : }
717 :
718 312 : rTab.SetRebuildLastLine( false );
719 : // #i26945#
720 312 : rTab.SetDoesObjsFit( true );
721 :
722 312 : return bRet;
723 : }
724 :
725 : // Sets the correct height for all spanned cells
726 30 : static void lcl_AdjustRowSpanCells( SwRowFrm* pRow )
727 : {
728 30 : SWRECTFN( pRow )
729 30 : SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower());
730 180 : while ( pCellFrm )
731 : {
732 120 : const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan();
733 120 : if ( nLayoutRowSpan > 1 )
734 : {
735 : // calculate height of cell:
736 20 : const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan );
737 20 : const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
738 20 : if ( nDiff )
739 20 : (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
740 : }
741 :
742 120 : pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
743 : }
744 30 : }
745 :
746 : // Returns the maximum layout row span of the row
747 : // Looking for the next row that contains no covered cells:
748 1676 : static long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow )
749 : {
750 1676 : long nRet = 1;
751 :
752 1676 : const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext());
753 1676 : bool bNextRow = false;
754 :
755 4896 : while ( pCurrentRowFrm )
756 : {
757 : // if there is any covered cell, we proceed to the next row frame
758 1544 : const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower());
759 6496 : while ( pLower )
760 : {
761 3418 : if ( pLower->GetTabBox()->getRowSpan() < 0 )
762 : {
763 10 : ++nRet;
764 10 : bNextRow = true;
765 10 : break;
766 : }
767 3408 : pLower = static_cast<const SwCellFrm*>(pLower->GetNext());
768 : }
769 : pCurrentRowFrm = bNextRow ?
770 10 : static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) :
771 1554 : 0;
772 : }
773 :
774 1676 : return nRet;
775 : }
776 :
777 : // Function to remove the FollowFlowLine of rTab.
778 : // The content of the FollowFlowLine is moved to the associated line in the
779 : // master table.
780 254 : bool SwTabFrm::RemoveFollowFlowLine()
781 : {
782 : // find FollowFlowLine
783 254 : SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow());
784 :
785 : // find last row in master
786 254 : SwFrm* pLastLine = GetLastLower();
787 :
788 : OSL_ENSURE( HasFollowFlowLine() &&
789 : pFollowFlowLine &&
790 : pLastLine, "There should be a flowline in the follow" );
791 :
792 : // We have to reset the flag here, because lcl_MoveRowContent
793 : // calls a GrowFrm(), which has a different bahavior if
794 : // this flag is set.
795 254 : SetFollowFlowLine( false );
796 :
797 : // #140081# Make code robust.
798 254 : if ( !pFollowFlowLine || !pLastLine )
799 0 : return true;
800 :
801 : // Move content
802 254 : lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine );
803 :
804 : // NEW TABLES
805 : // If a row span follow flow line is removed, we want to move the whole span
806 : // to the master:
807 254 : long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine );
808 :
809 254 : if ( nRowsToMove > 1 )
810 : {
811 10 : SWRECTFN( this )
812 10 : SwFrm* pRow = pFollowFlowLine->GetNext();
813 10 : SwFrm* pInsertBehind = GetLastLower();
814 10 : SwTwips nGrow = 0;
815 :
816 30 : while ( pRow && nRowsToMove-- > 1 )
817 : {
818 10 : SwFrm* pNxt = pRow->GetNext();
819 10 : nGrow += (pRow->Frm().*fnRect->fnGetHeight)();
820 :
821 : // The footnotes have to be moved:
822 10 : lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow );
823 :
824 10 : pRow->Remove();
825 10 : pRow->InsertBehind( this, pInsertBehind );
826 10 : pRow->_InvalidateAll();
827 10 : pRow->CheckDirChange();
828 10 : pInsertBehind = pRow;
829 10 : pRow = pNxt;
830 : }
831 :
832 10 : SwFrm* pFirstRow = Lower();
833 50 : while ( pFirstRow )
834 : {
835 30 : lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) );
836 30 : pFirstRow = pFirstRow->GetNext();
837 : }
838 :
839 10 : Grow( nGrow );
840 10 : GetFollow()->Shrink( nGrow );
841 : }
842 :
843 254 : bool bJoin = !pFollowFlowLine->GetNext();
844 254 : pFollowFlowLine->Cut();
845 254 : delete pFollowFlowLine;
846 :
847 254 : return bJoin;
848 : }
849 :
850 : // #i26945# - Floating screen objects are no longer searched.
851 504 : static bool lcl_FindSectionsInRow( const SwRowFrm& rRow )
852 : {
853 504 : bool bRet = false;
854 504 : SwCellFrm* pLower = (SwCellFrm*)rRow.Lower();
855 2118 : while ( pLower )
856 : {
857 1110 : if ( pLower->IsVertical() != rRow.IsVertical() )
858 0 : return true;
859 :
860 1110 : SwFrm* pTmpFrm = pLower->Lower();
861 4082 : while ( pTmpFrm )
862 : {
863 1862 : if ( pTmpFrm->IsRowFrm() )
864 : {
865 0 : bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm );
866 : }
867 : else
868 : {
869 : // #i26945# - search only for sections
870 1862 : bRet = pTmpFrm->IsSctFrm();
871 : }
872 :
873 1862 : if ( bRet )
874 0 : return true;
875 1862 : pTmpFrm = pTmpFrm->GetNext();
876 : }
877 :
878 1110 : pLower = (SwCellFrm*)pLower->GetNext();
879 : }
880 504 : return bRet;
881 : }
882 :
883 504 : bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep )
884 : {
885 504 : bool bRet = true;
886 :
887 504 : SWRECTFN( this )
888 :
889 : // #i26745# - format row and cell frames of table
890 : {
891 504 : this->Lower()->_InvalidatePos();
892 : // #i43913# - correction
893 : // call method <lcl_InnerCalcLayout> with first lower.
894 504 : lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
895 : }
896 :
897 : //In order to be able to compare the positions of the cells whit CutPos,
898 : //they have to be calculated consecutively starting from the table.
899 : //They can definitely be invalid because of position changes of the table.
900 504 : SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower());
901 504 : if( !pRow )
902 0 : return bRet;
903 :
904 504 : const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
905 504 : sal_uInt16 nRowCount = 0; // pRow currently points to the first row
906 :
907 : SwTwips nRemainingSpaceForLastRow =
908 504 : (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() );
909 504 : nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)();
910 :
911 : // Make pRow point to the line that does not fit anymore:
912 21700 : while( pRow->GetNext() &&
913 31188 : nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() +
914 10396 : (IsCollapsingBorders() ?
915 10396 : pRow->GetBottomLineSize() :
916 : 0 ) ) )
917 : {
918 10296 : if( bTryToSplit || !pRow->IsRowSpanLine() ||
919 0 : 0 != (pRow->Frm().*fnRect->fnGetHeight)() )
920 10296 : ++nRowCount;
921 10296 : nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)();
922 10296 : pRow = static_cast<SwRowFrm*>(pRow->GetNext());
923 : }
924 :
925 : // bSplitRowAllowed: Row may be split according to its attributes.
926 : // bTryToSplit: Row will never be split if bTryToSplit = false.
927 : // This can either be passed as a parameter, indicating
928 : // that we are currently doing the second try to split the
929 : // table, or it will be set to falseunder certain
930 : // conditions that are not suitable for splitting
931 : // the row.
932 504 : bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
933 :
934 : // #i29438#
935 : // #i26945# - Floating screen objects no longer forbid
936 : // a splitting of the table row.
937 : // Special DoNotSplit case 1:
938 : // Search for sections inside pRow:
939 504 : if ( lcl_FindSectionsInRow( *pRow ) )
940 : {
941 0 : bTryToSplit = false;
942 : }
943 :
944 : // #i29771#
945 : // To avoid loops, we do some checks before actually trying to split
946 : // the row. Maybe we should keep the next row in this table.
947 : // Note: This is only done if we are at the beginning of our upper
948 504 : bool bKeepNextRow = false;
949 504 : if ( nRowCount < nRepeat )
950 : {
951 : // First case: One of the repeated headline does not fit to the page anymore.
952 : // At least one more non-heading row has to stay in this table in
953 : // order to avoid loops:
954 : OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
955 0 : bKeepNextRow = true;
956 : }
957 504 : else if ( !GetIndPrev() && nRepeat == nRowCount )
958 : {
959 : // Second case: The first non-headline row does not fit to the page.
960 : // If it is not allowed to be split, or it contains a sub-row that
961 : // is not allowed to be split, we keep the row in this table:
962 36 : if ( bTryToSplit && bSplitRowAllowed )
963 : {
964 : // Check if there are (first) rows inside this row,
965 : // which are not allowed to be split.
966 24 : SwCellFrm* pLowerCell = (SwCellFrm*)pRow->Lower();
967 82 : while ( pLowerCell )
968 : {
969 34 : if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() )
970 : {
971 0 : const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower();
972 0 : if ( !pLowerRow->IsRowSplitAllowed() &&
973 0 : (pLowerRow->Frm().*fnRect->fnGetHeight)() >
974 : nRemainingSpaceForLastRow )
975 : {
976 0 : bKeepNextRow = true;
977 0 : break;
978 : }
979 : }
980 34 : pLowerCell = (SwCellFrm*)pLowerCell->GetNext();
981 24 : }
982 : }
983 : else
984 12 : bKeepNextRow = true;
985 : }
986 :
987 : // Better keep the next row in this table:
988 504 : if ( bKeepNextRow )
989 : {
990 12 : pRow = GetFirstNonHeadlineRow();
991 12 : if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() )
992 0 : pRow = static_cast<SwRowFrm*>(pRow->GetNext());
993 12 : if ( pRow )
994 : {
995 12 : pRow = static_cast<SwRowFrm*>(pRow->GetNext());
996 12 : ++nRowCount;
997 : }
998 : }
999 :
1000 : // No more row to split or to move to follow table:
1001 504 : if ( !pRow )
1002 0 : return bRet;
1003 :
1004 : // We try to split the row if
1005 : // - the attributes of the row are set accordingly and
1006 : // - we are allowed to do so
1007 : // - the it should not keep with the next row
1008 1104 : bSplitRowAllowed = bSplitRowAllowed && bTryToSplit &&
1009 596 : ( !bTableRowKeep ||
1010 800 : !pRow->ShouldRowKeepWithNext() );
1011 :
1012 : // Adjust pRow according to the keep-with-next attribute:
1013 504 : if ( !bSplitRowAllowed && bTableRowKeep )
1014 : {
1015 200 : SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev());
1016 200 : SwRowFrm* pOldRow = pRow;
1017 400 : while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
1018 : nRowCount > nRepeat )
1019 : {
1020 0 : pRow = pTmpRow;
1021 0 : --nRowCount;
1022 0 : pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev());
1023 : }
1024 :
1025 : // loop prevention
1026 200 : if ( nRowCount == nRepeat && !GetIndPrev())
1027 : {
1028 0 : pRow = pOldRow;
1029 : }
1030 : }
1031 :
1032 : // If we do not indent to split pRow, we check if we are
1033 : // allowed to move pRow to a follow. Otherwise we return
1034 : // false, indicating an error
1035 504 : if ( !bSplitRowAllowed )
1036 : {
1037 204 : SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
1038 204 : if ( pRow == pFirstNonHeadlineRow )
1039 6 : return false;
1040 :
1041 : // #i91764#
1042 : // Ignore row span lines
1043 198 : SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
1044 396 : while ( pTmpRow && pTmpRow->IsRowSpanLine() )
1045 : {
1046 0 : pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext());
1047 : }
1048 198 : if ( !pTmpRow || pRow == pTmpRow )
1049 : {
1050 0 : return false;
1051 : }
1052 : }
1053 :
1054 : // Build follow table if not already done:
1055 : bool bNewFollow;
1056 : SwTabFrm *pFoll;
1057 498 : if ( GetFollow() )
1058 : {
1059 362 : pFoll = GetFollow();
1060 362 : bNewFollow = false;
1061 : }
1062 : else
1063 : {
1064 136 : bNewFollow = true;
1065 136 : pFoll = new SwTabFrm( *this );
1066 :
1067 : // We give the follow table an initial width.
1068 136 : (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() );
1069 136 : (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() );
1070 136 : (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() );
1071 :
1072 : // Insert the new follow table
1073 136 : pFoll->InsertBehind( GetUpper(), this );
1074 :
1075 : // Repeat the headlines.
1076 138 : for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount )
1077 : {
1078 : // Insert new headlines:
1079 2 : bDontCreateObjects = true; //frmtool
1080 : SwRowFrm* pHeadline = new SwRowFrm(
1081 2 : *GetTable()->GetTabLines()[ nRowCount ], this );
1082 2 : pHeadline->SetRepeatedHeadline( true );
1083 2 : bDontCreateObjects = false;
1084 2 : pHeadline->InsertBefore( pFoll, 0 );
1085 :
1086 2 : SwPageFrm *pPage = pHeadline->FindPageFrm();
1087 2 : const SwFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts();
1088 2 : if( !pTbl->empty() )
1089 : {
1090 : sal_uLong nIndex;
1091 0 : SwCntntFrm* pFrm = pHeadline->ContainsCntnt();
1092 0 : while( pFrm )
1093 : {
1094 0 : nIndex = pFrm->GetNode()->GetIndex();
1095 0 : AppendObjs( pTbl, nIndex, pFrm, pPage );
1096 0 : pFrm = pFrm->GetNextCntntFrm();
1097 0 : if( !pHeadline->IsAnLower( pFrm ) )
1098 0 : break;
1099 : }
1100 : }
1101 : }
1102 : }
1103 :
1104 498 : SwRowFrm* pLastRow = 0; // will point to the last remaining line in master
1105 498 : SwRowFrm* pFollowRow = 0; // points to either the follow flow line of the
1106 : // first regular line in the follow
1107 :
1108 498 : if ( bSplitRowAllowed )
1109 : {
1110 : // If the row that does not fit anymore is allowed
1111 : // to be split, the next row has to be moved to the follow table.
1112 300 : pLastRow = pRow;
1113 300 : pRow = static_cast<SwRowFrm*>(pRow->GetNext());
1114 :
1115 : // new follow flow line for last row of master table
1116 300 : pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false );
1117 : }
1118 : else
1119 : {
1120 198 : pFollowRow = pRow;
1121 :
1122 : // NEW TABLES
1123 : // check if we will break a row span by moving pFollowRow to the follow:
1124 : // In this case we want to reformat the last line.
1125 198 : const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower());
1126 828 : while ( pCellFrm )
1127 : {
1128 444 : if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
1129 : {
1130 12 : pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev());
1131 12 : break;
1132 : }
1133 :
1134 432 : pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext());
1135 : }
1136 :
1137 : // new follow flow line for last row of master table
1138 198 : if ( pLastRow )
1139 12 : pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
1140 : }
1141 :
1142 498 : SwTwips nRet = 0;
1143 :
1144 : //Optimization: There is no paste needed for the new Follow and the
1145 : //optimized insert can be used (big amounts of rows luckily only occurs in
1146 : //such situations).
1147 498 : if ( bNewFollow )
1148 : {
1149 136 : SwFrm* pNxt = 0;
1150 136 : SwFrm* pInsertBehind = pFoll->GetLastLower();
1151 :
1152 4938 : while ( pRow )
1153 : {
1154 4666 : pNxt = pRow->GetNext();
1155 4666 : nRet += (pRow->Frm().*fnRect->fnGetHeight)();
1156 : // The footnotes do not have to be moved, this is done in the
1157 : // MoveFwd of the follow table!!!
1158 4666 : pRow->Remove();
1159 4666 : pRow->InsertBehind( pFoll, pInsertBehind );
1160 4666 : pRow->_InvalidateAll();
1161 4666 : pInsertBehind = pRow;
1162 4666 : pRow = static_cast<SwRowFrm*>(pNxt);
1163 : }
1164 : }
1165 : else
1166 : {
1167 362 : SwFrm* pNxt = 0;
1168 362 : SwFrm* pPasteBefore = HasFollowFlowLine() ?
1169 184 : pFollowRow->GetNext() :
1170 546 : pFoll->GetFirstNonHeadlineRow();
1171 :
1172 924 : while ( pRow )
1173 : {
1174 200 : pNxt = pRow->GetNext();
1175 200 : nRet += (pRow->Frm().*fnRect->fnGetHeight)();
1176 :
1177 : // The footnotes have to be moved:
1178 200 : lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
1179 :
1180 200 : pRow->Remove();
1181 200 : pRow->Paste( pFoll, pPasteBefore );
1182 :
1183 200 : pRow->CheckDirChange();
1184 200 : pRow = static_cast<SwRowFrm*>(pNxt);
1185 : }
1186 : }
1187 :
1188 498 : Shrink( nRet );
1189 :
1190 : // we rebuild the last line to assure that it will be fully formatted
1191 498 : if ( pLastRow )
1192 : {
1193 : // recalculate the split line
1194 312 : bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow );
1195 :
1196 : // NEW TABLES
1197 : // check if each cell in the row span line has a good height
1198 312 : if ( bRet && pFollowRow->IsRowSpanLine() )
1199 0 : lcl_AdjustRowSpanCells( pFollowRow );
1200 :
1201 : // We The RowSplitLine stuff did not work. In this case we conceal the split error:
1202 312 : if ( !bRet && !bSplitRowAllowed )
1203 : {
1204 12 : bRet = true;
1205 : }
1206 : }
1207 :
1208 498 : return bRet;
1209 : }
1210 :
1211 132 : bool SwTabFrm::Join()
1212 : {
1213 : OSL_ENSURE( !HasFollowFlowLine(), "Joining follow flow line" );
1214 :
1215 132 : SwTabFrm *pFoll = GetFollow();
1216 :
1217 132 : if ( !pFoll->IsJoinLocked() )
1218 : {
1219 132 : SWRECTFN( this )
1220 132 : pFoll->Cut(); //Cut out first to avoid unnecessary notifications.
1221 :
1222 132 : SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(),
1223 : *pNxt;
1224 :
1225 132 : SwFrm* pPrv = GetLastLower();
1226 :
1227 132 : SwTwips nHeight = 0; //Total height of the inserted rows as return value.
1228 :
1229 378 : while ( pRow )
1230 : {
1231 114 : pNxt = pRow->GetNext();
1232 114 : nHeight += (pRow->Frm().*fnRect->fnGetHeight)();
1233 114 : pRow->Remove();
1234 114 : pRow->_InvalidateAll();
1235 114 : pRow->InsertBehind( this, pPrv );
1236 114 : pRow->CheckDirChange();
1237 114 : pPrv = pRow;
1238 114 : pRow = pNxt;
1239 : }
1240 :
1241 132 : SetFollow( pFoll->GetFollow() );
1242 132 : SetFollowFlowLine( pFoll->HasFollowFlowLine() );
1243 132 : delete pFoll;
1244 :
1245 132 : Grow( nHeight );
1246 : }
1247 :
1248 132 : return true;
1249 : }
1250 :
1251 1530 : void SwInvalidatePositions( SwFrm *pFrm, long nBottom )
1252 : {
1253 : // LONG_MAX == nBottom means we have to calculate all
1254 1530 : bool bAll = LONG_MAX == nBottom;
1255 1530 : SWRECTFN( pFrm )
1256 2726 : do
1257 2726 : { pFrm->_InvalidatePos();
1258 2726 : pFrm->_InvalidateSize();
1259 2726 : if( pFrm->IsLayoutFrm() )
1260 : {
1261 1444 : if ( ((SwLayoutFrm*)pFrm)->Lower() )
1262 : {
1263 1444 : ::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom);
1264 : // #i26945#
1265 1444 : ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) );
1266 : }
1267 : }
1268 : else
1269 1282 : pFrm->Prepare( PREP_ADJUST_FRM );
1270 2726 : pFrm = pFrm->GetNext();
1271 3922 : } while ( pFrm &&
1272 0 : ( bAll ||
1273 0 : (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
1274 1530 : }
1275 :
1276 10360 : void SwInvalidateAll( SwFrm *pFrm, long nBottom )
1277 : {
1278 : // LONG_MAX == nBottom means we have to calculate all
1279 10360 : bool bAll = LONG_MAX == nBottom;
1280 10360 : SWRECTFN( pFrm )
1281 17358 : do
1282 : {
1283 17358 : pFrm->_InvalidatePos();
1284 17358 : pFrm->_InvalidateSize();
1285 17358 : pFrm->_InvalidatePrt();
1286 17358 : if( pFrm->IsLayoutFrm() )
1287 : {
1288 : // NEW TABLES
1289 9890 : SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm);
1290 9890 : SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
1291 9890 : if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
1292 : {
1293 0 : pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
1294 0 : pToInvalidate->_InvalidatePos();
1295 0 : pToInvalidate->_InvalidateSize();
1296 0 : pToInvalidate->_InvalidatePrt();
1297 : }
1298 :
1299 9890 : if ( pToInvalidate->Lower() )
1300 9736 : ::SwInvalidateAll( pToInvalidate->Lower(), nBottom);
1301 : }
1302 : else
1303 7468 : pFrm->Prepare( PREP_CLEAR );
1304 :
1305 17358 : pFrm = pFrm->GetNext();
1306 24356 : } while ( pFrm &&
1307 0 : ( bAll ||
1308 0 : (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
1309 10360 : }
1310 :
1311 : // #i29550#
1312 680 : static void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm )
1313 : {
1314 680 : pLayFrm->_InvalidatePrt();
1315 680 : pLayFrm->_InvalidateSize();
1316 680 : pLayFrm->SetCompletePaint();
1317 :
1318 680 : SwFrm* pFrm = pLayFrm->Lower();
1319 :
1320 2320 : while ( pFrm )
1321 : {
1322 960 : if ( pFrm->IsLayoutFrm() )
1323 488 : lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm );
1324 : else
1325 : {
1326 472 : pFrm->_InvalidatePrt();
1327 472 : pFrm->_InvalidateSize();
1328 472 : pFrm->SetCompletePaint();
1329 : }
1330 :
1331 960 : pFrm = pFrm->GetNext();
1332 : }
1333 680 : }
1334 :
1335 3578 : bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave,
1336 : long nBottom, bool bSkipRowSpanCells )
1337 : {
1338 3578 : if ( !pLay )
1339 0 : return true;
1340 :
1341 : // LONG_MAX == nBottom means we have to calculate all
1342 3578 : bool bAll = LONG_MAX == nBottom;
1343 3578 : bool bRet = false;
1344 3578 : SwCntntFrm *pCnt = pLay->ContainsCntnt();
1345 3578 : SWRECTFN( pLay )
1346 :
1347 : // FME 2007-08-30 #i81146# new loop control
1348 3578 : int nLoopControlRuns = 0;
1349 3578 : const int nLoopControlMax = 10;
1350 3578 : const SwModify* pLoopControlCond = 0;
1351 :
1352 91382 : while ( pCnt && pDontLeave->IsAnLower( pCnt ) )
1353 : {
1354 : // #115759# - check, if a format of content frame is
1355 : // possible. Thus, 'copy' conditions, found at the beginning of
1356 : // <SwCntntFrm::MakeAll(..)>, and check these.
1357 169212 : const bool bFormatPossible = !pCnt->IsJoinLocked() &&
1358 169212 : ( !pCnt->IsTxtFrm() ||
1359 338424 : !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) &&
1360 253464 : ( pCnt->IsFollow() || !StackHack::IsLocked() );
1361 :
1362 : // NEW TABLES
1363 84606 : bool bSkipContent = false;
1364 84606 : if ( bSkipRowSpanCells && pCnt->IsInTab() )
1365 : {
1366 84534 : const SwFrm* pCell = pCnt->GetUpper();
1367 169068 : while ( pCell && !pCell->IsCellFrm() )
1368 0 : pCell = pCell->GetUpper();
1369 84534 : if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() )
1370 180 : bSkipContent = true;
1371 : }
1372 :
1373 84606 : if ( bFormatPossible && !bSkipContent )
1374 : {
1375 84426 : bRet |= !pCnt->IsValid();
1376 : // #i26945# - no extra invalidation of floating
1377 : // screen objects needed.
1378 : // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
1379 84426 : pCnt->Calc();
1380 : // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
1381 : // to format the floating screen objects
1382 : // #i46941# - frame has to be valid
1383 : // Note: frame could be invalid after calling its format, if it's locked.
1384 : OSL_ENSURE( !pCnt->IsTxtFrm() ||
1385 : pCnt->IsValid() ||
1386 : static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(),
1387 : "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." );
1388 84426 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
1389 : {
1390 : // #i23129#, #i36347# - pass correct page frame to
1391 : // the object formatter
1392 84426 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1393 84426 : *(pCnt->FindPageFrm()) ) )
1394 : {
1395 0 : if ( pCnt->GetRegisteredIn() == pLoopControlCond )
1396 0 : ++nLoopControlRuns;
1397 : else
1398 : {
1399 0 : nLoopControlRuns = 0;
1400 0 : pLoopControlCond = pCnt->GetRegisteredIn();
1401 : }
1402 :
1403 0 : if ( nLoopControlRuns < nLoopControlMax )
1404 : {
1405 : // restart format with first content
1406 0 : pCnt = pLay->ContainsCntnt();
1407 0 : continue;
1408 : }
1409 :
1410 : #if OSL_DEBUG_LEVEL > 1
1411 : OSL_FAIL( "LoopControl in SwCntntFrm::CalcLowers" );
1412 : #endif
1413 : }
1414 : }
1415 84426 : pCnt->GetUpper()->Calc();
1416 : }
1417 84606 : if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 )
1418 380 : break;
1419 84226 : pCnt = pCnt->GetNextCntntFrm();
1420 : }
1421 3578 : return bRet;
1422 : }
1423 :
1424 : // #i26945# - add parameter <_bOnlyRowsAndCells> to control
1425 : // that only row and cell frames are formatted.
1426 239064 : static bool lcl_InnerCalcLayout( SwFrm *pFrm,
1427 : long nBottom,
1428 : bool _bOnlyRowsAndCells )
1429 : {
1430 : // LONG_MAX == nBottom means we have to calculate all
1431 239064 : bool bAll = LONG_MAX == nBottom;
1432 239064 : bool bRet = false;
1433 239064 : const SwFrm* pOldUp = pFrm->GetUpper();
1434 239064 : SWRECTFN( pFrm )
1435 398266 : do
1436 : {
1437 : // #i26945# - parameter <_bOnlyRowsAndCells> controls,
1438 : // if only row and cell frames are formatted.
1439 867718 : if ( pFrm->IsLayoutFrm() &&
1440 250218 : ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) )
1441 : {
1442 : // #130744# An invalid locked table frame will
1443 : // not be calculated => It will not become valid =>
1444 : // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
1445 234726 : bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() );
1446 234726 : pFrm->Calc();
1447 234726 : if( static_cast<SwLayoutFrm*>(pFrm)->Lower() )
1448 233618 : bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom);
1449 :
1450 : // NEW TABLES
1451 234726 : SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
1452 234726 : if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
1453 : {
1454 104 : SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
1455 104 : bRet |= !rToCalc.IsValid();
1456 104 : rToCalc.Calc();
1457 104 : if ( rToCalc.Lower() )
1458 24 : bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom);
1459 : }
1460 : }
1461 398266 : pFrm = pFrm->GetNext();
1462 159842 : } while( pFrm &&
1463 79024 : ( bAll ||
1464 79024 : (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 )
1465 557468 : && pFrm->GetUpper() == pOldUp );
1466 239064 : return bRet;
1467 : }
1468 :
1469 2108 : static void lcl_RecalcRow( SwRowFrm& rRow, long nBottom )
1470 : {
1471 : // FME 2007-08-30 #i81146# new loop control
1472 2108 : int nLoopControlRuns_1 = 0;
1473 2108 : sal_uInt16 nLoopControlStage_1 = 0;
1474 2108 : const int nLoopControlMax = 10;
1475 :
1476 2108 : bool bCheck = true;
1477 : do
1478 : {
1479 : // FME 2007-08-30 #i81146# new loop control
1480 3506 : int nLoopControlRuns_2 = 0;
1481 3506 : sal_uInt16 nLoopControlStage_2 = 0;
1482 :
1483 8424 : while( lcl_InnerCalcLayout( &rRow, nBottom ) )
1484 : {
1485 1412 : if ( ++nLoopControlRuns_2 > nLoopControlMax )
1486 : {
1487 : #if OSL_DEBUG_LEVEL > 1
1488 : OSL_ENSURE( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
1489 : OSL_ENSURE( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
1490 : OSL_ENSURE( 2 > nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
1491 : #endif
1492 0 : rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ );
1493 0 : nLoopControlRuns_2 = 0;
1494 0 : if( nLoopControlStage_2 > 2 )
1495 0 : break;
1496 : }
1497 :
1498 1412 : bCheck = true;
1499 : }
1500 :
1501 3506 : if( bCheck )
1502 : {
1503 : // #115759# - force another format of the
1504 : // lowers, if at least one of it was invalid.
1505 3506 : bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true );
1506 :
1507 : // NEW TABLES
1508 : // First we calculate the cells with row span of < 1, afterwards
1509 : // all cells with row span of > 1:
1510 10518 : for ( int i = 0; i < 2; ++i )
1511 : {
1512 7012 : SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower());
1513 30208 : while ( pCellFrm )
1514 : {
1515 : const bool bCalc = 0 == i ?
1516 8092 : pCellFrm->GetLayoutRowSpan() < 1 :
1517 24276 : pCellFrm->GetLayoutRowSpan() > 1;
1518 :
1519 16184 : if ( bCalc )
1520 : {
1521 : SwCellFrm& rToRecalc = 0 == i ?
1522 : const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) :
1523 72 : *pCellFrm;
1524 72 : bCheck |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false );
1525 : }
1526 :
1527 16184 : pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
1528 : }
1529 : }
1530 :
1531 3506 : if ( bCheck )
1532 : {
1533 1398 : if ( ++nLoopControlRuns_1 > nLoopControlMax )
1534 : {
1535 : #if OSL_DEBUG_LEVEL > 1
1536 : OSL_ENSURE( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
1537 : OSL_ENSURE( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
1538 : OSL_ENSURE( 2 > nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
1539 : #endif
1540 0 : rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ );
1541 0 : nLoopControlRuns_1 = 0;
1542 0 : if( nLoopControlStage_1 > 2 )
1543 0 : break;
1544 : }
1545 :
1546 1398 : continue;
1547 : }
1548 : }
1549 2108 : break;
1550 1398 : } while( true );
1551 2108 : }
1552 :
1553 86 : static void lcl_RecalcTable( SwTabFrm& rTab,
1554 : SwLayoutFrm *pFirstRow,
1555 : SwLayNotify &rNotify )
1556 : {
1557 86 : if ( rTab.Lower() )
1558 : {
1559 86 : if ( !pFirstRow )
1560 : {
1561 86 : pFirstRow = (SwLayoutFrm*)rTab.Lower();
1562 86 : rNotify.SetLowersComplete( true );
1563 : }
1564 86 : ::SwInvalidatePositions( pFirstRow, LONG_MAX );
1565 86 : lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX );
1566 : }
1567 86 : }
1568 :
1569 : // This is a new function to check the first condition whether
1570 : // a tab frame may move backward. It replaces the formerly used
1571 : // GetIndPrev(), which did not work correctly for #i5947#
1572 9380 : static bool lcl_NoPrev( const SwFrm& rFrm )
1573 : {
1574 : // #i79774#
1575 : // skip empty sections on investigation of direct previous frame.
1576 : // use information, that at least one empty section is skipped in the following code.
1577 9380 : bool bSkippedDirectPrevEmptySection( false );
1578 9380 : if ( rFrm.GetPrev() )
1579 : {
1580 2492 : const SwFrm* pPrev( rFrm.GetPrev() );
1581 7476 : while ( pPrev &&
1582 2492 : pPrev->IsSctFrm() &&
1583 0 : !dynamic_cast<const SwSectionFrm&>(*pPrev).GetSection() )
1584 : {
1585 0 : pPrev = pPrev->GetPrev();
1586 0 : bSkippedDirectPrevEmptySection = true;
1587 : }
1588 2492 : if ( pPrev )
1589 : {
1590 2492 : return false;
1591 : }
1592 : }
1593 :
1594 13752 : if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) ||
1595 0 : ( bSkippedDirectPrevEmptySection &&
1596 0 : ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) )
1597 : {
1598 6864 : return true;
1599 : }
1600 :
1601 : // I do not have a direct prev, but I have an indirect prev.
1602 : // In section frames I have to check if I'm located inside
1603 : // the first column:
1604 24 : if ( rFrm.IsInSct() )
1605 : {
1606 24 : const SwFrm* pSct = rFrm.GetUpper();
1607 24 : if ( pSct && pSct->IsColBodyFrm() &&
1608 0 : pSct->GetUpper()->GetUpper()->IsSctFrm() )
1609 : {
1610 0 : const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev();
1611 0 : if ( pPrevCol )
1612 : // I'm not inside the first column and do not have a direct
1613 : // prev. I can try to go backward.
1614 0 : return true;
1615 : }
1616 : }
1617 :
1618 24 : return false;
1619 : }
1620 :
1621 : #define KEEPTAB ( !GetFollow() && !IsFollow() )
1622 :
1623 : // - helper method to find next content frame of
1624 : // a table frame and format it to assure keep attribute.
1625 : // method return true, if a next content frame is formatted.
1626 : // Precondition: The given table frame hasn't a follow and isn't a follow.
1627 38 : SwFrm* sw_FormatNextCntntForKeep( SwTabFrm* pTabFrm )
1628 : {
1629 : // find next content, table or section
1630 38 : SwFrm* pNxt = pTabFrm->FindNext();
1631 :
1632 : // skip empty sections
1633 76 : while ( pNxt && pNxt->IsSctFrm() &&
1634 0 : !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
1635 : {
1636 0 : pNxt = pNxt->FindNext();
1637 : }
1638 :
1639 : // if found next frame is a section, get its first content.
1640 38 : if ( pNxt && pNxt->IsSctFrm() )
1641 : {
1642 0 : pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny();
1643 : }
1644 :
1645 : // format found next frame.
1646 : // if table frame is inside another table, method <SwFrm::MakeAll()> is
1647 : // called to avoid that the superior table frame is formatted.
1648 38 : if ( pNxt )
1649 : {
1650 38 : if ( pTabFrm->GetUpper()->IsInTab() )
1651 12 : pNxt->MakeAll();
1652 : else
1653 26 : pNxt->Calc();
1654 : }
1655 :
1656 38 : return pNxt;
1657 : }
1658 :
1659 : namespace {
1660 512 : bool AreAllRowsKeepWithNext( const SwRowFrm* pFirstRowFrm )
1661 : {
1662 1024 : bool bRet = pFirstRowFrm != 0 &&
1663 1024 : pFirstRowFrm->ShouldRowKeepWithNext();
1664 :
1665 1026 : while ( bRet && pFirstRowFrm->GetNext() != 0 )
1666 : {
1667 2 : pFirstRowFrm = dynamic_cast<const SwRowFrm*>(pFirstRowFrm->GetNext());
1668 4 : bRet = pFirstRowFrm != 0 &&
1669 4 : pFirstRowFrm->ShouldRowKeepWithNext();
1670 : }
1671 :
1672 512 : return bRet;
1673 : }
1674 : }
1675 28310 : void SwTabFrm::MakeAll()
1676 : {
1677 28310 : if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
1678 41340 : return;
1679 :
1680 7640 : if ( HasFollow() )
1681 : {
1682 362 : SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
1683 : OSL_ENSURE( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
1684 : "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" );
1685 362 : if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
1686 0 : return;
1687 : }
1688 :
1689 : PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1690 :
1691 7640 : LockJoin(); //I don't want to be destroyed on the way.
1692 7640 : SwLayNotify aNotify( this ); //does the notification in the DTor
1693 : // If pos is invalid, we have to call a SetInvaKeep at aNotify.
1694 : // Otherwise the keep attribute would not work in front of a table.
1695 7640 : const bool bOldValidPos = GetValidPosFlag();
1696 :
1697 : //If my neighbour is my Follow at the same time, I'll swallow it up.
1698 : // OD 09.04.2003 #108698# - join all follows, which are placed on the
1699 : // same page/column.
1700 : // OD 29.04.2003 #109213# - join follow, only if join for the follow
1701 : // is not locked. Otherwise, join will not be performed and this loop
1702 : // will be endless.
1703 15284 : while ( GetNext() && GetNext() == GetFollow() &&
1704 2 : !GetFollow()->IsJoinLocked()
1705 : )
1706 : {
1707 2 : if ( HasFollowFlowLine() )
1708 2 : RemoveFollowFlowLine();
1709 2 : Join();
1710 : }
1711 :
1712 : // The bRemoveFollowFlowLinePending is set if the split attribute of the
1713 : // last line is set:
1714 7640 : if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
1715 : {
1716 0 : if ( RemoveFollowFlowLine() )
1717 0 : Join();
1718 0 : SetRemoveFollowFlowLinePending( false );
1719 : }
1720 :
1721 7640 : if ( bResizeHTMLTable ) //Optimized interplay with grow/shrink of the content
1722 : {
1723 92 : bResizeHTMLTable = false;
1724 92 : SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
1725 92 : if ( pLayout )
1726 : bCalcLowers = pLayout->Resize(
1727 92 : pLayout->GetBrowseWidthByTabFrm( *this ), false );
1728 : }
1729 :
1730 : // as long as bMakePage is true, a new page can be created (exactly once)
1731 7640 : bool bMakePage = true;
1732 : // bMovedBwd gets set to true when the frame flows backwards
1733 7640 : bool bMovedBwd = false;
1734 : // as long as bMovedFwd is false, the Frm may flow backwards (until
1735 : // it has been moved forward once)
1736 7640 : bool bMovedFwd = false;
1737 : // gets set to true when the Frm is split
1738 7640 : bool bSplit = false;
1739 7640 : const bool bFtnsInDoc = !GetFmt()->GetDoc()->GetFtnIdxs().empty();
1740 : bool bMoveable;
1741 7640 : const bool bFly = IsInFly();
1742 :
1743 7640 : SwBorderAttrAccess *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
1744 7640 : const SwBorderAttrs *pAttrs = pAccess->Get();
1745 :
1746 : // The beloved keep attribute
1747 7640 : const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
1748 :
1749 : // All rows should keep together
1750 : // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
1751 14716 : const bool bDontSplit = !IsFollow() &&
1752 21762 : ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
1753 :
1754 : // The number of repeated headlines
1755 7640 : const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
1756 :
1757 : // This flag indicates that we are allowed to try to split the
1758 : // table rows.
1759 7640 : bool bTryToSplit = true;
1760 :
1761 : // #131283#
1762 : // Indicates that two individual rows may keep together, based on the keep
1763 : // attribute set at the first paragraph in the first cell.
1764 7640 : const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->GetDocumentSettingManager().get(IDocumentSettingAccess::TABLE_ROW_KEEP);
1765 :
1766 : // The Magic Move: Used for the table row keep feature.
1767 : // If only the last row of the table wants to keep (implicitly by setting
1768 : // keep for the first paragraph in the first cell), and this table does
1769 : // not have a next, the last line will be cut. Loop prevention: Only
1770 : // one try.
1771 7640 : bool bLastRowHasToMoveToFollow = false;
1772 7640 : bool bLastRowMoveNoMoreTries = false;
1773 :
1774 : // Join follow table, if this table is not allowed to split:
1775 7640 : if ( bDontSplit )
1776 : {
1777 20 : while ( GetFollow() && !GetFollow()->IsJoinLocked() )
1778 : {
1779 0 : if ( HasFollowFlowLine() )
1780 0 : RemoveFollowFlowLine();
1781 0 : Join();
1782 : }
1783 : }
1784 :
1785 : // Join follow table, if this does not have enough (repeated) lines:
1786 7640 : if ( nRepeat )
1787 : {
1788 98 : if( GetFollow() && !GetFollow()->IsJoinLocked() &&
1789 0 : 0 == GetFirstNonHeadlineRow() )
1790 : {
1791 0 : if ( HasFollowFlowLine() )
1792 0 : RemoveFollowFlowLine();
1793 0 : Join();
1794 : }
1795 : }
1796 :
1797 : // Join follow table, if last row of this table should keep:
1798 7640 : if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
1799 : {
1800 336 : const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
1801 336 : if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
1802 : {
1803 0 : if ( HasFollowFlowLine() )
1804 0 : RemoveFollowFlowLine();
1805 0 : Join();
1806 : }
1807 : }
1808 :
1809 : // a new one is moved forwards immediately
1810 7640 : if ( !Frm().Top() && IsFollow() )
1811 : {
1812 152 : SwFrm *pPre = GetPrev();
1813 152 : if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
1814 : {
1815 100 : if ( !MoveFwd( bMakePage, false ) )
1816 74 : bMakePage = false;
1817 100 : bMovedFwd = true;
1818 : }
1819 : }
1820 :
1821 7640 : int nUnSplitted = 5; // Just another loop control :-(
1822 7640 : int nThrowAwayValidLayoutLimit = 5; // And another one :-(
1823 7640 : SWRECTFN( this )
1824 25862 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
1825 : {
1826 10582 : if ( (bMoveable = IsMoveable()) )
1827 8842 : if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
1828 : {
1829 2 : bMovedFwd = true;
1830 2 : bCalcLowers = true;
1831 : // #i99267#
1832 : // reset <bSplit> after forward move to assure that follows
1833 : // can be joined, if further space is available.
1834 2 : bSplit = false;
1835 : }
1836 :
1837 10582 : Point aOldPos( (Frm().*fnRect->fnGetPos)() );
1838 10582 : MakePos();
1839 :
1840 10582 : if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
1841 : {
1842 1820 : if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
1843 : {
1844 1718 : SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
1845 1718 : if( pLayout )
1846 : {
1847 6 : delete pAccess;
1848 : bCalcLowers |= pLayout->Resize(
1849 6 : pLayout->GetBrowseWidthByTabFrm( *this ), false );
1850 6 : pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
1851 6 : pAttrs = pAccess->Get();
1852 : }
1853 :
1854 1718 : mbValidPrtArea = false;
1855 1718 : aNotify.SetLowersComplete( false );
1856 : }
1857 : SwFrm *pPre;
1858 2704 : if ( bKeep || (0 != (pPre = FindPrev()) &&
1859 884 : pPre->GetAttrSet()->GetKeep().GetValue()) )
1860 : {
1861 30 : bCalcLowers = true;
1862 : // #i99267#
1863 : // reset <bSplit> after forward move to assure that follows
1864 : // can be joined, if further space is available.
1865 30 : bSplit = false;
1866 : }
1867 : }
1868 :
1869 : //We need to know the height of the first row, because the master needs
1870 : //to be activated if it shrinks and then absorb the row if necessary.
1871 10582 : long n1StLineHeight = 0;
1872 10582 : if ( IsFollow() )
1873 : {
1874 1072 : SwFrm* pFrm = GetFirstNonHeadlineRow();
1875 1072 : if ( pFrm )
1876 1072 : n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
1877 : }
1878 :
1879 10582 : if ( !mbValidSize || !mbValidPrtArea )
1880 : {
1881 8482 : const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
1882 8482 : const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
1883 8482 : const Point aOldPrtPos = (Prt().*fnRect->fnGetPos)();
1884 8482 : Format( pAttrs );
1885 :
1886 8482 : SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
1887 8562 : if ( pLayout &&
1888 146 : ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
1889 72 : (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
1890 : {
1891 6 : delete pAccess;
1892 : bCalcLowers |= pLayout->Resize(
1893 6 : pLayout->GetBrowseWidthByTabFrm( *this ), false );
1894 6 : pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
1895 6 : pAttrs = pAccess->Get();
1896 : }
1897 8482 : if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
1898 840 : aNotify.SetLowersComplete( false );
1899 : }
1900 :
1901 : // If this is the first one in a chain, check if this can flow
1902 : // backwards (if this is movable at all).
1903 : // To prevent oscillations/loops, check that this has not just
1904 : // flowed forwards.
1905 10582 : if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
1906 : {
1907 : // for Follows notify Master.
1908 : // only move Follow if it has to skip empty pages.
1909 6864 : if ( IsFollow() )
1910 : {
1911 : // Only if the height of the first line got smaller.
1912 822 : SwFrm *pFrm = GetFirstNonHeadlineRow();
1913 822 : if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
1914 : {
1915 0 : SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
1916 : bool bDummy;
1917 0 : if ( ShouldBwdMoved( pMaster->GetUpper(), false, bDummy ) )
1918 0 : pMaster->InvalidatePos();
1919 : }
1920 : }
1921 6864 : SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( true ) : 0;
1922 : bool bReformat;
1923 6864 : if ( MoveBwd( bReformat ) )
1924 : {
1925 32 : SWREFRESHFN( this )
1926 32 : bMovedBwd = true;
1927 32 : aNotify.SetLowersComplete( false );
1928 32 : if ( bFtnsInDoc )
1929 0 : MoveLowerFtns( 0, pOldBoss, 0, true );
1930 32 : if ( bReformat || bKeep )
1931 : {
1932 22 : long nOldTop = (Frm().*fnRect->fnGetTop)();
1933 22 : MakePos();
1934 22 : if( nOldTop != (Frm().*fnRect->fnGetTop)() )
1935 : {
1936 : SwHTMLTableLayout *pHTMLLayout =
1937 22 : GetTable()->GetHTMLTableLayout();
1938 22 : if( pHTMLLayout )
1939 : {
1940 0 : delete pAccess;
1941 : bCalcLowers |= pHTMLLayout->Resize(
1942 0 : pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
1943 0 : false );
1944 :
1945 0 : pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
1946 0 : pAttrs = pAccess->Get();
1947 : }
1948 :
1949 22 : mbValidPrtArea = false;
1950 22 : Format( pAttrs );
1951 : }
1952 22 : lcl_RecalcTable( *this, 0, aNotify );
1953 22 : bLowersFormatted = true;
1954 22 : if ( bKeep && KEEPTAB )
1955 : {
1956 :
1957 : // Consider case that table is inside another table,
1958 : // because it has to be avoided, that superior table
1959 : // is formatted.
1960 : // Thus, find next content, table or section
1961 : // and, if a section is found, get its first
1962 : // content.
1963 0 : if ( 0 != sw_FormatNextCntntForKeep( this ) && !GetNext() )
1964 : {
1965 0 : mbValidPos = false;
1966 : }
1967 : }
1968 : }
1969 : }
1970 : }
1971 :
1972 : //Again an invalid value? - do it again...
1973 10582 : if ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
1974 11664 : continue;
1975 :
1976 : // check, if calculation of table frame is ready.
1977 :
1978 : // Local variable <nDistanceToUpperPrtBottom>
1979 : // Introduce local variable and init it with the distance from the
1980 : // table frame bottom to the bottom of the upper printing area.
1981 : // Note: negative values denotes the situation that table frame doesn't fit in its upper.
1982 : SwTwips nDistanceToUpperPrtBottom =
1983 9486 : (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
1984 :
1985 : /// In online layout try to grow upper of table frame, if table frame doesn't fit in its upper.
1986 9486 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
1987 9486 : const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
1988 9486 : if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
1989 : {
1990 0 : if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
1991 : {
1992 : // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
1993 0 : nDistanceToUpperPrtBottom = (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
1994 : }
1995 : }
1996 :
1997 : // If there is still some space left in the upper, we check if we
1998 : // can join some rows of the follow.
1999 : // Setting bLastRowHasToMoveToFollow to true means we want to force
2000 : // the table to be split! Only skip this if condition once.
2001 9486 : if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
2002 : {
2003 : // If there is space left in the upper printing area, join as for trial
2004 : // at least one further row of an existing follow.
2005 8578 : if ( !bSplit && GetFollow() )
2006 : {
2007 : bool bDummy;
2008 1494 : if ( GetFollow()->ShouldBwdMoved( GetUpper(), false, bDummy ) )
2009 : {
2010 1434 : SwFrm *pTmp = GetUpper();
2011 1434 : SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
2012 1434 : if ( bBrowseMode )
2013 0 : nDeadLine += pTmp->Grow( LONG_MAX, true );
2014 1434 : if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
2015 : {
2016 : // First, we remove an existing follow flow line.
2017 1422 : if ( HasFollowFlowLine() )
2018 : {
2019 0 : SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
2020 0 : RemoveFollowFlowLine();
2021 : // invalidate and rebuild last row
2022 0 : if ( pLastLine )
2023 : {
2024 0 : ::SwInvalidateAll( pLastLine, LONG_MAX );
2025 0 : SetRebuildLastLine( true );
2026 0 : lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
2027 0 : SetRebuildLastLine( false );
2028 : }
2029 :
2030 0 : SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
2031 :
2032 0 : if ( !pRow || !pRow->GetNext() )
2033 : //The follow becomes empty and invalid for this reason.
2034 0 : Join();
2035 :
2036 1422 : continue;
2037 : }
2038 :
2039 : // If there is no follow flow line, we move the first
2040 : // row in the follow table to the master table.
2041 1422 : SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
2042 :
2043 : //The follow becomes empty and invalid for this reason.
2044 1422 : if ( !pRow )
2045 : {
2046 0 : Join();
2047 0 : continue;
2048 : }
2049 :
2050 1422 : const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
2051 1422 : long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
2052 1422 : SwFrm* pRowToMove = pRow;
2053 :
2054 4266 : while ( pRowToMove && nRowsToMove-- > 0 )
2055 : {
2056 1422 : const bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
2057 :
2058 1422 : SwFtnBossFrm *pOldBoss = 0;
2059 1422 : if ( bMoveFtns )
2060 0 : pOldBoss = pRowToMove->FindFtnBossFrm( true );
2061 :
2062 1422 : SwFrm* pNextRow = pRowToMove->GetNext();
2063 :
2064 1422 : if ( !pNextRow )
2065 : {
2066 : //The follow becomes empty and invalid for this reason.
2067 114 : Join();
2068 : }
2069 : else
2070 : {
2071 1308 : pRowToMove->Cut();
2072 1308 : pRowToMove->Paste( this );
2073 : }
2074 :
2075 : //Displace the footnotes!
2076 1422 : if ( bMoveFtns )
2077 0 : if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns( 0, pOldBoss, FindFtnBossFrm( true ), true ) )
2078 0 : GetUpper()->Calc();
2079 :
2080 1422 : pRowToMove = pNextRow;
2081 : }
2082 :
2083 1422 : if ( nOld != (Frm().*fnRect->fnGetHeight)() )
2084 0 : lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
2085 :
2086 1422 : continue;
2087 : }
2088 : }
2089 : }
2090 7084 : else if ( KEEPTAB )
2091 : {
2092 6468 : bool bFormat = false;
2093 6468 : if ( bKeep )
2094 0 : bFormat = true;
2095 6468 : else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
2096 : {
2097 : // We only want to give the last row one chance to move
2098 : // to the follow table. Set the flag as early as possible:
2099 4804 : bLastRowMoveNoMoreTries = true;
2100 :
2101 : // The last line of the table has to be cut off if:
2102 : // 1. The table does not want to keep with its next
2103 : // 2. The compatibility option is set and the table is allowed to split
2104 : // 3. We did not already cut off the last row
2105 : // 4. There is not break after attribute set at the table
2106 : // 5. There is no break before attribute set behind the table
2107 : // 6. There is no section change behind the table (see IsKeep)
2108 : // 7. The last table row wants to keep with its next.
2109 4804 : const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
2110 9438 : if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
2111 4634 : pLastRow->ShouldRowKeepWithNext() )
2112 38 : bFormat = true;
2113 : }
2114 :
2115 6468 : if ( bFormat )
2116 : {
2117 38 : delete pAccess;
2118 :
2119 : // Consider case that table is inside another table, because
2120 : // it has to be avoided, that superior table is formatted.
2121 : // Thus, find next content, table or section and, if a section
2122 : // is found, get its first content.
2123 38 : const SwFrm* pTmpNxt = sw_FormatNextCntntForKeep( this );
2124 :
2125 38 : pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2126 38 : pAttrs = pAccess->Get();
2127 :
2128 : // The last row wants to keep with the frame behind the table.
2129 : // Check if the next frame is on a different page and valid.
2130 : // In this case we do a magic trick:
2131 38 : if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
2132 : {
2133 0 : mbValidPos = false;
2134 0 : bLastRowHasToMoveToFollow = true;
2135 : }
2136 : }
2137 : }
2138 :
2139 7156 : if ( IsValid() )
2140 : {
2141 7156 : if ( bCalcLowers )
2142 : {
2143 64 : lcl_RecalcTable( *this, 0, aNotify );
2144 64 : bLowersFormatted = true;
2145 64 : bCalcLowers = false;
2146 : }
2147 7092 : else if ( bONECalcLowers )
2148 : {
2149 714 : lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2150 714 : bONECalcLowers = false;
2151 : }
2152 : }
2153 7156 : continue;
2154 : }
2155 :
2156 : //I don't fit in the higher-ranked element anymore, therefore it's the
2157 : //right moment to do some preferably constructive changes.
2158 :
2159 : //If I'm NOT allowed to leave the parent Frm, I've got a problem.
2160 : // Following Arthur Dent, we do the only thing that you can do with
2161 : // an unsolvable problem: We ignore it with all our power.
2162 908 : if ( !bMoveable )
2163 : {
2164 388 : if ( bCalcLowers && IsValid() )
2165 : {
2166 0 : lcl_RecalcTable( *this, 0, aNotify );
2167 0 : bLowersFormatted = true;
2168 0 : bCalcLowers = false;
2169 : }
2170 388 : else if ( bONECalcLowers )
2171 : {
2172 0 : lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2173 0 : bONECalcLowers = false;
2174 : }
2175 :
2176 : // It does not make sense to cut off the last line if we are
2177 : // not moveable:
2178 388 : bLastRowHasToMoveToFollow = false;
2179 :
2180 388 : continue;
2181 : }
2182 :
2183 520 : if ( bCalcLowers && IsValid() )
2184 : {
2185 0 : lcl_RecalcTable( *this, 0, aNotify );
2186 0 : bLowersFormatted = true;
2187 0 : bCalcLowers = false;
2188 0 : if( !IsValid() )
2189 0 : continue;
2190 : }
2191 :
2192 : // First try to split the table. Condition:
2193 : // 1. We have at least one non headline row
2194 : // 2. If this row wants to keep, we need an additional row
2195 : // 3. The table is allowed to split or we do not have an pIndPrev:
2196 520 : SwFrm* pIndPrev = GetIndPrev();
2197 520 : const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
2198 : // #i120016# if this row wants to keep, allow split in case that all rows want to keep with next,
2199 : // the table can not move forward as it is the first one and a split is in general allowed.
2200 512 : const bool bAllowSplitOfRow = ( bTableRowKeep &&
2201 512 : AreAllRowsKeepWithNext( pFirstNonHeadlineRow ) ) &&
2202 520 : !pIndPrev &&
2203 520 : !bDontSplit;
2204 :
2205 1560 : if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
2206 2592 : ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() || bAllowSplitOfRow ) &&
2207 520 : ( !bDontSplit || !pIndPrev ) )
2208 : {
2209 : // #i29438#
2210 : // Special DoNotSplit case:
2211 : // We better avoid splitting of a row frame if we are inside a columned
2212 : // section which has a height of 0, because this is not growable and thus
2213 : // all kinds of unexpected things could happen.
2214 1040 : if ( IsInSct() &&
2215 520 : (FindSctFrm())->Lower()->IsColumnFrm() &&
2216 0 : 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)() )
2217 : {
2218 0 : bTryToSplit = false;
2219 : }
2220 :
2221 : // 1. Try: bTryToSplit = true => Try to split the row.
2222 : // 2. Try: bTryToSplit = false => Split the table between the rows.
2223 520 : if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
2224 : {
2225 512 : SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
2226 512 : if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
2227 : nDeadLine = (*fnRect->fnYInc)( nDeadLine,
2228 46 : GetUpper()->Grow( LONG_MAX, true ) );
2229 :
2230 : {
2231 512 : SetInRecalcLowerRow( true );
2232 512 : ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
2233 512 : SetInRecalcLowerRow( false );
2234 : }
2235 512 : bLowersFormatted = true;
2236 512 : aNotify.SetLowersComplete( true );
2237 :
2238 : // One more check if its really necessary to split the table.
2239 : // 1. The table either has to exceed the deadline or
2240 : // 2. We explicitly want to cut off the last row.
2241 512 : if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
2242 : {
2243 0 : continue;
2244 : }
2245 :
2246 : // Set to false again as early as possible.
2247 512 : bLastRowHasToMoveToFollow = false;
2248 :
2249 : // #i52781#
2250 : // YaSC - Yet another special case:
2251 : // If our upper is inside a table cell which is not allowed
2252 : // to split, we do not try to split:
2253 512 : if ( GetUpper()->IsInTab() )
2254 : {
2255 46 : const SwFrm* pTmpRow = GetUpper();
2256 138 : while ( pTmpRow && !pTmpRow->IsRowFrm() )
2257 46 : pTmpRow = pTmpRow->GetUpper();
2258 46 : if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
2259 0 : continue;
2260 : }
2261 :
2262 512 : sal_uInt16 nMinNumOfLines = nRepeat;
2263 :
2264 512 : if ( bTableRowKeep )
2265 : {
2266 504 : const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
2267 1010 : while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
2268 : {
2269 2 : ++nMinNumOfLines;
2270 2 : pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
2271 : }
2272 : }
2273 :
2274 512 : if ( !bTryToSplit )
2275 192 : ++nMinNumOfLines;
2276 :
2277 : const SwTwips nBreakLine = (*fnRect->fnYInc)(
2278 1024 : (Frm().*fnRect->fnGetTop)(),
2279 512 : (this->*fnRect->fnGetTopMargin)() +
2280 2048 : lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
2281 :
2282 : // Some more checks if we want to call the split algorithm or not:
2283 : // The repeating lines / keeping lines still fit into the upper or
2284 : // if we do not have an (in)direkt Prev, we split anyway.
2285 512 : if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
2286 : {
2287 506 : aNotify.SetLowersComplete( false );
2288 506 : bSplit = true;
2289 :
2290 : // An existing follow flow line has to be removed.
2291 506 : if ( HasFollowFlowLine() )
2292 : {
2293 60 : if (!nThrowAwayValidLayoutLimit)
2294 2 : continue;
2295 58 : bool bInitialLoopEndCondition = mbValidPos && mbValidSize && mbValidPrtArea;
2296 58 : RemoveFollowFlowLine();
2297 58 : bool bFinalLoopEndCondition = mbValidPos && mbValidSize && mbValidPrtArea;
2298 58 : if (bInitialLoopEndCondition && !bFinalLoopEndCondition)
2299 58 : --nThrowAwayValidLayoutLimit;
2300 : }
2301 :
2302 504 : const bool bSplitError = !Split( nDeadLine, bTryToSplit, ( bTableRowKeep && !bAllowSplitOfRow ) );
2303 504 : if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
2304 : {
2305 186 : --nUnSplitted;
2306 : }
2307 :
2308 : // #i29771# Two tries to split the table
2309 : // If an error occurred during splitting. We start a second
2310 : // try, this time without splitting of table rows.
2311 504 : if ( bSplitError )
2312 : {
2313 200 : if ( HasFollowFlowLine() )
2314 194 : RemoveFollowFlowLine();
2315 : }
2316 :
2317 : // #119477#
2318 : // If splitting the table was successful or not,
2319 : // we do not want to have 'empty' follow tables.
2320 504 : if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
2321 16 : Join();
2322 :
2323 : // We want to restore the situation before the failed
2324 : // split operation as good as possible. Therefore we
2325 : // do some more calculations. Note: Restricting this
2326 : // to nDeadLine may not be enough.
2327 504 : if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
2328 : {
2329 200 : lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2330 200 : mbValidPos = false;
2331 200 : bTryToSplit = false;
2332 200 : continue;
2333 : }
2334 :
2335 304 : bTryToSplit = !bSplitError;
2336 :
2337 : //To avoid oscillations the Follow must become valid now
2338 304 : if ( GetFollow() )
2339 : {
2340 : // #i80924#
2341 : // After a successful split assure that the first row
2342 : // is invalid. When graphics are present, this isn't hold.
2343 : // Note: defect i80924 could also be fixed, if it is
2344 : // assured, that <SwLayNotify::bLowersComplete> is only
2345 : // set, if all lower are valid *and* are correct laid out.
2346 304 : if ( !bSplitError && GetFollow()->GetLower() )
2347 : {
2348 304 : GetFollow()->GetLower()->InvalidatePos();
2349 : }
2350 304 : SWRECTFNX( GetFollow() )
2351 :
2352 : static sal_uInt8 nStack = 0;
2353 304 : if ( !StackHack::IsLocked() && nStack < 4 )
2354 : {
2355 284 : ++nStack;
2356 284 : StackHack aHack;
2357 284 : delete pAccess;
2358 :
2359 284 : GetFollow()->MakeAll();
2360 :
2361 284 : pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2362 284 : pAttrs = pAccess->Get();
2363 :
2364 284 : ((SwTabFrm*)GetFollow())->SetLowersFormatted(false);
2365 : // #i43913# - lock follow table
2366 : // to avoid its formatting during the format of
2367 : // its content.
2368 284 : const bool bOldJoinLock = GetFollow()->IsJoinLocked();
2369 284 : GetFollow()->LockJoin();
2370 284 : ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
2371 568 : (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
2372 : // #i43913#
2373 : // #i63632# Do not unlock the
2374 : // follow if it wasn't locked before.
2375 284 : if ( !bOldJoinLock )
2376 284 : GetFollow()->UnlockJoin();
2377 :
2378 284 : if ( !GetFollow()->GetFollow() )
2379 : {
2380 118 : SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
2381 118 : if ( pNxt )
2382 : {
2383 : // #i18103# - no formatting of found next
2384 : // frame, if its a follow section of the
2385 : // 'ColLocked' section, the follow table is
2386 : // in.
2387 118 : bool bCalcNxt = true;
2388 118 : if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
2389 : {
2390 0 : SwSectionFrm* pSct = GetFollow()->FindSctFrm();
2391 0 : if ( pSct->IsColLocked() &&
2392 0 : pSct->GetFollow() == pNxt )
2393 : {
2394 0 : bCalcNxt = false;
2395 : }
2396 : }
2397 118 : if ( bCalcNxt )
2398 : {
2399 118 : pNxt->Calc();
2400 : }
2401 : }
2402 : }
2403 284 : --nStack;
2404 : }
2405 20 : else if ( GetFollow() == GetNext() )
2406 20 : ((SwTabFrm*)GetFollow())->MoveFwd( true, false );
2407 : }
2408 304 : continue;
2409 : }
2410 : }
2411 : }
2412 :
2413 : // Set to false again as early as possible.
2414 14 : bLastRowHasToMoveToFollow = false;
2415 :
2416 28 : if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
2417 0 : GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
2418 14 : ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
2419 0 : ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
2420 : {
2421 0 : bMovedFwd = false;
2422 : }
2423 :
2424 : // #i29771# Reset bTryToSplit flag on change of upper
2425 14 : const SwFrm* pOldUpper = GetUpper();
2426 :
2427 : //Let's see if we find some place anywhere...
2428 14 : if ( !bMovedFwd && !MoveFwd( bMakePage, false ) )
2429 14 : bMakePage = false;
2430 :
2431 : // #i29771# Reset bSplitError flag on change of upper
2432 14 : if ( GetUpper() != pOldUpper )
2433 : {
2434 6 : bTryToSplit = true;
2435 6 : nUnSplitted = 5;
2436 : }
2437 :
2438 14 : SWREFRESHFN( this )
2439 14 : bCalcLowers = true;
2440 14 : bMovedFwd = true;
2441 14 : aNotify.SetLowersComplete( false );
2442 14 : if ( IsFollow() )
2443 : {
2444 : //To avoid oscillations now invalid master should drop behind.
2445 0 : SwTabFrm *pTab = FindMaster();
2446 0 : if ( pTab->GetUpper() )
2447 0 : pTab->GetUpper()->Calc();
2448 0 : pTab->Calc();
2449 0 : pTab->SetLowersFormatted( false );
2450 : }
2451 :
2452 : //If my neighbour is my Follow at the same time, I'll swallow it up.
2453 14 : if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
2454 : {
2455 0 : if ( HasFollowFlowLine() )
2456 0 : RemoveFollowFlowLine();
2457 0 : if ( GetFollow() )
2458 0 : Join();
2459 : }
2460 :
2461 14 : if ( bMovedBwd && GetUpper() )
2462 : {
2463 : //During floating back the upper was animated to do a full repaint,
2464 : //we can now skip this after the whole back and forth floating.
2465 0 : GetUpper()->ResetCompletePaint();
2466 : }
2467 :
2468 14 : if ( bCalcLowers && IsValid() )
2469 : {
2470 : // #i44910# - format of lower frames unnecessary
2471 : // and can cause layout loops, if table doesn't fit and isn't
2472 : // allowed to split.
2473 : SwTwips nDistToUpperPrtBottom =
2474 8 : (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2475 8 : if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
2476 : {
2477 0 : lcl_RecalcTable( *this, 0, aNotify );
2478 0 : bLowersFormatted = true;
2479 0 : bCalcLowers = false;
2480 : }
2481 : #if OSL_DEBUG_LEVEL > 0
2482 : else
2483 : {
2484 : OSL_FAIL( "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
2485 : }
2486 : #endif
2487 : }
2488 :
2489 : } //while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
2490 :
2491 : //If my direct predecessor is my master now, it can destroy me during the
2492 : //next best opportunity.
2493 7640 : if ( IsFollow() )
2494 : {
2495 574 : SwFrm *pPre = GetPrev();
2496 574 : if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
2497 0 : pPre->InvalidatePos();
2498 : }
2499 :
2500 7640 : bCalcLowers = bONECalcLowers = false;
2501 7640 : delete pAccess;
2502 7640 : UnlockJoin();
2503 7640 : if ( bMovedFwd || bMovedBwd || !bOldValidPos )
2504 7258 : aNotify.SetInvaKeep();
2505 : }
2506 :
2507 : /// Calculate the offsets arising because of FlyFrames
2508 8608 : bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
2509 : long& rLeftOffset,
2510 : long& rRightOffset ) const
2511 : {
2512 8608 : bool bInvalidatePrtArea = false;
2513 8608 : const SwPageFrm *pPage = FindPageFrm();
2514 8608 : const SwFlyFrm* pMyFly = FindFlyFrm();
2515 :
2516 : // --> #108724# Page header/footer content doesn't have to wrap around
2517 : // floating screen objects
2518 :
2519 8608 : const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
2520 24894 : const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
2521 25780 : ( !IsInFtn() && 0 == FindFooterOrHeader() );
2522 :
2523 8608 : if ( pPage->GetSortedObjs() && bWrapAllowed )
2524 : {
2525 2290 : SWRECTFN( this )
2526 2290 : const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
2527 2290 : long nPrtPos = (Frm().*fnRect->fnGetTop)();
2528 2290 : nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
2529 2290 : SwRect aRect( Frm() );
2530 2290 : long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
2531 2290 : if( nYDiff > 0 )
2532 0 : (aRect.*fnRect->fnAddBottom)( -nYDiff );
2533 8160 : for ( size_t i = 0; i < pPage->GetSortedObjs()->size(); ++i )
2534 : {
2535 5870 : SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
2536 5870 : if ( pAnchoredObj->ISA(SwFlyFrm) )
2537 : {
2538 2846 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
2539 2846 : const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
2540 : // #i26945# - correction of conditions,
2541 : // if Writer fly frame has to be considered:
2542 : // - no need to check, if top of Writer fly frame differs
2543 : // from FAR_AWAY, because its also check, if the Writer
2544 : // fly frame rectangle overlaps with <aRect>
2545 : // - no check, if bottom of anchor frame is prior the top of
2546 : // the table, because Writer fly frames can be negative positioned.
2547 : // - correct check, if the Writer fly frame is an lower of the
2548 : // table, because table lines/rows can split and a at-character
2549 : // anchored Writer fly frame could be positioned in the follow
2550 : // flow line.
2551 : // - add condition, that an existing anchor character text frame
2552 : // has to be on the same page as the table.
2553 : // E.g., it could happen, that the fly frame is still registered
2554 : // at the page frame, the table is on, but it's anchor character
2555 : // text frame has already changed its page.
2556 2846 : const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
2557 : bool bConsiderFly =
2558 : // #i46807# - do not consider invalid
2559 : // Writer fly frames.
2560 3736 : pFly->IsValid() &&
2561 : // fly anchored at character
2562 1640 : pFly->IsFlyAtCntFrm() &&
2563 : // fly overlaps with corresponding table rectangle
2564 1060 : aFlyRect.IsOver( aRect ) &&
2565 : // fly isn't lower of table and
2566 : // anchor character frame of fly isn't lower of table
2567 610 : ( !IsAnLower( pFly ) &&
2568 354 : ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
2569 : // table isn't lower of fly
2570 304 : !pFly->IsAnLower( this ) &&
2571 : // fly is lower of fly, the table is in
2572 : // #123274# - correction
2573 : // assure that fly isn't a lower of a fly, the table isn't in.
2574 : // E.g., a table in the body doesn't wrap around a graphic,
2575 : // which is inside a frame.
2576 0 : ( ( !pMyFly ||
2577 4 : pMyFly->IsAnLower( pFly ) ) &&
2578 8 : pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
2579 : // anchor frame not on following page
2580 4 : pPage->GetPhyPageNum() >=
2581 2858 : pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2582 : // anchor character text frame on same page
2583 4 : ( !pAnchorCharFrm ||
2584 4 : pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
2585 2850 : pPage->GetPhyPageNum() );
2586 :
2587 2846 : if ( bConsiderFly )
2588 : {
2589 4 : const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
2590 4 : const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
2591 :
2592 4 : if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
2593 : // #148493# If bConsiderWrapOnObjPos is set,
2594 : // we want to consider the fly if it is located in the header and
2595 : // the table is located in the body:
2596 0 : ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
2597 0 : bConsiderFly = false;
2598 : }
2599 :
2600 2846 : if ( bConsiderFly )
2601 : {
2602 4 : const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
2603 4 : const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
2604 4 : if ( SURROUND_NONE == rSur.GetSurround() )
2605 : {
2606 0 : long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
2607 0 : if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
2608 0 : nPrtPos = nBottom;
2609 0 : bInvalidatePrtArea = true;
2610 : }
2611 12 : if ( (SURROUND_RIGHT == rSur.GetSurround() ||
2612 4 : SURROUND_PARALLEL == rSur.GetSurround())&&
2613 0 : text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
2614 : {
2615 : const long nWidth = (*fnRect->fnXDiff)(
2616 0 : (aFlyRect.*fnRect->fnGetRight)(),
2617 0 : (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
2618 0 : rLeftOffset = std::max( rLeftOffset, nWidth );
2619 0 : bInvalidatePrtArea = true;
2620 : }
2621 12 : if ( (SURROUND_LEFT == rSur.GetSurround() ||
2622 4 : SURROUND_PARALLEL == rSur.GetSurround())&&
2623 0 : text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
2624 : {
2625 : const long nWidth = (*fnRect->fnXDiff)(
2626 0 : (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
2627 0 : (aFlyRect.*fnRect->fnGetLeft)() );
2628 0 : rRightOffset = std::max( rRightOffset, nWidth );
2629 0 : bInvalidatePrtArea = true;
2630 : }
2631 : }
2632 : }
2633 : }
2634 2290 : rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
2635 : }
2636 :
2637 8608 : return bInvalidatePrtArea;
2638 : }
2639 :
2640 : /// "Formats" the frame; Frm and PrtArea.
2641 : /// The fixed size is not adjusted here.
2642 8504 : void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
2643 : {
2644 : OSL_ENSURE( pAttrs, "TabFrm::Format, pAttrs ist 0." );
2645 :
2646 8504 : SWRECTFN( this )
2647 8504 : if ( !mbValidSize )
2648 : {
2649 8118 : long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
2650 8118 : (Frm().*fnRect->fnGetWidth)();
2651 8118 : if( nDiff )
2652 1440 : (maFrm.*fnRect->fnAddRight)( nDiff );
2653 : }
2654 :
2655 : //VarSize is always the height.
2656 : //For the upper/lower border the same rules apply as for cntfrms (see
2657 : //MakePrtArea() of those).
2658 :
2659 8504 : SwTwips nUpper = CalcUpperSpace( pAttrs );
2660 :
2661 : //We want to dodge the border. Two possibilities:
2662 : //1. There are borders with SurroundNone, dodge them completely
2663 : //2. There are borders which only float on the right or the left side and
2664 : // are right or left aligned, those set the minimum for the borders.
2665 8504 : long nTmpRight = -1000000,
2666 8504 : nLeftOffset = 0;
2667 8504 : if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
2668 0 : mbValidPrtArea = false;
2669 8504 : long nRightOffset = std::max( 0L, nTmpRight );
2670 :
2671 8504 : SwTwips nLower = pAttrs->CalcBottomLine();
2672 : // #i29550#
2673 8504 : if ( IsCollapsingBorders() )
2674 8374 : nLower += GetBottomLineSize();
2675 :
2676 8504 : if ( !mbValidPrtArea )
2677 8488 : { mbValidPrtArea = true;
2678 :
2679 : //The width of the PrtArea is given by the FrmFmt, the borders have to
2680 : //be set accordingly.
2681 : //Minimum borders are determined depending on margins and shadows.
2682 : //The borders are adjusted so that the PrtArea is aligned into the Frm
2683 : //according to the adjustment.
2684 : //If the adjustment is 0, the borders are set according to the border
2685 : //attributes.
2686 :
2687 8488 : const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
2688 8488 : const SwTwips nMax = (maFrm.*fnRect->fnGetWidth)();
2689 :
2690 : // OD 14.03.2003 #i9040# - adjust variable names.
2691 8488 : const SwTwips nLeftLine = pAttrs->CalcLeftLine();
2692 8488 : const SwTwips nRightLine = pAttrs->CalcRightLine();
2693 :
2694 : //The width possibly is a percentage value. If the table is inside
2695 : //something else, the value applies to the surrounding. If it's the body
2696 : //the value applies to the screen width in the BrowseView.
2697 8488 : const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
2698 : // OD 14.03.2003 #i9040# - adjust variable name.
2699 8488 : const SwTwips nWishedTableWidth = CalcRel( rSz, true );
2700 :
2701 8488 : bool bCheckBrowseWidth = false;
2702 :
2703 : // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
2704 8488 : SwTwips nLeftSpacing = 0;
2705 8488 : SwTwips nRightSpacing = 0;
2706 8488 : switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
2707 : {
2708 : case text::HoriOrientation::LEFT:
2709 : {
2710 : // left indent:
2711 398 : nLeftSpacing = nLeftLine + nLeftOffset;
2712 : // OD 06.03.2003 #i9040# - correct calculation of right indent:
2713 : // - Consider right indent given by right line attributes.
2714 : // - Consider negative right indent.
2715 : // wished right indent determined by wished table width and
2716 : // left offset given by surround fly frames on the left:
2717 398 : const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
2718 398 : if ( nRightOffset > 0 )
2719 : {
2720 : // surrounding fly frames on the right
2721 : // -> right indent is maximun of given right offset
2722 : // and wished right offset.
2723 0 : nRightSpacing = nRightLine + std::max( nRightOffset, nWishRight );
2724 : }
2725 : else
2726 : {
2727 : // no surrounding fly frames on the right
2728 : // If intrinsic right indent (intrinsic means not considering
2729 : // determined left indent) is negative,
2730 : // then hold this intrinsic indent,
2731 : // otherwise non negative wished right indent is hold.
2732 1116 : nRightSpacing = nRightLine +
2733 398 : ( ( (nWishRight+nLeftOffset) < 0 ) ?
2734 78 : (nWishRight+nLeftOffset) :
2735 1038 : std::max( 0L, nWishRight ) );
2736 : }
2737 : }
2738 398 : break;
2739 : case text::HoriOrientation::RIGHT:
2740 : {
2741 : // right indent:
2742 28 : nRightSpacing = nRightLine + nRightOffset;
2743 : // OD 06.03.2003 #i9040# - correct calculation of left indent:
2744 : // - Consider left indent given by left line attributes.
2745 : // - Consider negative left indent.
2746 : // wished left indent determined by wished table width and
2747 : // right offset given by surrounding fyl frames on the right:
2748 28 : const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
2749 28 : if ( nLeftOffset > 0 )
2750 : {
2751 : // surrounding fly frames on the left
2752 : // -> right indent is maximun of given left offset
2753 : // and wished left offset.
2754 0 : nLeftSpacing = nLeftLine + std::max( nLeftOffset, nWishLeft );
2755 : }
2756 : else
2757 : {
2758 : // no surrounding fly frames on the left
2759 : // If intrinsic left indent (intrinsic = not considering
2760 : // determined right indent) is negative,
2761 : // then hold this intrinsic indent,
2762 : // otherwise non negative wished left indent is hold.
2763 84 : nLeftSpacing = nLeftLine +
2764 28 : ( ( (nWishLeft+nRightOffset) < 0 ) ?
2765 0 : (nWishLeft+nRightOffset) :
2766 84 : std::max( 0L, nWishLeft ) );
2767 : }
2768 : }
2769 28 : break;
2770 : case text::HoriOrientation::CENTER:
2771 : {
2772 : // OD 07.03.2003 #i9040# - consider left/right line attribute.
2773 : // OD 10.03.2003 #i9040# -
2774 1110 : const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
2775 1110 : nLeftSpacing = nLeftLine +
2776 1110 : ( (nLeftOffset > 0) ?
2777 0 : std::max( nCenterSpacing, nLeftOffset ) :
2778 1110 : nCenterSpacing );
2779 1110 : nRightSpacing = nRightLine +
2780 1110 : ( (nRightOffset > 0) ?
2781 0 : std::max( nCenterSpacing, nRightOffset ) :
2782 1110 : nCenterSpacing );
2783 : }
2784 1110 : break;
2785 : case text::HoriOrientation::FULL:
2786 : //This things grows over the whole width.
2787 : //Only the free space needed for the border is taken into
2788 : //account. The attribute values of LRSpace are ignored
2789 : //intentionally.
2790 700 : bCheckBrowseWidth = true;
2791 700 : nLeftSpacing = nLeftLine + nLeftOffset;
2792 700 : nRightSpacing = nRightLine + nRightOffset;
2793 700 : break;
2794 : case text::HoriOrientation::NONE:
2795 : {
2796 : //The border are defined by the border attribute.
2797 478 : nLeftSpacing = pAttrs->CalcLeft( this );
2798 478 : if( nLeftOffset )
2799 : {
2800 : // OD 07.03.2003 #i9040# - surround fly frames only, if
2801 : // they overlap with the table.
2802 : // Thus, take maximun of left spacing and left offset.
2803 : // OD 10.03.2003 #i9040# - consider left line attribute.
2804 0 : nLeftSpacing = std::max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
2805 : }
2806 : // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
2807 478 : nRightSpacing = pAttrs->CalcRight( this );
2808 478 : if( nRightOffset )
2809 : {
2810 : // OD 07.03.2003 #i9040# - surround fly frames only, if
2811 : // they overlap with the table.
2812 : // Thus, take maximun of right spacing and right offset.
2813 : // OD 10.03.2003 #i9040# - consider right line attribute.
2814 0 : nRightSpacing = std::max( nRightSpacing, ( nRightOffset + nRightLine ) );
2815 : }
2816 : }
2817 478 : break;
2818 : case text::HoriOrientation::LEFT_AND_WIDTH:
2819 : {
2820 : //Linker Rand und die Breite zaehlen (Word-Spezialitaet)
2821 : // OD 10.03.2003 #i9040# - no width alignment in online mode.
2822 : //bCheckBrowseWidth = true;
2823 5774 : nLeftSpacing = pAttrs->CalcLeft( this );
2824 5774 : if( nLeftOffset )
2825 : {
2826 : // OD 10.03.2003 #i9040# - surround fly frames only, if
2827 : // they overlap with the table.
2828 : // Thus, take maximun of right spacing and right offset.
2829 : // OD 10.03.2003 #i9040# - consider left line attribute.
2830 0 : nLeftSpacing = std::max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
2831 : }
2832 : // OD 10.03.2003 #i9040# - consider right and left line attribute.
2833 : const SwTwips nWishRight =
2834 5774 : nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
2835 5774 : nRightSpacing = nRightLine +
2836 5774 : ( (nRightOffset > 0) ?
2837 0 : std::max( nWishRight, nRightOffset ) :
2838 5774 : nWishRight );
2839 : }
2840 5774 : break;
2841 : default:
2842 : OSL_FAIL( "Ungueltige orientation fuer Table." );
2843 : }
2844 :
2845 : // #i26250# - extend bottom printing area, if table
2846 : // is last content inside a table cell.
2847 25442 : if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
2848 9300 : GetUpper()->IsInTab() && !GetIndNext() )
2849 : {
2850 56 : nLower += pAttrs->GetULSpace().GetLower();
2851 : }
2852 8488 : (this->*fnRect->fnSetYMargins)( nUpper, nLower );
2853 8488 : if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
2854 104 : (this->*fnRect->fnSetXMargins)( 0, 0 );
2855 : else
2856 8384 : (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
2857 :
2858 8488 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
2859 9188 : if ( bCheckBrowseWidth &&
2860 700 : pSh && pSh->GetViewOptions()->getBrowseMode() &&
2861 8488 : GetUpper()->IsPageBodyFrm() && // only PageBodyFrms and not ColBodyFrms
2862 0 : pSh->VisArea().Width() )
2863 : {
2864 : //Don't overlap the edge of the visible area.
2865 : //The page width can be bigger because objects with
2866 : //"over-size" are possible (RootFrm::ImplCalcBrowseWidth())
2867 0 : long nWidth = pSh->GetBrowseWidth();
2868 0 : nWidth -= Prt().Left();
2869 0 : nWidth -= pAttrs->CalcRightLine();
2870 0 : Prt().Width( std::min( nWidth, Prt().Width() ) );
2871 : }
2872 :
2873 8488 : if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
2874 1062 : mbValidSize = false;
2875 : }
2876 :
2877 8504 : if ( !mbValidSize )
2878 : {
2879 8128 : mbValidSize = true;
2880 :
2881 : //The size is defined by the content plus the borders.
2882 8128 : SwTwips nRemaining = 0, nDiff;
2883 8128 : SwFrm *pFrm = pLower;
2884 111890 : while ( pFrm )
2885 : {
2886 95634 : nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
2887 95634 : pFrm = pFrm->GetNext();
2888 : }
2889 : //And now add the borders
2890 8128 : nRemaining += nUpper + nLower;
2891 :
2892 8128 : nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
2893 8128 : if ( nDiff > 0 )
2894 24 : Shrink( nDiff );
2895 8104 : else if ( nDiff < 0 )
2896 1040 : Grow( -nDiff );
2897 : }
2898 8504 : }
2899 :
2900 23414 : SwTwips SwTabFrm::GrowFrm( SwTwips nDist, bool bTst, bool bInfo )
2901 : {
2902 23414 : SWRECTFN( this )
2903 23414 : SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
2904 23414 : if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
2905 2418 : nDist = LONG_MAX - nHeight;
2906 :
2907 23414 : if ( bTst && !IsRestrictTableGrowth() )
2908 668 : return nDist;
2909 :
2910 22746 : if ( GetUpper() )
2911 : {
2912 22746 : SwRect aOldFrm( Frm() );
2913 :
2914 : //The upper only grows as far as needed. nReal provides the distance
2915 : //which is already available.
2916 22746 : SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
2917 22746 : SwFrm *pFrm = GetUpper()->Lower();
2918 169280 : while ( pFrm && GetFollow() != pFrm )
2919 : {
2920 123788 : nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
2921 123788 : pFrm = pFrm->GetNext();
2922 : }
2923 :
2924 22746 : if ( nReal < nDist )
2925 : {
2926 13390 : long nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
2927 :
2928 13390 : if ( IsRestrictTableGrowth() )
2929 : {
2930 5082 : nTmp = std::min( nDist, nReal + nTmp );
2931 5082 : nDist = nTmp < 0 ? 0 : nTmp;
2932 : }
2933 : }
2934 :
2935 22746 : if ( !bTst )
2936 : {
2937 19504 : (Frm().*fnRect->fnAddBottom)( nDist );
2938 :
2939 19504 : SwRootFrm *pRootFrm = getRootFrm();
2940 19504 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2941 0 : pRootFrm->GetCurrShell() )
2942 : {
2943 0 : pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
2944 : }
2945 : }
2946 : }
2947 :
2948 22746 : if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
2949 : {
2950 19504 : SwPageFrm *pPage = FindPageFrm();
2951 19504 : if ( GetNext() )
2952 : {
2953 14492 : GetNext()->_InvalidatePos();
2954 14492 : if ( GetNext()->IsCntntFrm() )
2955 11540 : GetNext()->InvalidatePage( pPage );
2956 : }
2957 : // #i28701# - Due to the new object positioning the
2958 : // frame on the next page/column can flow backward (e.g. it was moved
2959 : // forward due to the positioning of its objects ). Thus, invalivate this
2960 : // next frame, if document compatibility option 'Consider wrapping style
2961 : // influence on object positioning' is ON.
2962 5012 : else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2963 : {
2964 4648 : InvalidateNextPos();
2965 : }
2966 19504 : _InvalidateAll();
2967 19504 : InvalidatePage( pPage );
2968 19504 : SetComplete();
2969 :
2970 19504 : SvxBrushItem aBack = GetFmt()->makeBackgroundBrushItem();
2971 19504 : const SvxGraphicPosition ePos = aBack.GetGraphicPos();
2972 19504 : if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2973 0 : SetCompletePaint();
2974 : }
2975 :
2976 22746 : return nDist;
2977 : }
2978 :
2979 112 : void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2980 : {
2981 112 : sal_uInt8 nInvFlags = 0;
2982 112 : bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
2983 :
2984 112 : if( bAttrSetChg )
2985 : {
2986 106 : SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2987 212 : SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2988 212 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2989 212 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2990 : while( true )
2991 : {
2992 : _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2993 : (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2994 200 : &aOldSet, &aNewSet );
2995 200 : if( aNIter.IsAtEnd() )
2996 106 : break;
2997 94 : aNIter.NextItem();
2998 94 : aOIter.NextItem();
2999 : }
3000 106 : if ( aOldSet.Count() || aNewSet.Count() )
3001 164 : SwLayoutFrm::Modify( &aOldSet, &aNewSet );
3002 : }
3003 : else
3004 6 : _UpdateAttr( pOld, pNew, nInvFlags );
3005 :
3006 112 : if ( nInvFlags != 0 )
3007 : {
3008 96 : SwPageFrm *pPage = FindPageFrm();
3009 96 : InvalidatePage( pPage );
3010 96 : if ( nInvFlags & 0x02 )
3011 72 : _InvalidatePrt();
3012 96 : if ( nInvFlags & 0x40 )
3013 26 : _InvalidatePos();
3014 : SwFrm *pTmp;
3015 96 : if ( 0 != (pTmp = GetIndNext()) )
3016 : {
3017 96 : if ( nInvFlags & 0x04 )
3018 : {
3019 4 : pTmp->_InvalidatePrt();
3020 4 : if ( pTmp->IsCntntFrm() )
3021 4 : pTmp->InvalidatePage( pPage );
3022 : }
3023 96 : if ( nInvFlags & 0x10 )
3024 4 : pTmp->SetCompletePaint();
3025 : }
3026 96 : if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
3027 : {
3028 0 : pTmp->_InvalidatePrt();
3029 0 : if ( pTmp->IsCntntFrm() )
3030 0 : pTmp->InvalidatePage( pPage );
3031 : }
3032 96 : if ( nInvFlags & 0x20 )
3033 : {
3034 70 : if ( pPage && pPage->GetUpper() && !IsFollow() )
3035 70 : ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3036 : }
3037 96 : if ( nInvFlags & 0x80 )
3038 2 : InvalidateNextPos();
3039 : }
3040 112 : }
3041 :
3042 206 : void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
3043 : sal_uInt8 &rInvFlags,
3044 : SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
3045 : {
3046 206 : bool bClear = true;
3047 206 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
3048 206 : switch( nWhich )
3049 : {
3050 : case RES_TBLHEADLINECHG:
3051 2 : if ( IsFollow() )
3052 : {
3053 : // Delete remaining headlines:
3054 0 : SwRowFrm* pLowerRow = 0;
3055 0 : while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
3056 : {
3057 0 : pLowerRow->Cut();
3058 0 : delete pLowerRow;
3059 : }
3060 :
3061 : // insert new headlines
3062 0 : const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
3063 0 : for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
3064 : {
3065 0 : bDontCreateObjects = true; //frmtool
3066 0 : SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
3067 0 : pHeadline->SetRepeatedHeadline( true );
3068 0 : bDontCreateObjects = false;
3069 0 : pHeadline->Paste( this, pLowerRow );
3070 : }
3071 : }
3072 2 : rInvFlags |= 0x02;
3073 2 : break;
3074 :
3075 : case RES_FRM_SIZE:
3076 : case RES_HORI_ORIENT:
3077 100 : rInvFlags |= 0x22;
3078 100 : break;
3079 :
3080 : case RES_PAGEDESC: //Attribute changes (on/off)
3081 22 : if ( IsInDocBody() )
3082 : {
3083 22 : rInvFlags |= 0x40;
3084 22 : SwPageFrm *pPage = FindPageFrm();
3085 22 : if (pPage)
3086 : {
3087 22 : if ( !GetPrev() )
3088 22 : CheckPageDescs( pPage );
3089 22 : if (GetFmt()->GetPageDesc().GetNumOffset())
3090 0 : ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( true );
3091 22 : SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
3092 22 : GetFmt()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFlds( &aMsgHnt );
3093 : }
3094 : }
3095 22 : break;
3096 :
3097 : case RES_BREAK:
3098 2 : rInvFlags |= 0xC0;
3099 2 : break;
3100 :
3101 : case RES_LAYOUT_SPLIT:
3102 2 : if ( !IsFollow() )
3103 2 : rInvFlags |= 0x40;
3104 2 : break;
3105 : case RES_FRAMEDIR :
3106 0 : SetDerivedR2L( false );
3107 0 : CheckDirChange();
3108 0 : break;
3109 : case RES_COLLAPSING_BORDERS :
3110 16 : rInvFlags |= 0x02;
3111 16 : lcl_InvalidateAllLowersPrt( this );
3112 16 : break;
3113 : case RES_UL_SPACE:
3114 4 : rInvFlags |= 0x1C;
3115 : /* no break here */
3116 :
3117 : default:
3118 62 : bClear = false;
3119 : }
3120 206 : if ( bClear )
3121 : {
3122 144 : if ( pOldSet || pNewSet )
3123 : {
3124 142 : if ( pOldSet )
3125 142 : pOldSet->ClearItem( nWhich );
3126 284 : if ( pNewSet )
3127 142 : pNewSet->ClearItem( nWhich );
3128 : }
3129 : else
3130 2 : SwLayoutFrm::Modify( pOld, pNew );
3131 : }
3132 206 : }
3133 :
3134 18 : bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
3135 : {
3136 18 : if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
3137 : {
3138 18 : SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
3139 18 : const SwPageFrm *pPage = FindPageFrm();
3140 18 : if ( pPage )
3141 : {
3142 18 : if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
3143 : {
3144 : //Here it should be (can temporary be different, should we be
3145 : // concerned about this?)
3146 6 : rInfo.SetInfo( pPage, this );
3147 6 : return false;
3148 : }
3149 12 : if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
3150 0 : (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
3151 : {
3152 : //This could be the one.
3153 0 : rInfo.SetInfo( pPage, this );
3154 : }
3155 : }
3156 : }
3157 12 : return true;
3158 : }
3159 :
3160 6842 : SwCntntFrm *SwTabFrm::FindLastCntnt()
3161 : {
3162 6842 : SwFrm *pRet = pLower;
3163 :
3164 27632 : while ( pRet && !pRet->IsCntntFrm() )
3165 : {
3166 13948 : SwFrm *pOld = pRet;
3167 :
3168 13948 : SwFrm *pTmp = pRet; // To skip empty section frames
3169 437412 : while ( pRet->GetNext() )
3170 : {
3171 409516 : pRet = pRet->GetNext();
3172 409516 : if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
3173 409516 : pTmp = pRet;
3174 : }
3175 13948 : pRet = pTmp;
3176 :
3177 13948 : if ( pRet->GetLower() )
3178 13638 : pRet = pRet->GetLower();
3179 13948 : if ( pRet == pOld )
3180 : {
3181 : // Check all other columns if there is a column based section with
3182 : // an empty last column at the end of the last line - this is done
3183 : // by SwSectionFrm::FindLastCntnt
3184 34 : if( pRet->IsColBodyFrm() )
3185 : {
3186 : #if OSL_DEBUG_LEVEL > 0
3187 : SwSectionFrm* pSect = pRet->FindSctFrm();
3188 : OSL_ENSURE( pSect, "Where does this column come fron?");
3189 : OSL_ENSURE( IsAnLower( pSect ), "Splited cell?" );
3190 : #endif
3191 0 : return pRet->FindSctFrm()->FindLastCntnt();
3192 : }
3193 :
3194 : // pRet may be a cell frame without a lower (cell has been split).
3195 : // We have to find the last content the hard way:
3196 :
3197 : OSL_ENSURE( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" );
3198 34 : const SwFrm* pRow = pRet->GetUpper();
3199 68 : while ( pRow && !pRow->GetUpper()->IsTabFrm() )
3200 0 : pRow = pRow->GetUpper();
3201 34 : SwCntntFrm* pCntntFrm = pRow ? ((SwLayoutFrm*)pRow)->ContainsCntnt() : NULL;
3202 34 : pRet = 0;
3203 :
3204 112 : while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
3205 : {
3206 44 : pRet = pCntntFrm;
3207 44 : pCntntFrm = pCntntFrm->GetNextCntntFrm();
3208 : }
3209 : }
3210 : }
3211 :
3212 : // #112929# There actually is a situation, which results in pRet = 0:
3213 : // Insert frame, insert table via text <-> table. This gives you a frame
3214 : // containing a table without any other content frames. Split the table
3215 : // and undo the splitting. This operation gives us a table frame without
3216 : // a lower.
3217 6842 : if ( pRet )
3218 : {
3219 19340 : while ( pRet->GetNext() )
3220 5668 : pRet = pRet->GetNext();
3221 :
3222 6836 : if( pRet->IsSctFrm() )
3223 0 : pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
3224 : }
3225 :
3226 6842 : return (SwCntntFrm*)pRet;
3227 : }
3228 :
3229 : /// Return value defines if the frm needs to be relocated
3230 1526 : bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, bool, bool &rReformat )
3231 : {
3232 1526 : rReformat = false;
3233 1526 : if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
3234 : {
3235 : //Floating back Frm's is quite time consuming unfortunately.
3236 : //Most often the location where the Frm wants to float to has the same
3237 : //FixSize as the Frm itself. In such a situation it's easy to check if
3238 : //the Frm will find enough space for its VarSize, if this is not the
3239 : //case, the relocation can be skipped.
3240 : //Checking if the Frm will find enough space is done by the Frm itself,
3241 : //this also takes the possibility of splitting the Frm into account.
3242 : //If the FixSize is different or Flys are involved (at the old or the
3243 : //new position) the whole checks don't make sense at all, the Frm then
3244 : //needs to be relocated tentatively (if a bit of space is available).
3245 :
3246 : //The FixSize of the surrounding which contain tables is always the
3247 : //width.
3248 :
3249 1526 : SwPageFrm *pOldPage = FindPageFrm(),
3250 1526 : *pNewPage = pNewUpper->FindPageFrm();
3251 1526 : bool bMoveAnyway = false;
3252 1526 : SwTwips nSpace = 0;
3253 :
3254 1526 : SWRECTFN( this )
3255 1526 : if ( !SwFlowFrm::IsMoveBwdJump() )
3256 : {
3257 :
3258 1504 : long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
3259 1504 : SWRECTFNX( pNewUpper );
3260 1504 : long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
3261 1504 : if( std::abs( nNewWidth - nOldWidth ) < 2 )
3262 : {
3263 1492 : if( !( bMoveAnyway = (BwdMoveNecessary( pOldPage, Frm() ) > 1) ) )
3264 : {
3265 1492 : SwRect aRect( pNewUpper->Prt() );
3266 1492 : aRect.Pos() += pNewUpper->Frm().Pos();
3267 1492 : const SwFrm *pPrevFrm = pNewUpper->Lower();
3268 5394 : while ( pPrevFrm && pPrevFrm != this )
3269 : {
3270 2410 : (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
3271 4820 : fnGetBottom)() );
3272 2410 : pPrevFrm = pPrevFrm->GetNext();
3273 : }
3274 1492 : bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
3275 :
3276 : // #i54861# Due to changes made in PrepareMake,
3277 : // the tabfrm may not have a correct position. Therefore
3278 : // it is possible that pNewUpper->Prt().Height == 0. In this
3279 : // case the above calculation of nSpace might give wrong
3280 : // results and we really do not want to MoveBackwrd into a
3281 : // 0 height frame. If nTmpSpace is already <= 0, we take this
3282 : // value:
3283 1492 : const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
3284 1492 : if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
3285 1492 : nSpace = nTmpSpace;
3286 :
3287 1492 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
3288 1492 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
3289 0 : nSpace += pNewUpper->Grow( LONG_MAX, true );
3290 : }
3291 : }
3292 12 : else if( !bLockBackMove )
3293 12 : bMoveAnyway = true;
3294 : }
3295 22 : else if( !bLockBackMove )
3296 22 : bMoveAnyway = true;
3297 :
3298 1526 : if ( bMoveAnyway )
3299 : {
3300 34 : rReformat = true;
3301 34 : return true;
3302 : }
3303 1492 : if ( !bLockBackMove && nSpace > 0 )
3304 : {
3305 : // #i26945# - check, if follow flow line
3306 : // contains frame, which are moved forward due to its object
3307 : // positioning.
3308 1454 : SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
3309 1456 : if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
3310 : SwLayouter::DoesRowContainMovedFwdFrm(
3311 2 : *(pFirstRow->GetFmt()->GetDoc()),
3312 2 : *(pFirstRow) ) )
3313 : {
3314 0 : return false;
3315 : }
3316 1454 : SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
3317 :
3318 : // #118840#
3319 : // For some mysterious reason, I changed the good old
3320 : // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
3321 : // This obviously results in problems with table frames in
3322 : // sections. Remember: Every twip is sacred.
3323 1454 : return nTmpHeight <= nSpace;
3324 : }
3325 : }
3326 38 : return false;
3327 : }
3328 :
3329 216 : void SwTabFrm::Cut()
3330 : {
3331 : OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
3332 :
3333 216 : SwPageFrm *pPage = FindPageFrm();
3334 216 : InvalidatePage( pPage );
3335 216 : SwFrm *pFrm = GetNext();
3336 216 : if( pFrm )
3337 : {
3338 : //The old follower eventually calculated a margin to the predecessor
3339 : //which is obsolete now as it became the first one
3340 112 : pFrm->_InvalidatePrt();
3341 112 : pFrm->_InvalidatePos();
3342 112 : if ( pFrm->IsCntntFrm() )
3343 112 : pFrm->InvalidatePage( pPage );
3344 112 : if( IsInSct() && !GetPrev() )
3345 : {
3346 0 : SwSectionFrm* pSct = FindSctFrm();
3347 0 : if( !pSct->IsFollow() )
3348 : {
3349 0 : pSct->_InvalidatePrt();
3350 0 : pSct->InvalidatePage( pPage );
3351 : }
3352 : }
3353 : }
3354 : else
3355 : {
3356 104 : InvalidateNextPos();
3357 : //Someone has to do the retouch: predecessor or upper
3358 104 : if ( 0 != (pFrm = GetPrev()) )
3359 6 : { pFrm->SetRetouche();
3360 6 : pFrm->Prepare( PREP_WIDOWS_ORPHANS );
3361 6 : pFrm->_InvalidatePos();
3362 6 : if ( pFrm->IsCntntFrm() )
3363 0 : pFrm->InvalidatePage( pPage );
3364 : }
3365 : //If I am (was) the only FlowFrm in my own upper, it has to do
3366 : //the retouch. Moreover it has to do the retouch.
3367 : else
3368 98 : { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
3369 98 : pRoot->SetSuperfluous();
3370 98 : GetUpper()->SetCompletePaint();
3371 98 : if( IsInSct() )
3372 : {
3373 2 : SwSectionFrm* pSct = FindSctFrm();
3374 2 : if( !pSct->IsFollow() )
3375 : {
3376 0 : pSct->_InvalidatePrt();
3377 0 : pSct->InvalidatePage( pPage );
3378 : }
3379 : }
3380 : }
3381 : }
3382 :
3383 : //First remove, then shrink the upper.
3384 216 : SwLayoutFrm *pUp = GetUpper();
3385 216 : SWRECTFN( this )
3386 216 : Remove();
3387 216 : if ( pUp )
3388 : {
3389 : OSL_ENSURE( !pUp->IsFtnFrm(), "Table in Footnote." );
3390 216 : SwSectionFrm *pSct = 0;
3391 : // #126020# - adjust check for empty section
3392 : // #130797# - correct fix #126020#
3393 534 : if ( !pUp->Lower() && pUp->IsInSct() &&
3394 222 : !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
3395 2 : !pSct->ContainsAny( true ) )
3396 : {
3397 2 : if ( pUp->GetUpper() )
3398 : {
3399 2 : pSct->DelEmpty( false );
3400 2 : pSct->_InvalidateSize();
3401 : }
3402 : }
3403 214 : else if( (Frm().*fnRect->fnGetHeight)() )
3404 : {
3405 : // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
3406 : // undo changes of fix for #104992#
3407 56 : pUp->Shrink( Frm().Height() );
3408 : }
3409 : }
3410 :
3411 216 : if ( pPage && !IsFollow() && pPage->GetUpper() )
3412 84 : ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3413 216 : }
3414 :
3415 174 : void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
3416 : {
3417 : OSL_ENSURE( pParent, "No parent for pasting." );
3418 : OSL_ENSURE( pParent->IsLayoutFrm(), "Parent is CntntFrm." );
3419 : OSL_ENSURE( pParent != this, "I'm the parent myself." );
3420 : OSL_ENSURE( pSibling != this, "I'm my own neighbour." );
3421 : OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
3422 : "I'm still registred somewhere." );
3423 :
3424 : //Insert in the tree.
3425 174 : InsertBefore( (SwLayoutFrm*)pParent, pSibling );
3426 :
3427 174 : _InvalidateAll();
3428 174 : SwPageFrm *pPage = FindPageFrm();
3429 174 : InvalidatePage( pPage );
3430 :
3431 174 : if ( GetNext() )
3432 : {
3433 142 : GetNext()->_InvalidatePos();
3434 142 : GetNext()->_InvalidatePrt();
3435 142 : if ( GetNext()->IsCntntFrm() )
3436 142 : GetNext()->InvalidatePage( pPage );
3437 : }
3438 :
3439 174 : SWRECTFN( this )
3440 174 : if( (Frm().*fnRect->fnGetHeight)() )
3441 4 : pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
3442 :
3443 174 : if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
3444 134 : Prepare( PREP_FIXSIZE_CHG );
3445 174 : if ( GetPrev() )
3446 : {
3447 86 : if ( !IsFollow() )
3448 : {
3449 86 : GetPrev()->InvalidateSize();
3450 86 : if ( GetPrev()->IsCntntFrm() )
3451 62 : GetPrev()->InvalidatePage( pPage );
3452 : }
3453 : }
3454 88 : else if ( GetNext() )
3455 : //Take the marging into account when dealing with CntntFrm's. There are
3456 : //two situations (both always happen at once):
3457 : //a) The Cntnt becomes the first in a chain
3458 : //b) The new follower was the first in a chain before
3459 88 : GetNext()->_InvalidatePrt();
3460 :
3461 174 : if ( pPage && !IsFollow() )
3462 : {
3463 174 : if ( pPage->GetUpper() )
3464 174 : ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3465 :
3466 174 : if ( !GetPrev() )//At least needed for HTML with a table at the beginning.
3467 : {
3468 88 : const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
3469 88 : if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
3470 88 : (!pDesc && pPage->GetPageDesc() != &GetFmt()->GetDoc()->GetPageDesc(0)) )
3471 0 : CheckPageDescs( pPage, true );
3472 : }
3473 : }
3474 174 : }
3475 :
3476 384 : void SwTabFrm::Prepare( const PrepareHint eHint, const void *, bool )
3477 : {
3478 384 : if( PREP_BOSS_CHGD == eHint )
3479 134 : CheckDirChange();
3480 384 : }
3481 :
3482 6544 : SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
3483 : SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
3484 : pTabLine( &rLine ),
3485 : pFollowRow( 0 ),
3486 : // #i29550#
3487 : mnTopMarginForLowers( 0 ),
3488 : mnBottomMarginForLowers( 0 ),
3489 : mnBottomLineSize( 0 ),
3490 : // --> split table rows
3491 : bIsFollowFlowRow( false ),
3492 : // <-- split table rows
3493 : bIsRepeatedHeadline( false ),
3494 6544 : mbIsRowSpanLine( false )
3495 : {
3496 6544 : mnType = FRMC_ROW;
3497 :
3498 : //Create the boxes and insert them.
3499 6544 : const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
3500 6544 : SwFrm *pTmpPrev = 0;
3501 25104 : for ( size_t i = 0; i < rBoxes.size(); ++i )
3502 : {
3503 18560 : SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
3504 18560 : pNew->InsertBehind( this, pTmpPrev );
3505 18560 : pTmpPrev = pNew;
3506 : }
3507 6544 : }
3508 :
3509 19632 : SwRowFrm::~SwRowFrm()
3510 : {
3511 6544 : SwModify* pMod = GetFmt();
3512 6544 : if( pMod )
3513 : {
3514 6544 : pMod->Remove( this ); // remove,
3515 6544 : if( !pMod->GetDepends() )
3516 0 : delete pMod; // and delete
3517 : }
3518 13088 : }
3519 :
3520 1328 : void SwRowFrm::RegistFlys( SwPageFrm *pPage )
3521 : {
3522 1328 : ::RegistFlys( pPage ? pPage : FindPageFrm(), this );
3523 1328 : }
3524 :
3525 286 : void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
3526 : {
3527 286 : bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
3528 286 : const SfxPoolItem *pItem = 0;
3529 :
3530 286 : if( bAttrSetChg )
3531 : {
3532 150 : const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
3533 150 : pChgSet->GetItemState( RES_FRM_SIZE, false, &pItem);
3534 150 : if ( !pItem )
3535 106 : pChgSet->GetItemState( RES_ROW_SPLIT, false, &pItem);
3536 : }
3537 136 : else if (pNew && (RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which()))
3538 136 : pItem = pNew;
3539 :
3540 286 : if ( pItem )
3541 : {
3542 186 : SwTabFrm *pTab = FindTabFrm();
3543 186 : if ( pTab )
3544 : {
3545 186 : const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
3546 186 : this == pTab->GetFirstNonHeadlineRow();
3547 : // #i35063#
3548 : // Invalidation required is pRow is last row
3549 186 : if ( bInFirstNonHeadlineRow || !GetNext() )
3550 : {
3551 166 : if ( bInFirstNonHeadlineRow )
3552 0 : pTab = pTab->FindMaster();
3553 166 : pTab->InvalidatePos();
3554 : }
3555 : }
3556 : }
3557 :
3558 286 : SwLayoutFrm::Modify( pOld, pNew );
3559 286 : }
3560 :
3561 34388 : void SwRowFrm::MakeAll()
3562 : {
3563 34388 : if ( !GetNext() )
3564 6226 : mbValidSize = false;
3565 34388 : SwLayoutFrm::MakeAll();
3566 34388 : }
3567 :
3568 245778 : long CalcHeightWithFlys( const SwFrm *pFrm )
3569 : {
3570 245778 : SWRECTFN( pFrm )
3571 245778 : long nHeight = 0;
3572 245778 : const SwFrm* pTmp = pFrm->IsSctFrm() ?
3573 245778 : ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
3574 491556 : while( pTmp )
3575 : {
3576 : // #i26945# - consider follow text frames
3577 245778 : const SwSortedObjs* pObjs( 0L );
3578 245778 : bool bIsFollow( false );
3579 245778 : if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
3580 : {
3581 : const SwFrm* pMaster;
3582 : // #i46450# Master does not necessarily have
3583 : // to exist if this function is called from JoinFrm() ->
3584 : // Cut() -> Shrink()
3585 2984 : const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
3586 8828 : if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
3587 5844 : static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
3588 1430 : static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
3589 0 : pMaster = 0;
3590 : else
3591 2984 : pMaster = pTmpFrm->FindMaster();
3592 :
3593 2984 : if ( pMaster )
3594 : {
3595 2984 : pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
3596 2984 : bIsFollow = true;
3597 : }
3598 : }
3599 : else
3600 : {
3601 242794 : pObjs = pTmp->GetDrawObjs();
3602 : }
3603 245778 : if ( pObjs )
3604 : {
3605 6026 : for ( size_t i = 0; i < pObjs->size(); ++i )
3606 : {
3607 3332 : const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
3608 : // #i26945# - if <pTmp> is follow, the
3609 : // anchor character frame has to be <pTmp>.
3610 3420 : if ( bIsFollow &&
3611 88 : const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
3612 : {
3613 88 : continue;
3614 : }
3615 : // #i26945# - consider also drawing objects
3616 : {
3617 : // OD 30.09.2003 #i18732# - only objects, which follow
3618 : // the text flow have to be considered.
3619 3244 : const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
3620 : const bool bConsiderObj =
3621 4720 : (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
3622 5946 : pAnchoredObj->GetObjRect().Top() != FAR_AWAY &&
3623 6986 : rFrmFmt.GetFollowTextFlow().GetValue() &&
3624 5760 : pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
3625 3244 : if ( bConsiderObj )
3626 : {
3627 10 : const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
3628 10 : if( !rSz.GetHeightPercent() )
3629 : {
3630 : const SwTwips nDistOfFlyBottomToAnchorTop =
3631 30 : (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
3632 : ( bVert ?
3633 10 : pAnchoredObj->GetCurrRelPos().X() :
3634 20 : pAnchoredObj->GetCurrRelPos().Y() );
3635 :
3636 : const SwTwips nFrmDiff =
3637 : (*fnRect->fnYDiff)(
3638 20 : (pTmp->Frm().*fnRect->fnGetTop)(),
3639 30 : (pFrm->Frm().*fnRect->fnGetTop)() );
3640 :
3641 20 : nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
3642 20 : (pFrm->Frm().*fnRect->fnGetHeight)() );
3643 :
3644 : // #i56115# The first height calculation
3645 : // gives wrong results if pFrm->Prt().Y() > 0. We do
3646 : // a second calculation based on the actual rectangles of
3647 : // pFrm and pAnchoredObj, and use the maximum of the results.
3648 : // I do not want to remove the first calculation because
3649 : // if clipping has been applied, using the GetCurrRelPos
3650 : // might be the better option to calculate nHeight.
3651 : const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
3652 20 : (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
3653 30 : (pFrm->Frm().*fnRect->fnGetBottom)() );
3654 :
3655 10 : nHeight = std::max( nHeight, nDistOfFlyBottomToAnchorTop2 );
3656 : }
3657 : }
3658 : }
3659 : }
3660 : }
3661 245778 : if( !pFrm->IsSctFrm() )
3662 245758 : break;
3663 20 : pTmp = pTmp->FindNextCnt();
3664 20 : if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
3665 20 : break;
3666 : }
3667 245778 : return nHeight;
3668 : }
3669 :
3670 162604 : static SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
3671 : {
3672 162604 : const SwTabFrm* pTab = rCell.FindTabFrm();
3673 162604 : SwTwips nTopSpace = 0;
3674 162604 : SwTwips nBottomSpace = 0;
3675 :
3676 : // #i29550#
3677 162604 : if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
3678 : {
3679 162162 : nTopSpace = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
3680 162162 : nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
3681 : }
3682 : else
3683 : {
3684 442 : if ( pTab->IsVertical() != rCell.IsVertical() )
3685 : {
3686 0 : nTopSpace = rAttrs.CalcLeft( &rCell );
3687 0 : nBottomSpace = rAttrs.CalcRight( &rCell );
3688 : }
3689 : else
3690 : {
3691 442 : nTopSpace = rAttrs.CalcTop();
3692 442 : nBottomSpace = rAttrs.CalcBottom();
3693 : }
3694 : }
3695 :
3696 162604 : return nTopSpace + nBottomSpace;
3697 : }
3698 :
3699 : // #i26945# - add parameter <_bConsiderObjs> in order to
3700 : // control, if floating screen objects have to be considered for the minimal
3701 : // cell height.
3702 152574 : static SwTwips lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
3703 : const bool _bConsiderObjs,
3704 : const SwBorderAttrs *pAttrs = 0 )
3705 : {
3706 152574 : SWRECTFN( _pCell )
3707 152574 : SwTwips nHeight = 0;
3708 152574 : const SwFrm* pLow = _pCell->Lower();
3709 152574 : if ( pLow )
3710 : {
3711 150176 : long nFlyAdd = 0;
3712 568184 : while ( pLow )
3713 : {
3714 : // OD 2004-02-18 #106629# - change condition and switch then-body
3715 : // and else-body
3716 267832 : if ( pLow->IsRowFrm() )
3717 : {
3718 : // #i26945#
3719 : nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
3720 0 : _bConsiderObjs );
3721 : }
3722 : else
3723 : {
3724 267832 : long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
3725 267832 : nHeight += nLowHeight;
3726 : // #i26945#
3727 267832 : if ( _bConsiderObjs )
3728 : {
3729 245778 : nFlyAdd = std::max( 0L, nFlyAdd - nLowHeight );
3730 245778 : nFlyAdd = std::max( nFlyAdd, ::CalcHeightWithFlys( pLow ) );
3731 : }
3732 : }
3733 :
3734 267832 : pLow = pLow->GetNext();
3735 : }
3736 150176 : if ( nFlyAdd )
3737 10 : nHeight += nFlyAdd;
3738 : }
3739 : //The border needs to be considered too, unfortunately it can't be
3740 : //calculated using PrtArea and Frm because those can be invalid in arbitrary
3741 : //combinations.
3742 152574 : if ( _pCell->Lower() )
3743 : {
3744 150176 : if ( pAttrs )
3745 40170 : nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
3746 : else
3747 : {
3748 110006 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
3749 110006 : const SwBorderAttrs &rAttrs = *aAccess.Get();
3750 110006 : nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
3751 : }
3752 : }
3753 152574 : return nHeight;
3754 : }
3755 :
3756 : // OD 2004-02-18 #106629# - correct type of 1st parameter
3757 : // #i26945# - add parameter <_bConsiderObjs> in order to control,
3758 : // if floating screen objects have to be considered for the minimal cell height
3759 42312 : static SwTwips lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
3760 : const bool _bConsiderObjs )
3761 : {
3762 42312 : SWRECTFN( _pRow )
3763 :
3764 42312 : const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
3765 :
3766 42312 : if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
3767 : {
3768 : OSL_ENSURE( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" );
3769 0 : return rSz.GetHeight();
3770 : }
3771 :
3772 42312 : SwTwips nHeight = 0;
3773 42312 : const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
3774 197258 : while ( pLow )
3775 : {
3776 112634 : SwTwips nTmp = 0;
3777 112634 : const long nRowSpan = pLow->GetLayoutRowSpan();
3778 : // --> NEW TABLES
3779 : // Consider height of
3780 : // 1. current cell if RowSpan == 1
3781 : // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
3782 : // 3. master cell if RowSpan == -1
3783 112634 : if ( 1 == nRowSpan )
3784 : {
3785 111788 : nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
3786 : }
3787 846 : else if ( -1 == nRowSpan )
3788 : {
3789 : // Height of the last cell of a row span is height of master cell
3790 : // minus the height of the other rows which are covered by the master
3791 : // cell:
3792 284 : const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
3793 284 : nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
3794 284 : const SwFrm* pMasterRow = rMaster.GetUpper();
3795 918 : while ( pMasterRow && pMasterRow != _pRow )
3796 : {
3797 350 : nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
3798 350 : pMasterRow = pMasterRow->GetNext();
3799 : }
3800 : }
3801 : // <-- NEW TABLES
3802 :
3803 : // Do not consider rotated cells:
3804 112634 : if ( pLow->IsVertical() == bVert && nTmp > nHeight )
3805 44566 : nHeight = nTmp;
3806 :
3807 112634 : pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
3808 : }
3809 42312 : if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
3810 20256 : nHeight = std::max( nHeight, rSz.GetHeight() );
3811 42312 : return nHeight;
3812 : }
3813 :
3814 : // #i29550#
3815 :
3816 : // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
3817 33038 : static sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
3818 : {
3819 33038 : sal_uInt16 nTopSpace = 0;
3820 111596 : for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
3821 78558 : pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
3822 : {
3823 78558 : sal_uInt16 nTmpTopSpace = 0;
3824 78558 : if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
3825 0 : nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
3826 : else
3827 : {
3828 78558 : const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
3829 78558 : const SvxBoxItem& rBoxItem = rSet.GetBox();
3830 78558 : nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, true );
3831 : }
3832 78558 : nTopSpace = std::max( nTopSpace, nTmpTopSpace );
3833 : }
3834 33038 : return nTopSpace;
3835 : }
3836 :
3837 : // Calculate the maximum of TopLineDist over all lowers:
3838 33038 : static sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
3839 : {
3840 33038 : sal_uInt16 nTopLineDist = 0;
3841 111596 : for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
3842 78558 : pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
3843 : {
3844 78558 : sal_uInt16 nTmpTopLineDist = 0;
3845 78558 : if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
3846 0 : nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
3847 : else
3848 : {
3849 78558 : const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
3850 78558 : const SvxBoxItem& rBoxItem = rSet.GetBox();
3851 78558 : nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
3852 : }
3853 78558 : nTopLineDist = std::max( nTopLineDist, nTmpTopLineDist );
3854 : }
3855 33038 : return nTopLineDist;
3856 : }
3857 :
3858 : // Calculate the maximum of BottomLineSize over all lowers:
3859 33038 : static sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
3860 : {
3861 33038 : sal_uInt16 nBottomLineSize = 0;
3862 111596 : for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
3863 78558 : pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
3864 : {
3865 78558 : sal_uInt16 nTmpBottomLineSize = 0;
3866 78558 : if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
3867 : {
3868 0 : const SwFrm* pRow = pCurrLower->GetLastLower();
3869 0 : nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
3870 : }
3871 : else
3872 : {
3873 78558 : const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
3874 78558 : const SvxBoxItem& rBoxItem = rSet.GetBox();
3875 78558 : nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, true ) -
3876 78558 : rBoxItem.GetDistance( BOX_LINE_BOTTOM );
3877 : }
3878 78558 : nBottomLineSize = std::max( nBottomLineSize, nTmpBottomLineSize );
3879 : }
3880 33038 : return nBottomLineSize;
3881 : }
3882 :
3883 : // Calculate the maximum of BottomLineDist over all lowers:
3884 33038 : static sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
3885 : {
3886 33038 : sal_uInt16 nBottomLineDist = 0;
3887 111596 : for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
3888 78558 : pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
3889 : {
3890 78558 : sal_uInt16 nTmpBottomLineDist = 0;
3891 78558 : if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
3892 : {
3893 0 : const SwFrm* pRow = pCurrLower->GetLastLower();
3894 0 : nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
3895 : }
3896 : else
3897 : {
3898 78558 : const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
3899 78558 : const SvxBoxItem& rBoxItem = rSet.GetBox();
3900 78558 : nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
3901 : }
3902 78558 : nBottomLineDist = std::max( nBottomLineDist, nTmpBottomLineDist );
3903 : }
3904 33038 : return nBottomLineDist;
3905 : }
3906 :
3907 33184 : void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
3908 : {
3909 33184 : SWRECTFN( this )
3910 : OSL_ENSURE( pAttrs, "SwRowFrm::Format without Attrs." );
3911 :
3912 33184 : const bool bFix = mbFixSize;
3913 :
3914 33184 : if ( !mbValidPrtArea )
3915 : {
3916 : //RowFrms don't have borders and so on therefore the PrtArea always
3917 : //matches the Frm.
3918 33184 : mbValidPrtArea = true;
3919 33184 : maPrt.Left( 0 );
3920 33184 : maPrt.Top( 0 );
3921 33184 : maPrt.Width ( maFrm.Width() );
3922 33184 : maPrt.Height( maFrm.Height() );
3923 :
3924 : // #i29550#
3925 : // Here we calculate the top-printing area for the lower cell frames
3926 33184 : SwTabFrm* pTabFrm = FindTabFrm();
3927 33184 : if ( pTabFrm->IsCollapsingBorders() )
3928 : {
3929 33038 : const sal_uInt16 nTopSpace = lcl_GetTopSpace( *this );
3930 33038 : const sal_uInt16 nTopLineDist = lcl_GetTopLineDist( *this );
3931 33038 : const sal_uInt16 nBottomLineSize = lcl_GetBottomLineSize( *this );
3932 33038 : const sal_uInt16 nBottomLineDist = lcl_GetBottomLineDist( *this );
3933 :
3934 33038 : const SwRowFrm* pPreviousRow = 0;
3935 :
3936 : // #i32456#
3937 : // In order to calculate the top printing area for the lower cell
3938 : // frames, we have to find the 'previous' row frame and compare
3939 : // the bottom values of the 'previous' row with the 'top' values
3940 : // of this row. The best way to find the 'previous' row is to
3941 : // use the table structure:
3942 33038 : const SwTable* pTable = pTabFrm->GetTable();
3943 33038 : const SwTableLine* pPrevTabLine = 0;
3944 33038 : const SwRowFrm* pTmpRow = this;
3945 :
3946 99114 : while ( pTmpRow && !pPrevTabLine )
3947 : {
3948 33038 : size_t nIdx = 0;
3949 33038 : const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
3950 0 : pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
3951 33038 : pTable->GetTabLines();
3952 :
3953 1965030 : while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
3954 1898954 : ++nIdx;
3955 :
3956 33038 : if ( nIdx > 0 )
3957 : {
3958 : // pTmpRow has a 'previous' row in the table structure:
3959 27818 : pPrevTabLine = rLines[ nIdx - 1 ];
3960 : }
3961 : else
3962 : {
3963 : // pTmpRow is a first row in the table structue.
3964 : // We go up in the table structure:
3965 10440 : pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
3966 5220 : pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
3967 0 : static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
3968 5220 : 0;
3969 : }
3970 : }
3971 :
3972 : // If we found a 'previous' row, we look for the appropriate row frame:
3973 33038 : if ( pPrevTabLine )
3974 : {
3975 27818 : SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
3976 43794 : for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
3977 : {
3978 : // #115759# - do *not* take repeated
3979 : // headlines, because during split of table it can be
3980 : // invalid and thus can't provide correct border values.
3981 71698 : if ( pRow->GetTabLine() == pPrevTabLine &&
3982 27904 : !pRow->IsRepeatedHeadline() )
3983 : {
3984 27818 : pPreviousRow = pRow;
3985 27818 : break;
3986 : }
3987 27818 : }
3988 : }
3989 :
3990 33038 : sal_uInt16 nTopPrtMargin = nTopSpace;
3991 33038 : if ( pPreviousRow )
3992 : {
3993 27818 : const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
3994 27818 : if ( nTmpPrtMargin > nTopPrtMargin )
3995 1964 : nTopPrtMargin = nTmpPrtMargin;
3996 : }
3997 :
3998 : // table has to be notified if it has to change its lower
3999 : // margin due to changes of nBottomLineSize:
4000 33038 : if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
4001 802 : pTabFrm->_InvalidatePrt();
4002 :
4003 : // If there are rows nested inside this row, the nested rows
4004 : // may not have been calculated yet. Therefore the
4005 : // ::lcl_CalcMinRowHeight( this ) operation later in this
4006 : // function cannot consider the correct border values. We
4007 : // have to trigger the invalidation of the outer row frame
4008 : // manually:
4009 : // Note: If any further invalidations should be necessary, we
4010 : // should consider moving the invalidation stuff to the
4011 : // appropriate SwNotify object.
4012 33038 : if ( GetUpper()->GetUpper()->IsRowFrm() &&
4013 0 : ( nBottomLineDist != GetBottomMarginForLowers() ||
4014 0 : nTopPrtMargin != GetTopMarginForLowers() ) )
4015 0 : GetUpper()->GetUpper()->_InvalidateSize();
4016 :
4017 33038 : SetBottomMarginForLowers( nBottomLineDist ); // 3.
4018 33038 : SetBottomLineSize( nBottomLineSize ); // 4.
4019 33038 : SetTopMarginForLowers( nTopPrtMargin ); // 5.
4020 :
4021 : }
4022 : }
4023 :
4024 99552 : while ( !mbValidSize )
4025 : {
4026 33184 : mbValidSize = true;
4027 :
4028 : #if OSL_DEBUG_LEVEL > 0
4029 : if ( HasFixSize() )
4030 : {
4031 : const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
4032 : OSL_ENSURE( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
4033 : }
4034 : #endif
4035 99552 : const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
4036 33742 : ( HasFixSize() && !IsRowSpanLine()
4037 558 : ? pAttrs->GetSize().Height()
4038 : // #i26945#
4039 : : ::lcl_CalcMinRowHeight( this,
4040 65810 : FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
4041 33184 : if ( nDiff )
4042 : {
4043 5600 : mbFixSize = false;
4044 5600 : if ( nDiff > 0 )
4045 378 : Shrink( nDiff, false, true );
4046 5222 : else if ( nDiff < 0 )
4047 5222 : Grow( -nDiff );
4048 5600 : mbFixSize = bFix;
4049 : }
4050 : }
4051 :
4052 : // last row will fill the space in its upper.
4053 33184 : if ( !GetNext() )
4054 : {
4055 : //The last fills the remaining space in the upper.
4056 7598 : SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
4057 7598 : SwFrm *pSibling = GetUpper()->Lower();
4058 63874 : do
4059 63874 : { nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
4060 63874 : pSibling = pSibling->GetNext();
4061 : } while ( pSibling );
4062 7598 : if ( nDiff > 0 )
4063 : {
4064 0 : mbFixSize = false;
4065 0 : Grow( nDiff );
4066 0 : mbFixSize = bFix;
4067 0 : mbValidSize = true;
4068 : }
4069 : }
4070 33184 : }
4071 :
4072 48946 : void SwRowFrm::AdjustCells( const SwTwips nHeight, const bool bHeight )
4073 : {
4074 48946 : SwFrm *pFrm = Lower();
4075 48946 : if ( bHeight )
4076 : {
4077 43084 : SwRootFrm *pRootFrm = getRootFrm();
4078 43084 : SWRECTFN( this )
4079 43084 : SwRect aOldFrm;
4080 :
4081 209848 : while ( pFrm )
4082 : {
4083 123680 : SwFrm* pNotify = 0;
4084 :
4085 123680 : SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
4086 :
4087 : // NEW TABLES
4088 : // Which cells need to be adjusted if the current row changes
4089 : // its height?
4090 :
4091 : // Current frame is a covered frame:
4092 : // Set new height for covered cell and adjust master cell:
4093 123680 : if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
4094 : {
4095 : // Set height of current (covered) cell to new line height.
4096 532 : const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
4097 532 : if ( nDiff )
4098 : {
4099 154 : (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
4100 154 : pCellFrm->_InvalidatePrt();
4101 : }
4102 : }
4103 :
4104 123680 : SwCellFrm* pToAdjust = 0;
4105 123680 : SwFrm* pToAdjustRow = 0;
4106 :
4107 : // If current frame is covered frame, we still want to adjust the
4108 : // height of the cell starting the row span
4109 123680 : if ( pCellFrm->GetLayoutRowSpan() < 1 )
4110 : {
4111 532 : pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
4112 532 : pToAdjustRow = pToAdjust->GetUpper();
4113 : }
4114 : else
4115 : {
4116 123148 : pToAdjust = pCellFrm;
4117 123148 : pToAdjustRow = this;
4118 : }
4119 :
4120 : // Set height of master cell to height of all lines spanned by this line.
4121 123680 : long nRowSpan = pToAdjust->GetLayoutRowSpan();
4122 123680 : SwTwips nSumRowHeight = 0;
4123 249162 : while ( pToAdjustRow )
4124 : {
4125 : // Use new height for the current row:
4126 125218 : nSumRowHeight += pToAdjustRow == this ?
4127 : nHeight :
4128 125218 : (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
4129 :
4130 125218 : if ( nRowSpan-- == 1 )
4131 123416 : break;
4132 :
4133 1802 : pToAdjustRow = pToAdjustRow->GetNext();
4134 : }
4135 :
4136 123680 : if ( pToAdjustRow && pToAdjustRow != this )
4137 382 : pToAdjustRow->_InvalidateSize();
4138 :
4139 123680 : const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
4140 123680 : if ( nDiff )
4141 : {
4142 50222 : aOldFrm = pToAdjust->Frm();
4143 50222 : (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
4144 50222 : pNotify = pToAdjust;
4145 : }
4146 :
4147 123680 : if ( pNotify )
4148 : {
4149 50222 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
4150 0 : pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
4151 :
4152 50222 : pNotify->_InvalidatePrt();
4153 : }
4154 :
4155 123680 : pFrm = pFrm->GetNext();
4156 : }
4157 : }
4158 : else
4159 27052 : { while ( pFrm )
4160 : {
4161 15328 : pFrm->_InvalidateAll();
4162 15328 : pFrm = pFrm->GetNext();
4163 : }
4164 : }
4165 48946 : InvalidatePage();
4166 48946 : }
4167 :
4168 1580 : void SwRowFrm::Cut()
4169 : {
4170 1580 : SwTabFrm *pTab = FindTabFrm();
4171 1580 : if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
4172 : {
4173 1562 : pTab->FindMaster()->InvalidatePos();
4174 : }
4175 :
4176 1580 : SwLayoutFrm::Cut();
4177 1580 : }
4178 :
4179 23316 : SwTwips SwRowFrm::GrowFrm( SwTwips nDist, bool bTst, bool bInfo )
4180 : {
4181 23316 : SwTwips nReal = 0;
4182 :
4183 23316 : SwTabFrm* pTab = FindTabFrm();
4184 23316 : SWRECTFN( pTab )
4185 :
4186 : bool bRestrictTableGrowth;
4187 23316 : bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
4188 :
4189 23316 : if ( GetUpper()->IsTabFrm() )
4190 : {
4191 23316 : const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
4192 23316 : bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
4193 : }
4194 : else
4195 : {
4196 : OSL_ENSURE( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" );
4197 0 : bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
4198 : OSL_ENSURE( !bRestrictTableGrowth || !GetNext(),
4199 : "GetFollowRow for row frame that has a Next" );
4200 :
4201 : // There may still be some space left in my direct upper:
4202 : const SwTwips nAdditionalSpace =
4203 0 : (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
4204 0 : if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
4205 : {
4206 0 : nReal = std::min( nAdditionalSpace, nDist );
4207 0 : nDist -= nReal;
4208 0 : if ( !bTst )
4209 0 : (Frm().*fnRect->fnAddBottom)( nReal );
4210 : }
4211 : }
4212 :
4213 23316 : if ( bRestrictTableGrowth )
4214 6050 : pTab->SetRestrictTableGrowth( true );
4215 : else
4216 : {
4217 : // Ok, this looks like a hack, indeed, it is a hack.
4218 : // If the current row frame is inside another cell frame,
4219 : // and the current row frame has no follow, it should not
4220 : // be allowed to grow. In fact, setting bRestrictTableGrowth
4221 : // to 'false' does not work, because the surrounding RowFrm
4222 : // would set this to 'true'.
4223 17266 : pTab->SetFollowFlowLine( false );
4224 : }
4225 :
4226 23316 : nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
4227 :
4228 23316 : pTab->SetRestrictTableGrowth( false );
4229 23316 : pTab->SetFollowFlowLine( bHasFollowFlowLine );
4230 :
4231 : //Update the height of the cells to the newest value.
4232 23316 : if ( !bTst )
4233 : {
4234 19406 : SWRECTFNX( this )
4235 19406 : AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, true );
4236 19406 : if ( nReal )
4237 16744 : SetCompletePaint();
4238 : }
4239 :
4240 23316 : return nReal;
4241 : }
4242 :
4243 18146 : SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, bool bTst, bool bInfo )
4244 : {
4245 18146 : SWRECTFN( this )
4246 18146 : if( HasFixSize() )
4247 : {
4248 952 : AdjustCells( (Prt().*fnRect->fnGetHeight)(), true );
4249 952 : return 0L;
4250 : }
4251 :
4252 : // bInfo may be set to true by SwRowFrm::Format; we need to hangle this
4253 : // here accordingly
4254 17194 : const bool bShrinkAnyway = bInfo;
4255 :
4256 : //Only shrink as much as the content of the biggest cell allows.
4257 17194 : SwTwips nRealDist = nDist;
4258 : {
4259 17194 : const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
4260 17194 : SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
4261 : rSz.GetHeight() :
4262 17194 : 0;
4263 :
4264 : // Only necessary to calculate minimal row height if height
4265 : // of pRow is at least nMinHeight. Otherwise nMinHeight is the
4266 : // minimum height.
4267 17194 : if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
4268 : {
4269 : // #i26945#
4270 : OSL_ENSURE( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
4271 9686 : const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
4272 9686 : nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
4273 : }
4274 :
4275 17194 : if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
4276 14298 : nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
4277 : }
4278 17194 : if ( nRealDist < 0 )
4279 6 : nRealDist = 0;
4280 :
4281 17194 : SwTwips nReal = nRealDist;
4282 17194 : if ( nReal )
4283 : {
4284 3314 : if ( !bTst )
4285 : {
4286 3314 : SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4287 3314 : (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
4288 :
4289 3314 : if( IsVertical() && !IsVertLR() && !bRev )
4290 0 : Frm().Pos().X() += nReal;
4291 : }
4292 :
4293 3314 : SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
4294 3314 : if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
4295 : {
4296 : //The last one gets the leftover in the upper and therefore takes
4297 : //care (otherwise: endless loop)
4298 0 : if ( !bTst )
4299 : {
4300 0 : nReal -= nTmp;
4301 0 : SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4302 0 : (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
4303 :
4304 0 : if( IsVertical() && !IsVertLR() && !bRev )
4305 0 : Frm().Pos().X() -= nReal;
4306 : }
4307 0 : nReal = nTmp;
4308 : }
4309 : }
4310 :
4311 : //Invalidate if possible and update the height to the newest value.
4312 17194 : if ( !bTst )
4313 : {
4314 17194 : if ( nReal )
4315 : {
4316 3314 : if ( GetNext() )
4317 646 : GetNext()->_InvalidatePos();
4318 3314 : _InvalidateAll();
4319 3314 : SetCompletePaint();
4320 :
4321 3314 : SwTabFrm *pTab = FindTabFrm();
4322 6628 : if ( !pTab->IsRebuildLastLine()
4323 1740 : && pTab->IsFollow()
4324 696 : && this == pTab->GetFirstNonHeadlineRow()
4325 3706 : && !pTab->IsInRecalcLowerRow() )
4326 : {
4327 392 : SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
4328 392 : pMasterTab->InvalidatePos();
4329 : }
4330 : }
4331 17194 : AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, true );
4332 : }
4333 17194 : return nReal;
4334 : }
4335 :
4336 3908 : bool SwRowFrm::IsRowSplitAllowed() const
4337 : {
4338 : // Fixed size rows are never allowed to split:
4339 3908 : if ( HasFixSize() )
4340 : {
4341 : OSL_ENSURE( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" );
4342 14 : return false;
4343 : }
4344 :
4345 : // Repeated headlines are never allowed to split:
4346 3894 : const SwTabFrm* pTabFrm = FindTabFrm();
4347 3906 : if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
4348 12 : pTabFrm->IsInHeadline( *this ) )
4349 0 : return false;
4350 :
4351 3894 : const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
4352 3894 : const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
4353 3894 : return rLP.GetValue();
4354 : }
4355 :
4356 8228 : bool SwRowFrm::ShouldRowKeepWithNext() const
4357 : {
4358 8228 : bool bRet = false;
4359 :
4360 8228 : const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
4361 8228 : const SwFrm* pTxt = pCell->Lower();
4362 :
4363 8228 : if ( pTxt && pTxt->IsTxtFrm() )
4364 : {
4365 7906 : bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
4366 : }
4367 8228 : return bRet;
4368 : }
4369 :
4370 18560 : SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
4371 : SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
4372 18560 : pTabBox( &rBox )
4373 : {
4374 18560 : mnType = FRMC_CELL;
4375 :
4376 18560 : if ( !bInsertContent )
4377 19226 : return;
4378 :
4379 : //If a StartIdx is available, CntntFrms are added in the cell, otherwise
4380 : //Rows have to be present and those are added.
4381 17894 : if ( rBox.GetSttIdx() )
4382 : {
4383 17894 : sal_uLong nIndex = rBox.GetSttIdx();
4384 17894 : ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
4385 : }
4386 : else
4387 : {
4388 0 : const SwTableLines &rLines = rBox.GetTabLines();
4389 0 : SwFrm *pTmpPrev = 0;
4390 0 : for ( size_t i = 0; i < rLines.size(); ++i )
4391 : {
4392 0 : SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
4393 0 : pNew->InsertBehind( this, pTmpPrev );
4394 0 : pTmpPrev = pNew;
4395 : }
4396 : }
4397 : }
4398 :
4399 55680 : SwCellFrm::~SwCellFrm()
4400 : {
4401 18560 : SwModify* pMod = GetFmt();
4402 18560 : if( pMod )
4403 : {
4404 : // At this stage the lower frames aren't destroyed already,
4405 : // therefore we have to do a recursive dispose.
4406 18560 : SwRootFrm *pRootFrm = getRootFrm();
4407 18560 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
4408 0 : pRootFrm->GetCurrShell() )
4409 : {
4410 0 : pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, true );
4411 : }
4412 :
4413 18560 : pMod->Remove( this ); // remove,
4414 18560 : if( !pMod->GetDepends() )
4415 0 : delete pMod; // and delete
4416 : }
4417 37120 : }
4418 :
4419 73794 : static bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, bool bInva )
4420 : {
4421 73794 : bool bRet = false;
4422 73794 : SwFrm *pFrm = pLay->Lower();
4423 73794 : SWRECTFN( pLay )
4424 292494 : while ( pFrm )
4425 : {
4426 144906 : long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
4427 144906 : if( nFrmTop != lYStart )
4428 : {
4429 113170 : bRet = true;
4430 113170 : const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
4431 113170 : const long lDiffX = lYStart - nFrmTop;
4432 113170 : (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
4433 113170 : (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
4434 113170 : pFrm->SetCompletePaint();
4435 113170 : if ( !pFrm->GetNext() )
4436 63616 : pFrm->SetRetouche();
4437 113170 : if( bInva )
4438 36414 : pFrm->Prepare( PREP_POS_CHGD );
4439 113170 : if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
4440 : lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
4441 33464 : (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
4442 66928 : + lDiffX, bInva );
4443 113170 : if ( pFrm->GetDrawObjs() )
4444 : {
4445 866 : for ( size_t i = 0; i < pFrm->GetDrawObjs()->size(); ++i )
4446 : {
4447 500 : SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
4448 : // #i26945# - check, if anchored object
4449 : // is lower of layout frame by checking, if the anchor
4450 : // frame, which contains the anchor position, is a lower
4451 : // of the layout frame.
4452 500 : if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
4453 : {
4454 0 : continue;
4455 : }
4456 : // #i52904# - distinguish between anchored
4457 : // objects, whose vertical position depends on its anchor
4458 : // frame and whose vertical position is independent
4459 : // from its anchor frame.
4460 500 : bool bVertPosDepOnAnchor( true );
4461 : {
4462 500 : SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
4463 500 : switch ( aVert.GetRelationOrient() )
4464 : {
4465 : case text::RelOrientation::PAGE_FRAME:
4466 : case text::RelOrientation::PAGE_PRINT_AREA:
4467 38 : bVertPosDepOnAnchor = false;
4468 38 : break;
4469 462 : default: break;
4470 500 : }
4471 : }
4472 500 : if ( pAnchoredObj->ISA(SwFlyFrm) )
4473 : {
4474 150 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
4475 :
4476 : // OD 2004-05-18 #i28701# - no direct move of objects,
4477 : // which are anchored to-paragraph/to-character, if
4478 : // the wrapping style influence has to be considered
4479 : // on the object positioning.
4480 : // #i52904# - no direct move of objects,
4481 : // whose vertical position doesn't depend on anchor frame.
4482 : const bool bDirectMove =
4483 162 : FAR_AWAY != pFly->Frm().Top() &&
4484 156 : bVertPosDepOnAnchor &&
4485 156 : !pFly->ConsiderObjWrapInfluenceOnObjPos();
4486 150 : if ( bDirectMove )
4487 : {
4488 6 : (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
4489 6 : (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
4490 6 : pFly->GetVirtDrawObj()->SetRectsDirty();
4491 : // --> OD 2004-08-17 - also notify view of <SdrObject>
4492 : // instance, which represents the Writer fly frame in
4493 : // the drawing layer
4494 6 : pFly->GetVirtDrawObj()->SetChanged();
4495 : // #i58280#
4496 6 : pFly->InvalidateObjRectWithSpaces();
4497 : }
4498 :
4499 150 : if ( pFly->IsFlyInCntFrm() )
4500 : {
4501 2 : static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
4502 : // #115759# - reset current relative
4503 : // position to get re-positioned, if not directly moved.
4504 2 : if ( !bDirectMove )
4505 : {
4506 2 : pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
4507 : }
4508 : }
4509 148 : else if( pFly->IsAutoPos() )
4510 : {
4511 106 : pFly->AddLastCharY( lDiff );
4512 : // OD 2004-05-18 #i28701# - follow-up of #i22341#
4513 : // <mnLastTopOfLine> has also been adjusted.
4514 106 : pFly->AddLastTopOfLineY( lDiff );
4515 : }
4516 : // #i26945# - re-registration at
4517 : // page frame of anchor frame, if table frame isn't
4518 : // a follow table and table frame isn't in its
4519 : // rebuild of last line.
4520 150 : const SwTabFrm* pTabFrm = pLay->FindTabFrm();
4521 : // #115759#
4522 : // - save: check, if table frame is found.
4523 300 : if ( pTabFrm &&
4524 150 : !( pTabFrm->IsFollow() &&
4525 300 : pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
4526 150 : pFly->IsFlyFreeFrm() )
4527 : {
4528 148 : SwPageFrm* pPageFrm = pFly->GetPageFrm();
4529 148 : SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
4530 148 : if ( pPageFrm != pPageOfAnchor )
4531 : {
4532 0 : pFly->InvalidatePos();
4533 0 : if ( pPageFrm )
4534 0 : pPageFrm->MoveFly( pFly, pPageOfAnchor );
4535 : else
4536 0 : pPageOfAnchor->AppendFlyToPage( pFly );
4537 : }
4538 : }
4539 : // OD 2004-05-11 #i28701# - Because of the introduction
4540 : // of new positionings and alignments (e.g. aligned at
4541 : // page area, but anchored at-character), the position
4542 : // of the Writer fly frame has to be invalidated.
4543 150 : pFly->InvalidatePos();
4544 :
4545 : // #i26945# - follow-up of #i3317#
4546 : // No arrangement of lowers, if Writer fly frame isn't
4547 : // moved
4548 156 : if ( bDirectMove &&
4549 : ::lcl_ArrangeLowers( pFly,
4550 12 : (pFly->*fnRect->fnGetPrtTop)(),
4551 18 : bInva ) )
4552 : {
4553 6 : pFly->SetCompletePaint();
4554 : }
4555 : }
4556 350 : else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
4557 : {
4558 : // #i26945#
4559 350 : const SwTabFrm* pTabFrm = pLay->FindTabFrm();
4560 700 : if ( pTabFrm &&
4561 350 : !( pTabFrm->IsFollow() &&
4562 700 : pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
4563 324 : (pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
4564 : != FLY_AS_CHAR))
4565 : {
4566 110 : SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
4567 110 : SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
4568 110 : if ( pPageFrm != pPageOfAnchor )
4569 : {
4570 22 : pAnchoredObj->InvalidateObjPos();
4571 22 : if ( pPageFrm )
4572 : {
4573 22 : pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
4574 : }
4575 22 : pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
4576 : }
4577 : }
4578 : // #i28701# - adjust last character
4579 : // rectangle and last top of line.
4580 350 : pAnchoredObj->AddLastCharY( lDiff );
4581 350 : pAnchoredObj->AddLastTopOfLineY( lDiff );
4582 : // #i52904# - re-introduce direct move
4583 : // of drawing objects
4584 : const bool bDirectMove =
4585 620 : static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
4586 614 : bVertPosDepOnAnchor &&
4587 614 : !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
4588 350 : if ( bDirectMove )
4589 : {
4590 264 : SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
4591 264 : if ( bVert )
4592 : {
4593 0 : pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
4594 : }
4595 : else
4596 : {
4597 264 : pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
4598 : }
4599 : // #i58280#
4600 264 : pAnchoredObj->InvalidateObjRectWithSpaces();
4601 : }
4602 350 : pAnchoredObj->InvalidateObjPos();
4603 : }
4604 : else
4605 : {
4606 : OSL_FAIL( "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
4607 : }
4608 : }
4609 : }
4610 : }
4611 : // Columns and cells are ordered horizontal, not vertical
4612 144906 : if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
4613 : lYStart = (*fnRect->fnYInc)( lYStart,
4614 122566 : (pFrm->Frm().*fnRect->fnGetHeight)() );
4615 :
4616 : // Nowadays, the content inside a cell can flow into the follow table.
4617 : // Thus, the cell may only grow up to the end of the environment.
4618 : // So the content may have grown, but the cell could not grow.
4619 : // Therefore we have to trigger a formatting for the frames, which do
4620 : // not fit into the cell anymore:
4621 : SwTwips nDistanceToUpperPrtBottom =
4622 144906 : (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
4623 : // #i56146# - Revise fix of issue #i26945#
4624 : // do *not* consider content inside fly frames, if it's an undersized paragraph.
4625 : // #i26945# - consider content inside fly frames
4626 161234 : if ( nDistanceToUpperPrtBottom < 0 &&
4627 16174 : ( ( pFrm->IsInFly() &&
4628 0 : ( !pFrm->IsTxtFrm() ||
4629 16174 : !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
4630 16174 : pFrm->IsInSplitTableRow() ) )
4631 : {
4632 154 : pFrm->InvalidatePos();
4633 : }
4634 :
4635 144906 : pFrm = pFrm->GetNext();
4636 : }
4637 73794 : return bRet;
4638 : }
4639 :
4640 40624 : void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
4641 : {
4642 : OSL_ENSURE( pAttrs, "CellFrm::Format, pAttrs ist 0." );
4643 40624 : const SwTabFrm* pTab = FindTabFrm();
4644 40624 : SWRECTFN( pTab )
4645 :
4646 40624 : if ( !mbValidPrtArea )
4647 : {
4648 40624 : mbValidPrtArea = true;
4649 :
4650 : //Adjust position.
4651 40624 : if ( Lower() )
4652 : {
4653 : SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
4654 : // #i29550#
4655 40292 : if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm() )
4656 : {
4657 40098 : const SvxBoxItem& rBoxItem = pAttrs->GetBox();
4658 40098 : nLeftSpace = rBoxItem.GetDistance( BOX_LINE_LEFT );
4659 40098 : nRightSpace = rBoxItem.GetDistance( BOX_LINE_RIGHT );
4660 40098 : nTopSpace = ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
4661 40098 : nBottomSpace = ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
4662 : }
4663 : else
4664 : {
4665 : // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
4666 194 : nLeftSpace = pAttrs->CalcLeft( this );
4667 194 : nRightSpace = pAttrs->CalcRight( this );
4668 194 : nTopSpace = pAttrs->CalcTop();
4669 194 : nBottomSpace = pAttrs->CalcBottom();
4670 : }
4671 40292 : (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
4672 40292 : (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
4673 : }
4674 : }
4675 : // #i26945#
4676 40624 : long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
4677 40502 : ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
4678 81126 : 0;
4679 40624 : if ( !mbValidSize )
4680 : {
4681 29462 : mbValidSize = true;
4682 :
4683 : //The VarSize of the CellFrms is always the width.
4684 : //The width is not variable though, it is defined by the format.
4685 : //This predefined value however does not necessary match the actual
4686 : //width. The width is calculated based on the attribute, the value in
4687 : //the attribute matches the desired value of the TabFrm. Changes which
4688 : //were done there are taken into account here proportionately.
4689 : //If the cell doesn't have a neighbour anymore, it does not take the
4690 : //attribute into account and takes the rest of the upper instead.
4691 : SwTwips nWidth;
4692 29462 : if ( GetNext() )
4693 : {
4694 18070 : const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
4695 18070 : nWidth = pAttrs->GetSize().Width();
4696 :
4697 : OSL_ENSURE( nWish, "Table without width?" );
4698 : OSL_ENSURE( nWidth <= nWish, "Width of cell larger than table." );
4699 : OSL_ENSURE( nWidth > 0, "Box without width" );
4700 :
4701 18070 : const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
4702 18070 : if ( nWish != nPrtWidth )
4703 : {
4704 : // Avoid rounding problems, at least for the new table model
4705 6270 : if ( pTab->GetTable()->IsNewModel() )
4706 : {
4707 : // 1. sum of widths of cells up to this cell (in model)
4708 6270 : const SwTableLine* pTabLine = GetTabBox()->GetUpper();
4709 6270 : const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
4710 6270 : const SwTableBox* pTmpBox = 0;
4711 :
4712 6270 : SwTwips nSumWidth = 0;
4713 6270 : size_t i = 0;
4714 12430 : do
4715 : {
4716 12430 : pTmpBox = rBoxes[ i++ ];
4717 12430 : nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
4718 : }
4719 12430 : while ( pTmpBox != GetTabBox() );
4720 :
4721 : // 2. calculate actual width of cells up to this one
4722 6270 : double nTmpWidth = nSumWidth;
4723 6270 : nTmpWidth *= nPrtWidth;
4724 6270 : nTmpWidth /= nWish;
4725 6270 : nWidth = (SwTwips)nTmpWidth;
4726 :
4727 : // 3. calculate frame widths of cells up to this one:
4728 6270 : const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
4729 6270 : SwTwips nSumFrameWidths = 0;
4730 18700 : while ( pTmpCell != this )
4731 : {
4732 6160 : nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
4733 6160 : pTmpCell = pTmpCell->GetNext();
4734 : }
4735 :
4736 6270 : nWidth = nWidth - nSumFrameWidths;
4737 : }
4738 : else
4739 : {
4740 : // #i12092# use double instead of long,
4741 : // otherwise this could lead to overflows
4742 0 : double nTmpWidth = nWidth;
4743 0 : nTmpWidth *= nPrtWidth;
4744 0 : nTmpWidth /= nWish;
4745 0 : nWidth = (SwTwips)nTmpWidth;
4746 : }
4747 : }
4748 : }
4749 : else
4750 : {
4751 : OSL_ENSURE( pAttrs->GetSize().Width() > 0, "Box without width" );
4752 11392 : nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
4753 11392 : SwFrm *pPre = GetUpper()->Lower();
4754 35974 : while ( pPre != this )
4755 : {
4756 13190 : nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
4757 13190 : pPre = pPre->GetNext();
4758 : }
4759 : }
4760 29462 : const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
4761 29462 : if( IsNeighbourFrm() && IsRightToLeft() )
4762 0 : (Frm().*fnRect->fnSubLeft)( nDiff );
4763 : else
4764 29462 : (Frm().*fnRect->fnAddRight)( nDiff );
4765 29462 : (Prt().*fnRect->fnAddRight)( nDiff );
4766 :
4767 : //Adjust the height, it's defined through the content and the border.
4768 29462 : const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
4769 29462 : if ( nDiffHeight )
4770 : {
4771 13518 : if ( nDiffHeight > 0 )
4772 : {
4773 : //Validate again if no growth happened. Invalidation is done
4774 : //through AdjustCells of the row.
4775 76 : if ( !Grow( nDiffHeight ) )
4776 76 : mbValidSize = mbValidPrtArea = true;
4777 : }
4778 : else
4779 : {
4780 : //Only keep invalidated if shrinking was done; this can be
4781 : //dismissed because all adjoined cells have to be the same size.
4782 13442 : if ( !Shrink( -nDiffHeight ) )
4783 13442 : mbValidSize = mbValidPrtArea = true;
4784 : }
4785 : }
4786 : }
4787 40624 : const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
4788 :
4789 40624 : if ( !Lower() )
4790 332 : return;
4791 :
4792 : // From now on, all operations are related to the table cell.
4793 40292 : SWREFRESHFN( this )
4794 :
4795 40292 : SwPageFrm* pPg = 0;
4796 131720 : if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
4797 : // #158225# no vertical alignment of covered cells
4798 77660 : !IsCoveredCell() &&
4799 : // #116532# Do not consider vertical alignment in grid mode
4800 24904 : !(pPg = FindPageFrm())->HasGrid() )
4801 : {
4802 12452 : if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
4803 : {
4804 : // OSL_ENSURE(for HTML-import!
4805 : OSL_ENSURE( false, "VAlign to cell without content" );
4806 0 : return;
4807 : }
4808 12452 : bool bVertDir = true;
4809 : // #i43913# - no vertical alignment, if wrapping
4810 : // style influence is considered on object positioning and
4811 : // an object is anchored inside the cell.
4812 12452 : const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
4813 : //No alignment if border with flow overlaps the cell.
4814 12452 : if ( pPg->GetSortedObjs() )
4815 : {
4816 6360 : SwRect aRect( Prt() ); aRect += Frm().Pos();
4817 19590 : for ( size_t i = 0; i < pPg->GetSortedObjs()->size(); ++i )
4818 : {
4819 13254 : const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
4820 13254 : SwRect aTmp( pAnchoredObj->GetObjRect() );
4821 13254 : if ( aTmp.IsOver( aRect ) )
4822 : {
4823 522 : const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
4824 522 : const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
4825 :
4826 522 : if ( SURROUND_THROUGHT != rSur.GetSurround() )
4827 : {
4828 : // frames, which the cell is a lower of, aren't relevant
4829 260 : if ( pAnchoredObj->ISA(SwFlyFrm) )
4830 : {
4831 : const SwFlyFrm *pFly =
4832 260 : static_cast<const SwFlyFrm*>(pAnchoredObj);
4833 260 : if ( pFly->IsAnLower( this ) )
4834 472 : continue;
4835 : }
4836 :
4837 24 : const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
4838 : // #i43913#
4839 : // #i52904# - no vertical alignment,
4840 : // if object, anchored inside cell, has temporarly
4841 : // consider its wrapping style on object positioning.
4842 : // #i58806# - no vertical alignment
4843 : // if object does not follow the text flow.
4844 24 : if ( bConsiderWrapOnObjPos ||
4845 0 : !IsAnLower( pAnch ) ||
4846 24 : pAnchoredObj->IsTmpConsiderWrapInfluence() ||
4847 0 : !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
4848 : {
4849 24 : bVertDir = false;
4850 48 : break;
4851 : }
4852 : }
4853 : }
4854 : }
4855 : }
4856 :
4857 12452 : long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
4858 18988 : if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
4859 6536 : (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
4860 : {
4861 8738 : long nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
4862 8738 : if ( nDiff >= 0 )
4863 : {
4864 8738 : long lTopOfst = 0;
4865 8738 : if ( bVertDir )
4866 : {
4867 8726 : switch ( rOri.GetVertOrient() )
4868 : {
4869 5330 : case text::VertOrientation::CENTER: lTopOfst = nDiff / 2; break;
4870 828 : case text::VertOrientation::BOTTOM: lTopOfst = nDiff; break;
4871 2568 : default: break;
4872 : };
4873 : }
4874 : long nTmp = (*fnRect->fnYInc)(
4875 8738 : (this->*fnRect->fnGetPrtTop)(), lTopOfst );
4876 8738 : if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
4877 7856 : SetCompletePaint();
4878 : }
4879 : }
4880 : }
4881 : else
4882 : {
4883 : //Was an old alignment taken into account?
4884 27840 : if ( Lower()->IsCntntFrm() )
4885 : {
4886 27506 : const long lYStart = (this->*fnRect->fnGetPrtTop)();
4887 27506 : lcl_ArrangeLowers( this, lYStart, true );
4888 : }
4889 : }
4890 : }
4891 :
4892 400 : void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
4893 : {
4894 400 : bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
4895 400 : const SfxPoolItem *pItem = 0;
4896 :
4897 400 : if( bAttrSetChg )
4898 400 : ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, false, &pItem);
4899 0 : else if (pNew && RES_VERT_ORIENT == pNew->Which())
4900 0 : pItem = pNew;
4901 :
4902 400 : if ( pItem )
4903 : {
4904 0 : bool bInva = true;
4905 0 : if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
4906 : // OD 04.11.2003 #112910#
4907 0 : Lower() && Lower()->IsCntntFrm() )
4908 : {
4909 0 : SWRECTFN( this )
4910 0 : const long lYStart = (this->*fnRect->fnGetPrtTop)();
4911 0 : bInva = lcl_ArrangeLowers( this, lYStart, false );
4912 : }
4913 0 : if ( bInva )
4914 : {
4915 0 : SetCompletePaint();
4916 0 : InvalidatePrt();
4917 : }
4918 : }
4919 :
4920 1200 : if ( ( bAttrSetChg && pNew &&
4921 1200 : SfxItemState::SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, false ) ) ||
4922 400 : ( pNew && RES_PROTECT == pNew->Which()) )
4923 : {
4924 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
4925 0 : if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
4926 0 : pSh->Imp()->InvalidateAccessibleEditableState( true, this );
4927 : }
4928 :
4929 800 : if ( bAttrSetChg && pNew &&
4930 400 : SfxItemState::SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, false, &pItem ) )
4931 : {
4932 0 : SetDerivedVert( false );
4933 0 : CheckDirChange();
4934 : }
4935 :
4936 : // #i29550#
4937 800 : if ( bAttrSetChg && pNew &&
4938 400 : SfxItemState::SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, false, &pItem ) )
4939 : {
4940 126 : SwFrm* pTmpUpper = GetUpper();
4941 252 : while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
4942 0 : pTmpUpper = pTmpUpper->GetUpper();
4943 :
4944 126 : SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
4945 126 : if ( pTabFrm->IsCollapsingBorders() )
4946 : {
4947 : // Invalidate lowers of this and next row:
4948 112 : lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
4949 112 : pTmpUpper = pTmpUpper->GetNext();
4950 112 : if ( pTmpUpper )
4951 64 : lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
4952 : else
4953 48 : pTabFrm->InvalidatePrt();
4954 : }
4955 : }
4956 :
4957 400 : SwLayoutFrm::Modify( pOld, pNew );
4958 400 : }
4959 :
4960 805417 : long SwCellFrm::GetLayoutRowSpan() const
4961 : {
4962 805417 : long nRet = GetTabBox()->getRowSpan();
4963 805417 : if ( nRet < 1 )
4964 : {
4965 1732 : const SwFrm* pRow = GetUpper();
4966 1732 : const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
4967 :
4968 1732 : if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
4969 0 : nRet = -nRet;
4970 : }
4971 805417 : return nRet;
4972 : }
4973 :
4974 : // #i103961#
4975 0 : void SwCellFrm::Cut()
4976 : {
4977 : // notification for accessibility
4978 : {
4979 0 : SwRootFrm *pRootFrm = getRootFrm();
4980 0 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
4981 : {
4982 0 : SwViewShell* pVSh = pRootFrm->GetCurrShell();
4983 0 : if ( pVSh && pVSh->Imp() )
4984 : {
4985 0 : pVSh->Imp()->DisposeAccessibleFrm( this );
4986 : }
4987 : }
4988 : }
4989 :
4990 0 : SwLayoutFrm::Cut();
4991 0 : }
4992 :
4993 : // Helper functions for repeated headlines:
4994 :
4995 5424 : bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
4996 : {
4997 : OSL_ENSURE( IsAnLower( &rFrm ) && rFrm.IsInTab(),
4998 : "SwTabFrm::IsInHeadline called for frame not lower of table" );
4999 :
5000 5424 : const SwFrm* pTmp = &rFrm;
5001 18328 : while ( !pTmp->GetUpper()->IsTabFrm() )
5002 7480 : pTmp = pTmp->GetUpper();
5003 :
5004 5424 : return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
5005 : }
5006 :
5007 : /*
5008 : * If this is a master table, we can may assume, that there are at least
5009 : * nRepeat lines in the table.
5010 : * If this is a follow table, there are intermediate states for the table
5011 : * layout, e.g., during deletion of rows, which makes it necessary to find
5012 : * the first non-headline row by evaluating the headline flag at the row frame.
5013 : */
5014 27402 : SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
5015 : {
5016 27402 : SwRowFrm* pRet = (SwRowFrm*)Lower();
5017 27402 : if ( pRet )
5018 : {
5019 27242 : if ( IsFollow() )
5020 : {
5021 54622 : while ( pRet && pRet->IsRepeatedHeadline() )
5022 542 : pRet = (SwRowFrm*)pRet->GetNext();
5023 : }
5024 : else
5025 : {
5026 202 : sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5027 442 : while ( pRet && nRepeat > 0 )
5028 : {
5029 38 : pRet = (SwRowFrm*)pRet->GetNext();
5030 38 : --nRepeat;
5031 : }
5032 : }
5033 : }
5034 :
5035 27402 : return (SwRowFrm*)pRet;
5036 : }
5037 :
5038 26890 : bool SwTable::IsHeadline( const SwTableLine& rLine ) const
5039 : {
5040 27466 : for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
5041 696 : if ( GetTabLines()[ i ] == &rLine )
5042 120 : return true;
5043 :
5044 26770 : return false;
5045 : }
5046 :
5047 2 : bool SwTabFrm::IsLayoutSplitAllowed() const
5048 : {
5049 2 : return GetFmt()->GetLayoutSplit().GetValue();
5050 : }
5051 :
5052 : // #i29550#
5053 :
5054 8374 : sal_uInt16 SwTabFrm::GetBottomLineSize() const
5055 : {
5056 : OSL_ENSURE( IsCollapsingBorders(),
5057 : "BottomLineSize only required for collapsing borders" );
5058 :
5059 : OSL_ENSURE( Lower(), "Warning! Trying to prevent a crash, please inform FME" );
5060 :
5061 8374 : const SwFrm* pTmp = GetLastLower();
5062 :
5063 : // #124755# Try to make code robust
5064 8374 : if ( !pTmp ) return 0;
5065 :
5066 8374 : return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
5067 : }
5068 :
5069 275466 : bool SwTabFrm::IsCollapsingBorders() const
5070 : {
5071 275466 : return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
5072 : }
5073 :
5074 : /// Local helper function to calculate height of first text row
5075 22 : static SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
5076 : {
5077 : // Find corresponding split line in master table
5078 22 : const SwTabFrm* pTab = rSourceLine.FindTabFrm();
5079 22 : SWRECTFN( pTab )
5080 22 : const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
5081 :
5082 : // 1. Case: rSourceLine is a follow flow line.
5083 : // In this case we have to return the minimum of the heights
5084 : // of the first lines in rSourceLine.
5085 :
5086 : // 2. Case: rSourceLine is not a follow flow line.
5087 : // In this case we have to return the maximum of the heights
5088 : // of the first lines in rSourceLine.
5089 22 : bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
5090 22 : SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
5091 :
5092 88 : while ( pCurrSourceCell )
5093 : {
5094 : // NEW TABLES
5095 : // Skip cells which are not responsible for the height of
5096 : // the follow flow line:
5097 44 : if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
5098 : {
5099 0 : pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5100 0 : continue;
5101 : }
5102 :
5103 44 : const SwFrm *pTmp = pCurrSourceCell->Lower();
5104 44 : if ( pTmp )
5105 : {
5106 42 : SwTwips nTmpHeight = USHRT_MAX;
5107 : // #i32456# Consider lower row frames
5108 42 : if ( pTmp->IsRowFrm() )
5109 : {
5110 0 : const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
5111 0 : nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
5112 : }
5113 42 : if ( pTmp->IsTabFrm() )
5114 : {
5115 0 : nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
5116 : }
5117 42 : else if ( pTmp->IsTxtFrm() )
5118 : {
5119 42 : SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
5120 42 : pTxtFrm->GetFormatted();
5121 42 : nTmpHeight = pTxtFrm->FirstLineHeight();
5122 : }
5123 :
5124 42 : if ( USHRT_MAX != nTmpHeight )
5125 : {
5126 42 : const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
5127 42 : if ( pPrevCell )
5128 : {
5129 : // If we are in a split row, there may be some space
5130 : // left in the cell frame of the master row.
5131 : // We look for the minimum of all first line heights;
5132 2 : SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
5133 2 : const SwFrm* pFrm = pPrevCell->Lower();
5134 2 : const SwFrm* pLast = pFrm;
5135 6 : while ( pFrm )
5136 : {
5137 2 : nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
5138 2 : pLast = pFrm;
5139 2 : pFrm = pFrm->GetNext();
5140 : }
5141 :
5142 : // #i26831#, #i26520#
5143 : // The additional lower space of the current last.
5144 : // #115759# - do *not* consider the
5145 : // additional lower space for 'master' text frames
5146 4 : if ( pLast && pLast->IsFlowFrm() &&
5147 4 : ( !pLast->IsTxtFrm() ||
5148 2 : !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
5149 : {
5150 0 : nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
5151 : }
5152 : // Don't forget the upper space and lower space,
5153 : // #115759# - do *not* consider the upper
5154 : // and the lower space for follow text frames.
5155 4 : if ( pTmp->IsFlowFrm() &&
5156 4 : ( !pTmp->IsTxtFrm() ||
5157 2 : !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
5158 : {
5159 0 : nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
5160 0 : nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5161 : }
5162 : // #115759# - consider additional lower
5163 : // space of <pTmp>, if contains only one line.
5164 : // In this case it would be the new last text frame, which
5165 : // would have no follow and thus would add this space.
5166 4 : if ( pTmp->IsTxtFrm() &&
5167 : const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
5168 2 : ->GetLineCount( COMPLETE_STRING ) == 1 )
5169 : {
5170 : nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
5171 2 : ->CalcAddLowerSpaceAsLastInTableCell();
5172 : }
5173 2 : if ( nReal > 0 )
5174 0 : nTmpHeight -= nReal;
5175 : }
5176 : else
5177 : {
5178 : // pFirstRow is not a FollowFlowRow. In this case,
5179 : // we look for the maximum of all first line heights:
5180 40 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
5181 40 : const SwBorderAttrs &rAttrs = *aAccess.Get();
5182 40 : nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
5183 : // #i26250#
5184 : // Don't forget the upper space and lower space,
5185 40 : if ( pTmp->IsFlowFrm() )
5186 : {
5187 40 : nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
5188 40 : nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5189 40 : }
5190 : }
5191 : }
5192 :
5193 42 : if ( bIsInFollowFlowLine )
5194 : {
5195 : // minimum
5196 2 : if ( nTmpHeight < nHeight )
5197 2 : nHeight = nTmpHeight;
5198 : }
5199 : else
5200 : {
5201 : // maximum
5202 40 : if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
5203 30 : nHeight = nTmpHeight;
5204 : }
5205 : }
5206 :
5207 44 : pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5208 : }
5209 :
5210 22 : return ( LONG_MAX == nHeight ) ? 0 : nHeight;
5211 : }
5212 :
5213 : /// Function to calculate height of first text row
5214 1454 : SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
5215 : {
5216 1454 : SWRECTFN( this )
5217 :
5218 1454 : const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
5219 :
5220 1454 : if ( bDontSplit )
5221 : {
5222 : // Table is not allowed to split: Take the whole height, that's all
5223 0 : return (Frm().*fnRect->fnGetHeight)();
5224 : }
5225 :
5226 1454 : SwTwips nTmpHeight = 0;
5227 :
5228 1454 : SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
5229 : OSL_ENSURE( !IsFollow() || pFirstRow, "FollowTable without Lower" );
5230 :
5231 : // NEW TABLES
5232 1454 : if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
5233 0 : pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5234 :
5235 : // Calculate the height of the headlines:
5236 1454 : const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5237 1454 : SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
5238 :
5239 : // Calculate the height of the keeping lines
5240 : // (headlines + following keeping lines):
5241 1454 : SwTwips nKeepHeight = nRepeatHeight;
5242 1454 : if ( GetFmt()->GetDoc()->GetDocumentSettingManager().get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
5243 : {
5244 1350 : sal_uInt16 nKeepRows = nRepeat;
5245 :
5246 : // Check how many rows want to keep together
5247 2700 : while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
5248 : {
5249 0 : ++nKeepRows;
5250 0 : pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5251 : }
5252 :
5253 1350 : if ( nKeepRows > nRepeat )
5254 0 : nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
5255 : }
5256 :
5257 : // For master tables, the height of the headlines + the height of the
5258 : // keeping lines (if any) has to be considered. For follow tables, we
5259 : // only consider the height of the keeping rows without the repeated lines:
5260 1454 : if ( !IsFollow() )
5261 : {
5262 10 : nTmpHeight = nKeepHeight;
5263 : }
5264 : else
5265 : {
5266 1444 : nTmpHeight = nKeepHeight - nRepeatHeight;
5267 : }
5268 :
5269 : // pFirstRow row is the first non-heading row.
5270 : // nTmpHeight is the height of the heading row if we are a follow.
5271 1454 : if ( pFirstRow )
5272 : {
5273 1454 : const bool bSplittable = pFirstRow->IsRowSplitAllowed();
5274 1454 : const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
5275 :
5276 1454 : if ( !bSplittable )
5277 : {
5278 : // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
5279 : // actually is determined by a lower cell with rowspan = -1. In this case we should not
5280 : // just return the height of the first line. Basically we need to get the height of the
5281 : // line as it would be on the last page. Since this is quite complicated to calculate,
5282 : // we olny calculate the height of the first line.
5283 8 : if ( pFirstRow->GetPrev() &&
5284 0 : static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
5285 : {
5286 : // Calculate maximum height of all cells with rowspan = 1:
5287 0 : SwTwips nMaxHeight = 0;
5288 0 : const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
5289 0 : while ( pLower2 )
5290 : {
5291 0 : if ( 1 == pLower2->GetTabBox()->getRowSpan() )
5292 : {
5293 0 : const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, true );
5294 0 : nMaxHeight = std::max( nCellHeight, nMaxHeight );
5295 : }
5296 0 : pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
5297 : }
5298 0 : nTmpHeight += nMaxHeight;
5299 : }
5300 : else
5301 : {
5302 8 : nTmpHeight += nFirstLineHeight;
5303 : }
5304 : }
5305 :
5306 : // #118411#
5307 : // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
5308 : // a formatting of the row frame (via the GetFormatted()). We don't
5309 : // want this formatting if the row does not have a height.
5310 1446 : else if ( 0 != nFirstLineHeight )
5311 : {
5312 22 : const bool bOldJoinLock = IsJoinLocked();
5313 22 : ((SwTabFrm*)this)->LockJoin();
5314 22 : const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
5315 :
5316 : // Consider minimum row height:
5317 22 : const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
5318 22 : const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
5319 22 : rSz.GetHeight() : 0;
5320 :
5321 22 : nTmpHeight += std::max( nHeightOfFirstContentLine, nMinRowHeight );
5322 :
5323 22 : if ( !bOldJoinLock )
5324 22 : ((SwTabFrm*)this)->UnlockJoin();
5325 : }
5326 : }
5327 :
5328 1454 : return nTmpHeight;
5329 : }
5330 :
5331 : // Some more functions for covered/covering cells. This way inclusion of
5332 : // SwCellFrm can be avoided
5333 :
5334 137600 : bool SwFrm::IsLeaveUpperAllowed() const
5335 : {
5336 137600 : const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5337 137600 : return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
5338 : }
5339 :
5340 136192 : bool SwFrm::IsCoveredCell() const
5341 : {
5342 136192 : const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5343 136192 : return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
5344 : }
5345 :
5346 6870 : bool SwFrm::IsInCoveredCell() const
5347 : {
5348 6870 : bool bRet = false;
5349 :
5350 6870 : const SwFrm* pThis = this;
5351 25830 : while ( pThis && !pThis->IsCellFrm() )
5352 12090 : pThis = pThis->GetUpper();
5353 :
5354 6870 : if ( pThis )
5355 702 : bRet = pThis->IsCoveredCell();
5356 :
5357 6870 : return bRet;
5358 270 : }
5359 :
5360 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|