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