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: ssfrm.cxx,v $
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"
35 #include <pagefrm.hxx>
36 #include <rootfrm.hxx>
41 #include <dcontact.hxx>
42 #include <dflyobj.hxx>
44 #include <txtfrm.hxx> // ClearPara()
45 #include <cellfrm.hxx>
46 #include <swtable.hxx>
47 #include <fmtfsize.hxx>
51 #include <ndindex.hxx>
52 #include <frmtool.hxx>
53 #include <pagedesc.hxx>
54 #include <svx/boxitem.hxx>
55 #include <svx/shaditem.hxx>
56 #include <fmtclds.hxx>
58 #include <viewimp.hxx>
60 // OD 2004-05-24 #i28701#
61 #include <sortedobjs.hxx>
64 // No inline cause we need the function pointers
65 long SwFrm::GetTopMargin() const
66 { return Prt().Top(); }
67 long SwFrm::GetBottomMargin() const
68 { return Frm().Height() -Prt().Height() -Prt().Top(); }
69 long SwFrm::GetLeftMargin() const
70 { return Prt().Left(); }
71 long SwFrm::GetRightMargin() const
72 { return Frm().Width() - Prt().Width() - Prt().Left(); }
73 long SwFrm::GetPrtLeft() const
74 { return Frm().Left() + Prt().Left(); }
75 long SwFrm::GetPrtBottom() const
76 { return Frm().Top() + Prt().Height() + Prt().Top(); }
77 long SwFrm::GetPrtRight() const
78 { return Frm().Left() + Prt().Width() + Prt().Left(); }
79 long SwFrm::GetPrtTop() const
80 { return Frm().Top() + Prt().Top(); }
82 BOOL
SwFrm::SetMinLeft( long nDeadline
)
84 SwTwips nDiff
= nDeadline
- Frm().Left();
87 Frm().Left( nDeadline
);
88 Prt().Width( Prt().Width() - nDiff
);
94 BOOL
SwFrm::SetMaxBottom( long nDeadline
)
96 SwTwips nDiff
= Frm().Top() + Frm().Height() - nDeadline
;
99 Frm().Height( Frm().Height() - nDiff
);
100 Prt().Height( Prt().Height() - nDiff
);
106 BOOL
SwFrm::SetMinTop( long nDeadline
)
108 SwTwips nDiff
= nDeadline
- Frm().Top();
111 Frm().Top( nDeadline
);
112 Prt().Height( Prt().Height() - nDiff
);
118 BOOL
SwFrm::SetMaxRight( long nDeadline
)
120 SwTwips nDiff
= Frm().Left() + Frm().Width() - nDeadline
;
123 Frm().Width( Frm().Width() - nDiff
);
124 Prt().Width( Prt().Width() - nDiff
);
130 void SwFrm::MakeBelowPos( const SwFrm
* pUp
, const SwFrm
* pPrv
, BOOL bNotify
)
134 aFrm
.Pos( pPrv
->Frm().Pos() );
135 aFrm
.Pos().Y() += pPrv
->Frm().Height();
139 aFrm
.Pos( pUp
->Frm().Pos() );
140 aFrm
.Pos() += pUp
->Prt().Pos();
146 void SwFrm::MakeUpperPos( const SwFrm
* pUp
, const SwFrm
* pPrv
, BOOL bNotify
)
150 aFrm
.Pos( pPrv
->Frm().Pos() );
151 aFrm
.Pos().Y() -= Frm().Height();
155 aFrm
.Pos( pUp
->Frm().Pos() );
156 aFrm
.Pos() += pUp
->Prt().Pos();
157 aFrm
.Pos().Y() += pUp
->Prt().Height() - aFrm
.Height();
163 void SwFrm::MakeLeftPos( const SwFrm
* pUp
, const SwFrm
* pPrv
, BOOL bNotify
)
167 aFrm
.Pos( pPrv
->Frm().Pos() );
168 aFrm
.Pos().X() -= Frm().Width();
172 aFrm
.Pos( pUp
->Frm().Pos() );
173 aFrm
.Pos() += pUp
->Prt().Pos();
174 aFrm
.Pos().X() += pUp
->Prt().Width() - aFrm
.Width();
180 void SwFrm::MakeRightPos( const SwFrm
* pUp
, const SwFrm
* pPrv
, BOOL bNotify
)
184 aFrm
.Pos( pPrv
->Frm().Pos() );
185 aFrm
.Pos().X() += pPrv
->Frm().Width();
189 aFrm
.Pos( pUp
->Frm().Pos() );
190 aFrm
.Pos() += pUp
->Prt().Pos();
196 void SwFrm::SetTopBottomMargins( long nTop
, long nBot
)
199 Prt().Height( Frm().Height() - nTop
- nBot
);
202 void SwFrm::SetBottomTopMargins( long nBot
, long nTop
)
205 Prt().Height( Frm().Height() - nTop
- nBot
);
208 void SwFrm::SetLeftRightMargins( long nLeft
, long nRight
)
211 Prt().Width( Frm().Width() - nLeft
- nRight
);
214 void SwFrm::SetRightLeftMargins( long nRight
, long nLeft
)
217 Prt().Width( Frm().Width() - nLeft
- nRight
);
220 const USHORT nMinVertCellHeight
= 1135;
222 /*-----------------11.9.2001 11:11------------------
223 * SwFrm::CheckDirChange(..)
224 * checks the layout direction and
225 * invalidates the lower frames rekursivly, if necessary.
226 * --------------------------------------------------*/
228 void SwFrm::CheckDirChange()
230 BOOL bOldVert
= GetVerticalFlag();
231 BOOL bOldRev
= IsReverse();
232 BOOL bOldR2L
= GetRightToLeftFlag();
233 SetInvalidVert( TRUE
);
234 SetInvalidR2L( TRUE
);
235 BOOL bChg
= bOldR2L
!= IsRightToLeft();
236 if( ( IsVertical() != bOldVert
) || bChg
|| IsReverse() != bOldRev
)
241 // set minimum row height for vertical cells in horizontal table:
242 if ( IsCellFrm() && GetUpper() )
244 if ( IsVertical() != GetUpper()->IsVertical() &&
245 ((SwCellFrm
*)this)->GetTabBox()->getRowSpan() == 1 )
247 SwTableLine
* pLine
= (SwTableLine
*)((SwCellFrm
*)this)->GetTabBox()->GetUpper();
248 SwFrmFmt
* pFrmFmt
= pLine
->GetFrmFmt();
249 SwFmtFrmSize
aNew( pFrmFmt
->GetFrmSize() );
250 if ( ATT_FIX_SIZE
!= aNew
.GetHeightSizeType() )
251 aNew
.SetHeightSizeType( ATT_MIN_SIZE
);
252 if ( aNew
.GetHeight() < nMinVertCellHeight
)
253 aNew
.SetHeight( nMinVertCellHeight
);
254 SwDoc
* pDoc
= pFrmFmt
->GetDoc();
255 pDoc
->SetAttr( aNew
, *pLine
->ClaimFrmFmt() );
259 SwFrm
* pFrm
= ((SwLayoutFrm
*)this)->Lower();
260 const SwFmtCol
* pCol
= NULL
;
261 SwLayoutFrm
* pBody
= 0;
266 // If we're a page frame and we change our layout direction,
267 // we have to look for columns and rearrange them.
268 pBody
= ((SwPageFrm
*)this)->FindBodyCont();
269 if(pBody
&& pBody
->Lower() && pBody
->Lower()->IsColumnFrm())
270 pCol
= &((SwPageFrm
*)this)->GetFmt()->GetCol();
272 else if( pFrm
->IsColumnFrm() )
274 pBody
= ((SwLayoutFrm
*)this);
275 const SwFrmFmt
*pFmt
= pBody
->GetFmt();
277 pCol
= &pFmt
->GetCol();
282 pFrm
->CheckDirChange();
283 pFrm
= pFrm
->GetNext();
286 pBody
->AdjustColumns( pCol
, TRUE
);
288 else if( IsTxtFrm() )
289 ((SwTxtFrm
*)this)->Prepare( PREP_CLEAR
);
291 // --> OD 2004-07-27 #i31698# - notify anchored objects also for page frames.
292 // Remove code above for special handling of page frames
295 const SwSortedObjs
*pObjs
= GetDrawObjs();
296 sal_uInt32 nCnt
= pObjs
->Count();
297 for ( sal_uInt32 i
= 0; i
< nCnt
; ++i
)
299 SwAnchoredObject
* pAnchoredObj
= (*pObjs
)[i
];
300 if( pAnchoredObj
->ISA(SwFlyFrm
) )
301 static_cast<SwFlyFrm
*>(pAnchoredObj
)->CheckDirChange();
304 // OD 2004-04-06 #i26791# - direct object
305 // positioning no longer needed. Instead
307 pAnchoredObj
->InvalidateObjPos();
309 // --> OD 2004-07-27 #i31698# - update layout direction of
312 ::setContextWritingMode( pAnchoredObj
->DrawObj(), pAnchoredObj
->GetAnchorFrmContainingAnchPos() );
313 pAnchoredObj
->UpdateLayoutDir();
321 /*-----------------13.9.2002 11:11------------------
322 * SwFrm::GetFrmAnchorPos(..)
323 * returns the position for anchors based on frame direction
324 * --------------------------------------------------*/
325 // OD 2004-03-10 #i11860# - consider lower space and line spacing of
326 // previous frame according to new option 'Use former object positioning'
327 Point
SwFrm::GetFrmAnchorPos( sal_Bool bIgnoreFlysAnchoredAtThisFrame
) const
329 Point aAnchor
= Frm().Pos();
330 if ( IsVertical() || IsRightToLeft() )
331 aAnchor
.X() += Frm().Width();
335 SwTwips nBaseOfstForFly
=
336 ((SwTxtFrm
*)this)->GetBaseOfstForFly( bIgnoreFlysAnchoredAtThisFrame
);
338 aAnchor
.Y() += nBaseOfstForFly
;
340 aAnchor
.X() += nBaseOfstForFly
;
342 // OD 2004-03-10 #i11860# - if option 'Use former object positioning'
343 // is OFF, consider the lower space and the line spacing of the
344 // previous frame and the spacing considered for the page grid
345 const SwTxtFrm
* pThisTxtFrm
= static_cast<const SwTxtFrm
*>(this);
346 const SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid
=
347 pThisTxtFrm
->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
350 aAnchor
.X() -= nUpperSpaceAmountConsideredForPrevFrmAndPageGrid
;
354 aAnchor
.Y() += nUpperSpaceAmountConsideredForPrevFrmAndPageGrid
;
362 /*************************************************************************
366 |* Ersterstellung MA 02. Mar. 94
367 |* Letzte Aenderung MA 25. Jun. 95
369 |*************************************************************************/
374 // accessible objects for fly and cell frames have been already disposed
375 // by the destructors of the derived classes.
376 if( IsAccessibleFrm() && !(IsFlyFrm() || IsCellFrm()) && GetDep() )
378 SwRootFrm
*pRootFrm
= FindRootFrm();
379 if( pRootFrm
&& pRootFrm
->IsAnyShellAccessible() )
381 ViewShell
*pVSh
= pRootFrm
->GetCurrShell();
382 if( pVSh
&& pVSh
->Imp() )
384 ASSERT( !GetLower(), "Lowers should be dispose already!" );
385 pVSh
->Imp()->DisposeAccessibleFrm( this );
392 for ( sal_uInt32 i
= pDrawObjs
->Count(); i
; )
394 SwAnchoredObject
* pAnchoredObj
= (*pDrawObjs
)[--i
];
395 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
399 SdrObject
* pSdrObj
= pAnchoredObj
->DrawObj();
400 SwDrawContact
* pContact
=
401 static_cast<SwDrawContact
*>(pSdrObj
->GetUserCall());
403 "<SwFrm::~SwFrm> - missing contact for drawing object" );
406 pContact
->DisconnectObjFromLayout( pSdrObj
);
415 // JP 15.10.2001: for detection of access to deleted frames
416 pDrawObjs
= (SwSortedObjs
*)0x33333333;
420 /*************************************************************************
422 |* SwLayoutFrm::SetFrmFmt()
423 |* Ersterstellung MA 22. Apr. 93
424 |* Letzte Aenderung MA 02. Nov. 94
426 |*************************************************************************/
429 void SwLayoutFrm::SetFrmFmt( SwFrmFmt
*pNew
)
431 if ( pNew
!= GetFmt() )
433 SwFmtChg
aOldFmt( GetFmt() );
435 SwFmtChg
aNewFmt( pNew
);
436 Modify( &aOldFmt
, &aNewFmt
);
440 /*************************************************************************
441 |* SwCntntFrm::SwCntntFrm()
442 |*************************************************************************/
443 SwCntntFrm::SwCntntFrm( SwCntntNode
* const pCntnt
) :
445 SwFlowFrm( (SwFrm
&)*this )
449 /*************************************************************************
450 |* SwCntntFrm::~SwCntntFrm()
451 |*************************************************************************/
452 SwCntntFrm::~SwCntntFrm()
455 if( 0 != ( pCNd
= PTR_CAST( SwCntntNode
, pRegisteredIn
)) &&
456 !pCNd
->GetDoc()->IsInDtor() )
458 //Bei der Root abmelden wenn ich dort noch im Turbo stehe.
459 SwRootFrm
*pRoot
= FindRootFrm();
460 if( pRoot
&& pRoot
->GetTurbo() == this )
462 pRoot
->DisallowTurbo();
465 if( IsTxtFrm() && ((SwTxtFrm
*)this)->HasFtn() )
467 SwTxtNode
*pTxtNd
= ((SwTxtFrm
*)this)->GetTxtNode();
468 const SwFtnIdxs
&rFtnIdxs
= pCNd
->GetDoc()->GetFtnIdxs();
470 ULONG nIndex
= pCNd
->GetIndex();
471 rFtnIdxs
.SeekEntry( *pTxtNd
, &nPos
);
473 if( nPos
< rFtnIdxs
.Count() )
475 while( nPos
&& pTxtNd
== &(rFtnIdxs
[ nPos
]->GetTxtNode()) )
477 if( nPos
|| pTxtNd
!= &(rFtnIdxs
[ nPos
]->GetTxtNode()) )
480 while( nPos
< rFtnIdxs
.Count() )
482 pTxtFtn
= rFtnIdxs
[ nPos
];
483 if( pTxtFtn
->GetTxtNode().GetIndex() > nIndex
)
492 /*************************************************************************
494 |* SwLayoutFrm::~SwLayoutFrm
496 |* Ersterstellung AK 28-Feb-1991
497 |* Letzte Aenderung MA 11. Jan. 95
499 |*************************************************************************/
502 SwLayoutFrm::~SwLayoutFrm()
504 SwFrm
*pFrm
= pLower
;
506 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
510 //Erst die Objs des Frm vernichten, denn diese koennen sich sonst nach
511 //dem Remove nicht mehr bei der Seite abmelden.
512 //Falls sich einer nicht abmeldet wollen wir nicht gleich
516 while ( pFrm
->GetDrawObjs() && pFrm
->GetDrawObjs()->Count() )
518 nCnt
= pFrm
->GetDrawObjs()->Count();
519 // --> OD 2004-06-30 #i28701#
520 SwAnchoredObject
* pAnchoredObj
= (*pFrm
->GetDrawObjs())[0];
521 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
524 //cmc: flush any accessible events that might be related to
526 if (ViewShell
*pSh
= GetShell())
527 if (SwViewImp
*pImp
= pSh
? pSh
->Imp() : 0)
528 pImp
->FireAccessibleEvents();
534 SdrObject
* pSdrObj
= pAnchoredObj
->DrawObj();
535 SwDrawContact
* pContact
=
536 static_cast<SwDrawContact
*>(pSdrObj
->GetUserCall());
538 "<SwFrm::~SwFrm> - missing contact for drawing object" );
541 pContact
->DisconnectObjFromLayout( pSdrObj
);
544 if ( pFrm
->GetDrawObjs() &&
545 nCnt
== pFrm
->GetDrawObjs()->Count() )
547 pFrm
->GetDrawObjs()->Remove( *pAnchoredObj
);
555 //Fly's vernichten. Der letzte loescht gleich das Array.
557 while ( GetDrawObjs() && GetDrawObjs()->Count() )
559 nCnt
= GetDrawObjs()->Count();
561 // --> OD 2004-06-30 #i28701#
562 SwAnchoredObject
* pAnchoredObj
= (*GetDrawObjs())[0];
563 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
567 SdrObject
* pSdrObj
= pAnchoredObj
->DrawObj();
568 SwDrawContact
* pContact
=
569 static_cast<SwDrawContact
*>(pSdrObj
->GetUserCall());
571 "<SwFrm::~SwFrm> - missing contact for drawing object" );
574 pContact
->DisconnectObjFromLayout( pSdrObj
);
577 if ( GetDrawObjs() && nCnt
== GetDrawObjs()->Count() )
579 GetDrawObjs()->Remove( *pAnchoredObj
);
588 SwFrm
*pNxt
= pFrm
->GetNext();
595 /*************************************************************************
597 |* SwFrm::PaintArea()
599 |* Created AMA 08/22/2000
600 |* Last change AMA 08/23/2000
602 |* The paintarea is the area, in which the content of a frame is allowed
603 |* to be displayed. This region could be larger than the printarea (Prt())
604 |* of the upper, it includes e.g. often the margin of the page.
606 |*************************************************************************/
608 const SwRect
SwFrm::PaintArea() const
611 // Cell frames may not leave their upper:
612 SwRect aRect
= IsRowFrm() ? GetUpper()->Frm() : Frm();
613 const BOOL bVert
= IsVertical();
614 SwRectFn fnRect
= bVert
? fnRectVert
: fnRectHori
;
615 long nRight
= (aRect
.*fnRect
->fnGetRight
)();
616 long nLeft
= (aRect
.*fnRect
->fnGetLeft
)();
617 const SwFrm
* pTmp
= this;
623 if( pTmp
->IsCellFrm() && pTmp
->GetUpper() &&
624 pTmp
->GetUpper()->IsVertical() != pTmp
->IsVertical() )
625 nRowSpan
= ((SwCellFrm
*)pTmp
)->GetTabBox()->getRowSpan();
626 long nTmpRight
= (pTmp
->Frm().*fnRect
->fnGetRight
)();
627 long nTmpLeft
= (pTmp
->Frm().*fnRect
->fnGetLeft
)();
628 if( pTmp
->IsRowFrm() && nRowSpan
> 1 )
630 const SwFrm
* pNxt
= pTmp
;
631 while( --nRowSpan
> 0 && pNxt
->GetNext() )
632 pNxt
= pNxt
->GetNext();
633 if( pTmp
->IsVertical() )
634 nTmpLeft
= (pNxt
->Frm().*fnRect
->fnGetLeft
)();
636 nTmpRight
= (pNxt
->Frm().*fnRect
->fnGetRight
)();
638 ASSERT( pTmp
, "PaintArea lost in time and space" );
639 if( pTmp
->IsPageFrm() || pTmp
->IsFlyFrm() ||
640 pTmp
->IsCellFrm() || pTmp
->IsRowFrm() || //nobody leaves a table!
643 if( bLeft
|| nLeft
< nTmpLeft
)
645 if( bRight
|| nTmpRight
< nRight
)
647 if( pTmp
->IsPageFrm() || pTmp
->IsFlyFrm() || pTmp
->IsRootFrm() )
652 else if( pTmp
->IsColumnFrm() ) // nobody enters neightbour columns
654 BOOL bR2L
= pTmp
->IsRightToLeft();
655 // the first column has _no_ influence to the left range
656 if( bR2L
? pTmp
->GetNext() : pTmp
->GetPrev() )
658 if( bLeft
|| nLeft
< nTmpLeft
)
662 // the last column has _no_ influence to the right range
663 if( bR2L
? pTmp
->GetPrev() : pTmp
->GetNext() )
665 if( bRight
|| nTmpRight
< nRight
)
670 else if( bVert
&& pTmp
->IsBodyFrm() )
672 // Header and footer frames have always horizontal direction and
673 // limit the body frame.
674 // A previous frame of a body frame must be a header,
675 // the next frame of a body frame may be a footnotecontainer or
676 // a footer. The footnotecontainer has the same direction like
678 if( pTmp
->GetPrev() && ( bLeft
|| nLeft
< nTmpLeft
) )
683 if( pTmp
->GetNext() &&
684 ( pTmp
->GetNext()->IsFooterFrm() || pTmp
->GetNext()->GetNext() )
685 && ( bRight
|| nTmpRight
< nRight
) )
691 pTmp
= pTmp
->GetUpper();
693 (aRect
.*fnRect
->fnSetLeft
)( nLeft
);
694 (aRect
.*fnRect
->fnSetRight
)( nRight
);
698 /*************************************************************************
702 |* Created AMA 08/22/2000
703 |* Last change AMA 08/23/2000
705 |* The unionframe is the framearea (Frm()) of a frame expanded by the
706 |* printarea, if there's a negative margin at the left or right side.
708 |*************************************************************************/
710 const SwRect
SwFrm::UnionFrm( BOOL bBorder
) const
712 BOOL bVert
= IsVertical();
713 SwRectFn fnRect
= bVert
? fnRectVert
: fnRectHori
;
714 long nLeft
= (Frm().*fnRect
->fnGetLeft
)();
715 long nWidth
= (Frm().*fnRect
->fnGetWidth
)();
716 long nPrtLeft
= (Prt().*fnRect
->fnGetLeft
)();
717 long nPrtWidth
= (Prt().*fnRect
->fnGetWidth
)();
718 if( nPrtLeft
+ nPrtWidth
> nWidth
)
719 nWidth
= nPrtLeft
+ nPrtWidth
;
725 SwTwips nRight
= nLeft
+ nWidth
;
729 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), this );
730 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
731 const SvxBoxItem
&rBox
= rAttrs
.GetBox();
732 if ( rBox
.GetLeft() )
733 nLeft
-= rBox
.CalcLineSpace( BOX_LINE_LEFT
);
734 else if ( rAttrs
.IsBorderDist() )
735 nLeft
-= rBox
.GetDistance( BOX_LINE_LEFT
) + 1;
736 if ( rBox
.GetRight() )
737 nAdd
+= rBox
.CalcLineSpace( BOX_LINE_RIGHT
);
738 else if ( rAttrs
.IsBorderDist() )
739 nAdd
+= rBox
.GetDistance( BOX_LINE_RIGHT
) + 1;
740 if( rAttrs
.GetShadow().GetLocation() != SVX_SHADOW_NONE
)
742 const SvxShadowItem
&rShadow
= rAttrs
.GetShadow();
743 nLeft
-= rShadow
.CalcShadowSpace( SHADOW_LEFT
);
744 nAdd
+= rShadow
.CalcShadowSpace( SHADOW_RIGHT
);
747 if( IsTxtFrm() && ((SwTxtFrm
*)this)->HasPara() )
749 long nTmp
= ((SwTxtFrm
*)this)->HangingMargin();
753 nWidth
= nRight
+ nAdd
- nLeft
;
754 SwRect
aRet( Frm() );
755 (aRet
.*fnRect
->fnSetPosX
)( nLeft
);
756 (aRet
.*fnRect
->fnSetWidth
)( nWidth
);