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