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