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