1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tabfrm.cxx,v $
10 * $Revision: 1.105.58.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include "pagefrm.hxx"
34 #include "rootfrm.hxx"
39 #include "viewimp.hxx"
40 #include "swtable.hxx"
41 #include "dflyobj.hxx"
43 #include "frmtool.hxx"
45 #include "dcontact.hxx"
46 #include "viewopt.hxx"
48 #include "dbg_lay.hxx"
51 #include <svtools/itemiter.hxx>
53 #include <svx/keepitem.hxx>
54 #include <svx/ulspitem.hxx>
55 #include <svx/lrspitem.hxx>
56 #include <svx/brshitem.hxx>
57 // --> collapsing borders FME 2005-05-27 #i29550#
58 #include <svx/boxitem.hxx>
60 #ifndef _OUTDEV_HXX //autogen
61 #include <vcl/outdev.hxx>
63 #include <fmtlsplt.hxx>
64 #include <fmtrowsplt.hxx>
65 #include <fmtsrnd.hxx>
66 #include <fmtornt.hxx>
67 #include <fmtpdsc.hxx>
68 #include <fmtfsize.hxx>
69 #include <swtblfmt.hxx>
74 #include "cellfrm.hxx"
75 #include "flyfrms.hxx"
76 #include "txtfrm.hxx" //HasFtn()
77 #include "htmltbl.hxx"
78 #include "sectfrm.hxx" //SwSectionFrm
79 // OD 30.09.2003 #i18732#
80 #include <fmtfollowtextflow.hxx>
81 // --> OD 2004-06-28 #i28701#
82 #include <sortedobjs.hxx>
83 #include <objectformatter.hxx>
85 // --> OD 2004-10-05 #i26945#
86 #include <layouter.hxx>
89 extern void AppendObjs( const SwSpzFrmFmts
*pTbl
, ULONG nIndex
,
90 SwFrm
*pFrm
, SwPageFrm
*pPage
);
92 using namespace ::com::sun::star
;
95 /*************************************************************************
97 |* SwTabFrm::SwTabFrm(), ~SwTabFrm()
99 |* Ersterstellung MA 09. Mar. 93
100 |* Letzte Aenderung MA 30. May. 96
102 |*************************************************************************/
103 SwTabFrm::SwTabFrm( SwTable
&rTab
):
104 SwLayoutFrm( rTab
.GetFrmFmt() ),
105 SwFlowFrm( (SwFrm
&)*this ),
108 bComplete
= bCalcLowers
= bONECalcLowers
= bLowersFormatted
= bLockBackMove
=
109 bResizeHTMLTable
= bHasFollowFlowLine
= bIsRebuildLastLine
=
110 bRestrictTableGrowth
= bRemoveFollowFlowLinePending
= FALSE
;
111 // --> OD 2004-10-04 #i26945#
112 bConsiderObjsForMinCellHeight
= TRUE
;
115 bFixSize
= FALSE
; //Nicht nochmal auf die Importfilter hereinfallen.
118 //Gleich die Zeilen erzeugen und einfuegen.
119 const SwTableLines
&rLines
= rTab
.GetTabLines();
121 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
123 SwRowFrm
*pNew
= new SwRowFrm( *rLines
[i
] );
126 pNew
->InsertBehind( this, pTmpPrev
);
132 ASSERT( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
135 SwTabFrm::SwTabFrm( SwTabFrm
&rTab
) :
136 SwLayoutFrm( rTab
.GetFmt() ),
137 SwFlowFrm( (SwFrm
&)*this ),
138 pTable( rTab
.GetTable() )
141 bLockJoin
= bComplete
= bONECalcLowers
= bCalcLowers
= bLowersFormatted
= bLockBackMove
=
142 bResizeHTMLTable
= bHasFollowFlowLine
= bIsRebuildLastLine
=
143 bRestrictTableGrowth
= bRemoveFollowFlowLinePending
= FALSE
;
144 // --> OD 2004-10-04 #i26945#
145 bConsiderObjsForMinCellHeight
= TRUE
;
148 bFixSize
= FALSE
; //Nicht nochmal auf die Importfilter hereinfallen.
151 SetFollow( rTab
.GetFollow() );
152 rTab
.SetFollow( this );
155 extern const SwTable
*pColumnCacheLastTable
;
156 extern const SwTabFrm
*pColumnCacheLastTabFrm
;
157 extern const SwFrm
*pColumnCacheLastCellFrm
;
158 extern const SwTable
*pRowCacheLastTable
;
159 extern const SwTabFrm
*pRowCacheLastTabFrm
;
160 extern const SwFrm
*pRowCacheLastCellFrm
;
162 SwTabFrm::~SwTabFrm()
164 // There is some terrible code in fetab.cxx, that
165 // makes use of these global pointers. Obviously
166 // this code did not consider that a TabFrm can be
168 if ( this == pColumnCacheLastTabFrm
)
170 pColumnCacheLastTable
= NULL
;
171 pColumnCacheLastTabFrm
= NULL
;
172 pColumnCacheLastCellFrm
= NULL
;
173 pRowCacheLastTable
= NULL
;
174 pRowCacheLastTabFrm
= NULL
;
175 pRowCacheLastCellFrm
= NULL
;
179 /*************************************************************************
181 |* SwTabFrm::JoinAndDelFollows()
183 |* Ersterstellung MA 30. May. 96
184 |* Letzte Aenderung MA 30. May. 96
186 |*************************************************************************/
187 void SwTabFrm::JoinAndDelFollows()
189 SwTabFrm
*pFoll
= GetFollow();
190 if ( pFoll
->HasFollow() )
191 pFoll
->JoinAndDelFollows();
193 SetFollow( pFoll
->GetFollow() );
197 /*************************************************************************
199 |* SwTabFrm::RegistFlys()
201 |* Ersterstellung MA 08. Jul. 93
202 |* Letzte Aenderung MA 27. Jan. 99
204 |*************************************************************************/
205 void SwTabFrm::RegistFlys()
207 ASSERT( Lower() && Lower()->IsRowFrm(), "Keine Zeilen." );
209 SwPageFrm
*pPage
= FindPageFrm();
212 SwRowFrm
*pRow
= (SwRowFrm
*)Lower();
215 pRow
->RegistFlys( pPage
);
216 pRow
= (SwRowFrm
*)pRow
->GetNext();
221 /*************************************************************************
223 |*************************************************************************/
224 void MA_FASTCALL
SwInvalidateAll( SwFrm
*pFrm
, long nBottom
);
225 bool MA_FASTCALL
lcl_CalcLowers( SwLayoutFrm
*pLay
, const SwLayoutFrm
* pDontLeave
,
226 long nBottom
, bool bSkipRowSpanCells
);
227 void MA_FASTCALL
lcl_RecalcRow( SwRowFrm
& rRow
, long nBottom
);
228 BOOL
lcl_ArrangeLowers( SwLayoutFrm
*pLay
, long lYStart
, BOOL bInva
);
229 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
230 // that only row and cell frames are formatted.
231 BOOL MA_FASTCALL
lcl_InnerCalcLayout( SwFrm
*pFrm
,
233 bool _bOnlyRowsAndCells
= false );
235 // OD 2004-02-18 #106629# - correct type of 1st parameter
236 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
237 // control, if floating screen objects have to be considered for the minimal
239 SwTwips MA_FASTCALL
lcl_CalcMinRowHeight( const SwRowFrm
*pRow
,
240 const BOOL _bConsiderObjs
);
242 SwTwips
lcl_CalcTopAndBottomMargin( const SwLayoutFrm
&, const SwBorderAttrs
& );
244 /*************************************************************************
245 |* START: local helper functions for repeated headlines
246 |*************************************************************************/
248 SwTwips
lcl_GetHeightOfRows( const SwFrm
* pStart
, long nCount
)
250 if ( !nCount
|| !pStart
)
255 while ( pStart
&& nCount
> 0 )
257 nRet
+= (pStart
->Frm().*fnRect
->fnGetHeight
)();
258 pStart
= pStart
->GetNext();
265 /*************************************************************************
266 |* END: local helper functions for repeated headlines
267 |*************************************************************************/
269 /*************************************************************************
270 |* START: local helper functions for splitting row frames
271 |*************************************************************************/
274 // Local helper function to insert a new follow flow line
276 SwRowFrm
* lcl_InsertNewFollowFlowLine( SwTabFrm
& rTab
, const SwFrm
& rTmpRow
, bool bRowSpanLine
)
278 ASSERT( rTmpRow
.IsRowFrm(), "No row frame to copy for FollowFlowLine" )
279 const SwRowFrm
& rRow
= (SwRowFrm
&)rTmpRow
;
281 rTab
.SetFollowFlowLine( TRUE
);
282 SwRowFrm
*pFollowFlowLine
= new SwRowFrm(*rRow
.GetTabLine(), false );
283 pFollowFlowLine
->SetRowSpanLine( bRowSpanLine
);
284 SwFrm
* pFirstRow
= rTab
.GetFollow()->GetFirstNonHeadlineRow();
285 pFollowFlowLine
->InsertBefore( rTab
.GetFollow(), pFirstRow
);
286 return pFollowFlowLine
;
289 // --> OD 2004-11-05 #i26945# - local helper function to invalidate all lower
290 // objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
291 // additionally the objects are moved 'out of range'.
292 void lcl_InvalidateLowerObjs( SwLayoutFrm
& _rLayoutFrm
,
293 const bool _bMoveObjsOutOfRange
= false,
294 SwPageFrm
* _pPageFrm
= 0L )
296 // determine page frame, if needed
299 _pPageFrm
= _rLayoutFrm
.FindPageFrm();
301 "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
308 // loop on lower frames
309 SwFrm
* pLowerFrm
= _rLayoutFrm
.Lower();
312 if ( pLowerFrm
->IsLayoutFrm() )
314 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm
*>(pLowerFrm
)),
315 _bMoveObjsOutOfRange
, _pPageFrm
);
317 if ( pLowerFrm
->GetDrawObjs() )
319 for ( USHORT i
= 0; i
< pLowerFrm
->GetDrawObjs()->Count(); ++i
)
321 SwAnchoredObject
* pAnchoredObj
= (*pLowerFrm
->GetDrawObjs())[i
];
323 // invalidate position of anchored object
324 pAnchoredObj
->SetTmpConsiderWrapInfluence( false );
325 pAnchoredObj
->SetConsiderForTextWrap( false );
326 pAnchoredObj
->UnlockPosition();
327 pAnchoredObj
->InvalidateObjPos();
329 // move anchored object 'out of range'
330 if ( _bMoveObjsOutOfRange
)
332 // indicate, that positioning is progress to avoid
333 // modification of the anchored object resp. its attributes
334 // due to the movement
335 SwObjPositioningInProgress
aObjPosInProgress( *pAnchoredObj
);
336 pAnchoredObj
->SetObjLeft( _pPageFrm
->Frm().Right() );
337 // --> OD 2004-11-24 #115759# - reset character rectangle,
338 // top of line and relative position in order to assure,
339 // that anchored object is correctly positioned.
340 pAnchoredObj
->ClearCharRectAndTopOfLine();
341 pAnchoredObj
->SetCurrRelPos( Point( 0, 0 ) );
342 if ( pAnchoredObj
->GetFrmFmt().GetAnchor().GetAnchorId()
345 pAnchoredObj
->AnchorFrm()
346 ->Prepare( PREP_FLY_ATTR_CHG
,
347 &(pAnchoredObj
->GetFrmFmt()) );
350 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
352 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
353 pFly
->GetVirtDrawObj()->SetRectsDirty();
354 pFly
->GetVirtDrawObj()->SetChanged();
358 // If anchored object is a fly frame, invalidate its lower objects
359 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
361 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
362 ::lcl_InvalidateLowerObjs( *pFly
, _bMoveObjsOutOfRange
, _pPageFrm
);
366 pLowerFrm
= pLowerFrm
->GetNext();
371 // Local helper function to shrink all lowers of rRow to 0 height
373 void lcl_ShrinkCellsAndAllContent( SwRowFrm
& rRow
)
375 SwCellFrm
* pCurrMasterCell
= static_cast<SwCellFrm
*>(rRow
.Lower());
376 SWRECTFN( pCurrMasterCell
)
378 while ( pCurrMasterCell
)
381 SwCellFrm
& rToAdjust
= pCurrMasterCell
->GetTabBox()->getRowSpan() < 1 ?
382 const_cast<SwCellFrm
&>(pCurrMasterCell
->FindStartEndOfRowSpanCell( true, true )) :
385 // --> OD 2004-10-04 #i26945#
386 // all lowers should have the correct position
387 lcl_ArrangeLowers( &rToAdjust
,
388 (rToAdjust
.*fnRect
->fnGetPrtTop
)(),
391 // TODO: Optimize number of frames which are set to 0 height
392 // we have to start with the last lower frame, otherwise
393 // the shrink will not shrink the current cell
394 SwFrm
* pTmp
= rToAdjust
.GetLastLower();
396 if ( pTmp
&& pTmp
->IsRowFrm() )
398 SwRowFrm
* pTmpRow
= (SwRowFrm
*)pTmp
;
399 lcl_ShrinkCellsAndAllContent( *pTmpRow
);
403 // TODO: Optimize number of frames which are set to 0 height
406 // the frames have to be shrunk
407 if ( pTmp
&& pTmp
->IsTabFrm() )
409 SwRowFrm
* pTmpRow
= (SwRowFrm
*)((SwTabFrm
*)pTmp
)->Lower();
412 lcl_ShrinkCellsAndAllContent( *pTmpRow
);
413 pTmpRow
= (SwRowFrm
*)pTmpRow
->GetNext();
418 pTmp
->Shrink( (pTmp
->Frm().*fnRect
->fnGetHeight
)() );
419 (pTmp
->Prt().*fnRect
->fnSetTop
)( 0 );
420 (pTmp
->Prt().*fnRect
->fnSetHeight
)( 0 );
423 pTmp
= pTmp
->GetPrev();
426 // all lowers should have the correct position
427 lcl_ArrangeLowers( &rToAdjust
,
428 (rToAdjust
.*fnRect
->fnGetPrtTop
)(),
432 pCurrMasterCell
= static_cast<SwCellFrm
*>(pCurrMasterCell
->GetNext());
437 // Local helper function to move the content from rSourceLine to rDestLine
438 // The content is inserted behind the last content in the corresponding
439 // cell in rDestLine.
441 void lcl_MoveRowContent( SwRowFrm
& rSourceLine
, SwRowFrm
& rDestLine
)
443 SwCellFrm
* pCurrDestCell
= (SwCellFrm
*)rDestLine
.Lower();
444 SwCellFrm
* pCurrSourceCell
= (SwCellFrm
*)rSourceLine
.Lower();
446 // Move content of follow cells into master cells
447 while ( pCurrSourceCell
)
449 if ( pCurrSourceCell
->Lower() && pCurrSourceCell
->Lower()->IsRowFrm() )
451 SwRowFrm
* pTmpSourceRow
= (SwRowFrm
*)pCurrSourceCell
->Lower();
452 while ( pTmpSourceRow
)
454 // --> FME 2006-01-10 #125926# Achtung! It is possible,
455 // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
456 // cannot be found. In this case, we have to move the complete
458 SwRowFrm
* pTmpDestRow
= (SwRowFrm
*)pCurrDestCell
->Lower();
461 if ( pTmpSourceRow
->IsFollowFlowRow() && pTmpDestRow
)
463 // move content from follow flow row to pTmpDestRow:
464 while ( pTmpDestRow
->GetNext() )
465 pTmpDestRow
= (SwRowFrm
*)pTmpDestRow
->GetNext();
467 ASSERT( pTmpDestRow
->GetFollowRow() == pTmpSourceRow
, "Knoten in der Tabelle" )
469 lcl_MoveRowContent( *pTmpSourceRow
, *pTmpDestRow
);
470 pTmpDestRow
->SetFollowRow( pTmpSourceRow
->GetFollowRow() );
471 pTmpSourceRow
->Remove();
472 delete pTmpSourceRow
;
476 // move complete row:
477 pTmpSourceRow
->Remove();
478 pTmpSourceRow
->InsertBefore( pCurrDestCell
, 0 );
481 pTmpSourceRow
= (SwRowFrm
*)pCurrSourceCell
->Lower();
486 SwFrm
*pTmp
= ::SaveCntnt( (SwCellFrm
*)pCurrSourceCell
);
490 SwCellFrm
* pDestCell
= static_cast<SwCellFrm
*>(pCurrDestCell
);
491 if ( pDestCell
->GetTabBox()->getRowSpan() < 1 )
492 pDestCell
= & const_cast<SwCellFrm
&>(pDestCell
->FindStartEndOfRowSpanCell( true, true ));
495 SwFrm
* pFrm
= pDestCell
->GetLastLower();
496 ::RestoreCntnt( pTmp
, pDestCell
, pFrm
, true );
499 pCurrDestCell
= (SwCellFrm
*)pCurrDestCell
->GetNext();
500 pCurrSourceCell
= (SwCellFrm
*)pCurrSourceCell
->GetNext();
505 // Local helper function to move all footnotes in rRowFrm from
506 // the footnote boss of rSource to the footnote boss of rDest.
508 void lcl_MoveFootnotes( SwTabFrm
& rSource
, SwTabFrm
& rDest
, SwLayoutFrm
& rRowFrm
)
510 if ( 0 != rSource
.GetFmt()->GetDoc()->GetFtnIdxs().Count() )
512 SwFtnBossFrm
* pOldBoss
= rSource
.FindFtnBossFrm( TRUE
);
513 SwFtnBossFrm
* pNewBoss
= rDest
.FindFtnBossFrm( TRUE
);
514 rRowFrm
.MoveLowerFtns( 0, pOldBoss
, pNewBoss
, TRUE
);
519 // Local helper function to handle nested table cells before the split process
521 void lcl_PreprocessRowsInCells( SwTabFrm
& rTab
, SwRowFrm
& rLastLine
,
522 SwRowFrm
& rFollowFlowLine
, SwTwips nRemain
)
524 SwCellFrm
* pCurrLastLineCell
= (SwCellFrm
*)rLastLine
.Lower();
525 SwCellFrm
* pCurrFollowFlowLineCell
= (SwCellFrm
*)rFollowFlowLine
.Lower();
527 SWRECTFN( pCurrLastLineCell
)
530 // Move content of follow cells into master cells
532 while ( pCurrLastLineCell
)
534 if ( pCurrLastLineCell
->Lower() && pCurrLastLineCell
->Lower()->IsRowFrm() )
536 SwTwips nTmpCut
= nRemain
;
537 SwRowFrm
* pTmpLastLineRow
= (SwRowFrm
*)pCurrLastLineCell
->Lower();
539 // --> OD 2004-10-04 #i26945#
540 SwTwips nCurrentHeight
=
541 lcl_CalcMinRowHeight( pTmpLastLineRow
,
542 rTab
.IsConsiderObjsForMinCellHeight() );
544 while ( pTmpLastLineRow
&& pTmpLastLineRow
->GetNext() && nTmpCut
> nCurrentHeight
)
546 nTmpCut
-= nCurrentHeight
;
547 pTmpLastLineRow
= (SwRowFrm
*)pTmpLastLineRow
->GetNext();
548 // --> OD 2004-10-04 #i26945#
550 lcl_CalcMinRowHeight( pTmpLastLineRow
,
551 rTab
.IsConsiderObjsForMinCellHeight() );
556 // pTmpLastLineRow does not fit to the line or it is the last line
558 if ( pTmpLastLineRow
)
561 // Check if we can move pTmpLastLineRow to the follow table,
562 // or if we have to split the line:
564 SwFrm
* pCell
= pTmpLastLineRow
->Lower();
565 bool bTableLayoutToComplex
= false;
569 // We have to take into account:
570 // 1. The fixed height of the row
571 // 2. The borders of the cells inside the row
572 // 3. The minimum height of the row
574 if ( pTmpLastLineRow
->HasFixSize() )
575 nMinHeight
= (pTmpLastLineRow
->Frm().*fnRect
->fnGetHeight
)();
580 if ( ((SwCellFrm
*)pCell
)->Lower() &&
581 ((SwCellFrm
*)pCell
)->Lower()->IsRowFrm() )
583 bTableLayoutToComplex
= true;
587 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pCell
);
588 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
589 nMinHeight
= Max( nMinHeight
, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm
*)pCell
, rAttrs
) );
590 pCell
= pCell
->GetNext();
593 const SwFmtFrmSize
&rSz
= pTmpLastLineRow
->GetFmt()->GetFrmSize();
594 if ( rSz
.GetHeightSizeType() == ATT_MIN_SIZE
)
595 nMinHeight
= Max( nMinHeight
, rSz
.GetHeight() );
600 // The line completely fits into the master table.
601 // Nevertheless, we build a follow (otherwise painting problems
605 // The line has to be split, the minimum height still fits into
606 // the master table, and the table structure is not to complex.
608 if ( nTmpCut
> nCurrentHeight
||
609 ( pTmpLastLineRow
->IsRowSplitAllowed() &&
610 !bTableLayoutToComplex
&& nMinHeight
< nTmpCut
) )
612 // The line has to be split:
613 SwRowFrm
* pNewRow
= new SwRowFrm( *pTmpLastLineRow
->GetTabLine(), false );
614 pNewRow
->SetFollowFlowRow( true );
615 pNewRow
->SetFollowRow( pTmpLastLineRow
->GetFollowRow() );
616 pTmpLastLineRow
->SetFollowRow( pNewRow
);
617 pNewRow
->InsertBehind( pCurrFollowFlowLineCell
, 0 );
618 pTmpLastLineRow
= (SwRowFrm
*)pTmpLastLineRow
->GetNext();
622 // The following lines have to be moved:
624 while ( pTmpLastLineRow
)
626 SwRowFrm
* pTmp
= (SwRowFrm
*)pTmpLastLineRow
->GetNext();
627 lcl_MoveFootnotes( rTab
, *rTab
.GetFollow(), *pTmpLastLineRow
);
628 pTmpLastLineRow
->Remove();
629 pTmpLastLineRow
->InsertBefore( pCurrFollowFlowLineCell
, 0 );
630 pTmpLastLineRow
->Shrink( ( pTmpLastLineRow
->Frm().*fnRect
->fnGetHeight
)() );
631 pCurrFollowFlowLineCell
->Grow( ( pTmpLastLineRow
->Frm().*fnRect
->fnGetHeight
)() );
632 pTmpLastLineRow
= pTmp
;
637 pCurrLastLineCell
= (SwCellFrm
*)pCurrLastLineCell
->GetNext();
638 pCurrFollowFlowLineCell
= (SwCellFrm
*)pCurrFollowFlowLineCell
->GetNext();
643 // Local helper function to handle nested table cells after the split process
645 void lcl_PostprocessRowsInCells( SwTabFrm
& rTab
, SwRowFrm
& rLastLine
)
647 SwCellFrm
* pCurrMasterCell
= (SwCellFrm
*)rLastLine
.Lower();
648 while ( pCurrMasterCell
)
650 if ( pCurrMasterCell
->Lower() &&
651 pCurrMasterCell
->Lower()->IsRowFrm() )
653 SwRowFrm
* pRowFrm
= static_cast<SwRowFrm
*>(pCurrMasterCell
->GetLastLower());
655 if ( NULL
!= pRowFrm
->GetPrev() && !pRowFrm
->ContainsCntnt() )
657 ASSERT( pRowFrm
->GetFollowRow(), "Deleting row frame without follow" )
659 // The footnotes have to be moved:
660 lcl_MoveFootnotes( rTab
, *rTab
.GetFollow(), *pRowFrm
);
662 SwRowFrm
* pFollowRow
= pRowFrm
->GetFollowRow();
663 pRowFrm
->Paste( pFollowRow
->GetUpper(), pFollowRow
);
664 pRowFrm
->SetFollowRow( pFollowRow
->GetFollowRow() );
665 lcl_MoveRowContent( *pFollowRow
, *pRowFrm
);
668 ::SwInvalidateAll( pCurrMasterCell
, LONG_MAX
);
672 pCurrMasterCell
= (SwCellFrm
*)pCurrMasterCell
->GetNext();
677 // Local helper function to re-calculate the split line.
679 inline void TableSplitRecalcLock( SwFlowFrm
*pTab
) { pTab
->LockJoin(); }
680 inline void TableSplitRecalcUnlock( SwFlowFrm
*pTab
) { pTab
->UnlockJoin(); }
682 bool lcl_RecalcSplitLine( SwRowFrm
& rLastLine
, SwRowFrm
& rFollowLine
,
683 SwTwips nRemainingSpaceForLastRow
)
687 SwTabFrm
& rTab
= (SwTabFrm
&)*rLastLine
.GetUpper();
690 // If there are nested cells in rLastLine, the recalculation of the last
691 // line needs some preprocessing.
693 lcl_PreprocessRowsInCells( rTab
, rLastLine
, rFollowLine
, nRemainingSpaceForLastRow
);
696 // Here the recalculation process starts:
698 rTab
.SetRebuildLastLine( TRUE
);
699 // --> OD 2004-10-15 #i26945#
700 rTab
.SetDoesObjsFit( TRUE
);
702 SWRECTFN( rTab
.GetUpper() )
704 // --> OD 2004-11-05 #i26945# - invalidate and move floating screen
705 // objects 'out of range'
706 ::lcl_InvalidateLowerObjs( rLastLine
, true );
709 // manipulate row and cell sizes
711 // --> OD 2004-10-04 #i26945# - Do *not* consider floating screen objects
712 // for the minimal cell height.
713 rTab
.SetConsiderObjsForMinCellHeight( FALSE
);
714 ::lcl_ShrinkCellsAndAllContent( rLastLine
);
715 rTab
.SetConsiderObjsForMinCellHeight( TRUE
);
719 // invalidate last line
721 ::SwInvalidateAll( &rLastLine
, LONG_MAX
);
724 // Lock this tab frame and its follow
726 bool bUnlockMaster
= false;
727 bool bUnlockFollow
= false;
728 SwTabFrm
* pMaster
= rTab
.IsFollow() ? (SwTabFrm
*)rTab
.FindMaster() : 0;
729 if ( pMaster
&& !pMaster
->IsJoinLocked() )
731 bUnlockMaster
= true;
732 ::TableSplitRecalcLock( pMaster
);
734 if ( !rTab
.GetFollow()->IsJoinLocked() )
736 bUnlockFollow
= true;
737 ::TableSplitRecalcLock( rTab
.GetFollow() );
741 // TODO: e.g., for i71806: What shall we do if the table already
742 // exceeds its upper? I think we have to adjust the heights of the
743 // table, rLastRow and all cells in rLastRow
745 /*SwTwips nDistanceToUpperPrtBottom =
746 (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
748 if ( nDistanceToUpperPrtBottom < 0 )
750 (rTab.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
751 (rTab.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
753 (rLastLine.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
754 (rLastLine.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
756 SwFrm* pTmpCell = rLastLine.Lower();
759 (pTmpCell->Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
760 (pTmpCell->Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
762 pTmpCell = pTmpCell->GetNext();
767 // Do the recalculation
769 lcl_RecalcRow( rLastLine
, LONG_MAX
);
770 // --> OD 2004-11-23 #115759# - force a format of the last line in order to
771 // get the correct height.
772 rLastLine
.InvalidateSize();
777 // Unlock this tab frame and its follow
780 ::TableSplitRecalcUnlock( rTab
.GetFollow() );
782 ::TableSplitRecalcUnlock( pMaster
);
785 // If there are nested cells in rLastLine, the recalculation of the last
786 // line needs some postprocessing.
788 lcl_PostprocessRowsInCells( rTab
, rLastLine
);
791 // Do a couple of checks on the current situation.
793 // If we are not happy with the current situation we return false.
794 // This will start a new try to split the table, this time we do not
795 // try to split the table rows.
799 // 1. Check if table fits to its upper.
800 // --> OD 2004-10-15 #i26945# - include check, if objects fit
802 const SwTwips nDistanceToUpperPrtBottom
=
803 (rTab
.Frm().*fnRect
->fnBottomDist
)( (rTab
.GetUpper()->*fnRect
->fnGetPrtBottom
)());
804 if ( nDistanceToUpperPrtBottom
< 0 || !rTab
.DoesObjsFit() )
809 // 2. Check if each cell in the last line has at least one content frame.
811 // Note: a FollowFlowRow may contains empty cells!
815 if ( !rLastLine
.IsInFollowFlowRow() )
817 SwCellFrm
* pCurrMasterCell
= (SwCellFrm
*)rLastLine
.Lower();
818 while ( pCurrMasterCell
)
820 if ( !pCurrMasterCell
->ContainsCntnt() && pCurrMasterCell
->GetTabBox()->getRowSpan() >= 1 )
825 pCurrMasterCell
= (SwCellFrm
*)pCurrMasterCell
->GetNext();
831 // 3. Check if last line does not contain any content:
835 if ( !rLastLine
.ContainsCntnt() )
843 // 4. Check if follow flow line does not contain content:
847 if ( !rFollowLine
.IsRowSpanLine() && !rFollowLine
.ContainsCntnt() )
856 // Everything looks fine. Splitting seems to be successful. We invalidate
857 // rFollowLine to force a new formatting.
859 ::SwInvalidateAll( &rFollowLine
, LONG_MAX
);
864 // Splitting the table row gave us an unexpected result.
865 // Everything has to be prepared for a second try to split
866 // the table, this time without splitting the row.
868 ::SwInvalidateAll( &rLastLine
, LONG_MAX
);
871 rTab
.SetRebuildLastLine( FALSE
);
872 // --> OD 2004-10-15 #i26945#
873 rTab
.SetDoesObjsFit( TRUE
);
880 // Sets the correct height for all spanned cells
882 void lcl_AdjustRowSpanCells( SwRowFrm
* pRow
)
885 SwCellFrm
* pCellFrm
= static_cast<SwCellFrm
*>(pRow
->GetLower());
888 const long nLayoutRowSpan
= pCellFrm
->GetLayoutRowSpan();
889 if ( nLayoutRowSpan
> 1 )
891 // calculate height of cell:
892 const long nNewCellHeight
= lcl_GetHeightOfRows( pRow
, nLayoutRowSpan
);
893 const long nDiff
= nNewCellHeight
- (pCellFrm
->Frm().*fnRect
->fnGetHeight
)();
895 (pCellFrm
->Frm().*fnRect
->fnAddBottom
)( nDiff
);
898 pCellFrm
= static_cast<SwCellFrm
*>(pCellFrm
->GetNext());
903 // Returns the maximum layout row span of the row
904 // Looking for the next row that contains no covered cells:
905 long lcl_GetMaximumLayoutRowSpan( const SwRowFrm
& rRow
)
909 const SwRowFrm
* pCurrentRowFrm
= static_cast<const SwRowFrm
*>(rRow
.GetNext());
910 bool bNextRow
= false;
912 while ( pCurrentRowFrm
)
914 // if there is any covered cell, we proceed to the next row frame
915 const SwCellFrm
* pLower
= static_cast<const SwCellFrm
*>( pCurrentRowFrm
->Lower());
918 if ( pLower
->GetTabBox()->getRowSpan() < 0 )
924 pLower
= static_cast<const SwCellFrm
*>(pLower
->GetNext());
926 pCurrentRowFrm
= bNextRow
?
927 static_cast<const SwRowFrm
*>(pCurrentRowFrm
->GetNext() ) :
934 /*************************************************************************
935 |* END: local helper functions for splitting row frames
936 |*************************************************************************/
939 // Function to remove the FollowFlowLine of rTab.
940 // The content of the FollowFlowLine is moved to the associated line in the
943 bool SwTabFrm::RemoveFollowFlowLine()
945 // find FollowFlowLine
946 SwRowFrm
* pFollowFlowLine
= static_cast<SwRowFrm
*>(GetFollow()->GetFirstNonHeadlineRow());
948 // find last row in master
949 SwFrm
* pLastLine
= GetLastLower();
951 ASSERT( HasFollowFlowLine() &&
953 pLastLine
, "There should be a flowline in the follow" )
955 // We have to reset the flag here, because lcl_MoveRowContent
956 // calls a GrowFrm(), which has a different bahavior if
958 SetFollowFlowLine( FALSE
);
960 // --> FME 2007-07-19 #140081# Make code robust.
961 if ( !pFollowFlowLine
|| !pLastLine
)
965 lcl_MoveRowContent( *pFollowFlowLine
, *(SwRowFrm
*)pLastLine
);
968 // If a row span follow flow line is removed, we want to move the whole span
971 long nRowsToMove
= lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine
);
973 if ( nRowsToMove
> 1 )
976 SwFrm
* pRow
= pFollowFlowLine
->GetNext();
977 SwFrm
* pInsertBehind
= GetLastLower();
979 while ( pRow
&& nRowsToMove
-- > 1 )
981 SwFrm
* pNxt
= pRow
->GetNext();
982 nGrow
+= (pRow
->Frm().*fnRect
->fnGetHeight
)();
984 // The footnotes have to be moved:
985 lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm
&)*pRow
);
988 pRow
->InsertBehind( this, pInsertBehind
);
989 pRow
->_InvalidateAll();
990 pRow
->CheckDirChange();
991 pInsertBehind
= pRow
;
995 SwFrm
* pFirstRow
= Lower();
998 lcl_AdjustRowSpanCells( static_cast<SwRowFrm
*>(pFirstRow
) );
999 pFirstRow
= pFirstRow
->GetNext();
1003 GetFollow()->Shrink( nGrow
);
1006 bool bJoin
= !pFollowFlowLine
->GetNext();
1007 pFollowFlowLine
->Cut();
1008 delete pFollowFlowLine
;
1013 // --> OD 2004-10-04 #i26945# - Floating screen objects are no longer searched.
1014 bool lcl_FindSectionsInRow( const SwRowFrm
& rRow
)
1017 SwCellFrm
* pLower
= (SwCellFrm
*)rRow
.Lower();
1020 if ( pLower
->IsVertical() != rRow
.IsVertical() )
1023 SwFrm
* pTmpFrm
= pLower
->Lower();
1026 if ( pTmpFrm
->IsRowFrm() )
1028 bRet
= lcl_FindSectionsInRow( *(SwRowFrm
*)pTmpFrm
);
1032 // --> OD 2004-10-04 #i26945# - search only for sections
1033 bRet
= pTmpFrm
->IsSctFrm();
1039 pTmpFrm
= pTmpFrm
->GetNext();
1042 pLower
= (SwCellFrm
*)pLower
->GetNext();
1047 /*************************************************************************
1049 |* SwTabFrm::Split(), Join()
1051 |* Ersterstellung MA 03. Jun. 93
1052 |* Letzte Aenderung MA 03. Sep. 96
1054 |*************************************************************************/
1055 bool SwTabFrm::Split( const SwTwips nCutPos
, bool bTryToSplit
, bool bTableRowKeep
)
1060 //ASSERT( bVert ? nCutPos >= Frm().Left() &&
1061 // nCutPos <= Frm().Left() + Frm().Width() :
1062 // nCutPos >= Frm().Top() && nCutPos <= Frm().Bottom(), "SplitLine out of table." );
1064 // --> OD 2004-10-14 #i26745# - format row and cell frames of table
1066 this->Lower()->_InvalidatePos();
1067 // --> OD 2005-03-30 #i43913# - correction:
1068 // call method <lcl_InnerCalcLayout> with first lower.
1069 lcl_InnerCalcLayout( this->Lower(), LONG_MAX
, true );
1074 //Um die Positionen der Zellen mit der CutPos zu vergleichen muessen sie
1075 //ausgehend von der Tabelle nacheinander berechnet werden. Sie koennen
1076 //wg. Positionsaenderungen der Tabelle durchaus ungueltig sein.
1077 SwRowFrm
*pRow
= static_cast<SwRowFrm
*>(Lower());
1081 const USHORT nRepeat
= GetTable()->GetRowsToRepeat();
1082 USHORT nRowCount
= 0; // pRow currently points to the first row
1084 SwTwips nRemainingSpaceForLastRow
=
1085 (*fnRect
->fnYDiff
)( nCutPos
, (Frm().*fnRect
->fnGetTop
)() );
1086 nRemainingSpaceForLastRow
-= (this->*fnRect
->fnGetTopMargin
)();
1089 // Make pRow point to the line that does not fit anymore:
1091 while( pRow
->GetNext() &&
1092 nRemainingSpaceForLastRow
>= ( (pRow
->Frm().*fnRect
->fnGetHeight
)() +
1093 (IsCollapsingBorders() ?
1094 pRow
->GetBottomLineSize() :
1097 if( bTryToSplit
|| !pRow
->IsRowSpanLine() ||
1098 0 != (pRow
->Frm().*fnRect
->fnGetHeight
)() )
1100 nRemainingSpaceForLastRow
-= (pRow
->Frm().*fnRect
->fnGetHeight
)();
1101 pRow
= static_cast<SwRowFrm
*>(pRow
->GetNext());
1105 // bSplitRowAllowed: Row may be split according to its attributes.
1106 // bTryToSplit: Row will never be split if bTryToSplit = false.
1107 // This can either be passed as a parameter, indicating
1108 // that we are currently doing the second try to split the
1109 // table, or it will be set to falseunder certain
1110 // conditions that are not suitable for splitting
1113 bool bSplitRowAllowed
= pRow
->IsRowSplitAllowed();
1115 // --> FME 2004-06-03 #i29438#
1116 // --> OD 2004-10-04 #i26945# - Floating screen objects no longer forbid
1117 // a splitting of the table row.
1118 // Special DoNotSplit case 1:
1119 // Search for sections inside pRow:
1121 if ( lcl_FindSectionsInRow( *pRow
) )
1123 bTryToSplit
= false;
1127 // --> FME 2004-06-07 #i29771#
1128 // To avoid loops, we do some checks before actually trying to split
1129 // the row. Maybe we should keep the next row in this table.
1130 // Note: This is only done if we are at the beginning of our upper
1131 bool bKeepNextRow
= false;
1132 if ( nRowCount
< nRepeat
)
1135 // First case: One of the repeated headline does not fit to the page anymore.
1136 // At least one more non-heading row has to stay in this table in
1137 // order to avoid loops:
1139 ASSERT( !GetIndPrev(), "Table is supposed to be at beginning" )
1140 bKeepNextRow
= true;
1142 else if ( !GetIndPrev() && nRepeat
== nRowCount
)
1145 // Second case: The first non-headline row does not fit to the page.
1146 // If it is not allowed to be split, or it contains a sub-row that
1147 // is not allowed to be split, we keep the row in this table:
1149 if ( bTryToSplit
&& bSplitRowAllowed
)
1151 // Check if there are (first) rows inside this row,
1152 // which are not allowed to be split.
1153 SwCellFrm
* pLowerCell
= pRow
? (SwCellFrm
*)pRow
->Lower() : 0;
1154 while ( pLowerCell
)
1156 if ( pLowerCell
->Lower() && pLowerCell
->Lower()->IsRowFrm() )
1158 const SwRowFrm
* pLowerRow
= (SwRowFrm
*)pLowerCell
->Lower();
1159 if ( !pLowerRow
->IsRowSplitAllowed() &&
1160 (pLowerRow
->Frm().*fnRect
->fnGetHeight
)() >
1161 nRemainingSpaceForLastRow
)
1163 bKeepNextRow
= true;
1167 pLowerCell
= (SwCellFrm
*)pLowerCell
->GetNext();
1171 bKeepNextRow
= true;
1175 // Better keep the next row in this table:
1179 pRow
= GetFirstNonHeadlineRow();
1180 if( pRow
&& pRow
->IsRowSpanLine() && 0 == (pRow
->Frm().*fnRect
->fnGetHeight
)() )
1181 pRow
= static_cast<SwRowFrm
*>(pRow
->GetNext());
1184 pRow
= static_cast<SwRowFrm
*>(pRow
->GetNext());
1190 // No more row to split or to move to follow table:
1196 // We try to split the row if
1197 // - the attributes of the row are set accordingly and
1198 // - we are allowed to do so
1199 // - the it should not keep with the next row
1201 bSplitRowAllowed
= bSplitRowAllowed
&& bTryToSplit
&&
1203 !pRow
->ShouldRowKeepWithNext() );
1205 // Adjust pRow according to the keep-with-next attribute:
1206 if ( !bSplitRowAllowed
&& bTableRowKeep
)
1208 SwRowFrm
* pTmpRow
= static_cast<SwRowFrm
*>(pRow
->GetPrev());
1209 SwRowFrm
* pOldRow
= pRow
;
1210 while ( pTmpRow
&& pTmpRow
->ShouldRowKeepWithNext() &&
1211 nRowCount
> nRepeat
)
1215 pTmpRow
= static_cast<SwRowFrm
*>(pTmpRow
->GetPrev());
1219 if ( nRowCount
== nRepeat
&& !GetIndPrev())
1226 // If we do not indent to split pRow, we check if we are
1227 // allowed to move pRow to a follow. Otherwise we return
1228 // false, indicating an error
1230 if ( !bSplitRowAllowed
)
1232 SwRowFrm
* pFirstNonHeadlineRow
= GetFirstNonHeadlineRow();
1233 if ( pRow
== pFirstNonHeadlineRow
)
1236 // --> OD 2008-10-21 #i91764#
1237 // Ignore row span lines
1238 SwRowFrm
* pTmpRow
= pFirstNonHeadlineRow
;
1239 while ( pTmpRow
&& pTmpRow
->IsRowSpanLine() )
1241 pTmpRow
= static_cast<SwRowFrm
*>(pTmpRow
->GetNext());
1243 if ( !pTmpRow
|| pRow
== pTmpRow
)
1251 // Build follow table if not already done:
1257 pFoll
= GetFollow();
1263 pFoll
= new SwTabFrm( *this );
1266 // We give the follow table an initial width.
1268 (pFoll
->Frm().*fnRect
->fnAddWidth
)( (Frm().*fnRect
->fnGetWidth
)() );
1269 (pFoll
->Prt().*fnRect
->fnAddWidth
)( (Prt().*fnRect
->fnGetWidth
)() );
1270 (pFoll
->Frm().*fnRect
->fnSetLeft
)( (Frm().*fnRect
->fnGetLeft
)() );
1273 // Insert the new follow table
1275 pFoll
->InsertBehind( GetUpper(), this );
1278 // Repeat the headlines.
1280 for ( nRowCount
= 0; nRowCount
< nRepeat
; ++nRowCount
)
1282 // Insert new headlines:
1283 bDontCreateObjects
= TRUE
; //frmtool
1284 SwRowFrm
* pHeadline
= new SwRowFrm(
1285 *GetTable()->GetTabLines()[ nRowCount
] );
1286 pHeadline
->SetRepeatedHeadline( true );
1287 bDontCreateObjects
= FALSE
;
1288 pHeadline
->InsertBefore( pFoll
, 0 );
1290 SwPageFrm
*pPage
= pHeadline
->FindPageFrm();
1291 const SwSpzFrmFmts
*pTbl
= GetFmt()->GetDoc()->GetSpzFrmFmts();
1295 SwCntntFrm
* pFrm
= pHeadline
->ContainsCntnt();
1298 nIndex
= pFrm
->GetNode()->GetIndex();
1299 AppendObjs( pTbl
, nIndex
, pFrm
, pPage
);
1300 pFrm
= pFrm
->GetNextCntntFrm();
1301 if( !pHeadline
->IsAnLower( pFrm
) )
1308 SwRowFrm
* pLastRow
= 0; // will point to the last remaining line in master
1309 SwRowFrm
* pFollowRow
= 0; // points to either the follow flow line of the
1310 // first regular line in the follow
1312 if ( bSplitRowAllowed
)
1314 // If the row that does not fit anymore is allowed
1315 // to be split, the next row has to be moved to the follow table.
1317 pRow
= static_cast<SwRowFrm
*>(pRow
->GetNext());
1319 // new follow flow line for last row of master table
1320 pFollowRow
= lcl_InsertNewFollowFlowLine( *this, *pLastRow
, false );
1327 // check if we will break a row span by moving pFollowRow to the follow:
1328 // In this case we want to reformat the last line.
1329 const SwCellFrm
* pCellFrm
= static_cast<const SwCellFrm
*>(pFollowRow
->GetLower());
1332 if ( pCellFrm
->GetTabBox()->getRowSpan() < 1 )
1334 pLastRow
= static_cast<SwRowFrm
*>(pRow
->GetPrev());
1338 pCellFrm
= static_cast<const SwCellFrm
*>(pCellFrm
->GetNext());
1341 // new follow flow line for last row of master table
1343 pFollowRow
= lcl_InsertNewFollowFlowLine( *this, *pLastRow
, true );
1348 //Optimierung beim neuen Follow braucht's kein Paste und dann kann
1349 //das Optimierte Insert verwendet werden (nur dann treten gluecklicher weise
1350 //auch groessere Mengen von Rows auf).
1354 SwFrm
* pInsertBehind
= pFoll
->GetLastLower();
1358 pNxt
= pRow
->GetNext();
1359 nRet
+= (pRow
->Frm().*fnRect
->fnGetHeight
)();
1360 // The footnotes do not have to be moved, this is done in the
1361 // MoveFwd of the follow table!!!
1363 pRow
->InsertBehind( pFoll
, pInsertBehind
);
1364 pRow
->_InvalidateAll();
1365 pInsertBehind
= pRow
;
1366 pRow
= static_cast<SwRowFrm
*>(pNxt
);
1372 SwFrm
* pPasteBefore
= HasFollowFlowLine() ?
1373 pFollowRow
->GetNext() :
1374 pFoll
->GetFirstNonHeadlineRow();
1378 pNxt
= pRow
->GetNext();
1379 nRet
+= (pRow
->Frm().*fnRect
->fnGetHeight
)();
1381 // The footnotes have to be moved:
1382 lcl_MoveFootnotes( *this, *GetFollow(), *pRow
);
1385 pRow
->Paste( pFoll
, pPasteBefore
);
1387 pRow
->CheckDirChange();
1388 pRow
= static_cast<SwRowFrm
*>(pNxt
);
1394 // we rebuild the last line to assure that it will be fully formatted
1397 // recalculate the split line
1398 bRet
= lcl_RecalcSplitLine( *pLastRow
, *pFollowRow
, nRemainingSpaceForLastRow
);
1401 // check if each cell in the row span line has a good height
1402 if ( bRet
&& pFollowRow
->IsRowSpanLine() )
1403 lcl_AdjustRowSpanCells( pFollowRow
);
1405 // We The RowSplitLine stuff did not work. In this case we conceal the split error:
1406 if ( !bRet
&& !bSplitRowAllowed
)
1415 bool SwTabFrm::Join()
1417 ASSERT( !HasFollowFlowLine(), "Joining follow flow line" )
1419 SwTabFrm
*pFoll
= GetFollow();
1420 SwTwips nHeight
= 0; //Gesamthoehe der eingefuegten Zeilen als Return.
1422 if ( !pFoll
->IsJoinLocked() )
1425 pFoll
->Cut(); //Erst ausschneiden um unuetze Benachrichtigungen zu
1428 SwFrm
*pRow
= pFoll
->GetFirstNonHeadlineRow(),
1431 SwFrm
* pPrv
= GetLastLower();
1435 pNxt
= pRow
->GetNext();
1436 nHeight
+= (pRow
->Frm().*fnRect
->fnGetHeight
)();
1438 pRow
->_InvalidateAll();
1439 pRow
->InsertBehind( this, pPrv
);
1440 pRow
->CheckDirChange();
1445 SetFollow( pFoll
->GetFollow() );
1446 SetFollowFlowLine( pFoll
->HasFollowFlowLine() );
1455 /*************************************************************************
1457 |* SwTabFrm::MakeAll()
1459 |* Ersterstellung MA 09. Mar. 93
1460 |* Letzte Aenderung MA 10. Apr. 97
1462 |*************************************************************************/
1463 void MA_FASTCALL
SwInvalidatePositions( SwFrm
*pFrm
, long nBottom
)
1465 // LONG_MAX == nBottom means we have to calculate all
1466 BOOL bAll
= LONG_MAX
== nBottom
;
1469 { pFrm
->_InvalidatePos();
1470 pFrm
->_InvalidateSize();
1471 if( pFrm
->IsLayoutFrm() )
1473 if ( ((SwLayoutFrm
*)pFrm
)->Lower() )
1475 ::SwInvalidatePositions( ((SwLayoutFrm
*)pFrm
)->Lower(), nBottom
);
1476 // --> OD 2004-11-05 #i26945#
1477 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm
*>(pFrm
)) );
1482 pFrm
->Prepare( PREP_ADJUST_FRM
);
1483 pFrm
= pFrm
->GetNext();
1486 (*fnRect
->fnYDiff
)( (pFrm
->Frm().*fnRect
->fnGetTop
)(), nBottom
) < 0 ) );
1489 void MA_FASTCALL
SwInvalidateAll( SwFrm
*pFrm
, long nBottom
)
1491 // LONG_MAX == nBottom means we have to calculate all
1492 BOOL bAll
= LONG_MAX
== nBottom
;
1496 pFrm
->_InvalidatePos();
1497 pFrm
->_InvalidateSize();
1498 pFrm
->_InvalidatePrt();
1499 if( pFrm
->IsLayoutFrm() )
1502 SwLayoutFrm
* pToInvalidate
= static_cast<SwLayoutFrm
*>(pFrm
);
1503 SwCellFrm
* pThisCell
= dynamic_cast<SwCellFrm
*>(pFrm
);
1504 if ( pThisCell
&& pThisCell
->GetTabBox()->getRowSpan() < 1 )
1506 pToInvalidate
= & const_cast<SwCellFrm
&>(pThisCell
->FindStartEndOfRowSpanCell( true, true ));
1507 pToInvalidate
->_InvalidatePos();
1508 pToInvalidate
->_InvalidateSize();
1509 pToInvalidate
->_InvalidatePrt();
1512 if ( pToInvalidate
->Lower() )
1513 ::SwInvalidateAll( pToInvalidate
->Lower(), nBottom
);
1516 pFrm
->Prepare( PREP_CLEAR
);
1518 pFrm
= pFrm
->GetNext();
1521 (*fnRect
->fnYDiff
)( (pFrm
->Frm().*fnRect
->fnGetTop
)(), nBottom
) < 0 ) );
1524 // --> collapsing borders FME 2005-05-27 #i29550#
1525 void lcl_InvalidateAllLowersPrt( SwLayoutFrm
* pLayFrm
)
1527 pLayFrm
->_InvalidatePrt();
1528 pLayFrm
->_InvalidateSize();
1529 pLayFrm
->SetCompletePaint();
1531 SwFrm
* pFrm
= pLayFrm
->Lower();
1535 if ( pFrm
->IsLayoutFrm() )
1536 lcl_InvalidateAllLowersPrt( (SwLayoutFrm
*)pFrm
);
1539 pFrm
->_InvalidatePrt();
1540 pFrm
->_InvalidateSize();
1541 pFrm
->SetCompletePaint();
1544 pFrm
= pFrm
->GetNext();
1549 bool MA_FASTCALL
lcl_CalcLowers( SwLayoutFrm
* pLay
, const SwLayoutFrm
* pDontLeave
,
1550 long nBottom
, bool bSkipRowSpanCells
)
1555 // LONG_MAX == nBottom means we have to calculate all
1556 bool bAll
= LONG_MAX
== nBottom
;
1558 SwCntntFrm
*pCnt
= pLay
->ContainsCntnt();
1561 // FME 2007-08-30 #i81146# new loop control
1562 USHORT nLoopControlRuns
= 0;
1563 const USHORT nLoopControlMax
= 10;
1564 const SwModify
* pLoopControlCond
= 0;
1566 while ( pCnt
&& pDontLeave
->IsAnLower( pCnt
) )
1568 // --> OD 2004-11-23 #115759# - check, if a format of content frame is
1569 // possible. Thus, 'copy' conditions, found at the beginning of
1570 // <SwCntntFrm::MakeAll(..)>, and check these.
1571 const bool bFormatPossible
= !pCnt
->IsJoinLocked() &&
1572 ( !pCnt
->IsTxtFrm() ||
1573 !static_cast<SwTxtFrm
*>(pCnt
)->IsLocked() ) &&
1574 ( pCnt
->IsFollow() || !StackHack::IsLocked() );
1577 bool bSkipContent
= false;
1578 if ( bSkipRowSpanCells
&& pCnt
->IsInTab() )
1580 const SwFrm
* pCell
= pCnt
->GetUpper();
1581 while ( pCell
&& !pCell
->IsCellFrm() )
1582 pCell
= pCell
->GetUpper();
1583 if ( pCell
&& 1 != static_cast<const SwCellFrm
*>( pCell
)->GetLayoutRowSpan() )
1584 bSkipContent
= true;
1587 if ( bFormatPossible
&& !bSkipContent
)
1589 bRet
|= !pCnt
->IsValid();
1590 // --> OD 2004-10-06 #i26945# - no extra invalidation of floating
1591 // screen objects needed.
1592 // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
1595 // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
1596 // to format the floating screen objects
1597 // --> OD 2005-05-03 #i46941# - frame has to be valid
1598 // Note: frame could be invalid after calling its format, if it's locked.
1599 ASSERT( !pCnt
->IsTxtFrm() ||
1601 static_cast<SwTxtFrm
*>(pCnt
)->IsJoinLocked(),
1602 "<lcl_CalcLowers(..)> - text frame invalid and not locked." );
1603 if ( pCnt
->IsTxtFrm() && pCnt
->IsValid() )
1605 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame to
1606 // the object formatter
1607 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt
,
1608 *(pCnt
->FindPageFrm()) ) )
1611 if ( pCnt
->GetRegisteredIn() == pLoopControlCond
)
1615 nLoopControlRuns
= 0;
1616 pLoopControlCond
= pCnt
->GetRegisteredIn();
1619 if ( nLoopControlRuns
< nLoopControlMax
)
1621 // restart format with first content
1622 pCnt
= pLay
->ContainsCntnt();
1626 #if OSL_DEBUG_LEVEL > 1
1627 ASSERT( false, "LoopControl in lcl_CalcLowers" )
1631 pCnt
->GetUpper()->Calc();
1634 if( ! bAll
&& (*fnRect
->fnYDiff
)((pCnt
->Frm().*fnRect
->fnGetTop
)(), nBottom
) > 0 )
1636 pCnt
= pCnt
->GetNextCntntFrm();
1641 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
1642 // that only row and cell frames are formatted.
1643 BOOL MA_FASTCALL
lcl_InnerCalcLayout( SwFrm
*pFrm
,
1645 bool _bOnlyRowsAndCells
)
1647 // LONG_MAX == nBottom means we have to calculate all
1648 BOOL bAll
= LONG_MAX
== nBottom
;
1650 const SwFrm
* pOldUp
= pFrm
->GetUpper();
1654 // --> OD 2004-10-15 #i26945# - parameter <_bOnlyRowsAndCells> controls,
1655 // if only row and cell frames are formatted.
1656 if ( pFrm
->IsLayoutFrm() &&
1657 ( !_bOnlyRowsAndCells
|| pFrm
->IsRowFrm() || pFrm
->IsCellFrm() ) )
1660 // --> FME 2006-02-23 #130744# An invalid locked table frame will
1661 // not be calculated => It will not become valid =>
1662 // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
1663 bRet
|= !pFrm
->IsValid() && ( !pFrm
->IsTabFrm() || !static_cast<SwTabFrm
*>(pFrm
)->IsJoinLocked() );
1666 if( static_cast<SwLayoutFrm
*>(pFrm
)->Lower() )
1667 bRet
|= lcl_InnerCalcLayout( static_cast<SwLayoutFrm
*>(pFrm
)->Lower(), nBottom
);
1670 SwCellFrm
* pThisCell
= dynamic_cast<SwCellFrm
*>(pFrm
);
1671 if ( pThisCell
&& pThisCell
->GetTabBox()->getRowSpan() < 1 )
1673 SwCellFrm
& rToCalc
= const_cast<SwCellFrm
&>(pThisCell
->FindStartEndOfRowSpanCell( true, true ));
1674 bRet
|= !rToCalc
.IsValid();
1676 if ( rToCalc
.Lower() )
1677 bRet
|= lcl_InnerCalcLayout( rToCalc
.Lower(), nBottom
);
1680 pFrm
= pFrm
->GetNext();
1683 (*fnRect
->fnYDiff
)((pFrm
->Frm().*fnRect
->fnGetTop
)(), nBottom
) < 0 )
1684 && pFrm
->GetUpper() == pOldUp
);
1688 void MA_FASTCALL
lcl_FirstTabCalc( SwTabFrm
*pTab
)
1691 if ( !pTab
->IsFollow() && !pTab
->GetTable()->IsTblComplex() )
1693 SwLayoutFrm
* pRow
= (SwLayoutFrm
*)pTab
->Lower();
1694 // --> FME 2006-07-17 #134526# TabFrm without a lower? Better we check
1695 // it before crashing. However, I still don't know how this can happen!
1698 SwLayoutFrm
*pCell
= (SwLayoutFrm
*)pRow
->Lower();
1699 SwFrm
*pCnt
= pCell
->Lower();
1700 // --> OD 2006-11-08 #i70641# - make code robust
1704 const long nCellHeight
= (pCell
->Frm().*fnRect
->fnGetHeight
)();
1705 const long nCellY
= (pCell
->Frm().*fnRect
->fnGetTop
)()-1;
1706 const long nCntHeight
= (pCnt
->Frm().*fnRect
->fnGetHeight
)();
1707 const long nCntY
= (pCnt
->Frm().*fnRect
->fnGetTop
)()-1;
1708 if ( 0 != (pCell
= (SwLayoutFrm
*)pCell
->GetNext()) )
1712 (pCell
->Frm().*fnRect
->fnSetTopAndHeight
)( nCellY
, nCellHeight
);
1713 (pCell
->Prt().*fnRect
->fnSetHeight
)( nCellHeight
);
1714 pCell
->_InvalidateAll();
1716 pCnt
= pCell
->Lower();
1719 (pCnt
->Frm().*fnRect
->fnSetTopAndHeight
)(nCntY
, nCntHeight
);
1720 (pCnt
->Prt().*fnRect
->fnSetHeight
)( nCntHeight
);
1721 pCnt
->_InvalidateAll();
1724 pCell
= (SwLayoutFrm
*)pCell
->GetNext();
1728 SwTwips nRowTop
= (pRow
->Frm().*fnRect
->fnGetTop
)();
1729 SwTwips nUpBot
= (pTab
->GetUpper()->Frm().*fnRect
->fnGetBottom
)();
1730 if( (*fnRect
->fnYDiff
)( nUpBot
, nRowTop
) < 0 )
1734 pRow
= (SwLayoutFrm
*)pRow
->GetNext();
1737 SwFrm
*pUp
= pTab
->GetUpper();
1738 long nBottom
= (pUp
->*fnRect
->fnGetPrtBottom
)();
1739 if ( pTab
->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
1740 nBottom
+= pUp
->Grow( LONG_MAX
, TRUE
);
1741 lcl_CalcLowers( (SwLayoutFrm
*)pTab
->Lower(), pTab
, LONG_MAX
, false );
1744 void MA_FASTCALL
lcl_RecalcRow( SwRowFrm
& rRow
, long nBottom
)
1746 // --> OD 2004-10-05 #i26945# - For correct appliance of the 'straightforward
1747 // object positioning process, it's needed to notify that the page frame,
1748 // on which the given layout frame is in, is in its layout process.
1749 SwPageFrm
* pPageFrm
= rRow
.FindPageFrm();
1750 if ( pPageFrm
&& !pPageFrm
->IsLayoutInProgress() )
1751 pPageFrm
->SetLayoutInProgress( true );
1756 // FME 2007-08-30 #i81146# new loop control
1757 USHORT nLoopControlRuns_1
= 0;
1758 USHORT nLoopControlStage_1
= 0;
1759 const USHORT nLoopControlMax
= 10;
1764 // FME 2007-08-30 #i81146# new loop control
1765 USHORT nLoopControlRuns_2
= 0;
1766 USHORT nLoopControlStage_2
= 0;
1768 while( lcl_InnerCalcLayout( &rRow
, nBottom
) )
1770 if ( ++nLoopControlRuns_2
> nLoopControlMax
)
1772 #if OSL_DEBUG_LEVEL > 1
1773 ASSERT( 0 != nLoopControlStage_2
, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
1774 ASSERT( 1 != nLoopControlStage_2
, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
1775 ASSERT( 2 > nLoopControlStage_2
, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
1777 rRow
.ValidateThisAndAllLowers( nLoopControlStage_2
++ );
1778 nLoopControlRuns_2
= 0;
1779 if( nLoopControlStage_2
> 2 )
1788 // --> OD 2004-11-23 #115759# - force another format of the
1789 // lowers, if at least one of it was invalid.
1790 bCheck
= lcl_CalcLowers( &rRow
, rRow
.GetUpper(), nBottom
, true );
1794 // First we calculate the cells with row span of < 1, afterwards
1795 // all cells with row span of > 1:
1796 for ( int i
= 0; i
< 2; ++i
)
1798 SwCellFrm
* pCellFrm
= static_cast<SwCellFrm
*>(rRow
.Lower());
1801 const bool bCalc
= 0 == i
?
1802 pCellFrm
->GetLayoutRowSpan() < 1 :
1803 pCellFrm
->GetLayoutRowSpan() > 1;
1807 SwCellFrm
& rToRecalc
= 0 == i
?
1808 const_cast<SwCellFrm
&>(pCellFrm
->FindStartEndOfRowSpanCell( true, true )) :
1810 bCheck
|= lcl_CalcLowers( &rToRecalc
, &rToRecalc
, nBottom
, false );
1813 pCellFrm
= static_cast<SwCellFrm
*>(pCellFrm
->GetNext());
1819 if ( ++nLoopControlRuns_1
> nLoopControlMax
)
1821 #if OSL_DEBUG_LEVEL > 1
1822 ASSERT( 0 != nLoopControlStage_1
, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
1823 ASSERT( 1 != nLoopControlStage_1
, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
1824 ASSERT( 2 > nLoopControlStage_1
, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
1826 rRow
.ValidateThisAndAllLowers( nLoopControlStage_1
++ );
1827 nLoopControlRuns_1
= 0;
1828 if( nLoopControlStage_1
> 2 )
1838 // --> OD 2004-10-05 #i26945#
1840 pPageFrm
->SetLayoutInProgress( false );
1844 void MA_FASTCALL
lcl_RecalcTable( SwTabFrm
& rTab
,
1845 SwLayoutFrm
*pFirstRow
,
1846 SwLayNotify
&rNotify
)
1852 pFirstRow
= (SwLayoutFrm
*)rTab
.Lower();
1853 rNotify
.SetLowersComplete( TRUE
);
1855 ::SwInvalidatePositions( pFirstRow
, LONG_MAX
);
1856 lcl_RecalcRow( static_cast<SwRowFrm
&>(*pFirstRow
), LONG_MAX
);
1860 // This is a new function to check the first condition whether
1861 // a tab frame may move backward. It replaces the formerly used
1862 // GetIndPrev(), which did not work correctly for #i5947#
1863 bool lcl_NoPrev( const SwFrm
& rFrm
)
1865 // --> OD 2007-09-04 #i79774#, #b6596954#
1866 // skip empty sections on investigation of direct previous frame.
1867 // use information, that at least one empty section is skipped in the following code.
1868 bool bSkippedDirectPrevEmptySection( false );
1869 if ( rFrm
.GetPrev() )
1871 const SwFrm
* pPrev( rFrm
.GetPrev() );
1873 pPrev
->IsSctFrm() &&
1874 !dynamic_cast<const SwSectionFrm
*>(pPrev
)->GetSection() )
1876 pPrev
= pPrev
->GetPrev();
1877 bSkippedDirectPrevEmptySection
= true;
1885 if ( ( !bSkippedDirectPrevEmptySection
&& !rFrm
.GetIndPrev() ) ||
1886 ( bSkippedDirectPrevEmptySection
&&
1887 ( !rFrm
.IsInSct() || !rFrm
._GetIndPrev() ) ) )
1893 // I do not have a direct prev, but I have an indirect prev.
1894 // In section frames I have to check if I'm located inside
1895 // the first column:
1896 if ( rFrm
.IsInSct() )
1898 const SwFrm
* pSct
= rFrm
.GetUpper();
1899 if ( pSct
&& pSct
->IsColBodyFrm() &&
1900 (pSct
= pSct
->GetUpper()->GetUpper())->IsSctFrm() )
1902 const SwFrm
* pPrevCol
= rFrm
.GetUpper()->GetUpper()->GetPrev();
1904 // I'm not inside the first column and do not have a direct
1905 // prev. I can try to go backward.
1913 #define KEEPTAB ( !GetFollow() && !IsFollow() )
1915 // --> OD 2005-09-28 #b6329202# - helper method to find next content frame of
1916 // a table frame and format it to assure keep attribute.
1917 // method return true, if a next content frame is formatted.
1918 // Precondition: The given table frame hasn't a follow and isn't a follow.
1919 SwFrm
* lcl_FormatNextCntntForKeep( SwTabFrm
* pTabFrm
)
1921 // find next content, table or section
1922 SwFrm
* pNxt
= pTabFrm
->FindNext();
1924 // skip empty sections
1925 while ( pNxt
&& pNxt
->IsSctFrm() &&
1926 !static_cast<SwSectionFrm
*>(pNxt
)->GetSection() )
1928 pNxt
= pNxt
->FindNext();
1931 // if found next frame is a section, get its first content.
1932 if ( pNxt
&& pNxt
->IsSctFrm() )
1934 pNxt
= static_cast<SwSectionFrm
*>(pNxt
)->ContainsAny();
1937 // format found next frame.
1938 // if table frame is inside another table, method <SwFrm::MakeAll()> is
1939 // called to avoid that the superior table frame is formatted.
1942 if ( pTabFrm
->GetUpper()->IsInTab() )
1951 void SwTabFrm::MakeAll()
1953 if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
1958 SwTabFrm
* pFollowFrm
= (SwTabFrm
*)GetFollow();
1959 ASSERT( !pFollowFrm
->IsJoinLocked() || !pFollowFrm
->IsRebuildLastLine(),
1960 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" )
1961 if ( pFollowFrm
->IsJoinLocked() && pFollowFrm
->IsRebuildLastLine() )
1965 PROTOCOL_ENTER( this, PROT_MAKEALL
, 0, 0 )
1967 LockJoin(); //Ich lass mich nicht unterwegs vernichten.
1968 SwLayNotify
aNotify( this ); //uebernimmt im DTor die Benachrichtigung
1969 // If pos is invalid, we have to call a SetInvaKeep at aNotify.
1970 // Otherwise the keep atribute would not work in front of a table.
1971 const BOOL bOldValidPos
= GetValidPosFlag();
1973 //Wenn mein direkter Nachbar gleichzeitig mein Follow ist
1974 //verleibe ich mir das Teil ein.
1975 // OD 09.04.2003 #108698# - join all follows, which are placed on the
1976 // same page/column.
1977 // OD 29.04.2003 #109213# - join follow, only if join for the follow
1978 // is not locked. Otherwise, join will not be performed and this loop
1980 while ( GetNext() && GetNext() == GetFollow() &&
1981 !GetFollow()->IsJoinLocked()
1984 if ( HasFollowFlowLine() )
1985 RemoveFollowFlowLine();
1989 // The bRemoveFollowFlowLinePending is set if the split attribute of the
1990 // last line is set:
1991 if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
1993 if ( RemoveFollowFlowLine() )
1995 SetRemoveFollowFlowLinePending( FALSE
);
1998 if ( bResizeHTMLTable
) //Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes
2000 bResizeHTMLTable
= FALSE
;
2001 SwHTMLTableLayout
*pLayout
= GetTable()->GetHTMLTableLayout();
2003 bCalcLowers
= pLayout
->Resize(
2004 pLayout
->GetBrowseWidthByTabFrm( *this ), FALSE
);
2008 BOOL bMakePage
= TRUE
; //solange TRUE kann eine neue Seite
2009 //angelegt werden (genau einmal)
2010 BOOL bMovedBwd
= FALSE
; //Wird TRUE wenn der Frame zurueckfliesst
2011 BOOL bMovedFwd
= FALSE
; //solange FALSE kann der Frm zurueck-
2012 //fliessen (solange, bis er einmal
2013 //vorwaerts ge'moved wurde).
2014 BOOL bSplit
= FALSE
; //Wird TRUE wenn der Frm gesplittet wurde.
2015 const BOOL bFtnsInDoc
= 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count();
2017 const BOOL bFly
= IsInFly();
2019 SwBorderAttrAccess
*pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2020 const SwBorderAttrs
*pAttrs
= pAccess
->Get();
2022 // The beloved keep attribute
2023 const bool bKeep
= IsKeep( pAttrs
->GetAttrSet() );
2025 // All rows should keep together
2026 // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
2027 const bool bDontSplit
= !IsFollow() &&
2028 ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep
);
2030 // The number of repeated headlines
2031 const USHORT nRepeat
= GetTable()->GetRowsToRepeat();
2033 // This flag indicates that we are allowed to try to split the
2035 bool bTryToSplit
= true;
2037 // --> FME 2006-02-16 #131283#
2038 // Indicates that two individual rows may keep together, based on the keep
2039 // attribute set at the first paragraph in the first cell.
2040 const bool bTableRowKeep
= !bDontSplit
&& GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP
);
2042 // The Magic Move: Used for the table row keep feature.
2043 // If only the last row of the table wants to keep (implicitely by setting
2044 // keep for the first paragraph in the first cell), and this table does
2045 // not have a next, the last line will be cut. Loop prevention: Only
2047 bool bLastRowHasToMoveToFollow
= false;
2048 bool bLastRowMoveNoMoreTries
= false;
2050 // Join follow table, if this table is not allowed to split:
2053 while ( GetFollow() && !GetFollow()->IsJoinLocked() )
2055 if ( HasFollowFlowLine() )
2056 RemoveFollowFlowLine();
2061 // Join follow table, if this does not have enough (repeated) lines:
2064 if( GetFollow() && !GetFollow()->IsJoinLocked() &&
2065 0 == GetFirstNonHeadlineRow() )
2067 if ( HasFollowFlowLine() )
2068 RemoveFollowFlowLine();
2073 // Join follow table, if last row of this table should keep:
2074 if ( bTableRowKeep
&& GetFollow() && !GetFollow()->IsJoinLocked() )
2076 const SwRowFrm
* pTmpRow
= static_cast<const SwRowFrm
*>(GetLastLower());
2077 if ( pTmpRow
&& pTmpRow
->ShouldRowKeepWithNext() )
2079 if ( HasFollowFlowLine() )
2080 RemoveFollowFlowLine();
2085 //Einen Frischling moven wir gleich schon einmal vorwaerts...
2086 if ( !Frm().Top() && IsFollow() )
2088 SwFrm
*pPre
= GetPrev();
2089 if ( pPre
&& pPre
->IsTabFrm() && ((SwTabFrm
*)pPre
)->GetFollow() == this)
2091 if ( !MoveFwd( bMakePage
, FALSE
) )
2097 int nUnSplitted
= 5; // Just another loop control :-(
2099 while ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
2101 if ( TRUE
== (bMoveable
= IsMoveable()) )
2102 if ( CheckMoveFwd( bMakePage
, bKeep
&& KEEPTAB
, bMovedBwd
) )
2106 // --> OD 2009-08-12 #i99267#
2107 // reset <bSplit> after forward move to assure that follows
2108 // can be joined, if further space is available.
2113 Point
aOldPos( (Frm().*fnRect
->fnGetPos
)() );
2116 if ( aOldPos
!= (Frm().*fnRect
->fnGetPos
)() )
2118 if ( aOldPos
.Y() != (Frm().*fnRect
->fnGetTop
)() )
2120 SwHTMLTableLayout
*pLayout
= GetTable()->GetHTMLTableLayout();
2124 bCalcLowers
|= pLayout
->Resize(
2125 pLayout
->GetBrowseWidthByTabFrm( *this ), FALSE
);
2126 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2127 pAttrs
= pAccess
->Get();
2130 bValidPrtArea
= FALSE
;
2131 aNotify
.SetLowersComplete( FALSE
);
2134 if ( bKeep
|| (0 != (pPre
= FindPrev()) &&
2135 pPre
->GetAttrSet()->GetKeep().GetValue()) )
2138 // --> OD 2009-03-06 #i99267#
2139 // reset <bSplit> after forward move to assure that follows
2140 // can be joined, if further space is available.
2146 //Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese
2147 //kleiner wird muss ggf. der Master angestossen werden um noetigenfalls
2148 //die Zeile aufzunehmen.
2149 long n1StLineHeight
= 0;
2152 SwFrm
* pFrm
= GetFirstNonHeadlineRow();
2154 n1StLineHeight
= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
2157 if ( !bValidSize
|| !bValidPrtArea
)
2159 // HB #i101593# no optimization as it leeds to not layouting certain nested tables
2160 // const BOOL bOptLower = (Frm().*fnRect->fnGetHeight)() == 0;
2161 const BOOL bOptLower
= FALSE
;
2163 const long nOldPrtWidth
= (Prt().*fnRect
->fnGetWidth
)();
2164 const long nOldFrmWidth
= (Frm().*fnRect
->fnGetWidth
)();
2165 const Point aOldPrtPos
= (Prt().*fnRect
->fnGetPos
)();
2168 SwHTMLTableLayout
*pLayout
= GetTable()->GetHTMLTableLayout();
2169 if ( /*!bOptLower &&*/ pLayout
&&
2170 ((Prt().*fnRect
->fnGetWidth
)() != nOldPrtWidth
||
2171 (Frm().*fnRect
->fnGetWidth
)() != nOldFrmWidth
) )
2174 bCalcLowers
|= pLayout
->Resize(
2175 pLayout
->GetBrowseWidthByTabFrm( *this ), FALSE
);
2176 // GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() ? FALSE : TRUE );
2177 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2178 pAttrs
= pAccess
->Get();
2180 if ( !bOptLower
&& aOldPrtPos
!= (Prt().*fnRect
->fnGetPos
)() )
2181 aNotify
.SetLowersComplete( FALSE
);
2183 if ( bOptLower
&& Lower() )
2185 //MA 24. May. 95: Optimierungsversuch!
2186 //Ganz nigel nagel neu das Teil. Damit wir nicht n-fach
2187 //MakeAll'en formatieren wir flugs den Inhalt.
2188 //Das erste Format mussten wir allerdings abwarten, damit
2189 //die Breiten Stimmen!
2190 //MA: Fix, Kein Calc wenn evtl. noch Seitengebunde Flys
2191 //an den Cntnt haengen (siehe frmtool.cxx, ~SwCntntNotify).
2192 SwDoc
*pDoc
= GetFmt()->GetDoc();
2193 if ( !pDoc
->GetSpzFrmFmts()->Count() ||
2194 pDoc
->IsLoaded() || pDoc
->IsNewDoc() )
2196 //MA 28. Nov. 95: Und wieder ein Trick, gleich mal sehen
2197 //ob ein Rueckfluss lohnt.
2198 if ( bMoveable
&& !GetPrev() )
2200 GetLeaf( MAKEPAGE_NONE
, FALSE
); //setzt das BackMoveJump
2201 if ( SwFlowFrm::IsMoveBwdJump() )
2204 SwFtnBossFrm
*pOldBoss
= bFtnsInDoc
?
2205 FindFtnBossFrm( TRUE
) : 0;
2206 const BOOL bOldPrev
= GetPrev() != 0;
2207 if ( MoveBwd( bDummy
) )
2212 MoveLowerFtns( 0, pOldBoss
, 0, TRUE
);
2214 long nOldTop
= (Frm().*fnRect
->fnGetTop
)();
2216 if( nOldTop
!= (Frm().*fnRect
->fnGetTop
)() )
2218 SwHTMLTableLayout
*pHTMLLayout
=
2219 GetTable()->GetHTMLTableLayout();
2223 bCalcLowers
|= pHTMLLayout
->Resize(
2224 pHTMLLayout
->GetBrowseWidthByTabFrm(
2226 pAccess
= new SwBorderAttrAccess(
2227 SwFrm::GetCache(), this );
2228 pAttrs
= pAccess
->Get();
2232 if ( bOldPrev
!= (0 != GetPrev()) )
2234 //Abstand nicht vergessen!
2235 bValidPrtArea
= FALSE
;
2238 if ( bKeep
&& KEEPTAB
)
2240 // --> OD 2005-09-28 #b6329202#
2241 // Consider case that table is inside another
2242 // table, because it has to be avoided, that
2243 // superior table is formatted.
2244 // Thus, find next content, table or section
2245 // and, if a section is found, get its first
2247 // SwFrm *pNxt = FindNextCnt();
2248 // // FindNextCnt geht ggf. in einen Bereich
2249 // // hinein, in eine Tabelle allerdings auch
2250 // if( pNxt && pNxt->IsInTab() )
2251 // pNxt = pNxt->FindTabFrm();
2255 // if ( !GetNext() )
2256 // bValidPos = FALSE;
2258 if ( 0 != lcl_FormatNextCntntForKeep( this ) &&
2268 ::lcl_FirstTabCalc( this );
2269 bValidSize
= bValidPrtArea
= FALSE
;
2271 aNotify
.SetLowersComplete( TRUE
);
2276 //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
2277 //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
2278 //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
2280 if ( !bMovedFwd
&& (bMoveable
|| bFly
) && lcl_NoPrev( *this ) )
2282 //Bei Follows muss der Master benachrichtigt
2283 //werden. Der Follow muss nur dann Moven, wenn er leere Blaetter
2284 //ueberspringen muss.
2287 //Nur wenn die Hoehe der ersten Zeile kleiner geworder ist.
2288 SwFrm
*pFrm
= GetFirstNonHeadlineRow();
2289 if( pFrm
&& n1StLineHeight
>(pFrm
->Frm().*fnRect
->fnGetHeight
)() )
2291 SwTabFrm
*pMaster
= (SwTabFrm
*)FindMaster();
2293 if ( ShouldBwdMoved( pMaster
->GetUpper(), FALSE
, bDummy
) )
2294 pMaster
->InvalidatePos();
2297 SwFtnBossFrm
*pOldBoss
= bFtnsInDoc
? FindFtnBossFrm( TRUE
) : 0;
2299 if ( MoveBwd( bReformat
) )
2303 aNotify
.SetLowersComplete( FALSE
);
2305 MoveLowerFtns( 0, pOldBoss
, 0, TRUE
);
2306 if ( bReformat
|| bKeep
)
2308 long nOldTop
= (Frm().*fnRect
->fnGetTop
)();
2310 if( nOldTop
!= (Frm().*fnRect
->fnGetTop
)() )
2312 SwHTMLTableLayout
*pHTMLLayout
=
2313 GetTable()->GetHTMLTableLayout();
2317 bCalcLowers
|= pHTMLLayout
->Resize(
2318 pHTMLLayout
->GetBrowseWidthByTabFrm( *this ),
2321 pAccess
= new SwBorderAttrAccess(
2322 SwFrm::GetCache(), this );
2323 pAttrs
= pAccess
->Get();
2326 bValidPrtArea
= FALSE
;
2329 lcl_RecalcTable( *this, 0, aNotify
);
2330 bLowersFormatted
= TRUE
;
2331 if ( bKeep
&& KEEPTAB
)
2333 // --> OD 2005-09-28 #b6329202#
2334 // Consider case that table is inside another table,
2335 // because it has to be avoided, that superior table
2337 // Thus, find next content, table or section
2338 // and, if a section is found, get its first
2340 // SwFrm *pNxt = FindNextCnt();
2341 // if( pNxt && pNxt->IsInTab() )
2342 // pNxt = pNxt->FindTabFrm();
2346 // if ( !GetNext() )
2347 // bValidPos = FALSE;
2349 if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() )
2359 //Wieder ein Wert ungueltig? - dann nochmal das ganze...
2360 if ( !bValidPos
|| !bValidSize
|| !bValidPrtArea
)
2363 // check, if calculation of table frame is ready.
2365 /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom>
2366 /// Introduce local variable and init it with the distance from the
2367 /// table frame bottom to the bottom of the upper printing area.
2368 /// Note: negative values denotes the situation that table frame doesn't
2369 /// fit in its upper.
2371 SwTwips nDistanceToUpperPrtBottom
=
2372 (Frm().*fnRect
->fnBottomDist
)( (GetUpper()->*fnRect
->fnGetPrtBottom
)());
2374 /// OD 23.10.2002 #103517# - In online layout try to grow upper of table
2375 /// frame, if table frame doesn't fit in its upper.
2376 const bool bBrowseMode
= GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
);
2377 if ( nDistanceToUpperPrtBottom
< 0 && bBrowseMode
)
2379 if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom
) )
2381 // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
2382 nDistanceToUpperPrtBottom
=
2383 (Frm().*fnRect
->fnBottomDist
)( (GetUpper()->*fnRect
->fnGetPrtBottom
)());
2387 // If there is still some space left in the upper, we check if we
2388 // can join some rows of the follow.
2389 // Setting bLastRowHasToMoveToFollow to true means we want to force
2390 // the table to be split! Only skip this if condition once.
2391 if( nDistanceToUpperPrtBottom
>= 0 && !bLastRowHasToMoveToFollow
)
2393 // OD 23.10.2002 - translate german commentary
2394 // If there is space left in the upper printing area, join as for trial
2395 // at least one further row of an existing follow.
2396 if ( !bSplit
&& GetFollow() )
2399 if ( GetFollow()->ShouldBwdMoved( GetUpper(), FALSE
, bDummy
) )
2401 SwFrm
*pTmp
= GetUpper();
2402 SwTwips nDeadLine
= (pTmp
->*fnRect
->fnGetPrtBottom
)();
2404 nDeadLine
+= pTmp
->Grow( LONG_MAX
, TRUE
);
2405 if( (Frm().*fnRect
->fnBottomDist
)( nDeadLine
) > 0 )
2408 // First, we remove an existing follow flow line.
2410 if ( HasFollowFlowLine() )
2412 SwFrm
* pLastLine
= const_cast<SwFrm
*>(GetLastLower());
2413 RemoveFollowFlowLine();
2414 // invalidate and rebuild last row
2417 ::SwInvalidateAll( pLastLine
, LONG_MAX
);
2418 SetRebuildLastLine( TRUE
);
2419 lcl_RecalcRow( static_cast<SwRowFrm
&>(*pLastLine
), LONG_MAX
);
2420 SetRebuildLastLine( FALSE
);
2423 SwFrm
* pRow
= GetFollow()->GetFirstNonHeadlineRow();
2425 if ( !pRow
|| !pRow
->GetNext() )
2426 //Der Follow wird leer und damit ueberfluessig.
2433 // If there is no follow flow line, we move the first
2434 // row in the follow table to the master table.
2436 SwRowFrm
*pRow
= GetFollow()->GetFirstNonHeadlineRow();
2438 //Der Follow wird leer und damit ueberfluessig.
2445 const SwTwips nOld
= (Frm().*fnRect
->fnGetHeight
)();
2446 long nRowsToMove
= lcl_GetMaximumLayoutRowSpan( *pRow
);
2447 SwFrm
* pRowToMove
= pRow
;
2449 while ( pRowToMove
&& nRowsToMove
-- > 0 )
2451 const BOOL bMoveFtns
= bFtnsInDoc
&& !GetFollow()->IsJoinLocked();
2453 SwFtnBossFrm
*pOldBoss
= 0;
2455 pOldBoss
= pRowToMove
->FindFtnBossFrm( TRUE
);
2457 SwFrm
* pNextRow
= pRowToMove
->GetNext();
2460 //Der Follow wird leer und damit ueberfluessig.
2465 pRowToMove
->Paste( this );
2468 //Die Fussnoten verschieben!
2470 if ( ((SwLayoutFrm
*)pRowToMove
)->MoveLowerFtns(
2471 0, pOldBoss
, FindFtnBossFrm( TRUE
), TRUE
) )
2474 pRowToMove
= pNextRow
;
2477 if ( nOld
!= (Frm().*fnRect
->fnGetHeight
)() )
2478 lcl_RecalcTable( *this, (SwLayoutFrm
*)pRow
, aNotify
);
2486 bool bFormat
= false;
2489 else if ( bTableRowKeep
&& !bLastRowMoveNoMoreTries
)
2491 // We only want to give the last row one chance to move
2492 // to the follow table. Set the flag as early as possible:
2493 bLastRowMoveNoMoreTries
= true;
2495 // The last line of the table has to be cut off if:
2496 // 1. The table does not want to keep with its next
2497 // 2. The compatibility option is set and the table is allowed to split
2498 // 3. We did not already cut off the last row
2499 // 4. There is not break after attribute set at the table
2500 // 5. There is no break before attribute set behind the table
2501 // 6. There is no section change behind the table (see IsKeep)
2502 // 7. The last table row wants to keep with its next.
2503 const SwRowFrm
* pLastRow
= static_cast<const SwRowFrm
*>(GetLastLower());
2504 if ( pLastRow
&& IsKeep( pAttrs
->GetAttrSet(), true ) &&
2505 pLastRow
->ShouldRowKeepWithNext() )
2513 // --> OD 2005-09-28 #b6329202#
2514 // Consider case that table is inside another table, because
2515 // it has to be avoided, that superior table is formatted.
2516 // Thus, find next content, table or section and, if a section
2517 // is found, get its first content.
2518 const SwFrm
* pTmpNxt
= lcl_FormatNextCntntForKeep( this );
2521 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2522 pAttrs
= pAccess
->Get();
2524 // The last row wants to keep with the frame behind the table.
2525 // Check if the next frame is on a different page and valid.
2526 // In this case we do a magic trick:
2527 if ( !bKeep
&& !GetNext() && pTmpNxt
&& pTmpNxt
->IsValid() )
2530 bLastRowHasToMoveToFollow
= true;
2539 lcl_RecalcTable( *this, 0, aNotify
);
2540 bLowersFormatted
= TRUE
;
2541 bCalcLowers
= FALSE
;
2543 else if ( bONECalcLowers
)
2545 lcl_RecalcRow( static_cast<SwRowFrm
&>(*Lower()), LONG_MAX
);
2546 bONECalcLowers
= FALSE
;
2552 //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
2553 //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
2555 //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
2556 //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
2557 //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
2558 //zwar mit aller Kraft.
2561 if ( bCalcLowers
&& IsValid() )
2563 lcl_RecalcTable( *this, 0, aNotify
);
2564 bLowersFormatted
= TRUE
;
2565 bCalcLowers
= FALSE
;
2567 else if ( bONECalcLowers
)
2569 lcl_RecalcRow( static_cast<SwRowFrm
&>(*Lower()), LONG_MAX
);
2570 bONECalcLowers
= FALSE
;
2573 // It does not make sense to cut off the last line if we are
2575 bLastRowHasToMoveToFollow
= false;
2580 if ( bCalcLowers
&& IsValid() )
2582 lcl_RecalcTable( *this, 0, aNotify
);
2583 bLowersFormatted
= TRUE
;
2584 bCalcLowers
= FALSE
;
2590 // First try to split the table. Condition:
2591 // 1. We have at least one non headline row
2592 // 2. If this row wants to keep, we need an additional row
2593 // 3. The table is allowed to split or we do not have an pIndPrev:
2595 SwFrm
* pIndPrev
= GetIndPrev();
2596 const SwRowFrm
* pFirstNonHeadlineRow
= GetFirstNonHeadlineRow();
2598 if ( pFirstNonHeadlineRow
&& nUnSplitted
> 0 &&
2599 ( !bTableRowKeep
|| pFirstNonHeadlineRow
->GetNext() || !pFirstNonHeadlineRow
->ShouldRowKeepWithNext() ) &&
2600 ( !bDontSplit
|| !pIndPrev
) )
2602 // --> FME 2004-06-03 #i29438#
2603 // Special DoNotSplit case:
2604 // We better avoid splitting of a row frame if we are inside a columned
2605 // section which has a height of 0, because this is not growable and thus
2606 // all kinds of unexpected things could happen.
2607 const SwSectionFrm
* pTmpSct
= 0;
2609 (pTmpSct
= FindSctFrm())->Lower()->IsColumnFrm() &&
2610 0 == (GetUpper()->Frm().*fnRect
->fnGetHeight
)() )
2612 bTryToSplit
= false;
2616 // 1. Try: bTryToSplit = true => Try to split the row.
2617 // 2. Try: bTryToSplit = false => Split the table between the rows.
2618 if ( pFirstNonHeadlineRow
->GetNext() || bTryToSplit
)
2620 SwTwips nDeadLine
= (GetUpper()->*fnRect
->fnGetPrtBottom
)();
2621 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
2622 nDeadLine
= (*fnRect
->fnYInc
)( nDeadLine
,
2623 GetUpper()->Grow( LONG_MAX
, TRUE
) );
2625 ::lcl_RecalcRow( static_cast<SwRowFrm
&>(*Lower()), nDeadLine
);
2626 bLowersFormatted
= TRUE
;
2627 aNotify
.SetLowersComplete( TRUE
);
2629 // One more check if its really necessary to split the table.
2630 // 1. The table either has to exceed the deadline or
2631 // 2. We explicitly want to cut off the last row.
2632 if( (Frm().*fnRect
->fnBottomDist
)( nDeadLine
) > 0 && !bLastRowHasToMoveToFollow
)
2637 // Set to false again as early as possible.
2638 bLastRowHasToMoveToFollow
= false;
2640 // --> FME 2005-08-03 #i52781#
2641 // YaSC - Yet another special case:
2642 // If our upper is inside a table cell which is not allowed
2643 // to split, we do not try to split:
2644 if ( GetUpper()->IsInTab() )
2646 const SwFrm
* pTmpRow
= GetUpper();
2647 while ( pTmpRow
&& !pTmpRow
->IsRowFrm() )
2648 pTmpRow
= pTmpRow
->GetUpper();
2649 if ( pTmpRow
&& !static_cast<const SwRowFrm
*>(pTmpRow
)->IsRowSplitAllowed() )
2654 USHORT nMinNumOfLines
= nRepeat
;
2656 if ( bTableRowKeep
)
2658 const SwRowFrm
* pTmpRow
= pFirstNonHeadlineRow
;
2659 while ( pTmpRow
&& pTmpRow
->ShouldRowKeepWithNext() )
2662 pTmpRow
= static_cast<const SwRowFrm
*>(pTmpRow
->GetNext());
2664 // Check if all lines want to keep together and we
2665 // have a pIndPrev. In this case we set nDeadLine
2666 // to 0, forcing the table to move forward.
2667 if ( !pTmpRow
&& pIndPrev
)
2674 const SwTwips nBreakLine
= (*fnRect
->fnYInc
)(
2675 (Frm().*fnRect
->fnGetTop
)(),
2676 (this->*fnRect
->fnGetTopMargin
)() +
2677 lcl_GetHeightOfRows( GetLower(), nMinNumOfLines
) );
2679 // Some more checks if we want to call the split algorithm or not:
2680 // The repeating lines / keeping lines still fit into the upper or
2681 // if we do not have an (in)direkt Prev, we split anyway.
2682 if( (*fnRect
->fnYDiff
)(nDeadLine
, nBreakLine
) >=0 || !pIndPrev
)
2684 aNotify
.SetLowersComplete( FALSE
);
2688 // An existing follow flow line has to be removed.
2690 if ( HasFollowFlowLine() )
2691 RemoveFollowFlowLine();
2693 const bool bSplitError
= !Split( nDeadLine
, bTryToSplit
, bTableRowKeep
);
2694 if( !bTryToSplit
&& !bSplitError
&& nUnSplitted
> 0 )
2697 // --> FME 2004-06-09 #i29771# Two tries to split the table:
2698 // If an error occured during splitting. We start a second
2699 // try, this time without splitting of table rows.
2702 if ( HasFollowFlowLine() )
2703 RemoveFollowFlowLine();
2706 // --> FME 2005-02-10 #119477#
2707 // If splitting the table was successfull or not,
2708 // we do not want to have 'empty' follow tables.
2709 if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
2714 // We want to restore the situation before the failed
2715 // split operation as good as possible. Therefore we
2716 // do some more calculations. Note: Restricting this
2717 // to nDeadLine may not be enough.
2718 if ( bSplitError
&& bTryToSplit
) // no restart if we did not try to split: i72847, i79426
2720 lcl_RecalcRow( static_cast<SwRowFrm
&>(*Lower()), LONG_MAX
);
2722 bTryToSplit
= false;
2727 bTryToSplit
= !bSplitError
;
2729 //Damit es nicht zu Oszillationen kommt, muss der
2730 //Follow gleich gueltig gemacht werden.
2733 // --> OD 2007-11-30 #i80924#
2734 // After a successful split assure that the first row
2735 // is invalid. When graphics are present, this isn't hold.
2736 // Note: defect i80924 could also be fixed, if it is
2737 // assured, that <SwLayNotify::bLowersComplete> is only
2738 // set, if all lower are valid *and* are correct laid out.
2739 if ( !bSplitError
&& GetFollow()->GetLower() )
2741 GetFollow()->GetLower()->InvalidatePos();
2744 SWRECTFNX( GetFollow() )
2746 static BYTE nStack
= 0;
2747 if ( !StackHack::IsLocked() && nStack
< 4 )
2753 GetFollow()->MakeAll();
2755 pAccess
= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2756 pAttrs
= pAccess
->Get();
2758 ((SwTabFrm
*)GetFollow())->SetLowersFormatted(FALSE
);
2759 // --> OD 2005-03-30 #i43913# - lock follow table
2760 // to avoid its formatting during the format of
2762 const bool bOldJoinLock
= GetFollow()->IsJoinLocked();
2763 GetFollow()->LockJoin();
2765 ::lcl_RecalcRow( static_cast<SwRowFrm
&>(*GetFollow()->Lower()),
2766 (GetFollow()->GetUpper()->Frm().*fnRectX
->fnGetBottom
)() );
2767 // --> OD 2005-03-30 #i43913#
2768 // --> FME 2006-04-05 #i63632# Do not unlock the
2769 // follow if it wasn't locked before.
2770 if ( !bOldJoinLock
)
2771 GetFollow()->UnlockJoin();
2774 if ( !GetFollow()->GetFollow() )
2776 SwFrm
* pNxt
= ((SwFrm
*)GetFollow())->FindNext();
2779 // OD 26.08.2003 #i18103# - no formatting
2780 // of found next frame, if its a follow
2781 // section of the 'ColLocked' section,
2782 // the follow table is in.
2783 bool bCalcNxt
= true;
2784 if ( GetFollow()->IsInSct() && pNxt
->IsSctFrm() )
2786 SwSectionFrm
* pSct
= GetFollow()->FindSctFrm();
2787 if ( pSct
->IsColLocked() &&
2788 pSct
->GetFollow() == pNxt
)
2801 else if ( GetFollow() == GetNext() )
2802 ((SwTabFrm
*)GetFollow())->MoveFwd( TRUE
, FALSE
);
2804 if ( 0 != (pSh
= GetShell()) )
2805 pSh
->Imp()->ResetScroll();
2812 // Set to false again as early as possible.
2813 bLastRowHasToMoveToFollow
= false;
2815 if( IsInSct() && bMovedFwd
&& bMakePage
&& GetUpper()->IsColBodyFrm() &&
2816 GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
2817 ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
2818 ((SwSectionFrm
*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
2821 // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper
2822 const SwFrm
* pOldUpper
= GetUpper();
2825 //Mal sehen ob ich irgenwo Platz finde...
2826 if ( !bMovedFwd
&& !MoveFwd( bMakePage
, FALSE
) )
2829 // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper
2830 if ( GetUpper() != pOldUpper
)
2838 bMovedFwd
= bCalcLowers
= TRUE
;
2839 aNotify
.SetLowersComplete( FALSE
);
2841 { //Um Oszillationen zu vermeiden sollte kein ungueltiger Master
2843 SwTabFrm
*pTab
= FindMaster();
2844 if ( pTab
->GetUpper() )
2845 pTab
->GetUpper()->Calc();
2847 pTab
->SetLowersFormatted( FALSE
);
2850 //Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist
2851 //verleibe ich mir das Teil ein.
2852 if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
2854 if ( HasFollowFlowLine() )
2855 RemoveFollowFlowLine();
2860 if ( bMovedBwd
&& GetUpper() )
2861 //Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig
2862 //zu Painten, dass koennen wir uns jetzt nach dem hin und her
2864 GetUpper()->ResetCompletePaint();
2866 if ( bCalcLowers
&& IsValid() )
2868 // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary
2869 // and can cause layout loops, if table doesn't fit and isn't
2870 // allowed to split.
2871 SwTwips nDistToUpperPrtBottom
=
2872 (Frm().*fnRect
->fnBottomDist
)( (GetUpper()->*fnRect
->fnGetPrtBottom
)());
2873 if ( nDistToUpperPrtBottom
>= 0 || bTryToSplit
)
2875 lcl_RecalcTable( *this, 0, aNotify
);
2876 bLowersFormatted
= TRUE
;
2877 bCalcLowers
= FALSE
;
2879 #if OSL_DEBUG_LEVEL > 1
2882 ASSERT( false, "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
2888 } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
2890 //Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich
2891 //bei der nachstbesten Gelegenheit vernichten.
2894 SwFrm
*pPre
= GetPrev();
2895 if ( pPre
&& pPre
->IsTabFrm() && ((SwTabFrm
*)pPre
)->GetFollow() == this)
2896 pPre
->InvalidatePos();
2899 bCalcLowers
= bONECalcLowers
= FALSE
;
2902 if ( bMovedFwd
|| bMovedBwd
|| !bOldValidPos
)
2903 aNotify
.SetInvaKeep();
2906 /*************************************************************************
2908 |* SwTabFrm::CalcFlyOffsets()
2910 |* Beschreibung: Berechnet die Offsets, die durch FlyFrames
2912 |* Ersterstellung MA/MIB 14. Apr. 99
2915 |*************************************************************************/
2916 BOOL
SwTabFrm::CalcFlyOffsets( SwTwips
& rUpper
,
2918 long& rRightOffset
) const
2920 BOOL bInvalidatePrtArea
= FALSE
;
2921 const SwPageFrm
*pPage
= FindPageFrm();
2922 const SwFlyFrm
* pMyFly
= FindFlyFrm();
2924 // --> #108724# Page header/footer content doesn't have to wrap around
2925 // floating screen objects
2927 const IDocumentSettingAccess
* pIDSA
= GetFmt()->getIDocumentSettingAccess();
2928 const bool bWrapAllowed
= pIDSA
->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING
) ||
2929 ( !IsInFtn() && 0 == FindFooterOrHeader() );
2932 if ( pPage
->GetSortedObjs() && bWrapAllowed
)
2935 const bool bConsiderWrapOnObjPos
= pIDSA
->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
);
2936 long nPrtPos
= (Frm().*fnRect
->fnGetTop
)();
2937 nPrtPos
= (*fnRect
->fnYInc
)( nPrtPos
, rUpper
);
2938 SwRect
aRect( Frm() );
2939 long nYDiff
= (*fnRect
->fnYDiff
)( (Prt().*fnRect
->fnGetTop
)(), rUpper
);
2941 (aRect
.*fnRect
->fnAddBottom
)( -nYDiff
);
2942 for ( USHORT i
= 0; i
< pPage
->GetSortedObjs()->Count(); ++i
)
2944 SwAnchoredObject
* pAnchoredObj
= (*pPage
->GetSortedObjs())[i
];
2945 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
2947 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
2948 const SwRect aFlyRect
= pFly
->GetObjRectWithSpaces();
2949 // --> OD 2004-10-07 #i26945# - correction of conditions,
2950 // if Writer fly frame has to be considered:
2951 // - no need to check, if top of Writer fly frame differs
2952 // from WEIT_WECH, because its also check, if the Writer
2953 // fly frame rectangle overlaps with <aRect>
2954 // - no check, if bottom of anchor frame is prior the top of
2955 // the table, because Writer fly frames can be negative positioned.
2956 // - correct check, if the Writer fly frame is an lower of the
2957 // table, because table lines/rows can split and a at-character
2958 // anchored Writer fly frame could be positioned in the follow
2960 // - add condition, that an existing anchor character text frame
2961 // has to be on the same page as the table.
2962 // E.g., it could happen, that the fly frame is still registered
2963 // at the page frame, the table is on, but it's anchor character
2964 // text frame has already changed its page.
2965 //if ( WEIT_WECH != (pFly->Frm().*fnRect->fnGetTop)() &&
2966 // pFly->IsFlyAtCntFrm() && aFlyRect.IsOver( aRect ) &&
2967 // // OD 25.02.2003 #i9040# - use '<=' instead of '<'
2968 // (*fnRect->fnYDiff)(
2969 // (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetBottom)(),
2970 // (Frm().*fnRect->fnGetTop)() ) <= 0 &&
2971 // !IsAnLower( pFly ) && !pFly->IsAnLower( this ) &&
2972 // ( !pMyFly || pMyFly->IsAnLower( pFly ) ) &&
2973 // pPage->GetPhyPageNum() >=
2974 // pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2975 // // anchor should be in same page body/header/footer
2976 // ( pFly->GetAnchorFrm()->FindFooterOrHeader() ==
2977 // FindFooterOrHeader() ) )
2978 const SwTxtFrm
* pAnchorCharFrm
= pFly
->FindAnchorCharFrm();
2980 // --> OD 2005-04-06 #i46807# - do not consider invalid
2981 // Writer fly frames.
2984 // fly anchored at character
2985 pFly
->IsFlyAtCntFrm() &&
2986 // fly overlaps with corresponding table rectangle
2987 aFlyRect
.IsOver( aRect
) &&
2988 // fly isn't lower of table and
2989 // anchor character frame of fly isn't lower of table
2990 ( !IsAnLower( pFly
) &&
2991 ( !pAnchorCharFrm
|| !IsAnLower( pAnchorCharFrm
) ) ) &&
2992 // table isn't lower of fly
2993 !pFly
->IsAnLower( this ) &&
2994 // fly is lower of fly, the table is in
2995 // --> OD 2005-05-31 #123274# - correction:
2996 // assure that fly isn't a lower of a fly, the table isn't in.
2997 // E.g., a table in the body doesn't wrap around a graphic,
2998 // which is inside a frame.
3000 pMyFly
->IsAnLower( pFly
) ) &&
3001 pMyFly
== pFly
->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
3003 // anchor frame not on following page
3004 pPage
->GetPhyPageNum() >=
3005 pFly
->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
3006 // anchor character text frame on same page
3007 ( !pAnchorCharFrm
||
3008 pAnchorCharFrm
->FindPageFrm()->GetPhyPageNum() ==
3009 pPage
->GetPhyPageNum() );
3013 const SwFrm
* pFlyHeaderFooterFrm
= pFly
->GetAnchorFrm()->FindFooterOrHeader();
3014 const SwFrm
* pThisHeaderFooterFrm
= FindFooterOrHeader();
3016 if ( pFlyHeaderFooterFrm
!= pThisHeaderFooterFrm
&&
3017 // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set,
3018 // we want to consider the fly if it is located in the header and
3019 // the table is located in the body:
3020 ( !bConsiderWrapOnObjPos
|| 0 != pThisHeaderFooterFrm
|| !pFlyHeaderFooterFrm
->IsHeaderFrm() ) )
3021 bConsiderFly
= false;
3028 const SwFmtSurround
&rSur
= pFly
->GetFmt()->GetSurround();
3029 const SwFmtHoriOrient
&rHori
= pFly
->GetFmt()->GetHoriOrient();
3030 if ( SURROUND_NONE
== rSur
.GetSurround() )
3032 long nBottom
= (aFlyRect
.*fnRect
->fnGetBottom
)();
3033 if( (*fnRect
->fnYDiff
)( nPrtPos
, nBottom
) < 0 )
3035 bInvalidatePrtArea
= TRUE
;
3037 if ( (SURROUND_RIGHT
== rSur
.GetSurround() ||
3038 SURROUND_PARALLEL
== rSur
.GetSurround())&&
3039 text::HoriOrientation::LEFT
== rHori
.GetHoriOrient() )
3041 const long nWidth
= (*fnRect
->fnXDiff
)(
3042 (aFlyRect
.*fnRect
->fnGetRight
)(),
3043 (pFly
->GetAnchorFrm()->Frm().*fnRect
->fnGetLeft
)() );
3044 rLeftOffset
= Max( rLeftOffset
, nWidth
);
3045 bInvalidatePrtArea
= TRUE
;
3047 if ( (SURROUND_LEFT
== rSur
.GetSurround() ||
3048 SURROUND_PARALLEL
== rSur
.GetSurround())&&
3049 text::HoriOrientation::RIGHT
== rHori
.GetHoriOrient() )
3051 const long nWidth
= (*fnRect
->fnXDiff
)(
3052 (pFly
->GetAnchorFrm()->Frm().*fnRect
->fnGetRight
)(),
3053 (aFlyRect
.*fnRect
->fnGetLeft
)() );
3054 rRightOffset
= Max( rRightOffset
, nWidth
);
3055 bInvalidatePrtArea
= TRUE
;
3060 rUpper
= (*fnRect
->fnYDiff
)( nPrtPos
, (Frm().*fnRect
->fnGetTop
)() );
3063 return bInvalidatePrtArea
;
3066 /*************************************************************************
3068 |* SwTabFrm::Format()
3070 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea
3071 |* Die Fixsize wird hier nicht eingestellt.
3072 |* Ersterstellung MA 09. Mar. 93
3073 |* Letzte Aenderung MA 18. Jun. 97
3075 |*************************************************************************/
3076 void SwTabFrm::Format( const SwBorderAttrs
*pAttrs
)
3078 ASSERT( pAttrs
, "TabFrm::Format, pAttrs ist 0." );
3083 long nDiff
= (GetUpper()->Prt().*fnRect
->fnGetWidth
)() -
3084 (Frm().*fnRect
->fnGetWidth
)();
3086 (aFrm
.*fnRect
->fnAddRight
)( nDiff
);
3089 //VarSize ist immer die Hoehe.
3090 //Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer
3091 //cntfrms (sie MakePrtArea() von diesen).
3093 SwTwips nUpper
= CalcUpperSpace( pAttrs
);
3095 //Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten:
3096 //1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen
3097 //2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind
3098 // rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die
3100 long nTmpRight
= -1000000,
3102 if( CalcFlyOffsets( nUpper
, nLeftOffset
, nTmpRight
) )
3103 bValidPrtArea
= FALSE
;
3104 long nRightOffset
= Max( 0L, nTmpRight
);
3106 SwTwips nLower
= pAttrs
->CalcBottomLine();
3107 // --> collapsing borders FME 2005-05-27 #i29550#
3108 if ( IsCollapsingBorders() )
3109 nLower
+= GetBottomLineSize();
3112 if ( !bValidPrtArea
)
3113 { bValidPrtArea
= TRUE
;
3115 //Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender
3116 //sind entsprechend einzustellen.
3117 //Mindestraender werden von Umrandung und Schatten vorgegeben.
3118 //Die Rander werden so eingestellt, dass die PrtArea nach dem
3119 //angegebenen Adjustment im Frm ausgerichtet wird.
3120 //Wenn das Adjustment 0 ist, so werden die Rander anhand des
3121 //Randattributes eingestellt.
3123 const SwTwips nOldHeight
= (Prt().*fnRect
->fnGetHeight
)();
3124 const SwTwips nMax
= (aFrm
.*fnRect
->fnGetWidth
)();
3126 // OD 14.03.2003 #i9040# - adjust variable names.
3127 const SwTwips nLeftLine
= pAttrs
->CalcLeftLine();
3128 const SwTwips nRightLine
= pAttrs
->CalcRightLine();
3130 //Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo
3131 //'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so
3132 //bezieht sie sich in der BrowseView auf die Bildschirmbreite.
3133 const SwFmtFrmSize
&rSz
= GetFmt()->GetFrmSize();
3134 // OD 14.03.2003 #i9040# - adjust variable name.
3135 const SwTwips nWishedTableWidth
= CalcRel( rSz
, TRUE
);
3137 BOOL bCheckBrowseWidth
= FALSE
;
3139 // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
3140 SwTwips nLeftSpacing
= 0;
3141 SwTwips nRightSpacing
= 0;
3142 switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
3144 case text::HoriOrientation::LEFT
:
3147 nLeftSpacing
= nLeftLine
+ nLeftOffset
;
3148 // OD 06.03.2003 #i9040# - correct calculation of right indent:
3149 // - Consider right indent given by right line attributes.
3150 // - Consider negative right indent.
3151 // wished right indent determined by wished table width and
3152 // left offset given by surround fly frames on the left:
3153 const SwTwips nWishRight
= nMax
- nWishedTableWidth
- nLeftOffset
;
3154 if ( nRightOffset
> 0 )
3156 // surrounding fly frames on the right
3157 // -> right indent is maximun of given right offset
3158 // and wished right offset.
3159 nRightSpacing
= nRightLine
+ Max( nRightOffset
, nWishRight
);
3163 // no surrounding fly frames on the right
3164 // If intrinsic right indent (intrinsic means not considering
3165 // determined left indent) is negative,
3166 // then hold this intrinsic indent,
3167 // otherwise non negative wished right indent is hold.
3168 nRightSpacing
= nRightLine
+
3169 ( ( (nWishRight
+nLeftOffset
) < 0 ) ?
3170 (nWishRight
+nLeftOffset
) :
3171 Max( 0L, nWishRight
) );
3175 case text::HoriOrientation::RIGHT
:
3178 nRightSpacing
= nRightLine
+ nRightOffset
;
3179 // OD 06.03.2003 #i9040# - correct calculation of left indent:
3180 // - Consider left indent given by left line attributes.
3181 // - Consider negative left indent.
3182 // wished left indent determined by wished table width and
3183 // right offset given by surrounding fyl frames on the right:
3184 const SwTwips nWishLeft
= nMax
- nWishedTableWidth
- nRightOffset
;
3185 if ( nLeftOffset
> 0 )
3187 // surrounding fly frames on the left
3188 // -> right indent is maximun of given left offset
3189 // and wished left offset.
3190 nLeftSpacing
= nLeftLine
+ Max( nLeftOffset
, nWishLeft
);
3194 // no surrounding fly frames on the left
3195 // If intrinsic left indent (intrinsic = not considering
3196 // determined right indent) is negative,
3197 // then hold this intrinsic indent,
3198 // otherwise non negative wished left indent is hold.
3199 nLeftSpacing
= nLeftLine
+
3200 ( ( (nWishLeft
+nRightOffset
) < 0 ) ?
3201 (nWishLeft
+nRightOffset
) :
3202 Max( 0L, nWishLeft
) );
3206 case text::HoriOrientation::CENTER
:
3208 // OD 07.03.2003 #i9040# - consider left/right line attribute.
3209 // OD 10.03.2003 #i9040# -
3210 const SwTwips nCenterSpacing
= ( nMax
- nWishedTableWidth
) / 2;
3211 nLeftSpacing
= nLeftLine
+
3212 ( (nLeftOffset
> 0) ?
3213 Max( nCenterSpacing
, nLeftOffset
) :
3215 nRightSpacing
= nRightLine
+
3216 ( (nRightOffset
> 0) ?
3217 Max( nCenterSpacing
, nRightOffset
) :
3221 case text::HoriOrientation::FULL
:
3222 //Das Teil dehnt sich ueber die gesamte Breite aus.
3223 //Nur die fuer die Umrandung benoetigten Freiraeume
3224 //werden beruecksichtigt.
3225 //Die Attributwerte von LRSpace werden bewusst missachtet!
3226 bCheckBrowseWidth
= TRUE
;
3227 nLeftSpacing
= nLeftLine
+ nLeftOffset
;
3228 nRightSpacing
= nRightLine
+ nRightOffset
;
3230 case text::HoriOrientation::NONE
:
3232 //Die Raender werden vom Randattribut bestimmt.
3233 nLeftSpacing
= pAttrs
->CalcLeft( this );
3236 // OD 07.03.2003 #i9040# - surround fly frames only, if
3237 // they overlap with the table.
3238 // Thus, take maximun of left spacing and left offset.
3239 // OD 10.03.2003 #i9040# - consider left line attribute.
3240 nLeftSpacing
= Max( nLeftSpacing
, ( nLeftOffset
+ nLeftLine
) );
3242 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
3243 nRightSpacing
= pAttrs
->CalcRight( this );
3246 // OD 07.03.2003 #i9040# - surround fly frames only, if
3247 // they overlap with the table.
3248 // Thus, take maximun of right spacing and right offset.
3249 // OD 10.03.2003 #i9040# - consider right line attribute.
3250 nRightSpacing
= Max( nRightSpacing
, ( nRightOffset
+ nRightLine
) );
3252 // OD 10.03.2003 #i9040# - do not hold wished table width.
3254 if ( !pAttrs->GetLRSpace().GetRight() )
3255 nRight = Max( nRight, nMax - (nWish + nLeft + nRight));
3259 case text::HoriOrientation::LEFT_AND_WIDTH
:
3261 //Linker Rand und die Breite zaehlen (Word-Spezialitaet)
3262 // OD 10.03.2003 #i9040# - no width alignment in online mode.
3263 //bCheckBrowseWidth = TRUE;
3264 nLeftSpacing
= pAttrs
->CalcLeft( this );
3267 // OD 10.03.2003 #i9040# - surround fly frames only, if
3268 // they overlap with the table.
3269 // Thus, take maximun of right spacing and right offset.
3270 // OD 10.03.2003 #i9040# - consider left line attribute.
3271 nLeftSpacing
= Max( nLeftSpacing
, ( pAttrs
->CalcLeftLine() + nLeftOffset
) );
3273 // OD 10.03.2003 #i9040# - consider right and left line attribute.
3274 const SwTwips nWishRight
=
3275 nMax
- (nLeftSpacing
-pAttrs
->CalcLeftLine()) - nWishedTableWidth
;
3276 nRightSpacing
= nRightLine
+
3277 ( (nRightOffset
> 0) ?
3278 Max( nWishRight
, nRightOffset
) :
3283 ASSERT( FALSE
, "Ungueltige orientation fuer Table." );
3286 // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table
3287 // is last content inside a table cell.
3288 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
) &&
3289 GetUpper()->IsInTab() && !GetIndNext() )
3291 nLower
+= pAttrs
->GetULSpace().GetLower();
3294 (this->*fnRect
->fnSetYMargins
)( nUpper
, nLower
);
3295 if( (nMax
- MINLAY
) < (nLeftSpacing
+ nRightSpacing
) )
3296 (this->*fnRect
->fnSetXMargins
)( 0, 0 );
3298 (this->*fnRect
->fnSetXMargins
)( nLeftSpacing
, nRightSpacing
);
3301 if ( bCheckBrowseWidth
&&
3302 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) &&
3303 GetUpper()->IsPageBodyFrm() && // nur PageBodyFrms, nicht etwa ColBodyFrms
3304 0 != (pSh
= GetShell()) && pSh
->VisArea().Width() )
3306 //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
3307 //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
3308 //geben kann (RootFrm::ImplCalcBrowseWidth())
3309 long nWidth
= pSh
->GetBrowseWidth();
3310 nWidth
-= Prt().Left();
3311 nWidth
-= pAttrs
->CalcRightLine();
3312 Prt().Width( Min( nWidth
, Prt().Width() ) );
3315 if ( nOldHeight
!= (Prt().*fnRect
->fnGetHeight
)() )
3323 //Die Groesse wird durch den Inhalt plus den Raendern bestimmt.
3324 SwTwips nRemaining
= 0, nDiff
;
3325 SwFrm
*pFrm
= pLower
;
3328 nRemaining
+= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
3329 pFrm
= pFrm
->GetNext();
3331 //Jetzt noch die Raender addieren
3332 nRemaining
+= nUpper
+ nLower
;
3334 nDiff
= (Frm().*fnRect
->fnGetHeight
)() - nRemaining
;
3337 else if ( nDiff
< 0 )
3341 /*************************************************************************
3343 |* SwTabFrm::GrowFrm()
3345 |* Ersterstellung MA 12. Mar. 93
3346 |* Letzte Aenderung MA 23. Sep. 96
3348 |*************************************************************************/
3349 SwTwips
SwTabFrm::GrowFrm( SwTwips nDist
, BOOL bTst
, BOOL bInfo
)
3352 SwTwips nHeight
=(Frm().*fnRect
->fnGetHeight
)();
3353 if( nHeight
> 0 && nDist
> ( LONG_MAX
- nHeight
) )
3354 nDist
= LONG_MAX
- nHeight
;
3356 if ( bTst
&& !IsRestrictTableGrowth() )
3361 SwRect
aOldFrm( Frm() );
3363 //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal
3364 //die bereits zur Verfuegung stehende Strecke bereitgestellt.
3365 SwTwips nReal
= (GetUpper()->Prt().*fnRect
->fnGetHeight
)();
3366 SwFrm
*pFrm
= GetUpper()->Lower();
3367 while ( pFrm
&& GetFollow() != pFrm
)
3369 nReal
-= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
3370 pFrm
= pFrm
->GetNext();
3374 if ( nReal
< nDist
)
3376 nTmp
= GetUpper()->Grow( nDist
- ( nReal
> 0 ? nReal
: 0), bTst
, bInfo
);
3378 if ( IsRestrictTableGrowth() )
3380 nTmp
= Min( nDist
, nReal
+ nTmp
);
3381 nDist
= nTmp
< 0 ? 0 : nTmp
;
3387 (Frm().*fnRect
->fnAddBottom
)( nDist
);
3389 SwRootFrm
*pRootFrm
= FindRootFrm();
3390 if( pRootFrm
&& pRootFrm
->IsAnyShellAccessible() &&
3391 pRootFrm
->GetCurrShell() )
3393 pRootFrm
->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm
);
3398 if ( !bTst
&& ( nDist
|| IsRestrictTableGrowth() ) )
3400 SwPageFrm
*pPage
= FindPageFrm();
3403 GetNext()->_InvalidatePos();
3404 if ( GetNext()->IsCntntFrm() )
3405 GetNext()->InvalidatePage( pPage
);
3407 // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
3408 // frame on the next page/column can flow backward (e.g. it was moved
3409 // forward due to the positioning of its objects ). Thus, invalivate this
3410 // next frame, if document compatibility option 'Consider wrapping style
3411 // influence on object positioning' is ON.
3412 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
) )
3414 InvalidateNextPos();
3418 InvalidatePage( pPage
);
3421 const SvxGraphicPosition ePos
= GetFmt()->GetBackground().GetGraphicPos();
3422 if ( GPOS_NONE
!= ePos
&& GPOS_TILED
!= ePos
)
3428 /*************************************************************************
3430 |* SwTabFrm::Modify()
3432 |* Ersterstellung MA 14. Mar. 93
3433 |* Letzte Aenderung MA 06. Dec. 96
3435 |*************************************************************************/
3436 void SwTabFrm::Modify( SfxPoolItem
* pOld
, SfxPoolItem
* pNew
)
3439 BOOL bAttrSetChg
= pNew
&& RES_ATTRSET_CHG
== pNew
->Which();
3443 SfxItemIter
aNIter( *((SwAttrSetChg
*)pNew
)->GetChgSet() );
3444 SfxItemIter
aOIter( *((SwAttrSetChg
*)pOld
)->GetChgSet() );
3445 SwAttrSetChg
aOldSet( *(SwAttrSetChg
*)pOld
);
3446 SwAttrSetChg
aNewSet( *(SwAttrSetChg
*)pNew
);
3449 _UpdateAttr( (SfxPoolItem
*)aOIter
.GetCurItem(),
3450 (SfxPoolItem
*)aNIter
.GetCurItem(), nInvFlags
,
3451 &aOldSet
, &aNewSet
);
3452 if( aNIter
.IsAtEnd() )
3457 if ( aOldSet
.Count() || aNewSet
.Count() )
3458 SwLayoutFrm::Modify( &aOldSet
, &aNewSet
);
3461 _UpdateAttr( pOld
, pNew
, nInvFlags
);
3463 if ( nInvFlags
!= 0 )
3465 SwPageFrm
*pPage
= FindPageFrm();
3466 InvalidatePage( pPage
);
3467 // if ( nInvFlags & 0x01 )
3468 // SetCompletePaint();
3469 if ( nInvFlags
& 0x02 )
3471 if ( nInvFlags
& 0x40 )
3474 if ( 0 != (pTmp
= GetIndNext()) )
3476 if ( nInvFlags
& 0x04 )
3478 pTmp
->_InvalidatePrt();
3479 if ( pTmp
->IsCntntFrm() )
3480 pTmp
->InvalidatePage( pPage
);
3482 if ( nInvFlags
& 0x10 )
3483 pTmp
->SetCompletePaint();
3485 if ( nInvFlags
& 0x08 && 0 != (pTmp
= GetPrev()) )
3487 pTmp
->_InvalidatePrt();
3488 if ( pTmp
->IsCntntFrm() )
3489 pTmp
->InvalidatePage( pPage
);
3491 if ( nInvFlags
& 0x20 )
3493 if ( pPage
&& pPage
->GetUpper() && !IsFollow() )
3494 ((SwRootFrm
*)pPage
->GetUpper())->InvalidateBrowseWidth();
3496 if ( nInvFlags
& 0x80 )
3497 InvalidateNextPos();
3501 void SwTabFrm::_UpdateAttr( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
,
3503 SwAttrSetChg
*pOldSet
, SwAttrSetChg
*pNewSet
)
3506 const USHORT nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
3509 case RES_TBLHEADLINECHG
:
3512 // Delete remaining headlines:
3513 SwRowFrm
* pLowerRow
= 0;
3514 while ( 0 != ( pLowerRow
= (SwRowFrm
*)Lower() ) && pLowerRow
->IsRepeatedHeadline() )
3520 // insert new headlines
3521 const USHORT nNewRepeat
= GetTable()->GetRowsToRepeat();
3522 for ( USHORT nIdx
= 0; nIdx
< nNewRepeat
; ++nIdx
)
3524 bDontCreateObjects
= TRUE
; //frmtool
3525 SwRowFrm
* pHeadline
= new SwRowFrm( *GetTable()->GetTabLines()[ nIdx
] );
3526 pHeadline
->SetRepeatedHeadline( true );
3527 bDontCreateObjects
= FALSE
;
3528 pHeadline
->Paste( this, pLowerRow
);
3535 case RES_HORI_ORIENT
:
3539 case RES_PAGEDESC
: //Attributaenderung (an/aus)
3540 if ( IsInDocBody() )
3543 SwPageFrm
*pPage
= FindPageFrm();
3545 CheckPageDescs( pPage
);
3546 if ( pPage
&& GetFmt()->GetPageDesc().GetNumOffset() )
3547 ((SwRootFrm
*)pPage
->GetUpper())->SetVirtPageNum( TRUE
);
3548 SwDocPosUpdate
aMsgHnt( pPage
->Frm().Top() );
3549 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt
);
3557 case RES_LAYOUT_SPLIT
:
3562 SetDerivedR2L( sal_False
);
3565 case RES_COLLAPSING_BORDERS
:
3567 lcl_InvalidateAllLowersPrt( this );
3571 /* kein Break hier */
3578 if ( pOldSet
|| pNewSet
)
3581 pOldSet
->ClearItem( nWhich
);
3583 pNewSet
->ClearItem( nWhich
);
3586 SwLayoutFrm::Modify( pOld
, pNew
);
3590 /*************************************************************************
3592 |* SwTabFrm::GetInfo()
3594 |* Ersterstellung MA 06. Dec. 96
3595 |* Letzte Aenderung MA 26. Jun. 98
3597 |*************************************************************************/
3598 BOOL
SwTabFrm::GetInfo( SfxPoolItem
&rHnt
) const
3600 if ( RES_VIRTPAGENUM_INFO
== rHnt
.Which() && IsInDocBody() && !IsFollow() )
3602 SwVirtPageNumInfo
&rInfo
= (SwVirtPageNumInfo
&)rHnt
;
3603 const SwPageFrm
*pPage
= FindPageFrm();
3606 if ( pPage
== rInfo
.GetOrigPage() && !GetPrev() )
3608 //Das sollte er sein (kann allenfalls temporaer anders sein,
3609 // sollte uns das beunruhigen?)
3610 rInfo
.SetInfo( pPage
, this );
3613 if ( pPage
->GetPhyPageNum() < rInfo
.GetOrigPage()->GetPhyPageNum() &&
3614 (!rInfo
.GetPage() || pPage
->GetPhyPageNum() > rInfo
.GetPage()->GetPhyPageNum()))
3616 //Das koennte er sein.
3617 rInfo
.SetInfo( pPage
, this );
3624 /*************************************************************************
3626 |* SwTabFrm::FindLastCntnt()
3628 |* Ersterstellung MA 13. Apr. 93
3629 |* Letzte Aenderung MA 15. May. 98
3631 |*************************************************************************/
3632 SwCntntFrm
*SwTabFrm::FindLastCntnt()
3634 SwFrm
*pRet
= pLower
;
3636 while ( pRet
&& !pRet
->IsCntntFrm() )
3640 SwFrm
*pTmp
= pRet
; // To skip empty section frames
3641 while ( pRet
->GetNext() )
3643 pRet
= pRet
->GetNext();
3644 if( !pRet
->IsSctFrm() || ((SwSectionFrm
*)pRet
)->GetSection() )
3649 if ( pRet
->GetLower() )
3650 pRet
= pRet
->GetLower();
3653 // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht,
3654 // der eine leere letzte Spalte hat, muessen wir noch die anderen
3655 // Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt
3656 if( pRet
->IsColBodyFrm() )
3659 SwSectionFrm
* pSect
= pRet
->FindSctFrm();
3660 ASSERT( pSect
, "Wo kommt denn die Spalte her?")
3661 ASSERT( IsAnLower( pSect
), "Gespaltene Zelle?" );
3663 return pRet
->FindSctFrm()->FindLastCntnt();
3667 // pRet may be a cell frame without a lower (cell has been split).
3668 // We have to find the last content the hard way:
3670 ASSERT( pRet
->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" )
3671 const SwFrm
* pRow
= pRet
->GetUpper();
3672 while ( pRow
&& !pRow
->GetUpper()->IsTabFrm() )
3673 pRow
= pRow
->GetUpper();
3674 SwCntntFrm
* pCntntFrm
= ((SwLayoutFrm
*)pRow
)->ContainsCntnt();
3677 while ( pCntntFrm
&& ((SwLayoutFrm
*)pRow
)->IsAnLower( pCntntFrm
) )
3680 pCntntFrm
= pCntntFrm
->GetNextCntntFrm();
3685 // #112929# There actually is a situation, which results in pRet = 0:
3686 // Insert frame, insert table via text <-> table. This gives you a frame
3687 // containing a table without any other content frames. Split the table
3688 // and undo the splitting. This operation gives us a table frame without
3692 while ( pRet
->GetNext() )
3693 pRet
= pRet
->GetNext();
3695 if( pRet
->IsSctFrm() )
3696 pRet
= ((SwSectionFrm
*)pRet
)->FindLastCntnt();
3699 return (SwCntntFrm
*)pRet
;
3702 /*************************************************************************
3704 |* SwTabFrm::GetLeaf()
3706 |* Ersterstellung MA 19. Mar. 93
3707 |* Letzte Aenderung MA 25. Apr. 95
3709 |*************************************************************************/
3710 SwLayoutFrm
*SwTabFrm::GetLeaf( MakePageType eMakePage
, BOOL bFwd
)
3715 pRet
= GetNextLeaf( eMakePage
);
3716 while ( IsAnLower( pRet
) )
3717 pRet
= pRet
->GetNextLeaf( eMakePage
);
3720 pRet
= GetPrevLeaf();
3726 /*************************************************************************
3728 |* SwTabFrm::ShouldBwdMoved()
3730 |* Beschreibung Returnwert sagt ob der Frm verschoben werden sollte
3731 |* Ersterstellung MA 10. Jul. 95
3732 |* Letzte Aenderung MA 04. Mar. 97
3734 |*************************************************************************/
3735 BOOL
SwTabFrm::ShouldBwdMoved( SwLayoutFrm
*pNewUpper
, BOOL
, BOOL
&rReformat
)
3738 if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
3740 //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
3741 //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
3742 //moechte die FixSize die gleiche ist, die der Frm selbst hat.
3743 //In diesem Fall kann einfach geprueft werden, ob der Frm genug
3744 //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
3745 //gleich auf das Verschieben verzichtet werden.
3746 //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
3747 //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
3749 //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
3750 //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
3751 //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
3752 //etwas Platz zur Verfuegung steht).
3754 //Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer
3757 SwPageFrm
*pOldPage
= FindPageFrm(),
3758 *pNewPage
= pNewUpper
->FindPageFrm();
3759 BOOL bMoveAnyway
= FALSE
;
3763 if ( !SwFlowFrm::IsMoveBwdJump() )
3766 long nOldWidth
= (GetUpper()->Prt().*fnRect
->fnGetWidth
)();
3767 SWRECTFNX( pNewUpper
);
3768 long nNewWidth
= (pNewUpper
->Prt().*fnRectX
->fnGetWidth
)();
3769 if( Abs( nNewWidth
- nOldWidth
) < 2 )
3772 ( bMoveAnyway
= BwdMoveNecessary( pOldPage
, Frm() ) > 1 ) )
3774 SwRect
aRect( pNewUpper
->Prt() );
3775 aRect
.Pos() += pNewUpper
->Frm().Pos();
3776 const SwFrm
*pPrevFrm
= pNewUpper
->Lower();
3777 while ( pPrevFrm
&& pPrevFrm
!= this )
3779 (aRect
.*fnRectX
->fnSetTop
)( (pPrevFrm
->Frm().*fnRectX
->
3781 pPrevFrm
= pPrevFrm
->GetNext();
3783 bMoveAnyway
= BwdMoveNecessary( pNewPage
, aRect
) > 1;
3785 // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake,
3786 // the tabfrm may not have a correct position. Therefore
3787 // it is possible that pNewUpper->Prt().Height == 0. In this
3788 // case the above calculation of nSpace might give wrong
3789 // results and we really do not want to MoveBackwrd into a
3790 // 0 height frame. If nTmpSpace is already <= 0, we take this
3792 const SwTwips nTmpSpace
= (aRect
.*fnRectX
->fnGetHeight
)();
3793 if ( (pNewUpper
->Prt().*fnRectX
->fnGetHeight
)() > 0 || nTmpSpace
<= 0 )
3797 if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
3798 nSpace
+= pNewUpper
->Grow( LONG_MAX
, TRUE
);
3801 else if( !bLockBackMove
)
3804 else if( !bLockBackMove
)
3808 return rReformat
= TRUE
;
3809 else if ( !bLockBackMove
&& nSpace
> 0 )
3811 // --> OD 2004-10-05 #i26945# - check, if follow flow line
3812 // contains frame, which are moved forward due to its object
3814 SwRowFrm
* pFirstRow
= GetFirstNonHeadlineRow();
3815 if ( pFirstRow
&& pFirstRow
->IsInFollowFlowRow() &&
3816 SwLayouter::DoesRowContainMovedFwdFrm(
3817 *(pFirstRow
->GetFmt()->GetDoc()),
3823 SwTwips nTmpHeight
= CalcHeightOfFirstContentLine();
3825 // --> FME 2005-01-17 #118840#
3826 // For some mysterious reason, I changed the good old
3827 // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
3828 // This obviously results in problems with table frames in
3829 // sections. Remember: Every twip is sacred.
3830 return nTmpHeight
<= nSpace
;
3837 /*************************************************************************
3841 |* Ersterstellung MA 23. Feb. 94
3842 |* Letzte Aenderung MA 09. Sep. 98
3844 |*************************************************************************/
3845 void SwTabFrm::Cut()
3847 ASSERT( GetUpper(), "Cut ohne Upper()." );
3849 SwPageFrm
*pPage
= FindPageFrm();
3850 InvalidatePage( pPage
);
3851 SwFrm
*pFrm
= GetNext();
3853 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
3854 //berechnet der ist jetzt wo er der erste wird obsolete
3855 pFrm
->_InvalidatePrt();
3856 pFrm
->_InvalidatePos();
3857 if ( pFrm
->IsCntntFrm() )
3858 pFrm
->InvalidatePage( pPage
);
3859 if( IsInSct() && !GetPrev() )
3861 SwSectionFrm
* pSct
= FindSctFrm();
3862 if( !pSct
->IsFollow() )
3864 pSct
->_InvalidatePrt();
3865 pSct
->InvalidatePage( pPage
);
3871 InvalidateNextPos();
3872 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
3873 if ( 0 != (pFrm
= GetPrev()) )
3874 { pFrm
->SetRetouche();
3875 pFrm
->Prepare( PREP_WIDOWS_ORPHANS
);
3876 pFrm
->_InvalidatePos();
3877 if ( pFrm
->IsCntntFrm() )
3878 pFrm
->InvalidatePage( pPage
);
3880 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
3881 //er die Retouche uebernehmen.
3882 //Ausserdem kann eine Leerseite entstanden sein.
3884 { SwRootFrm
*pRoot
= (SwRootFrm
*)pPage
->GetUpper();
3885 pRoot
->SetSuperfluous();
3886 GetUpper()->SetCompletePaint();
3889 SwSectionFrm
* pSct
= FindSctFrm();
3890 if( !pSct
->IsFollow() )
3892 pSct
->_InvalidatePrt();
3893 pSct
->InvalidatePage( pPage
);
3899 //Erst removen, dann Upper Shrinken.
3900 SwLayoutFrm
*pUp
= GetUpper();
3905 ASSERT( !pUp
->IsFtnFrm(), "Tabelle in Fussnote." );
3906 SwSectionFrm
*pSct
= 0;
3907 // --> OD 2006-01-04 #126020# - adjust check for empty section
3908 // --> OD 2006-02-01 #130797# - correct fix #126020#
3909 if ( !pUp
->Lower() && pUp
->IsInSct() &&
3910 !(pSct
= pUp
->FindSctFrm())->ContainsCntnt() &&
3911 !pSct
->ContainsAny( true ) )
3914 if ( pUp
->GetUpper() )
3916 pSct
->DelEmpty( FALSE
);
3917 pSct
->_InvalidateSize();
3920 else if( (Frm().*fnRect
->fnGetHeight
)() )
3922 // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
3923 // undo changes of fix for #104992#
3924 pUp
->Shrink( Frm().Height() );
3928 if ( pPage
&& !IsFollow() && pPage
->GetUpper() )
3929 ((SwRootFrm
*)pPage
->GetUpper())->InvalidateBrowseWidth();
3932 /*************************************************************************
3934 |* SwTabFrm::Paste()
3936 |* Ersterstellung MA 23. Feb. 94
3937 |* Letzte Aenderung MA 09. Sep. 98
3939 |*************************************************************************/
3940 void SwTabFrm::Paste( SwFrm
* pParent
, SwFrm
* pSibling
)
3942 ASSERT( pParent
, "Kein Parent fuer Paste." );
3943 ASSERT( pParent
->IsLayoutFrm(), "Parent ist CntntFrm." );
3944 ASSERT( pParent
!= this, "Bin selbst der Parent." );
3945 ASSERT( pSibling
!= this, "Bin mein eigener Nachbar." );
3946 ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
3947 "Bin noch irgendwo angemeldet." );
3949 //In den Baum einhaengen.
3950 InsertBefore( (SwLayoutFrm
*)pParent
, pSibling
);
3953 SwPageFrm
*pPage
= FindPageFrm();
3954 InvalidatePage( pPage
);
3958 GetNext()->_InvalidatePos();
3959 GetNext()->_InvalidatePrt();
3960 if ( GetNext()->IsCntntFrm() )
3961 GetNext()->InvalidatePage( pPage
);
3965 if( (Frm().*fnRect
->fnGetHeight
)() )
3966 pParent
->Grow( (Frm().*fnRect
->fnGetHeight
)() );
3968 if( (Frm().*fnRect
->fnGetWidth
)() != (pParent
->Prt().*fnRect
->fnGetWidth
)() )
3969 Prepare( PREP_FIXSIZE_CHG
);
3974 GetPrev()->InvalidateSize();
3975 if ( GetPrev()->IsCntntFrm() )
3976 GetPrev()->InvalidatePage( pPage
);
3979 else if ( GetNext() )
3980 //Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger
3981 //zu beachten. Faelle (beide treten immer gleichzeitig auf):
3982 //a) Der Cntnt wird der erste einer Kette
3983 //b) Der neue Nachfolger war vorher der erste einer Kette
3984 GetNext()->_InvalidatePrt();
3986 if ( pPage
&& !IsFollow() )
3988 if ( pPage
->GetUpper() )
3989 ((SwRootFrm
*)pPage
->GetUpper())->InvalidateBrowseWidth();
3991 if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig.
3993 const SwPageDesc
*pDesc
= GetFmt()->GetPageDesc().GetPageDesc();
3994 if ( (pDesc
&& pDesc
!= pPage
->GetPageDesc()) ||
3995 (!pDesc
&& pPage
->GetPageDesc() !=
3996 &(const_cast<const SwDoc
*>(GetFmt()->GetDoc())
3997 ->GetPageDesc(0))) )
3998 CheckPageDescs( pPage
, TRUE
);
4003 /*************************************************************************
4005 |* SwTabFrm::Prepare()
4007 |* Created AMA 01/10/02
4008 |* Last Change AMA 01/10/02
4010 |*************************************************************************/
4011 void SwTabFrm::Prepare( const PrepareHint eHint
, const void *, BOOL
)
4013 if( PREP_BOSS_CHGD
== eHint
)
4017 /*************************************************************************
4019 |* SwRowFrm::SwRowFrm(), ~SwRowFrm()
4021 |* Ersterstellung MA 09. Mar. 93
4022 |* Letzte Aenderung MA 30. May. 96
4024 |*************************************************************************/
4025 SwRowFrm::SwRowFrm( const SwTableLine
&rLine
, bool bInsertContent
):
4026 SwLayoutFrm( rLine
.GetFrmFmt() ),
4029 // --> collapsing borders FME 2005-05-27 #i29550#
4030 mnTopMarginForLowers( 0 ),
4031 mnBottomMarginForLowers( 0 ),
4032 mnBottomLineSize( 0 ),
4034 // --> split table rows
4035 bIsFollowFlowRow( false ),
4036 // <-- split table rows
4037 bIsRepeatedHeadline( false ),
4038 mbIsRowSpanLine( false )
4042 //Gleich die Boxen erzeugen und einfuegen.
4043 const SwTableBoxes
&rBoxes
= rLine
.GetTabBoxes();
4044 SwFrm
*pTmpPrev
= 0;
4045 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
4047 SwCellFrm
*pNew
= new SwCellFrm( *rBoxes
[i
], bInsertContent
);
4048 pNew
->InsertBehind( this, pTmpPrev
);
4053 SwRowFrm::~SwRowFrm()
4055 SwModify
* pMod
= GetFmt();
4058 pMod
->Remove( this ); // austragen,
4059 if( !pMod
->GetDepends() )
4060 delete pMod
; // und loeschen
4064 /*************************************************************************
4066 |* SwRowFrm::RegistFlys()
4068 |* Ersterstellung MA 08. Jul. 93
4069 |* Letzte Aenderung MA 08. Jul. 93
4071 |*************************************************************************/
4072 void SwRowFrm::RegistFlys( SwPageFrm
*pPage
)
4074 ::RegistFlys( pPage
? pPage
: FindPageFrm(), this );
4077 /*************************************************************************
4079 |* SwRowFrm::Modify()
4081 |* Ersterstellung MA 12. Nov. 97
4082 |* Letzte Aenderung MA 12. Nov. 97
4084 |*************************************************************************/
4085 void SwRowFrm::Modify( SfxPoolItem
* pOld
, SfxPoolItem
* pNew
)
4087 BOOL bAttrSetChg
= pNew
&& RES_ATTRSET_CHG
== pNew
->Which();
4088 const SfxPoolItem
*pItem
= 0;
4092 const SwAttrSet
* pChgSet
= ((SwAttrSetChg
*)pNew
)->GetChgSet();
4093 pChgSet
->GetItemState( RES_FRM_SIZE
, FALSE
, &pItem
);
4095 pChgSet
->GetItemState( RES_ROW_SPLIT
, FALSE
, &pItem
);
4097 else if ( RES_FRM_SIZE
== pNew
->Which() || RES_ROW_SPLIT
== pNew
->Which() )
4102 SwTabFrm
*pTab
= FindTabFrm();
4105 const bool bInFirstNonHeadlineRow
= pTab
->IsFollow() &&
4106 this == pTab
->GetFirstNonHeadlineRow();
4107 // --> FME 2004-10-27 #i35063#
4108 // Invalidation required is pRow is last row
4109 if ( bInFirstNonHeadlineRow
|| !GetNext() )
4112 if ( bInFirstNonHeadlineRow
)
4113 pTab
= pTab
->FindMaster();
4114 pTab
->InvalidatePos();
4119 SwLayoutFrm::Modify( pOld
, pNew
);
4124 /*************************************************************************
4126 |* SwRowFrm::MakeAll()
4128 |* Ersterstellung MA 01. Mar. 94
4129 |* Letzte Aenderung MA 01. Mar. 94
4131 |*************************************************************************/
4132 void SwRowFrm::MakeAll()
4136 SwLayoutFrm::MakeAll();
4139 /*************************************************************************
4141 |* SwRowFrm::Format()
4143 |* Ersterstellung MA 13. Mar. 93
4144 |* Letzte Aenderung MA 20. Jun. 96
4146 |*************************************************************************/
4147 long MA_FASTCALL
CalcHeightWidthFlys( const SwFrm
*pFrm
)
4151 const SwFrm
* pTmp
= pFrm
->IsSctFrm() ?
4152 ((SwSectionFrm
*)pFrm
)->ContainsCntnt() : pFrm
;
4155 // --> OD 2004-10-08 #i26945# - consider follow text frames
4156 const SwSortedObjs
* pObjs( 0L );
4157 bool bIsFollow( false );
4158 if ( pTmp
->IsTxtFrm() && static_cast<const SwTxtFrm
*>(pTmp
)->IsFollow() )
4160 const SwFrm
* pMaster
;
4161 // --> FME 2005-04-01 #i46450# Master does not necessarily have
4162 // to exist if this function is called from JoinFrm() ->
4163 // Cut() -> Shrink()
4164 const SwTxtFrm
* pTmpFrm
= static_cast<const SwTxtFrm
*>(pTmp
);
4165 if ( pTmpFrm
->GetPrev() && pTmpFrm
->GetPrev()->IsTxtFrm() &&
4166 static_cast<const SwTxtFrm
*>(pTmpFrm
->GetPrev())->GetFollow() &&
4167 static_cast<const SwTxtFrm
*>(pTmpFrm
->GetPrev())->GetFollow() != pTmp
)
4170 pMaster
= pTmpFrm
->FindMaster();
4174 pObjs
= static_cast<const SwTxtFrm
*>(pTmp
)->FindMaster()->GetDrawObjs();
4180 pObjs
= pTmp
->GetDrawObjs();
4185 for ( USHORT i
= 0; i
< pObjs
->Count(); ++i
)
4187 const SwAnchoredObject
* pAnchoredObj
= (*pObjs
)[i
];
4188 // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the
4189 // anchor character frame has to be <pTmp>.
4191 const_cast<SwAnchoredObject
*>(pAnchoredObj
)->FindAnchorCharFrm() != pTmp
)
4196 // --> OD 2004-10-04 #i26945# - consider also drawing objects
4198 // OD 30.09.2003 #i18732# - only objects, which follow
4199 // the text flow have to be considered.
4200 const SwFrmFmt
& rFrmFmt
= pAnchoredObj
->GetFrmFmt();
4201 const bool bConsiderObj
=
4202 rFrmFmt
.GetAnchor().GetAnchorId() != FLY_IN_CNTNT
&&
4203 pAnchoredObj
->GetObjRect().Top() != WEIT_WECH
&&
4204 rFrmFmt
.GetFollowTextFlow().GetValue() &&
4205 pAnchoredObj
->GetPageFrm() == pTmp
->FindPageFrm();
4208 const SwFmtFrmSize
&rSz
= rFrmFmt
.GetFrmSize();
4209 if( !rSz
.GetHeightPercent() )
4211 const SwTwips nDistOfFlyBottomToAnchorTop
=
4212 (pAnchoredObj
->GetObjRect().*fnRect
->fnGetHeight
)() +
4214 pAnchoredObj
->GetCurrRelPos().X() :
4215 pAnchoredObj
->GetCurrRelPos().Y() );
4217 const SwTwips nFrmDiff
=
4219 (pTmp
->Frm().*fnRect
->fnGetTop
)(),
4220 (pFrm
->Frm().*fnRect
->fnGetTop
)() );
4222 nHeight
= Max( nHeight
, nDistOfFlyBottomToAnchorTop
+ nFrmDiff
-
4223 (pFrm
->Frm().*fnRect
->fnGetHeight
)() );
4225 // --> FME 2006-01-24 #i56115# The first height calculation
4226 // gives wrong results if pFrm->Prt().Y() > 0. We do
4227 // a second calculation based on the actual rectangles of
4228 // pFrm and pAnchoredObj, and use the maximum of the results.
4229 // I do not want to remove the first calculation because
4230 // if clipping has been applied, using the GetCurrRelPos
4231 // might be the better option to calculate nHeight.
4232 const SwTwips nDistOfFlyBottomToAnchorTop2
= (*fnRect
->fnYDiff
)(
4233 (pAnchoredObj
->GetObjRect().*fnRect
->fnGetBottom
)(),
4234 (pFrm
->Frm().*fnRect
->fnGetBottom
)() );
4236 nHeight
= Max( nHeight
, nDistOfFlyBottomToAnchorTop2
);
4244 if( !pFrm
->IsSctFrm() )
4246 pTmp
= pTmp
->FindNextCnt();
4247 if( !((SwSectionFrm
*)pFrm
)->IsAnLower( pTmp
) )
4253 SwTwips
lcl_CalcTopAndBottomMargin( const SwLayoutFrm
& rCell
, const SwBorderAttrs
& rAttrs
)
4255 const SwTabFrm
* pTab
= rCell
.FindTabFrm();
4256 SwTwips nTopSpace
= 0;
4257 SwTwips nBottomSpace
= 0;
4259 // --> collapsing borders FME 2005-05-27 #i29550#
4260 if ( pTab
->IsCollapsingBorders() && rCell
.Lower() && !rCell
.Lower()->IsRowFrm() )
4262 nTopSpace
= ((SwRowFrm
*)rCell
.GetUpper())->GetTopMarginForLowers();
4263 nBottomSpace
= ((SwRowFrm
*)rCell
.GetUpper())->GetBottomMarginForLowers();
4268 if ( pTab
->IsVertical() != rCell
.IsVertical() )
4270 nTopSpace
= rAttrs
.CalcLeft( &rCell
);
4271 nBottomSpace
= rAttrs
.CalcRight( &rCell
);
4275 nTopSpace
= rAttrs
.CalcTop();
4276 nBottomSpace
= rAttrs
.CalcBottom();
4280 return nTopSpace
+ nBottomSpace
;
4284 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
4285 // control, if floating screen objects have to be considered for the minimal
4287 SwTwips MA_FASTCALL
lcl_CalcMinCellHeight( const SwLayoutFrm
*_pCell
,
4288 const BOOL _bConsiderObjs
,
4289 const SwBorderAttrs
*pAttrs
= 0 )
4292 SwTwips nHeight
= 0;
4293 const SwFrm
* pLow
= _pCell
->Lower();
4299 // OD 2004-02-18 #106629# - change condition and switch then-body
4301 if ( pLow
->IsRowFrm() )
4303 // --> OD 2004-10-04 #i26945#
4304 nHeight
+= ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm
*>(pLow
),
4310 long nLowHeight
= (pLow
->Frm().*fnRect
->fnGetHeight
)();
4311 nHeight
+= nLowHeight
;
4312 // --> OD 2004-10-04 #i26945#
4313 if ( _bConsiderObjs
)
4315 nFlyAdd
= Max( 0L, nFlyAdd
- nLowHeight
);
4316 nFlyAdd
= Max( nFlyAdd
, ::CalcHeightWidthFlys( pLow
) );
4321 pLow
= pLow
->GetNext();
4326 //Der Border will natuerlich auch mitspielen, er kann leider nicht
4327 //aus PrtArea und Frm errechnet werden, da diese in beliebiger
4328 //Kombination ungueltig sein koennen.
4329 if ( _pCell
->Lower() )
4332 nHeight
+= lcl_CalcTopAndBottomMargin( *_pCell
, *pAttrs
);
4335 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), _pCell
);
4336 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
4337 nHeight
+= lcl_CalcTopAndBottomMargin( *_pCell
, rAttrs
);
4343 // OD 2004-02-18 #106629# - correct type of 1st parameter
4344 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control,
4345 // if floating screen objects have to be considered for the minimal cell height
4346 SwTwips MA_FASTCALL
lcl_CalcMinRowHeight( const SwRowFrm
* _pRow
,
4347 const BOOL _bConsiderObjs
)
4351 const SwFmtFrmSize
&rSz
= _pRow
->GetFmt()->GetFrmSize();
4353 if ( _pRow
->HasFixSize() && !_pRow
->IsRowSpanLine() )
4355 ASSERT( ATT_FIX_SIZE
== rSz
.GetHeightSizeType(), "pRow claims to have fixed size" )
4356 return rSz
.GetHeight();
4359 SwTwips nHeight
= 0;
4360 const SwCellFrm
* pLow
= static_cast<const SwCellFrm
*>(_pRow
->Lower());
4364 const long nRowSpan
= pLow
->GetLayoutRowSpan();
4366 // Consider height of
4367 // 1. current cell if RowSpan == 1
4368 // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
4369 // 3. master cell if RowSpan == -1
4370 if ( 1 == nRowSpan
)
4372 nTmp
= ::lcl_CalcMinCellHeight( pLow
, _bConsiderObjs
);
4374 else if ( -1 == nRowSpan
)
4376 // Height of the last cell of a row span is height of master cell
4377 // minus the height of the other rows which are covered by the master
4379 const SwCellFrm
& rMaster
= pLow
->FindStartEndOfRowSpanCell( true, true );
4380 nTmp
= ::lcl_CalcMinCellHeight( &rMaster
, _bConsiderObjs
);
4381 const SwFrm
* pMasterRow
= rMaster
.GetUpper();
4382 while ( pMasterRow
&& pMasterRow
!= _pRow
)
4384 nTmp
-= (pMasterRow
->Frm().*fnRect
->fnGetHeight
)();
4385 pMasterRow
= pMasterRow
->GetNext();
4390 // Do not consider rotated cells:
4391 if ( ( 0 != pLow
->IsVertical() ) == ( 0 != bVert
) && nTmp
> nHeight
)
4394 pLow
= static_cast<const SwCellFrm
*>(pLow
->GetNext());
4396 if ( rSz
.GetHeightSizeType() == ATT_MIN_SIZE
&& !_pRow
->IsRowSpanLine() )
4397 nHeight
= Max( nHeight
, rSz
.GetHeight() );
4401 // --> collapsing borders FME 2005-05-27 #i29550#
4403 // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
4404 USHORT
lcl_GetTopSpace( const SwRowFrm
& rRow
)
4406 USHORT nTopSpace
= 0;
4407 for ( SwCellFrm
* pCurrLower
= (SwCellFrm
*)rRow
.Lower(); pCurrLower
;
4408 pCurrLower
= (SwCellFrm
*)pCurrLower
->GetNext() )
4410 USHORT nTmpTopSpace
= 0;
4411 if ( pCurrLower
->Lower() && pCurrLower
->Lower()->IsRowFrm() )
4412 nTmpTopSpace
= lcl_GetTopSpace( *(SwRowFrm
*)pCurrLower
->Lower() );
4415 const SwAttrSet
& rSet
= ((SwCellFrm
*)pCurrLower
)->GetFmt()->GetAttrSet();
4416 const SvxBoxItem
& rBoxItem
= rSet
.GetBox();
4417 nTmpTopSpace
= rBoxItem
.CalcLineSpace( BOX_LINE_TOP
, sal_True
);
4419 nTopSpace
= Max( nTopSpace
, nTmpTopSpace
);
4424 // Calculate the maximum of TopLineDist over all lowers:
4425 USHORT
lcl_GetTopLineDist( const SwRowFrm
& rRow
)
4427 USHORT nTopLineDist
= 0;
4428 for ( SwCellFrm
* pCurrLower
= (SwCellFrm
*)rRow
.Lower(); pCurrLower
;
4429 pCurrLower
= (SwCellFrm
*)pCurrLower
->GetNext() )
4431 USHORT nTmpTopLineDist
= 0;
4432 if ( pCurrLower
->Lower() && pCurrLower
->Lower()->IsRowFrm() )
4433 nTmpTopLineDist
= lcl_GetTopLineDist( *(SwRowFrm
*)pCurrLower
->Lower() );
4436 const SwAttrSet
& rSet
= ((SwCellFrm
*)pCurrLower
)->GetFmt()->GetAttrSet();
4437 const SvxBoxItem
& rBoxItem
= rSet
.GetBox();
4438 nTmpTopLineDist
= rBoxItem
.GetDistance( BOX_LINE_TOP
);
4440 nTopLineDist
= Max( nTopLineDist
, nTmpTopLineDist
);
4442 return nTopLineDist
;
4445 // Calculate the maximum of BottomLineSize over all lowers:
4446 USHORT
lcl_GetBottomLineSize( const SwRowFrm
& rRow
)
4448 USHORT nBottomLineSize
= 0;
4449 for ( SwCellFrm
* pCurrLower
= (SwCellFrm
*)rRow
.Lower(); pCurrLower
;
4450 pCurrLower
= (SwCellFrm
*)pCurrLower
->GetNext() )
4452 USHORT nTmpBottomLineSize
= 0;
4453 if ( pCurrLower
->Lower() && pCurrLower
->Lower()->IsRowFrm() )
4455 const SwFrm
* pRow
= pCurrLower
->GetLastLower();
4456 nTmpBottomLineSize
= lcl_GetBottomLineSize( *(SwRowFrm
*)pRow
);
4460 const SwAttrSet
& rSet
= ((SwCellFrm
*)pCurrLower
)->GetFmt()->GetAttrSet();
4461 const SvxBoxItem
& rBoxItem
= rSet
.GetBox();
4462 nTmpBottomLineSize
= rBoxItem
.CalcLineSpace( BOX_LINE_BOTTOM
, sal_True
) -
4463 rBoxItem
.GetDistance( BOX_LINE_BOTTOM
);
4465 nBottomLineSize
= Max( nBottomLineSize
, nTmpBottomLineSize
);
4467 return nBottomLineSize
;
4470 // Calculate the maximum of BottomLineDist over all lowers:
4471 USHORT
lcl_GetBottomLineDist( const SwRowFrm
& rRow
)
4473 USHORT nBottomLineDist
= 0;
4474 for ( SwCellFrm
* pCurrLower
= (SwCellFrm
*)rRow
.Lower(); pCurrLower
;
4475 pCurrLower
= (SwCellFrm
*)pCurrLower
->GetNext() )
4477 USHORT nTmpBottomLineDist
= 0;
4478 if ( pCurrLower
->Lower() && pCurrLower
->Lower()->IsRowFrm() )
4480 const SwFrm
* pRow
= pCurrLower
->GetLastLower();
4481 nTmpBottomLineDist
= lcl_GetBottomLineDist( *(SwRowFrm
*)pRow
);
4485 const SwAttrSet
& rSet
= ((SwCellFrm
*)pCurrLower
)->GetFmt()->GetAttrSet();
4486 const SvxBoxItem
& rBoxItem
= rSet
.GetBox();
4487 nTmpBottomLineDist
= rBoxItem
.GetDistance( BOX_LINE_BOTTOM
);
4489 nBottomLineDist
= Max( nBottomLineDist
, nTmpBottomLineDist
);
4491 return nBottomLineDist
;
4496 void SwRowFrm::Format( const SwBorderAttrs
*pAttrs
)
4499 ASSERT( pAttrs
, "SwRowFrm::Format ohne Attrs." );
4501 const BOOL bFix
= bFixSize
;
4503 if ( !bValidPrtArea
)
4505 //RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer
4507 bValidPrtArea
= TRUE
;
4510 aPrt
.Width ( aFrm
.Width() );
4511 aPrt
.Height( aFrm
.Height() );
4513 // --> collapsing borders FME 2005-05-27 #i29550#
4514 // Here we calculate the top-printing area for the lower cell frames
4515 SwTabFrm
* pTabFrm
= FindTabFrm();
4516 if ( pTabFrm
->IsCollapsingBorders() )
4518 const USHORT nTopSpace
= lcl_GetTopSpace( *this );
4519 const USHORT nTopLineDist
= lcl_GetTopLineDist( *this );
4520 const USHORT nBottomLineSize
= lcl_GetBottomLineSize( *this );
4521 const USHORT nBottomLineDist
= lcl_GetBottomLineDist( *this );
4524 const SwRowFrm
* pPreviousRow
= 0;
4526 // --> FME 2004-09-14 #i32456#
4527 // In order to calculate the top printing area for the lower cell
4528 // frames, we have to find the 'previous' row frame and compare
4529 // the bottom values of the 'previous' row with the 'top' values
4530 // of this row. The best way to find the 'previous' row is to
4531 // use the table structure:
4532 const SwTable
* pTable
= pTabFrm
->GetTable();
4533 const SwTableLine
* pPrevTabLine
= 0;
4534 const SwRowFrm
* pTmpRow
= this;
4536 while ( pTmpRow
&& !pPrevTabLine
)
4539 const SwTableLines
& rLines
= pTmpRow
->GetTabLine()->GetUpper() ?
4540 pTmpRow
->GetTabLine()->GetUpper()->GetTabLines() :
4541 pTable
->GetTabLines();
4543 while ( rLines
[ nIdx
] != pTmpRow
->GetTabLine() )
4548 // pTmpRow has a 'previous' row in the table structure:
4549 pPrevTabLine
= rLines
[ nIdx
- 1 ];
4553 // pTmpRow is a first row in the table structue.
4554 // We go up in the table structure:
4555 pTmpRow
= pTmpRow
->GetUpper()->GetUpper() &&
4556 pTmpRow
->GetUpper()->GetUpper()->IsRowFrm() ?
4557 static_cast<const SwRowFrm
*>( pTmpRow
->GetUpper()->GetUpper() ) :
4562 // If we found a 'previous' row, we look for the appropriate row frame:
4565 SwClientIter
aIter( *pPrevTabLine
->GetFrmFmt() );
4567 for ( pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
4569 ASSERT( ((SwFrm
*)pLast
)->IsRowFrm(),
4570 "Non-row frame registered in table line" )
4571 SwRowFrm
* pRow
= (SwRowFrm
*)pLast
;
4572 // --> OD 2004-11-23 #115759# - do *not* take repeated
4573 // headlines, because during split of table it can be
4574 // invalid and thus can't provide correct border values.
4575 if ( pRow
->GetTabLine() == pPrevTabLine
&&
4576 !pRow
->IsRepeatedHeadline() )
4579 pPreviousRow
= pRow
;
4586 USHORT nTopPrtMargin
= nTopSpace
;
4589 const USHORT nTmpPrtMargin
= pPreviousRow
->GetBottomLineSize() + nTopLineDist
;
4590 if ( nTmpPrtMargin
> nTopPrtMargin
)
4591 nTopPrtMargin
= nTmpPrtMargin
;
4594 // table has to be notified if it has to change its lower
4595 // margin due to changes of nBottomLineSize:
4596 if ( !GetNext() && nBottomLineSize
!= GetBottomLineSize() )
4597 pTabFrm
->_InvalidatePrt();
4599 // If there are rows nested inside this row, the nested rows
4600 // may not have been calculated yet. Therefore the
4601 // ::lcl_CalcMinRowHeight( this ) operation later in this
4602 // function cannot consider the correct border values. We
4603 // have to trigger the invalidation of the outer row frame
4605 // Note: If any further invalidations should be necessary, we
4606 // should consider moving the invalidation stuff to the
4607 // appropriate SwNotify object.
4608 if ( GetUpper()->GetUpper()->IsRowFrm() &&
4609 ( nBottomLineDist
!= GetBottomMarginForLowers() ||
4610 nTopPrtMargin
!= GetTopMarginForLowers() ) )
4611 GetUpper()->GetUpper()->_InvalidateSize();
4613 SetBottomMarginForLowers( nBottomLineDist
); // 3.
4614 SetBottomLineSize( nBottomLineSize
); // 4.
4615 SetTopMarginForLowers( nTopPrtMargin
); // 5.
4621 while ( !bValidSize
)
4628 const SwFmtFrmSize
&rFrmSize
= GetFmt()->GetFrmSize();
4629 ASSERT( rFrmSize
.GetSize().Height() > 0, "Hat ihn" );
4632 const SwTwips nDiff
= (Frm().*fnRect
->fnGetHeight
)() -
4633 ( HasFixSize() && !IsRowSpanLine()
4634 ? pAttrs
->GetSize().Height()
4635 // --> OD 2004-10-04 #i26945#
4636 : ::lcl_CalcMinRowHeight( this,
4637 FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
4643 Shrink( nDiff
, FALSE
, TRUE
);
4644 else if ( nDiff
< 0 )
4650 // last row will fill the space in its upper.
4653 //Der letzte fuellt den verbleibenden Raum im Upper aus.
4654 SwTwips nDiff
= (GetUpper()->Prt().*fnRect
->fnGetHeight
)();
4655 SwFrm
*pSibling
= GetUpper()->Lower();
4657 { nDiff
-= (pSibling
->Frm().*fnRect
->fnGetHeight
)();
4658 pSibling
= pSibling
->GetNext();
4659 } while ( pSibling
);
4670 /*************************************************************************
4672 |* SwRowFrm::AdjustCells()
4674 |* Ersterstellung MA 10. Aug. 93
4675 |* Letzte Aenderung MA 16. Dec. 96
4677 |*************************************************************************/
4678 void SwRowFrm::AdjustCells( const SwTwips nHeight
, const BOOL bHeight
)
4680 SwFrm
*pFrm
= Lower();
4683 SwRootFrm
*pRootFrm
= FindRootFrm();
4691 SwCellFrm
* pCellFrm
= static_cast<SwCellFrm
*>(pFrm
);
4694 // Which cells need to be adjusted if the current row changes
4697 // Current frame is a covered frame:
4698 // Set new height for covered cell and adjust master cell:
4699 if ( pCellFrm
->GetTabBox()->getRowSpan() < 1 )
4701 // Set height of current (covered) cell to new line height.
4702 const long nDiff
= nHeight
- (pCellFrm
->Frm().*fnRect
->fnGetHeight
)();
4705 (pCellFrm
->Frm().*fnRect
->fnAddBottom
)( nDiff
);
4706 pCellFrm
->_InvalidatePrt();
4710 SwCellFrm
* pToAdjust
= 0;
4711 SwFrm
* pToAdjustRow
= 0;
4713 // If current frame is covered frame, we still want to adjust the
4714 // height of the cell starting the row span
4715 if ( pCellFrm
->GetLayoutRowSpan() < 1 )
4717 pToAdjust
= const_cast< SwCellFrm
*>(&pCellFrm
->FindStartEndOfRowSpanCell( true, true ));
4718 pToAdjustRow
= pToAdjust
->GetUpper();
4722 pToAdjust
= pCellFrm
;
4723 pToAdjustRow
= this;
4726 // Set height of master cell to height of all lines spanned by this line.
4727 long nRowSpan
= pToAdjust
->GetLayoutRowSpan();
4728 SwTwips nSumRowHeight
= 0;
4729 while ( pToAdjustRow
)
4731 // Use new height for the current row:
4732 nSumRowHeight
+= pToAdjustRow
== this ?
4734 (pToAdjustRow
->Frm().*fnRect
->fnGetHeight
)();
4736 if ( nRowSpan
-- == 1 )
4739 pToAdjustRow
= pToAdjustRow
->GetNext();
4742 if ( pToAdjustRow
&& pToAdjustRow
!= this )
4743 pToAdjustRow
->_InvalidateSize();
4745 const long nDiff
= nSumRowHeight
- (pToAdjust
->Frm().*fnRect
->fnGetHeight
)();
4748 aOldFrm
= pToAdjust
->Frm();
4749 (pToAdjust
->Frm().*fnRect
->fnAddBottom
)( nDiff
);
4750 pNotify
= pToAdjust
;
4755 if( pRootFrm
&& pRootFrm
->IsAnyShellAccessible() && pRootFrm
->GetCurrShell() )
4756 pRootFrm
->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify
, aOldFrm
);
4758 pNotify
->_InvalidatePrt();
4761 pFrm
= pFrm
->GetNext();
4767 pFrm
->_InvalidateAll();
4768 pFrm
= pFrm
->GetNext();
4774 /*************************************************************************
4778 |* Ersterstellung MA 12. Nov. 97
4779 |* Letzte Aenderung MA 12. Nov. 97
4781 |*************************************************************************/
4782 void SwRowFrm::Cut()
4784 SwTabFrm
*pTab
= FindTabFrm();
4785 if ( pTab
&& pTab
->IsFollow() && this == pTab
->GetFirstNonHeadlineRow() )
4787 pTab
->FindMaster()->InvalidatePos();
4792 /*************************************************************************
4794 |* SwRowFrm::GrowFrm()
4796 |* Ersterstellung MA 15. Mar. 93
4797 |* Letzte Aenderung MA 05. May. 94
4799 |*************************************************************************/
4802 SwTwips
SwRowFrm::GrowFrm( SwTwips nDist
, BOOL bTst
, BOOL bInfo
)
4806 SwTabFrm
* pTab
= FindTabFrm();
4809 bool bRestrictTableGrowth
;
4810 bool bHasFollowFlowLine
= pTab
->HasFollowFlowLine();
4812 if ( GetUpper()->IsTabFrm() )
4814 const SwRowFrm
* pFollowFlowRow
= IsInSplitTableRow();
4815 bRestrictTableGrowth
= pFollowFlowRow
&& !pFollowFlowRow
->IsRowSpanLine();
4819 ASSERT( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" )
4820 bRestrictTableGrowth
= GetFollowRow() && bHasFollowFlowLine
;
4821 ASSERT( !bRestrictTableGrowth
|| !GetNext(),
4822 "GetFollowRow for row frame that has a Next" )
4825 // There may still be some space left in my direct upper:
4827 const SwTwips nAdditionalSpace
=
4828 (Frm().*fnRect
->fnBottomDist
)( (GetUpper()->GetUpper()->*fnRect
->fnGetPrtBottom
)() );
4829 if ( bRestrictTableGrowth
&& nAdditionalSpace
> 0 )
4831 nReal
= Min( nAdditionalSpace
, nDist
);
4834 (Frm().*fnRect
->fnAddBottom
)( nReal
);
4838 if ( bRestrictTableGrowth
)
4839 pTab
->SetRestrictTableGrowth( TRUE
);
4842 // Ok, this looks like a hack, indeed, it is a hack.
4843 // If the current row frame is inside another cell frame,
4844 // and the current row frame has no follow, it should not
4845 // be allowed to grow. In fact, setting bRestrictTableGrowth
4846 // to 'false' does not work, because the surrounding RowFrm
4847 // would set this to 'true'.
4848 pTab
->SetFollowFlowLine( FALSE
);
4851 nReal
+= SwLayoutFrm::GrowFrm( nDist
, bTst
, bInfo
);
4853 pTab
->SetRestrictTableGrowth( FALSE
);
4854 pTab
->SetFollowFlowLine( bHasFollowFlowLine
);
4856 //Hoehe der Zellen auf den neuesten Stand bringen.
4860 AdjustCells( (Prt().*fnRectX
->fnGetHeight
)() + nReal
, TRUE
);
4868 /*************************************************************************
4870 |* SwRowFrm::ShrinkFrm()
4872 |* Ersterstellung MA 15. Mar. 93
4873 |* Letzte Aenderung MA 20. Jun. 96
4875 |*************************************************************************/
4876 SwTwips
SwRowFrm::ShrinkFrm( SwTwips nDist
, BOOL bTst
, BOOL bInfo
)
4881 AdjustCells( (Prt().*fnRect
->fnGetHeight
)(), TRUE
);
4885 //bInfo wird ggf. vom SwRowFrm::Format auf TRUE gesetzt, hier muss dann
4886 //entsprechend reagiert werden
4887 const BOOL bShrinkAnyway
= bInfo
;
4889 //Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst.
4890 SwTwips nRealDist
= nDist
;
4892 const SwFmtFrmSize
&rSz
= GetFmt()->GetFrmSize();
4893 SwTwips nMinHeight
= rSz
.GetHeightSizeType() == ATT_MIN_SIZE
?
4897 // Only necessary to calculate minimal row height if height
4898 // of pRow is at least nMinHeight. Otherwise nMinHeight is the
4900 if( nMinHeight
< (Frm().*fnRect
->fnGetHeight
)() )
4902 // --> OD 2004-10-04 #i26945#
4903 ASSERT( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
4904 const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
4906 nMinHeight
= lcl_CalcMinRowHeight( this, bConsiderObjs
);
4909 if ( ((Frm().*fnRect
->fnGetHeight
)() - nRealDist
) < nMinHeight
)
4910 nRealDist
= (Frm().*fnRect
->fnGetHeight
)() - nMinHeight
;
4912 if ( nRealDist
< 0 )
4915 SwTwips nReal
= nRealDist
;
4920 SwTwips nHeight
= (Frm().*fnRect
->fnGetHeight
)();
4921 (Frm().*fnRect
->fnSetHeight
)( nHeight
- nReal
);
4922 if( IsVertical() && !bRev
)
4923 Frm().Pos().X() += nReal
;
4926 SwTwips nTmp
= GetUpper()->Shrink( nReal
, bTst
);
4927 if ( !bShrinkAnyway
&& !GetNext() && nTmp
!= nReal
)
4929 //Der letzte bekommt den Rest im Upper und nimmt deshalb
4930 //ggf. Ruecksichten (sonst: Endlosschleife)
4934 SwTwips nHeight
= (Frm().*fnRect
->fnGetHeight
)();
4935 (Frm().*fnRect
->fnSetHeight
)( nHeight
+ nReal
);
4936 if( IsVertical() && !bRev
)
4937 Frm().Pos().X() -= nReal
;
4943 //Geeignet invalidieren und die Hoehe der Zellen auf den neuesten
4950 GetNext()->_InvalidatePos();
4954 SwTabFrm
*pTab
= FindTabFrm();
4955 if ( !pTab
->IsRebuildLastLine() && pTab
->IsFollow() &&
4956 this == pTab
->GetFirstNonHeadlineRow() )
4958 SwTabFrm
* pMasterTab
= const_cast< SwTabFrm
* >( pTab
->FindMaster() );
4959 pMasterTab
->InvalidatePos();
4962 AdjustCells( (Prt().*fnRect
->fnGetHeight
)() - nReal
, TRUE
);
4967 /*************************************************************************
4969 |* SwRowFrm::IsRowSplitAllowed()
4971 |*************************************************************************/
4972 bool SwRowFrm::IsRowSplitAllowed() const
4974 // Fixed size rows are never allowed to split:
4977 ASSERT( ATT_FIX_SIZE
== GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" )
4981 // Repeated headlines are never allowed to split:
4982 const SwTabFrm
* pTabFrm
= FindTabFrm();
4983 if ( pTabFrm
->GetTable()->GetRowsToRepeat() > 0 &&
4984 pTabFrm
->IsInHeadline( *this ) )
4987 const SwTableLineFmt
* pFrmFmt
= (SwTableLineFmt
*)GetTabLine()->GetFrmFmt();
4988 const SwFmtRowSplit
& rLP
= pFrmFmt
->GetRowSplit();
4989 return 0 != rLP
.GetValue();
4992 /*************************************************************************
4994 |* SwRowFrm::ShouldRowKeepWithNext()
4996 |*************************************************************************/
4997 bool SwRowFrm::ShouldRowKeepWithNext() const
5001 const SwCellFrm
* pCell
= static_cast<const SwCellFrm
*>(Lower());
5002 const SwFrm
* pTxt
= pCell
->Lower();
5004 if ( pTxt
&& pTxt
->IsTxtFrm() )
5006 bRet
= static_cast<const SwTxtFrm
*>(pTxt
)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
5011 /*************************************************************************
5013 |* SwCellFrm::SwCellFrm(), ~SwCellFrm()
5015 |* Ersterstellung MA 09. Mar. 93
5016 |* Letzte Aenderung MA 30. May. 96
5018 |*************************************************************************/
5019 SwCellFrm::SwCellFrm( const SwTableBox
&rBox
, bool bInsertContent
) :
5020 SwLayoutFrm( rBox
.GetFrmFmt() ),
5025 if ( !bInsertContent
)
5028 //Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle
5029 //angelegt, andernfalls muessen Rows vorhanden sein und diese werden
5031 if ( rBox
.GetSttIdx() )
5033 ULONG nIndex
= rBox
.GetSttIdx();
5034 ::_InsertCnt( this, rBox
.GetFrmFmt()->GetDoc(), ++nIndex
);
5038 const SwTableLines
&rLines
= rBox
.GetTabLines();
5039 SwFrm
*pTmpPrev
= 0;
5040 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
5042 SwRowFrm
*pNew
= new SwRowFrm( *rLines
[i
], bInsertContent
);
5043 pNew
->InsertBehind( this, pTmpPrev
);
5049 SwCellFrm::~SwCellFrm()
5051 SwModify
* pMod
= GetFmt();
5054 // At this stage the lower frames aren't destroyed already,
5055 // therfor we have to do a recursive dispose.
5056 SwRootFrm
*pRootFrm
= FindRootFrm();
5057 if( pRootFrm
&& pRootFrm
->IsAnyShellAccessible() &&
5058 pRootFrm
->GetCurrShell() )
5060 pRootFrm
->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True
);
5063 pMod
->Remove( this ); // austragen,
5064 if( !pMod
->GetDepends() )
5065 delete pMod
; // und loeschen
5069 /*************************************************************************
5071 |* SwCellFrm::Format()
5073 |* Ersterstellung MA 09. Mar. 93
5074 |* Letzte Aenderung MA 29. Jan. 98
5076 |*************************************************************************/
5077 BOOL
lcl_ArrangeLowers( SwLayoutFrm
*pLay
, long lYStart
, BOOL bInva
)
5080 SwFrm
*pFrm
= pLay
->Lower();
5084 long nFrmTop
= (pFrm
->Frm().*fnRect
->fnGetTop
)();
5085 if( nFrmTop
!= lYStart
)
5088 const long lDiff
= (*fnRect
->fnYDiff
)( lYStart
, nFrmTop
);
5089 const long lDiffX
= lYStart
- nFrmTop
;
5090 (pFrm
->Frm().*fnRect
->fnSubTop
)( -lDiff
);
5091 (pFrm
->Frm().*fnRect
->fnAddBottom
)( lDiff
);
5092 pFrm
->SetCompletePaint();
5093 if ( !pFrm
->GetNext() )
5094 pFrm
->SetRetouche();
5096 pFrm
->Prepare( PREP_POS_CHGD
);
5097 if ( pFrm
->IsLayoutFrm() && ((SwLayoutFrm
*)pFrm
)->Lower() )
5098 lcl_ArrangeLowers( (SwLayoutFrm
*)pFrm
,
5099 (((SwLayoutFrm
*)pFrm
)->Lower()->Frm().*fnRect
->fnGetTop
)()
5101 if ( pFrm
->GetDrawObjs() )
5103 for ( USHORT i
= 0; i
< pFrm
->GetDrawObjs()->Count(); ++i
)
5105 SwAnchoredObject
* pAnchoredObj
= (*pFrm
->GetDrawObjs())[i
];
5106 // --> OD 2004-10-08 #i26945# - check, if anchored object
5107 // is lower of layout frame by checking, if the anchor
5108 // frame, which contains the anchor position, is a lower
5109 // of the layout frame.
5110 if ( !pLay
->IsAnLower( pAnchoredObj
->GetAnchorFrmContainingAnchPos() ) )
5115 // --> OD 2005-08-08 #i52904# - distinguish between anchored
5116 // objects, whose vertical position depends on its anchor
5117 // frame and whose vertical position is independent
5118 // from its anchor frame.
5119 bool bVertPosDepOnAnchor( true );
5121 SwFmtVertOrient
aVert( pAnchoredObj
->GetFrmFmt().GetVertOrient() );
5122 switch ( aVert
.GetRelationOrient() )
5124 case text::RelOrientation::PAGE_FRAME
:
5125 case text::RelOrientation::PAGE_PRINT_AREA
:
5126 bVertPosDepOnAnchor
= false;
5131 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
5133 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
5135 // OD 2004-05-18 #i28701# - no direct move of objects,
5136 // which are anchored to-paragraph/to-character, if
5137 // the wrapping style influence has to be considered
5138 // on the object positioning.
5139 // --> OD 2005-08-08 #i52904# - no direct move of objects,
5140 // whose vertical position doesn't depend on anchor frame.
5141 const bool bDirectMove
=
5142 WEIT_WECH
!= pFly
->Frm().Top() &&
5143 bVertPosDepOnAnchor
&&
5144 !pFly
->ConsiderObjWrapInfluenceOnObjPos();
5148 (pFly
->Frm().*fnRect
->fnSubTop
)( -lDiff
);
5149 (pFly
->Frm().*fnRect
->fnAddBottom
)( lDiff
);
5150 pFly
->GetVirtDrawObj()->SetRectsDirty();
5151 // --> OD 2004-08-17 - also notify view of <SdrObject>
5152 // instance, which represents the Writer fly frame in
5153 // the drawing layer
5154 pFly
->GetVirtDrawObj()->SetChanged();
5156 // --> OD 2006-10-13 #i58280#
5157 pFly
->InvalidateObjRectWithSpaces();
5161 if ( pFly
->IsFlyInCntFrm() )
5163 static_cast<SwFlyInCntFrm
*>(pFly
)->AddRefOfst( lDiff
);
5164 // --> OD 2004-12-02 #115759# - reset current relative
5165 // position to get re-positioned, if not directly moved.
5168 pAnchoredObj
->SetCurrRelPos( Point( 0, 0 ) );
5172 else if( pFly
->IsAutoPos() )
5174 pFly
->AddLastCharY( lDiff
);
5175 // OD 2004-05-18 #i28701# - follow-up of #i22341#
5176 // <mnLastTopOfLine> has also been adjusted.
5177 pFly
->AddLastTopOfLineY( lDiff
);
5179 // --> OD 2004-11-05 #i26945# - re-registration at
5180 // page frame of anchor frame, if table frame isn't
5181 // a follow table and table frame isn't in its
5182 // rebuild of last line.
5183 const SwTabFrm
* pTabFrm
= pLay
->FindTabFrm();
5184 // --> OD 2004-11-23 #115759#
5185 // - save: check, if table frame is found.
5187 !( pTabFrm
->IsFollow() &&
5188 pTabFrm
->FindMaster()->IsRebuildLastLine() ) &&
5189 pFly
->IsFlyFreeFrm() )
5192 SwPageFrm
* pPageFrm
= pFly
->GetPageFrm();
5193 SwPageFrm
* pPageOfAnchor
= pFrm
->FindPageFrm();
5194 if ( pPageFrm
!= pPageOfAnchor
)
5196 pFly
->InvalidatePos();
5198 pPageFrm
->MoveFly( pFly
, pPageOfAnchor
);
5200 pPageOfAnchor
->AppendFlyToPage( pFly
);
5204 // OD 2004-05-11 #i28701# - Because of the introduction
5205 // of new positionings and alignments (e.g. aligned at
5206 // page area, but anchored at-character), the position
5207 // of the Writer fly frame has to be invalidated.
5208 pFly
->InvalidatePos();
5210 // --> OD 2004-11-04 #i26945# - follow-up of #i3317#
5211 // No arrangement of lowers, if Writer fly frame isn't
5214 ::lcl_ArrangeLowers( pFly
,
5215 (pFly
->*fnRect
->fnGetPrtTop
)(),
5219 pFly
->SetCompletePaint();
5222 else if ( pAnchoredObj
->ISA(SwAnchoredDrawObject
) )
5224 // --> OD 2004-11-05 #i26945#
5225 const SwTabFrm
* pTabFrm
= pLay
->FindTabFrm();
5227 !( pTabFrm
->IsFollow() &&
5228 pTabFrm
->FindMaster()->IsRebuildLastLine() ) &&
5229 !pAnchoredObj
->GetFrmFmt().GetAnchor().GetAnchorId()
5232 SwPageFrm
* pPageFrm
= pAnchoredObj
->GetPageFrm();
5233 SwPageFrm
* pPageOfAnchor
= pFrm
->FindPageFrm();
5234 if ( pPageFrm
!= pPageOfAnchor
)
5236 pAnchoredObj
->InvalidateObjPos();
5239 pPageFrm
->RemoveDrawObjFromPage( *pAnchoredObj
);
5241 pPageOfAnchor
->AppendDrawObjToPage( *pAnchoredObj
);
5244 // --> OD 2004-07-01 #i28701# - adjust last character
5245 // rectangle and last top of line.
5246 pAnchoredObj
->AddLastCharY( lDiff
);
5247 pAnchoredObj
->AddLastTopOfLineY( lDiff
);
5248 // --> OD 2005-08-08 #i52904# - re-introduce direct move
5249 // of drawing objects
5250 const bool bDirectMove
=
5251 static_cast<const SwDrawFrmFmt
&>(pAnchoredObj
->GetFrmFmt()).IsPosAttrSet() &&
5252 bVertPosDepOnAnchor
&&
5253 !pAnchoredObj
->ConsiderObjWrapInfluenceOnObjPos();
5256 SwObjPositioningInProgress
aObjPosInProgress( *pAnchoredObj
);
5259 pAnchoredObj
->DrawObj()->Move( Size( lDiff
, 0 ) );
5263 pAnchoredObj
->DrawObj()->Move( Size( 0, lDiff
) );
5265 // --> OD 2006-10-13 #i58280#
5266 pAnchoredObj
->InvalidateObjRectWithSpaces();
5270 pAnchoredObj
->InvalidateObjPos();
5275 "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
5280 // Columns and cells are ordered horizontal, not vertical
5281 if( !pFrm
->IsColumnFrm() && !pFrm
->IsCellFrm() )
5282 lYStart
= (*fnRect
->fnYInc
)( lYStart
,
5283 (pFrm
->Frm().*fnRect
->fnGetHeight
)() );
5285 // Nowadays, the content inside a cell can flow into the follow table.
5286 // Thus, the cell may only grow up to the end of the environment.
5287 // So the content may have grown, but the cell could not grow.
5288 // Therefore we have to trigger a formatting for the frames, which do
5289 // not fit into the cell anymore:
5290 SwTwips nDistanceToUpperPrtBottom
=
5291 (pFrm
->Frm().*fnRect
->fnBottomDist
)( (pLay
->*fnRect
->fnGetPrtBottom
)());
5292 // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945#
5293 // do *not* consider content inside fly frames, if it's an undersized paragraph.
5294 // --> OD 2004-10-08 #i26945# - consider content inside fly frames
5295 if ( nDistanceToUpperPrtBottom
< 0 &&
5296 ( ( pFrm
->IsInFly() &&
5297 ( !pFrm
->IsTxtFrm() ||
5298 !static_cast<SwTxtFrm
*>(pFrm
)->IsUndersized() ) ) ||
5299 pFrm
->IsInSplitTableRow() ) )
5302 pFrm
->InvalidatePos();
5305 pFrm
= pFrm
->GetNext();
5310 void SwCellFrm::Format( const SwBorderAttrs
*pAttrs
)
5312 ASSERT( pAttrs
, "CellFrm::Format, pAttrs ist 0." );
5313 const SwTabFrm
* pTab
= FindTabFrm();
5316 if ( !bValidPrtArea
)
5318 bValidPrtArea
= TRUE
;
5320 //Position einstellen.
5323 SwTwips nTopSpace
, nBottomSpace
, nLeftSpace
, nRightSpace
;
5324 // --> collapsing borders FME 2005-05-27 #i29550#
5325 if ( pTab
->IsCollapsingBorders() && !Lower()->IsRowFrm() )
5327 const SvxBoxItem
& rBoxItem
= pAttrs
->GetBox();
5328 nLeftSpace
= rBoxItem
.GetDistance( BOX_LINE_LEFT
);
5329 nRightSpace
= rBoxItem
.GetDistance( BOX_LINE_RIGHT
);
5330 nTopSpace
= ((SwRowFrm
*)GetUpper())->GetTopMarginForLowers();
5331 nBottomSpace
= ((SwRowFrm
*)GetUpper())->GetBottomMarginForLowers();
5336 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
5337 nLeftSpace
= pAttrs
->CalcLeft( this );
5338 nRightSpace
= pAttrs
->CalcRight( this );
5339 nTopSpace
= pAttrs
->CalcTop();
5340 nBottomSpace
= pAttrs
->CalcBottom();
5342 (this->*fnRect
->fnSetXMargins
)( nLeftSpace
, nRightSpace
);
5343 (this->*fnRect
->fnSetYMargins
)( nTopSpace
, nBottomSpace
);
5346 // --> OD 2004-10-04 #i26945#
5347 long nRemaining
= GetTabBox()->getRowSpan() >= 1 ?
5348 ::lcl_CalcMinCellHeight( this, pTab
->IsConsiderObjsForMinCellHeight(), pAttrs
) :
5355 //Die VarSize der CellFrms ist immer die Breite.
5356 //Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das
5357 //Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum
5358 //nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf
5359 //Basis des Attributes errechnet, der Wert im Attribut passt zu dem
5360 //gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen
5361 //wurden werden hier Proportional beruecksichtigt.
5362 //Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht
5363 //die Attribute, sonder greift sich einfach den Rest des
5368 const SwTwips nWish
= pTab
->GetFmt()->GetFrmSize().GetWidth();
5369 nWidth
= pAttrs
->GetSize().Width();
5371 ASSERT( nWish
, "Tabelle ohne Breite?" );
5372 ASSERT( nWidth
<= nWish
, "Zelle breiter als Tabelle." );
5373 ASSERT( nWidth
> 0, "Box without width" );
5375 const long nPrtWidth
= (pTab
->Prt().*fnRect
->fnGetWidth
)();
5376 if ( nWish
!= nPrtWidth
)
5378 // Avoid rounding problems, at least for the new table model
5379 if ( pTab
->GetTable()->IsNewModel() )
5381 // 1. sum of widths of cells up to this cell (in model)
5382 const SwTableLine
* pTabLine
= GetTabBox()->GetUpper();
5383 const SwTableBoxes
& rBoxes
= pTabLine
->GetTabBoxes();
5384 const SwTableBox
* pTmpBox
= 0;
5386 SwTwips nSumWidth
= 0;
5390 pTmpBox
= rBoxes
[ i
++ ];
5391 nSumWidth
+= pTmpBox
->GetFrmFmt()->GetFrmSize().GetWidth();
5393 while ( pTmpBox
!= GetTabBox() );
5395 // 2. calculate actual width of cells up to this one
5396 double nTmpWidth
= nSumWidth
;
5397 nTmpWidth
*= nPrtWidth
;
5399 nWidth
= (SwTwips
)nTmpWidth
;
5401 // 3. calculate frame widths of cells up to this one:
5402 const SwFrm
* pTmpCell
= static_cast<const SwLayoutFrm
*>(GetUpper())->Lower();
5403 SwTwips nSumFrameWidths
= 0;
5404 while ( pTmpCell
!= this )
5406 nSumFrameWidths
+= (pTmpCell
->Frm().*fnRect
->fnGetWidth
)();
5407 pTmpCell
= pTmpCell
->GetNext();
5410 nWidth
= nWidth
- nSumFrameWidths
;
5414 // #i12092# use double instead of long,
5415 // otherwise this could lead to overflows
5416 double nTmpWidth
= nWidth
;
5417 nTmpWidth
*= nPrtWidth
;
5419 nWidth
= (SwTwips
)nTmpWidth
;
5425 ASSERT( pAttrs
->GetSize().Width() > 0, "Box without width" );
5426 nWidth
= (GetUpper()->Prt().*fnRect
->fnGetWidth
)();
5427 SwFrm
*pPre
= GetUpper()->Lower();
5428 while ( pPre
!= this )
5430 nWidth
-= (pPre
->Frm().*fnRect
->fnGetWidth
)();
5431 pPre
= pPre
->GetNext();
5434 const long nDiff
= nWidth
- (Frm().*fnRect
->fnGetWidth
)();
5435 if( IsNeighbourFrm() && IsRightToLeft() )
5436 (Frm().*fnRect
->fnSubLeft
)( nDiff
);
5438 (Frm().*fnRect
->fnAddRight
)( nDiff
);
5439 (Prt().*fnRect
->fnAddRight
)( nDiff
);
5441 //Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern
5443 const long nDiffHeight
= nRemaining
- (Frm().*fnRect
->fnGetHeight
)();
5446 if ( nDiffHeight
> 0 )
5448 //Wieder validieren wenn kein Wachstum stattgefunden hat.
5449 //Invalidiert wird durch AdjustCells von der Row.
5450 if ( !Grow( nDiffHeight
) )
5451 bValidSize
= bValidPrtArea
= TRUE
;
5455 //Nur dann invalidiert lassen, wenn tatsaechlich
5456 //geshrinkt wurde; das kann abgelehnt werden, weil alle
5457 //nebeneinanderliegenden Zellen gleichgross sein muessen.
5458 if ( !Shrink( -nDiffHeight
) )
5459 bValidSize
= bValidPrtArea
= TRUE
;
5463 const SwFmtVertOrient
&rOri
= pAttrs
->GetAttrSet().GetVertOrient();
5468 // From now on, all operations are related to the table cell.
5472 if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE
!= rOri
.GetVertOrient() &&
5473 // --> OD 2008-07-16 #158225# no vertical alignment of covered cells
5476 // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode
5477 !(pPg
= FindPageFrm())->HasGrid() )
5480 if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
5482 //ASSERT fuer HTML-Import!
5483 ASSERT( !this, "VAlign an Zelle ohne Inhalt" );
5486 BOOL bVertDir
= TRUE
;
5487 // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping
5488 // style influence is considered on object positioning and
5489 // an object is anchored inside the cell.
5490 const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
) );
5492 //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen.
5493 if ( pPg
->GetSortedObjs() )
5495 SwRect
aRect( Prt() ); aRect
+= Frm().Pos();
5496 for ( USHORT i
= 0; i
< pPg
->GetSortedObjs()->Count(); ++i
)
5498 const SwAnchoredObject
* pAnchoredObj
= (*pPg
->GetSortedObjs())[i
];
5499 SwRect
aTmp( pAnchoredObj
->GetObjRect() );
5500 if ( aTmp
.IsOver( aRect
) )
5502 const SwFrmFmt
& rAnchoredObjFrmFmt
= pAnchoredObj
->GetFrmFmt();
5503 const SwFmtSurround
&rSur
= rAnchoredObjFrmFmt
.GetSurround();
5505 if ( SURROUND_THROUGHT
!= rSur
.GetSurround() )
5507 // frames, which the cell is a lower of, aren't relevant
5508 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
5510 const SwFlyFrm
*pFly
=
5511 static_cast<const SwFlyFrm
*>(pAnchoredObj
);
5512 if ( pFly
->IsAnLower( this ) )
5516 const SwFrm
* pAnch
= pAnchoredObj
->GetAnchorFrm();
5517 // --> OD 2005-03-30 #i43913#
5518 // --> OD 2005-08-08 #i52904# - no vertical alignment,
5519 // if object, anchored inside cell, has temporarly
5520 // consider its wrapping style on object positioning.
5521 // --> FME 2006-02-01 #i58806# - no vertical alignment
5522 // if object does not follow the text flow.
5523 if ( bConsiderWrapOnObjPos
||
5524 !IsAnLower( pAnch
) ||
5525 pAnchoredObj
->IsTmpConsiderWrapInfluence() ||
5526 !rAnchoredObjFrmFmt
.GetFollowTextFlow().GetValue() )
5537 long nPrtHeight
= (Prt().*fnRect
->fnGetHeight
)();
5538 if( ( bVertDir
&& ( nRemaining
-= lcl_CalcTopAndBottomMargin( *this, *pAttrs
) ) < nPrtHeight
) ||
5539 (Lower()->Frm().*fnRect
->fnGetTop
)() != (this->*fnRect
->fnGetPrtTop
)() )
5542 nDiff
= (Prt().*fnRect
->fnGetHeight
)() - nRemaining
;
5547 switch ( rOri
.GetVertOrient() )
5549 case text::VertOrientation::CENTER
: lTopOfst
= nDiff
/ 2; break;
5550 case text::VertOrientation::BOTTOM
: lTopOfst
= nDiff
; break;
5554 long nTmp
= (*fnRect
->fnYInc
)(
5555 (this->*fnRect
->fnGetPrtTop
)(), lTopOfst
);
5556 if ( lcl_ArrangeLowers( this, nTmp
, !bVertDir
) )
5563 //Ist noch eine alte Ausrichtung beruecksichtigt worden?
5564 if ( Lower()->IsCntntFrm() )
5566 const long lYStart
= (this->*fnRect
->fnGetPrtTop
)();
5567 lcl_ArrangeLowers( this, lYStart
, TRUE
);
5572 /*************************************************************************
5574 |* SwCellFrm::Modify()
5576 |* Ersterstellung MA 20. Dec. 96
5577 |* Letzte Aenderung MA 20. Dec. 96
5579 |*************************************************************************/
5581 void SwCellFrm::Modify( SfxPoolItem
* pOld
, SfxPoolItem
* pNew
)
5583 BOOL bAttrSetChg
= pNew
&& RES_ATTRSET_CHG
== pNew
->Which();
5584 const SfxPoolItem
*pItem
= 0;
5587 ((SwAttrSetChg
*)pNew
)->GetChgSet()->GetItemState( RES_VERT_ORIENT
, FALSE
, &pItem
);
5588 else if ( RES_VERT_ORIENT
== pNew
->Which() )
5594 if ( text::VertOrientation::NONE
== ((SwFmtVertOrient
*)pItem
)->GetVertOrient() &&
5595 // OD 04.11.2003 #112910#
5596 Lower() && Lower()->IsCntntFrm() )
5599 const long lYStart
= (this->*fnRect
->fnGetPrtTop
)();
5600 bInva
= lcl_ArrangeLowers( this, lYStart
, FALSE
);
5609 if ( ( bAttrSetChg
&&
5610 SFX_ITEM_SET
== ((SwAttrSetChg
*)pNew
)->GetChgSet()->GetItemState( RES_PROTECT
, FALSE
) ) ||
5611 RES_PROTECT
== pNew
->Which() )
5613 ViewShell
*pSh
= GetShell();
5614 if( pSh
&& pSh
->GetLayout()->IsAnyShellAccessible() )
5615 pSh
->Imp()->InvalidateAccessibleEditableState( sal_True
, this );
5619 SFX_ITEM_SET
== ((SwAttrSetChg
*)pNew
)->GetChgSet()->GetItemState( RES_FRAMEDIR
, FALSE
, &pItem
) )
5621 SetDerivedVert( FALSE
);
5625 // --> collapsing borders FME 2005-05-27 #i29550#
5627 SFX_ITEM_SET
== ((SwAttrSetChg
*)pNew
)->GetChgSet()->GetItemState( RES_BOX
, FALSE
, &pItem
) )
5629 SwFrm
* pTmpUpper
= GetUpper();
5630 while ( pTmpUpper
->GetUpper() && !pTmpUpper
->GetUpper()->IsTabFrm() )
5631 pTmpUpper
= pTmpUpper
->GetUpper();
5633 SwTabFrm
* pTabFrm
= (SwTabFrm
*)pTmpUpper
->GetUpper();
5634 if ( pTabFrm
->IsCollapsingBorders() )
5636 // Invalidate lowers of this and next row:
5637 lcl_InvalidateAllLowersPrt( (SwRowFrm
*)pTmpUpper
);
5638 pTmpUpper
= pTmpUpper
->GetNext();
5640 lcl_InvalidateAllLowersPrt( (SwRowFrm
*)pTmpUpper
);
5642 pTabFrm
->InvalidatePrt();
5647 SwLayoutFrm::Modify( pOld
, pNew
);
5650 /*************************************************************************
5651 |* SwCellFrm::GetLayoutRowSpan() const
5652 |*************************************************************************/
5654 long SwCellFrm::GetLayoutRowSpan() const
5656 long nRet
= GetTabBox()->getRowSpan();
5659 const SwFrm
* pRow
= GetUpper();
5660 const SwTabFrm
* pTab
= static_cast<const SwTabFrm
*>(pRow
->GetUpper());
5662 if ( pTab
&& pTab
->IsFollow() && pRow
== pTab
->GetFirstNonHeadlineRow() )
5668 /*************************************************************************
5670 |* SwCellFrm::Modify()
5672 |* Ersterstellung MA 20. Dec. 96
5673 |* Letzte Aenderung MA 20. Dec. 96
5675 |*************************************************************************/
5679 // Helper functions for repeated headlines:
5683 * SwTabFrm::IsInHeadline( const SwFrm& rFrm )
5685 bool SwTabFrm::IsInHeadline( const SwFrm
& rFrm
) const
5687 ASSERT( IsAnLower( &rFrm
) && rFrm
.IsInTab(),
5688 "SwTabFrm::IsInHeadline called for frame not lower of table" )
5690 const SwFrm
* pTmp
= &rFrm
;
5691 while ( !pTmp
->GetUpper()->IsTabFrm() )
5692 pTmp
= pTmp
->GetUpper();
5694 return GetTable()->IsHeadline( *((SwRowFrm
*)pTmp
)->GetTabLine() );
5698 * SwTabFrm::GetFirstNonHeadlineRow()
5700 * If this is a master table, we can may assume, that there are at least
5701 * nRepeat lines in the table.
5702 * If this is a follow table, there are intermediate states for the table
5703 * layout, e.g., during deletion of rows, which makes it necessary to find
5704 * the first non-headline row by evaluating the headline flag at the row frame.
5706 SwRowFrm
* SwTabFrm::GetFirstNonHeadlineRow() const
5708 SwRowFrm
* pRet
= (SwRowFrm
*)Lower();
5713 while ( pRet
&& pRet
->IsRepeatedHeadline() )
5714 pRet
= (SwRowFrm
*)pRet
->GetNext();
5718 USHORT nRepeat
= GetTable()->GetRowsToRepeat();
5719 while ( pRet
&& nRepeat
> 0 )
5721 pRet
= (SwRowFrm
*)pRet
->GetNext();
5727 return (SwRowFrm
*)pRet
;
5731 * SwTable::IsHeadline()
5733 bool SwTable::IsHeadline( const SwTableLine
& rLine
) const
5735 for ( USHORT i
= 0; i
< GetRowsToRepeat(); ++i
)
5736 if ( GetTabLines()[ i
] == &rLine
)
5742 bool SwTabFrm::IsLayoutSplitAllowed() const
5744 return GetFmt()->GetLayoutSplit().GetValue();
5747 // --> collapsing borders FME 2005-05-27 #i29550#
5749 USHORT
SwTabFrm::GetBottomLineSize() const
5751 ASSERT( IsCollapsingBorders(),
5752 "BottomLineSize only required for collapsing borders" )
5754 ASSERT( Lower(), "Warning! Trying to prevent a crash, please inform FME" )
5756 const SwFrm
* pTmp
= GetLastLower();
5758 // --> FME 2005-12-07 #124755# Try to make code robust:
5759 if ( !pTmp
) return 0;
5762 return static_cast<const SwRowFrm
*>(pTmp
)->GetBottomLineSize();
5765 bool SwTabFrm::IsCollapsingBorders() const
5767 return ((SfxBoolItem
&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS
)).GetValue();
5774 // Local helper function to calculate height of first text row
5776 SwTwips
lcl_CalcHeightOfFirstContentLine( const SwRowFrm
& rSourceLine
)
5778 // Find corresponding split line in master table
5779 const SwTabFrm
* pTab
= rSourceLine
.FindTabFrm();
5781 const SwCellFrm
* pCurrSourceCell
= (SwCellFrm
*)rSourceLine
.Lower();
5784 // 1. Case: rSourceLine is a follow flow line.
5785 // In this case we have to return the minimum of the heights
5786 // of the first lines in rSourceLine.
5788 // 2. Case: rSourceLine is not a follow flow line.
5789 // In this case we have to return the maximum of the heights
5790 // of the first lines in rSourceLine.
5792 bool bIsInFollowFlowLine
= rSourceLine
.IsInFollowFlowRow();
5793 SwTwips nHeight
= bIsInFollowFlowLine
? LONG_MAX
: 0;
5795 while ( pCurrSourceCell
)
5798 // Skip cells which are not responsible for the height of
5799 // the follow flow line:
5800 if ( bIsInFollowFlowLine
&& pCurrSourceCell
->GetLayoutRowSpan() > 1 )
5802 pCurrSourceCell
= (SwCellFrm
*)pCurrSourceCell
->GetNext();
5806 const SwFrm
*pTmp
= pCurrSourceCell
->Lower();
5809 SwTwips nTmpHeight
= USHRT_MAX
;
5810 // --> FME 2004-09-14 #i32456# Consider lower row frames
5811 if ( pTmp
->IsRowFrm() )
5813 const SwRowFrm
* pTmpSourceRow
= (SwRowFrm
*)pCurrSourceCell
->Lower();
5814 nTmpHeight
= lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow
);
5817 if ( pTmp
->IsTabFrm() )
5819 nTmpHeight
= ((SwTabFrm
*)pTmp
)->CalcHeightOfFirstContentLine();
5821 else if ( pTmp
->IsTxtFrm() )
5823 SwTxtFrm
* pTxtFrm
= (SwTxtFrm
*)pTmp
;
5824 pTxtFrm
->GetFormatted();
5825 nTmpHeight
= pTxtFrm
->FirstLineHeight();
5828 if ( USHRT_MAX
!= nTmpHeight
)
5830 const SwCellFrm
* pPrevCell
= pCurrSourceCell
->GetPreviousCell();
5833 // If we are in a split row, there may be some space
5834 // left in the cell frame of the master row.
5835 // We look for the minimum of all first line heights;
5836 SwTwips nReal
= (pPrevCell
->Prt().*fnRect
->fnGetHeight
)();
5837 const SwFrm
* pFrm
= pPrevCell
->Lower();
5838 const SwFrm
* pLast
= pFrm
;
5841 nReal
-= (pFrm
->Frm().*fnRect
->fnGetHeight
)();
5843 pFrm
= pFrm
->GetNext();
5846 // --> FME, OD 2004-07-15 #i26831#, #i26520#
5847 // The additional lower space of the current last.
5848 // --> OD 2004-11-25 #115759# - do *not* consider the
5849 // additional lower space for 'master' text frames
5850 if ( pLast
&& pLast
->IsFlowFrm() &&
5851 ( !pLast
->IsTxtFrm() ||
5852 !static_cast<const SwTxtFrm
*>(pLast
)->GetFollow() ) )
5855 nReal
+= SwFlowFrm::CastFlowFrm(pLast
)->CalcAddLowerSpaceAsLastInTableCell();
5857 // Don't forget the upper space and lower space,
5858 // --> OD 2004-11-25 #115759# - do *not* consider the upper
5859 // and the lower space for follow text frames.
5860 if ( pTmp
->IsFlowFrm() &&
5861 ( !pTmp
->IsTxtFrm() ||
5862 !static_cast<const SwTxtFrm
*>(pTmp
)->IsFollow() ) )
5864 nTmpHeight
+= SwFlowFrm::CastFlowFrm(pTmp
)->CalcUpperSpace( NULL
, pLast
);
5865 nTmpHeight
+= SwFlowFrm::CastFlowFrm(pTmp
)->CalcLowerSpace();
5868 // --> OD 2004-11-25 #115759# - consider additional lower
5869 // space of <pTmp>, if contains only one line.
5870 // In this case it would be the new last text frame, which
5871 // would have no follow and thus would add this space.
5872 if ( pTmp
->IsTxtFrm() &&
5873 const_cast<SwTxtFrm
*>(static_cast<const SwTxtFrm
*>(pTmp
))
5874 ->GetLineCount( STRING_LEN
) == 1 )
5876 nTmpHeight
+= SwFlowFrm::CastFlowFrm(pTmp
)
5877 ->CalcAddLowerSpaceAsLastInTableCell();
5881 nTmpHeight
-= nReal
;
5885 // pFirstRow is not a FollowFlowRow. In this case,
5886 // we look for the maximum of all first line heights:
5887 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pCurrSourceCell
);
5888 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
5889 nTmpHeight
+= rAttrs
.CalcTop() + rAttrs
.CalcBottom();
5890 // --> OD 2004-07-16 #i26250#
5891 // Don't forget the upper space and lower space,
5892 if ( pTmp
->IsFlowFrm() )
5894 nTmpHeight
+= SwFlowFrm::CastFlowFrm(pTmp
)->CalcUpperSpace();
5895 nTmpHeight
+= SwFlowFrm::CastFlowFrm(pTmp
)->CalcLowerSpace();
5901 if ( bIsInFollowFlowLine
)
5904 if ( nTmpHeight
< nHeight
)
5905 nHeight
= nTmpHeight
;
5910 if ( nTmpHeight
> nHeight
&& USHRT_MAX
!= nTmpHeight
)
5911 nHeight
= nTmpHeight
;
5915 pCurrSourceCell
= (SwCellFrm
*)pCurrSourceCell
->GetNext();
5918 return ( LONG_MAX
== nHeight
) ? 0 : nHeight
;
5922 // Function to calculate height of first text row
5924 SwTwips
SwTabFrm::CalcHeightOfFirstContentLine() const
5928 const bool bDontSplit
= !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
5932 // Table is not allowed to split: Take the whole height, that's all
5933 return (Frm().*fnRect
->fnGetHeight
)();
5936 SwRowFrm
* pFirstRow
= 0;
5937 SwTwips nTmpHeight
= 0;
5939 pFirstRow
= GetFirstNonHeadlineRow();
5940 ASSERT( !IsFollow() || pFirstRow
, "FollowTable without Lower" )
5943 if ( pFirstRow
&& pFirstRow
->IsRowSpanLine() && pFirstRow
->GetNext() )
5944 pFirstRow
= static_cast<SwRowFrm
*>(pFirstRow
->GetNext());
5946 // Calculate the height of the headlines:
5947 const USHORT nRepeat
= GetTable()->GetRowsToRepeat();
5948 SwTwips nRepeatHeight
= nRepeat
? lcl_GetHeightOfRows( GetLower(), nRepeat
) : 0;
5950 // Calculate the height of the keeping lines
5951 // (headlines + following keeping lines):
5952 SwTwips nKeepHeight
= nRepeatHeight
;
5953 if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP
) )
5955 USHORT nKeepRows
= nRepeat
;
5957 // Check how many rows want to keep together
5958 while ( pFirstRow
&& pFirstRow
->ShouldRowKeepWithNext() )
5961 pFirstRow
= static_cast<SwRowFrm
*>(pFirstRow
->GetNext());
5964 if ( nKeepRows
> nRepeat
)
5965 nKeepHeight
= lcl_GetHeightOfRows( GetLower(), nKeepRows
);
5968 // For master tables, the height of the headlines + the heigth of the
5969 // keeping lines (if any) has to be considered. For follow tables, we
5970 // only consider the height of the keeping rows without the repeated lines:
5973 nTmpHeight
= nKeepHeight
;
5977 nTmpHeight
= nKeepHeight
- nRepeatHeight
;
5980 // pFirstRow row is the first non-heading row.
5981 // nTmpHeight is the height of the heading row if we are a follow.
5984 const bool bSplittable
= pFirstRow
->IsRowSplitAllowed();
5985 const SwTwips nFirstLineHeight
= (pFirstRow
->Frm().*fnRect
->fnGetHeight
)();
5989 // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
5990 // actually is determined by a lower cell with rowspan = -1. In this case we should not
5991 // just return the height of the first line. Basically we need to get the height of the
5992 // line as it would be on the last page. Since this is quite complicated to calculate,
5993 // we olny calculate the height of the first line.
5994 if ( pFirstRow
->GetPrev() &&
5995 static_cast<SwRowFrm
*>(pFirstRow
->GetPrev())->IsRowSpanLine() )
5997 // Calculate maximum height of all cells with rowspan = 1:
5998 SwTwips nMaxHeight
= 0;
5999 const SwCellFrm
* pLower2
= static_cast<const SwCellFrm
*>(pFirstRow
->Lower());
6002 if ( 1 == pLower2
->GetTabBox()->getRowSpan() )
6004 const SwTwips nCellHeight
= lcl_CalcMinCellHeight( pLower2
, TRUE
);
6005 nMaxHeight
= Max( nCellHeight
, nMaxHeight
);
6007 pLower2
= static_cast<const SwCellFrm
*>(pLower2
->GetNext());
6009 nTmpHeight
+= nMaxHeight
;
6013 nTmpHeight
+= nFirstLineHeight
;
6017 // --> FME 2004-11-18 #118411#
6018 // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
6019 // a formatting of the row frame (via the GetFormatted()). We don't
6020 // want this formatting if the row does not have a height.
6021 else if ( 0 != nFirstLineHeight
)
6024 const bool bOldJoinLock
= IsJoinLocked();
6025 ((SwTabFrm
*)this)->LockJoin();
6026 const SwTwips nHeightOfFirstContentLine
= lcl_CalcHeightOfFirstContentLine( *(SwRowFrm
*)pFirstRow
);
6028 // Consider minimum row height:
6029 const SwFmtFrmSize
&rSz
= static_cast<const SwRowFrm
*>(pFirstRow
)->GetFmt()->GetFrmSize();
6030 const SwTwips nMinRowHeight
= rSz
.GetHeightSizeType() == ATT_MIN_SIZE
?
6031 rSz
.GetHeight() : 0;
6033 nTmpHeight
+= Max( nHeightOfFirstContentLine
, nMinRowHeight
);
6035 if ( !bOldJoinLock
)
6036 ((SwTabFrm
*)this)->UnlockJoin();
6044 // Some more functions for covered/covering cells. This way inclusion of
6045 // SwCellFrm can be avoided
6048 bool SwFrm::IsLeaveUpperAllowed() const
6050 const SwCellFrm
* pThisCell
= dynamic_cast<const SwCellFrm
*>(this);
6051 return pThisCell
&& pThisCell
->GetLayoutRowSpan() > 1;
6054 bool SwFrm::IsCoveredCell() const
6056 const SwCellFrm
* pThisCell
= dynamic_cast<const SwCellFrm
*>(this);
6057 return pThisCell
&& pThisCell
->GetLayoutRowSpan() < 1;
6060 bool SwFrm::IsInCoveredCell() const
6064 const SwFrm
* pThis
= this;
6065 while ( pThis
&& !pThis
->IsCellFrm() )
6066 pThis
= pThis
->GetUpper();
6069 bRet
= pThis
->IsCoveredCell();