summaryrefslogtreecommitdiff
path: root/sw/source/core/layout
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout')
-rw-r--r--sw/source/core/layout/anchoreddrawobject.cxx900
-rw-r--r--sw/source/core/layout/anchoredobject.cxx1062
-rw-r--r--sw/source/core/layout/atrfrm.cxx3299
-rw-r--r--sw/source/core/layout/calcmove.cxx2116
-rw-r--r--sw/source/core/layout/colfrm.cxx478
-rw-r--r--sw/source/core/layout/dbg_lay.cxx868
-rw-r--r--sw/source/core/layout/findfrm.cxx1793
-rw-r--r--sw/source/core/layout/flowfrm.cxx2672
-rw-r--r--sw/source/core/layout/fly.cxx2882
-rw-r--r--sw/source/core/layout/flycnt.cxx1541
-rw-r--r--sw/source/core/layout/flyincnt.cxx338
-rw-r--r--sw/source/core/layout/flylay.cxx1319
-rw-r--r--sw/source/core/layout/flypos.cxx114
-rw-r--r--sw/source/core/layout/frmtool.cxx3604
-rw-r--r--sw/source/core/layout/ftnfrm.cxx3241
-rw-r--r--sw/source/core/layout/hffrm.cxx796
-rw-r--r--sw/source/core/layout/layact.cxx2546
-rw-r--r--sw/source/core/layout/laycache.cxx1338
-rw-r--r--sw/source/core/layout/layhelp.hxx240
-rw-r--r--sw/source/core/layout/layouter.cxx565
-rw-r--r--sw/source/core/layout/movedfwdfrmsbyobjpos.cxx108
-rw-r--r--sw/source/core/layout/newfrm.cxx679
-rw-r--r--sw/source/core/layout/objectformatter.cxx580
-rw-r--r--sw/source/core/layout/objectformatterlayfrm.cxx216
-rw-r--r--sw/source/core/layout/objectformatterlayfrm.hxx84
-rw-r--r--sw/source/core/layout/objectformattertxtfrm.cxx814
-rw-r--r--sw/source/core/layout/objectformattertxtfrm.hxx201
-rw-r--r--sw/source/core/layout/objstmpconsiderwrapinfl.cxx76
-rw-r--r--sw/source/core/layout/objstmpconsiderwrapinfl.hxx50
-rw-r--r--sw/source/core/layout/pagechg.cxx2454
-rw-r--r--sw/source/core/layout/pagedesc.cxx487
-rw-r--r--sw/source/core/layout/pagefrm.src7
-rw-r--r--sw/source/core/layout/paintfrm.cxx6701
-rw-r--r--sw/source/core/layout/sectfrm.cxx2779
-rw-r--r--sw/source/core/layout/softpagebreak.cxx157
-rw-r--r--sw/source/core/layout/sortedobjs.cxx79
-rw-r--r--sw/source/core/layout/sortedobjsimpl.cxx312
-rw-r--r--sw/source/core/layout/ssfrm.cxx814
-rw-r--r--sw/source/core/layout/swselectionlist.cxx96
-rw-r--r--sw/source/core/layout/tabfrm.cxx5798
-rw-r--r--sw/source/core/layout/trvlfrm.cxx2611
-rw-r--r--sw/source/core/layout/unusedf.cxx92
-rw-r--r--sw/source/core/layout/virtoutp.cxx258
-rw-r--r--sw/source/core/layout/virtoutp.hxx77
-rw-r--r--sw/source/core/layout/wsfrm.cxx3967
45 files changed, 61209 insertions, 0 deletions
diff --git a/sw/source/core/layout/anchoreddrawobject.cxx b/sw/source/core/layout/anchoreddrawobject.cxx
new file mode 100644
index 000000000000..c00f394c9a83
--- /dev/null
+++ b/sw/source/core/layout/anchoreddrawobject.cxx
@@ -0,0 +1,900 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <anchoreddrawobject.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <tocntntanchoredobjectposition.hxx>
+#include <tolayoutanchoredobjectposition.hxx>
+#include <frmtool.hxx>
+#include <fmtornt.hxx>
+// --> #i32795#
+#include <txtfrm.hxx>
+// <--
+// --> #i32795#
+// template class <std::vector>
+#include <vector>
+// <--
+
+// --> #i28749#
+#include <com/sun/star/text/PositionLayoutDir.hpp>
+// <--
+// --> #i44559#
+#include <ndtxt.hxx>
+// <--
+
+using namespace ::com::sun::star;
+
+// ============================================================================
+// helper class for correct notification due to the positioning of
+// the anchored drawing object
+// ============================================================================
+class SwPosNotify
+{
+ private:
+ SwAnchoredDrawObject* mpAnchoredDrawObj;
+ SwRect maOldObjRect;
+ SwPageFrm* mpOldPageFrm;
+
+ public:
+ SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj );
+ ~SwPosNotify();
+ // --> OD 2004-08-12 #i32795#
+ Point LastObjPos() const;
+ // <--
+};
+
+SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) :
+ mpAnchoredDrawObj( _pAnchoredDrawObj )
+{
+ maOldObjRect = mpAnchoredDrawObj->GetObjRect();
+ // --> #i35640# - determine correct page frame
+ mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm();
+ // <--
+}
+
+SwPosNotify::~SwPosNotify()
+{
+ if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() )
+ {
+ if( maOldObjRect.HasArea() && mpOldPageFrm )
+ {
+ mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect,
+ PREP_FLY_LEAVE );
+ }
+ SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() );
+ if( aNewObjRect.HasArea() )
+ {
+ // --> #i35640# - determine correct page frame
+ SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm();
+ // <--
+ if( pNewPageFrm )
+ mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect,
+ PREP_FLY_ARRIVE );
+ }
+
+ ::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() );
+
+ // --> #i35640# - additional notify anchor text frame
+ // Needed for negative positioned drawing objects
+ // --> #i43255# - refine condition to avoid unneeded
+ // invalidations: anchored object had to be on the page of its anchor
+ // text frame.
+ if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() &&
+ mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() )
+ {
+ mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+
+ // indicate a restart of the layout process
+ mpAnchoredDrawObj->SetRestartLayoutProcess( true );
+ }
+ else
+ {
+ // lock position
+ mpAnchoredDrawObj->LockPosition();
+
+ if ( !mpAnchoredDrawObj->ConsiderForTextWrap() )
+ {
+ // indicate that object has to be considered for text wrap
+ mpAnchoredDrawObj->SetConsiderForTextWrap( true );
+ // invalidate 'background' in order to allow its 'background'
+ // to wrap around it.
+ mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrm(),
+ mpAnchoredDrawObj->GetObjRectWithSpaces(),
+ PREP_FLY_ARRIVE );
+ // invalidate position of anchor frame in order to force
+ // a re-format of the anchor frame, which also causes a
+ // re-format of the invalid previous frames of the anchor frame.
+ mpAnchoredDrawObj->AnchorFrm()->InvalidatePos();
+ }
+ }
+}
+
+// --> #i32795#
+Point SwPosNotify::LastObjPos() const
+{
+ return maOldObjRect.Pos();
+}
+//<--
+
+// ============================================================================
+// #i32795#
+// helper class for oscillation control on object positioning
+// ============================================================================
+class SwObjPosOscillationControl
+{
+ private:
+ sal_uInt8 mnPosStackSize;
+
+ const SwAnchoredDrawObject* mpAnchoredDrawObj;
+
+ std::vector<Point*> maObjPositions;
+
+ public:
+ SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj );
+ ~SwObjPosOscillationControl();
+
+ bool OscillationDetected();
+};
+
+SwObjPosOscillationControl::SwObjPosOscillationControl(
+ const SwAnchoredDrawObject& _rAnchoredDrawObj )
+ : mnPosStackSize( 20 ),
+ mpAnchoredDrawObj( &_rAnchoredDrawObj )
+{
+}
+
+SwObjPosOscillationControl::~SwObjPosOscillationControl()
+{
+ while ( !maObjPositions.empty() )
+ {
+ Point* pPos = maObjPositions.back();
+ delete pPos;
+
+ maObjPositions.pop_back();
+ }
+}
+
+bool SwObjPosOscillationControl::OscillationDetected()
+{
+ bool bOscillationDetected = false;
+
+ if ( maObjPositions.size() == mnPosStackSize )
+ {
+ // position stack is full -> oscillation
+ bOscillationDetected = true;
+ }
+ else
+ {
+ Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() );
+ for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
+ aObjPosIter != maObjPositions.end();
+ ++aObjPosIter )
+ {
+ if ( *(pNewObjPos) == *(*aObjPosIter) )
+ {
+ // position already occurred -> oscillation
+ bOscillationDetected = true;
+ delete pNewObjPos;
+ break;
+ }
+ }
+ if ( !bOscillationDetected )
+ {
+ maObjPositions.push_back( pNewObjPos );
+ }
+ }
+
+ return bOscillationDetected;
+}
+
+// ============================================================================
+// implementation of class <SwAnchoredDrawObject>
+// ============================================================================
+TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject);
+
+SwAnchoredDrawObject::SwAnchoredDrawObject() :
+ SwAnchoredObject(),
+ mbValidPos( false ),
+ // --> #i34748#
+ mpLastObjRect( 0L ),
+ // <--
+ mbNotYetAttachedToAnchorFrame( true ),
+ // --> #i28749#
+ mbNotYetPositioned( true ),
+ // <--
+ // --> #i62875#
+ mbCaptureAfterLayoutDirChange( false )
+ // <--
+{
+}
+
+SwAnchoredDrawObject::~SwAnchoredDrawObject()
+{
+ // --> follow-up of #i34748#
+ delete mpLastObjRect;
+ // <--
+}
+
+// --> #i62875#
+void SwAnchoredDrawObject::UpdateLayoutDir()
+{
+ SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() );
+
+ SwAnchoredObject::UpdateLayoutDir();
+
+ if ( !NotYetPositioned() &&
+ GetFrmFmt().GetLayoutDir() != nOldLayoutDir &&
+ GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
+ !IsOutsidePage() )
+ {
+ mbCaptureAfterLayoutDirChange = true;
+ }
+}
+// <--
+
+// --> #i62875#
+bool SwAnchoredDrawObject::IsOutsidePage() const
+{
+ bool bOutsidePage( false );
+
+ if ( !NotYetPositioned() && GetPageFrm() )
+ {
+ SwRect aTmpRect( GetObjRect() );
+ bOutsidePage =
+ ( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() );
+ }
+
+ return bOutsidePage;
+}
+// <--
+
+// =============================================================================
+// #i26791# - implementation of pure virtual method declared in
+// base class <SwAnchoredObject>
+// =============================================================================
+void SwAnchoredDrawObject::MakeObjPos()
+{
+ if ( IsPositioningInProgress() )
+ {
+ // nothind to do - positioning already in progress
+ return;
+ }
+
+ if ( mbValidPos )
+ {
+ // nothing to do - position is valid
+ return;
+ }
+
+ // --> #i28749# - anchored drawing object has to be attached
+ // to anchor frame
+ if ( mbNotYetAttachedToAnchorFrame )
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" );
+ return;
+ }
+
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() ));
+
+ // --> #i28749# - if anchored drawing object hasn't been yet
+ // positioned, convert its positioning attributes, if its positioning
+ // attributes are given in horizontal left-to-right layout.
+ // --> #i36010# - Note: horizontal left-to-right layout is made
+ // the default layout direction for <SwDrawFrmFmt> instances. Thus, it has
+ // to be adjusted manually, if no adjustment of the positioning attributes
+ // have to be performed here.
+ // --> #i35635# - additionally move drawing object to the visible layer.
+ if ( mbNotYetPositioned )
+ {
+ // --> #i35635#
+ pDrawContact->MoveObjToVisibleLayer( DrawObj() );
+ // <--
+ // --> perform conversion of positioning
+ // attributes only for 'master' drawing objects
+ // --> #i44334#, #i44681# - check, if positioning
+ // attributes already have been set.
+ if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
+ !static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() )
+ {
+ _SetPositioningAttr();
+ }
+ // <--
+ // -->
+ // - reset internal flag after all needed actions are performed to
+ // avoid callbacks from drawing layer
+ mbNotYetPositioned = false;
+ // <--
+ }
+ // <--
+
+ // indicate that positioning is in progress
+ {
+ SwObjPositioningInProgress aObjPosInProgress( *this );
+
+ // determine relative position of drawing object and set it
+ switch ( pDrawContact->GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ {
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+ // nothing to do, because as-character anchored objects are positioned
+ // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
+ }
+ break;
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ {
+ // --> #i32795# - move intrinsic positioning to
+ // helper method <_MakeObjPosAnchoredAtPara()>
+ _MakeObjPosAnchoredAtPara();
+ }
+ break;
+ case FLY_AT_PAGE:
+ case FLY_AT_FLY:
+ {
+ // --> #i32795# - move intrinsic positioning to
+ // helper method <_MakeObjPosAnchoredAtLayout()>
+ _MakeObjPosAnchoredAtLayout();
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." );
+ }
+ }
+
+ // keep, current object rectangle
+ // --> #i34748# - use new method <SetLastObjRect(..)>
+ SetLastObjRect( GetObjRect().SVRect() );
+ // <--
+
+ // Assure for 'master' drawing object, that it's registered at the correct page.
+ // Perform check not for as-character anchored drawing objects and only if
+ // the anchor frame is valid.
+ if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
+ !pDrawContact->ObjAnchoredAsChar() &&
+ GetAnchorFrm()->IsValid() )
+ {
+ pDrawContact->ChkPage();
+ }
+ }
+
+ // --> #i62875#
+ if ( mbCaptureAfterLayoutDirChange &&
+ GetPageFrm() )
+ {
+ SwRect aPageRect( GetPageFrm()->Frm() );
+ SwRect aObjRect( GetObjRect() );
+ if ( aObjRect.Right() >= aPageRect.Right() + 10 )
+ {
+ Size aSize( aPageRect.Right() - aObjRect.Right(), 0 );
+ DrawObj()->Move( aSize );
+ aObjRect = GetObjRect();
+ }
+
+ if ( aObjRect.Left() + 10 <= aPageRect.Left() )
+ {
+ Size aSize( aPageRect.Left() - aObjRect.Left(), 0 );
+ DrawObj()->Move( aSize );
+ }
+
+ mbCaptureAfterLayoutDirChange = false;
+ }
+ // <--
+}
+
+/** method for the intrinsic positioning of a at-paragraph|at-character
+ anchored drawing object
+
+ #i32795# - helper method for method <MakeObjPos>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara()
+{
+ // --> #i32795# - adopt positioning algorithm from Writer
+ // fly frames, which are anchored at paragraph|at character
+
+ // Determine, if anchor frame can/has to be formatted.
+ // If yes, after each object positioning the anchor frame is formatted.
+ // If after the anchor frame format the object position isn't valid, the
+ // object is positioned again.
+ // --> #i43255# - refine condition: anchor frame format not
+ // allowed, if another anchored object, has to be consider its wrap influence
+ // --> #i50356# - format anchor frame containing the anchor
+ // position. E.g., for at-character anchored object this can be the follow
+ // frame of the anchor frame, which contains the anchor character.
+ const bool bFormatAnchor =
+ !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
+ !ConsiderObjWrapInfluenceOnObjPos() &&
+ !ConsiderObjWrapInfluenceOfOtherObjs();
+ // <--
+
+ if ( bFormatAnchor )
+ {
+ // --> #i50356#
+ GetAnchorFrmContainingAnchPos()->Calc();
+ // <--
+ }
+
+ bool bOscillationDetected = false;
+ SwObjPosOscillationControl aObjPosOscCtrl( *this );
+ // --> #i3317# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to its
+ // overlapping with a previous column.
+ bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
+ // <--
+ do {
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+
+ // --> #i35640# - correct scope for <SwPosNotify> instance
+ {
+ // create instance of <SwPosNotify> for correct notification
+ SwPosNotify aPosNotify( this );
+
+ // determine and set position
+ objectpositioning::SwToCntntAnchoredObjectPosition
+ aObjPositioning( *DrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // get further needed results of the positioning algorithm
+ SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
+ _SetDrawObjAnchor();
+
+ // check for object position oscillation, if position has changed.
+ if ( GetObjRect().Pos() != aPosNotify.LastObjPos() )
+ {
+ bOscillationDetected = aObjPosOscCtrl.OscillationDetected();
+ }
+ }
+ // <--
+ // format anchor frame, if requested.
+ // Note: the format of the anchor frame can cause the object position
+ // to be invalid.
+ if ( bFormatAnchor )
+ {
+ // --> #i50356#
+ GetAnchorFrmContainingAnchPos()->Calc();
+ // <--
+ }
+
+ // --> #i3317#
+ if ( !ConsiderObjWrapInfluenceOnObjPos() &&
+ OverlapsPrevColumn() )
+ {
+ bConsiderWrapInfluenceDueToOverlapPrevCol = true;
+ }
+ // <--
+ } while ( !mbValidPos && !bOscillationDetected &&
+ !bConsiderWrapInfluenceDueToOverlapPrevCol );
+
+ // --> #i3317# - consider a detected oscillation and overlapping
+ // with previous column.
+ // temporarly consider the anchored objects wrapping style influence
+ if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
+ {
+ SetTmpConsiderWrapInfluence( true );
+ SetRestartLayoutProcess( true );
+ }
+ // <--
+}
+
+/** method for the intrinsic positioning of a at-page|at-frame anchored
+ drawing object
+
+ #i32795# - helper method for method <MakeObjPos>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_MakeObjPosAnchoredAtLayout()
+{
+ // indicate that position will be valid after positioning is performed
+ mbValidPos = true;
+
+ // create instance of <SwPosNotify> for correct notification
+ SwPosNotify aPosNotify( this );
+
+ // determine position
+ objectpositioning::SwToLayoutAnchoredObjectPosition
+ aObjPositioning( *DrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // set position
+
+ // --> #i31698#
+ // --> #i34995# - setting anchor position needed for filters,
+ // especially for the xml-filter to the OpenOffice.org file format
+ {
+ const Point aNewAnchorPos =
+ GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ DrawObj()->SetAnchorPos( aNewAnchorPos );
+ // --> #i70122# - missing invalidation
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ // <--
+ SetCurrRelPos( aObjPositioning.GetRelPos() );
+ const SwFrm* pAnchorFrm = GetAnchorFrm();
+ SWRECTFN( pAnchorFrm );
+ const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() );
+ SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
+ SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
+ // <--
+}
+
+void SwAnchoredDrawObject::_SetDrawObjAnchor()
+{
+ // new anchor position
+ // --> #i31698# -
+ Point aNewAnchorPos =
+ GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos();
+ if ( aNewAnchorPos != aCurrAnchorPos )
+ {
+ // determine movement to be applied after setting the new anchor position
+ Size aMove( aCurrAnchorPos.X() - aNewAnchorPos.X(),
+ aCurrAnchorPos.Y() - aNewAnchorPos.Y() );
+ // set new anchor position
+ DrawObj()->SetAnchorPos( aNewAnchorPos );
+ // correct object position, caused by setting new anchor position
+ DrawObj()->Move( aMove );
+ // --> #i70122# - missing invalidation
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+/** method to invalidate the given page frame
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm )
+{
+ if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() )
+ {
+ if ( _pPageFrm->GetUpper() )
+ {
+ // --> #i35007# - correct invalidation for as-character
+ // anchored objects.
+ if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR )
+ {
+ _pPageFrm->InvalidateFlyInCnt();
+ }
+ else
+ {
+ _pPageFrm->InvalidateFlyLayout();
+ }
+ // <--
+
+ SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper());
+ pRootFrm->DisallowTurbo();
+ if ( pRootFrm->GetTurbo() )
+ {
+ const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo();
+ pRootFrm->ResetTurbo();
+ pTmpFrm->InvalidatePage();
+ }
+ pRootFrm->SetIdleFlags();
+ }
+ }
+}
+
+void SwAnchoredDrawObject::InvalidateObjPos()
+{
+ // --> #i28701# - check, if invalidation is allowed
+ if ( mbValidPos &&
+ InvalidationOfPosAllowed() )
+ {
+ mbValidPos = false;
+ // --> #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( GetAnchorFrm() )
+ {
+ // --> #118547# - notify anchor frame of as-character
+ // anchored object, because its positioned by the format of its anchor frame.
+ // --> #i44559# - assure, that text hint is already
+ // existing in the text frame
+ if ( GetAnchorFrm()->ISA(SwTxtFrm) &&
+ (GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
+ if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() &&
+ pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN )
+ {
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
+ }
+ }
+ // <--
+
+ SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm();
+ _InvalidatePage( pPageFrm );
+
+ // --> #i32270# - also invalidate page frame, at which the
+ // drawing object is registered at.
+ SwPageFrm* pPageFrmRegisteredAt = GetPageFrm();
+ if ( pPageFrmRegisteredAt &&
+ pPageFrmRegisteredAt != pPageFrm )
+ {
+ _InvalidatePage( pPageFrmRegisteredAt );
+ }
+ // <--
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor &&
+ pPageFrmOfAnchor != pPageFrm &&
+ pPageFrmOfAnchor != pPageFrmRegisteredAt )
+ // <--
+ {
+ _InvalidatePage( pPageFrmOfAnchor );
+ }
+ }
+ // <--
+ }
+}
+
+SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt()
+{
+ OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
+ "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
+ return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
+}
+const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const
+{
+ OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
+ "<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
+ return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
+}
+
+const SwRect SwAnchoredDrawObject::GetObjRect() const
+{
+ // use geometry of drawing object
+ //return GetDrawObj()->GetCurrentBoundRect();
+ return GetDrawObj()->GetSnapRect();
+}
+
+// --> #i70122#
+const SwRect SwAnchoredDrawObject::GetObjBoundRect() const
+{
+ return GetDrawObj()->GetCurrentBoundRect();
+}
+// <--
+
+// --> #i68520#
+bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop )
+{
+ SwTwips nDiff = _nTop - GetObjRect().Top();
+ DrawObj()->Move( Size( 0, nDiff ) );
+
+ return nDiff != 0;
+}
+bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft )
+{
+ SwTwips nDiff = _nLeft - GetObjRect().Left();
+ DrawObj()->Move( Size( nDiff, 0 ) );
+
+ return nDiff != 0;
+}
+// <--
+
+/** adjust positioning and alignment attributes for new anchor frame
+
+ #i33313# - add second optional parameter <_pNewObjRect>
+
+ @author OD
+*/
+void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm,
+ const SwRect* _pNewObjRect )
+{
+ SwTwips nHoriRelPos = 0;
+ SwTwips nVertRelPos = 0;
+ const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
+ // --> #i33313#
+ const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() );
+ // <--
+ const bool bVert = _pNewAnchorFrm->IsVertical();
+ const bool bR2L = _pNewAnchorFrm->IsRightToLeft();
+ if ( bVert )
+ {
+ nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
+ nVertRelPos = aAnchorPos.X() - aObjRect.Right();
+ }
+ else if ( bR2L )
+ {
+ nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+ else
+ {
+ nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
+ nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
+ }
+
+ GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
+ GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
+}
+
+// --> #i34748# - change return type
+const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const
+{
+ return mpLastObjRect;
+}
+// <--
+
+// --> #i34748# - change return type.
+// If member <mpLastObjRect> is NULL, create one.
+void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect )
+{
+ if ( !mpLastObjRect )
+ {
+ mpLastObjRect = new Rectangle;
+ }
+ *(mpLastObjRect) = _rNewLastRect;
+}
+// <--
+
+void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
+{
+ // --> #i31698#
+ SwAnchoredObject::ObjectAttachedToAnchorFrame();
+ // <--
+
+ if ( mbNotYetAttachedToAnchorFrame )
+ {
+ mbNotYetAttachedToAnchorFrame = false;
+ }
+}
+
+/** method to set positioning attributes
+
+ #i35798#
+ During load the positioning attributes aren't set.
+ Thus, the positioning attributes are set by the current object geometry.
+ This method is also used for the conversion for drawing objects
+ (not anchored as-character) imported from OpenOffice.org file format
+ once and directly before the first positioning.
+
+ @author OD
+*/
+void SwAnchoredDrawObject::_SetPositioningAttr()
+{
+ SwDrawContact* pDrawContact =
+ static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() ));
+
+ if ( !pDrawContact->ObjAnchoredAsChar() )
+ {
+ SwRect aObjRect( GetObjRect() );
+
+ SwTwips nHoriPos = aObjRect.Left();
+ SwTwips nVertPos = aObjRect.Top();
+ // --> #i44334#, #i44681#
+ // perform conversion only if position is in horizontal-left-to-right-layout.
+ if ( GetFrmFmt().GetPositionLayoutDir() ==
+ text::PositionLayoutDir::PositionInHoriL2R )
+ {
+ SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir();
+ switch ( eLayoutDir )
+ {
+ case SwFrmFmt::HORI_L2R:
+ {
+ // nothing to do
+ }
+ break;
+ case SwFrmFmt::HORI_R2L:
+ {
+ nHoriPos = -aObjRect.Left() - aObjRect.Width();
+ }
+ break;
+ case SwFrmFmt::VERT_R2L:
+ {
+ nHoriPos = aObjRect.Top();
+ nVertPos = -aObjRect.Left() - aObjRect.Width();
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" );
+ }
+ }
+ }
+ // <--
+
+ // --> #i71182#
+ // only change position - do not lose other attributes
+ SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
+ aHori.SetPos( nHoriPos );
+ GetFrmFmt().SetFmtAttr( aHori );
+
+ SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
+
+ aVert.SetPos( nVertPos );
+ GetFrmFmt().SetFmtAttr( aVert );
+ // <--
+
+ // --> #i36010# - set layout direction of the position
+ GetFrmFmt().SetPositionLayoutDir(
+ text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
+ // <--
+ }
+ // --> #i65798# - also for as-character anchored objects
+ // --> #i45952# - indicate that position
+ // attributes are set now.
+ static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet();
+ // <--
+}
+
+void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm,
+ const SwRect& _rRect,
+ PrepareHint _eHint )
+{
+ ::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True );
+}
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredDrawObject::RegisterAtCorrectPage()
+{
+ SwPageFrm* pPageFrm( 0L );
+ if ( GetVertPosOrientFrm() )
+ {
+ pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
+ }
+ if ( pPageFrm && GetPageFrm() != pPageFrm )
+ {
+ if ( GetPageFrm() )
+ GetPageFrm()->RemoveDrawObjFromPage( *this );
+ pPageFrm->AppendDrawObjToPage( *this );
+ }
+}
+
+// =============================================================================
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/anchoredobject.cxx b/sw/source/core/layout/anchoredobject.cxx
new file mode 100644
index 000000000000..d33b6e009753
--- /dev/null
+++ b/sw/source/core/layout/anchoredobject.cxx
@@ -0,0 +1,1062 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <anchoredobject.hxx>
+#include <pam.hxx>
+#include <frame.hxx>
+#include <txtfrm.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+// --> #i28701#
+#include <doc.hxx>
+#include <fmtsrnd.hxx>
+#include <svx/svdobj.hxx>
+#include <dcontact.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <sortedobjs.hxx>
+#include <pagefrm.hxx>
+// <--
+#include <frmatr.hxx>
+// --> #i3317#
+#include <colfrm.hxx>
+// <--
+// --> #i35911#
+#include <layouter.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+// <--
+// ============================================================================
+// --> #i28701# -
+// implementation of helper class <SwObjPositioningInProgress>
+// ============================================================================
+SwObjPositioningInProgress::SwObjPositioningInProgress( SdrObject& _rSdrObj ) :
+ mpAnchoredObj( 0L ),
+ // --> #i52904#
+ mbOldObjPositioningInProgress( false )
+ // <--
+{
+ mpAnchoredObj = ::GetUserCall( &_rSdrObj )->GetAnchoredObj( &_rSdrObj );
+ // --> #i52904#
+ mbOldObjPositioningInProgress = mpAnchoredObj->IsPositioningInProgress();
+ // <--
+ mpAnchoredObj->SetPositioningInProgress( true );
+}
+SwObjPositioningInProgress::SwObjPositioningInProgress( SwAnchoredObject& _rAnchoredObj ) :
+ mpAnchoredObj( &_rAnchoredObj ),
+ // --> #i52904#
+ mbOldObjPositioningInProgress( false )
+ // <--
+{
+ // --> #i52904#
+ mbOldObjPositioningInProgress = mpAnchoredObj->IsPositioningInProgress();
+ // <--
+ mpAnchoredObj->SetPositioningInProgress( true );
+}
+
+SwObjPositioningInProgress::~SwObjPositioningInProgress()
+{
+ if ( mpAnchoredObj )
+ {
+ // --> #i52904#
+ mpAnchoredObj->SetPositioningInProgress( mbOldObjPositioningInProgress );
+ // <--
+ }
+}
+
+// ============================================================================
+
+TYPEINIT0(SwAnchoredObject);
+
+SwAnchoredObject::SwAnchoredObject() :
+ mpDrawObj( 0L ),
+ mpAnchorFrm( 0L ),
+ // --> #i28701#
+ mpPageFrm( 0L ),
+ // <--
+ maRelPos(),
+ maLastCharRect(),
+ mnLastTopOfLine( 0L ),
+ mpVertPosOrientFrm( 0L ),
+ // --> #i28701#
+ mbPositioningInProgress( false ),
+ mbConsiderForTextWrap( false ),
+ mbPositionLocked( false ),
+ // --> #i40147#
+ mbKeepPositionLockedForSection( false ),
+ // <--
+ mbRestartLayoutProcess( false ),
+ // <--
+ // --> #i35911#
+ mbClearedEnvironment( false ),
+ // <--
+ // --> #i3317#
+ mbTmpConsiderWrapInfluence( false ),
+ // <--
+ // --> #i68520#
+ maObjRectWithSpaces(),
+ mbObjRectWithSpacesValid( false ),
+ maLastObjRect()
+ // <--
+{
+}
+
+SwAnchoredObject::~SwAnchoredObject()
+{
+}
+
+// =============================================================================
+// accessors for member <mpDrawObj>
+// =============================================================================
+void SwAnchoredObject::SetDrawObj( SdrObject& _rDrawObj )
+{
+ mpDrawObj = &_rDrawObj;
+}
+
+const SdrObject* SwAnchoredObject::GetDrawObj() const
+{
+ return mpDrawObj;
+}
+
+SdrObject* SwAnchoredObject::DrawObj()
+{
+ return mpDrawObj;
+}
+
+// =============================================================================
+// accessors for member <mpAnchorFrm>
+// =============================================================================
+const SwFrm* SwAnchoredObject::GetAnchorFrm() const
+{
+ return mpAnchorFrm;
+}
+
+SwFrm* SwAnchoredObject::AnchorFrm()
+{
+ return mpAnchorFrm;
+}
+
+void SwAnchoredObject::ChgAnchorFrm( SwFrm* _pNewAnchorFrm )
+{
+ mpAnchorFrm = _pNewAnchorFrm;
+
+ if ( mpAnchorFrm )
+ {
+ ObjectAttachedToAnchorFrame();
+ }
+}
+
+/** determine anchor frame containing the anchor position
+
+ #i26945#
+ the anchor frame, which is determined, is <mpAnchorFrm>
+ for an at-page, at-frame or at-paragraph anchored object
+ and the anchor character frame for an at-character and as-character
+ anchored object.
+
+ @author OD
+*/
+SwFrm* SwAnchoredObject::GetAnchorFrmContainingAnchPos()
+{
+ SwFrm* pAnchorFrmContainingAnchPos = FindAnchorCharFrm();
+ if ( !pAnchorFrmContainingAnchPos )
+ {
+ pAnchorFrmContainingAnchPos = AnchorFrm();
+ }
+
+ return pAnchorFrmContainingAnchPos;
+}
+
+// =============================================================================
+// #i28701# accessors for member <mpPageFrm>
+// =============================================================================
+SwPageFrm* SwAnchoredObject::GetPageFrm()
+{
+ return mpPageFrm;
+}
+
+const SwPageFrm* SwAnchoredObject::GetPageFrm() const
+{
+ return mpPageFrm;
+}
+
+void SwAnchoredObject::SetPageFrm( SwPageFrm* _pNewPageFrm )
+{
+ if ( mpPageFrm != _pNewPageFrm )
+ {
+ // clear member, which denotes the layout frame at which the vertical
+ // position is oriented at, if it doesn't fit to the new page frame.
+ if ( GetVertPosOrientFrm() &&
+ ( !_pNewPageFrm ||
+ _pNewPageFrm != GetVertPosOrientFrm()->FindPageFrm() ) )
+ {
+ ClearVertPosOrientFrm();
+ }
+
+ // assign new page frame
+ mpPageFrm = _pNewPageFrm;
+ }
+}
+
+// =============================================================================
+// accessors for member <maLastCharRect>
+// =============================================================================
+const SwRect& SwAnchoredObject::GetLastCharRect() const
+{
+ return maLastCharRect;
+}
+
+SwTwips SwAnchoredObject::GetRelCharX( const SwFrm* pFrm ) const
+{
+ return maLastCharRect.Left() - pFrm->Frm().Left();
+}
+
+SwTwips SwAnchoredObject::GetRelCharY( const SwFrm* pFrm ) const
+{
+ return maLastCharRect.Bottom() - pFrm->Frm().Top();
+}
+
+void SwAnchoredObject::AddLastCharY( long nDiff )
+{
+ maLastCharRect.Pos().Y() += nDiff;
+}
+
+void SwAnchoredObject::ResetLastCharRectHeight()
+{
+ maLastCharRect.Height( 0 );
+}
+// =============================================================================
+// accessors for member <mpVertPosOrientFrm>
+// =============================================================================
+void SwAnchoredObject::SetVertPosOrientFrm( const SwLayoutFrm& _rVertPosOrientFrm )
+{
+ mpVertPosOrientFrm = &_rVertPosOrientFrm;
+
+ // --> OD 2004-07-02 #i28701# - take over functionality of deleted method
+ // <SwFlyAtCntFrm::AssertPage()>: assure for at-paragraph and at-character
+ // an anchored object, that it is registered at the correct page frame
+ RegisterAtCorrectPage();
+}
+
+// =============================================================================
+// accessors for member <mnLastTopOfLine>
+// =============================================================================
+SwTwips SwAnchoredObject::GetLastTopOfLine() const
+{
+ return mnLastTopOfLine;
+}
+
+// #i28701# - follow-up of #i22341#
+void SwAnchoredObject::AddLastTopOfLineY( SwTwips _nDiff )
+{
+ mnLastTopOfLine += _nDiff;
+}
+
+/** check anchor character rectangle and top of line
+
+ #i26791
+ For to-character anchored Writer fly frames the members <maLastCharRect>
+ and <maLastTopOfLine> are updated. These are checked for change and
+ depending on the applied positioning, it's decided, if the Writer fly
+ frame has to be invalidated.
+
+ add parameter <_bCheckForParaPorInf>, default value <true>
+
+ @author OD
+*/
+void SwAnchoredObject::CheckCharRectAndTopOfLine(
+ const bool _bCheckForParaPorInf )
+{
+ if ( GetAnchorFrm() &&
+ GetAnchorFrm()->IsTxtFrm() )
+ {
+ const SwFmtAnchor& rAnch = GetFrmFmt().GetAnchor();
+ if ( (rAnch.GetAnchorId() == FLY_AT_CHAR) &&
+ rAnch.GetCntntAnchor() )
+ {
+ // --> if requested, assure that anchor frame,
+ // which contains the anchor character, has a paragraph portion information.
+ // The paragraph portion information is needed to determine the
+ // anchor character rectangle respectively the top of the line.
+ // Thus, a format of this frame is avoided to determine the
+ // paragraph portion information.
+ // --> #i26945# - use new method <FindAnchorCharFrm()>
+ const SwTxtFrm& aAnchorCharFrm = *(FindAnchorCharFrm());
+ // <--
+ if ( !_bCheckForParaPorInf || aAnchorCharFrm.HasPara() )
+ {
+ _CheckCharRect( rAnch, aAnchorCharFrm );
+ _CheckTopOfLine( rAnch, aAnchorCharFrm );
+ }
+ // <--
+ }
+ }
+}
+
+/** check anchor character rectangle
+
+ #i22341#
+ helper method for method <CheckCharRectAndTopOfLine()>
+ For to-character anchored Writer fly frames the member <maLastCharRect>
+ is updated. This is checked for change and depending on the applied
+ positioning, it's decided, if the Writer fly frame has to be invalidated.
+
+ improvement - add second parameter <_rAnchorCharFrm>
+
+ @author OD
+*/
+void SwAnchoredObject::_CheckCharRect( const SwFmtAnchor& _rAnch,
+ const SwTxtFrm& _rAnchorCharFrm )
+{
+ // determine rectangle of anchor character. If not exist, abort operation
+ SwRect aCharRect;
+ if ( !_rAnchorCharFrm.GetAutoPos( aCharRect, *_rAnch.GetCntntAnchor() ) )
+ {
+ return;
+ }
+ // check, if anchor character rectangle has changed
+ if ( aCharRect != maLastCharRect )
+ {
+ // check positioning and alignment for invalidation of position
+ {
+ SWRECTFN( (&_rAnchorCharFrm) );
+ // determine positioning and alignment
+ SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
+ SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
+ // check for anchor character rectangle changes for certain
+ // positionings and alignments
+ // add condition to invalidate position,
+ // if vertical aligned at frame/page area and vertical position
+ // of anchor character has changed.
+ const sal_Int16 eVertRelOrient = aVert.GetRelationOrient();
+ if ( ( aHori.GetRelationOrient() == text::RelOrientation::CHAR &&
+ (aCharRect.*fnRect->fnGetLeft)() !=
+ (maLastCharRect.*fnRect->fnGetLeft)() ) ||
+ ( eVertRelOrient == text::RelOrientation::CHAR &&
+ ( (aCharRect.*fnRect->fnGetTop)() !=
+ (maLastCharRect.*fnRect->fnGetTop)() ||
+ (aCharRect.*fnRect->fnGetHeight)() !=
+ (maLastCharRect.*fnRect->fnGetHeight)() ) ) ||
+ ( ( ( eVertRelOrient == text::RelOrientation::FRAME ) ||
+ ( eVertRelOrient == text::RelOrientation::PRINT_AREA ) ||
+ ( eVertRelOrient == text::RelOrientation::PAGE_FRAME ) ||
+ ( eVertRelOrient == text::RelOrientation::PAGE_PRINT_AREA ) ) &&
+ ( (aCharRect.*fnRect->fnGetTop)() !=
+ (maLastCharRect.*fnRect->fnGetTop)() ) ) )
+ {
+ // --> #i26945#, #i35911# - unlock position of
+ // anchored object, if it isn't registered at the page,
+ // where its anchor character frame is on.
+ if ( GetPageFrm() != _rAnchorCharFrm.FindPageFrm() )
+ {
+ UnlockPosition();
+ }
+ // <--
+ InvalidateObjPos();
+ }
+ }
+ // keep new anchor character rectangle
+ maLastCharRect = aCharRect;
+ }
+}
+
+/** check top of line
+
+ #i22341#
+ helper method for method <CheckCharRectAndTopOfLine()>
+ For to-character anchored Writer fly frames the member <mnLastTopOfLine>
+ is updated. This is checked for change and depending on the applied
+ positioning, it's decided, if the Writer fly frame has to be invalidated.
+
+ improvement - add second parameter <_rAnchorCharFrm>
+
+ @author OD
+*/
+void SwAnchoredObject::_CheckTopOfLine( const SwFmtAnchor& _rAnch,
+ const SwTxtFrm& _rAnchorCharFrm )
+{
+ SwTwips nTopOfLine = 0L;
+ if ( _rAnchorCharFrm.GetTopOfLine( nTopOfLine, *_rAnch.GetCntntAnchor() ) )
+ {
+ if ( nTopOfLine != mnLastTopOfLine )
+ {
+ // check alignment for invalidation of position
+ if ( GetFrmFmt().GetVertOrient().GetRelationOrient() == text::RelOrientation::TEXT_LINE )
+ {
+ // --> #i26945#, #i35911# - unlock position of
+ // anchored object, if it isn't registered at the page,
+ // where its anchor character frame is on.
+ if ( GetPageFrm() != _rAnchorCharFrm.FindPageFrm() )
+ {
+ UnlockPosition();
+ }
+ // <--
+ InvalidateObjPos();
+ }
+ // keep new top of line value
+ mnLastTopOfLine = nTopOfLine;
+ }
+ }
+}
+
+void SwAnchoredObject::ClearCharRectAndTopOfLine()
+{
+ maLastCharRect.Clear();
+ mnLastTopOfLine = 0;
+}
+
+const Point SwAnchoredObject::GetCurrRelPos() const
+{
+ return maRelPos;
+}
+void SwAnchoredObject::SetCurrRelPos( Point _aRelPos )
+{
+ maRelPos = _aRelPos;
+}
+
+void SwAnchoredObject::ObjectAttachedToAnchorFrame()
+{
+ // default behaviour:
+ // update layout direction, the anchored object is assigned to
+ UpdateLayoutDir();
+}
+
+/** method update layout direction the layout direction, the anchored
+ object is in
+
+ #i31698#
+ method has typically to be called, if the anchored object gets its
+ anchor frame assigned.
+
+ @author OD
+*/
+void SwAnchoredObject::UpdateLayoutDir()
+{
+ SwFrmFmt::tLayoutDir nLayoutDir = SwFrmFmt::HORI_L2R;
+ const SwFrm* pAnchorFrm = GetAnchorFrm();
+ if ( pAnchorFrm )
+ {
+ const bool bVert = pAnchorFrm->IsVertical();
+ const bool bR2L = pAnchorFrm->IsRightToLeft();
+ if ( bVert )
+ {
+ nLayoutDir = SwFrmFmt::VERT_R2L;
+ }
+ else if ( bR2L )
+ {
+ nLayoutDir = SwFrmFmt::HORI_R2L;
+ }
+ }
+ GetFrmFmt().SetLayoutDir( nLayoutDir );
+}
+
+/** method to perform necessary invalidations for the positioning of
+ objects, for whose the wrapping style influence has to be considered
+ on the object positioning.
+
+ #i28701#
+
+ @author OD
+*/
+void SwAnchoredObject::InvalidateObjPosForConsiderWrapInfluence(
+ const bool _bNotifyBackgrd )
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ // indicate that object has not to be considered for text wrap
+ SetConsiderForTextWrap( false );
+ // unlock position
+ UnlockPosition();
+ // invalidate position
+ InvalidateObjPos();
+ // invalidate 'background', if requested
+ if ( _bNotifyBackgrd )
+ {
+ NotifyBackground( GetPageFrm(), GetObjRectWithSpaces(), PREP_FLY_LEAVE );
+ }
+ }
+}
+
+/** method to determine, if wrapping style influence of the anchored
+ object has to be considered on the object positioning
+
+ #i28701#
+ Note: result of this method also decides, if the booleans for the
+ layout process are of relevance.
+
+ @author OD
+*/
+bool SwAnchoredObject::ConsiderObjWrapInfluenceOnObjPos() const
+{
+ bool bRet( false );
+
+ const SwFrmFmt& rObjFmt = GetFrmFmt();
+
+ // --> #i3317# - add condition <IsTmpConsiderWrapInfluence()>
+ // --> #i55204#
+ // - correction: wrapping style influence has been considered, if condition
+ // <IsTmpConsiderWrapInfluence()> is hold, regardless of its anchor type
+ // or its wrapping style.
+ if ( IsTmpConsiderWrapInfluence() )
+ {
+ bRet = true;
+ }
+ else if ( rObjFmt.getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ // <--
+ {
+ const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
+ if ( ((rAnchor.GetAnchorId() == FLY_AT_CHAR) ||
+ (rAnchor.GetAnchorId() == FLY_AT_PARA)) &&
+ rObjFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
+ {
+ // --> #i34520# - text also wraps around anchored
+ // objects in the layer Hell - see the text formatting.
+ // Thus, it hasn't to be checked here.
+ bRet = true;
+ // <--
+ }
+ }
+
+ return bRet;
+}
+
+/** method to determine, if other anchored objects, also attached at
+ to the anchor frame, have to consider its wrap influence.
+
+ // --> #i43255#
+
+ @author OD
+*/
+bool SwAnchoredObject::ConsiderObjWrapInfluenceOfOtherObjs() const
+{
+ bool bRet( false );
+
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ if ( pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj != this &&
+ pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// =============================================================================
+// --> #i28701# - accessors to booleans for layout process
+// =============================================================================
+bool SwAnchoredObject::ConsiderForTextWrap() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbConsiderForTextWrap;
+ else
+ return true;
+}
+
+void SwAnchoredObject::SetConsiderForTextWrap( const bool _bConsiderForTextWrap )
+{
+ mbConsiderForTextWrap = _bConsiderForTextWrap;
+}
+
+bool SwAnchoredObject::PositionLocked() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbPositionLocked;
+ else
+ return false;
+}
+
+bool SwAnchoredObject::RestartLayoutProcess() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbRestartLayoutProcess;
+ else
+ return false;
+}
+
+void SwAnchoredObject::SetRestartLayoutProcess( const bool _bRestartLayoutProcess )
+{
+ mbRestartLayoutProcess = _bRestartLayoutProcess;
+}
+
+// --> #i35911#
+bool SwAnchoredObject::ClearedEnvironment() const
+{
+ if ( ConsiderObjWrapInfluenceOnObjPos() )
+ return mbClearedEnvironment;
+ else
+ return false;
+}
+void SwAnchoredObject::SetClearedEnvironment( const bool _bClearedEnvironment )
+{
+ mbClearedEnvironment = _bClearedEnvironment;
+}
+// <--
+
+/** method to determine, if due to anchored object size and wrapping
+ style, its layout environment is cleared.
+
+ #i35911#
+
+ @author OD
+*/
+bool SwAnchoredObject::HasClearedEnvironment() const
+{
+ bool bHasClearedEnvironment( false );
+
+ // --> #i43913# - layout frame, vertical position is orient at, has to be set.
+ OSL_ENSURE( GetVertPosOrientFrm(),
+ "<SwAnchoredObject::HasClearedEnvironment()> - layout frame missing, at which the vertical position is oriented at." );
+ if ( GetVertPosOrientFrm() &&
+ GetAnchorFrm()->IsTxtFrm() &&
+ !static_cast<const SwTxtFrm*>(GetAnchorFrm())->IsFollow() &&
+ static_cast<const SwTxtFrm*>(GetAnchorFrm())->FindPageFrm()->GetPhyPageNum() >=
+ GetPageFrm()->GetPhyPageNum() )
+ // <--
+ {
+ const SwFrm* pTmpFrm = GetVertPosOrientFrm()->Lower();
+ while ( pTmpFrm && pTmpFrm->IsLayoutFrm() && !pTmpFrm->IsTabFrm() )
+ {
+ pTmpFrm = static_cast<const SwLayoutFrm*>(pTmpFrm)->Lower();
+ }
+ if ( !pTmpFrm )
+ {
+ bHasClearedEnvironment = true;
+ }
+ else if ( pTmpFrm->IsTxtFrm() && !pTmpFrm->GetNext() )
+ {
+ const SwTxtFrm* pTmpTxtFrm = static_cast<const SwTxtFrm*>(pTmpFrm);
+ if ( pTmpTxtFrm->IsUndersized() ||
+ ( pTmpTxtFrm->GetFollow() &&
+ pTmpTxtFrm->GetFollow()->GetOfst() == 0 ) )
+ {
+ bHasClearedEnvironment = true;
+ }
+ }
+ }
+
+ return bHasClearedEnvironment;
+}
+
+/** method to add spacing to object area
+
+ #i28701#
+ #i68520# - return constant reference and use cache
+
+ @author OD
+*/
+const SwRect& SwAnchoredObject::GetObjRectWithSpaces() const
+{
+ if ( mbObjRectWithSpacesValid &&
+ maLastObjRect != GetObjRect() )
+ {
+ OSL_FAIL( "<SwAnchoredObject::GetObjRectWithSpaces> - cache for object rectangle inclusive spaces marked as valid, but it couldn't be. Missing invalidation of cache. Please inform OD." );
+ InvalidateObjRectWithSpaces();
+ }
+ if ( !mbObjRectWithSpacesValid )
+ {
+ // --> #i70122# - correction:
+ // use bounding rectangle of anchored objects.
+// maObjRectWithSpaces = GetObjRect();
+ maObjRectWithSpaces = GetObjBoundRect();
+ // <--
+ const SwFrmFmt& rFmt = GetFrmFmt();
+ const SvxULSpaceItem& rUL = rFmt.GetULSpace();
+ const SvxLRSpaceItem& rLR = rFmt.GetLRSpace();
+ {
+ maObjRectWithSpaces.Top ( Max( maObjRectWithSpaces.Top() - long(rUL.GetUpper()), 0L ));
+ maObjRectWithSpaces.Left( Max( maObjRectWithSpaces.Left()- long(rLR.GetLeft()), 0L ));
+ maObjRectWithSpaces.SSize().Height() += rUL.GetLower();
+ maObjRectWithSpaces.SSize().Width() += rLR.GetRight();
+ }
+
+ mbObjRectWithSpacesValid = true;
+ maLastObjRect = GetObjRect();
+ }
+
+ return maObjRectWithSpaces;
+}
+
+// --> #i68520#
+void SwAnchoredObject::SetObjTop( const SwTwips _nTop)
+{
+ const bool bTopChanged( _SetObjTop( _nTop ) );
+ if ( bTopChanged )
+ {
+ mbObjRectWithSpacesValid = false;
+ }
+}
+
+void SwAnchoredObject::SetObjLeft( const SwTwips _nLeft)
+{
+ const bool bLeftChanged( _SetObjLeft( _nLeft ) );
+ if ( bLeftChanged )
+ {
+ mbObjRectWithSpacesValid = false;
+ }
+}
+// <--
+
+/** method to update anchored object in the <SwSortedObjs> lists
+
+ #i28701#
+ If document compatibility option 'Consider wrapping style influence
+ on object positioning' is ON, additionally all anchored objects
+ at the anchor frame and all following anchored objects on the page
+ frame are invalidated.
+
+ @author OD
+*/
+void SwAnchoredObject::UpdateObjInSortedList()
+{
+ if ( GetAnchorFrm() )
+ {
+ if ( GetFrmFmt().getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ // invalidate position of all anchored objects at anchor frame
+ if ( GetAnchorFrm()->GetDrawObjs() )
+ {
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ // determine start index
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ }
+ }
+ // invalidate all following anchored objects on the page frame
+ if ( GetPageFrm() && GetPageFrm()->GetSortedObjs() )
+ {
+ const SwSortedObjs* pObjs = GetPageFrm()->GetSortedObjs();
+ // determine start index
+ sal_uInt32 i = pObjs->ListPosOf( *this ) + 1;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ }
+ }
+ }
+ // update its position in the sorted object list of its anchor frame
+ AnchorFrm()->GetDrawObjs()->Update( *this );
+ // update its position in the sorted object list of its page frame
+ // note: as-character anchored object aren't registered at a page frame
+ if ( GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR )
+ {
+ GetPageFrm()->GetSortedObjs()->Update( *this );
+ }
+ }
+}
+
+/** method to determine, if invalidation of position is allowed
+
+ #i28701#
+
+ @author OD
+*/
+bool SwAnchoredObject::InvalidationOfPosAllowed() const
+{
+ // --> Check, if page frame layout is in progress,
+ // isn't needed, because of anchored object, whose are moved forward.
+ return !PositionLocked();
+ // <--
+}
+
+/** method to determine the page frame, on which the 'anchor' of
+ the given anchored object is.
+
+ #i28701#
+ #i33751#, #i34060#
+ Adjust meaning of method and thus its name: If the anchored object
+ or its anchor isn't correctly inserted in the layout, no page frame
+ can be found. Thus, the return type changed to be a pointer and can
+ be NULL.
+
+ @author OD
+*/
+SwPageFrm* SwAnchoredObject::FindPageFrmOfAnchor()
+{
+ SwPageFrm* pRetPageFrm = 0L;
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( mpAnchorFrm )
+ {
+ // --> #i26945# - use new method <GetAnchorFrmContainingAnchPos()>
+ pRetPageFrm = GetAnchorFrmContainingAnchPos()->FindPageFrm();
+ // <--
+ }
+
+ return pRetPageFrm;
+}
+
+/** get frame, which contains the anchor character, if the object
+ is anchored at-character or as-character.
+
+ #i26945#
+
+ @author OD
+
+ @return SwTxtFrm*
+ text frame containing the anchor character. It's NULL, if the object
+ isn't anchored at-character resp. as-character.
+*/
+SwTxtFrm* SwAnchoredObject::FindAnchorCharFrm()
+{
+ SwTxtFrm* pAnchorCharFrm( 0L );
+
+ // --> #i44339# - check, if anchor frame exists.
+ if ( mpAnchorFrm )
+ {
+ const SwFmtAnchor& rAnch = GetFrmFmt().GetAnchor();
+ if ((rAnch.GetAnchorId() == FLY_AT_CHAR) ||
+ (rAnch.GetAnchorId() == FLY_AS_CHAR))
+ {
+ pAnchorCharFrm = &(static_cast<SwTxtFrm*>(AnchorFrm())->
+ GetFrmAtOfst( rAnch.GetCntntAnchor()->nContent.GetIndex() ));
+ }
+ }
+ // <--
+
+ return pAnchorCharFrm;
+}
+
+/** method to determine, if a format on the anchored object is possible
+
+ #i28701#
+ A format is possible, if anchored object is in an invisible layer.
+ Note: method is virtual to refine the conditions for the sub-classes.
+
+ @author OD
+*/
+bool SwAnchoredObject::IsFormatPossible() const
+{
+ return GetFrmFmt().GetDoc()->IsVisibleLayerId( GetDrawObj()->GetLayer() );
+}
+
+// --> #i3317#
+void SwAnchoredObject::SetTmpConsiderWrapInfluence( const bool _bTmpConsiderWrapInfluence )
+{
+ mbTmpConsiderWrapInfluence = _bTmpConsiderWrapInfluence;
+ // --> #i35911#
+ if ( mbTmpConsiderWrapInfluence )
+ {
+ SwLayouter::InsertObjForTmpConsiderWrapInfluence( *(GetFrmFmt().GetDoc()),
+ *this );
+ }
+ // <--
+}
+
+bool SwAnchoredObject::IsTmpConsiderWrapInfluence() const
+{
+ return mbTmpConsiderWrapInfluence;
+}
+// <--
+
+void SwAnchoredObject::SetTmpConsiderWrapInfluenceOfOtherObjs( const bool bTmpConsiderWrapInfluence )
+{
+ const SwSortedObjs* pObjs = GetAnchorFrm()->GetDrawObjs();
+ if ( pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj != this )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( bTmpConsiderWrapInfluence );
+ }
+ }
+ }
+}
+
+/** method to determine, if the anchored object is overlapping with a
+ previous column
+
+ #i3317#
+ overlapping with a previous column means, that the object overlaps
+ with a column, which is a previous one of the column its anchor
+ frame is in.
+ Only applied for at-paragraph and at-character anchored objects.
+
+ @author OD
+*/
+bool SwAnchoredObject::OverlapsPrevColumn() const
+{
+ bool bOverlapsPrevColumn( false );
+
+ if ( mpAnchorFrm && mpAnchorFrm->IsTxtFrm() )
+ {
+ const SwFrm* pColFrm = mpAnchorFrm->FindColFrm();
+ if ( pColFrm && pColFrm->GetPrev() )
+ {
+ const SwFrm* pTmpColFrm = pColFrm->GetPrev();
+ SwRect aChkRect;
+ while ( pTmpColFrm )
+ {
+ aChkRect.Union( pTmpColFrm->Frm() );
+ pTmpColFrm = pTmpColFrm->GetPrev();
+ }
+ bOverlapsPrevColumn = GetObjRect().IsOver( aChkRect );
+ }
+ }
+
+ return bOverlapsPrevColumn;
+}
+
+/** method to determine position of anchored object relative to
+ anchor frame
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToAnchorFrm() const
+{
+ Point aRelPos;
+
+ OSL_ENSURE( GetAnchorFrm(),
+ "<SwAnchoredObject::GetRelPosToAnchorFrm()> - missing anchor frame." );
+ aRelPos = GetObjRect().Pos();
+ aRelPos -= GetAnchorFrm()->Frm().Pos();
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ page frame
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+ #i33818# - add parameters <_bFollowTextFlow> and
+ <_obRelToTableCell>
+ If <_bFollowTextFlow> is set and object is anchored inside table,
+ the position relative to the table cell is determined. Output
+ parameter <_obRelToTableCell> reflects this situation
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToPageFrm( const bool _bFollowTextFlow,
+ bool& _obRelToTableCell ) const
+{
+ Point aRelPos;
+ _obRelToTableCell = false;
+
+ OSL_ENSURE( GetAnchorFrm(),
+ "<SwAnchoredObject::GetRelPosToPageFrm()> - missing anchor frame." );
+ OSL_ENSURE( GetAnchorFrm()->FindPageFrm(),
+ "<SwAnchoredObject::GetRelPosToPageFrm()> - missing page frame." );
+
+ aRelPos = GetObjRect().Pos();
+ // --> #i33818# - search for cell frame, if object has to
+ // follow the text flow.
+ const SwFrm* pFrm( 0L );
+ if ( _bFollowTextFlow && !GetAnchorFrm()->IsPageFrm() )
+ {
+ pFrm = GetAnchorFrm()->GetUpper();
+ while ( !pFrm->IsCellFrm() && !pFrm->IsPageFrm() )
+ {
+ pFrm = pFrm->GetUpper();
+ }
+ }
+ else
+ {
+ pFrm = GetAnchorFrm()->FindPageFrm();
+ }
+ if ( pFrm->IsCellFrm() )
+ {
+ aRelPos -= ( pFrm->Frm().Pos() + pFrm->Prt().Pos() );
+ _obRelToTableCell = true;
+ }
+ else
+ {
+ aRelPos -= pFrm->Frm().Pos();
+ }
+ // <--
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ anchor character
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToChar() const
+{
+ Point aRelPos;
+
+ aRelPos = GetObjRect().Pos();
+ aRelPos -= GetLastCharRect().Pos();
+
+ return aRelPos;
+}
+
+/** method to determine position of anchored object relative to
+ top of line
+
+ #i30669#
+ Usage: Needed layout information for WW8 export
+
+ @author OD
+*/
+Point SwAnchoredObject::GetRelPosToLine() const
+{
+ Point aRelPos;
+
+ aRelPos = GetObjRect().Pos();
+ aRelPos.Y() -= GetLastTopOfLine();
+
+ return aRelPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
new file mode 100644
index 000000000000..5d3c7924531e
--- /dev/null
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -0,0 +1,3299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/HorizontalAdjust.hpp>
+#include <com/sun/star/text/DocumentStatistic.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/HoriOrientationFormat.hpp>
+#include <com/sun/star/text/NotePrintMode.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/VertOrientationFormat.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/InvalidTextContentException.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/text/TextGridMode.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <svtools/unoimap.hxx>
+#include <svtools/unoevent.hxx>
+#include <basic/sbxvar.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <unosett.hxx>
+#include <unostyle.hxx>
+#include <fmtclds.hxx>
+#include <fmtornt.hxx>
+#include <fmthdft.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfordr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtftntx.hxx>
+#include <fmteiro.hxx>
+#include <fmturl.hxx>
+#include <fmtcnct.hxx>
+#include <node.hxx>
+#include <section.hxx>
+#include <fmtline.hxx>
+#include <tgrditem.hxx>
+#include <hfspacingitem.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <crsrsh.hxx>
+#include <pam.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <flyfrms.hxx>
+#include <pagedesc.hxx>
+#include <grfatr.hxx>
+#include <ndnotxt.hxx>
+#include <docary.hxx>
+#include <node2lay.hxx>
+#include <fmtclbl.hxx>
+#include <swunohelper.hxx>
+#include <unoframe.hxx>
+#include <unotextbodyhf.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <editeng/brshitem.hxx>
+#include <svtools/grfmgr.hxx>
+#include <cmdid.h>
+#include <unomid.h>
+#include <comcore.hrc>
+#include <svx/svdundo.hxx> // #111827#
+#include <sortedobjs.hxx>
+#include <HandleAnchorNodeChg.hxx>
+#include <svl/cjkoptions.hxx>
+#include <switerator.hxx>
+#include <pagedeschint.hxx>
+
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+SV_IMPL_PTRARR(SwColumns,SwColumn*)
+
+TYPEINIT1(SwFmtVertOrient, SfxPoolItem);
+TYPEINIT1(SwFmtHoriOrient, SfxPoolItem);
+TYPEINIT2(SwFmtHeader, SfxPoolItem, SwClient );
+TYPEINIT2(SwFmtFooter, SfxPoolItem, SwClient );
+TYPEINIT2(SwFmtPageDesc, SfxPoolItem, SwClient );
+TYPEINIT1_AUTOFACTORY(SwFmtLineNumber, SfxPoolItem);
+
+/* --------------------------------------------------
+ * Umwandlung fuer QueryValue
+ * --------------------------------------------------*/
+sal_Int16 lcl_RelToINT(sal_Int16 eRelation)
+{
+ sal_Int16 nRet = text::RelOrientation::FRAME;
+ switch(eRelation)
+ {
+ case text::RelOrientation::PRINT_AREA: nRet = text::RelOrientation::PRINT_AREA; break;
+ case text::RelOrientation::CHAR: nRet = text::RelOrientation::CHAR; break;
+ case text::RelOrientation::PAGE_LEFT: nRet = text::RelOrientation::PAGE_LEFT; break;
+ case text::RelOrientation::PAGE_RIGHT: nRet = text::RelOrientation::PAGE_RIGHT; break;
+ case text::RelOrientation::FRAME_LEFT: nRet = text::RelOrientation::FRAME_LEFT; break;
+ case text::RelOrientation::FRAME_RIGHT: nRet = text::RelOrientation::FRAME_RIGHT; break;
+ case text::RelOrientation::PAGE_FRAME: nRet = text::RelOrientation::PAGE_FRAME; break;
+ case text::RelOrientation::PAGE_PRINT_AREA: nRet = text::RelOrientation::PAGE_PRINT_AREA; break;
+ // OD 13.11.2003 #i22341#
+ case text::RelOrientation::TEXT_LINE: nRet = text::RelOrientation::TEXT_LINE; break;
+ default: break;
+ }
+ return nRet;
+}
+
+sal_Int16 lcl_IntToRelation(const uno::Any& rVal)
+{
+ sal_Int16 eRet = text::RelOrientation::FRAME;
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ switch(nVal)
+ {
+ case text::RelOrientation::PRINT_AREA: eRet = text::RelOrientation::PRINT_AREA ; break;
+ case text::RelOrientation::CHAR: eRet = text::RelOrientation::CHAR ; break;
+ case text::RelOrientation::PAGE_LEFT: eRet = text::RelOrientation::PAGE_LEFT ; break;
+ case text::RelOrientation::PAGE_RIGHT: eRet = text::RelOrientation::PAGE_RIGHT ; break;
+ case text::RelOrientation::FRAME_LEFT: eRet = text::RelOrientation::FRAME_LEFT ; break;
+ case text::RelOrientation::FRAME_RIGHT: eRet = text::RelOrientation::FRAME_RIGHT ; break;
+ case text::RelOrientation::PAGE_FRAME: eRet = text::RelOrientation::PAGE_FRAME ; break;
+ case text::RelOrientation::PAGE_PRINT_AREA: eRet = text::RelOrientation::PAGE_PRINT_AREA ; break;
+ // OD 13.11.2003 #i22341#
+ case text::RelOrientation::TEXT_LINE: eRet = text::RelOrientation::TEXT_LINE; break;
+ }
+ return eRet;
+}
+
+void DelHFFormat( SwClient *pToRemove, SwFrmFmt *pFmt )
+{
+ //Wenn der Client der letzte ist der das Format benutzt, so muss dieses
+ //vernichtet werden. Zuvor muss jedoch ggf. die Inhaltssection vernichtet
+ //werden.
+ SwDoc* pDoc = pFmt->GetDoc();
+ pFmt->Remove( pToRemove );
+ if( pDoc->IsInDtor() )
+ {
+ delete pFmt;
+ return;
+ }
+
+ //Nur noch Frms angemeldet?
+ sal_Bool bDel = sal_True;
+ {
+ // Klammer, weil im DTOR SwClientIter das Flag bTreeChg zurueck
+ // gesetzt wird. Unguenstig, wenn das Format vorher zerstoert wird.
+ SwClientIter aIter( *pFmt ); // TODO
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do {
+ bDel = pLast->IsA( TYPE(SwFrm) )
+ || SwXHeadFootText::IsXHeadFootText(pLast);
+ } while( bDel && 0 != ( pLast = aIter++ ));
+ }
+
+ if ( bDel )
+ {
+ //Wenn in einem der Nodes noch ein Crsr angemeldet ist, muss das
+ //ParkCrsr einer (beliebigen) Shell gerufen werden.
+ SwFmtCntnt& rCnt = (SwFmtCntnt&)pFmt->GetCntnt();
+ if ( rCnt.GetCntntIdx() )
+ {
+ SwNode *pNode = 0;
+ {
+ // --> OD 2008-10-07 #i92993#
+ // Begin with start node of page header/footer to assure that
+ // complete content is checked for cursors and the complete content
+ // is deleted on below made method call <pDoc->DeleteSection(pNode)>
+// SwNodeIndex aIdx( *rCnt.GetCntntIdx(), 1 );
+ SwNodeIndex aIdx( *rCnt.GetCntntIdx(), 0 );
+ // <--
+ //Wenn in einem der Nodes noch ein Crsr angemeldet ist, muss das
+ //ParkCrsr einer (beliebigen) Shell gerufen werden.
+ pNode = & aIdx.GetNode();
+ sal_uInt32 nEnd = pNode->EndOfSectionIndex();
+ while ( aIdx < nEnd )
+ {
+ if ( pNode->IsCntntNode() &&
+ ((SwCntntNode*)pNode)->GetDepends() )
+ {
+ SwCrsrShell *pShell = SwIterator<SwCrsrShell,SwCntntNode>::FirstElement( *(SwCntntNode*)pNode );
+ if( pShell )
+ {
+ pShell->ParkCrsr( aIdx );
+ aIdx = nEnd-1;
+ }
+ }
+ aIdx++;
+ pNode = & aIdx.GetNode();
+ }
+ }
+ rCnt.SetNewCntntIdx( (const SwNodeIndex*)0 );
+
+ // beim Loeschen von Header/Footer-Formaten IMMER das Undo
+ // abschalten! (Bug 31069)
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ OSL_ENSURE( pNode, "Ein grosses Problem." );
+ pDoc->DeleteSection( pNode );
+ }
+ delete pFmt;
+ }
+}
+
+// class SwFmtFrmSize
+// Implementierung teilweise inline im hxx
+
+SwFmtFrmSize::SwFmtFrmSize( SwFrmSize eSize, SwTwips nWidth, SwTwips nHeight )
+ : SfxPoolItem( RES_FRM_SIZE ),
+ aSize( nWidth, nHeight ),
+ eFrmHeightType( eSize ),
+ eFrmWidthType( ATT_FIX_SIZE )
+{
+ nWidthPercent = nHeightPercent = 0;
+}
+
+SwFmtFrmSize& SwFmtFrmSize::operator=( const SwFmtFrmSize& rCpy )
+{
+ aSize = rCpy.GetSize();
+ eFrmHeightType = rCpy.GetHeightSizeType();
+ eFrmWidthType = rCpy.GetWidthSizeType();
+ nHeightPercent = rCpy.GetHeightPercent();
+ nWidthPercent = rCpy.GetWidthPercent();
+ return *this;
+}
+
+int SwFmtFrmSize::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return( eFrmHeightType == ((SwFmtFrmSize&)rAttr).eFrmHeightType &&
+ eFrmWidthType == ((SwFmtFrmSize&)rAttr).eFrmWidthType &&
+ aSize == ((SwFmtFrmSize&)rAttr).GetSize()&&
+ nWidthPercent == ((SwFmtFrmSize&)rAttr).GetWidthPercent() &&
+ nHeightPercent == ((SwFmtFrmSize&)rAttr).GetHeightPercent() );
+}
+
+SfxPoolItem* SwFmtFrmSize::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFrmSize( *this );
+}
+
+bool SwFmtFrmSize::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ switch ( nMemberId )
+ {
+ case MID_FRMSIZE_SIZE:
+ {
+ awt::Size aTmp;
+ aTmp.Height = TWIP_TO_MM100(aSize.Height());
+ aTmp.Width = TWIP_TO_MM100(aSize.Width());
+ rVal.setValue(&aTmp, ::getCppuType((const awt::Size*)0));
+ }
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ rVal <<= (sal_Int16)(GetHeightPercent() != 0xFF ? GetHeightPercent() : 0);
+ break;
+ case MID_FRMSIZE_REL_WIDTH:
+ rVal <<= (sal_Int16)(GetWidthPercent() != 0xFF ? GetWidthPercent() : 0);
+ break;
+ case MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH:
+ {
+ sal_Bool bTmp = 0xFF == GetHeightPercent();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT:
+ {
+ sal_Bool bTmp = 0xFF == GetWidthPercent();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_WIDTH :
+ rVal <<= (sal_Int32)TWIP_TO_MM100(aSize.Width());
+ break;
+ case MID_FRMSIZE_HEIGHT:
+ // #95848# returned size should never be zero.
+ // (there was a bug that allowed for setting height to 0.
+ // Thus there some documents existing with that not allowed
+ // attribut value which may cause problems on import.)
+ rVal <<= (sal_Int32)TWIP_TO_MM100(aSize.Height() < MINLAY ? MINLAY : aSize.Height() );
+ break;
+ case MID_FRMSIZE_SIZE_TYPE:
+ rVal <<= (sal_Int16)GetHeightSizeType();
+ break;
+ case MID_FRMSIZE_IS_AUTO_HEIGHT:
+ {
+ sal_Bool bTmp = ATT_FIX_SIZE != GetHeightSizeType();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_FRMSIZE_WIDTH_TYPE:
+ rVal <<= (sal_Int16)GetWidthSizeType();
+ break;
+ }
+ return true;
+}
+
+bool SwFmtFrmSize::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_FRMSIZE_SIZE:
+ {
+ awt::Size aVal;
+ if(!(rVal >>= aVal))
+ bRet = false;
+ else
+ {
+ Size aTmp(aVal.Width, aVal.Height);
+ if(bConvert)
+ {
+ aTmp.Height() = MM100_TO_TWIP(aTmp.Height());
+ aTmp.Width() = MM100_TO_TWIP(aTmp.Width());
+ }
+ if(aTmp.Height() && aTmp.Width())
+ aSize = aTmp;
+ else
+ bRet = false;
+ }
+ }
+ break;
+ case MID_FRMSIZE_REL_HEIGHT:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet <= 0xfe)
+ SetHeightPercent((sal_uInt8)nSet);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_REL_WIDTH:
+ {
+ sal_Int16 nSet = 0;
+ rVal >>= nSet;
+ if(nSet >= 0 && nSet <= 0xfe)
+ SetWidthPercent((sal_uInt8)nSet);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_HEIGHT_TO_WIDTH:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ if(bSet)
+ SetHeightPercent(0xff);
+ else if( 0xff == GetHeightPercent() )
+ SetHeightPercent( 0 );
+ }
+ break;
+ case MID_FRMSIZE_IS_SYNC_WIDTH_TO_HEIGHT:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ if(bSet)
+ SetWidthPercent(0xff);
+ else if( 0xff == GetWidthPercent() )
+ SetWidthPercent(0);
+ }
+ break;
+ case MID_FRMSIZE_WIDTH :
+ {
+ sal_Int32 nWd = 0;
+ if(rVal >>= nWd)
+ {
+ if(bConvert)
+ nWd = MM100_TO_TWIP(nWd);
+ if(nWd < MINLAY)
+ nWd = MINLAY;
+ aSize.Width() = nWd;
+ }
+ else
+ bRet = sal_False;
+ }
+ break;
+ case MID_FRMSIZE_HEIGHT:
+ {
+ sal_Int32 nHg = 0;
+ if(rVal >>= nHg)
+ {
+ if(bConvert)
+ nHg = MM100_TO_TWIP(nHg);
+ if(nHg < MINLAY)
+ nHg = MINLAY;
+ aSize.Height() = nHg;
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_SIZE_TYPE:
+ {
+ sal_Int16 nType = 0;
+ if((rVal >>= nType) && nType >= 0 && nType <= ATT_MIN_SIZE )
+ {
+ SetHeightSizeType((SwFrmSize)nType);
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_FRMSIZE_IS_AUTO_HEIGHT:
+ {
+ sal_Bool bSet = *(sal_Bool*)rVal.getValue();
+ SetHeightSizeType(bSet ? ATT_VAR_SIZE : ATT_FIX_SIZE);
+ }
+ break;
+ case MID_FRMSIZE_WIDTH_TYPE:
+ {
+ sal_Int16 nType = 0;
+ if((rVal >>= nType) && nType >= 0 && nType <= ATT_MIN_SIZE )
+ {
+ SetWidthSizeType((SwFrmSize)nType);
+ }
+ else
+ bRet = false;
+ }
+ break;
+ default:
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtFillOrder
+// Implementierung teilweise inline im hxx
+
+SwFmtFillOrder::SwFmtFillOrder( SwFillOrder nFO )
+ : SfxEnumItem( RES_FILL_ORDER, sal_uInt16(nFO) )
+{}
+
+SfxPoolItem* SwFmtFillOrder::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFillOrder( GetFillOrder() );
+}
+
+sal_uInt16 SwFmtFillOrder::GetValueCount() const
+{
+ return SW_FILL_ORDER_END - SW_FILL_ORDER_BEGIN;
+}
+
+// class SwFmtHeader
+// Implementierung teilweise inline im hxx
+
+SwFmtHeader::SwFmtHeader( SwFrmFmt *pHeaderFmt )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( pHeaderFmt ),
+ bActive( pHeaderFmt ? sal_True : sal_False )
+{
+}
+
+SwFmtHeader::SwFmtHeader( const SwFmtHeader &rCpy )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( (SwModify*)rCpy.GetRegisteredIn() ),
+ bActive( rCpy.IsActive() )
+{
+}
+
+SwFmtHeader::SwFmtHeader( sal_Bool bOn )
+ : SfxPoolItem( RES_HEADER ),
+ SwClient( 0 ),
+ bActive( bOn )
+{
+}
+
+ SwFmtHeader::~SwFmtHeader()
+{
+ if ( GetHeaderFmt() )
+ DelHFFormat( this, GetHeaderFmt() );
+}
+
+int SwFmtHeader::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetRegisteredIn() == ((SwFmtHeader&)rAttr).GetRegisteredIn() &&
+ bActive == ((SwFmtHeader&)rAttr).IsActive() );
+}
+
+SfxPoolItem* SwFmtHeader::Clone( SfxItemPool* ) const
+{
+ return new SwFmtHeader( *this );
+}
+
+void SwFmtHeader::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add(this);
+}
+
+// class SwFmtFooter
+// Implementierung teilweise inline im hxx
+
+SwFmtFooter::SwFmtFooter( SwFrmFmt *pFooterFmt )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( pFooterFmt ),
+ bActive( pFooterFmt ? sal_True : sal_False )
+{
+}
+
+SwFmtFooter::SwFmtFooter( const SwFmtFooter &rCpy )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( (SwModify*)rCpy.GetRegisteredIn() ),
+ bActive( rCpy.IsActive() )
+{
+}
+
+SwFmtFooter::SwFmtFooter( sal_Bool bOn )
+ : SfxPoolItem( RES_FOOTER ),
+ SwClient( 0 ),
+ bActive( bOn )
+{
+}
+
+ SwFmtFooter::~SwFmtFooter()
+{
+ if ( GetFooterFmt() )
+ DelHFFormat( this, GetFooterFmt() );
+}
+
+void SwFmtFooter::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add(this);
+}
+
+int SwFmtFooter::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetRegisteredIn() == ((SwFmtFooter&)rAttr).GetRegisteredIn() &&
+ bActive == ((SwFmtFooter&)rAttr).IsActive() );
+}
+
+SfxPoolItem* SwFmtFooter::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFooter( *this );
+}
+
+// class SwFmtCntnt
+// Implementierung teilweise inline im hxx
+
+SwFmtCntnt::SwFmtCntnt( const SwFmtCntnt &rCpy )
+ : SfxPoolItem( RES_CNTNT )
+{
+ pStartNode = rCpy.GetCntntIdx() ?
+ new SwNodeIndex( *rCpy.GetCntntIdx() ) : 0;
+}
+
+SwFmtCntnt::SwFmtCntnt( const SwStartNode *pStartNd )
+ : SfxPoolItem( RES_CNTNT )
+{
+ pStartNode = pStartNd ? new SwNodeIndex( *pStartNd ) : 0;
+}
+
+ SwFmtCntnt::~SwFmtCntnt()
+{
+ delete pStartNode;
+}
+
+void SwFmtCntnt::SetNewCntntIdx( const SwNodeIndex *pIdx )
+{
+ delete pStartNode;
+ pStartNode = pIdx ? new SwNodeIndex( *pIdx ) : 0;
+}
+
+int SwFmtCntnt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ if( (long)pStartNode ^ (long)((SwFmtCntnt&)rAttr).pStartNode )
+ return 0;
+ if( pStartNode )
+ return ( *pStartNode == *((SwFmtCntnt&)rAttr).GetCntntIdx() );
+ return 1;
+}
+
+SfxPoolItem* SwFmtCntnt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtCntnt( *this );
+}
+
+// class SwFmtPageDesc
+// Implementierung teilweise inline im hxx
+
+SwFmtPageDesc::SwFmtPageDesc( const SwFmtPageDesc &rCpy )
+ : SfxPoolItem( RES_PAGEDESC ),
+ SwClient( (SwPageDesc*)rCpy.GetPageDesc() ),
+ nNumOffset( rCpy.nNumOffset ),
+ nDescNameIdx( rCpy.nDescNameIdx ),
+ pDefinedIn( 0 )
+{
+}
+
+SwFmtPageDesc::SwFmtPageDesc( const SwPageDesc *pDesc )
+ : SfxPoolItem( RES_PAGEDESC ),
+ SwClient( (SwPageDesc*)pDesc ),
+ nNumOffset( 0 ),
+ nDescNameIdx( 0xFFFF ), // IDX_NO_VALUE
+ pDefinedIn( 0 )
+{
+}
+
+ SwFmtPageDesc::~SwFmtPageDesc() {}
+
+bool SwFmtPageDesc::KnowsPageDesc() const
+{
+ return (GetRegisteredIn() != 0);
+}
+
+int SwFmtPageDesc::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( pDefinedIn == ((SwFmtPageDesc&)rAttr).pDefinedIn ) &&
+ ( nNumOffset == ((SwFmtPageDesc&)rAttr).nNumOffset ) &&
+ ( GetPageDesc() == ((SwFmtPageDesc&)rAttr).GetPageDesc() );
+}
+
+SfxPoolItem* SwFmtPageDesc::Clone( SfxItemPool* ) const
+{
+ return new SwFmtPageDesc( *this );
+}
+
+void SwFmtPageDesc::SwClientNotify( const SwModify&, const SfxHint& rHint )
+{
+ const SwPageDescHint* pHint = dynamic_cast<const SwPageDescHint*>(&rHint);
+ if ( pHint )
+ {
+ // mba: shouldn't that be broadcasted also?
+ SwFmtPageDesc aDfltDesc( pHint->GetPageDesc() );
+ SwPageDesc* pDesc = pHint->GetPageDesc();
+ const SwModify* pMod = GetDefinedIn();
+ if ( pMod )
+ {
+ if( pMod->ISA( SwCntntNode ) )
+ ((SwCntntNode*)pMod)->SetAttr( aDfltDesc );
+ else if( pMod->ISA( SwFmt ))
+ ((SwFmt*)pMod)->SetFmtAttr( aDfltDesc );
+ else
+ {
+ OSL_FAIL( "What kind of SwModify is this?" );
+ RegisterToPageDesc( *pDesc );
+ }
+ }
+ else
+ // there could be an Undo-copy
+ RegisterToPageDesc( *pDesc );
+ }
+}
+
+void SwFmtPageDesc::RegisterToPageDesc( SwPageDesc& rDesc )
+{
+ rDesc.Add( this );
+}
+
+void SwFmtPageDesc::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ if( !pDefinedIn )
+ return;
+
+ const sal_uInt16 nWhichId = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhichId )
+ {
+ case RES_OBJECTDYING:
+ //Der Pagedesc, bei dem ich angemeldet bin stirbt, ich trage
+ //mich also bei meinem Format aus.
+ //Dabei werden ich Deletet!!!
+ if( IS_TYPE( SwFmt, pDefinedIn ))
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Bool bDel = ((SwFmt*)pDefinedIn)->ResetFmtAttr( RES_PAGEDESC );
+ OSL_ENSURE( bDel, ";-) FmtPageDesc nicht zerstoert." );
+ }
+#else
+ ((SwFmt*)pDefinedIn)->ResetFmtAttr( RES_PAGEDESC );
+#endif
+ else if( IS_TYPE( SwCntntNode, pDefinedIn ))
+#if OSL_DEBUG_LEVEL > 1
+ {
+ sal_Bool bDel = ((SwCntntNode*)pDefinedIn)->ResetAttr( RES_PAGEDESC );
+ OSL_ENSURE( bDel, ";-) FmtPageDesc nicht zerstoert." );
+ }
+#else
+ ((SwCntntNode*)pDefinedIn)->ResetAttr( RES_PAGEDESC );
+#endif
+ break;
+
+ default:
+ /* do nothing */;
+ }
+}
+
+bool SwFmtPageDesc::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_PAGEDESC_PAGENUMOFFSET:
+ rVal <<= (sal_Int16)GetNumOffset();
+ break;
+
+ case MID_PAGEDESC_PAGEDESCNAME:
+ {
+ const SwPageDesc* pDesc = GetPageDesc();
+ if( pDesc )
+ {
+ String aString;
+ SwStyleNameMapper::FillProgName(pDesc->GetName(), aString, nsSwGetPoolIdFromName::GET_POOLID_PAGEDESC, sal_True );
+ rVal <<= OUString( aString );
+ }
+ else
+ rVal.clear();
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtPageDesc::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ sal_Bool bRet = sal_True;
+ switch ( nMemberId )
+ {
+ case MID_PAGEDESC_PAGENUMOFFSET:
+ {
+ sal_Int16 nOffset = 0;
+ if(rVal >>= nOffset)
+ SetNumOffset( nOffset );
+ else
+ bRet = false;
+ }
+ break;
+
+ case MID_PAGEDESC_PAGEDESCNAME:
+ /* geht nicht, weil das Attribut eigentlich nicht den Namen
+ * sondern einen Pointer auf den PageDesc braucht (ist Client davon).
+ * Der Pointer waere aber ueber den Namen nur vom Dokument zu erfragen.
+ */
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwFmtCol
+// Implementierung teilweise inline im hxx
+
+SwColumn::SwColumn() :
+ nWish ( 0 ),
+ nUpper( 0 ),
+ nLower( 0 ),
+ nLeft ( 0 ),
+ nRight( 0 )
+{
+}
+
+sal_Bool SwColumn::operator==( const SwColumn &rCmp )
+{
+ return (nWish == rCmp.GetWishWidth() &&
+ GetLeft() == rCmp.GetLeft() &&
+ GetRight() == rCmp.GetRight() &&
+ GetUpper() == rCmp.GetUpper() &&
+ GetLower() == rCmp.GetLower()) ? sal_True : sal_False;
+}
+
+SwFmtCol::SwFmtCol( const SwFmtCol& rCpy )
+ : SfxPoolItem( RES_COL ),
+ eLineStyle( rCpy.eLineStyle ),
+ nLineWidth( rCpy.nLineWidth),
+ aLineColor( rCpy.aLineColor),
+ nLineHeight( rCpy.GetLineHeight() ),
+ eAdj( rCpy.GetLineAdj() ),
+ aColumns( (sal_Int8)rCpy.GetNumCols(), 1 ),
+ nWidth( rCpy.GetWishWidth() ),
+ bOrtho( rCpy.IsOrtho() )
+{
+ for ( sal_uInt16 i = 0; i < rCpy.GetNumCols(); ++i )
+ {
+ SwColumn *pCol = new SwColumn( *rCpy.GetColumns()[i] );
+ aColumns.Insert( pCol, aColumns.Count() );
+ }
+}
+
+SwFmtCol::~SwFmtCol() {}
+
+SwFmtCol& SwFmtCol::operator=( const SwFmtCol& rCpy )
+{
+ eLineStyle = rCpy.eLineStyle;
+ nLineWidth = rCpy.nLineWidth;
+ aLineColor = rCpy.aLineColor;
+ nLineHeight = rCpy.GetLineHeight();
+ eAdj = rCpy.GetLineAdj();
+ nWidth = rCpy.GetWishWidth();
+ bOrtho = rCpy.IsOrtho();
+
+ if ( aColumns.Count() )
+ aColumns.DeleteAndDestroy( 0, aColumns.Count() );
+ for ( sal_uInt16 i = 0; i < rCpy.GetNumCols(); ++i )
+ {
+ SwColumn *pCol = new SwColumn( *rCpy.GetColumns()[i] );
+ aColumns.Insert( pCol, aColumns.Count() );
+ }
+ return *this;
+}
+
+SwFmtCol::SwFmtCol()
+ : SfxPoolItem( RES_COL ),
+ eLineStyle( editeng::NO_STYLE ),
+ nLineWidth(0),
+ nLineHeight( 100 ),
+ eAdj( COLADJ_NONE ),
+ nWidth( USHRT_MAX ),
+ bOrtho( sal_True )
+{
+}
+
+int SwFmtCol::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ const SwFmtCol &rCmp = (const SwFmtCol&)rAttr;
+ if( !(eLineStyle == rCmp.eLineStyle &&
+ nLineWidth == rCmp.nLineWidth &&
+ aLineColor == rCmp.aLineColor &&
+ nLineHeight == rCmp.GetLineHeight() &&
+ eAdj == rCmp.GetLineAdj() &&
+ nWidth == rCmp.GetWishWidth() &&
+ bOrtho == rCmp.IsOrtho() &&
+ aColumns.Count() == rCmp.GetNumCols()) )
+ return 0;
+
+ for ( sal_uInt16 i = 0; i < aColumns.Count(); ++i )
+ if ( !(*aColumns[i] == *rCmp.GetColumns()[i]) )
+ return 0;
+
+ return 1;
+}
+
+SfxPoolItem* SwFmtCol::Clone( SfxItemPool* ) const
+{
+ return new SwFmtCol( *this );
+}
+
+sal_uInt16 SwFmtCol::GetGutterWidth( sal_Bool bMin ) const
+{
+ sal_uInt16 nRet = 0;
+ if ( aColumns.Count() == 2 )
+ nRet = aColumns[0]->GetRight() + aColumns[1]->GetLeft();
+ else if ( aColumns.Count() > 2 )
+ {
+ sal_Bool bSet = sal_False;
+ for ( sal_uInt16 i = 1; i < aColumns.Count()-1; ++i )
+ {
+ const sal_uInt16 nTmp = aColumns[i]->GetRight() + aColumns[i+1]->GetLeft();
+ if ( bSet )
+ {
+ if ( nTmp != nRet )
+ {
+ if ( !bMin )
+ return USHRT_MAX;
+ if ( nRet > nTmp )
+ nRet = nTmp;
+ }
+ }
+ else
+ { bSet = sal_True;
+ nRet = nTmp;
+ }
+ }
+ }
+ return nRet;
+}
+
+void SwFmtCol::SetGutterWidth( sal_uInt16 nNew, sal_uInt16 nAct )
+{
+ if ( bOrtho )
+ Calc( nNew, nAct );
+ else
+ {
+ sal_uInt16 nHalf = nNew / 2;
+ for ( sal_uInt16 i = 0; i < aColumns.Count(); ++i )
+ { SwColumn *pCol = aColumns[i];
+ pCol->SetLeft ( nHalf );
+ pCol->SetRight( nHalf );
+ if ( i == 0 )
+ pCol->SetLeft( 0 );
+ else if ( i == (aColumns.Count() - 1) )
+ pCol->SetRight( 0 );
+ }
+ }
+}
+
+void SwFmtCol::Init( sal_uInt16 nNumCols, sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ //Loeschen scheint hier auf den erste Blick vielleicht etwas zu heftig;
+ //anderfalls muessten allerdings alle Werte der verbleibenden SwColumn's
+ //initialisiert werden.
+ if ( aColumns.Count() )
+ aColumns.DeleteAndDestroy( 0, aColumns.Count() );
+ for ( sal_uInt16 i = 0; i < nNumCols; ++i )
+ { SwColumn *pCol = new SwColumn;
+ aColumns.Insert( pCol, i );
+ }
+ bOrtho = sal_True;
+ nWidth = USHRT_MAX;
+ if( nNumCols )
+ Calc( nGutterWidth, nAct );
+}
+
+void SwFmtCol::SetOrtho( sal_Bool bNew, sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ bOrtho = bNew;
+ if ( bNew && aColumns.Count() )
+ Calc( nGutterWidth, nAct );
+}
+
+sal_uInt16 SwFmtCol::CalcColWidth( sal_uInt16 nCol, sal_uInt16 nAct ) const
+{
+ OSL_ENSURE( nCol < aColumns.Count(), ":-( ColumnsArr ueberindiziert." );
+ if ( nWidth != nAct )
+ {
+ long nW = aColumns[nCol]->GetWishWidth();
+ nW *= nAct;
+ nW /= nWidth;
+ return sal_uInt16(nW);
+ }
+ else
+ return aColumns[nCol]->GetWishWidth();
+}
+
+sal_uInt16 SwFmtCol::CalcPrtColWidth( sal_uInt16 nCol, sal_uInt16 nAct ) const
+{
+ OSL_ENSURE( nCol < aColumns.Count(), ":-( ColumnsArr ueberindiziert." );
+ sal_uInt16 nRet = CalcColWidth( nCol, nAct );
+ SwColumn *pCol = aColumns[nCol];
+ nRet = nRet - pCol->GetLeft();
+ nRet = nRet - pCol->GetRight();
+ return nRet;
+}
+
+void SwFmtCol::Calc( sal_uInt16 nGutterWidth, sal_uInt16 nAct )
+{
+ if(!GetNumCols())
+ return;
+ //Erstmal die Spalten mit der Aktuellen Breite einstellen, dann die
+ //Wunschbreite der Spalten anhand der Gesamtwunschbreite hochrechnen.
+
+ const sal_uInt16 nGutterHalf = nGutterWidth ? nGutterWidth / 2 : 0;
+
+ //Breite der PrtAreas ist Gesamtbreite - Zwischenraeume / Anzahl
+ const sal_uInt16 nPrtWidth =
+ (nAct - ((GetNumCols()-1) * nGutterWidth)) / GetNumCols();
+ sal_uInt16 nAvail = nAct;
+
+ //Die erste Spalte ist PrtBreite + (Zwischenraumbreite/2)
+ const sal_uInt16 nLeftWidth = nPrtWidth + nGutterHalf;
+ SwColumn *pCol = aColumns[0];
+ pCol->SetWishWidth( nLeftWidth );
+ pCol->SetRight( nGutterHalf );
+ pCol->SetLeft ( 0 );
+ nAvail = nAvail - nLeftWidth;
+
+ //Spalte 2 bis n-1 ist PrtBreite + Zwischenraumbreite
+ const sal_uInt16 nMidWidth = nPrtWidth + nGutterWidth;
+ sal_uInt16 i;
+
+ for ( i = 1; i < GetNumCols()-1; ++i )
+ {
+ pCol = aColumns[i];
+ pCol->SetWishWidth( nMidWidth );
+ pCol->SetLeft ( nGutterHalf );
+ pCol->SetRight( nGutterHalf );
+ nAvail = nAvail - nMidWidth;
+ }
+
+ //Die Letzte Spalte entspricht wieder der ersten, um Rundungsfehler
+ //auszugleichen wird der letzten Spalte alles zugeschlagen was die
+ //anderen nicht verbraucht haben.
+ pCol = aColumns[aColumns.Count()-1];
+ pCol->SetWishWidth( nAvail );
+ pCol->SetLeft ( nGutterHalf );
+ pCol->SetRight( 0 );
+
+ //Umrechnen der aktuellen Breiten in Wunschbreiten.
+ for ( i = 0; i < aColumns.Count(); ++i )
+ {
+ pCol = aColumns[i];
+ long nTmp = pCol->GetWishWidth();
+ nTmp *= GetWishWidth();
+ nTmp /= nAct;
+ pCol->SetWishWidth( sal_uInt16(nTmp) );
+ }
+}
+
+bool SwFmtCol::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ if(MID_COLUMN_SEPARATOR_LINE == nMemberId)
+ {
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ uno::Reference< text::XTextColumns > xCols = new SwXTextColumns(*this);
+ rVal.setValue(&xCols, ::getCppuType((uno::Reference< text::XTextColumns>*)0));
+ }
+ return true;
+}
+
+bool SwFmtCol::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = false;
+ if(MID_COLUMN_SEPARATOR_LINE == nMemberId)
+ {
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ uno::Reference< text::XTextColumns > xCols;
+ rVal >>= xCols;
+ if(xCols.is())
+ {
+ uno::Sequence<text::TextColumn> aSetColumns = xCols->getColumns();
+ const text::TextColumn* pArray = aSetColumns.getConstArray();
+ aColumns.DeleteAndDestroy(0, aColumns.Count());
+ //max. Count ist hier 64K - das kann das Array aber nicht
+ sal_uInt16 nCount = Min( (sal_uInt16)aSetColumns.getLength(),
+ (sal_uInt16) 0x3fff );
+ sal_uInt16 nWidthSum = 0;
+ // #101224# one column is no column
+ //
+ if(nCount > 1)
+ for(sal_uInt16 i = 0; i < nCount; i++)
+ {
+ SwColumn* pCol = new SwColumn;
+ pCol->SetWishWidth( static_cast<sal_uInt16>(pArray[i].Width) );
+ nWidthSum = static_cast<sal_uInt16>(nWidthSum + pArray[i].Width);
+ pCol->SetLeft ( static_cast<sal_uInt16>(MM100_TO_TWIP(pArray[i].LeftMargin)) );
+ pCol->SetRight( static_cast<sal_uInt16>(MM100_TO_TWIP(pArray[i].RightMargin)) );
+ aColumns.Insert(pCol, i);
+ }
+ bRet = true;
+ nWidth = nWidthSum;
+ bOrtho = sal_False;
+
+ uno::Reference<lang::XUnoTunnel> xNumTunnel(xCols, uno::UNO_QUERY);
+ SwXTextColumns* pSwColums = 0;
+ if(xNumTunnel.is())
+ {
+ pSwColums = reinterpret_cast< SwXTextColumns * >(
+ sal::static_int_cast< sal_IntPtr >(
+ xNumTunnel->getSomething( SwXTextColumns::getUnoTunnelId() )));
+ }
+ if(pSwColums)
+ {
+ bOrtho = pSwColums->IsAutomaticWidth();
+ nLineWidth = pSwColums->GetSepLineWidth();
+ aLineColor.SetColor(pSwColums->GetSepLineColor());
+ nLineHeight = pSwColums->GetSepLineHeightRelative();
+ switch ( pSwColums->GetSepLineStyle() )
+ {
+ default:
+ case 0: eLineStyle = editeng::NO_STYLE; break;
+ case 1: eLineStyle = editeng::SOLID; break;
+ case 2: eLineStyle = editeng::DOTTED; break;
+ case 3: eLineStyle = editeng::DASHED; break;
+ }
+ if(!pSwColums->GetSepLineIsOn())
+ eAdj = COLADJ_NONE;
+ else switch(pSwColums->GetSepLineVertAlign())
+ {
+ case 0: eAdj = COLADJ_TOP; break; //VerticalAlignment_TOP
+ case 1: eAdj = COLADJ_CENTER;break; //VerticalAlignment_MIDDLE
+ case 2: eAdj = COLADJ_BOTTOM;break; //VerticalAlignment_BOTTOM
+ default: OSL_ENSURE( !this, "unknown alignment" ); break;
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+
+// class SwFmtSurround
+// Implementierung teilweise inline im hxx
+
+SwFmtSurround::SwFmtSurround( SwSurround eFly ) :
+ SfxEnumItem( RES_SURROUND, sal_uInt16( eFly ) )
+{
+ bAnchorOnly = bContour = bOutside = sal_False;
+}
+
+SwFmtSurround::SwFmtSurround( const SwFmtSurround &rCpy ) :
+ SfxEnumItem( RES_SURROUND, rCpy.GetValue() )
+{
+ bAnchorOnly = rCpy.bAnchorOnly;
+ bContour = rCpy.bContour;
+ bOutside = rCpy.bOutside;
+}
+
+int SwFmtSurround::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( GetValue() == ((SwFmtSurround&)rAttr).GetValue() &&
+ bAnchorOnly== ((SwFmtSurround&)rAttr).bAnchorOnly &&
+ bContour== ((SwFmtSurround&)rAttr).bContour &&
+ bOutside== ((SwFmtSurround&)rAttr).bOutside );
+}
+
+SfxPoolItem* SwFmtSurround::Clone( SfxItemPool* ) const
+{
+ return new SwFmtSurround( *this );
+}
+
+sal_uInt16 SwFmtSurround::GetValueCount() const
+{
+ return SURROUND_END - SURROUND_BEGIN;
+}
+
+
+bool SwFmtSurround::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_SURROUND_SURROUNDTYPE:
+ rVal <<= (text::WrapTextMode)GetSurround();
+ break;
+ case MID_SURROUND_ANCHORONLY:
+ {
+ sal_Bool bTmp = IsAnchorOnly();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_SURROUND_CONTOUR:
+ {
+ sal_Bool bTmp = IsContour();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_SURROUND_CONTOUROUTSIDE:
+ {
+ sal_Bool bTmp = IsOutside();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtSurround::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_SURROUND_SURROUNDTYPE:
+ {
+ sal_Int32 eVal = SWUnoHelper::GetEnumAsInt32( rVal );
+ if( eVal >= 0 && eVal < (sal_Int16)SURROUND_END )
+ SetValue( static_cast<sal_uInt16>(eVal) );
+ else {
+ //exception
+ ;
+ }
+ }
+ break;
+
+ case MID_SURROUND_ANCHORONLY:
+ SetAnchorOnly( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_SURROUND_CONTOUR:
+ SetContour( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_SURROUND_CONTOUROUTSIDE:
+ SetOutside( *(sal_Bool*)rVal.getValue() );
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtVertOrient
+// Implementierung teilweise inline im hxx
+
+SwFmtVertOrient::SwFmtVertOrient( SwTwips nY, sal_Int16 eVert,
+ sal_Int16 eRel )
+ : SfxPoolItem( RES_VERT_ORIENT ),
+ nYPos( nY ),
+ eOrient( eVert ),
+ eRelation( eRel )
+{}
+
+int SwFmtVertOrient::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( nYPos == ((SwFmtVertOrient&)rAttr).nYPos &&
+ eOrient == ((SwFmtVertOrient&)rAttr).eOrient &&
+ eRelation == ((SwFmtVertOrient&)rAttr).eRelation );
+}
+
+SfxPoolItem* SwFmtVertOrient::Clone( SfxItemPool* ) const
+{
+ return new SwFmtVertOrient( nYPos, eOrient, eRelation );
+}
+
+bool SwFmtVertOrient::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_VERTORIENT_ORIENT:
+ {
+ sal_Int16 nRet = text::VertOrientation::NONE;
+ switch( eOrient )
+ {
+ case text::VertOrientation::TOP : nRet = text::VertOrientation::TOP ;break;
+ case text::VertOrientation::CENTER : nRet = text::VertOrientation::CENTER ;break;
+ case text::VertOrientation::BOTTOM : nRet = text::VertOrientation::BOTTOM ;break;
+ case text::VertOrientation::CHAR_TOP : nRet = text::VertOrientation::CHAR_TOP ;break;
+ case text::VertOrientation::CHAR_CENTER: nRet = text::VertOrientation::CHAR_CENTER;break;
+ case text::VertOrientation::CHAR_BOTTOM: nRet = text::VertOrientation::CHAR_BOTTOM;break;
+ case text::VertOrientation::LINE_TOP : nRet = text::VertOrientation::LINE_TOP ;break;
+ case text::VertOrientation::LINE_CENTER: nRet = text::VertOrientation::LINE_CENTER;break;
+ case text::VertOrientation::LINE_BOTTOM: nRet = text::VertOrientation::LINE_BOTTOM;break;
+ default: break;
+ }
+ rVal <<= nRet;
+ }
+ break;
+ case MID_VERTORIENT_RELATION:
+ rVal <<= lcl_RelToINT(eRelation);
+ break;
+ case MID_VERTORIENT_POSITION:
+ rVal <<= (sal_Int32)TWIP_TO_MM100(GetPos());
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtVertOrient::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_VERTORIENT_ORIENT:
+ {
+ sal_uInt16 nVal = 0;
+ rVal >>= nVal;
+ switch( nVal )
+ {
+ case text::VertOrientation::NONE: eOrient = text::VertOrientation::NONE; break;
+ case text::VertOrientation::TOP : eOrient = text::VertOrientation::TOP; break;
+ case text::VertOrientation::CENTER : eOrient = text::VertOrientation::CENTER; break;
+ case text::VertOrientation::BOTTOM : eOrient = text::VertOrientation::BOTTOM; break;
+ case text::VertOrientation::CHAR_TOP : eOrient = text::VertOrientation::CHAR_TOP; break;
+ case text::VertOrientation::CHAR_CENTER: eOrient = text::VertOrientation::CHAR_CENTER;break;
+ case text::VertOrientation::CHAR_BOTTOM: eOrient = text::VertOrientation::CHAR_BOTTOM;break;
+ case text::VertOrientation::LINE_TOP : eOrient = text::VertOrientation::LINE_TOP; break;
+ case text::VertOrientation::LINE_CENTER: eOrient = text::VertOrientation::LINE_CENTER;break;
+ case text::VertOrientation::LINE_BOTTOM: eOrient = text::VertOrientation::LINE_BOTTOM;break;
+ }
+ }
+ break;
+ case MID_VERTORIENT_RELATION:
+ {
+ eRelation = lcl_IntToRelation(rVal);
+ }
+ break;
+ case MID_VERTORIENT_POSITION:
+ {
+ sal_Int32 nVal = 0;
+ rVal >>= nVal;
+ if(bConvert)
+ nVal = MM100_TO_TWIP(nVal);
+ SetPos( nVal );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+
+// class SwFmtHoriOrient
+// Implementierung teilweise inline im hxx
+
+SwFmtHoriOrient::SwFmtHoriOrient( SwTwips nX, sal_Int16 eHori,
+ sal_Int16 eRel, sal_Bool bPos )
+ : SfxPoolItem( RES_HORI_ORIENT ),
+ nXPos( nX ),
+ eOrient( eHori ),
+ eRelation( eRel ),
+ bPosToggle( bPos )
+{}
+
+int SwFmtHoriOrient::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return ( nXPos == ((SwFmtHoriOrient&)rAttr).nXPos &&
+ eOrient == ((SwFmtHoriOrient&)rAttr).eOrient &&
+ eRelation == ((SwFmtHoriOrient&)rAttr).eRelation &&
+ bPosToggle == ((SwFmtHoriOrient&)rAttr).bPosToggle );
+}
+
+SfxPoolItem* SwFmtHoriOrient::Clone( SfxItemPool* ) const
+{
+ return new SwFmtHoriOrient( nXPos, eOrient, eRelation, bPosToggle );
+}
+
+bool SwFmtHoriOrient::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_HORIORIENT_ORIENT:
+ {
+ sal_Int16 nRet = text::HoriOrientation::NONE;
+ switch( eOrient )
+ {
+ case text::HoriOrientation::RIGHT: nRet = text::HoriOrientation::RIGHT; break;
+ case text::HoriOrientation::CENTER : nRet = text::HoriOrientation::CENTER; break;
+ case text::HoriOrientation::LEFT : nRet = text::HoriOrientation::LEFT; break;
+ case text::HoriOrientation::INSIDE : nRet = text::HoriOrientation::INSIDE; break;
+ case text::HoriOrientation::OUTSIDE: nRet = text::HoriOrientation::OUTSIDE; break;
+ case text::HoriOrientation::FULL: nRet = text::HoriOrientation::FULL; break;
+ case text::HoriOrientation::LEFT_AND_WIDTH :
+ nRet = text::HoriOrientation::LEFT_AND_WIDTH;
+ break;
+ default:
+ break;
+
+ }
+ rVal <<= nRet;
+ }
+ break;
+ case MID_HORIORIENT_RELATION:
+ rVal <<= lcl_RelToINT(eRelation);
+ break;
+ case MID_HORIORIENT_POSITION:
+ rVal <<= (sal_Int32)TWIP_TO_MM100(GetPos());
+ break;
+ case MID_HORIORIENT_PAGETOGGLE:
+ {
+ sal_Bool bTmp = IsPosToggle();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtHoriOrient::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ sal_Bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_HORIORIENT_ORIENT:
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ switch( nVal )
+ {
+ case text::HoriOrientation::NONE: eOrient = text::HoriOrientation::NONE ; break;
+ case text::HoriOrientation::RIGHT: eOrient = text::HoriOrientation::RIGHT; break;
+ case text::HoriOrientation::CENTER : eOrient = text::HoriOrientation::CENTER; break;
+ case text::HoriOrientation::LEFT : eOrient = text::HoriOrientation::LEFT; break;
+ case text::HoriOrientation::INSIDE : eOrient = text::HoriOrientation::INSIDE; break;
+ case text::HoriOrientation::OUTSIDE: eOrient = text::HoriOrientation::OUTSIDE; break;
+ case text::HoriOrientation::FULL: eOrient = text::HoriOrientation::FULL; break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ eOrient = text::HoriOrientation::LEFT_AND_WIDTH;
+ break;
+ }
+ }
+ break;
+ case MID_HORIORIENT_RELATION:
+ {
+ eRelation = lcl_IntToRelation(rVal);
+ }
+ break;
+ case MID_HORIORIENT_POSITION:
+ {
+ sal_Int32 nVal = 0;
+ if(!(rVal >>= nVal))
+ bRet = false;
+ if(bConvert)
+ nVal = MM100_TO_TWIP(nVal);
+ SetPos( nVal );
+ }
+ break;
+ case MID_HORIORIENT_PAGETOGGLE:
+ SetPosToggle( *(sal_Bool*)rVal.getValue());
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+
+// class SwFmtAnchor
+// Implementierung teilweise inline im hxx
+
+SwFmtAnchor::SwFmtAnchor( RndStdIds nRnd, sal_uInt16 nPage )
+ : SfxPoolItem( RES_ANCHOR ),
+ pCntntAnchor( 0 ),
+ nAnchorId( nRnd ),
+ nPageNum( nPage ),
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder( ++mnOrderCounter )
+{}
+
+SwFmtAnchor::SwFmtAnchor( const SwFmtAnchor &rCpy )
+ : SfxPoolItem( RES_ANCHOR ),
+ nAnchorId( rCpy.GetAnchorId() ),
+ nPageNum( rCpy.GetPageNum() ),
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder( ++mnOrderCounter )
+{
+ pCntntAnchor = rCpy.GetCntntAnchor() ?
+ new SwPosition( *rCpy.GetCntntAnchor() ) : 0;
+}
+
+ SwFmtAnchor::~SwFmtAnchor()
+{
+ delete pCntntAnchor;
+}
+
+void SwFmtAnchor::SetAnchor( const SwPosition *pPos )
+{
+ if ( pCntntAnchor )
+ delete pCntntAnchor;
+ pCntntAnchor = pPos ? new SwPosition( *pPos ) : 0;
+ //AM Absatz gebundene Flys sollten nie in den Absatz hineinzeigen.
+ if (pCntntAnchor &&
+ ((FLY_AT_PARA == nAnchorId) || (FLY_AT_FLY == nAnchorId)))
+ {
+ pCntntAnchor->nContent.Assign( 0, 0 );
+ }
+}
+
+SwFmtAnchor& SwFmtAnchor::operator=(const SwFmtAnchor& rAnchor)
+{
+ nAnchorId = rAnchor.GetAnchorId();
+ nPageNum = rAnchor.GetPageNum();
+ // OD 2004-05-05 #i28701# - get always new increased order number
+ mnOrder = ++mnOrderCounter;
+
+ delete pCntntAnchor;
+ pCntntAnchor = rAnchor.pCntntAnchor ?
+ new SwPosition(*(rAnchor.pCntntAnchor)) : 0;
+ return *this;
+}
+
+int SwFmtAnchor::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ // OD 2004-05-05 #i28701# - Note: <mnOrder> hasn't to be considered.
+ return ( nAnchorId == ((SwFmtAnchor&)rAttr).GetAnchorId() &&
+ nPageNum == ((SwFmtAnchor&)rAttr).GetPageNum() &&
+ //Anker vergleichen. Entweder zeigen beide auf das gleiche
+ //Attribut bzw. sind 0 oder die SwPosition* sind beide
+ //gueltig und die SwPositions sind gleich.
+ (pCntntAnchor == ((SwFmtAnchor&)rAttr).GetCntntAnchor() ||
+ (pCntntAnchor && ((SwFmtAnchor&)rAttr).GetCntntAnchor() &&
+ *pCntntAnchor == *((SwFmtAnchor&)rAttr).GetCntntAnchor())));
+}
+
+SfxPoolItem* SwFmtAnchor::Clone( SfxItemPool* ) const
+{
+ return new SwFmtAnchor( *this );
+}
+
+// OD 2004-05-05 #i28701#
+sal_uInt32 SwFmtAnchor::mnOrderCounter = 0;
+
+// OD 2004-05-05 #i28701#
+sal_uInt32 SwFmtAnchor::GetOrder() const
+{
+ return mnOrder;
+}
+
+bool SwFmtAnchor::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_ANCHOR_ANCHORTYPE:
+
+ text::TextContentAnchorType eRet;
+ switch (GetAnchorId())
+ {
+ case FLY_AT_CHAR:
+ eRet = text::TextContentAnchorType_AT_CHARACTER;
+ break;
+ case FLY_AT_PAGE:
+ eRet = text::TextContentAnchorType_AT_PAGE;
+ break;
+ case FLY_AT_FLY:
+ eRet = text::TextContentAnchorType_AT_FRAME;
+ break;
+ case FLY_AS_CHAR:
+ eRet = text::TextContentAnchorType_AS_CHARACTER;
+ break;
+ //case FLY_AT_PARA:
+ default:
+ eRet = text::TextContentAnchorType_AT_PARAGRAPH;
+ }
+ rVal <<= eRet;
+ break;
+ case MID_ANCHOR_PAGENUM:
+ rVal <<= (sal_Int16)GetPageNum();
+ break;
+ case MID_ANCHOR_ANCHORFRAME:
+ {
+ if(pCntntAnchor && FLY_AT_FLY == nAnchorId)
+ {
+ SwFrmFmt* pFmt = pCntntAnchor->nNode.GetNode().GetFlyFmt();
+ if(pFmt)
+ {
+ uno::Reference<container::XNamed> xNamed = SwXFrames::GetObject( *pFmt, FLYCNTTYPE_FRM );
+ uno::Reference<text::XTextFrame> xRet(xNamed, uno::UNO_QUERY);
+ rVal <<= xRet;
+ }
+ }
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtAnchor::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_ANCHOR_ANCHORTYPE:
+ {
+ RndStdIds eAnchor;
+ switch( SWUnoHelper::GetEnumAsInt32( rVal ) )
+ {
+ case text::TextContentAnchorType_AS_CHARACTER:
+ eAnchor = FLY_AS_CHAR;
+ break;
+ case text::TextContentAnchorType_AT_PAGE:
+ eAnchor = FLY_AT_PAGE;
+ if( GetPageNum() > 0 && pCntntAnchor )
+ {
+ // If the anchor type is page and a valid page number
+ // has been set, the content position isn't required
+ // any longer.
+ delete pCntntAnchor;
+ pCntntAnchor = 0;
+ }
+ break;
+ case text::TextContentAnchorType_AT_FRAME:
+ eAnchor = FLY_AT_FLY;
+ break;
+ case text::TextContentAnchorType_AT_CHARACTER:
+ eAnchor = FLY_AT_CHAR;
+ break;
+ //case text::TextContentAnchorType_AT_PARAGRAPH:
+ default:
+ eAnchor = FLY_AT_PARA;
+ break;
+ }
+ SetType( eAnchor );
+ }
+ break;
+ case MID_ANCHOR_PAGENUM:
+ {
+ sal_Int16 nVal = 0;
+ if((rVal >>= nVal) && nVal > 0)
+ {
+ SetPageNum( nVal );
+ if ((FLY_AT_PAGE == GetAnchorId()) && pCntntAnchor)
+ {
+ // If the anchor type is page and a valid page number
+ // is set, the content paoition has to be deleted to not
+ // confuse the layout (frmtool.cxx). However, if the
+ // anchor type is not page, any content position will
+ // be kept.
+ delete pCntntAnchor;
+ pCntntAnchor = 0;
+ }
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_ANCHOR_ANCHORFRAME:
+ //no break here!;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+// class SwFmtURL
+// Implementierung teilweise inline im hxx
+
+SwFmtURL::SwFmtURL() :
+ SfxPoolItem( RES_URL ),
+ pMap( 0 ),
+ bIsServerMap( sal_False )
+{
+}
+
+SwFmtURL::SwFmtURL( const SwFmtURL &rURL) :
+ SfxPoolItem( RES_URL ),
+ sTargetFrameName( rURL.GetTargetFrameName() ),
+ sURL( rURL.GetURL() ),
+ sName( rURL.GetName() ),
+ bIsServerMap( rURL.IsServerMap() )
+{
+ pMap = rURL.GetMap() ? new ImageMap( *rURL.GetMap() ) : 0;
+}
+
+SwFmtURL::~SwFmtURL()
+{
+ if ( pMap )
+ delete pMap;
+}
+
+int SwFmtURL::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ const SwFmtURL &rCmp = (SwFmtURL&)rAttr;
+ sal_Bool bRet = bIsServerMap == rCmp.IsServerMap() &&
+ sURL == rCmp.GetURL() &&
+ sTargetFrameName == rCmp.GetTargetFrameName() &&
+ sName == rCmp.GetName();
+ if ( bRet )
+ {
+ if ( pMap && rCmp.GetMap() )
+ bRet = *pMap == *rCmp.GetMap();
+ else
+ bRet = pMap == rCmp.GetMap();
+ }
+ return bRet;
+}
+
+SfxPoolItem* SwFmtURL::Clone( SfxItemPool* ) const
+{
+ return new SwFmtURL( *this );
+}
+
+void SwFmtURL::SetURL( const XubString &rURL, sal_Bool bServerMap )
+{
+ sURL = rURL;
+ bIsServerMap = bServerMap;
+}
+
+void SwFmtURL::SetMap( const ImageMap *pM )
+{
+ if ( pMap )
+ delete pMap;
+ pMap = pM ? new ImageMap( *pM ) : 0;
+}
+extern const SvEventDescription* lcl_GetSupportedMacroItems();
+
+bool SwFmtURL::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_URL_URL:
+ {
+ OUString sRet = GetURL();
+ rVal <<= sRet;
+ }
+ break;
+ case MID_URL_TARGET:
+ {
+ OUString sRet = GetTargetFrameName();
+ rVal <<= sRet;
+ }
+ break;
+ case MID_URL_HYPERLINKNAME:
+ rVal <<= OUString( GetName() );
+ break;
+ case MID_URL_CLIENTMAP:
+ {
+ uno::Reference< uno::XInterface > xInt;
+ if(pMap)
+ {
+ xInt = SvUnoImageMap_createInstance( *pMap, lcl_GetSupportedMacroItems() );
+ }
+ else
+ {
+ ImageMap aEmptyMap;
+ xInt = SvUnoImageMap_createInstance( aEmptyMap, lcl_GetSupportedMacroItems() );
+ }
+ uno::Reference< container::XIndexContainer > xCont(xInt, uno::UNO_QUERY);
+ rVal <<= xCont;
+ }
+ break;
+ case MID_URL_SERVERMAP:
+ {
+ sal_Bool bTmp = IsServerMap();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtURL::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_URL_URL:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetURL( sTmp, bIsServerMap );
+ }
+ break;
+ case MID_URL_TARGET:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetTargetFrameName( sTmp );
+ }
+ break;
+ case MID_URL_HYPERLINKNAME:
+ {
+ OUString sTmp;
+ rVal >>= sTmp;
+ SetName( sTmp );
+ }
+ break;
+ case MID_URL_CLIENTMAP:
+ {
+ uno::Reference<container::XIndexContainer> xCont;
+ if(!rVal.hasValue())
+ DELETEZ(pMap);
+ else if(rVal >>= xCont)
+ {
+ if(!pMap)
+ pMap = new ImageMap;
+ bRet = SvUnoImageMap_fillImageMap( xCont, *pMap );
+ }
+ else
+ bRet = false;
+ }
+ break;
+ case MID_URL_SERVERMAP:
+ bIsServerMap = *(sal_Bool*)rVal.getValue();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwNoReadOnly
+
+SfxPoolItem* SwFmtEditInReadonly::Clone( SfxItemPool* ) const
+{
+ return new SwFmtEditInReadonly( Which(), GetValue() );
+}
+
+// class SwFmtLayoutSplit
+
+SfxPoolItem* SwFmtLayoutSplit::Clone( SfxItemPool* ) const
+{
+ return new SwFmtLayoutSplit( GetValue() );
+}
+
+// class SwFmtRowSplit
+
+SfxPoolItem* SwFmtRowSplit::Clone( SfxItemPool* ) const
+{
+ return new SwFmtRowSplit( GetValue() );
+}
+
+
+// class SwFmtNoBalancedColumns
+
+SfxPoolItem* SwFmtNoBalancedColumns::Clone( SfxItemPool* ) const
+{
+ return new SwFmtNoBalancedColumns( GetValue() );
+}
+
+// class SwFmtFtnEndAtTxtEnd
+
+sal_uInt16 SwFmtFtnEndAtTxtEnd::GetValueCount() const
+{
+ return sal_uInt16( FTNEND_ATTXTEND_END );
+}
+
+SwFmtFtnEndAtTxtEnd& SwFmtFtnEndAtTxtEnd::operator=(
+ const SwFmtFtnEndAtTxtEnd& rAttr )
+{
+ SfxEnumItem::SetValue( rAttr.GetValue() );
+ aFmt = rAttr.aFmt;
+ nOffset = rAttr.nOffset;
+ sPrefix = rAttr.sPrefix;
+ sSuffix = rAttr.sSuffix;
+ return *this;
+}
+
+int SwFmtFtnEndAtTxtEnd::operator==( const SfxPoolItem& rItem ) const
+{
+ const SwFmtFtnEndAtTxtEnd& rAttr = (SwFmtFtnEndAtTxtEnd&)rItem;
+ return SfxEnumItem::operator==( rAttr ) &&
+ aFmt.GetNumberingType() == rAttr.aFmt.GetNumberingType() &&
+ nOffset == rAttr.nOffset &&
+ sPrefix == rAttr.sPrefix &&
+ sSuffix == rAttr.sSuffix;
+}
+
+bool SwFmtFtnEndAtTxtEnd::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_COLLECT :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_RESTART_NUM :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND_OWNNUMSEQ;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_NUM_START_AT: rVal <<= (sal_Int16) nOffset; break;
+ case MID_OWN_NUM :
+ {
+ sal_Bool bVal = GetValue() >= FTNEND_ATTXTEND_OWNNUMANDFMT;
+ rVal.setValue(&bVal, ::getBooleanCppuType());
+ }
+ break;
+ case MID_NUM_TYPE : rVal <<= aFmt.GetNumberingType(); break;
+ case MID_PREFIX : rVal <<= OUString(sPrefix); break;
+ case MID_SUFFIX : rVal <<= OUString(sSuffix); break;
+ default: return sal_False;
+ }
+ return true;
+}
+
+bool SwFmtFtnEndAtTxtEnd::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ nMemberId &= ~CONVERT_TWIPS;
+ switch(nMemberId)
+ {
+ case MID_COLLECT :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND)
+ SetValue(FTNEND_ATPGORDOCEND);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND)
+ SetValue(FTNEND_ATTXTEND);
+ }
+ break;
+ case MID_RESTART_NUM :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND_OWNNUMSEQ)
+ SetValue(FTNEND_ATTXTEND);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND_OWNNUMSEQ)
+ SetValue(FTNEND_ATTXTEND_OWNNUMSEQ);
+ }
+ break;
+ case MID_NUM_START_AT:
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ if(nVal >= 0)
+ nOffset = nVal;
+ else
+ bRet = false;
+ }
+ break;
+ case MID_OWN_NUM :
+ {
+ sal_Bool bVal = *(sal_Bool*)rVal.getValue();
+ if(!bVal && GetValue() >= FTNEND_ATTXTEND_OWNNUMANDFMT)
+ SetValue(FTNEND_ATTXTEND_OWNNUMSEQ);
+ else if(bVal && GetValue() < FTNEND_ATTXTEND_OWNNUMANDFMT)
+ SetValue(FTNEND_ATTXTEND_OWNNUMANDFMT);
+ }
+ break;
+ case MID_NUM_TYPE :
+ {
+ sal_Int16 nVal = 0;
+ rVal >>= nVal;
+ if(nVal >= 0 &&
+ (nVal <= SVX_NUM_ARABIC ||
+ SVX_NUM_CHARS_UPPER_LETTER_N == nVal ||
+ SVX_NUM_CHARS_LOWER_LETTER_N == nVal ))
+ aFmt.SetNumberingType(nVal);
+ else
+ bRet = false;
+ }
+ break;
+ case MID_PREFIX :
+ {
+ OUString sVal; rVal >>= sVal;
+ sPrefix = sVal;
+ }
+ break;
+ case MID_SUFFIX :
+ {
+ OUString sVal; rVal >>= sVal;
+ sSuffix = sVal;
+ }
+ break;
+ default: bRet = false;
+ }
+ return bRet;
+}
+
+
+// class SwFmtFtnAtTxtEnd
+
+SfxPoolItem* SwFmtFtnAtTxtEnd::Clone( SfxItemPool* ) const
+{
+ SwFmtFtnAtTxtEnd* pNew = new SwFmtFtnAtTxtEnd;
+ *pNew = *this;
+ return pNew;
+}
+
+// class SwFmtEndAtTxtEnd
+
+SfxPoolItem* SwFmtEndAtTxtEnd::Clone( SfxItemPool* ) const
+{
+ SwFmtEndAtTxtEnd* pNew = new SwFmtEndAtTxtEnd;
+ *pNew = *this;
+ return pNew;
+}
+
+//class SwFmtChain
+
+
+int SwFmtChain::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+
+ return GetPrev() == ((SwFmtChain&)rAttr).GetPrev() &&
+ GetNext() == ((SwFmtChain&)rAttr).GetNext();
+}
+
+SwFmtChain::SwFmtChain( const SwFmtChain &rCpy ) :
+ SfxPoolItem( RES_CHAIN )
+{
+ SetPrev( rCpy.GetPrev() );
+ SetNext( rCpy.GetNext() );
+}
+
+SfxPoolItem* SwFmtChain::Clone( SfxItemPool* ) const
+{
+ SwFmtChain *pRet = new SwFmtChain;
+ pRet->SetPrev( GetPrev() );
+ pRet->SetNext( GetNext() );
+ return pRet;
+}
+
+void SwFmtChain::SetPrev( SwFlyFrmFmt *pFmt )
+{
+ if ( pFmt )
+ pFmt->Add( &aPrev );
+ else if ( aPrev.GetRegisteredIn() )
+ ((SwModify*)aPrev.GetRegisteredIn())->Remove( &aPrev );
+}
+
+void SwFmtChain::SetNext( SwFlyFrmFmt *pFmt )
+{
+ if ( pFmt )
+ pFmt->Add( &aNext );
+ else if ( aNext.GetRegisteredIn() )
+ ((SwModify*)aNext.GetRegisteredIn())->Remove( &aNext );
+}
+
+bool SwFmtChain::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ XubString aRet;
+ switch ( nMemberId )
+ {
+ case MID_CHAIN_PREVNAME:
+ if ( GetPrev() )
+ aRet = GetPrev()->GetName();
+ break;
+ case MID_CHAIN_NEXTNAME:
+ if ( GetNext() )
+ aRet = GetNext()->GetName();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ rVal <<= OUString(aRet);
+ return bRet;
+}
+
+
+
+
+//class SwFmtLineNumber
+
+SwFmtLineNumber::SwFmtLineNumber() :
+ SfxPoolItem( RES_LINENUMBER )
+{
+ nStartValue = 0;
+ bCountLines = sal_True;
+}
+
+SwFmtLineNumber::~SwFmtLineNumber()
+{
+}
+
+int SwFmtLineNumber::operator==( const SfxPoolItem &rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+
+ return nStartValue == ((SwFmtLineNumber&)rAttr).GetStartValue() &&
+ bCountLines == ((SwFmtLineNumber&)rAttr).IsCount();
+}
+
+SfxPoolItem* SwFmtLineNumber::Clone( SfxItemPool* ) const
+{
+ return new SwFmtLineNumber( *this );
+}
+
+bool SwFmtLineNumber::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_LINENUMBER_COUNT:
+ {
+ sal_Bool bTmp = IsCount();
+ rVal.setValue(&bTmp, ::getBooleanCppuType());
+ }
+ break;
+ case MID_LINENUMBER_STARTVALUE:
+ rVal <<= (sal_Int32)GetStartValue();
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+bool SwFmtLineNumber::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ // hier wird immer konvertiert!
+ nMemberId &= ~CONVERT_TWIPS;
+ bool bRet = true;
+ switch ( nMemberId )
+ {
+ case MID_LINENUMBER_COUNT:
+ SetCountLines( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_LINENUMBER_STARTVALUE:
+ {
+ sal_Int32 nVal = 0;
+ if(rVal >>= nVal)
+ SetStartValue( nVal );
+ else
+ bRet = false;
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "unknown MemberId" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+ * class SwTextGridItem
+ *************************************************************************/
+
+SwTextGridItem::SwTextGridItem()
+ : SfxPoolItem( RES_TEXTGRID ), aColor( COL_LIGHTGRAY ), nLines( 20 ),
+ nBaseHeight( 400 ), nRubyHeight( 200 ), eGridType( GRID_NONE ),
+ bRubyTextBelow( 0 ), bPrintGrid( 1 ), bDisplayGrid( 1 ),
+ nBaseWidth(400), bSnapToChars( 1 ), bSquaredMode(1)
+{
+}
+
+SwTextGridItem::~SwTextGridItem()
+{
+}
+
+int SwTextGridItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return eGridType == ((SwTextGridItem&)rAttr).GetGridType() &&
+ nLines == ((SwTextGridItem&)rAttr).GetLines() &&
+ nBaseHeight == ((SwTextGridItem&)rAttr).GetBaseHeight() &&
+ nRubyHeight == ((SwTextGridItem&)rAttr).GetRubyHeight() &&
+ bRubyTextBelow == ((SwTextGridItem&)rAttr).GetRubyTextBelow() &&
+ bDisplayGrid == ((SwTextGridItem&)rAttr).GetDisplayGrid() &&
+ bPrintGrid == ((SwTextGridItem&)rAttr).GetPrintGrid() &&
+ aColor == ((SwTextGridItem&)rAttr).GetColor() &&
+ nBaseWidth == ((SwTextGridItem&)rAttr).GetBaseWidth() &&
+ bSnapToChars == ((SwTextGridItem&)rAttr).GetSnapToChars() &&
+ bSquaredMode == ((SwTextGridItem&)rAttr).GetSquaredMode();
+}
+
+SfxPoolItem* SwTextGridItem::Clone( SfxItemPool* ) const
+{
+ return new SwTextGridItem( *this );
+}
+
+SwTextGridItem& SwTextGridItem::operator=( const SwTextGridItem& rCpy )
+{
+ aColor = rCpy.GetColor();
+ nLines = rCpy.GetLines();
+ nBaseHeight = rCpy.GetBaseHeight();
+ nRubyHeight = rCpy.GetRubyHeight();
+ eGridType = rCpy.GetGridType();
+ bRubyTextBelow = rCpy.GetRubyTextBelow();
+ bPrintGrid = rCpy.GetPrintGrid();
+ bDisplayGrid = rCpy.GetDisplayGrid();
+ nBaseWidth = rCpy.GetBaseWidth();
+ bSnapToChars = rCpy.GetSnapToChars();
+ bSquaredMode = rCpy.GetSquaredMode();
+
+ return *this;
+}
+
+bool SwTextGridItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
+{
+ bool bRet = true;
+
+ switch( nMemberId & ~CONVERT_TWIPS )
+ {
+ case MID_GRID_COLOR:
+ rVal <<= GetColor().GetColor();
+ break;
+ case MID_GRID_LINES:
+ rVal <<= GetLines();
+ break;
+ case MID_GRID_RUBY_BELOW:
+ rVal.setValue( &bRubyTextBelow, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_PRINT:
+ rVal.setValue( &bPrintGrid, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_DISPLAY:
+ rVal.setValue( &bDisplayGrid, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_BASEHEIGHT:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32) TWIP_TO_MM100_UNSIGNED(nBaseHeight);
+ break;
+ case MID_GRID_BASEWIDTH:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32) TWIP_TO_MM100_UNSIGNED(nBaseWidth);
+ break;
+ case MID_GRID_RUBYHEIGHT:
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ rVal <<= (sal_Int32)TWIP_TO_MM100_UNSIGNED(nRubyHeight);
+ break;
+ case MID_GRID_TYPE:
+ switch( GetGridType() )
+ {
+ case GRID_NONE:
+ rVal <<= text::TextGridMode::NONE;
+ break;
+ case GRID_LINES_ONLY:
+ rVal <<= text::TextGridMode::LINES;
+ break;
+ case GRID_LINES_CHARS:
+ rVal <<= text::TextGridMode::LINES_AND_CHARS;
+ break;
+ default:
+ OSL_FAIL("unknown SwTextGrid value");
+ bRet = false;
+ break;
+ }
+ break;
+ case MID_GRID_SNAPTOCHARS:
+ rVal.setValue( &bSnapToChars, ::getBooleanCppuType() );
+ break;
+ case MID_GRID_STANDARD_MODE:
+ {
+ sal_Bool bStandardMode = !bSquaredMode;
+ rVal.setValue( &bStandardMode, ::getBooleanCppuType() );
+ }
+ break;
+ default:
+ OSL_FAIL("Unknown SwTextGridItem member");
+ bRet = false;
+ break;
+ }
+
+ return bRet;
+}
+
+bool SwTextGridItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
+{
+ bool bRet = true;
+ switch( nMemberId & ~CONVERT_TWIPS )
+ {
+ case MID_GRID_COLOR:
+ {
+ sal_Int32 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet )
+ SetColor( Color(nTmp) );
+ }
+ break;
+ case MID_GRID_LINES:
+ {
+ sal_Int16 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet && (nTmp >= 0) )
+ SetLines( (sal_uInt16)nTmp );
+ else
+ bRet = false;
+ }
+ break;
+ case MID_GRID_RUBY_BELOW:
+ SetRubyTextBelow( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_PRINT:
+ SetPrintGrid( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_DISPLAY:
+ SetDisplayGrid( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_BASEHEIGHT:
+ case MID_GRID_BASEWIDTH:
+ case MID_GRID_RUBYHEIGHT:
+ {
+ DBG_ASSERT( (nMemberId & CONVERT_TWIPS) != 0,
+ "This value needs TWIPS-MM100 conversion" );
+ sal_Int32 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ nTmp = MM100_TO_TWIP( nTmp );
+ if( bRet && (nTmp >= 0) && ( nTmp <= USHRT_MAX) )
+ if( (nMemberId & ~CONVERT_TWIPS) == MID_GRID_BASEHEIGHT )
+ SetBaseHeight( (sal_uInt16)nTmp );
+ else if( (nMemberId & ~CONVERT_TWIPS) == MID_GRID_BASEWIDTH )
+ SetBaseWidth( (sal_uInt16)nTmp );
+ else
+ SetRubyHeight( (sal_uInt16)nTmp );
+ else
+ bRet = false;
+ }
+ break;
+ case MID_GRID_TYPE:
+ {
+ sal_Int16 nTmp = 0;
+ bRet = (rVal >>= nTmp);
+ if( bRet )
+ {
+ switch( nTmp )
+ {
+ case text::TextGridMode::NONE:
+ SetGridType( GRID_NONE );
+ break;
+ case text::TextGridMode::LINES:
+ SetGridType( GRID_LINES_ONLY );
+ break;
+ case text::TextGridMode::LINES_AND_CHARS:
+ SetGridType( GRID_LINES_CHARS );
+ break;
+ default:
+ bRet = false;
+ break;
+ }
+ }
+ break;
+ }
+ case MID_GRID_SNAPTOCHARS:
+ SetSnapToChars( *(sal_Bool*)rVal.getValue() );
+ break;
+ case MID_GRID_STANDARD_MODE:
+ {
+ sal_Bool bStandard = *(sal_Bool*)rVal.getValue();
+ SetSquaredMode( !bStandard );
+ break;
+ }
+ default:
+ OSL_FAIL("Unknown SwTextGridItem member");
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+void SwTextGridItem::SwitchPaperMode(sal_Bool bNew)
+{
+ if( bNew == bSquaredMode )
+ {
+ //same paper mode, not switch
+ return;
+ }
+
+ // use default value when grid is disable
+ if( eGridType == GRID_NONE )
+ {
+ bSquaredMode = bNew;
+ Init();
+ return;
+ }
+
+ if( bSquaredMode )
+ {
+ //switch from "squared mode" to "standard mode"
+ nBaseWidth = nBaseHeight;
+ nBaseHeight = nBaseHeight + nRubyHeight;
+ nRubyHeight = 0;
+ }
+ else
+ {
+ //switch from "standard mode" to "squared mode"
+ nRubyHeight = nBaseHeight/3;
+ nBaseHeight = nBaseHeight - nRubyHeight;
+ nBaseWidth = nBaseHeight;
+ }
+ bSquaredMode = !bSquaredMode;
+}
+
+void SwTextGridItem::Init()
+{
+ if( bSquaredMode )
+ {
+ nLines = 20;
+ nBaseHeight = 400;
+ nRubyHeight = 200;
+ eGridType = GRID_NONE;
+ bRubyTextBelow = 0;
+ bPrintGrid = 1;
+ bDisplayGrid = 1;
+ bSnapToChars = 1;
+ nBaseWidth = 400;
+ }
+ else
+ {
+ nLines = 44;
+ nBaseHeight = 312;
+ nRubyHeight = 0;
+ eGridType = GRID_NONE;
+ bRubyTextBelow = 0;
+ bPrintGrid = 1;
+ bDisplayGrid = 1;
+ nBaseWidth = 210;
+ bSnapToChars = 1;
+
+ //default grid type is line only in CJK env
+ //disable this function due to type area change
+ //if grid type change.
+ //if(SvtCJKOptions().IsAsianTypographyEnabled())
+ //{
+ // bDisplayGrid = 0;
+ // eGridType = GRID_LINES_ONLY;
+ //}
+ }
+}
+// class SwHeaderAndFooterEatSpacingItem
+
+SfxPoolItem* SwHeaderAndFooterEatSpacingItem::Clone( SfxItemPool* ) const
+{
+ return new SwHeaderAndFooterEatSpacingItem( Which(), GetValue() );
+}
+
+
+// class SwFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwFrmFmt, SwFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL_DLL( SwFrmFmt, 20, 20 )
+
+void SwFrmFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
+{
+ SwFmtHeader *pH = 0;
+ SwFmtFooter *pF = 0;
+
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+
+ if( RES_ATTRSET_CHG == nWhich )
+ {
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_HEADER, sal_False, (const SfxPoolItem**)&pH );
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState(
+ RES_FOOTER, sal_False, (const SfxPoolItem**)&pF );
+ }
+ else if( RES_HEADER == nWhich )
+ pH = (SwFmtHeader*)pNew;
+ else if( RES_FOOTER == nWhich )
+ pF = (SwFmtFooter*)pNew;
+
+ if( pH && pH->IsActive() && !pH->GetHeaderFmt() )
+ { //Hat er keinen, mach ich ihm einen
+ SwFrmFmt *pFmt = GetDoc()->MakeLayoutFmt( RND_STD_HEADER, 0 );
+ pH->RegisterToFormat( *pFmt );
+ }
+
+ if( pF && pF->IsActive() && !pF->GetFooterFmt() )
+ { //Hat er keinen, mach ich ihm einen
+ SwFrmFmt *pFmt = GetDoc()->MakeLayoutFmt( RND_STD_FOOTER, 0 );
+ pF->RegisterToFormat( *pFmt );
+ }
+
+ // MIB 24.3.98: Modify der Basisklasse muss immer gerufen werden, z.B.
+ // wegen RESET_FMTWRITTEN.
+// if ( GetDepends() )
+ SwFmt::Modify( pOld, pNew );
+
+ if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
+ { // invalidate cached uno object
+ SetXObject(uno::Reference<uno::XInterface>(0));
+ }
+}
+
+void SwFrmFmt::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+//Vernichtet alle Frms, die in aDepend angemeldet sind.
+
+void SwFrmFmt::DelFrms()
+{
+ SwIterator<SwFrm,SwFmt> aIter( *this );
+ SwFrm * pLast = aIter.First();
+ if( pLast )
+ do {
+ pLast->Cut();
+ delete pLast;
+ } while( 0 != ( pLast = aIter.Next() ));
+}
+
+void SwFrmFmt::MakeFrms()
+{
+ OSL_ENSURE( !this, "Sorry not implemented." );
+}
+
+
+
+SwRect SwFrmFmt::FindLayoutRect( const sal_Bool bPrtArea, const Point* pPoint,
+ const sal_Bool bCalcFrm ) const
+{
+ SwRect aRet;
+ SwFrm *pFrm = 0;
+ if( ISA( SwSectionFmt ) )
+ {
+ // dann den frame::Frame per Node2Layout besorgen
+ SwSectionNode* pSectNd = ((SwSectionFmt*)this)->GetSectionNode();
+ if( pSectNd )
+ {
+ SwNode2Layout aTmp( *pSectNd, pSectNd->GetIndex() - 1 );
+ pFrm = aTmp.NextFrm();
+
+ if( pFrm && !pFrm->KnowsFormat(*this) )
+ {
+ // die Section hat keinen eigenen frame::Frame, also falls
+ // jemand die tatsaechliche Groe?e braucht, so muss das
+ // noch implementier werden, in dem sich vom Ende noch
+ // der entsprechende frame::Frame besorgt wird.
+ // PROBLEM: was passiert bei SectionFrames, die auf unter-
+ // schiedlichen Seiten stehen??
+ if( bPrtArea )
+ aRet = pFrm->Prt();
+ else
+ {
+ aRet = pFrm->Frm();
+ --aRet.Pos().Y();
+ }
+ pFrm = 0; // das Rect ist ja jetzt fertig
+ }
+ }
+ }
+ else
+ {
+ sal_uInt16 nFrmType = RES_FLYFRMFMT == Which() ? FRM_FLY : USHRT_MAX;
+ pFrm = ::GetFrmOfModify( 0, *(SwModify*)this, nFrmType, pPoint,
+ 0, bCalcFrm );
+ }
+
+ if( pFrm )
+ {
+ if( bPrtArea )
+ aRet = pFrm->Prt();
+ else
+ aRet = pFrm->Frm();
+ }
+ return aRet;
+}
+
+SwContact* SwFrmFmt::FindContactObj()
+{
+ return SwIterator<SwContact,SwFmt>::FirstElement( *this );
+}
+
+SdrObject* SwFrmFmt::FindSdrObject()
+{
+ // --> OD 2005-01-06 #i30669# - use method <FindContactObj()> instead of
+ // duplicated code.
+ SwContact* pFoundContact = FindContactObj();
+ return pFoundContact ? pFoundContact->GetMaster() : 0;
+ // <--
+}
+
+SdrObject* SwFrmFmt::FindRealSdrObject()
+{
+ if( RES_FLYFRMFMT == Which() )
+ {
+ Point aNullPt;
+ SwFlyFrm* pFly = (SwFlyFrm*)::GetFrmOfModify( 0, *this, FRM_FLY,
+ &aNullPt, 0, sal_False );
+ return pFly ? pFly->GetVirtDrawObj() : 0;
+ }
+ return FindSdrObject();
+}
+
+
+sal_Bool SwFrmFmt::IsLowerOf( const SwFrmFmt& rFmt ) const
+{
+ //Auch eine Verkettung von Innen nach aussen oder von aussen
+ //nach innen ist nicht zulaessig.
+ SwFlyFrm *pSFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(*this);
+ if( pSFly )
+ {
+ SwFlyFrm *pAskFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(rFmt);
+ if( pAskFly )
+ return pSFly->IsLowerOf( pAskFly );
+ }
+
+ // dann mal ueber die Node-Positionen versuchen
+ const SwFmtAnchor* pAnchor = &rFmt.GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) && pAnchor->GetCntntAnchor())
+ {
+ const SwSpzFrmFmts& rFmts = *GetDoc()->GetSpzFrmFmts();
+ const SwNode* pFlyNd = pAnchor->GetCntntAnchor()->nNode.GetNode().
+ FindFlyStartNode();
+ while( pFlyNd )
+ {
+ // dann ueber den Anker nach oben "hangeln"
+ sal_uInt16 n;
+ for( n = 0; n < rFmts.Count(); ++n )
+ {
+ const SwFrmFmt* pFmt = rFmts[ n ];
+ const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
+ if( pIdx && pFlyNd == &pIdx->GetNode() )
+ {
+ if( pFmt == this )
+ return sal_True;
+
+ pAnchor = &pFmt->GetAnchor();
+ if ((FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
+ !pAnchor->GetCntntAnchor() )
+ {
+ return sal_False;
+ }
+
+ pFlyNd = pAnchor->GetCntntAnchor()->nNode.GetNode().
+ FindFlyStartNode();
+ break;
+ }
+ }
+ if( n >= rFmts.Count() )
+ {
+ OSL_ENSURE( !this, "Fly-Section aber kein Format gefunden" );
+ return sal_False;
+ }
+ }
+ }
+ return sal_False;
+}
+
+// --> OD 2004-07-27 #i31698#
+SwFrmFmt::tLayoutDir SwFrmFmt::GetLayoutDir() const
+{
+ return SwFrmFmt::HORI_L2R;
+}
+
+void SwFrmFmt::SetLayoutDir( const SwFrmFmt::tLayoutDir )
+{
+ // empty body, because default implementation does nothing
+}
+// <--
+
+// --> OD 2004-08-06 #i28749#
+sal_Int16 SwFrmFmt::GetPositionLayoutDir() const
+{
+ return text::PositionLayoutDir::PositionInLayoutDirOfAnchor;
+}
+void SwFrmFmt::SetPositionLayoutDir( const sal_Int16 )
+{
+ // empty body, because default implementation does nothing
+}
+// <--
+String SwFrmFmt::GetDescription() const
+{
+ return SW_RES(STR_FRAME);
+}
+
+// class SwFlyFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwFlyFrmFmt, SwFrmFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL( SwFlyFrmFmt, 10, 10 )
+
+SwFlyFrmFmt::~SwFlyFrmFmt()
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( *this );
+ SwFlyFrm * pLast = aIter.First();
+ if( pLast )
+ do {
+ delete pLast;
+ } while( 0 != ( pLast = aIter.Next() ));
+
+ SwIterator<SwFlyDrawContact,SwFmt> a2ndIter( *this );
+ SwFlyDrawContact* pC = a2ndIter.First();
+ if( pC )
+ do {
+ delete pC;
+
+ } while( 0 != ( pC = a2ndIter.Next() ));
+}
+
+//Erzeugen der Frms wenn das Format einen Absatzgebundenen Rahmen beschreibt.
+//MA: 14. Feb. 94, Erzeugen der Frms auch fuer Seitengebundene Rahmen.
+
+void SwFlyFrmFmt::MakeFrms()
+{
+ // gibts ueberhaupt ein Layout ??
+ if( !GetDoc()->GetCurrentViewShell() )
+ return; //swmod 071108//swmod 071225
+
+ SwModify *pModify = 0;
+ // OD 24.07.2003 #111032# - create local copy of anchor attribute for possible changes.
+ SwFmtAnchor aAnchorAttr( GetAnchor() );
+ switch( aAnchorAttr.GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ if( aAnchorAttr.GetCntntAnchor() )
+ {
+ pModify = aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ }
+ break;
+
+ case FLY_AT_FLY:
+ if( aAnchorAttr.GetCntntAnchor() )
+ {
+ //Erst einmal ueber den Inhalt suchen, weil konstant schnell. Kann
+ //Bei verketteten Rahmen aber auch schief gehen, weil dann evtl.
+ //niemals ein frame::Frame zu dem Inhalt existiert. Dann muss leider noch
+ //die Suche vom StartNode zum FrameFormat sein.
+ SwNodeIndex aIdx( aAnchorAttr.GetCntntAnchor()->nNode );
+ SwCntntNode *pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
+ // --> OD 2009-12-28 #i105535#
+ if ( pCNd == 0 )
+ {
+ pCNd = aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ }
+ if ( pCNd )
+ // <--
+ {
+ if( SwIterator<SwFrm,SwCntntNode>::FirstElement( *pCNd ) )
+ {
+ pModify = pCNd;
+ }
+ }
+ // --> OD 2009-12-28 #i105535#
+ if ( pModify == 0 )
+ // <--
+ {
+ const SwNodeIndex &rIdx = aAnchorAttr.GetCntntAnchor()->nNode;
+ SwSpzFrmFmts& rFmts = *GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 i = 0; i < rFmts.Count(); ++i )
+ {
+ SwFrmFmt* pFlyFmt = rFmts[i];
+ if( pFlyFmt->GetCntnt().GetCntntIdx() &&
+ rIdx == *pFlyFmt->GetCntnt().GetCntntIdx() )
+ {
+ pModify = pFlyFmt;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case FLY_AT_PAGE:
+ {
+ sal_uInt16 nPgNum = aAnchorAttr.GetPageNum();
+ SwPageFrm *pPage = (SwPageFrm*)GetDoc()->GetCurrentLayout()->Lower(); //swmod 080218
+ if( !nPgNum && aAnchorAttr.GetCntntAnchor() )
+ {
+ SwCntntNode *pCNd =
+ aAnchorAttr.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
+ SwIterator<SwFrm,SwCntntNode> aIter( *pCNd );
+ for (SwFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ pPage = pFrm->FindPageFrm();
+ if( pPage )
+ {
+ nPgNum = pPage->GetPhyPageNum();
+ // OD 24.07.2003 #111032# - update anchor attribute
+ aAnchorAttr.SetPageNum( nPgNum );
+ aAnchorAttr.SetAnchor( 0 );
+ SetFmtAttr( aAnchorAttr );
+ }
+ break;
+ }
+ }
+ while ( pPage )
+ {
+ if ( pPage->GetPhyPageNum() == nPgNum )
+ {
+ // --> OD 2005-06-09 #i50432# - adjust synopsis of <PlaceFly(..)>
+ pPage->PlaceFly( 0, this );
+ // <--
+ break;
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if( pModify )
+ {
+ SwIterator<SwFrm,SwModify> aIter( *pModify );
+ for( SwFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ sal_Bool bAdd = !pFrm->IsCntntFrm() ||
+ !((SwCntntFrm*)pFrm)->IsFollow();
+
+ if ( FLY_AT_FLY == aAnchorAttr.GetAnchorId() && !pFrm->IsFlyFrm() )
+ {
+ // --> OD 2009-12-28 #i105535#
+ // fallback to anchor type at-paragraph, if no fly frame is found.
+// pFrm = pFrm->FindFlyFrm();
+ SwFrm* pFlyFrm = pFrm->FindFlyFrm();
+ if ( pFlyFrm )
+ {
+ pFrm = pFlyFrm;
+ }
+ else
+ {
+ aAnchorAttr.SetType( FLY_AT_PARA );
+ SetFmtAttr( aAnchorAttr );
+ MakeFrms();
+ return;
+ }
+ // <--
+ }
+
+ if( pFrm->GetDrawObjs() )
+ {
+ // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+ SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ SwAnchoredObject* pObj = rObjs[i];
+ if( pObj->ISA(SwFlyFrm) &&
+ (&pObj->GetFrmFmt()) == this )
+ {
+ bAdd = sal_False;
+ break;
+ }
+ }
+ }
+
+ if( bAdd )
+ {
+ SwFlyFrm *pFly = 0;
+ switch( aAnchorAttr.GetAnchorId() )
+ {
+ case FLY_AT_FLY:
+ pFly = new SwFlyLayFrm( this, pFrm, pFrm );
+ break;
+
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ pFly = new SwFlyAtCntFrm( this, pFrm, pFrm );
+ break;
+
+ case FLY_AS_CHAR:
+ pFly = new SwFlyInCntFrm( this, pFrm, pFrm );
+ break;
+ default:
+ OSL_ENSURE( !this, "Neuer Ankertyp" );
+ break;
+ }
+ pFrm->AppendFly( pFly );
+ SwPageFrm *pPage = pFly->FindPageFrm();
+ if( pPage )
+ ::RegistFlys( pPage, pFly );
+ }
+ }
+ }
+}
+
+SwFlyFrm* SwFlyFrmFmt::GetFrm( const Point* pPoint, const sal_Bool bCalcFrm ) const
+{
+ return (SwFlyFrm*)::GetFrmOfModify( 0, *(SwModify*)this, FRM_FLY,
+ pPoint, 0, bCalcFrm );
+}
+
+SwAnchoredObject* SwFlyFrmFmt::GetAnchoredObj( const Point* pPoint, const sal_Bool bCalcFrm ) const
+{
+ SwFlyFrm* pFlyFrm( GetFrm( pPoint, bCalcFrm ) );
+ if ( pFlyFrm )
+ {
+ return dynamic_cast<SwAnchoredObject*>(pFlyFrm);
+ }
+ else
+ {
+ return 0L;
+ }
+}
+
+
+sal_Bool SwFlyFrmFmt::GetInfo( SfxPoolItem& rInfo ) const
+{
+ switch( rInfo.Which() )
+ {
+ case RES_CONTENT_VISIBLE:
+ {
+ ((SwPtrMsgPoolItem&)rInfo).pObject = SwIterator<SwFrm,SwFmt>::FirstElement( *this );
+ }
+ return sal_False;
+
+ default:
+ return SwFrmFmt::GetInfo( rInfo );
+ }
+ return sal_True;
+}
+
+// --> OD 2009-07-14 #i73249#
+void SwFlyFrmFmt::SetObjTitle( const String& rTitle, bool bBroadcast )
+{
+ SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwNoTxtNode::SetObjTitle(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return;
+ }
+
+ if( bBroadcast )
+ {
+ SwStringMsgPoolItem aOld( RES_TITLE_CHANGED, pMasterObject->GetTitle() );
+ SwStringMsgPoolItem aNew( RES_TITLE_CHANGED, rTitle );
+ pMasterObject->SetTitle( rTitle );
+ ModifyNotification( &aOld, &aNew );
+ }
+ else
+ {
+ pMasterObject->SetTitle( rTitle );
+ }
+}
+
+const String SwFlyFrmFmt::GetObjTitle() const
+{
+ const SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwFlyFrmFmt::GetObjTitle(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return aEmptyStr;
+ }
+
+ return pMasterObject->GetTitle();
+}
+
+void SwFlyFrmFmt::SetObjDescription( const String& rDescription, bool bBroadcast )
+{
+ SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwFlyFrmFmt::SetDescription(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return;
+ }
+
+ if( bBroadcast )
+ {
+ SwStringMsgPoolItem aOld( RES_DESCRIPTION_CHANGED, pMasterObject->GetDescription() );
+ SwStringMsgPoolItem aNew( RES_DESCRIPTION_CHANGED, rDescription );
+ pMasterObject->SetDescription( rDescription );
+ ModifyNotification( &aOld, &aNew );
+ }
+ else
+ {
+ pMasterObject->SetDescription( rDescription );
+ }
+}
+
+const String SwFlyFrmFmt::GetObjDescription() const
+{
+ const SdrObject* pMasterObject = FindSdrObject();
+ OSL_ENSURE( pMasterObject,
+ "<SwNoTxtNode::GetDescription(..)> - missing <SdrObject> instance" );
+ if ( !pMasterObject )
+ {
+ return aEmptyStr;
+ }
+
+ return pMasterObject->GetDescription();
+}
+// <--
+
+/** SwFlyFrmFmt::IsBackgroundTransparent - for #99657#
+
+ OD 22.08.2002 - overloading virtual method and its default implementation,
+ because format of fly frame provides transparent backgrounds.
+ Method determines, if background of fly frame is transparent.
+
+ @author OD
+
+ @return true, if background color is transparent, but not "no fill"
+ or the transparency of a existing background graphic is set.
+*/
+sal_Bool SwFlyFrmFmt::IsBackgroundTransparent() const
+{
+ sal_Bool bReturn = sal_False;
+
+ /// NOTE: If background color is "no fill"/"auto fill" (COL_TRANSPARENT)
+ /// and there is no background graphic, it "inherites" the background
+ /// from its anchor.
+ if ( (GetBackground().GetColor().GetTransparency() != 0) &&
+ (GetBackground().GetColor() != COL_TRANSPARENT)
+ )
+ {
+ bReturn = sal_True;
+ }
+ else
+ {
+ const GraphicObject *pTmpGrf =
+ static_cast<const GraphicObject*>(GetBackground().GetGraphicObject());
+ if ( (pTmpGrf) &&
+ (pTmpGrf->GetAttr().GetTransparency() != 0)
+ )
+ {
+ bReturn = sal_True;
+ }
+ }
+
+ return bReturn;
+}
+
+/** SwFlyFrmFmt::IsBackgroundBrushInherited - for #103898#
+
+ OD 08.10.2002 - method to determine, if the brush for drawing the
+ background is "inherited" from its parent/grandparent.
+ This is the case, if no background graphic is set and the background
+ color is "no fill"/"auto fill"
+ NOTE: condition is "copied" from method <SwFrm::GetBackgroundBrush(..).
+
+ @author OD
+
+ @return true, if background brush is "inherited" from parent/grandparent
+*/
+sal_Bool SwFlyFrmFmt::IsBackgroundBrushInherited() const
+{
+ sal_Bool bReturn = sal_False;
+
+ if ( (GetBackground().GetColor() == COL_TRANSPARENT) &&
+ !(GetBackground().GetGraphicObject()) )
+ {
+ bReturn = sal_True;
+ }
+
+ return bReturn;
+}
+
+// --> OD 2006-02-28 #125892#
+SwHandleAnchorNodeChg::SwHandleAnchorNodeChg( SwFlyFrmFmt& _rFlyFrmFmt,
+ const SwFmtAnchor& _rNewAnchorFmt,
+ SwFlyFrm* _pKeepThisFlyFrm )
+ : mrFlyFrmFmt( _rFlyFrmFmt ),
+ mbAnchorNodeChanged( false )
+{
+ const RndStdIds nNewAnchorType( _rNewAnchorFmt.GetAnchorId() );
+ if ( ((nNewAnchorType == FLY_AT_PARA) ||
+ (nNewAnchorType == FLY_AT_CHAR)) &&
+ _rNewAnchorFmt.GetCntntAnchor() &&
+ _rNewAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode() )
+ {
+ const SwFmtAnchor& aOldAnchorFmt( _rFlyFrmFmt.GetAnchor() );
+ if ( aOldAnchorFmt.GetAnchorId() == nNewAnchorType &&
+ aOldAnchorFmt.GetCntntAnchor() &&
+ aOldAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode() &&
+ aOldAnchorFmt.GetCntntAnchor()->nNode !=
+ _rNewAnchorFmt.GetCntntAnchor()->nNode )
+ {
+ // determine 'old' number of anchor frames
+ sal_uInt32 nOldNumOfAnchFrm( 0L );
+ SwIterator<SwFrm,SwCntntNode> aOldIter( *(aOldAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode()) );
+ for( SwFrm* pOld = aOldIter.First(); pOld; pOld = aOldIter.Next() )
+ {
+ ++nOldNumOfAnchFrm;
+ }
+ // determine 'new' number of anchor frames
+ sal_uInt32 nNewNumOfAnchFrm( 0L );
+ SwIterator<SwFrm,SwCntntNode> aNewIter( *(_rNewAnchorFmt.GetCntntAnchor()->nNode.GetNode().GetCntntNode()) );
+ for( SwFrm* pNew = aNewIter.First(); pNew; pNew = aNewIter.Next() )
+ {
+ ++nNewNumOfAnchFrm;
+ }
+ if ( nOldNumOfAnchFrm != nNewNumOfAnchFrm )
+ {
+ // delete existing fly frames except <_pKeepThisFlyFrm>
+ SwIterator<SwFrm,SwFmt> aIter( mrFlyFrmFmt );
+ SwFrm* pFrm = aIter.First();
+ if ( pFrm )
+ {
+ do {
+ if ( pFrm != _pKeepThisFlyFrm )
+ {
+ pFrm->Cut();
+ delete pFrm;
+ }
+ } while( 0 != ( pFrm = aIter.Next() ));
+ }
+ // indicate, that re-creation of fly frames necessary
+ mbAnchorNodeChanged = true;
+ }
+ }
+ }
+}
+
+SwHandleAnchorNodeChg::~SwHandleAnchorNodeChg()
+{
+ if ( mbAnchorNodeChanged )
+ {
+ mrFlyFrmFmt.MakeFrms();
+ }
+}
+// <--
+// class SwDrawFrmFmt
+// Implementierung teilweise inline im hxx
+
+TYPEINIT1( SwDrawFrmFmt, SwFrmFmt );
+IMPL_FIXEDMEMPOOL_NEWDEL( SwDrawFrmFmt, 10, 10 )
+
+SwDrawFrmFmt::~SwDrawFrmFmt()
+{
+ SwContact *pContact = FindContactObj();
+ delete pContact;
+}
+
+void SwDrawFrmFmt::MakeFrms()
+{
+ SwDrawContact *pContact = (SwDrawContact*)FindContactObj();
+ if ( pContact )
+ pContact->ConnectToLayout();
+}
+
+void SwDrawFrmFmt::DelFrms()
+{
+ SwDrawContact *pContact = (SwDrawContact *)FindContactObj();
+ if ( pContact ) //fuer den Reader und andere Unabwaegbarkeiten.
+ pContact->DisconnectFromLayout();
+}
+
+// --> OD 2004-07-27 #i31698#
+SwFrmFmt::tLayoutDir SwDrawFrmFmt::GetLayoutDir() const
+{
+ return meLayoutDir;
+}
+
+void SwDrawFrmFmt::SetLayoutDir( const SwFrmFmt::tLayoutDir _eLayoutDir )
+{
+ meLayoutDir = _eLayoutDir;
+}
+// <--
+
+// --> OD 2004-08-06 #i28749#
+sal_Int16 SwDrawFrmFmt::GetPositionLayoutDir() const
+{
+ return mnPositionLayoutDir;
+}
+void SwDrawFrmFmt::SetPositionLayoutDir( const sal_Int16 _nPositionLayoutDir )
+{
+ switch ( _nPositionLayoutDir )
+ {
+ case text::PositionLayoutDir::PositionInHoriL2R:
+ case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
+ {
+ mnPositionLayoutDir = _nPositionLayoutDir;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "<SwDrawFrmFmt::SetPositionLayoutDir(..)> - invalid attribute value." );
+ }
+ }
+}
+// <--
+
+String SwDrawFrmFmt::GetDescription() const
+{
+ String aResult;
+ const SdrObject * pSdrObj = FindSdrObject();
+
+ if (pSdrObj)
+ {
+ if (pSdrObj != pSdrObjCached)
+ {
+ SdrObject * pSdrObjCopy = pSdrObj->Clone();
+ SdrUndoNewObj * pSdrUndo = new SdrUndoNewObj(*pSdrObjCopy);
+ sSdrObjCachedComment = pSdrUndo->GetComment();
+
+ delete pSdrUndo;
+
+ pSdrObjCached = pSdrObj;
+ }
+
+ aResult = sSdrObjCachedComment;
+ }
+ else
+ aResult = SW_RES(STR_GRAPHIC);
+
+ return aResult;
+}
+
+IMapObject* SwFrmFmt::GetIMapObject( const Point& rPoint,
+ const SwFlyFrm *pFly ) const
+{
+ const SwFmtURL &rURL = GetURL();
+ if( !rURL.GetMap() )
+ return 0;
+
+ if( !pFly )
+ {
+ pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( *this );
+ if( !pFly )
+ return 0;
+ }
+
+ //Orignialgroesse fuer OLE und Grafik ist die TwipSize,
+ //ansonsten die Groesse vom FrmFmt des Fly.
+ const SwFrm *pRef;
+ SwNoTxtNode *pNd = 0;
+ Size aOrigSz;
+ if( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
+ {
+ pRef = pFly->Lower();
+ pNd = ((SwCntntFrm*)pRef)->GetNode()->GetNoTxtNode();
+ aOrigSz = pNd->GetTwipSize();
+ }
+ else
+ {
+ pRef = pFly;
+ aOrigSz = pFly->GetFmt()->GetFrmSize().GetSize();
+ }
+
+ if( aOrigSz.Width() != 0 && aOrigSz.Height() != 0 )
+ {
+ Point aPos( rPoint );
+ Size aActSz ( pRef == pFly ? pFly->Frm().SSize() : pRef->Prt().SSize() );
+ const MapMode aSrc ( MAP_TWIP );
+ const MapMode aDest( MAP_100TH_MM );
+ aOrigSz = OutputDevice::LogicToLogic( aOrigSz, aSrc, aDest );
+ aActSz = OutputDevice::LogicToLogic( aActSz, aSrc, aDest );
+ aPos -= pRef->Frm().Pos();
+ aPos -= pRef->Prt().Pos();
+ aPos = OutputDevice::LogicToLogic( aPos, aSrc, aDest );
+ sal_uInt32 nFlags = 0;
+ if ( pFly != pRef && pNd->IsGrfNode() )
+ {
+ const sal_uInt16 nMirror = pNd->GetSwAttrSet().
+ GetMirrorGrf().GetValue();
+ if ( RES_MIRROR_GRAPH_BOTH == nMirror )
+ nFlags = IMAP_MIRROR_HORZ | IMAP_MIRROR_VERT;
+ else if ( RES_MIRROR_GRAPH_VERT == nMirror )
+ nFlags = IMAP_MIRROR_VERT;
+ else if ( RES_MIRROR_GRAPH_HOR == nMirror )
+ nFlags = IMAP_MIRROR_HORZ;
+
+ }
+ return ((ImageMap*)rURL.GetMap())->GetHitIMapObject( aOrigSz,
+ aActSz, aPos, nFlags );
+ }
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
new file mode 100644
index 000000000000..e3bcf56ee9c4
--- /dev/null
+++ b/sw/source/core/layout/calcmove.cxx
@@ -0,0 +1,2116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "swtypes.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "txtftn.hxx"
+#include "fmtftn.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/keepitem.hxx>
+
+#include <vcl/outdev.hxx>
+#include <fmtfsize.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclbl.hxx>
+
+#include "tabfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "pagedesc.hxx"
+#include "ftninfo.hxx"
+#include "sectfrm.hxx"
+#include "dbg_lay.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+// --> OD 2004-11-01 #i36347#
+#include <flyfrms.hxx>
+// <--
+
+#include <ndtxt.hxx>
+
+//------------------------------------------------------------------------
+// Move-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwCntntFrm::ShouldBwdMoved()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm verschoben werden sollte.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwCntntFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool & )
+{
+ if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()))
+ {
+ //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
+ //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
+ //moechte die FixSize die gleiche ist, die der Frm selbst hat.
+ //In diesem Fall kann einfach geprueft werden, ob der Frm genug
+ //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
+ //gleich auf das Verschieben verzichtet werden.
+ //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
+ //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
+ //aufspalten kann.
+ //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
+ //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
+ //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
+ //etwas Platz zur Verfuegung steht).
+
+ //Die FixSize der Umgebungen in denen Cntnts herumlungern ist immer
+ //Die Breite.
+
+ //Wenn mehr als ein Blatt zurueckgegangen wurde (z.B. ueberspringen
+ //von Leerseiten), so muss in jedemfall gemoved werden - sonst wuerde,
+ //falls der Frm nicht in das Blatt passt, nicht mehr auf die
+ //dazwischenliegenden Blaetter geachtet werden.
+ sal_uInt8 nMoveAnyway = 0;
+ SwPageFrm * const pNewPage = pNewUpper->FindPageFrm();
+ SwPageFrm *pOldPage = FindPageFrm();
+
+ if ( SwFlowFrm::IsMoveBwdJump() )
+ return sal_True;
+
+ if( IsInFtn() && IsInSct() )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwSectionFrm* pMySect = pFtn->FindSctFrm();
+ if( pMySect && pMySect->IsFtnLock() )
+ {
+ SwSectionFrm *pSect = pNewUpper->FindSctFrm();
+ while( pSect && pSect->IsInFtn() )
+ pSect = pSect->GetUpper()->FindSctFrm();
+ OSL_ENSURE( pSect, "Escaping footnote" );
+ if( pSect != pMySect )
+ return sal_False;
+ }
+ }
+ SWRECTFN( this )
+ SWRECTFNX( pNewUpper )
+ if( Abs( (pNewUpper->Prt().*fnRectX->fnGetWidth)() -
+ (GetUpper()->Prt().*fnRect->fnGetWidth)() ) > 1 )
+ nMoveAnyway = 2; // Damit kommt nur noch ein _WouldFit mit Umhaengen in Frage
+
+ // OD 2004-05-26 #i25904# - do *not* move backward,
+ // if <nMoveAnyway> equals 3 and no space is left in new upper.
+ nMoveAnyway |= BwdMoveNecessary( pOldPage, Frm() );
+ {
+ const IDocumentSettingAccess* pIDSA = pNewPage->GetFmt()->getIDocumentSettingAccess();
+ SwTwips nSpace = 0;
+ SwRect aRect( pNewUpper->Prt() );
+ aRect.Pos() += pNewUpper->Frm().Pos();
+ const SwFrm *pPrevFrm = pNewUpper->Lower();
+ while ( pPrevFrm )
+ {
+ SwTwips nNewTop = (pPrevFrm->Frm().*fnRectX->fnGetBottom)();
+ // OD 2004-03-01 #106629#:
+ // consider lower spacing of last frame in a table cell
+ {
+ // check, if last frame is inside table and if it includes
+ // its lower spacing.
+ if ( !pPrevFrm->GetNext() && pPrevFrm->IsInTab() &&
+ pIDSA->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ const SwFrm* pLastFrm = pPrevFrm;
+ // if last frame is a section, take its last content
+ if ( pPrevFrm->IsSctFrm() )
+ {
+ pLastFrm = static_cast<const SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
+ if ( pLastFrm &&
+ pLastFrm->FindTabFrm() != pPrevFrm->FindTabFrm() )
+ {
+ pLastFrm = pLastFrm->FindTabFrm();
+ }
+ }
+
+ if ( pLastFrm )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pLastFrm );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ nNewTop -= rAttrs.GetULSpace().GetLower();
+ }
+ }
+ }
+ (aRect.*fnRectX->fnSetTop)( nNewTop );
+
+ pPrevFrm = pPrevFrm->GetNext();
+ }
+
+ nMoveAnyway |= BwdMoveNecessary( pNewPage, aRect);
+
+ //determine space left in new upper frame
+ nSpace = (aRect.*fnRectX->fnGetHeight)();
+ const ViewShell *pSh = pNewUpper->getRootFrm()->GetCurrShell();
+ if ( IsInFtn() ||
+ (pSh && pSh->GetViewOptions()->getBrowseMode()) ||
+ pNewUpper->IsCellFrm() ||
+ ( pNewUpper->IsInSct() && ( pNewUpper->IsSctFrm() ||
+ ( pNewUpper->IsColBodyFrm() &&
+ !pNewUpper->GetUpper()->GetPrev() &&
+ !pNewUpper->GetUpper()->GetNext() ) ) ) )
+ nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
+
+ if ( nMoveAnyway < 3 )
+ {
+ if ( nSpace )
+ {
+ //Keine Beruecksichtigung der Fussnoten die an dem Absatz
+ //kleben, denn dies wuerde extrem unuebersichtlichen Code
+ //beduerfen (wg. Beruecksichtung der Breiten und vor allem
+ //der Flys, die ja wieder Einfluss auf die Fussnoten nehmen...).
+
+ // _WouldFit kann bei gleicher Breite und _nur_ selbst verankerten Flys
+ // befragt werden.
+ // _WouldFit kann auch gefragt werden, wenn _nur_ fremdverankerte Flys vorliegen,
+ // dabei ist sogar die Breite egal, da ein TestFormat in der neuen Umgebung
+ // vorgenommen wird.
+ // --> OD 2007-11-26 #b6614158#
+ const sal_uInt8 nBwdMoveNecessaryResult =
+ BwdMoveNecessary( pNewPage, aRect);
+ const bool bObjsInNewUpper( nBwdMoveNecessaryResult == 2 ||
+ nBwdMoveNecessaryResult == 3 );
+
+ return _WouldFit( nSpace, pNewUpper, nMoveAnyway == 2,
+ bObjsInNewUpper );
+ // <--
+ }
+ //Bei einem spaltigen Bereichsfrischling kann _WouldFit kein
+ //brauchbares Ergebnis liefern, also muessen wir wirklich
+ //zurueckfliessen
+ else if( pNewUpper->IsInSct() && pNewUpper->IsColBodyFrm() &&
+ !(pNewUpper->Prt().*fnRectX->fnGetWidth)() &&
+ ( pNewUpper->GetUpper()->GetPrev() ||
+ pNewUpper->GetUpper()->GetNext() ) )
+ return sal_True;
+ else
+ return sal_False; // Kein Platz, dann ist es sinnlos, zurueckzufliessen
+ }
+ else
+ {
+ // OD 2004-05-26 #i25904# - check for space left in new upper
+ if ( nSpace )
+ return sal_True;
+ else
+ return sal_False;
+ }
+ }
+ }
+ return sal_False;
+}
+
+//------------------------------------------------------------------------
+// Calc-Methoden
+//------------------------------------------------------------------------
+
+/*************************************************************************
+|*
+|* SwFrm::Prepare()
+|*
+|* Beschreibung Bereitet den Frm auf die 'Formatierung' (MakeAll())
+|* vor. Diese Methode dient dazu auf dem Stack Platz einzusparen,
+|* denn zur Positionsberechnung des Frm muss sichergestellt sein, dass
+|* die Position von Upper und Prev gueltig sind, mithin also ein
+|* rekursiver Aufruf (Schleife waere relativ teuer, da selten notwendig).
+|* Jeder Aufruf von MakeAll verbraucht aber ca. 500Byte Stack -
+|* das Ende ist leicht abzusehen. _Prepare benoetigt nur wenig Stack,
+|* deshalb solle der Rekursive Aufruf hier kein Problem sein.
+|* Ein weiterer Vorteil ist, das eines schoenen Tages das _Prepare und
+|* damit die Formatierung von Vorgaengern umgangen werden kann.
+|* So kann evtl. mal 'schnell' an's Dokumentende gesprungen werden.
+|*
+|*************************************************************************/
+//Zwei kleine Freundschaften werden hier zu einem Geheimbund.
+inline void PrepareLock( SwFlowFrm *pTab )
+{
+ pTab->LockJoin();
+}
+inline void PrepareUnlock( SwFlowFrm *pTab )
+{
+ pTab->UnlockJoin();
+
+}
+
+// hopefully, one day this function simply will return 'false'
+bool lcl_IsCalcUpperAllowed( const SwFrm& rFrm )
+{
+ return !rFrm.GetUpper()->IsSctFrm() &&
+ !rFrm.GetUpper()->IsFooterFrm() &&
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ !rFrm.GetUpper()->IsFlyFrm() &&
+ // <--
+ !( rFrm.GetUpper()->IsTabFrm() && rFrm.GetUpper()->GetUpper()->IsInTab() ) &&
+ !( rFrm.IsTabFrm() && rFrm.GetUpper()->IsInTab() );
+}
+
+void SwFrm::PrepareMake()
+{
+ StackHack aHack;
+ if ( GetUpper() )
+ {
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+ sal_Bool bOldTabLock = sal_False, bFoll = sal_False;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ pThis = (SwTabFrm*)this;
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ bFoll = pThis->IsFollow();
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bFoll = pThis->IsFollow();
+ bNoSect = sal_False;
+ }
+ else if ( bCnt && sal_True == (bFoll = pThis->IsFollow()) &&
+ GetPrev() )
+ {
+ //Wenn der Master gereade ein CalcFollow ruft braucht die Kette
+ //nicht durchlaufen werden. Das spart Zeit und vermeidet Probleme.
+ if ( ((SwTxtFrm*)((SwTxtFrm*)this)->FindMaster())->IsLocked() )
+ {
+ MakeAll();
+ return;
+ }
+ }
+
+ // --> OD 2005-03-04 #i44049# - no format of previous frame, if current
+ // frame is a table frame and its previous frame wants to keep with it.
+ const bool bFormatPrev = !bTab ||
+ !GetPrev() ||
+ !GetPrev()->GetAttrSet()->GetKeep().GetValue();
+ if ( bFormatPrev )
+ {
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ //MA: 24. Mar. 94, Calc wuerde doch nur wieder in ein _Prepare laufen und so
+ //die ganze Kette nocheinmal abhuenern.
+ // pFrm->Calc();
+ pFrm->MakeAll();
+ if( IsSctFrm() && !((SwSectionFrm*)this)->GetSection() )
+ break;
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+
+ //Wenn wir in einem SectionFrm gestartet sind, koennen wir durch die
+ //MakeAll-Aufrufe in einen Section-Follow gewandert sein.
+ //FindNext liefert allerdings den SectionFrm, nicht seinen Inhalt.
+ // => wir finden uns selbst nicht mehr!
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ if ( lcl_IsCalcUpperAllowed( *this ) )
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+ }
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ MakeAll();
+}
+
+void SwFrm::OptPrepareMake()
+{
+ // --> OD 2004-11-02 #i23129#, #i36347# - no format of upper Writer fly frame
+ if ( GetUpper() && !GetUpper()->IsFooterFrm() &&
+ !GetUpper()->IsFlyFrm() )
+ // <--
+ {
+ GetUpper()->Calc();
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+ }
+ if ( GetPrev() && !GetPrev()->IsValid() )
+ PrepareMake();
+ else
+ {
+ StackHack aHack;
+ MakeAll();
+ }
+}
+
+
+
+void SwFrm::PrepareCrsr()
+{
+ StackHack aHack;
+ if( GetUpper() && !GetUpper()->IsSctFrm() )
+ {
+ GetUpper()->PrepareCrsr();
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), ":-( Layoutgeruest wackelig (Upper wech)." );
+ if ( !GetUpper() )
+ return;
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTab = IsTabFrm();
+ sal_Bool bNoSect = IsInSct();
+
+ sal_Bool bOldTabLock = sal_False, bFoll;
+ SwFlowFrm* pThis = bCnt ? (SwCntntFrm*)this : NULL;
+
+ if ( bTab )
+ {
+ bOldTabLock = ((SwTabFrm*)this)->IsJoinLocked();
+ ::PrepareLock( (SwTabFrm*)this );
+ pThis = (SwTabFrm*)this;
+ }
+ else if( IsSctFrm() )
+ {
+ pThis = (SwSectionFrm*)this;
+ bNoSect = sal_False;
+ }
+ bFoll = pThis && pThis->IsFollow();
+
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm != this )
+ {
+ OSL_ENSURE( pFrm, ":-( Layoutgeruest wackelig (this not found)." );
+ if ( !pFrm )
+ return; //Oioioioi ...
+
+ if ( !pFrm->IsValid() )
+ {
+ //Ein kleiner Eingriff der hoffentlich etwas zur Verbesserung
+ //der Stabilitaet beitraegt:
+ //Wenn ich Follow _und_ Nachbar eines Frms vor mir bin,
+ //so wuerde dieser mich beim Formatieren deleten; wie jeder
+ //leicht sehen kann waere dies eine etwas unuebersichtliche
+ //Situation die es zu vermeiden gilt.
+ if ( bFoll && pFrm->IsFlowFrm() &&
+ (SwFlowFrm::CastFlowFrm(pFrm))->IsAnFollow( pThis ) )
+ break;
+
+ pFrm->MakeAll();
+ }
+ //Die Kette kann bei CntntFrms waehrend des durchlaufens
+ //aufgebrochen werden, deshalb muss der Nachfolger etwas
+ //umstaendlich ermittelt werden. However, irgendwann _muss_
+ //ich wieder bei mir selbst ankommen.
+ pFrm = pFrm->FindNext();
+ if( bNoSect && pFrm && pFrm->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pCnt )
+ pFrm = pCnt;
+ }
+ }
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech II)." );
+ if ( !GetUpper() )
+ return;
+
+ GetUpper()->Calc();
+
+ OSL_ENSURE( GetUpper(), "Layoutgeruest wackelig (Upper wech III)." );
+
+ if ( bTab && !bOldTabLock )
+ ::PrepareUnlock( (SwTabFrm*)this );
+ }
+ Calc();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::MakePos()
+|*
+|*************************************************************************/
+
+// Hier wird GetPrev() zurueckgegeben, allerdings werden
+// dabei leere SectionFrms ueberlesen
+SwFrm* lcl_Prev( SwFrm* pFrm, sal_Bool bSectPrv = sal_True )
+{
+ SwFrm* pRet = pFrm->GetPrev();
+ if( !pRet && pFrm->GetUpper() && pFrm->GetUpper()->IsSctFrm() &&
+ bSectPrv && !pFrm->IsColumnFrm() )
+ pRet = pFrm->GetUpper()->GetPrev();
+ while( pRet && pRet->IsSctFrm() &&
+ !((SwSectionFrm*)pRet)->GetSection() )
+ pRet = pRet->GetPrev();
+ return pRet;
+}
+
+SwFrm* lcl_NotHiddenPrev( SwFrm* pFrm )
+{
+ SwFrm *pRet = pFrm;
+ do
+ {
+ pRet = lcl_Prev( pRet );
+ } while ( pRet && pRet->IsTxtFrm() && ((SwTxtFrm*)pRet)->IsHiddenNow() );
+ return pRet;
+}
+
+void SwFrm::MakePos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+ sal_Bool bUseUpper = sal_False;
+ SwFrm* pPrv = lcl_Prev( this );
+ if ( pPrv &&
+ ( !pPrv->IsCntntFrm() ||
+ ( ((SwCntntFrm*)pPrv)->GetFollow() != this ) )
+ )
+ {
+ if ( !StackHack::IsLocked() &&
+ ( !IsInSct() || IsSctFrm() ) &&
+ !pPrv->IsSctFrm() &&
+ !pPrv->GetAttrSet()->GetKeep().GetValue()
+ )
+ {
+ pPrv->Calc(); //hierbei kann der Prev verschwinden!
+ }
+ else if ( pPrv->Frm().Top() == 0 )
+ {
+ bUseUpper = sal_True;
+ }
+ }
+
+ pPrv = lcl_Prev( this, sal_False );
+ sal_uInt16 nMyType = GetType();
+ SWRECTFN( ( IsCellFrm() && GetUpper() ? GetUpper() : this ) )
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else if ( GetUpper() )
+ {
+ // OD 15.10.2002 #103517# - add safeguard for <SwFooterFrm::Calc()>
+ // If parent frame is a footer frame and its <ColLocked()>, then
+ // do *not* calculate it.
+ // NOTE: Footer frame is <ColLocked()> during its
+ // <FormatSize(..)>, which is called from <Format(..)>, which
+ // is called from <MakeAll()>, which is called from <Calc()>.
+ // --> OD 2005-11-17 #i56850#
+ // - no format of upper Writer fly frame, which is anchored
+ // at-paragraph or at-character.
+ if ( !GetUpper()->IsTabFrm() &&
+ !( IsTabFrm() && GetUpper()->IsInTab() ) &&
+ !GetUpper()->IsSctFrm() &&
+ !dynamic_cast<SwFlyAtCntFrm*>(GetUpper()) &&
+ !( GetUpper()->IsFooterFrm() &&
+ GetUpper()->IsColLocked() )
+ )
+ {
+ GetUpper()->Calc();
+ }
+ // <--
+ pPrv = lcl_Prev( this, sal_False );
+ if ( !bUseUpper && pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ if( FRM_NEIGHBOUR & nMyType )
+ {
+ sal_Bool bR2L = IsRightToLeft();
+ if( bR2L )
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() -
+ (aFrm.*fnRect->fnGetWidth)() );
+ else
+ (aFrm.*fnRect->fnSetPosX)( (aFrm.*fnRect->fnGetLeft)() +
+ (pPrv->Frm().*fnRect->fnGetWidth)() );
+
+ // cells may now leave their uppers
+ if( bVert && FRM_CELL & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() -pPrv->Frm().Width();
+ }
+ else if( bVert && FRM_NOTE_VERT & nMyType )
+ {
+ if( bReverse )
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ else
+ aFrm.Pos().X() -= aFrm.Width();
+ }
+ else
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( GetUpper()->Frm().Pos() );
+ aFrm.Pos() += GetUpper()->Prt().Pos();
+ if( FRM_NEIGHBOUR & nMyType && IsRightToLeft() )
+ {
+ if( bVert )
+ aFrm.Pos().Y() += GetUpper()->Prt().Height()
+ - aFrm.Height();
+ else
+ aFrm.Pos().X() += GetUpper()->Prt().Width()
+ - aFrm.Width();
+ }
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ else if( bVert && !bVertL2R && FRM_NOTE_VERT & nMyType && !bReverse )
+ aFrm.Pos().X() -= aFrm.Width() - GetUpper()->Prt().Width();
+ }
+ }
+ else
+ aFrm.Pos().X() = aFrm.Pos().Y() = 0;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsBodyFrm() && bVert && !bVertL2R && !bReverse && GetUpper() )
+ aFrm.Pos().X() += GetUpper()->Prt().Width() - aFrm.Width();
+ bValidPos = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::MakeAll()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+void lcl_CheckObjects( SwSortedObjs* pSortedObjs, SwFrm* pFrm, long& rBot )
+{
+ //Und dann kann es natuerlich noch Absatzgebundene
+ //Rahmen geben, die unterhalb ihres Absatzes stehen.
+ long nMax = 0;
+ for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of <SwSortedObjs>
+ // entries.
+ SwAnchoredObject* pObj = (*pSortedObjs)[i];
+ long nTmp = 0;
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ if( pFly->Frm().Top() != WEIT_WECH &&
+ ( pFrm->IsPageFrm() ? pFly->IsFlyLayFrm() :
+ ( pFly->IsFlyAtCntFrm() &&
+ ( pFrm->IsBodyFrm() ? pFly->GetAnchorFrm()->IsInDocBody() :
+ pFly->GetAnchorFrm()->IsInFtn() ) ) ) )
+ {
+ nTmp = pFly->Frm().Bottom();
+ }
+ }
+ else
+ nTmp = pObj->GetObjRect().Bottom();
+ nMax = Max( nTmp, nMax );
+ // <--
+ }
+ ++nMax; //Unterkante vs. Hoehe!
+ rBot = Max( rBot, nMax );
+}
+
+void SwPageFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ const SwRect aOldRect( Frm() ); //Anpassung der Root-Groesse
+ const SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ {
+ // PAGES01
+ bValidPos = sal_True; // positioning of the pages is taken care of by the root frame
+ }
+
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( IsEmptyPage() )
+ {
+ Frm().Width( 0 ); Prt().Width( 0 );
+ Frm().Height( 0 ); Prt().Height( 0 );
+ Prt().Left( 0 ); Prt().Top( 0 );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ //Bei der BrowseView gelten feste Einstellungen.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ const long nTop = pAttrs->CalcTopLine() + aBorder.Height();
+ const long nBottom = pAttrs->CalcBottomLine()+ aBorder.Height();
+
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() : 0;
+ if ( nWidth < pSh->GetBrowseWidth() )
+ nWidth = pSh->GetBrowseWidth();
+ nWidth += + 2 * aBorder.Width();
+/*
+ long nWidth = GetUpper() ? ((SwRootFrm*)GetUpper())->GetBrowseWidth() + 2 * aBorder.Width() : 0;
+ if ( nWidth < pSh->VisArea().Width() )
+ nWidth = pSh->VisArea().Width(); */
+
+ nWidth = Max( nWidth, 2L * aBorder.Width() + 4L*MM50 );
+ Frm().Width( nWidth );
+
+ SwLayoutFrm *pBody = FindBodyCont();
+ if ( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ //Fuer Spalten gilt eine feste Hoehe
+ Frm().Height( pAttrs->GetSize().Height() );
+ }
+ else
+ {
+ //Fuer Seiten ohne Spalten bestimmt der Inhalt die
+ //Groesse.
+ long nBot = Frm().Top() + nTop;
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ {
+ long nTmp = 0;
+ SwFrm *pCnt = ((SwLayoutFrm*)pFrm)->ContainsAny();
+ while ( pCnt && (pCnt->GetUpper() == pFrm ||
+ ((SwLayoutFrm*)pFrm)->IsAnLower( pCnt )))
+ {
+ nTmp += pCnt->Frm().Height();
+ if( pCnt->IsTxtFrm() &&
+ ((SwTxtFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwTxtFrm*)pCnt)->GetParHeight()
+ - pCnt->Prt().Height();
+ else if( pCnt->IsSctFrm() &&
+ ((SwSectionFrm*)pCnt)->IsUndersized() )
+ nTmp += ((SwSectionFrm*)pCnt)->Undersize();
+ pCnt = pCnt->FindNext();
+ }
+ // OD 29.10.2002 #97265# - consider invalid body frame properties
+ if ( pFrm->IsBodyFrm() &&
+ ( !pFrm->GetValidSizeFlag() ||
+ !pFrm->GetValidPrtAreaFlag() ) &&
+ ( pFrm->Frm().Height() < pFrm->Prt().Height() )
+ )
+ {
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ }
+ else
+ {
+ // OD 30.10.2002 #97265# - assert invalid lower property
+ OSL_ENSURE( !(pFrm->Frm().Height() < pFrm->Prt().Height()),
+ "SwPageFrm::MakeAll(): Lower with frame height < printing height" );
+ nTmp += pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+ if ( !pFrm->IsBodyFrm() )
+ nTmp = Min( nTmp, pFrm->Frm().Height() );
+ nBot += nTmp;
+ // Hier werden die absatzgebundenen Objekte ueberprueft,
+ // ob sie ueber den Body/FtnCont hinausragen.
+ if( pSortedObjs && !pFrm->IsHeaderFrm() &&
+ !pFrm->IsFooterFrm() )
+ lcl_CheckObjects( pSortedObjs, pFrm, nBot );
+ pFrm = pFrm->GetNext();
+ }
+ nBot += nBottom;
+ //Und die Seitengebundenen
+ if ( pSortedObjs )
+ lcl_CheckObjects( pSortedObjs, this, nBot );
+ nBot -= Frm().Top();
+ // --> OD 2004-11-10 #i35143# - If second page frame
+ // exists, the first page doesn't have to fulfill the
+ // visible area.
+ if ( !GetPrev() && !GetNext() )
+ // <--
+ {
+ nBot = Max( nBot, pSh->VisArea().Height() );
+ }
+ // --> OD 2004-11-10 #i35143# - Assure, that the page
+ // doesn't exceed the defined browse height.
+ Frm().Height( Min( nBot, BROWSE_HEIGHT ) );
+ // <--
+ }
+ Prt().Left ( pAttrs->CalcLeftLine() + aBorder.Width() );
+ Prt().Top ( nTop );
+ Prt().Width( Frm().Width() - ( Prt().Left()
+ + pAttrs->CalcRightLine() + aBorder.Width() ) );
+ Prt().Height( Frm().Height() - (nTop + nBottom) );
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ { //FixSize einstellen, bei Seiten nicht vom Upper sondern vom
+ //Attribut vorgegeben.
+ Frm().SSize( pAttrs->GetSize() );
+ Format( pAttrs );
+ }
+ }
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ delete pAccess;
+
+ // PAGES01
+ if ( Frm() != aOldRect && GetUpper() )
+ static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+ //Der Upper (Root) muss mindestens so breit
+ //sein, dass er die breiteste Seite aufnehmen kann.
+ if ( GetUpper() )
+ {
+ OSL_ENSURE( GetUpper()->Prt().Width() >= aFrm.Width(), "Rootsize" );
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MakeAll()
+|*
+|*************************************************************************/
+
+
+void SwLayoutFrm::MakeAll()
+{
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwLayNotify aNotify( this );
+ sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = ( IsNeighbourFrm() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert );
+
+ SwBorderAttrAccess *pAccess = 0;
+ const SwBorderAttrs*pAttrs = 0;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( !bValidPos )
+ MakePos();
+
+ if ( GetUpper() )
+ {
+ // NEW TABLES
+ if ( IsLeaveUpperAllowed() )
+ {
+ if ( !bValidSize )
+ bValidPrtArea = sal_False;
+ }
+ else
+ {
+ if ( !bValidSize )
+ {
+ //FixSize einstellen, die VarSize wird von Format() nach
+ //Berechnung der PrtArea eingestellt.
+ bValidPrtArea = sal_False;
+
+ SwTwips nPrtWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if( bVert && ( IsBodyFrm() || IsFtnContFrm() ) )
+ {
+ SwFrm* pNxt = GetPrev();
+ while( pNxt && !pNxt->IsHeaderFrm() )
+ pNxt = pNxt->GetPrev();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ pNxt = GetNext();
+ while( pNxt && !pNxt->IsFooterFrm() )
+ pNxt = pNxt->GetNext();
+ if( pNxt )
+ nPrtWidth -= pNxt->Frm().Height();
+ }
+
+ const long nDiff = nPrtWidth - (Frm().*fnRect->fnGetWidth)();
+
+ if( IsNeighbourFrm() && IsRightToLeft() )
+ (Frm().*fnRect->fnSubLeft)( nDiff );
+ else
+ (Frm().*fnRect->fnAddRight)( nDiff );
+ }
+ else
+ {
+ // Don't leave your upper
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (Frm().*fnRect->fnOverStep)( nDeadLine ) )
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ if ( !pAccess )
+ {
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ Format( pAttrs );
+ }
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ if ( pAccess )
+ delete pAccess;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakePrtArea()
+|*
+|*************************************************************************/
+bool SwTxtNode::IsCollapse() const
+{
+ if ( GetDoc()->get( IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA ) && GetTxt().Len()==0 ) {
+ sal_uLong nIdx=GetIndex();
+ const SwEndNode *pNdBefore=GetNodes()[nIdx-1]->GetEndNode();
+ const SwEndNode *pNdAfter=GetNodes()[nIdx+1]->GetEndNode();
+
+ // The paragraph is collapsed only if the NdAfter is the end of a cell
+ bool bInTable = this->FindTableNode( ) != NULL;
+
+ SwSortedObjs* pObjs = this->getLayoutFrm( GetDoc()->GetCurrentLayout() )->GetDrawObjs( );
+ sal_uInt32 nObjs = ( pObjs != NULL ) ? pObjs->Count( ) : 0;
+
+ if ( pNdBefore!=NULL && pNdAfter!=NULL && nObjs == 0 && bInTable ) {
+ return true;
+ } else {
+ return false;
+ }
+ } else
+ return false;
+}
+
+bool SwFrm::IsCollapse() const
+{
+ if (IsTxtFrm()) {
+ const SwTxtFrm *pTxtFrm=(SwTxtFrm*)this;
+ const SwTxtNode *pTxtNode=pTxtFrm->GetTxtNode();
+ if (pTxtNode && pTxtNode->IsCollapse()) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+sal_Bool SwCntntFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
+{
+ sal_Bool bSizeChgd = sal_False;
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ SWRECTFN( this )
+ const sal_Bool bTxtFrm = IsTxtFrm();
+ SwTwips nUpper = 0;
+ if ( bTxtFrm && ((SwTxtFrm*)this)->IsHiddenNow() )
+ {
+ if ( ((SwTxtFrm*)this)->HasFollow() )
+ ((SwTxtFrm*)this)->JoinFrm();
+
+ if( (Prt().*fnRect->fnGetHeight)() )
+ ((SwTxtFrm*)this)->HideHidden();
+ Prt().Pos().X() = Prt().Pos().Y() = 0;
+ (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ nUpper = -( (Frm().*fnRect->fnGetHeight)() );
+ }
+ else
+ {
+ //Vereinfachung: CntntFrms sind immer in der Hoehe Variabel!
+
+ //An der FixSize gibt der umgebende Frame die Groesse vor, die
+ //Raender werden einfach abgezogen.
+ const long nLeft = rAttrs.CalcLeft( this );
+ const long nRight = ((SwBorderAttrs&)rAttrs).CalcRight( this );
+ (this->*fnRect->fnSetXMargins)( nLeft, nRight );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwTwips nWidthArea;
+ if( pSh && 0!=(nWidthArea=(pSh->VisArea().*fnRect->fnGetWidth)()) &&
+ GetUpper()->IsPageBodyFrm() && // nicht dagegen bei BodyFrms in Columns
+ pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
+ //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
+ //geben kann (RootFrm::ImplCalcBrowseWidth())
+ long nMinWidth = 0;
+
+ for (sal_uInt16 i = 0; GetDrawObjs() && i < GetDrawObjs()->Count();++i)
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries
+ SwAnchoredObject* pObj = (*GetDrawObjs())[i];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const sal_Bool bFly = pObj->ISA(SwFlyFrm);
+ if ((bFly && (WEIT_WECH == pObj->GetObjRect().Width()))
+ || rFmt.GetFrmSize().GetWidthPercent())
+ {
+ continue;
+ }
+
+ if ( FLY_AS_CHAR == rFmt.GetAnchor().GetAnchorId() )
+ {
+ nMinWidth = Max( nMinWidth,
+ bFly ? rFmt.GetFrmSize().GetWidth()
+ : pObj->GetObjRect().Width() );
+ }
+ // <--
+ }
+
+ const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ long nWidth = nWidthArea - 2 * ( IsVertical() ? aBorder.Height() : aBorder.Width() );
+ nWidth -= (Prt().*fnRect->fnGetLeft)();
+ nWidth -= rAttrs.CalcRightLine();
+ nWidth = Max( nMinWidth, nWidth );
+ (Prt().*fnRect->fnSetWidth)( Min( nWidth,
+ (Prt().*fnRect->fnGetWidth)() ) );
+ }
+
+ if ( (Prt().*fnRect->fnGetWidth)() <= MINLAY )
+ {
+ //Die PrtArea sollte schon wenigstens MINLAY breit sein, passend
+ //zu den Minimalwerten des UI
+ (Prt().*fnRect->fnSetWidth)( Min( long(MINLAY),
+ (Frm().*fnRect->fnGetWidth)() ) );
+ SwTwips nTmp = (Frm().*fnRect->fnGetWidth)() -
+ (Prt().*fnRect->fnGetWidth)();
+ if( (Prt().*fnRect->fnGetLeft)() > nTmp )
+ (Prt().*fnRect->fnSetLeft)( nTmp );
+ }
+
+ //Fuer die VarSize gelten folgende Regeln:
+ //1. Der erste einer Kette hat keinen Rand nach oben
+ //2. Nach unten gibt es nie einen Rand
+ //3. Der Rand nach oben ist das Maximum aus dem Abstand des
+ // Prev nach unten und dem eigenen Abstand nach oben.
+ //Die drei Regeln werden auf die Berechnung der Freiraeume, die von
+ //UL- bzw. LRSpace vorgegeben werden, angewand. Es gibt in alle
+ //Richtungen jedoch ggf. trotzdem einen Abstand; dieser wird durch
+ //Umrandung und/oder Schatten vorgegeben.
+ //4. Der Abstand fuer TextFrms entspricht mindestens dem Durchschuss
+
+ nUpper = CalcUpperSpace( &rAttrs, NULL );
+
+ SwTwips nLower = CalcLowerSpace( &rAttrs );
+ if (IsCollapse()) {
+ nUpper=0;
+ nLower=0;
+ }
+// // in balanced columned section frames we do not want the
+// // common border
+// sal_Bool bCommonBorder = sal_True;
+// if ( IsInSct() && GetUpper()->IsColBodyFrm() )
+// {
+// const SwSectionFrm* pSct = FindSctFrm();
+// bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+// }
+// SwTwips nLower = bCommonBorder ?
+// rAttrs.GetBottomLine( this ) :
+// rAttrs.CalcBottomLine();
+
+ (Prt().*fnRect->fnSetPosY)( (!bVert || bReverse) ? nUpper : nLower);
+ nUpper += nLower;
+ nUpper -= (Frm().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetHeight)();
+ }
+ //Wenn Unterschiede zwischen Alter und neuer Groesse,
+ //Grow() oder Shrink() rufen
+ if ( nUpper )
+ {
+ if ( nUpper > 0 )
+ GrowFrm( nUpper );
+ else
+ ShrinkFrm( -nUpper );
+ bSizeChgd = sal_True;
+ }
+ }
+ return bSizeChgd;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::MakeAll()
+|*
+|*************************************************************************/
+
+#define STOP_FLY_FORMAT 10
+// --> OD 2006-09-25 #b6448963# - loop prevention
+const int cnStopFormat = 15;
+// <--
+
+inline void ValidateSz( SwFrm *pFrm )
+{
+ if ( pFrm )
+ {
+ pFrm->bValidSize = sal_True;
+ pFrm->bValidPrtArea = sal_True;
+ }
+}
+
+void SwCntntFrm::MakeAll()
+{
+ OSL_ENSURE( GetUpper(), "keinen Upper?" );
+ OSL_ENSURE( IsTxtFrm(), "MakeAll(), NoTxt" );
+
+ if ( !IsFollow() && StackHack::IsLocked() )
+ return;
+
+ if ( IsJoinLocked() )
+ return;
+
+ OSL_ENSURE( !((SwTxtFrm*)this)->IsSwapped(), "Calculation of a swapped frame" );
+
+ StackHack aHack;
+
+ if ( ((SwTxtFrm*)this)->IsLocked() )
+ {
+ OSL_FAIL( "Format fuer gelockten TxtFrm." );
+ return;
+ }
+
+ LockJoin();
+ long nFormatCount = 0;
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ int nConsequetiveFormatsWithoutChange = 0;
+ // <--
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwDoc *pDoc = GetAttrSet()->GetDoc();
+ if( pDoc )
+ {
+ static sal_Bool bWarn = sal_False;
+ if( pDoc->InXMLExport() )
+ {
+ OSL_ENSURE( bWarn, "Formatting during XML-export!" );
+ bWarn = sal_True;
+ }
+ else
+ bWarn = sal_False;
+ }
+#endif
+
+ //uebernimmt im DTor die Benachrichtigung
+ SwCntntNotify *pNotify = new SwCntntNotify( this );
+
+ sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite
+ //angelegt werden (genau einmal)
+ sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst
+ sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck-
+ //fliessen (solange, bis er einmal
+ //vorwaerts ge'moved wurde).
+ sal_Bool bFormatted = sal_False; //Fuer die Witwen und Waisen Regelung
+ //wird der letzte CntntFrm einer Kette
+ //u.U. zum Formatieren angeregt, dies
+ //braucht nur einmal zu passieren.
+ //Immer wenn der Frm gemoved wird muss
+ //das Flag zurueckgesetzt werden.
+ sal_Bool bMustFit = sal_False; //Wenn einmal die Notbremse gezogen wurde,
+ //werden keine anderen Prepares mehr
+ //abgesetzt.
+ sal_Bool bFitPromise = sal_False; //Wenn ein Absatz nicht passte, mit WouldFit
+ //aber verspricht, dass er sich passend
+ //einstellt wird dieses Flag gesetzt.
+ //Wenn er dann sein Versprechen nicht haelt,
+ //kann kontrolliert verfahren werden.
+ sal_Bool bMoveable;
+ const sal_Bool bFly = IsInFly();
+ const sal_Bool bTab = IsInTab();
+ const sal_Bool bFtn = IsInFtn();
+ const sal_Bool bSct = IsInSct();
+ Point aOldFrmPos; //Damit bei Turnarounds jew. mit der
+ Point aOldPrtPos; //letzten Pos verglichen und geprueft
+ //werden kann, ob ein Prepare sinnvoll ist.
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // OD 2004-02-26 #i25029#
+ if ( !IsFollow() && rAttrs.JoinedWithPrev( *(this) ) )
+ {
+ pNotify->SetBordersJoinedWithPrev();
+ }
+
+ const sal_Bool bKeep = IsKeep( rAttrs.GetAttrSet() );
+
+ SwSaveFtnHeight *pSaveFtn = 0;
+ if ( bFtn )
+ {
+ SwFtnFrm *pFtn = FindFtnFrm();
+ SwSectionFrm* pSct = pFtn->FindSctFrm();
+ if ( !((SwTxtFrm*)pFtn->GetRef())->IsLocked() )
+ {
+ SwFtnBossFrm* pBoss = pFtn->GetRef()->FindFtnBossFrm(
+ pFtn->GetAttr()->GetFtn().IsEndNote() );
+ if( !pSct || pSct->IsColLocked() || !pSct->Growable() )
+ pSaveFtn = new SwSaveFtnHeight( pBoss,
+ ((SwTxtFrm*)pFtn->GetRef())->GetFtnLine( pFtn->GetAttr() ) );
+ }
+ }
+
+ // --> OD 2008-08-12 #b6732519#
+ if ( GetUpper()->IsSctFrm() &&
+ HasFollow() &&
+ GetFollow()->GetFrm() == GetNext() )
+ {
+ dynamic_cast<SwTxtFrm*>(this)->JoinFrm();
+ }
+ // <--
+
+ // --> OD 2004-06-23 #i28701# - move master forward, if it has to move,
+ // because of its object positioning.
+ if ( !static_cast<SwTxtFrm*>(this)->IsFollow() )
+ {
+ sal_uInt32 nToPageNum = 0L;
+ const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
+ *(GetAttrSet()->GetDoc()),
+ *(static_cast<SwTxtFrm*>(this)),
+ nToPageNum );
+ // --> OD 2006-01-27 #i58182#
+ // Also move a paragraph forward, which is the first one inside a table cell.
+ if ( bMoveFwdByObjPos &&
+ FindPageFrm()->GetPhyPageNum() < nToPageNum &&
+ ( lcl_Prev( this ) ||
+ GetUpper()->IsCellFrm() ||
+ ( GetUpper()->IsSctFrm() &&
+ GetUpper()->GetUpper()->IsCellFrm() ) ) &&
+ IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ // <--
+ }
+ // <--
+
+ //Wenn ein Follow neben seinem Master steht und nicht passt, kann er
+ //gleich verschoben werden.
+ if ( lcl_Prev( this ) && ((SwTxtFrm*)this)->IsFollow() && IsMoveable() )
+ {
+ bMovedFwd = sal_True;
+ // OD 2004-03-02 #106629# - If follow frame is in table, it's master
+ // will be the last in the current table cell. Thus, invalidate the
+ // printing area of the master,
+ if ( IsInTab() )
+ {
+ lcl_Prev( this )->InvalidatePrt();
+ }
+ MoveFwd( bMakePage, sal_False );
+ }
+
+ // OD 08.11.2002 #104840# - check footnote content for forward move.
+ // If a content of a footnote is on a prior page/column as its invalid
+ // reference, it can be moved forward.
+ if ( bFtn && !bValidPos )
+ {
+ SwFtnFrm* pFtn = FindFtnFrm();
+ SwCntntFrm* pRefCnt = pFtn ? pFtn->GetRef() : 0;
+ if ( pRefCnt && !pRefCnt->IsValid() )
+ {
+ SwFtnBossFrm* pFtnBossOfFtn = pFtn->FindFtnBossFrm();
+ SwFtnBossFrm* pFtnBossOfRef = pRefCnt->FindFtnBossFrm();
+ //<loop of movefwd until condition held or no move>
+ if ( pFtnBossOfFtn && pFtnBossOfRef &&
+ pFtnBossOfFtn != pFtnBossOfRef &&
+ pFtnBossOfFtn->IsBefore( pFtnBossOfRef ) )
+ {
+ bMovedFwd = sal_True;
+ MoveFwd( bMakePage, sal_False );
+ }
+ }
+ }
+
+ SWRECTFN( this )
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ SwRect aOldFrm_StopFormat( Frm() );
+ SwRect aOldPrt_StopFormat( Prt() );
+ // <--
+ if ( sal_True == (bMoveable = IsMoveable()) )
+ {
+ SwFrm *pPre = GetIndPrev();
+ if ( CheckMoveFwd( bMakePage, bKeep, bMovedBwd ) )
+ {
+ SWREFRESHFN( this )
+ bMovedFwd = sal_True;
+ if ( bMovedBwd )
+ {
+ //Beim zurueckfliessen wurde der Upper angeregt sich
+ //vollstaendig zu Painten, dass koennen wir uns jetzt
+ //nach dem hin und her fliessen sparen.
+ GetUpper()->ResetCompletePaint();
+ //Der Vorgaenger wurde Invalidiert, das ist jetzt auch obsolete.
+ OSL_ENSURE( pPre, "missing old Prev" );
+ if( !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+ bMoveable = IsMoveable();
+ }
+ }
+
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+
+ if ( !bValidPos )
+ MakePos();
+
+ //FixSize einstellen, die VarSize wird von Format() justiert.
+ if ( !bValidSize )
+ {
+ // --> OD 2006-01-03 #125452#
+ // invalidate printing area flag, if the following conditions are hold:
+ // - current frame width is 0.
+ // - current printing area width is 0.
+ // - frame width is adjusted to a value greater than 0.
+ // - printing area flag is sal_True.
+ // Thus, it's assured that the printing area is adjusted, if the
+ // frame area width changes its width from 0 to something greater
+ // than 0.
+ // Note: A text frame can be in such a situation, if the format is
+ // triggered by method call <SwCrsrShell::SetCrsr()> after
+ // loading the document.
+ const SwTwips nNewFrmWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ if ( bValidPrtArea && nNewFrmWidth > 0 &&
+ (Frm().*fnRect->fnGetWidth)() == 0 &&
+ (Prt().*fnRect->fnGetWidth)() == 0 )
+ {
+ bValidPrtArea = sal_False;
+ }
+
+ (Frm().*fnRect->fnSetWidth)( nNewFrmWidth );
+ // <--
+ }
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ // --> OD 2004-09-28 #i34730# - keep current frame height
+ const SwTwips nOldH = (Frm().*fnRect->fnGetHeight)();
+ // <--
+ MakePrtArea( rAttrs );
+ if ( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG );
+ // --> OD 2004-09-28 #i34730# - check, if frame height has changed.
+ // If yes, send a PREP_ADJUST_FRM and invalidate the size flag to
+ // force a format. The format will check in its method
+ // <SwTxtFrm::CalcPreps()>, if the already formatted lines still
+ // fit and if not, performs necessary actions.
+ // --> OD 2005-01-10 #i40150# - no check, if frame is undersized.
+ if ( bValidSize && !IsUndersized() &&
+ nOldH != (Frm().*fnRect->fnGetHeight)() )
+ {
+ // --> OD 2004-11-25 #115759# - no PREP_ADJUST_FRM and size
+ // invalidation, if height decreases only by the additional
+ // lower space as last content of a table cell and an existing
+ // follow containing one line exists.
+ const SwTwips nHDiff = nOldH - (Frm().*fnRect->fnGetHeight)();
+ const bool bNoPrepAdjustFrm =
+ nHDiff > 0 && IsInTab() && GetFollow() &&
+ ( 1 == static_cast<SwTxtFrm*>(GetFollow())->GetLineCount( STRING_LEN ) || (static_cast<SwTxtFrm*>(GetFollow())->Frm().*fnRect->fnGetWidth)() < 0 ) &&
+ GetFollow()->CalcAddLowerSpaceAsLastInTableCell() == nHDiff;
+ if ( !bNoPrepAdjustFrm )
+ {
+ Prepare( PREP_ADJUST_FRM );
+ bValidSize = sal_False;
+ }
+ // <--
+ }
+ // <--
+ }
+
+ //Damit die Witwen- und Waisen-Regelung eine Change bekommt muss der
+ //CntntFrm benachrichtigt werden.
+ //Kriterium:
+ //- Er muss Moveable sein (sonst mach das Spalten keinen Sinn.)
+ //- Er muss mit der Unterkante der PrtArea des Upper ueberlappen.
+ if ( !bMustFit )
+ {
+ sal_Bool bWidow = sal_True;
+ const SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if ( bMoveable && !bFormatted && ( GetFollow() ||
+ ( (Frm().*fnRect->fnOverStep)( nDeadLine ) ) ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bWidow = sal_False;
+ }
+ if( (Frm().*fnRect->fnGetPos)() != aOldFrmPos ||
+ (Prt().*fnRect->fnGetPos)() != aOldPrtPos )
+ {
+ // In diesem Prepare erfolgt ggf. ein _InvalidateSize().
+ // bValidSize wird sal_False und das Format() wird gerufen.
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( bWidow && GetFollow() )
+ { Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ }
+ }
+ }
+ if ( !bValidSize )
+ {
+ bValidSize = bFormatted = sal_True;
+ ++nFormatCount;
+ if( nFormatCount > STOP_FLY_FORMAT )
+ SetFlyLock( sal_True );
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ // No format any longer, if <cnStopFormat> consequetive formats
+ // without change occur.
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Format();
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "debug assertion: <SwCntntFrm::MakeAll()> - format of text frame suppressed by fix b6448963" );
+ }
+#endif
+ // <--
+ }
+
+ //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
+ //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
+ //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
+ //geflossen sein.
+ sal_Bool bDummy;
+ if ( !lcl_Prev( this ) &&
+ !bMovedFwd &&
+ ( bMoveable || ( bFly && !bTab ) ) &&
+ ( !bFtn || !GetUpper()->FindFtnFrm()->GetPrev() )
+ && MoveBwd( bDummy ) )
+ {
+ SWREFRESHFN( this )
+ bMovedBwd = sal_True;
+ bFormatted = sal_False;
+ if ( bKeep && bMoveable )
+ {
+ if( CheckMoveFwd( bMakePage, sal_False, bMovedBwd ) )
+ {
+ bMovedFwd = sal_True;
+ bMoveable = IsMoveable();
+ SWREFRESHFN( this )
+ }
+ Point aOldPos = (Frm().*fnRect->fnGetPos)();
+ MakePos();
+ if( aOldPos != (Frm().*fnRect->fnGetPos)() )
+ {
+ Prepare( PREP_POS_CHGD, (const void*)&bFormatted, sal_False );
+ if ( !bValidSize )
+ {
+ (Frm().*fnRect->fnSetWidth)( (GetUpper()->
+ Prt().*fnRect->fnGetWidth)() );
+ if ( !bValidPrtArea )
+ {
+ const long nOldW = (Prt().*fnRect->fnGetWidth)();
+ MakePrtArea( rAttrs );
+ if( nOldW != (Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG, 0, sal_False );
+ }
+ if( GetFollow() )
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = bFormatted = sal_True;
+ Format();
+ }
+ }
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ while( pNxt && pNxt->IsSctFrm() )
+ { // Leere Bereiche auslassen, in die anderen hinein
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pTmp )
+ {
+ pNxt = pTmp;
+ break;
+ }
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ pNxt->Calc();
+ if( bValidPos && !GetIndNext() )
+ {
+ SwSectionFrm *pSct = FindSctFrm();
+ if( pSct && !pSct->GetValidSizeFlag() )
+ {
+ SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
+ if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
+ bValidPos = sal_False;
+ }
+ else
+ bValidPos = sal_False;
+ }
+ }
+ }
+ }
+
+ //Der TxtFrm Validiert sich bei Fussnoten ggf. selbst, dass kann leicht
+ //dazu fuehren, dass seine Position obwohl unrichtig valide ist.
+ if ( bValidPos )
+ {
+ // --> OD 2006-01-23 #i59341#
+ // Workaround for inadequate layout algorithm:
+ // suppress invalidation and calculation of position, if paragraph
+ // has formatted itself at least STOP_FLY_FORMAT times and
+ // has anchored objects.
+ // Thus, the anchored objects get the possibility to format itself
+ // and this probably solve the layout loop.
+ if ( bFtn &&
+ nFormatCount <= STOP_FLY_FORMAT &&
+ !GetDrawObjs() )
+ // <--
+ {
+ bValidPos = sal_False;
+ MakePos();
+ aOldFrmPos = (Frm().*fnRect->fnGetPos)();
+ aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+ }
+ }
+
+ // --> OD 2006-09-25 #b6448963# - loop prevention
+ {
+ if ( aOldFrm_StopFormat == Frm() &&
+ aOldPrt_StopFormat == Prt() )
+ {
+ ++nConsequetiveFormatsWithoutChange;
+ }
+ else
+ {
+ nConsequetiveFormatsWithoutChange = 0;
+ }
+ }
+ // <--
+
+ //Wieder ein Wert ungueltig? - dann nochmal das ganze...
+ if ( !bValidPos || !bValidSize || !bValidPrtArea )
+ continue;
+
+ //Fertig?
+ // Achtung, wg. Hoehe==0, ist es besser statt Bottom() Top()+Height() zu nehmen
+ // (kommt bei Undersized TxtFrms an der Unterkante eines spaltigen Bereichs vor)
+ const long nPrtBottom = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ const long nBottomDist = (Frm().*fnRect->fnBottomDist)( nPrtBottom );
+ if( nBottomDist >= 0 )
+ {
+ if ( bKeep && bMoveable )
+ {
+ //Wir sorgen dafuer, dass der Nachfolger gleich mit formatiert
+ //wird. Dadurch halten wir das Heft in der Hand, bis wirklich
+ //(fast) alles stabil ist. So vermeiden wir Endlosschleifen,
+ //die durch staendig wiederholte Versuche entstehen.
+ //Das bMoveFwdInvalid ist fuer #38407# notwendig. War urspruenglich
+ //in flowfrm.cxx rev 1.38 behoben, das unterbrach aber obiges
+ //Schema und spielte lieber Tuerme von Hanoi (#43669#).
+ SwFrm *pNxt = HasFollow() ? NULL : FindNext();
+ // Bei Bereichen nehmen wir lieber den Inhalt, denn nur
+ // dieser kann ggf. die Seite wechseln
+ while( pNxt && pNxt->IsSctFrm() )
+ {
+ if( ((SwSectionFrm*)pNxt)->GetSection() )
+ {
+ pNxt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ break;
+ }
+ pNxt = pNxt->FindNext();
+ }
+ if ( pNxt )
+ {
+ const sal_Bool bMoveFwdInvalid = 0 != GetIndNext();
+ const sal_Bool bNxtNew =
+ ( 0 == (pNxt->Prt().*fnRect->fnGetHeight)() ) &&
+ (!pNxt->IsTxtFrm() ||!((SwTxtFrm*)pNxt)->IsHiddenNow());
+
+ pNxt->Calc();
+
+ if ( !bMovedBwd &&
+ ((bMoveFwdInvalid && !GetIndNext()) ||
+ bNxtNew) )
+ {
+ if( bMovedFwd )
+ pNotify->SetInvaKeep();
+ bMovedFwd = sal_False;
+ }
+ }
+ }
+ continue;
+ }
+
+ //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
+ //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
+
+ //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
+ //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
+ //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
+ //zwar mit aller Kraft.
+ if ( !bMoveable || IsUndersized() )
+ {
+ if( !bMoveable && IsInTab() )
+ {
+ long nDiff = -(Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ long nReal = GetUpper()->Grow( nDiff );
+ if( nReal )
+ continue;
+ }
+ break;
+ }
+
+ //Wenn ich nun ueberhaupt ganz und garnicht in meinen Upper passe
+ //so kann die Situation vielleicht doch noch durch Aufbrechen
+ //aufgeklart werden. Diese Situation tritt bei einem frisch
+ //erzeugten Follow auf, der zwar auf die Folgeseite geschoben wurde
+ //aber selbst noch zu gross fuer diese ist; also wiederum
+ //aufgespalten werden muss.
+ //Wenn ich nicht passe und nicht Spaltbar (WouldFit()) bin, so schicke
+ //ich meinem TxtFrmanteil die Nachricht, dass eben falls moeglich
+ //trotz des Attributes 'nicht aufspalten' aufgespalten werden muss.
+ sal_Bool bMoveOrFit = sal_False;
+ sal_Bool bDontMoveMe = !GetIndPrev();
+ if( bDontMoveMe && IsInSct() )
+ {
+ SwFtnBossFrm* pBoss = FindFtnBossFrm();
+ bDontMoveMe = !pBoss->IsInSct() ||
+ ( !pBoss->Lower()->GetNext() && !pBoss->GetPrev() );
+ }
+
+ // Finally, we are able to split table rows. Therefore, bDontMoveMe
+ // can be set to sal_False:
+ if( bDontMoveMe && IsInTab() &&
+ 0 != const_cast<SwCntntFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) )
+ bDontMoveMe = sal_False;
+
+ if ( bDontMoveMe && (Frm().*fnRect->fnGetHeight)() >
+ (GetUpper()->Prt().*fnRect->fnGetHeight)() )
+ {
+ if ( !bFitPromise )
+ {
+ SwTwips nTmp = (GetUpper()->Prt().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetTop)();
+ sal_Bool bSplit = !IsFwdMoveAllowed();
+ if ( nTmp > 0 && WouldFit( nTmp, bSplit, sal_False ) )
+ {
+ Prepare( PREP_WIDOWS_ORPHANS, 0, sal_False );
+ bValidSize = sal_False;
+ bFitPromise = sal_True;
+ continue;
+ }
+ /* --------------------------------------------------
+ * Frueher wurde in Rahmen und Bereichen niemals versucht,
+ * durch bMoveOrFit den TxtFrm unter Verzicht auf seine
+ * Attribute (Widows,Keep) doch noch passend zu bekommen.
+ * Dies haette zumindest bei spaltigen Rahmen versucht
+ * werden muessen, spaetestens bei verketteten Rahmen und
+ * in Bereichen muss es versucht werden.
+ * Ausnahme: Wenn wir im FormatWidthCols stehen, duerfen die
+ * Attribute nicht ausser Acht gelassen werden.
+ * --------------------------------------------------*/
+ else if ( !bFtn && bMoveable &&
+ ( !bFly || !FindFlyFrm()->IsColLocked() ) &&
+ ( !bSct || !FindSctFrm()->IsColLocked() ) )
+ bMoveOrFit = sal_True;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "+TxtFrm hat WouldFit-Versprechen nicht eingehalten." );
+ }
+#endif
+ }
+
+ //Mal sehen ob ich irgenwo Platz finde...
+ //Benachbarte Fussnoten werden in _MoveFtnCntFwd 'vorgeschoben'
+ SwFrm *pPre = GetIndPrev();
+ SwFrm *pOldUp = GetUpper();
+
+/* MA 13. Oct. 98: Was soll das denn sein!?
+ * AMA 14. Dec 98: Wenn ein spaltiger Bereich keinen Platz mehr fuer seinen ersten ContentFrm
+ * bietet, so soll dieser nicht nur in die naechste Spalte, sondern ggf. bis zur naechsten
+ * Seite wandern und dort einen Section-Follow erzeugen.
+ */
+ if( IsInSct() && bMovedFwd && bMakePage && pOldUp->IsColBodyFrm() &&
+ pOldUp->GetUpper()->GetUpper()->IsSctFrm() &&
+ ( pPre || pOldUp->GetUpper()->GetPrev() ) &&
+ ((SwSectionFrm*)pOldUp->GetUpper()->GetUpper())->MoveAllowed(this) )
+ bMovedFwd = sal_False;
+
+ const sal_Bool bCheckForGrownBody = pOldUp->IsBodyFrm();
+ const long nOldBodyHeight = (pOldUp->Frm().*fnRect->fnGetHeight)();
+
+ if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+ SWREFRESHFN( this )
+
+ // If MoveFwd moves the paragraph to the next page, a following
+ // paragraph, which contains footnotes can can cause the old upper
+ // frame to grow. In this case we explicitely allow a new check
+ // for MoveBwd. Robust: We also check the bMovedBwd flag again.
+ // If pOldUp was a footnote frame, it has been deleted inside MoveFwd.
+ // Therefore we only check for growing body frames.
+ if ( bCheckForGrownBody && ! bMovedBwd && pOldUp != GetUpper() &&
+ (pOldUp->Frm().*fnRect->fnGetHeight)() > nOldBodyHeight )
+ bMovedFwd = sal_False;
+ else
+ bMovedFwd = sal_True;
+
+ bFormatted = sal_False;
+ if ( bMoveOrFit && GetUpper() == pOldUp )
+ {
+ // FME 2007-08-30 #i81146# new loop control
+ if ( nConsequetiveFormatsWithoutChange <= cnStopFormat )
+ {
+ Prepare( PREP_MUST_FIT, 0, sal_False );
+ bValidSize = sal_False;
+ bMustFit = sal_True;
+ continue;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwCntntFrm::MakeAll" );
+#endif
+ }
+ if ( bMovedBwd && GetUpper() )
+ { //Unuetz gewordene Invalidierungen zuruecknehmen.
+ GetUpper()->ResetCompletePaint();
+ if( pPre && !pPre->IsSctFrm() )
+ ::ValidateSz( pPre );
+ }
+
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+
+
+ // NEW: Looping Louie (Light). Should not be applied in balanced sections.
+ // Should only be applied if there is no better solution!
+ LOOPING_LOUIE_LIGHT( bMovedFwd && bMovedBwd && !IsInBalancedSection() &&
+ (
+
+ // --> FME 2005-01-26 #118572#
+ ( bFtn && !FindFtnFrm()->GetRef()->IsInSct() ) ||
+ // <--
+
+ // --> FME 2005-01-27 #i33887#
+ ( IsInSct() && bKeep )
+ // <--
+
+ // ... add your conditions here ...
+
+ ),
+ static_cast<SwTxtFrm&>(*this) );
+
+
+ if ( pSaveFtn )
+ delete pSaveFtn;
+
+ UnlockJoin();
+ if ( bMovedFwd || bMovedBwd )
+ pNotify->SetInvaKeep();
+ // OD 2004-02-26 #i25029#
+ if ( bMovedFwd )
+ {
+ pNotify->SetInvalidatePrevPrtArea();
+ }
+ delete pNotify;
+ SetFlyLock( sal_False );
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::_WouldFit()
+|*
+|*************************************************************************/
+
+
+
+
+void MakeNxt( SwFrm *pFrm, SwFrm *pNxt )
+{
+ //fix(25455): Validieren, sonst kommt es zu einer Rekursion.
+ //Der erste Versuch, der Abbruch mit pFrm = 0 wenn !Valid,
+ //fuehrt leider zu dem Problem, dass das Keep dann u.U. nicht mehr
+ //korrekt beachtet wird (27417)
+ const sal_Bool bOldPos = pFrm->GetValidPosFlag();
+ const sal_Bool bOldSz = pFrm->GetValidSizeFlag();
+ const sal_Bool bOldPrt = pFrm->GetValidPrtAreaFlag();
+ pFrm->bValidPos = pFrm->bValidPrtArea = pFrm->bValidSize = sal_True;
+
+ //fix(29272): Nicht MakeAll rufen, dort wird evtl. pFrm wieder invalidert
+ //und kommt rekursiv wieder herein.
+ if ( pNxt->IsCntntFrm() )
+ {
+ SwCntntNotify aNotify( (SwCntntFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ ((SwCntntFrm*)pNxt)->MakePrtArea( rAttrs );
+ pNxt->Format( &rAttrs );
+ }
+ else
+ {
+ SwLayNotify aNotify( (SwLayoutFrm*)pNxt );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNxt );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( !pNxt->GetValidSizeFlag() )
+ {
+ if( pNxt->IsVertical() )
+ pNxt->Frm().Height( pNxt->GetUpper()->Prt().Height() );
+ else
+ pNxt->Frm().Width( pNxt->GetUpper()->Prt().Width() );
+ }
+ pNxt->Format( &rAttrs );
+ }
+
+ pFrm->bValidPos = bOldPos;
+ pFrm->bValidSize = bOldSz;
+ pFrm->bValidPrtArea = bOldPrt;
+}
+
+// Diese Routine ueberprueft, ob zwischen dem FtnBoss von pFrm und dem
+// von pNxt keine anderen FtnBosse liegen
+
+sal_Bool lcl_IsNextFtnBoss( const SwFrm *pFrm, const SwFrm* pNxt )
+{
+ OSL_ENSURE( pFrm && pNxt, "lcl_IsNextFtnBoss: No Frames?" );
+ pFrm = pFrm->FindFtnBossFrm();
+ pNxt = pNxt->FindFtnBossFrm();
+ // Falls pFrm eine letzte Spalte ist, wird stattdessen die Seite genommen
+ while( pFrm && pFrm->IsColumnFrm() && !pFrm->GetNext() )
+ pFrm = pFrm->GetUpper()->FindFtnBossFrm();
+ // Falls pNxt eine erste Spalte ist, wird stattdessen die Seite genommen
+ while( pNxt && pNxt->IsColumnFrm() && !pNxt->GetPrev() )
+ pNxt = pNxt->GetUpper()->FindFtnBossFrm();
+ // So, jetzt muessen pFrm und pNxt entweder zwei benachbarte Seiten oder Spalten sein.
+ return ( pFrm && pNxt && pFrm->GetNext() == pNxt );
+}
+
+// --> OD 2007-11-26 #b6614158#
+sal_Bool SwCntntFrm::_WouldFit( SwTwips nSpace,
+ SwLayoutFrm *pNewUpper,
+ sal_Bool bTstMove,
+ const bool bObjsInNewUpper )
+// <--
+{
+ //Damit die Fussnote sich ihren Platz sorgsam waehlt, muss
+ //sie in jedem Fall gemoved werden, wenn zwischen dem
+ //neuen Upper und ihrer aktuellen Seite/Spalte mindestens eine
+ //Seite/Spalte liegt.
+ SwFtnFrm* pFtnFrm = 0;
+ if ( IsInFtn() )
+ {
+ if( !lcl_IsNextFtnBoss( pNewUpper, this ) )
+ return sal_True;
+ pFtnFrm = FindFtnFrm();
+ }
+
+ sal_Bool bRet;
+ sal_Bool bSplit = !pNewUpper->Lower();
+ SwCntntFrm *pFrm = this;
+ const SwFrm *pTmpPrev = pNewUpper->Lower();
+ if( pTmpPrev && pTmpPrev->IsFtnFrm() )
+ pTmpPrev = ((SwFtnFrm*)pTmpPrev)->Lower();
+ while ( pTmpPrev && pTmpPrev->GetNext() )
+ pTmpPrev = pTmpPrev->GetNext();
+ do
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ SwTwips nSecondCheck = 0;
+ SwTwips nOldSpace = nSpace;
+ sal_Bool bOldSplit = bSplit;
+ // <--
+
+ if ( bTstMove || IsInFly() || ( IsInSct() &&
+ ( pFrm->GetUpper()->IsColBodyFrm() || ( pFtnFrm &&
+ pFtnFrm->GetUpper()->GetUpper()->IsColumnFrm() ) ) ) )
+ {
+ //Jetzt wirds ein bischen hinterlistig; empfindliche Gemueter sollten
+ //lieber wegsehen. Wenn ein Flys Spalten enthaelt so sind die Cntnts
+ //moveable, mit Ausnahme der in der letzten Spalte (siehe
+ //SwFrm::IsMoveable()). Zurueckfliessen duerfen sie aber natuerlich.
+ //Das WouldFit() liefert leider nur dann einen vernueftigen Wert, wenn
+ //der Frm moveable ist. Um dem WouldFit() einen Moveable Frm
+ //vorzugaukeln haenge ich ihn einfach solange um.
+ // Auch bei spaltigen Bereichen muss umgehaengt werden, damit
+ // SwSectionFrm::Growable() den richtigen Wert liefert.
+ // Innerhalb von Fussnoten muss ggf. sogar der SwFtnFrm umgehaengt werden,
+ // falls es dort keinen SwFtnFrm gibt.
+ SwFrm* pTmpFrm = pFrm->IsInFtn() && !pNewUpper->FindFtnFrm() ?
+ (SwFrm*)pFrm->FindFtnFrm() : pFrm;
+ SwLayoutFrm *pUp = pTmpFrm->GetUpper();
+ SwFrm *pOldNext = pTmpFrm->GetNext();
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pNewUpper, 0 );
+ if ( pFrm->IsTxtFrm() &&
+ ( bTstMove ||
+ ((SwTxtFrm*)pFrm)->HasFollow() ||
+ ( !((SwTxtFrm*)pFrm)->HasPara() &&
+ !((SwTxtFrm*)pFrm)->IsEmpty()
+ )
+ )
+ )
+ {
+ bTstMove = sal_True;
+ bRet = ((SwTxtFrm*)pFrm)->TestFormat( pTmpPrev, nSpace, bSplit );
+ }
+ else
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+
+ pTmpFrm->Remove();
+ pTmpFrm->InsertBefore( pUp, pOldNext );
+ }
+ else
+ {
+ bRet = pFrm->WouldFit( nSpace, bSplit, sal_False );
+ nSecondCheck = !bSplit ? 1 : 0;
+ }
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ //Bitter aber wahr: Der Abstand muss auch noch mit einkalkuliert werden.
+ //Bei TestFormatierung ist dies bereits geschehen.
+ if ( bRet && !bTstMove )
+ {
+ SwTwips nUpper;
+
+ if ( pTmpPrev )
+ {
+ nUpper = CalcUpperSpace( NULL, pTmpPrev );
+
+ // in balanced columned section frames we do not want the
+ // common border
+ sal_Bool bCommonBorder = sal_True;
+ if ( pFrm->IsInSct() && pFrm->GetUpper()->IsColBodyFrm() )
+ {
+ const SwSectionFrm* pSct = pFrm->FindSctFrm();
+ bCommonBorder = pSct->GetFmt()->GetBalancedColumns().GetValue();
+ }
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = ( 1 == nSecondCheck &&
+ pFrm == this &&
+ IsTxtFrm() &&
+ bCommonBorder &&
+ !static_cast<const SwTxtFrm*>(this)->IsEmpty() ) ?
+ nUpper :
+ 0;
+ // <--
+
+ nUpper += bCommonBorder ?
+ rAttrs.GetBottomLine( *(pFrm) ) :
+ rAttrs.CalcBottomLine();
+
+ }
+ else
+ {
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ nSecondCheck = 0;
+ // <--
+
+ if( pFrm->IsVertical() )
+ nUpper = pFrm->Frm().Width() - pFrm->Prt().Width();
+ else
+ nUpper = pFrm->Frm().Height() - pFrm->Prt().Height();
+ }
+
+ nSpace -= nUpper;
+
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+
+ // --> FME 2005-03-31 #b6236853# #i46181#
+ if ( nSecondCheck > 0 )
+ {
+ // The following code is indented to solve a (rare) problem
+ // causing some frames not to move backward:
+ // SwTxtFrm::WouldFit() claims that the whole paragraph
+ // fits into the given space and subtracts the height of
+ // all lines from nSpace. nSpace - nUpper is not a valid
+ // indicator if the frame should be allowed to move backward.
+ // We do a second check with the original remaining space
+ // reduced by the required upper space:
+ nOldSpace -= nSecondCheck;
+ const bool bSecondRet = nOldSpace >= 0 && pFrm->WouldFit( nOldSpace, bOldSplit, sal_False );
+ if ( bSecondRet && bOldSplit && nOldSpace >= 0 )
+ {
+ bRet = sal_True;
+ bSplit = sal_True;
+ }
+ }
+ // <--
+ }
+ }
+
+ // OD 2004-03-01 #106629# - also consider lower spacing in table cells
+ if ( bRet && IsInTab() &&
+ pNewUpper->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ nSpace -= rAttrs.GetULSpace().GetLower();
+ if ( nSpace < 0 )
+ {
+ bRet = sal_False;
+ }
+ }
+
+ if ( bRet && !bSplit && pFrm->IsKeep( rAttrs.GetAttrSet() ) )
+ {
+ if( bTstMove )
+ {
+ while( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->HasFollow() )
+ {
+ pFrm = ((SwTxtFrm*)pFrm)->GetFollow();
+ }
+ // OD 11.04.2003 #108824# - If last follow frame of <this> text
+ // frame isn't valid, a formatting of the next content frame
+ // doesn't makes sense. Thus, return sal_True.
+ if ( IsAnFollow( pFrm ) && !pFrm->IsValid() )
+ {
+ OSL_FAIL( "Only a warning for task 108824:/n<SwCntntFrm::_WouldFit(..) - follow not valid!" );
+ return sal_True;
+ }
+ }
+ SwFrm *pNxt;
+ if( 0 != (pNxt = pFrm->FindNext()) && pNxt->IsCntntFrm() &&
+ ( !pFtnFrm || ( pNxt->IsInFtn() &&
+ pNxt->FindFtnFrm()->GetAttr() == pFtnFrm->GetAttr() ) ) )
+ {
+ // ProbeFormatierung vertraegt keine absatz- oder gar zeichengebundene Objekte
+ // --> OD 2007-11-26 #b6614158#
+ // current solution for the test formatting doesn't work, if
+ // objects are present in the remaining area of the new upper
+ if ( bTstMove &&
+ ( pNxt->GetDrawObjs() || bObjsInNewUpper ) )
+ {
+ return sal_True;
+ }
+ // <--
+
+ if ( !pNxt->IsValid() )
+ MakeNxt( pFrm, pNxt );
+
+ //Kleiner Trick: Wenn der naechste einen Vorgaenger hat, so hat
+ //er den Absatzabstand bereits berechnet. Er braucht dann nicht
+ //teuer kalkuliert werden.
+ if( lcl_NotHiddenPrev( pNxt ) )
+ pTmpPrev = 0;
+ else
+ {
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow() )
+ pTmpPrev = lcl_NotHiddenPrev( pFrm );
+ else
+ pTmpPrev = pFrm;
+ }
+ pFrm = (SwCntntFrm*)pNxt;
+ }
+ else
+ pFrm = 0;
+ }
+ else
+ pFrm = 0;
+
+ } while ( bRet && pFrm );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/colfrm.cxx b/sw/source/core/layout/colfrm.cxx
new file mode 100644
index 000000000000..5e9aa78fdb59
--- /dev/null
+++ b/sw/source/core/layout/colfrm.cxx
@@ -0,0 +1,478 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include "cntfrm.hxx"
+#include "doc.hxx"
+
+#include "hintids.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <fmtclds.hxx>
+#include <fmtfordr.hxx>
+#include <frmfmt.hxx>
+#include <node.hxx>
+#include "frmtool.hxx"
+#include "colfrm.hxx"
+#include "pagefrm.hxx"
+#include "bodyfrm.hxx" // ColumnFrms jetzt mit BodyFrm
+#include "rootfrm.hxx" // wg. RemoveFtns
+#include "sectfrm.hxx" // wg. FtnAtEnd-Flag
+#include "switerator.hxx"
+
+// ftnfrm.cxx:
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
+
+
+/*************************************************************************
+|*
+|* SwColumnFrm::SwColumnFrm()
+|*
+|*************************************************************************/
+SwColumnFrm::SwColumnFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwFtnBossFrm( pFmt, pSib )
+{
+ nType = FRMC_COLUMN;
+ SwBodyFrm* pColBody = new SwBodyFrm( pFmt->GetDoc()->GetDfltFrmFmt(), pSib );
+ pColBody->InsertBehind( this, 0 ); // ColumnFrms jetzt mit BodyFrm
+ SetMaxFtnHeight( LONG_MAX );
+}
+
+SwColumnFrm::~SwColumnFrm()
+{
+ SwFrmFmt *pFmt = GetFmt();
+ SwDoc *pDoc;
+ if ( !(pDoc = pFmt->GetDoc())->IsInDtor() && pFmt->IsLastDepend() )
+ {
+ //Ich bin der einzige, weg mit dem Format.
+ //Vorher ummelden, damit die Basisklasse noch klarkommt.
+ pDoc->GetDfltFrmFmt()->Add( this );
+ pDoc->DelFrmFmt( pFmt );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ChgColumns()
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_RemoveColumns( SwLayoutFrm *pCont, sal_uInt16 nCnt )
+{
+ OSL_ENSURE( pCont && pCont->Lower() && pCont->Lower()->IsColumnFrm(),
+ "Keine Spalten zu entfernen." );
+
+ SwColumnFrm *pColumn = (SwColumnFrm*)pCont->Lower();
+ ::lcl_RemoveFtns( pColumn, sal_True, sal_True );
+ while ( pColumn->GetNext() )
+ {
+ OSL_ENSURE( pColumn->GetNext()->IsColumnFrm(),
+ "Nachbar von ColFrm kein ColFrm." );
+ pColumn = (SwColumnFrm*)pColumn->GetNext();
+ }
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwColumnFrm *pTmp = (SwColumnFrm*)pColumn->GetPrev();
+ pColumn->Cut();
+ delete pColumn; //Format wird ggf. im DTor mit vernichtet.
+ pColumn = pTmp;
+ }
+}
+
+SwLayoutFrm * MA_FASTCALL lcl_FindColumns( SwLayoutFrm *pLay, sal_uInt16 nCount )
+{
+ SwFrm *pCol = pLay->Lower();
+ if ( pLay->IsPageFrm() )
+ pCol = ((SwPageFrm*)pLay)->FindBodyCont()->Lower();
+
+ if ( pCol && pCol->IsColumnFrm() )
+ {
+ SwFrm *pTmp = pCol;
+ sal_uInt16 i;
+ for ( i = 0; pTmp; pTmp = pTmp->GetNext(), ++i )
+ /* do nothing */;
+ return i == nCount ? (SwLayoutFrm*)pCol : 0;
+ }
+ return 0;
+}
+
+
+static sal_Bool lcl_AddColumns( SwLayoutFrm *pCont, sal_uInt16 nCount )
+{
+ SwDoc *pDoc = pCont->GetFmt()->GetDoc();
+ const sal_Bool bMod = pDoc->IsModified();
+
+ //Format sollen soweit moeglich geshared werden. Wenn es also schon einen
+ //Nachbarn mit den selben Spalteneinstellungen gibt, so koennen die
+ //Spalten an die selben Formate gehaengt werden.
+ //Der Nachbar kann ueber das Format gesucht werden, wer der Owner des Attributes
+ //ist, ist allerdings vom Frametyp abhaengig.
+ SwLayoutFrm *pAttrOwner = pCont;
+ if ( pCont->IsBodyFrm() )
+ pAttrOwner = pCont->FindPageFrm();
+ SwLayoutFrm *pNeighbourCol = 0;
+ SwIterator<SwLayoutFrm,SwFmt> aIter( *pAttrOwner->GetFmt() );
+ SwLayoutFrm *pNeighbour = aIter.First();
+
+ sal_uInt16 nAdd = 0;
+ SwFrm *pCol = pCont->Lower();
+ if ( pCol && pCol->IsColumnFrm() )
+ for ( nAdd = 1; pCol; pCol = pCol->GetNext(), ++nAdd )
+ /* do nothing */;
+ while ( pNeighbour )
+ {
+ if ( 0 != (pNeighbourCol = lcl_FindColumns( pNeighbour, nCount+nAdd )) &&
+ pNeighbourCol != pCont )
+ break;
+ pNeighbourCol = 0;
+ pNeighbour = aIter.Next();
+ }
+
+ sal_Bool bRet;
+ SwTwips nMax = pCont->IsPageBodyFrm() ?
+ pCont->FindPageFrm()->GetMaxFtnHeight() : LONG_MAX;
+ if ( pNeighbourCol )
+ {
+ bRet = sal_False;
+ SwFrm *pTmp = pCont->Lower();
+ while ( pTmp )
+ {
+ pTmp = pTmp->GetNext();
+ pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
+ }
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwColumnFrm *pTmpCol = new SwColumnFrm( pNeighbourCol->GetFmt(), pCont );
+ pTmpCol->SetMaxFtnHeight( nMax );
+ pTmpCol->InsertBefore( pCont, NULL );
+ pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
+ }
+ }
+ else
+ {
+ bRet = sal_True;
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ SwFrmFmt *pFmt = pDoc->MakeFrmFmt( aEmptyStr, pDoc->GetDfltFrmFmt());
+ SwColumnFrm *pTmp = new SwColumnFrm( pFmt, pCont );
+ pTmp->SetMaxFtnHeight( nMax );
+ pTmp->Paste( pCont );
+ }
+ }
+
+ if ( !bMod )
+ pDoc->ResetModified();
+ return bRet;
+}
+
+/*--------------------------------------------------
+ * ChgColumns() adds or removes columns from a layoutframe.
+ * Normally, a layoutframe with a column attribut of 1 or 0 columns contains
+ * no columnframe. However, a sectionframe with "footnotes at the end" needs
+ * a columnframe. If the bChgFtn-flag is set, the columnframe will be inserted
+ * or remove, if necessary.
+ * --------------------------------------------------*/
+
+void SwLayoutFrm::ChgColumns( const SwFmtCol &rOld, const SwFmtCol &rNew,
+ const sal_Bool bChgFtn )
+{
+ if ( rOld.GetNumCols() <= 1 && rNew.GetNumCols() <= 1 && !bChgFtn )
+ return;
+ // --> OD 2009-08-12 #i97379#
+ // If current lower is a no text frame, then columns are not allowed
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ rNew.GetNumCols() > 1 )
+ {
+ return;
+ }
+ // <--
+
+ sal_uInt16 nNewNum, nOldNum = 1;
+ if( Lower() && Lower()->IsColumnFrm() )
+ {
+ SwFrm* pCol = Lower();
+ while( 0 != (pCol=pCol->GetNext()) )
+ ++nOldNum;
+ }
+ nNewNum = rNew.GetNumCols();
+ if( !nNewNum )
+ ++nNewNum;
+ sal_Bool bAtEnd;
+ if( IsSctFrm() )
+ bAtEnd = ((SwSectionFrm*)this)->IsAnyNoteAtEnd();
+ else
+ bAtEnd = sal_False;
+
+ //Einstellung der Spaltenbreiten ist nur bei neuen Formaten notwendig.
+ sal_Bool bAdjustAttributes = nOldNum != rOld.GetNumCols();
+
+ //Wenn die Spaltenanzahl unterschiedlich ist, wird der Inhalt
+ //gesichert und restored.
+ SwFrm *pSave = 0;
+ if( nOldNum != nNewNum || bChgFtn )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ OSL_ENSURE( pDoc, "FrmFmt gibt kein Dokument her." );
+ // SaveCntnt wuerde auch den Inhalt der Fussnotencontainer aufsaugen
+ // und im normalen Textfluss unterbringen.
+ if( IsPageBodyFrm() )
+ pDoc->GetCurrentLayout()->RemoveFtns( (SwPageFrm*)GetUpper(), sal_True, sal_False ); //swmod 080218
+ pSave = ::SaveCntnt( this );
+
+ //Wenn Spalten existieren, jetzt aber eine Spaltenanzahl von
+ //0 oder eins gewuenscht ist, so werden die Spalten einfach vernichtet.
+ if ( nNewNum == 1 && !bAtEnd )
+ {
+ ::lcl_RemoveColumns( this, nOldNum );
+ if ( IsBodyFrm() )
+ SetFrmFmt( pDoc->GetDfltFrmFmt() );
+ else
+ GetFmt()->SetFmtAttr( SwFmtFillOrder() );
+ if ( pSave )
+ ::RestoreCntnt( pSave, this, 0, true );
+ return;
+ }
+ if ( nOldNum == 1 )
+ {
+ if ( IsBodyFrm() )
+ SetFrmFmt( pDoc->GetColumnContFmt() );
+ else
+ GetFmt()->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ) );
+ if( !Lower() || !Lower()->IsColumnFrm() )
+ --nOldNum;
+ }
+ if ( nOldNum > nNewNum )
+ {
+ ::lcl_RemoveColumns( this, nOldNum - nNewNum );
+ bAdjustAttributes = sal_True;
+ }
+ else if( nOldNum < nNewNum )
+ {
+ sal_uInt16 nAdd = nNewNum - nOldNum;
+ bAdjustAttributes = lcl_AddColumns( this, nAdd );
+ }
+ }
+
+ if ( !bAdjustAttributes )
+ {
+ if ( rOld.GetLineWidth() != rNew.GetLineWidth() ||
+ rOld.GetWishWidth() != rNew.GetWishWidth() ||
+ rOld.IsOrtho() != rNew.IsOrtho() )
+ bAdjustAttributes = sal_True;
+ else
+ {
+ sal_uInt16 nCount = Min( rNew.GetColumns().Count(), rOld.GetColumns().Count() );
+ for ( sal_uInt16 i = 0; i < nCount; ++i )
+ if ( !(*rOld.GetColumns()[i] == *rNew.GetColumns()[i]) )
+ {
+ bAdjustAttributes = sal_True;
+ break;
+ }
+ }
+ }
+
+ //Sodele, jetzt koennen die Spalten bequem eingestellt werden.
+ AdjustColumns( &rNew, bAdjustAttributes );
+
+ //Erst jetzt den Inhalt restaurieren. Ein frueheres Restaurieren wuerde
+ //unnuetzte Aktionen beim Einstellen zur Folge haben.
+ if ( pSave )
+ {
+ OSL_ENSURE( Lower() && Lower()->IsLayoutFrm() &&
+ ((SwLayoutFrm*)Lower())->Lower() &&
+ ((SwLayoutFrm*)Lower())->Lower()->IsLayoutFrm(),
+ "Gesucht: Spaltenbody (Tod oder Lebend)." ); // ColumnFrms jetzt mit BodyFrm
+ ::RestoreCntnt( pSave, (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower(), 0, true );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::AdjustColumns()
+|*
+|*************************************************************************/
+
+void SwLayoutFrm::AdjustColumns( const SwFmtCol *pAttr, sal_Bool bAdjustAttributes )
+{
+ if( !Lower()->GetNext() )
+ {
+ Lower()->ChgSize( Prt().SSize() );
+ return;
+ }
+
+ const sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ //Ist ein Pointer da, oder sollen wir die Attribute einstellen,
+ //so stellen wir auf jeden Fall die Spaltenbreiten ein. Andernfalls
+ //checken wir, ob eine Einstellung notwendig ist.
+ if ( !pAttr )
+ {
+ pAttr = &GetFmt()->GetCol();
+ if ( !bAdjustAttributes )
+ {
+ long nAvail = (Prt().*fnRect->fnGetWidth)();
+ for ( SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
+ pCol;
+ pCol = (SwLayoutFrm*)pCol->GetNext() )
+ nAvail -= (pCol->Frm().*fnRect->fnGetWidth)();
+ if ( !nAvail )
+ return;
+ }
+ }
+
+ //Sodele, jetzt koennen die Spalten bequem eingestellt werden.
+ //Die Breiten werden mitgezaehlt, damit wir dem letzten den Rest geben
+ //koennen.
+ SwTwips nAvail = (Prt().*fnRect->fnGetWidth)();
+ const sal_Bool bLine = pAttr->GetLineAdj() != COLADJ_NONE;
+ const sal_uInt16 nMin = bLine ? sal_uInt16( 20 + ( pAttr->GetLineWidth() / 2) ) : 0;
+
+ const sal_Bool bR2L = IsRightToLeft();
+ SwFrm *pCol = bR2L ? GetLastLower() : Lower();
+
+ // --> FME 2004-07-16 #i27399#
+ // bOrtho means we have to adjust the column frames manually. Otherwise
+ // we may use the values returned by CalcColWidth:
+ const sal_Bool bOrtho = pAttr->IsOrtho() && pAttr->GetNumCols() > 0;
+ long nGutter = 0;
+ // <--
+
+ for ( sal_uInt16 i = 0; i < pAttr->GetNumCols(); ++i )
+ {
+ if( !bOrtho )
+ {
+ const SwTwips nWidth = i == (pAttr->GetNumCols() - 1) ?
+ nAvail :
+ pAttr->CalcColWidth( i, sal_uInt16( (Prt().*fnRect->fnGetWidth)() ) );
+
+ const Size aColSz = bVert ?
+ Size( Prt().Width(), nWidth ) :
+ Size( nWidth, Prt().Height() );
+
+ pCol->ChgSize( aColSz );
+
+ // Hierdurch werden die ColumnBodyFrms von Seitenspalten angepasst und
+ // ihr bFixHeight-Flag wird gesetzt, damit sie nicht schrumpfen/wachsen.
+ // Bei Rahmenspalten hingegen soll das Flag _nicht_ gesetzt werden,
+ // da BodyFrms in Rahmenspalten durchaus wachsen/schrumpfen duerfen.
+ if( IsBodyFrm() )
+ ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
+
+ nAvail -= nWidth;
+ }
+
+ if ( bOrtho || bAdjustAttributes )
+ {
+ const SwColumn *pC = pAttr->GetColumns()[i];
+ const SwAttrSet* pSet = pCol->GetAttrSet();
+ SvxLRSpaceItem aLR( pSet->GetLRSpace() );
+
+ //Damit die Trennlinien Platz finden, muessen sie hier
+ //Beruecksichtigung finden. Ueberall wo zwei Spalten aufeinanderstossen
+ //wird jeweils rechts bzw. links ein Sicherheitsabstand von 20 plus
+ //der halben Penbreite einkalkuliert.
+ const sal_uInt16 nLeft = pC->GetLeft();
+ const sal_uInt16 nRight = pC->GetRight();
+
+ aLR.SetLeft ( nLeft );
+ aLR.SetRight( nRight );
+
+ if ( bLine )
+ {
+ if ( i == 0 )
+ {
+ aLR.SetRight( Max( nRight, nMin ) );
+ }
+ else if ( i == pAttr->GetNumCols() - 1 )
+ {
+ aLR.SetLeft ( Max( nLeft, nMin ) );
+ }
+ else
+ {
+ aLR.SetLeft ( Max( nLeft, nMin ) );
+ aLR.SetRight( Max( nRight, nMin ) );
+ }
+ }
+
+ if ( bAdjustAttributes )
+ {
+ SvxULSpaceItem aUL( pSet->GetULSpace() );
+ aUL.SetUpper( pC->GetUpper());
+ aUL.SetLower( pC->GetLower());
+
+ ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aLR );
+ ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aUL );
+ }
+
+ nGutter += aLR.GetLeft() + aLR.GetRight();
+ }
+
+ pCol = bR2L ? pCol->GetPrev() : pCol->GetNext();
+ }
+
+ if( bOrtho )
+ {
+ long nInnerWidth = ( nAvail - nGutter ) / pAttr->GetNumCols();
+ pCol = Lower();
+ for( sal_uInt16 i = 0; i < pAttr->GetNumCols(); pCol = pCol->GetNext(), ++i )
+ {
+ SwTwips nWidth;
+ if ( i == pAttr->GetNumCols() - 1 )
+ nWidth = nAvail;
+ else
+ {
+ SvxLRSpaceItem aLR( pCol->GetAttrSet()->GetLRSpace() );
+ nWidth = nInnerWidth + aLR.GetLeft() + aLR.GetRight();
+ }
+ if( nWidth < 0 )
+ nWidth = 0;
+
+ const Size aColSz = bVert ?
+ Size( Prt().Width(), nWidth ) :
+ Size( nWidth, Prt().Height() );
+
+ pCol->ChgSize( aColSz );
+
+ if( IsBodyFrm() )
+ ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
+
+ nAvail -= nWidth;
+ }
+ }
+}
+
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/dbg_lay.cxx b/sw/source/core/layout/dbg_lay.cxx
new file mode 100644
index 000000000000..8f70b6925a0a
--- /dev/null
+++ b/sw/source/core/layout/dbg_lay.cxx
@@ -0,0 +1,868 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*
+ * Und hier die Beschreibung:
+ *
+ * Durch die PROTOCOL-Makros wird es ermoeglicht, Ereignisse im Frame-Methoden zu protokollieren.
+ * In protokollwuerdigen Stellen in Frame-Methoden muss entweder ein PROTOCOL(...) oder bei Methoden,
+ * bei denen auch das Verlassen der Methode mitprotokolliert werden soll, ein PROTOCOL_ENTER(...)-Makro
+ * stehen.
+ * Die Parameter der PROTOCOL-Makros sind
+ * 1. Ein Pointer auf einen SwFrm, also meist "this" oder "rThis"
+ * 2. Die Funktionsgruppe z.B. PROT_MAKEALL, hierueber wird (inline) entschieden, ob dies
+ * zur Zeit protokolliert werden soll oder nicht.
+ * 3. Die Aktion, im Normalfall 0, aber z.B. ein ACT_START bewirkt eine Einrueckung in der
+ * Ausgabedatei, ein ACT_END nimmt dies wieder zurueck. Auf diese Art wird z.B. durch
+ * PROTOCOL_ENTER am Anfang einer Methode eingerueckt und beim Verlassen wieder zurueck.
+ * 4. Der vierte Parameter ist ein void-Pointer, damit man irgendetwas uebergeben kann,
+ * was in das Protokoll einfliessen kann, typesches Beispiel bei PROT_GROW muss man
+ * einen Pointer auf den Wert, um den gegrowt werden soll, uebergeben.
+ *
+ *
+ * Das Protokoll ist die Datei "dbg_lay.out" im aktuellen (BIN-)Verzeichnis.
+ * Es enthaelt Zeilen mit FrmId, Funktionsgruppe sowie weiteren Infos.
+ *
+ * Was genau protokolliert wird, kann auf folgende Arten eingestellt werden:
+ * 1. Die statische Variable SwProtokoll::nRecord enthaelt die Funktionsgruppen,
+ * die aufgezeichnet werden sollen.
+ * Ein Wert von z.B. PROT_GROW bewirkt, das Aufrufe von SwFrm::Grow dokumentiert werden,
+ * PROT_MAKEALL protokolliert Aufrufe von xxx::MakeAll.
+ * Die PROT_XY-Werte koennen oderiert werden.
+ * Default ist Null, es wird keine Methode aufgezeichnet.
+ * 2. In der SwImplProtocol-Klasse gibt es einen Filter fuer Frame-Typen,
+ * nur die Methodenaufrufe von Frame-Typen, die dort gesetzt sind, werden protokolliert.
+ * Der Member nTypes kann auf Werte wie FRM_PAGE, FRM_SECTION gesetzt und oderiert werden.
+ * Default ist 0xFFFF, d.h. alle Frame-Typen.
+ * 3. In der SwImplProtocol-Klasse gibt es einen ArrayPointer auf FrmIds, die zu ueberwachen sind.
+ * Ist der Pointer Null, so werden alle Frames protokolliert, ansonsten nur Frames,
+ * die in dem Array vermerkt sind.
+ *
+ * Eine Aufzeichnung in Gang zu setzen, erfordert entweder Codemanipulation, z.B. in
+ * SwProtocol::Init() einen anderen Default fuer nRecord setzen oder Debuggermanipulation.
+ * Im Debugger gibt verschiedene, sich anbietende Stellen:
+ * 1. In SwProtocol::Init() einen Breakpoint setzen und dort nRecord manipulieren, ggf.
+ * FrmIds eintragen, dann beginnt die Aufzeichnung bereits beim Programmstart.
+ * 2. Waehrend des Programmlaufs einen Breakpoint vor irgendein PROTOCOL oder PROTOCOL_ENTER-
+ * Makro setzen, dann am SwProtocol::nRecord das unterste Bit setzen (PROT_INIT). Dies
+ * bewirkt, dass die Funktionsgruppe des folgenden Makros aktiviert und in Zukunft
+ * protokolliert wird.
+ * 3. Spezialfall von 2.: Wenn man 2. in der Methode SwRootFrm::Paint(..) anwendet, werden
+ * die Aufzeichnungseinstellung aus der Datei "dbg_lay.ini" ausgelesen!
+ * In dieser INI-Datei kann es Kommentarzeilen geben, diese beginnen mit '#', dann
+ * sind die Sektionen "[frmid]", "[frmtype]" und "[record]" relevant.
+ * Nach [frmid] koennen die FrameIds der zu protokollierenden Frames folgen. Gibt es
+ * dort keine Eintraege, werden alle Frames aufgezeichnet.
+ * Nach [frmtype] koennen FrameTypen folgen, die aufgezeichnet werden sollen, da der
+ * Default hier allerdings USHRT_MAX ist, werden sowieso alle aufgezeichnet. Man kann
+ * allerdings auch Typen entfernen, in dem man ein '!' vor den Wert setzt, z.B.
+ * !0xC000 nimmt die SwCntntFrms aus der Aufzeichnung heraus.
+ * Nach [record] folgen die Funktionsgruppen, die aufgezeichnet werden sollen, Default
+ * ist hier 0, also keine. Auch hier kann man mit einem vorgestellten '!' Funktionen
+ * wieder entfernen.
+ * Hier mal ein Beispiel fuer eine INI-Datei:
+ * ------------------------------------------
+ * #Funktionen: Alle, ausser PRTAREA
+ * [record] 0xFFFFFFE !0x200
+ * [frmid]
+ * #folgende FrmIds:
+ * 1 2 12 13 14 15
+ * #keine Layoutframes ausser ColumnFrms
+ * [frmtype] !0x3FFF 0x4
+ * ------------------------------------------
+ *
+ * Wenn die Aufzeichnung erstmal laeuft, kann man in SwImplProtocol::_Record(...) mittels
+ * Debugger vielfaeltige Manipulationen vornehmen, z.B. bezueglich FrameTypen oder FrmIds.
+ *
+ * --------------------------------------------------*/
+
+#if !defined(OSL_DEBUG_LEVEL) || OSL_DEBUG_LEVEL <= 1
+#error Who broken the makefiles?
+#endif
+
+
+
+#include "dbg_lay.hxx"
+#include <tools/stream.hxx>
+
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTSSORT
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <stdio.h>
+
+#include "frame.hxx"
+#include "layfrm.hxx"
+#include "flyfrm.hxx"
+#include "txtfrm.hxx"
+#include "ndtxt.hxx"
+#include "dflyobj.hxx"
+#include <fntcache.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+sal_uLong SwProtocol::nRecord = 0;
+SwImplProtocol* SwProtocol::pImpl = NULL;
+
+sal_uLong lcl_GetFrameId( const SwFrm* pFrm )
+{
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bFrameId = sal_False;
+ if( bFrameId )
+ return pFrm->GetFrmId();
+#endif
+ if( pFrm && pFrm->IsTxtFrm() )
+ return ((SwTxtFrm*)pFrm)->GetTxtNode()->GetIndex();
+ return 0;
+}
+
+class SwImplProtocol
+{
+ SvFileStream *pStream; // Ausgabestream
+ SvUShortsSort *pFrmIds; // welche FrmIds sollen aufgezeichnet werden ( NULL == alle )
+ std::vector<long> aVars; // Variables
+ ByteString aLayer; // Einrueckung der Ausgabe (" " pro Start/End)
+ sal_uInt16 nTypes; // welche Typen sollen aufgezeichnet werden
+ sal_uInt16 nLineCount; // Ausgegebene Zeilen
+ sal_uInt16 nMaxLines; // Maximal auszugebende Zeilen
+ sal_uInt8 nInitFile; // Bereich (FrmId,FrmType,Record) beim Einlesen der INI-Datei
+ sal_uInt8 nTestMode; // Special fuer Testformatierung, es wird ggf. nur
+ // innerhalb einer Testformatierung aufgezeichnet.
+ void _Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam );
+ sal_Bool NewStream();
+ void CheckLine( ByteString& rLine );
+ void SectFunc( ByteString &rOut, const SwFrm* pFrm, sal_uLong nAct, void* pParam );
+public:
+ SwImplProtocol();
+ ~SwImplProtocol();
+ // Aufzeichnen
+ void Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+ { if( pStream ) _Record( pFrm, nFunction, nAct, pParam ); }
+ sal_Bool InsertFrm( sal_uInt16 nFrmId ); // FrmId aufnehmen zum Aufzeichnen
+ sal_Bool DeleteFrm( sal_uInt16 nFrmId ); // FrmId entfernen, diesen nicht mehr Aufzeichnen
+ void FileInit(); // Auslesen der INI-Datei
+ void ChkStream() { if( !pStream ) NewStream(); }
+ void SnapShot( const SwFrm* pFrm, sal_uLong nFlags );
+ void GetVar( const sal_uInt16 nNo, long& rVar )
+ { if( nNo < aVars.size() ) rVar = aVars[ nNo ]; }
+};
+
+/* --------------------------------------------------
+ * Durch das PROTOCOL_ENTER-Makro wird ein SwEnterLeave-Objekt erzeugt,
+ * wenn die aktuelle Funktion aufgezeichnet werden soll, wird ein
+ * SwImplEnterLeave-Objekt angelegt. Der Witz dabei ist, das der Ctor
+ * des Impl-Objekt am Anfang der Funktion und automatisch der Dtor beim
+ * Verlassen der Funktion gerufen wird. In der Basis-Implementierung ruft
+ * der Ctor lediglich ein PROTOCOL(..) mit ACT_START und im Dtor ein
+ * PROTOCOL(..) mit ACT_END.
+ * Es lassen sich Ableitungen der Klasse bilden, um z.B. beim Verlassen
+ * einer Funktion Groessenaenderungen des Frames zu dokumentieren u.v.a.m.
+ * Dazu braucht dann nur noch in SwEnterLeave::Ctor(...) die gewuenschte
+ * SwImplEnterLeave-Klasse angelegt zu werden.
+ *
+ * --------------------------------------------------*/
+
+class SwImplEnterLeave
+{
+protected:
+ const SwFrm* pFrm; // Der Frame,
+ sal_uLong nFunction, nAction; // die Funktion, ggf. die Aktion
+ void* pParam; // und weitere Parameter
+public:
+ SwImplEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : pFrm( pF ), nFunction( nFunct ), nAction( nAct ), pParam( pPar ) {}
+ virtual void Enter(); // Ausgabe beim Eintritt
+ virtual void Leave(); // Ausgabe beim Verlassen
+};
+
+class SwSizeEnterLeave : public SwImplEnterLeave
+{
+ long nFrmHeight;
+public:
+ SwSizeEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmHeight( pF->Frm().Height() ) {}
+ virtual void Leave(); // Ausgabe der Groessenaenderung
+};
+
+class SwUpperEnterLeave : public SwImplEnterLeave
+{
+ sal_uInt16 nFrmId;
+public:
+ SwUpperEnterLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), nFrmId( 0 ) {}
+ virtual void Enter(); // Ausgabe
+ virtual void Leave(); // Ausgabe der FrmId des Uppers
+};
+
+class SwFrmChangesLeave : public SwImplEnterLeave
+{
+ SwRect aFrm;
+public:
+ SwFrmChangesLeave( const SwFrm* pF, sal_uLong nFunct, sal_uLong nAct, void* pPar )
+ : SwImplEnterLeave( pF, nFunct, nAct, pPar ), aFrm( pF->Frm() ) {}
+ virtual void Enter(); // keine Ausgabe
+ virtual void Leave(); // Ausgabe bei Aenderung der Frm-Area
+};
+
+void SwProtocol::Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+{
+ if( Start() )
+ { // Hier landen wir, wenn im Debugger SwProtocol::nRecord mit PROT_INIT(0x1) oderiert wurde
+ sal_Bool bFinit = sal_False; // Dies bietet im Debugger die Moeglichkeit,
+ if( bFinit ) // die Aufzeichnung dieser Action zu beenden
+ {
+ nRecord &= ~nFunction; // Diese Funktion nicht mehr aufzeichnen
+ nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen
+ return;
+ }
+ nRecord |= nFunction; // Aufzeichnung dieser Funktion freischalten
+ nRecord &= ~PROT_INIT; // PROT_INIT stets zuruecksetzen
+ if( pImpl )
+ pImpl->ChkStream();
+ }
+ if( !pImpl ) // Impl-Object anlegen, wenn noetig
+ pImpl = new SwImplProtocol();
+ pImpl->Record( pFrm, nFunction, nAct, pParam ); // ...und Aufzeichnen
+}
+
+// Die folgende Funktion wird beim Anziehen der Writer-DLL durch TxtInit(..) aufgerufen
+// und ermoeglicht dem Debuggenden Funktionen und/oder FrmIds freizuschalten
+
+void SwProtocol::Init()
+{
+ nRecord = 0;
+ XubString aName( "dbg_lay.go", RTL_TEXTENCODING_MS_1252 );
+ SvFileStream aStream( aName, STREAM_READ );
+ if( aStream.IsOpen() )
+ {
+ pImpl = new SwImplProtocol();
+ pImpl->FileInit();
+ }
+ aStream.Close();
+}
+
+// Ende der Aufzeichnung
+
+void SwProtocol::Stop()
+{
+ if( pImpl )
+ {
+ delete pImpl;
+ pImpl = NULL;
+ if( pFntCache )
+ pFntCache->Flush();
+ }
+ nRecord = 0;
+}
+
+// Creates a more or less detailed snapshot of the layout structur
+
+void SwProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags )
+{
+ if( pImpl )
+ pImpl->SnapShot( pFrm, nFlags );
+}
+
+void SwProtocol::GetVar( const sal_uInt16 nNo, long& rVar )
+{
+ if( pImpl )
+ pImpl->GetVar( nNo, rVar );
+}
+
+SwImplProtocol::SwImplProtocol()
+ : pStream( NULL ), pFrmIds( NULL ), nTypes( 0xffff ),
+ nLineCount( 0 ), nMaxLines( USHRT_MAX ), nTestMode( 0 )
+{
+ NewStream();
+}
+
+sal_Bool SwImplProtocol::NewStream()
+{
+ XubString aName( "dbg_lay.out", RTL_TEXTENCODING_MS_1252 );
+ nLineCount = 0;
+ pStream = new SvFileStream( aName, STREAM_WRITE | STREAM_TRUNC );
+ if( pStream->GetError() )
+ {
+ delete pStream;
+ pStream = NULL;
+ }
+ return 0 != pStream;
+}
+
+SwImplProtocol::~SwImplProtocol()
+{
+ if( pStream )
+ {
+ pStream->Close();
+ delete pStream;
+ }
+ delete pFrmIds;
+ aVars.clear();
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::CheckLine analysiert eine Zeile der INI-Datei
+ * --------------------------------------------------*/
+
+void SwImplProtocol::CheckLine( ByteString& rLine )
+{
+ rLine = rLine.ToLowerAscii(); // Gross/Kleinschreibung ist einerlei
+ while( STRING_LEN > rLine.SearchAndReplace( '\t', ' ' ) )
+ ; //nothing // Tabs werden durch Blanks ersetzt
+ if( '#' == rLine.GetChar(0) ) // Kommentarzeilen beginnen mit '#'
+ return;
+ if( '[' == rLine.GetChar(0) ) // Bereiche: FrmIds, Typen oder Funktionen
+ {
+ ByteString aTmp = rLine.GetToken( 0, ']' );
+ if( "[frmid" == aTmp ) // Bereich FrmIds
+ {
+ nInitFile = 1;
+ delete pFrmIds;
+ pFrmIds = NULL; // Default: Alle Frames aufzeichnen
+ }
+ else if( "[frmtype" == aTmp )// Bereich Typen
+ {
+ nInitFile = 2;
+ nTypes = USHRT_MAX; // Default: Alle FrmaeTypen aufzeichnen
+ }
+ else if( "[record" == aTmp )// Bereich Funktionen
+ {
+ nInitFile = 3;
+ SwProtocol::SetRecord( 0 );// Default: Keine Funktion wird aufgezeichnet
+ }
+ else if( "[test" == aTmp )// Bereich Funktionen
+ {
+ nInitFile = 4; // Default:
+ nTestMode = 0; // Ausserhalb der Testformatierung wird aufgezeichnet
+ }
+ else if( "[max" == aTmp )// maximale Zeilenzahl
+ {
+ nInitFile = 5; // Default:
+ nMaxLines = USHRT_MAX;
+ }
+ else if( "[var" == aTmp )// variables
+ {
+ nInitFile = 6;
+ }
+ else
+ nInitFile = 0; // Nanu: Unbekannter Bereich?
+ rLine.Erase( 0, aTmp.Len() + 1 );
+ }
+ sal_uInt16 nToks = rLine.GetTokenCount( ' ' ); // Blanks (oder Tabs) sind die Trenner
+ for( sal_uInt16 i=0; i < nToks; ++i )
+ {
+ ByteString aTok = rLine.GetToken( i, ' ' );
+ sal_Bool bNo = sal_False;
+ if( '!' == aTok.GetChar(0) )
+ {
+ bNo = sal_True; // Diese(n) Funktion/Typ entfernen
+ aTok.Erase( 0, 1 );
+ }
+ if( aTok.Len() )
+ {
+ sal_uLong nVal;
+ sscanf( aTok.GetBuffer(), "%li", &nVal );
+ switch ( nInitFile )
+ {
+ case 1: InsertFrm( sal_uInt16( nVal ) ); // FrmId aufnehmen
+ break;
+ case 2: {
+ sal_uInt16 nNew = (sal_uInt16)nVal;
+ if( bNo )
+ nTypes &= ~nNew; // Typ entfernen
+ else
+ nTypes |= nNew; // Typ aufnehmen
+ }
+ break;
+ case 3: {
+ sal_uLong nOld = SwProtocol::Record();
+ if( bNo )
+ nOld &= ~nVal; // Funktion entfernen
+ else
+ nOld |= nVal; // Funktion aufnehmen
+ SwProtocol::SetRecord( nOld );
+ }
+ break;
+ case 4: {
+ sal_uInt8 nNew = (sal_uInt8)nVal;
+ if( bNo )
+ nTestMode &= ~nNew; // TestMode zuruecksetzen
+ else
+ nTestMode |= nNew; // TestMode setzen
+ }
+ break;
+ case 5: nMaxLines = (sal_uInt16)nVal;
+ break;
+ case 6: aVars.push_back( (long)nVal );
+ break;
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::FileInit() liest die Datei "dbg_lay.ini"
+ * im aktuellen Verzeichnis und wertet sie aus.
+ * --------------------------------------------------*/
+void SwImplProtocol::FileInit()
+{
+ XubString aName( "dbg_lay.ini", RTL_TEXTENCODING_MS_1252 );
+ SvFileStream aStream( aName, STREAM_READ );
+ if( aStream.IsOpen() )
+ {
+ ByteString aLine;
+ nInitFile = 0;
+ while( !aStream.IsEof() )
+ {
+ sal_Char c;
+ aStream >> c;
+ if( '\n' == c || '\r' == c ) // Zeilenende
+ {
+ aLine.EraseLeadingChars();
+ aLine.EraseTrailingChars();
+ if( aLine.Len() )
+ CheckLine( aLine ); // Zeile auswerten
+ aLine.Erase();
+ }
+ else
+ aLine += c;
+ }
+ if( aLine.Len() )
+ CheckLine( aLine ); // letzte Zeile auswerten
+ }
+ aStream.Close();
+}
+
+/* --------------------------------------------------
+ * lcl_Start sorgt fuer Einrueckung um zwei Blanks bei ACT_START
+ * und nimmt diese bei ACT_END wieder zurueck.
+ * --------------------------------------------------*/
+void lcl_Start( ByteString& rOut, ByteString& rLay, sal_uLong nAction )
+{
+ if( nAction == ACT_START )
+ {
+ rLay += " ";
+ rOut += " On";
+ }
+ else if( nAction == ACT_END )
+ {
+ if( rLay.Len() > 1 )
+ {
+ rLay.Erase( rLay.Len() - 2 );
+ rOut.Erase( 0, 2 );
+ }
+ rOut += " Off";
+ }
+}
+
+/* --------------------------------------------------
+ * lcl_Flags gibt das ValidSize-, ValidPos- und ValidPrtArea-Flag ("Sz","Ps","PA")
+ * des Frames aus, "+" fuer valid, "-" fuer invalid.
+ * --------------------------------------------------*/
+
+void lcl_Flags( ByteString& rOut, const SwFrm* pFrm )
+{
+ rOut += " Sz";
+ rOut += pFrm->GetValidSizeFlag() ? '+' : '-';
+ rOut += " Ps";
+ rOut += pFrm->GetValidPosFlag() ? '+' : '-';
+ rOut += " PA";
+ rOut += pFrm->GetValidPrtAreaFlag() ? '+' : '-';
+}
+
+/* --------------------------------------------------
+ * lcl_FrameType gibt den Typ des Frames in Klartext aus.
+ * --------------------------------------------------*/
+
+void lcl_FrameType( ByteString& rOut, const SwFrm* pFrm )
+{
+ if( pFrm->IsTxtFrm() )
+ rOut += "Txt ";
+ else if( pFrm->IsLayoutFrm() )
+ {
+ if( pFrm->IsPageFrm() )
+ rOut += "Page ";
+ else if( pFrm->IsColumnFrm() )
+ rOut += "Col ";
+ else if( pFrm->IsBodyFrm() )
+ {
+ if( pFrm->GetUpper() && pFrm->IsColBodyFrm() )
+ rOut += "(Col)";
+ rOut += "Body ";
+ }
+ else if( pFrm->IsRootFrm() )
+ rOut += "Root ";
+ else if( pFrm->IsCellFrm() )
+ rOut += "Cell ";
+ else if( pFrm->IsTabFrm() )
+ rOut += "Tab ";
+ else if( pFrm->IsRowFrm() )
+ rOut += "Row ";
+ else if( pFrm->IsSctFrm() )
+ rOut += "Sect ";
+ else if( pFrm->IsHeaderFrm() )
+ rOut += "Header ";
+ else if( pFrm->IsFooterFrm() )
+ rOut += "Footer ";
+ else if( pFrm->IsFtnFrm() )
+ rOut += "Ftn ";
+ else if( pFrm->IsFtnContFrm() )
+ rOut += "FtnCont ";
+ else if( pFrm->IsFlyFrm() )
+ rOut += "Fly ";
+ else
+ rOut += "Layout ";
+ }
+ else if( pFrm->IsNoTxtFrm() )
+ rOut += "NoTxt ";
+ else
+ rOut += "Not impl. ";
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::Record(..) wird nur gerufen, wenn das PROTOCOL-Makro
+ * feststellt, dass die Funktion aufgezeichnet werden soll ( SwProtocol::nRecord ).
+ * In dieser Methode werden noch die beiden weiteren Einschraenkungen ueberprueft,
+ * ob die FrmId und der FrameType zu den aufzuzeichnenden gehoeren.
+ * --------------------------------------------------*/
+
+void SwImplProtocol::_Record( const SwFrm* pFrm, sal_uLong nFunction, sal_uLong nAct, void* pParam )
+{
+ sal_uInt16 nSpecial = 0;
+ if( nSpecial ) // Debugger-Manipulationsmoeglichkeit
+ {
+ sal_uInt16 nId = sal_uInt16(lcl_GetFrameId( pFrm ));
+ switch ( nSpecial )
+ {
+ case 1: InsertFrm( nId ); break;
+ case 2: DeleteFrm( nId ); break;
+ case 3: delete pFrmIds; pFrmIds = NULL; break;
+ case 4: delete pStream; pStream = NULL; break;
+ }
+ return;
+ }
+ if( !pStream && !NewStream() )
+ return; // Immer noch kein Stream
+
+ if( pFrmIds && !pFrmIds->Seek_Entry( sal_uInt16(lcl_GetFrameId( pFrm )) ) )
+ return; // gehoert nicht zu den gewuenschten FrmIds
+
+ if( !(pFrm->GetType() & nTypes) )
+ return; // Der Typ ist unerwuenscht
+
+ if( 1 == nTestMode && nFunction != PROT_TESTFORMAT )
+ return; // Wir sollen nur innerhalb einer Testformatierung aufzeichnen
+ sal_Bool bTmp = sal_False;
+ ByteString aOut = aLayer;
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( pFrm ) );
+ aOut += ' ';
+ lcl_FrameType( aOut, pFrm ); // dann den FrameType
+ switch ( nFunction ) // und die Funktion
+ {
+ case PROT_SNAPSHOT: lcl_Flags( aOut, pFrm );
+ break;
+ case PROT_MAKEALL: aOut += "MakeAll";
+ lcl_Start( aOut, aLayer, nAct );
+ if( nAct == ACT_START )
+ lcl_Flags( aOut, pFrm );
+ break;
+ case PROT_MOVE_FWD: bTmp = sal_True; // NoBreak
+ case PROT_MOVE_BWD: aOut += ( nFunction == bTmp ) ? "Fwd" : "Bwd";
+ lcl_Start( aOut, aLayer, nAct );
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt32( *((sal_uInt16*)pParam) );
+ }
+ break;
+ case PROT_GROW_TST: if( ACT_START != nAct )
+ return;
+ aOut += "TestGrow";
+ break;
+ case PROT_SHRINK_TST: if( ACT_START != nAct )
+ return;
+ aOut += "TestShrink";
+ break;
+ case PROT_ADJUSTN :
+ case PROT_SHRINK: bTmp = sal_True; // NoBreak
+ case PROT_GROW: aOut += !bTmp ? "Grow" :
+ ( nFunction == PROT_SHRINK ? "Shrink" : "AdjustNgbhd" );
+ lcl_Start( aOut, aLayer, nAct );
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( *((long*)pParam) );
+ }
+ break;
+ case PROT_POS: break;
+ case PROT_PRTAREA: aOut += "PrtArea";
+ lcl_Start( aOut, aLayer, nAct );
+ break;
+ case PROT_SIZE: aOut += "Size";
+ lcl_Start( aOut, aLayer, nAct );
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( pFrm->Frm().Height() );
+ break;
+ case PROT_LEAF: aOut += "Prev/NextLeaf";
+ lcl_Start( aOut, aLayer, nAct );
+ aOut += ' ';
+ if( pParam )
+ {
+ aOut += ' ';
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ }
+ break;
+ case PROT_FILE_INIT: FileInit();
+ aOut = "Initialize";
+ break;
+ case PROT_SECTION: SectFunc( aOut, pFrm, nAct, pParam );
+ break;
+ case PROT_CUT: bTmp = sal_True; // NoBreak
+ case PROT_PASTE: aOut += bTmp ? "Cut from " : "Paste to ";
+ aOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case PROT_TESTFORMAT: aOut += "Test";
+ lcl_Start( aOut, aLayer, nAct );
+ if( ACT_START == nAct )
+ nTestMode |= 2;
+ else
+ nTestMode &= ~2;
+ break;
+ case PROT_FRMCHANGES:
+ {
+ SwRect& rFrm = *((SwRect*)pParam);
+ if( pFrm->Frm().Pos() != rFrm.Pos() )
+ {
+ aOut += "PosChg: (";
+ aOut += ByteString::CreateFromInt64(rFrm.Left());
+ aOut += ", ";
+ aOut += ByteString::CreateFromInt64(rFrm.Top());
+ aOut += ") (";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Left());
+ aOut += ", ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Top());
+ aOut += ") ";
+ }
+ if( pFrm->Frm().Height() != rFrm.Height() )
+ {
+ aOut += "Height: ";
+ aOut += ByteString::CreateFromInt64(rFrm.Height());
+ aOut += " -> ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Height());
+ aOut += " ";
+ }
+ if( pFrm->Frm().Width() != rFrm.Width() )
+ {
+ aOut += "Width: ";
+ aOut += ByteString::CreateFromInt64(rFrm.Width());
+ aOut += " -> ";
+ aOut += ByteString::CreateFromInt64(pFrm->Frm().Width());
+ aOut += " ";
+ }
+ break;
+ }
+ }
+ *pStream << aOut.GetBuffer() << endl; // Ausgabe
+ pStream->Flush(); // Gleich auf die Platte, damit man mitlesen kann
+ if( ++nLineCount >= nMaxLines ) // Maximale Ausgabe erreicht?
+ SwProtocol::SetRecord( 0 ); // => Ende der Aufzeichnung
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::SectFunc(...) wird von SwImplProtocol::_Record(..) gerufen,
+ * hier werden die Ausgaben rund um SectionFrms abgehandelt.
+ * --------------------------------------------------*/
+
+void SwImplProtocol::SectFunc( ByteString &rOut, const SwFrm* , sal_uLong nAct, void* pParam )
+{
+ sal_Bool bTmp = sal_False;
+ switch( nAct )
+ {
+ case ACT_MERGE: rOut += "Merge Section ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case ACT_CREATE_MASTER: bTmp = sal_True; // NoBreak
+ case ACT_CREATE_FOLLOW: rOut += "Create Section ";
+ rOut += bTmp ? "Master to " : "Follow from ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ case ACT_DEL_MASTER: bTmp = sal_True; // NoBreak
+ case ACT_DEL_FOLLOW: rOut += "Delete Section ";
+ rOut += bTmp ? "Master to " : "Follow from ";
+ rOut += ByteString::CreateFromInt64( lcl_GetFrameId( (SwFrm*)pParam ) );
+ break;
+ }
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::InsertFrm(..) nimmt eine neue FrmId zum Aufzeichnen auf,
+ * wenn pFrmIds==NULL, werden alle aufgezeichnet, sobald durch InsertFrm(..)
+ * pFrmIds angelegt wird, werden nur noch die enthaltenen FrmIds aufgezeichnet.
+ * --------------------------------------------------*/
+
+sal_Bool SwImplProtocol::InsertFrm( sal_uInt16 nId )
+{
+ if( !pFrmIds )
+ pFrmIds = new SvUShortsSort(5,5);
+ if( pFrmIds->Seek_Entry( nId ) )
+ return sal_False;
+ pFrmIds->Insert( nId );
+ return sal_True;
+}
+
+/* --------------------------------------------------
+ * SwImplProtocol::DeleteFrm(..) entfernt eine FrmId aus dem pFrmIds-Array,
+ * so dass diese Frame nicht mehr aufgezeichnet wird.
+ * --------------------------------------------------*/
+sal_Bool SwImplProtocol::DeleteFrm( sal_uInt16 nId )
+{
+ sal_uInt16 nPos;
+ if( !pFrmIds || !pFrmIds->Seek_Entry( nId, &nPos ) )
+ return sal_False;
+ pFrmIds->Remove( nPos );
+ return sal_True;
+}
+
+/*--------------------------------------------------
+ * SwProtocol::SnapShot(..)
+ * creates a snapshot of the given frame and its content.
+ * --------------------------------------------------*/
+void SwImplProtocol::SnapShot( const SwFrm* pFrm, sal_uLong nFlags )
+{
+ while( pFrm )
+ {
+ _Record( pFrm, PROT_SNAPSHOT, 0, 0);
+ if( pFrm->GetDrawObjs() && nFlags & SNAP_FLYFRAMES )
+ {
+ aLayer += "[ ";
+ const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ SnapShot( static_cast<SwFlyFrm*>(pObj), nFlags );
+ }
+ if( aLayer.Len() > 1 )
+ aLayer.Erase( aLayer.Len() - 2 );
+ }
+ if( pFrm->IsLayoutFrm() && nFlags & SNAP_LOWER &&
+ ( !pFrm->IsTabFrm() || nFlags & SNAP_TABLECONT ) )
+ {
+ aLayer += " ";
+ SnapShot( ((SwLayoutFrm*)pFrm)->Lower(), nFlags );
+ if( aLayer.Len() > 1 )
+ aLayer.Erase( aLayer.Len() - 2 );
+ }
+ pFrm = pFrm->GetNext();
+ }
+}
+
+/* --------------------------------------------------
+ * SwEnterLeave::Ctor(..) wird vom eigentlichen (inline-)Kontruktor gerufen,
+ * wenn die Funktion aufgezeichnet werden soll.
+ * Die Aufgabe ist es abhaengig von der Funktion das richtige SwImplEnterLeave-Objekt
+ * zu erzeugen, alles weitere geschieht dann in dessen Ctor/Dtor.
+ * --------------------------------------------------*/
+void SwEnterLeave::Ctor( const SwFrm* pFrm, sal_uLong nFunc, sal_uLong nAct, void* pPar )
+{
+ switch( nFunc )
+ {
+ case PROT_ADJUSTN :
+ case PROT_GROW:
+ case PROT_SHRINK : pImpl = new SwSizeEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ case PROT_MOVE_FWD:
+ case PROT_MOVE_BWD : pImpl = new SwUpperEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ case PROT_FRMCHANGES : pImpl = new SwFrmChangesLeave( pFrm, nFunc, nAct, pPar ); break;
+ default: pImpl = new SwImplEnterLeave( pFrm, nFunc, nAct, pPar ); break;
+ }
+ pImpl->Enter();
+}
+
+/* --------------------------------------------------
+ * SwEnterLeave::Dtor() ruft lediglich den Destruktor des SwImplEnterLeave-Objekts,
+ * ist nur deshalb nicht inline, damit die SwImplEnterLeave-Definition nicht
+ * im dbg_lay.hxx zu stehen braucht.
+ * --------------------------------------------------*/
+
+void SwEnterLeave::Dtor()
+{
+ if( pImpl )
+ {
+ pImpl->Leave();
+ delete pImpl;
+ }
+}
+
+void SwImplEnterLeave::Enter()
+{
+ SwProtocol::Record( pFrm, nFunction, ACT_START, pParam );
+}
+
+void SwImplEnterLeave::Leave()
+{
+ SwProtocol::Record( pFrm, nFunction, ACT_END, pParam );
+}
+
+void SwSizeEnterLeave::Leave()
+{
+ nFrmHeight = pFrm->Frm().Height() - nFrmHeight;
+ SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmHeight );
+}
+
+void SwUpperEnterLeave::Enter()
+{
+ nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0;
+ SwProtocol::Record( pFrm, nFunction, ACT_START, &nFrmId );
+}
+
+void SwUpperEnterLeave::Leave()
+{
+ nFrmId = pFrm->GetUpper() ? sal_uInt16(lcl_GetFrameId( pFrm->GetUpper() )) : 0;
+ SwProtocol::Record( pFrm, nFunction, ACT_END, &nFrmId );
+}
+
+void SwFrmChangesLeave::Enter()
+{
+}
+
+void SwFrmChangesLeave::Leave()
+{
+ if( pFrm->Frm() != aFrm )
+ SwProtocol::Record( pFrm, PROT_FRMCHANGES, 0, &aFrm );
+}
+
+#endif // DBG_UTIL
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx
new file mode 100644
index 000000000000..16bc348b6a42
--- /dev/null
+++ b/sw/source/core/layout/findfrm.cxx
@@ -0,0 +1,1793 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "node.hxx"
+#include "doc.hxx"
+#include "frmtool.hxx"
+#include "flyfrm.hxx"
+#include <frmfmt.hxx>
+#include <cellfrm.hxx>
+#include <rowfrm.hxx>
+#include <swtable.hxx>
+
+#include "tabfrm.hxx"
+#include "sectfrm.hxx"
+#include "flyfrms.hxx"
+#include "ftnfrm.hxx"
+#include "txtftn.hxx"
+#include "fmtftn.hxx"
+#include <txtfrm.hxx> // SwTxtFrm
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* FindBodyCont, FindLastBodyCntnt()
+|*
+|* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb
+|* der Seite.
+|*
+|*************************************************************************/
+SwLayoutFrm *SwFtnBossFrm::FindBodyCont()
+{
+ SwFrm *pLay = Lower();
+ while ( pLay && !pLay->IsBodyFrm() )
+ pLay = pLay->GetNext();
+ return (SwLayoutFrm*)pLay;
+}
+
+SwCntntFrm *SwPageFrm::FindLastBodyCntnt()
+{
+ SwCntntFrm *pRet = FindFirstBodyCntnt();
+ SwCntntFrm *pNxt = pRet;
+ while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
+ { pRet = pNxt;
+ pNxt = pNxt->FindNextCnt();
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ContainsCntnt
+|*
+|* Beschreibung Prueft, ob der Frame irgendwo in seiner
+|* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt;
+|* Falls ja wird der erste gefundene CntntFrm zurueckgegeben.
+|*
+|*************************************************************************/
+
+const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const
+{
+ //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
+ //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
+ //this verlassen wird.
+ //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section
+ //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht
+ //werden.
+
+ const SwLayoutFrm *pLayLeaf = this;
+ do
+ {
+ while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
+
+ if( pLayLeaf->IsSctFrm() && pLayLeaf != this )
+ {
+ const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt();
+ if( pCnt )
+ return pCnt;
+ if( pLayLeaf->GetNext() )
+ {
+ if( pLayLeaf->GetNext()->IsLayoutFrm() )
+ {
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext();
+ continue;
+ }
+ else
+ return (SwCntntFrm*)pLayLeaf->GetNext();
+ }
+ }
+ else if ( pLayLeaf->Lower() )
+ return (SwCntntFrm*)pLayLeaf->Lower();
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( !IsAnLower( pLayLeaf) )
+ return 0;
+ } while( pLayLeaf );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::FirstCell
+|*
+|* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle
+|* hineinzukommen. Dort hangelt es sich wieder hoch zum
+|* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein
+|* ContainsCntnt()->GetUpper() mehr...
+|*
+|*************************************************************************/
+
+const SwCellFrm *SwLayoutFrm::FirstCell() const
+{
+ const SwFrm* pCnt = ContainsAny();
+ while( pCnt && !pCnt->IsCellFrm() )
+ pCnt = pCnt->GetUpper();
+ return (const SwCellFrm*)pCnt;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ContainsAny
+|*
+|* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch
+|* Bereiche und Tabellen zurueckgegeben werden.
+|*
+|*************************************************************************/
+
+// --> OD 2006-02-01 #130797#
+// New parameter <_bInvestigateFtnForSections> controls investigation of
+// content of footnotes for sections.
+const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const
+{
+ //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat
+ //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der
+ //this verlassen wird.
+ // Oder bis wir einen SectionFrm oder TabFrm gefunden haben
+
+ const SwLayoutFrm *pLayLeaf = this;
+ // --> OD 2006-02-01 #130797#
+ const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections;
+ // <--
+ do
+ {
+ while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm())
+ || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() )
+ pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower();
+
+ if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() )
+ && pLayLeaf != this )
+ {
+ // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck,
+ // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden.
+ return pLayLeaf;
+ }
+ else if ( pLayLeaf->Lower() )
+ return (SwCntntFrm*)pLayLeaf->Lower();
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() )
+ {
+ do
+ {
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ } while( pLayLeaf && pLayLeaf->IsInFtn() );
+ }
+ if( !IsAnLower( pLayLeaf) )
+ return 0;
+ } while( pLayLeaf );
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::GetLower()
+|*
+|*************************************************************************/
+const SwFrm* SwFrm::GetLower() const
+{
+ return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
+}
+
+SwFrm* SwFrm::GetLower()
+{
+ return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::IsAnLower()
+|*
+|*************************************************************************/
+sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const
+{
+ const SwFrm *pUp = pAssumed;
+ while ( pUp )
+ {
+ if ( pUp == this )
+ return sal_True;
+ if ( pUp->IsFlyFrm() )
+ pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
+ else
+ pUp = pUp->GetUpper();
+ }
+ return sal_False;
+}
+
+/** method to check relative position of layout frame to
+ a given layout frame.
+
+ OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
+ <txtftn.cxx> for #104840#.
+
+ @param _aCheckRefLayFrm
+ constant reference of an instance of class <SwLayoutFrm> which
+ is used as the reference for the relative position check.
+
+ @author OD
+
+ @return true, if <this> is positioned before the layout frame <p>
+*/
+bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const
+{
+ OSL_ENSURE( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>.");
+ OSL_ENSURE( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>.");
+
+ bool bReturn;
+
+ // check, if on different pages
+ const SwPageFrm *pMyPage = FindPageFrm();
+ const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm();
+ if( pMyPage != pCheckRefPage )
+ {
+ // being on different page as check reference
+ bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
+ }
+ else
+ {
+ // being on same page as check reference
+ // --> search my supreme parent <pUp>, which doesn't contain check reference.
+ const SwLayoutFrm* pUp = this;
+ while ( pUp->GetUpper() &&
+ !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm )
+ )
+ pUp = pUp->GetUpper();
+ if( !pUp->GetUpper() )
+ {
+ // can occur, if <this> is a fly frm
+ bReturn = false;
+ }
+ else
+ {
+ // travel through the next's of <pUp> and check if one of these
+ // contain the check reference.
+ SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext();
+ while ( pUpNext &&
+ !pUpNext->IsAnLower( _pCheckRefLayFrm ) )
+ {
+ pUpNext = (SwLayoutFrm*)pUpNext->GetNext();
+ }
+ bReturn = pUpNext != 0;
+ }
+ }
+
+ return bReturn;
+}
+
+//
+// Local helper functions for GetNextLayoutLeaf
+//
+
+const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext )
+{
+ const SwFrm* pRet = 0;
+ if ( pFrm->IsFlyFrm() )
+ pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink();
+ else
+ pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev();
+
+ return pRet;
+}
+
+const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd )
+{
+ if ( !pFrm->IsLayoutFrm() )
+ return 0;
+
+ return bFwd ?
+ static_cast<const SwLayoutFrm*>(pFrm)->Lower() :
+ static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ImplGetNextLayoutLeaf
+|*
+|* Finds the next layout leaf. This is a layout frame, which does not
+ * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
+ * content frame.
+ *
+ * However, pLower may be a TabFrm
+ *
+|*************************************************************************/
+
+const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const
+{
+ const SwFrm *pFrm = this;
+ const SwLayoutFrm *pLayoutFrm = 0;
+ const SwFrm *p = 0;
+ bool bGoingUp = !bFwd; // false for forward, true for backward
+ do {
+
+ bool bGoingFwdOrBwd = false, bGoingDown = false;
+
+ bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) );
+ if ( !bGoingDown )
+ {
+ // I cannot go down, because either I'm currently going up or
+ // because the is no lower.
+ // I'll try to go forward:
+ bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ // I cannot go forward, because there is no next frame.
+ // I'll try to go up:
+ bGoingUp = (0 != (p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ {
+ // I cannot go up, because there is no upper frame.
+ return 0;
+ }
+ }
+ }
+
+ // If I could not go down or forward, I'll have to go up
+ bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
+
+ pFrm = p;
+ p = lcl_GetLower( pFrm, true );
+
+ } while( ( p && !p->IsFlowFrm() ) ||
+ pFrm == this ||
+ 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) ||
+ pLayoutFrm->IsAnLower( this ) );
+
+ return pLayoutFrm;
+}
+
+
+
+/*************************************************************************
+|*
+|* SwFrm::ImplGetNextCntntFrm( bool )
+|*
+|* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen,
+|* wenn es einen gibt und nicht gerade zuvor um eine Ebene
+|* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab
+|* fuehren!). Damit wird sichergestellt, dass beim
+|* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn
+|* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen,
+|* weil im weiteren ja vom letzten Frm innerhalb eines anderen
+|* Frms rueckwaerts gegangen wird.
+|* Vorwaetzwander funktioniert analog.
+|*
+|*************************************************************************/
+
+// Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in
+// die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden
+const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const
+{
+ const SwFrm *pFrm = this;
+ // #100926#
+ SwCntntFrm *pCntntFrm = 0;
+ sal_Bool bGoingUp = sal_False;
+ do {
+ const SwFrm *p = 0;
+ sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
+
+ bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) );
+ if ( !bGoingDown )
+ {
+ bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ {
+ return 0;
+ }
+ }
+ }
+
+ bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
+
+ if ( !bFwd )
+ {
+ if( bGoingDown && p )
+ while ( p->GetNext() )
+ p = p->GetNext();
+ }
+
+ pFrm = p;
+ } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
+
+ return pCntntFrm;
+}
+
+
+
+
+/*************************************************************************
+|*
+|* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(),
+|* FindPageFrm(), FindColFrm()
+|*
+|*************************************************************************/
+SwPageFrm* SwFrm::FindPageFrm()
+{
+ SwFrm *pRet = this;
+ while ( pRet && !pRet->IsPageFrm() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
+ pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
+ else
+ pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
+ }
+ else
+ return 0;
+ }
+ return (SwPageFrm*)pRet;
+}
+
+SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes )
+{
+ SwFrm *pRet = this;
+ // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige
+ // Bereiche enthalten dort keine Fussnotentexte
+ if( pRet->IsInTab() )
+ pRet = pRet->FindTabFrm();
+ while ( pRet && !pRet->IsFtnBossFrm() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() )
+ pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm();
+ else
+ pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm();
+ }
+ else
+ return 0;
+ }
+ if( bFootnotes && pRet && pRet->IsColumnFrm() &&
+ !pRet->GetNext() && !pRet->GetPrev() )
+ {
+ SwSectionFrm* pSct = pRet->FindSctFrm();
+ OSL_ENSURE( pSct, "FindFtnBossFrm: Single column outside section?" );
+ if( !pSct->IsFtnAtEnd() )
+ return pSct->FindFtnBossFrm( sal_True );
+ }
+ return (SwFtnBossFrm*)pRet;
+}
+
+SwTabFrm* SwFrm::ImplFindTabFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsTabFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwTabFrm*)pRet;
+}
+
+SwSectionFrm* SwFrm::ImplFindSctFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsSctFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwSectionFrm*)pRet;
+}
+
+SwFtnFrm *SwFrm::ImplFindFtnFrm()
+{
+ SwFrm *pRet = this;
+ while ( !pRet->IsFtnFrm() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return 0;
+ }
+ return (SwFtnFrm*)pRet;
+}
+
+SwFlyFrm *SwFrm::ImplFindFlyFrm()
+{
+ const SwFrm *pRet = this;
+ do
+ {
+ if ( pRet->IsFlyFrm() )
+ return (SwFlyFrm*)pRet;
+ else
+ pRet = pRet->GetUpper();
+ } while ( pRet );
+ return 0;
+}
+
+SwFrm *SwFrm::FindColFrm()
+{
+ SwFrm *pFrm = this;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsColumnFrm() );
+ return pFrm;
+}
+
+SwRowFrm *SwFrm::FindRowFrm()
+{
+ SwFrm *pFrm = this;
+ do
+ { pFrm = pFrm->GetUpper();
+ } while ( pFrm && !pFrm->IsRowFrm() );
+ return dynamic_cast< SwRowFrm* >( pFrm );
+}
+
+SwFrm* SwFrm::FindFooterOrHeader()
+{
+ SwFrm* pRet = this;
+ do
+ { if ( pRet->GetType() & 0x0018 ) //Header und Footer
+ return pRet;
+ else if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrm() )
+ pRet = ((SwFlyFrm*)pRet)->AnchorFrm();
+ else
+ return 0;
+ } while ( pRet );
+ return pRet;
+}
+
+const SwFtnFrm* SwFtnContFrm::FindFootNote() const
+{
+ const SwFtnFrm* pRet = (SwFtnFrm*)Lower();
+ if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() )
+ return pRet;
+ return NULL;
+}
+
+const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
+{
+ const SwPageFrm* pRet = 0;
+
+ SwRect aRect;
+ if ( pSize )
+ {
+ aRect.Pos() = rPt;
+ aRect.SSize() = *pSize;
+ }
+
+ const SwFrm* pPage = Lower();
+
+ if ( !bExtend )
+ {
+ if( !Frm().IsInside( rPt ) )
+ return 0;
+
+ // skip pages above point:
+ while( pPage && rPt.Y() > pPage->Frm().Bottom() )
+ pPage = pPage->GetNext();
+ }
+
+ OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" );
+ sal_uInt16 nPageIdx = 0;
+
+ while ( pPage && !pRet )
+ {
+ const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm();
+
+ if ( (!pSize && rBoundRect.IsInside(rPt)) ||
+ (pSize && rBoundRect.IsOver(aRect)) )
+ {
+ pRet = static_cast<const SwPageFrm*>(pPage);
+ }
+
+ pPage = pPage->GetNext();
+ }
+
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrmFrm::GetAttrSet()
+|*
+|*************************************************************************/
+const SwAttrSet* SwFrm::GetAttrSet() const
+{
+ if ( IsCntntFrm() )
+ return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet();
+ else
+ return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos()
+|* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert
+|* nur SwCntntFrms.
+|*
+|* Beschreibung Invalidiert die Position des Naechsten Frames.
+|* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste
+|* CntntFrm der im gleichen Fluss liegt wie ich:
+|* - Body,
+|* - Fussnoten,
+|* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des
+|* Bereiches weiterzuleiten.
+|* - dito fuer Flys.
+|* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle
+|* auf.
+|* - Tabellen verhalten sich prinzipiell analog zu den Cntnts
+|* - Bereiche ebenfalls
+|*
+|*************************************************************************/
+
+// Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode,
+// sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms.
+SwFrm* lcl_NextFrm( SwFrm* pFrm )
+{
+ SwFrm *pRet = 0;
+ sal_Bool bGoingUp = sal_False;
+ do {
+ SwFrm *p = 0;
+
+ sal_Bool bGoingFwd = sal_False;
+ sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0)));
+
+ if( !bGoingDown )
+ {
+ bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext())));
+ if ( !bGoingFwd )
+ {
+ bGoingUp = (0 != (p = pFrm->GetUpper()));
+ if ( !bGoingUp )
+ {
+ return 0;
+ }
+ }
+ }
+ bGoingUp = !(bGoingFwd || bGoingDown);
+ pFrm = p;
+ } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp &&
+ ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) );
+ return pRet;
+}
+
+SwFrm *SwFrm::_FindNext()
+{
+ sal_Bool bIgnoreTab = sal_False;
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ //Der letzte Cntnt der Tabelle wird
+ //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh.
+ //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
+ if ( ((SwTabFrm*)this)->GetFollow() )
+ return ((SwTabFrm*)this)->GetFollow();
+
+ pThis = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ pThis = this;
+ bIgnoreTab = sal_True;
+ }
+ else if ( IsSctFrm() )
+ {
+ //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger
+ // geliefert.
+ if ( ((SwSectionFrm*)this)->GetFollow() )
+ return ((SwSectionFrm*)this)->GetFollow();
+
+ pThis = ((SwSectionFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ pThis = this;
+ }
+ else if ( IsCntntFrm() )
+ {
+ if( ((SwCntntFrm*)this)->GetFollow() )
+ return ((SwCntntFrm*)this)->GetFollow();
+ }
+ else if ( IsRowFrm() )
+ {
+ SwFrm* pMyUpper = GetUpper();
+ if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() )
+ return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower();
+ else return NULL;
+ }
+ else
+ return NULL;
+
+ SwFrm* pRet = NULL;
+ const sal_Bool bFtn = pThis->IsInFtn();
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrm *pUp = pThis->GetUpper();
+ while ( !pUp->IsCellFrm() )
+ pUp = pUp->GetUpper();
+ OSL_ENSURE( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
+ SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell();
+ if ( pNxt )
+ pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt();
+ if ( !pNxt )
+ {
+ pNxt = lcl_NextFrm( pThis );
+ if ( pUp->IsAnLower( pNxt ) )
+ pRet = pNxt;
+ }
+ else
+ pRet = pNxt;
+ }
+ else
+ {
+ const sal_Bool bBody = pThis->IsInDocBody();
+ SwFrm *pNxtCnt = lcl_NextFrm( pThis );
+ if ( pNxtCnt )
+ {
+ if ( bBody || bFtn )
+ {
+ while ( pNxtCnt )
+ {
+ // OD 02.04.2003 #108446# - check for endnote, only if found
+ // next content isn't contained in a section, that collect its
+ // endnotes at its end.
+ bool bEndn = IsInSct() && !IsSctFrm() &&
+ ( !pNxtCnt->IsInSct() ||
+ !pNxtCnt->FindSctFrm()->IsEndnAtEnd()
+ );
+ if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
+ ( pNxtCnt->IsInFtn() &&
+ ( bFtn ||
+ ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
+ )
+ )
+ )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ break;
+ }
+ pNxtCnt = lcl_NextFrm( pNxtCnt );
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ }
+ else //Fuss-/oder Kopfbereich
+ {
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm()
+ : (SwFrm*)pNxtCnt;
+ }
+ }
+ }
+ }
+ if( pRet && pRet->IsInSct() )
+ {
+ SwSectionFrm* pSct = pRet->FindSctFrm();
+ //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich
+ //liefern, der die Fussnoten umfasst
+ if( !pSct->IsAnLower( this ) &&
+ (!bFtn || pSct->IsInFtn() ) )
+ return pSct;
+ }
+ return pRet;
+}
+
+// --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn>
+SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn )
+{
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ if ( ((SwTabFrm*)this)->GetFollow() )
+ {
+ pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pThis )
+ return (SwCntntFrm*)pThis;
+ }
+ pThis = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ return 0;
+ }
+ else if ( IsSctFrm() )
+ {
+ if ( ((SwSectionFrm*)this)->GetFollow() )
+ {
+ pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pThis )
+ return (SwCntntFrm*)pThis;
+ }
+ pThis = ((SwSectionFrm*)this)->FindLastCntnt();
+ if ( !pThis )
+ return 0;
+ }
+ else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() )
+ return ((SwCntntFrm*)this)->GetFollow();
+
+ if ( pThis->IsCntntFrm() )
+ {
+ const sal_Bool bBody = pThis->IsInDocBody();
+ const sal_Bool bFtn = pThis->IsInFtn();
+ SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm();
+ if ( pNxtCnt )
+ {
+ // --> OD 2005-12-01 #i27138#
+ if ( bBody || ( bFtn && !_bInSameFtn ) )
+ // <--
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ while ( pNxtCnt )
+ {
+ if ( (bBody && pNxtCnt->IsInDocBody()) ||
+ (bFtn && pNxtCnt->IsInFtn()) )
+ return pNxtCnt;
+ pNxtCnt = pNxtCnt->GetNextCntntFrm();
+ }
+ }
+ // --> OD 2005-12-01 #i27138#
+ else if ( bFtn && _bInSameFtn )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() );
+ const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() );
+ OSL_ENSURE( pFtnFrmOfCurr,
+ "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." );
+ if ( pFtnFrmOfNext == pFtnFrmOfCurr )
+ {
+ return pNxtCnt;
+ }
+ else if ( pFtnFrmOfCurr->GetFollow() )
+ {
+ // next content frame has to be the first content frame
+ // in the follow footnote, which contains a content frame.
+ SwFtnFrm* pFollowFtnFrmOfCurr(
+ const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
+ pNxtCnt = 0L;
+ do {
+ pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow();
+ pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt();
+ } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() );
+ return pNxtCnt;
+ }
+ else
+ {
+ // current content frame is the last content frame in the
+ // footnote - no next content frame exists.
+ return 0L;
+ }
+ }
+ // <--
+ else if ( pThis->IsInFly() )
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ return pNxtCnt;
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ return pNxtCnt;
+ }
+ }
+ }
+ return 0;
+}
+
+/** method to determine previous content frame in the same environment
+ for a flow frame (content frame, table frame, section frame)
+
+ OD 2005-11-30 #i27138#
+
+ @author OD
+*/
+SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn )
+{
+ if ( !IsFlowFrm() )
+ {
+ // nothing to do, if current frame isn't a flow frame.
+ return 0L;
+ }
+
+ SwCntntFrm* pPrevCntntFrm( 0L );
+
+ // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel
+ // through the layout, a content frame, at which the travel starts, is needed.
+ SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this);
+
+ // perform shortcut, if current frame is a follow, and
+ // determine <pCurrCntntFrm>, if current frame is a table or section frame
+ if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() )
+ {
+ // previous content frame is its master content frame
+ pPrevCntntFrm = pCurrCntntFrm->FindMaster();
+ }
+ else if ( IsTabFrm() )
+ {
+ SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) );
+ if ( pTabFrm->IsFollow() )
+ {
+ // previous content frame is the last content of its master table frame
+ pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the table frame.
+ pCurrCntntFrm = pTabFrm->ContainsCntnt();
+ }
+ }
+ else if ( IsSctFrm() )
+ {
+ SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) );
+ if ( pSectFrm->IsFollow() )
+ {
+ // previous content frame is the last content of its master section frame
+ pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the section frame.
+ pCurrCntntFrm = pSectFrm->ContainsCntnt();
+ }
+ }
+
+ // search for next content frame, depending on the environment, in which
+ // the current frame is in.
+ if ( !pPrevCntntFrm && pCurrCntntFrm )
+ {
+ pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm();
+ if ( pPrevCntntFrm )
+ {
+ if ( pCurrCntntFrm->IsInFly() )
+ {
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ // Nothing to do, <pPrevCntntFrm> is the one
+ }
+ else
+ {
+ const bool bInDocBody = pCurrCntntFrm->IsInDocBody();
+ const bool bInFtn = pCurrCntntFrm->IsInFtn();
+ if ( bInDocBody || ( bInFtn && !_bInSameFtn ) )
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ // Assure that found previous frame is also in one of these
+ // environments. Otherwise, travel further
+ while ( pPrevCntntFrm )
+ {
+ if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) ||
+ ( bInFtn && pPrevCntntFrm->IsInFtn() ) )
+ {
+ break;
+ }
+ pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm();
+ }
+ }
+ else if ( bInFtn && _bInSameFtn )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() );
+ const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() );
+ if ( pFtnFrmOfPrev != pFtnFrmOfCurr )
+ {
+ if ( pFtnFrmOfCurr->GetMaster() )
+ {
+ SwFtnFrm* pMasterFtnFrmOfCurr(
+ const_cast<SwFtnFrm*>(pFtnFrmOfCurr) );
+ pPrevCntntFrm = 0L;
+ // --> OD 2007-07-05 #146872#
+ // correct wrong loop-condition
+ do {
+ pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster();
+ pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt();
+ } while ( !pPrevCntntFrm &&
+ pMasterFtnFrmOfCurr->GetMaster() );
+ // <--
+ }
+ else
+ {
+ // current content frame is the first content in the
+ // footnote - no previous content exists.
+ pPrevCntntFrm = 0L;;
+ }
+ }
+ }
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ // Assure that found previous frame is also in the same
+ // page header respectively page footer as <pCurrCntntFrm>
+ // Note: At this point its clear, that <pCurrCntntFrm> has
+ // to be inside a page header or page footer and that
+ // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are
+ // inside a fly frame.
+ // Thus, method <FindFooterOrHeader()> can be used.
+ OSL_ENSURE( pCurrCntntFrm->FindFooterOrHeader(),
+ "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" );
+ OSL_ENSURE( !pPrevCntntFrm->IsInFly(),
+ "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
+ if ( pPrevCntntFrm->FindFooterOrHeader() !=
+ pCurrCntntFrm->FindFooterOrHeader() )
+ {
+ pPrevCntntFrm = 0L;
+ }
+ }
+ }
+ }
+ }
+
+ return pPrevCntntFrm;
+}
+
+SwFrm *SwFrm::_FindPrev()
+{
+ sal_Bool bIgnoreTab = sal_False;
+ SwFrm *pThis = this;
+
+ if ( IsTabFrm() )
+ {
+ //Der erste Cntnt der Tabelle wird
+ //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh.
+ //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt.
+ if ( ((SwTabFrm*)this)->IsFollow() )
+ return ((SwTabFrm*)this)->FindMaster();
+ else
+ pThis = ((SwTabFrm*)this)->ContainsCntnt();
+ bIgnoreTab = sal_True;
+ }
+
+ if ( pThis && pThis->IsCntntFrm() )
+ {
+ SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm();
+ if( !pPrvCnt )
+ return 0;
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrm *pUp = pThis->GetUpper();
+ while ( !pUp->IsCellFrm() )
+ pUp = pUp->GetUpper();
+ OSL_ENSURE( pUp, "Cntnt in Tabelle aber nicht in Zelle." );
+ if ( pUp->IsAnLower( pPrvCnt ) )
+ return pPrvCnt;
+ }
+ else
+ {
+ SwFrm* pRet;
+ const sal_Bool bBody = pThis->IsInDocBody();
+ const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn();
+ if ( bBody || bFtn )
+ {
+ while ( pPrvCnt )
+ {
+ if ( (bBody && pPrvCnt->IsInDocBody()) ||
+ (bFtn && pPrvCnt->IsInFtn()) )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ pPrvCnt = pPrvCnt->GetPrevCntntFrm();
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ else //Fuss-/oder Kopfbereich oder Fly
+ {
+ const SwFrm *pUp = pThis->GetUpper();
+ const SwFrm *pCntUp = pPrvCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm()
+ : (SwFrm*)pPrvCnt;
+ return pRet;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn )
+{
+ SwFrm *pFrm;
+ if ( 0 != (pFrm = _FindNext()) )
+ {
+ if( pFrm->IsSctFrm() )
+ {
+ while( pFrm && pFrm->IsSctFrm() )
+ {
+ if( ((SwSectionFrm*)pFrm)->GetSection() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ else if( !bNoFtn )
+ ((SwSectionFrm*)pFrm)->InvalidateFtnPos();
+ if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
+ pFrm->InvalidatePos();
+ return;
+ }
+ pFrm = pFrm->FindNext();
+ }
+ if( pFrm )
+ {
+ if ( pFrm->IsSctFrm())
+ { // Damit der Inhalt eines Bereichs die Chance erhaelt,
+ // die Seite zu wechseln, muss er ebenfalls invalidiert werden.
+ SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm )
+ pFrm->InvalidatePos();
+ }
+ else
+ pFrm->InvalidatePos();
+ }
+ }
+ else
+ pFrm->InvalidatePos();
+ }
+}
+
+/** method to invalidate printing area of next frame
+
+ OD 09.01.2004 #i11859#
+
+ @author OD
+
+ FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm
+*/
+void SwFrm::InvalidateNextPrtArea()
+{
+ // determine next frame
+ SwFrm* pNextFrm = FindNext();
+ // skip empty section frames and hidden text frames
+ {
+ while ( pNextFrm &&
+ ( ( pNextFrm->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) ||
+ ( pNextFrm->IsTxtFrm() &&
+ static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) )
+ {
+ pNextFrm = pNextFrm->FindNext();
+ }
+ }
+
+ // Invalidate printing area of found next frame
+ if ( pNextFrm )
+ {
+ if ( pNextFrm->IsSctFrm() )
+ {
+ // Invalidate printing area of found section frame, if
+ // (1) this text frame isn't in a section OR
+ // (2) found section frame isn't a follow of the section frame this
+ // text frame is in.
+ if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm )
+ {
+ pNextFrm->InvalidatePrt();
+ }
+
+ // Invalidate printing area of first content in found section.
+ SwFrm* pFstCntntOfSctFrm =
+ static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny();
+ if ( pFstCntntOfSctFrm )
+ {
+ pFstCntntOfSctFrm->InvalidatePrt();
+ }
+ }
+ else
+ {
+ pNextFrm->InvalidatePrt();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* lcl_IsInColSect()
+|* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht,
+|* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist.
+|*
+|*************************************************************************/
+
+sal_Bool lcl_IsInColSct( const SwFrm *pUp )
+{
+ sal_Bool bRet = sal_False;
+ while( pUp )
+ {
+ if( pUp->IsColumnFrm() )
+ bRet = sal_True;
+ else if( pUp->IsSctFrm() )
+ return bRet;
+ else if( pUp->IsTabFrm() )
+ return sal_False;
+ pUp = pUp->GetUpper();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::IsMoveable();
+|*
+|*************************************************************************/
+/** determine, if frame is moveable in given environment
+
+ OD 08.08.2003 #110978#
+ method replaced 'old' method <sal_Bool IsMoveable() const>.
+ Determines, if frame is moveable in given environment. if no environment
+ is given (parameter _pLayoutFrm == 0L), the movability in the actual
+ environment (<this->GetUpper()) is checked.
+
+ @author OD
+*/
+
+bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const
+{
+ bool bRetVal = false;
+
+ if ( !_pLayoutFrm )
+ {
+ _pLayoutFrm = GetUpper();
+ }
+
+ if ( _pLayoutFrm && IsFlowFrm() )
+ {
+ if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) )
+ {
+ bRetVal = true;
+ }
+ else if ( _pLayoutFrm->IsInFly() ||
+ _pLayoutFrm->IsInDocBody() ||
+ _pLayoutFrm->IsInFtn() )
+ {
+ if ( _pLayoutFrm->IsInTab() && !IsTabFrm() &&
+ ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) )
+ {
+ bRetVal = false;
+ }
+ else
+ {
+ if ( _pLayoutFrm->IsInFly() )
+ {
+ // if fly frame has a follow (next linked fly frame),
+ // frame is moveable.
+ if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() )
+ {
+ bRetVal = true;
+ }
+ else
+ {
+ // if environment is columned, frame is moveable, if
+ // it isn't in last column.
+ // search for column frame
+ const SwFrm* pCol = _pLayoutFrm;
+ while ( pCol && !pCol->IsColumnFrm() )
+ {
+ pCol = pCol->GetUpper();
+ }
+ // frame is moveable, if found column frame isn't last one.
+ if ( pCol && pCol->GetNext() )
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ else
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ }
+
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::SetInfFlags();
+|*
+|*************************************************************************/
+void SwFrm::SetInfFlags()
+{
+ if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen
+ return; //lieferbar
+
+ bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False;
+
+ SwFrm *pFrm = this;
+ if( IsFtnContFrm() )
+ bInfFtn = sal_True;
+ do
+ { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt
+ if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper()
+ && pFrm->GetUpper()->IsPageFrm() )
+ bInfBody = sal_True;
+ else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() )
+ {
+ bInfTab = sal_True;
+ }
+ else if ( pFrm->IsFlyFrm() )
+ bInfFly = sal_True;
+ else if ( pFrm->IsSctFrm() )
+ bInfSct = sal_True;
+ else if ( pFrm->IsFtnFrm() )
+ bInfFtn = sal_True;
+
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix
+}
+
+/*-----------------22.8.2001 14:30------------------
+ * SwFrm::SetDirFlags( sal_Bool )
+ * actualizes the vertical or the righttoleft-flags.
+ * If the property is derived, it's from the upper or (for fly frames) from
+ * the anchor. Otherwise we've to call a virtual method to check the property.
+ * --------------------------------------------------*/
+
+void SwFrm::SetDirFlags( sal_Bool bVert )
+{
+ if( bVert )
+ {
+ // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
+ // vertical flag of upper/anchor is valid.
+ if( bDerivedVert )
+ {
+ const SwFrm* pAsk = IsFlyFrm() ?
+ ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
+
+ if( pAsk )
+ {
+ bVertical = pAsk->IsVertical() ? 1 : 0;
+ bReverse = pAsk->IsReverse() ? 1 : 0;
+
+ bVertLR = pAsk->IsVertLR() ? 1 : 0;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( !pAsk->bInvalidVert )
+ bInvalidVert = sal_False;
+ }
+ }
+ else
+ CheckDirection( bVert );
+ }
+ else
+ {
+ sal_Bool bInv = 0;
+ if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
+ CheckDirection( bVert );
+ if( bDerivedR2L )
+ {
+ const SwFrm* pAsk = IsFlyFrm() ?
+ ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
+
+ if( pAsk )
+ bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0;
+ if( !pAsk || pAsk->bInvalidR2L )
+ bInv = bInvalidR2L;
+ }
+ bInvalidR2L = bInv;
+ }
+}
+
+SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType )
+{
+ SwFrm* pTmpFrm = this;
+ while ( !pTmpFrm->IsCellFrm() )
+ pTmpFrm = pTmpFrm->GetUpper();
+
+ OSL_ENSURE( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" );
+ return ((SwCellFrm*)pTmpFrm)->GetFollowCell();
+}
+
+SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType )
+{
+ SwFrm* pTmpFrm = this;
+ while ( !pTmpFrm->IsCellFrm() )
+ pTmpFrm = pTmpFrm->GetUpper();
+
+ OSL_ENSURE( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" );
+ return ((SwCellFrm*)pTmpFrm)->GetPreviousCell();
+}
+
+SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow,
+ const SwCellFrm& rOrigCell,
+ const SwRowFrm& rCorrRow,
+ bool bInFollow )
+{
+ SwCellFrm* pRet = NULL;
+ SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower();
+ SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower();
+
+ while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
+ {
+ pCell = (SwCellFrm*)pCell->GetNext();
+ pCorrCell = (SwCellFrm*)pCorrCell->GetNext();
+ }
+
+ OSL_ENSURE( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" );
+
+ if ( pCell != &rOrigCell )
+ {
+ // rOrigCell must be a lower of pCell. We need to recurse into the rows:
+ OSL_ENSURE( pCell->Lower() && pCell->Lower()->IsRowFrm(),
+ "lcl_FindCorrespondingCellFrm does not work" );
+
+ SwRowFrm* pRow = (SwRowFrm*)pCell->Lower();
+ while ( !pRow->IsAnLower( &rOrigCell ) )
+ pRow = (SwRowFrm*)pRow->GetNext();
+
+ SwRowFrm* pCorrRow = 0;
+ if ( bInFollow )
+ pCorrRow = pRow->GetFollowRow();
+ else
+ {
+ SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower());
+
+ if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
+ pCorrRow = pTmpRow;
+ }
+
+ if ( pCorrRow )
+ pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow );
+ }
+ else
+ pRet = pCorrCell;
+
+ return pRet;
+}
+
+// VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
+SwCellFrm* SwCellFrm::GetFollowCell() const
+{
+ SwCellFrm* pRet = NULL;
+
+ // NEW TABLES
+ // Covered cells do not have follow cells!
+ const long nRowSpan = GetLayoutRowSpan();
+ if ( nRowSpan < 1 )
+ return NULL;
+
+ // find most upper row frame
+ const SwFrm* pRow = GetUpper();
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow )
+ return NULL;
+
+ const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() );
+ if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() )
+ return NULL;
+
+ const SwCellFrm* pThisCell = this;
+
+ // Get last cell of the current table frame that belongs to the rowspan:
+ if ( nRowSpan > 1 )
+ {
+ // optimization: Will end of row span be in last row or exceed row?
+ long nMax = 0;
+ while ( pRow->GetNext() && ++nMax < nRowSpan )
+ pRow = pRow->GetNext();
+
+ if ( !pRow->GetNext() )
+ {
+ pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true );
+ pRow = pThisCell->GetUpper();
+ }
+ }
+
+ const SwRowFrm* pFollowRow = NULL;
+ if ( !pRow->GetNext() &&
+ NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
+ ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
+ pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true );
+
+ return pRet;
+}
+
+// VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
+SwCellFrm* SwCellFrm::GetPreviousCell() const
+{
+ SwCellFrm* pRet = NULL;
+
+ // NEW TABLES
+ // Covered cells do not have previous cells!
+ if ( GetLayoutRowSpan() < 1 )
+ return NULL;
+
+ // find most upper row frame
+ const SwFrm* pRow = GetUpper();
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+
+ OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" );
+
+ SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+
+ if ( pTab->IsFollow() )
+ {
+ const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( bIsInFirstLine )
+ {
+ SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster();
+ if ( pMaster && pMaster->HasFollowFlowLine() )
+ {
+ SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower());
+ if ( pMasterRow )
+ pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false );
+ if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
+ pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true ));
+ }
+ }
+ }
+
+ return pRet;
+}
+
+// --> NEW TABLES
+const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const
+{
+ const SwCellFrm* pRet = 0;
+
+ const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper());
+
+ if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) )
+ return *this;
+
+ OSL_ENSURE( pTableFrm &&
+ ( (bStart && GetTabBox()->getRowSpan() < 1) ||
+ (!bStart && GetLayoutRowSpan() > 1) ),
+ "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" );
+
+ if ( pTableFrm )
+ {
+ const SwTable* pTable = pTableFrm->GetTable();
+
+ sal_uInt16 nMax = USHRT_MAX;
+ if ( bCurrentTableOnly )
+ {
+ const SwFrm* pCurrentRow = GetUpper();
+ const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() &&
+ !pTableFrm->IsInHeadline( *pCurrentRow );
+
+ // check how many rows we are allowed to go up or down until we reach the end of
+ // the current table frame:
+ nMax = 0;
+ while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
+ {
+ if ( bStart )
+ {
+ // do not enter a repeated headline:
+ if ( bDoNotEnterHeadline && pTableFrm->IsFollow() &&
+ pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) )
+ break;
+
+ pCurrentRow = pCurrentRow->GetPrev();
+ }
+ else
+ pCurrentRow = pCurrentRow->GetNext();
+
+ ++nMax;
+ }
+ }
+
+ // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
+ // is set) we assure that we find a rMasterBox that has a SwCellFrm in
+ // the current table frame:
+ const SwTableBox& rMasterBox = bStart ?
+ GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
+ GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
+
+ SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() );
+
+ for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
+ {
+ if ( pMasterCell->GetTabBox() == &rMasterBox )
+ {
+ const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper());
+
+ if ( bCurrentTableOnly )
+ {
+ if ( pMasterTable == pTableFrm )
+ {
+ pRet = pMasterCell;
+ break;
+ }
+ }
+ else
+ {
+ if ( pMasterTable == pTableFrm ||
+ ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) ||
+ (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) )
+ {
+ pRet = pMasterCell;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ OSL_ENSURE( pRet, "SwCellFrm::FindStartRowSpanCell: No result" );
+
+ return *pRet;
+}
+// <-- NEW TABLES
+
+const SwRowFrm* SwFrm::IsInSplitTableRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ const SwFrm* pRow = this;
+
+ // find most upper row frame
+ while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return NULL;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
+
+ const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+ // --> OD 2006-06-28 #b6443897#
+ // If most upper row frame is a headline row, the current frame
+ // can't be in a splitted table row. Thus, add corresponding condition.
+ if ( pRow->GetNext() ||
+ pTab->GetTable()->IsHeadline(
+ *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) ||
+ !pTab->HasFollowFlowLine() ||
+ !pTab->GetFollow() )
+ return NULL;
+ // <--
+
+ // skip headline
+ const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
+
+ OSL_ENSURE( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" );
+
+ return pFollowRow;
+}
+
+const SwRowFrm* SwFrm::IsInFollowFlowRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ // find most upper row frame
+ const SwFrm* pRow = this;
+ while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return NULL;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" );
+
+ const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper();
+
+ const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0;
+
+ if ( !pMaster || !pMaster->HasFollowFlowLine() )
+ return NULL;
+
+ const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( !bIsInFirstLine )
+ return NULL;
+
+ const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower());
+ return pMasterRow;
+}
+
+bool SwFrm::IsInBalancedSection() const
+{
+ bool bRet = false;
+
+ if ( IsInSct() )
+ {
+ const SwSectionFrm* pSectionFrm = FindSctFrm();
+ if ( pSectionFrm )
+ bRet = pSectionFrm->IsBalancedSection();
+ }
+ return bRet;
+}
+
+/*
+ * SwLayoutFrm::GetLastLower()
+ */
+const SwFrm* SwLayoutFrm::GetLastLower() const
+{
+ const SwFrm* pRet = Lower();
+ if ( !pRet )
+ return 0;
+ while ( pRet->GetNext() )
+ pRet = pRet->GetNext();
+ return pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flowfrm.cxx b/sw/source/core/layout/flowfrm.cxx
new file mode 100644
index 000000000000..59fac2138f1d
--- /dev/null
+++ b/sw/source/core/layout/flowfrm.cxx
@@ -0,0 +1,2672 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "pam.hxx"
+#include "swtable.hxx"
+#include "frame.hxx"
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "flyfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "dflyobj.hxx"
+#include "frmtool.hxx"
+#include "dcontact.hxx"
+#include <editeng/brkitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <fmtpdsc.hxx>
+#include <editeng/ulspitem.hxx>
+#include <tgrditem.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <editeng/pgrditem.hxx>
+#include <paratr.hxx>
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "tabfrm.hxx"
+#include "pagedesc.hxx"
+#include "layact.hxx"
+#include "fmtornt.hxx"
+#include "flyfrms.hxx"
+#include "sectfrm.hxx"
+#include "section.hxx"
+#include "dbg_lay.hxx"
+#include "lineinfo.hxx"
+#include <fmtclbl.hxx>
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <switerator.hxx>
+
+sal_Bool SwFlowFrm::bMoveBwdJump = sal_False;
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::SwFlowFrm()
+|*
+|*************************************************************************/
+
+
+SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
+ rThis( rFrm ),
+ pFollow( 0 )
+{
+ bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum =
+ bFtnLock = bFlyLock = sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsFollowLocked()
+|* return sal_True if any follow has the JoinLocked flag
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::HasLockedFollow() const
+{
+ const SwFlowFrm* pFrm = GetFollow();
+ while( pFrm )
+ {
+ if( pFrm->IsJoinLocked() )
+ return sal_True;
+ pFrm = pFrm->GetFollow();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsKeepFwdMoveAllowed()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed()
+{
+ //Wenn der Vorgaenger das KeepAttribut traegt und auch dessen
+ //Vorgaenger usw. bis zum ersten der Kette und fuer diesen das
+ //IsFwdMoveAllowed ein sal_False liefert, so ist das Moven eben nicht erlaubt.
+ SwFrm *pFrm = &rThis;
+ if ( !pFrm->IsInFtn() )
+ do
+ { if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
+ pFrm = pFrm->GetIndPrev();
+ else
+ return sal_True;
+ } while ( pFrm );
+
+ //Siehe IsFwdMoveAllowed()
+ sal_Bool bRet = sal_False;
+ if ( pFrm && pFrm->GetIndPrev() )
+ bRet = sal_True;
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CheckKeep()
+|*
+|*************************************************************************/
+
+
+void SwFlowFrm::CheckKeep()
+{
+ //Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn
+ //die ganze Truppe koennte zuruckrutschen.
+ SwFrm *pPre = rThis.GetIndPrev();
+ if( pPre->IsSctFrm() )
+ {
+ SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
+ if( pLast && pLast->FindSctFrm() == pPre )
+ pPre = pLast;
+ else
+ return;
+ }
+ SwFrm* pTmp;
+ sal_Bool bKeep;
+ while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
+ 0 != ( pTmp = pPre->GetIndPrev() ) )
+ {
+ if( pTmp->IsSctFrm() )
+ {
+ SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
+ if( pLast && pLast->FindSctFrm() == pTmp )
+ pTmp = pLast;
+ else
+ break;
+ }
+ pPre = pTmp;
+ }
+ if ( bKeep )
+ pPre->InvalidatePos();
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsKeep()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
+{
+ // 1. The keep attribute is ignored inside footnotes
+ // 2. For compatibility reasons, the keep attribute is
+ // ignored for frames inside table cells
+ // 3. If bBreakCheck is set to true, this function only checks
+ // if there are any break after attributes set at rAttrs
+ // or break before attributes set for the next content (or next table)
+ sal_Bool bKeep = bCheckIfLastRowShouldKeep ||
+ ( !rThis.IsInFtn() &&
+ ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
+ rAttrs.GetKeep().GetValue() );
+
+ OSL_ENSURE( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
+ "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" );
+
+ // Ignore keep attribute if there are break situations:
+ if ( bKeep )
+ {
+ switch ( rAttrs.GetBreak().GetBreak() )
+ {
+ case SVX_BREAK_COLUMN_AFTER:
+ case SVX_BREAK_COLUMN_BOTH:
+ case SVX_BREAK_PAGE_AFTER:
+ case SVX_BREAK_PAGE_BOTH:
+ {
+ bKeep = sal_False;
+ }
+ default: break;
+ }
+ if ( bKeep )
+ {
+ SwFrm *pNxt;
+ if( 0 != (pNxt = rThis.FindNextCnt()) &&
+ (!pFollow || pNxt != pFollow->GetFrm()))
+ {
+ // --> FME 2006-05-15 #135914#
+ // The last row of a table only keeps with the next content
+ // it they are in the same section:
+ if ( bCheckIfLastRowShouldKeep )
+ {
+ const SwSection* pThisSection = 0;
+ const SwSection* pNextSection = 0;
+ const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
+ const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
+
+ if ( pThisSectionFrm )
+ pThisSection = pThisSectionFrm->GetSection();
+
+ if ( pNextSectionFrm )
+ pNextSection = pNextSectionFrm->GetSection();
+
+ if ( pThisSection != pNextSection )
+ bKeep = sal_False;
+ }
+ // <--
+
+ if ( bKeep )
+ {
+ const SwAttrSet* pSet = NULL;
+
+ if ( pNxt->IsInTab() )
+ {
+ SwTabFrm* pTab = pNxt->FindTabFrm();
+ if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
+ pSet = &pTab->GetFmt()->GetAttrSet();
+ }
+
+ if ( ! pSet )
+ pSet = pNxt->GetAttrSet();
+
+ OSL_ENSURE( pSet, "No AttrSet to check keep attribute" );
+
+ if ( pSet->GetPageDesc().GetPageDesc() )
+ bKeep = sal_False;
+ else switch ( pSet->GetBreak().GetBreak() )
+ {
+ case SVX_BREAK_COLUMN_BEFORE:
+ case SVX_BREAK_COLUMN_BOTH:
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_BOTH:
+ bKeep = sal_False;
+ default: break;
+ }
+ }
+ }
+ }
+ }
+ return bKeep;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::BwdMoveNecessary()
+|*
+|*************************************************************************/
+
+
+sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
+{
+ // Der return-Wert entscheidet mit,
+ // ob auf Zurueckgeflossen werden muss, (3)
+ // ob das gute alte WouldFit gerufen werden kann (0, 1)
+ // oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2)
+ // dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind
+ // und Bit 2, dass ich anderen Objekten ausweichen muss.
+
+ //Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt
+ //ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden
+ //koennen), es kann allerdings ggf. eine TestFormatierung stattfinden.
+ //Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly
+ //Lower von mir ist, so spielt er keine Rolle.
+ //Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich
+ //selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly
+ //keine Rolle.
+ //#32639# Wenn das Objekt bei mir verankert ist kann ich es
+ //vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst,
+ //eine TestFormatierung ist dann allerdings nicht erlaubt!
+ sal_uInt8 nRet = 0;
+ SwFlowFrm *pTmp = this;
+ do
+ { // Wenn an uns oder einem Follow Objekte haengen, so
+ // kann keine ProbeFormatierung stattfinden, da absatzgebundene
+ // nicht richtig beruecksichtigt wuerden und zeichengebundene sollten
+ // gar nicht zur Probe formatiert werden.
+ if( pTmp->GetFrm()->GetDrawObjs() )
+ nRet = 1;
+ pTmp = pTmp->GetFollow();
+ } while ( !nRet && pTmp );
+ if ( pPage->GetSortedObjs() )
+ {
+ // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ sal_uLong nIndex = ULONG_MAX;
+ for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ SwAnchoredObject* pObj = rObjs[i];
+ const SwFrmFmt& rFmt = pObj->GetFrmFmt();
+ const SwRect aRect( pObj->GetObjRect() );
+ if ( aRect.IsOver( rRect ) &&
+ rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
+ {
+ if( rThis.IsLayoutFrm() && //Fly Lower von This?
+ Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
+ continue;
+ if( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly?
+ continue;
+ }
+
+ const SwFrm* pAnchor = pObj->GetAnchorFrm();
+ if ( pAnchor == &rThis )
+ {
+ nRet |= 1;
+ continue;
+ }
+
+ //Nicht wenn das Objekt im Textfluss hinter mir verankert ist,
+ //denn dann weiche ich ihm nicht aus.
+ if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
+ {
+ if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA )
+ {
+ // Den Index des anderen erhalten wir immer ueber das Ankerattr.
+ sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
+ // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
+ // Anker des verdraengenden Objekts im Text steht, dann wird
+ // nicht ausgewichen.
+ // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
+ // da sonst recht teuer.
+ if( ULONG_MAX == nIndex )
+ {
+ const SwNode *pNode;
+ if ( rThis.IsCntntFrm() )
+ pNode = ((SwCntntFrm&)rThis).GetNode();
+ else if( rThis.IsSctFrm() )
+ pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
+ GetFmt())->GetSectionNode();
+ else
+ {
+ OSL_ENSURE( rThis.IsTabFrm(), "new FowFrm?" );
+ pNode = ((SwTabFrm&)rThis).GetTable()->
+ GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
+ }
+ nIndex = pNode->GetIndex();
+ }
+ if( nIndex < nTmpIndex )
+ continue;
+ }
+ }
+ else
+ continue;
+
+ nRet |= 2;
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
+|*
+|* Beschreibung Eine Spezialisierte Form des Cut() und Paste(), die
+|* eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden
+|* nur minimale Operationen und Benachrichtigungen ausgefuehrt.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
+{
+ //Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander-
+ //gereiht und ein Henkel auf den ersten wird zurueckgeliefert.
+ //Zurueckbleibende werden geeignet invalidiert.
+
+ SwLayoutFrm *pLay = pStart->GetUpper();
+ if ( pLay->IsInFtn() )
+ pLay = pLay->FindFtnFrm();
+
+ // --> OD 2006-05-08 #i58846#
+ // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
+ if( pStart->IsInFtn() )
+ {
+ SwFrm* pTmp = pStart->GetIndPrev();
+ if( pTmp )
+ pTmp->Prepare( PREP_QUOVADIS );
+ }
+ // <--
+
+ //Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den
+ //Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen
+ //noch wer weiss wo hin.
+ if ( pStart == pStart->GetUpper()->Lower() )
+ pStart->GetUpper()->pLower = 0;
+ if ( pStart->GetPrev() )
+ {
+ pStart->GetPrev()->pNext = 0;
+ pStart->pPrev = 0;
+ }
+
+ if ( pLay->IsFtnFrm() )
+ {
+ if ( !pLay->Lower() && !pLay->IsColLocked() &&
+ !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
+ {
+ pLay->Cut();
+ delete pLay;
+ }
+ else
+ {
+ sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
+ ((SwFtnFrm*)pLay)->LockBackMove();
+ pLay->InvalidateSize();
+ pLay->Calc();
+ SwCntntFrm *pCnt = pLay->ContainsCntnt();
+ while ( pCnt && pLay->IsAnLower( pCnt ) )
+ {
+ //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht
+ //in eine endlose Seitenwanderung hineinlaufen und rufen das
+ //Calc garnicht erst!
+ OSL_ENSURE( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." );
+ if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
+ ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
+ break;
+ pCnt->Calc();
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if( bUnlock )
+ ((SwFtnFrm*)pLay)->UnlockBackMove();
+ }
+ pLay = 0;
+ }
+ return pLay;
+}
+
+
+
+sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
+ SwFrm *pOldParent )
+{
+ //returnt sal_True wenn in der Kette ein LayoutFrm steht.
+ sal_Bool bRet = sal_False;
+
+ //Die mit pStart beginnende Kette wird vor den Sibling unter den Parent
+ //gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt.
+
+ //Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert
+ //werden, dann alle Upper fuer die Kette und schliesslich dass Ende.
+ //Unterwegs werden alle geeignet invalidiert.
+ if ( pSibling )
+ {
+ if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
+ pStart->GetPrev()->pNext = pStart;
+ else
+ pParent->pLower = pStart;
+ pSibling->_InvalidatePos();
+ pSibling->_InvalidatePrt();
+ }
+ else
+ {
+ if ( 0 == (pStart->pPrev = pParent->Lower()) )
+ pParent->pLower = pStart;
+ else
+ //Modified for #i100782#,04/03/2009
+ //If the pParent has more than 1 child nodes, former design will
+ //ignore them directly without any collection work. It will make some
+ //dangling pointers. This lead the crash...
+ //The new design will find the last child of pParent in loop way, and
+ //add the pStart after the last child.
+ // pParent->Lower()->pNext = pStart;
+ {
+ SwFrm* pTemp = pParent->pLower;
+ while (pTemp)
+ {
+ if (pTemp->pNext)
+ pTemp = pTemp->pNext;
+ else
+ {
+ pStart->pPrev = pTemp;
+ pTemp->pNext = pStart;
+ break;
+ }
+ }
+ }
+ //End modification for #i100782#,04/03/2009
+
+ // #i27145#
+ if ( pParent->IsSctFrm() )
+ {
+ // We have no sibling because pParent is a section frame and
+ // has just been created to contain some content. The printing
+ // area of the frame behind pParent has to be invalidated, so
+ // that the correct distance between pParent and the next frame
+ // can be calculated.
+ pParent->InvalidateNextPrtArea();
+ }
+ }
+ SwFrm *pFloat = pStart;
+ SwFrm *pLst = 0;
+ SWRECTFN( pParent )
+ SwTwips nGrowVal = 0;
+ do
+ { pFloat->pUpper = pParent;
+ pFloat->_InvalidateAll();
+ pFloat->CheckDirChange();
+
+ //Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit
+ //dem CacheIdx scheint etwas riskant!
+ if ( pFloat->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pFloat)->Init(); //Ich bin sein Freund.
+ }
+ else
+ bRet = sal_True;
+
+ nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
+ if ( pFloat->GetNext() )
+ pFloat = pFloat->GetNext();
+ else
+ {
+ pLst = pFloat;
+ pFloat = 0;
+ }
+ } while ( pFloat );
+
+ if ( pSibling )
+ {
+ pLst->pNext = pSibling;
+ pSibling->pPrev = pLst;
+ if( pSibling->IsInFtn() )
+ {
+ if( pSibling->IsSctFrm() )
+ pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
+ if( pSibling )
+ pSibling->Prepare( PREP_ERGOSUM );
+ }
+ }
+ if ( nGrowVal )
+ {
+ if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen
+ pOldParent->Shrink( nGrowVal );
+ pParent->Grow( nGrowVal );
+ }
+
+ if ( pParent->IsFtnFrm() )
+ ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
+ return bRet;
+}
+
+
+
+void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent uebergeben." );
+ OSL_ENSURE( rThis.GetUpper(), "Wo kommen wir denn her?" );
+
+ //Sparsamer benachrichtigen wenn eine Action laeuft.
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
+
+ if ( !bComplete )
+ {
+ SwFrm *pPre = rThis.GetIndPrev();
+ if ( pPre )
+ {
+ pPre->SetRetouche();
+ // --> OD 2004-11-23 #115759# - follow-up of #i26250#
+ // invalidate printing area of previous frame, if it's in a table
+ if ( pPre->GetUpper()->IsInTab() )
+ {
+ pPre->_InvalidatePrt();
+ }
+ // <--
+ pPre->InvalidatePage();
+ }
+ else
+ { rThis.GetUpper()->SetCompletePaint();
+ rThis.GetUpper()->InvalidatePage();
+ }
+ }
+
+ SwPageFrm *pOldPage = rThis.FindPageFrm();
+
+ SwLayoutFrm *pOldParent = CutTree( &rThis );
+ const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
+
+ // Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte
+ // dieser automatisch verschwinden.
+ SwSectionFrm *pSct;
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( pOldParent && !pOldParent->Lower() &&
+ ( pOldParent->IsInSct() &&
+ !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) ) )
+ // <--
+ {
+ pSct->DelEmpty( sal_False );
+ }
+
+ // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten"
+ if( !rThis.IsInSct() &&
+ ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
+ rThis.GetUpper()->Calc();
+ else if( rThis.GetUpper()->IsSctFrm() )
+ {
+ SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
+ sal_Bool bOld = pTmpSct->IsCntntLocked();
+ pTmpSct->SetCntntLock( sal_True );
+ pTmpSct->Calc();
+ if( !bOld )
+ pTmpSct->SetCntntLock( sal_False );
+ }
+ SwPageFrm *pPage = rThis.FindPageFrm();
+
+ if ( pOldPage != pPage )
+ {
+ rThis.InvalidatePage( pPage );
+ if ( rThis.IsLayoutFrm() )
+ {
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
+ if ( pCnt )
+ pCnt->InvalidatePage( pPage );
+ }
+ else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
+ && pPage->FindFirstBodyCntnt() == &rThis )
+ {
+ rThis._InvalidateLineNum();
+ }
+ }
+ if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
+ rThis.GetUpper()->InvalidatePage( pPage );
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsAnFollow()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
+{
+ const SwFlowFrm *pFoll = this;
+ do
+ { if ( pAssumed == pFoll )
+ return sal_True;
+ pFoll = pFoll->GetFollow();
+ } while ( pFoll );
+ return sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlowFrm::FindMaster()
+|*
+|*************************************************************************/
+
+SwTxtFrm* SwCntntFrm::FindMaster() const
+{
+ OSL_ENSURE( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
+
+ const SwCntntFrm* pCnt = GetPrevCntntFrm();
+
+ while ( pCnt )
+ {
+ if ( pCnt->HasFollow() && pCnt->GetFollow() == this )
+ {
+ OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" );
+ return (SwTxtFrm*)pCnt;
+ }
+ pCnt = pCnt->GetPrevCntntFrm();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+SwSectionFrm* SwSectionFrm::FindMaster() const
+{
+ OSL_ENSURE( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
+
+ SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() );
+ SwSectionFrm* pSect = aIter.First();
+ while ( pSect )
+ {
+ if( pSect->GetFollow() == this )
+ return pSect;
+ pSect = aIter.Next();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
+{
+ OSL_ENSURE( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
+
+ SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() );
+ SwTabFrm* pTab = aIter.First();
+ while ( pTab )
+ {
+ if ( bFirstMaster )
+ {
+ //
+ // Optimization. This makes code like this obsolete:
+ // while ( pTab->IsFollow() )
+ // pTab = pTab->FindMaster();
+ //
+ if ( !pTab->IsFollow() )
+ {
+ SwTabFrm* pNxt = pTab;
+ while ( pNxt )
+ {
+ if ( pNxt->GetFollow() == this )
+ return pTab;
+ pNxt = pNxt->GetFollow();
+ }
+ }
+ }
+ else
+ {
+ if ( pTab->GetFollow() == this )
+ return pTab;
+ }
+
+ pTab = aIter.Next();
+ }
+
+ OSL_FAIL( "Follow ist lost in Space." );
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetLeaf()
+|*
+|* Beschreibung Liefert das naechste/vorhergehende LayoutBlatt,
+|* das _nicht_ unterhalb von this liegt (oder gar this selbst ist).
+|* Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie
+|* pAnch Ausgangsfrm liegen (Body, Ftn)
+|*
+|*************************************************************************/
+
+
+const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd,
+ const SwFrm *pAnch ) const
+{
+ //Ohne Fluss kein genuss...
+ if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
+ return 0;
+
+ const SwFrm *pLeaf = this;
+ sal_Bool bFound = sal_False;
+
+ do
+ { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
+
+ if ( pLeaf &&
+ (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
+ {
+ if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
+ pAnch->IsInFtn() == pLeaf->IsInFtn() )
+ {
+ bFound = sal_True;
+ }
+ }
+ } while ( !bFound && pLeaf );
+
+ return (const SwLayoutFrm*)pLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetLeaf()
+|*
+|* Beschreibung Ruft Get[Next|Prev]Leaf
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
+{
+ if ( IsInFtn() )
+ return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
+
+ // --> OD 2005-08-16 #i53323#
+ // A frame could be inside a table AND inside a section.
+ // Thus, it has to be determined, which is the first parent.
+ bool bInTab( IsInTab() );
+ bool bInSct( IsInSct() );
+ if ( bInTab && bInSct )
+ {
+ const SwFrm* pUpperFrm( GetUpper() );
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->IsTabFrm() )
+ {
+ // the table is the first.
+ bInSct = false;
+ break;
+ }
+ else if ( pUpperFrm->IsSctFrm() )
+ {
+ // the section is the first.
+ bInTab = false;
+ break;
+ }
+
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+
+ if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
+ return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
+
+ if ( bInSct )
+ return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
+ // <--
+
+ return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
+}
+
+
+
+sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew )
+{
+ //Jetzt wirds leider etwas kompliziert:
+ //Ich bringe ich evtl. selbst
+ //einen Pagedesc mit; der der Folgeseite muss dann damit
+ //uebereinstimmen.
+ //Anderfalls muss ich mir etwas genauer ansehen wo der
+ //Folgepagedesc herkam.
+ //Wenn die Folgeseite selbst schon sagt, dass ihr
+ //Pagedesc nicht stimmt so kann ich das Teil bedenkenlos
+ //auswechseln.
+ //Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst
+ //das leider noch immer nicht, dass ich damit etwas anfangen
+ //kann: Wenn der erste BodyCntnt einen PageDesc oder einen
+ //PageBreak wuenscht, so muss ich ebenfalls eine neue
+ //Seite einfuegen; es sein denn die gewuenschte Seite ist
+ //die richtige.
+ //Wenn ich einen neue Seite eingefuegt habe, so fangen die
+ //Probleme leider erst an, denn wahrscheinlich wird die dann
+ //folgende Seite verkehrt gewesen und ausgewechselt worden
+ //sein. Das hat zur Folge, dass ich zwar eine neue (und
+ //jetzt richtige) Seite habe, die Bedingungen zum auswechseln
+ //aber leider noch immer stimmen.
+ //Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite
+ //einsetzen (Leerseiten werden noetigenfalls bereits von
+ //InsertPage() eingefuegt.
+ const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
+
+ //Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin!
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nTmp = 0;
+ SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
+ if ( !pFlow || !pFlow->IsFollow() )
+ {
+ pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
+ if( pDesc )
+ {
+ if( !pDesc->GetRightFmt() )
+ nTmp = 2;
+ else if( !pDesc->GetLeftFmt() )
+ nTmp = 1;
+ else if( rFmtDesc.GetNumOffset() )
+ nTmp = rFmtDesc.GetNumOffset();
+ }
+ }
+
+ //Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die
+ //virtuelle Seitennummer des neuen Layoutleafs?
+ // Bei Follows zaehlt der PageDesc nicht
+ const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False )
+ : pNew->OnRightPage();
+ if ( !pDesc )
+ pDesc = pNew->FindPageDesc();
+ const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
+ // Haben wir uns selbst gefunden?
+ if( pNewFlow == pFlow )
+ pNewFlow = NULL;
+ if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
+ pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
+ const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
+ ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
+
+ return ( pNew->GetPageDesc() != pDesc || // own desc ?
+ pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ||
+ ( pNewDesc && pNewDesc == pDesc ) );
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextLeaf()
+|*
+|* Beschreibung Liefert das naechste LayoutBlatt in den das
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
+{
+ OSL_ENSURE( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
+ OSL_ENSURE( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
+
+ const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
+ //Will ich auch im Body landen.
+
+ // Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich
+ // die Verkettung absuchen.
+ if( IsInFly() )
+ eMakePage = MAKEPAGE_NONE;
+
+ //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext...
+ //wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander
+ //abklappern....
+ SwLayoutFrm *pLayLeaf = 0;
+ if ( IsTabFrm() )
+ {
+ SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
+ if ( pTmp )
+ pLayLeaf = pTmp->GetUpper();
+ }
+ if ( !pLayLeaf )
+ pLayLeaf = GetNextLayoutLeaf();
+
+ SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
+ //nicht wieder vom Anfang gesucht
+ //wird.
+ sal_Bool bNewPg = sal_False; //nur einmal eine neue Seite einfuegen.
+
+ while ( sal_True )
+ {
+ if ( pLayLeaf )
+ {
+ //Es gibt noch einen weiteren LayoutFrm, mal sehen,
+ //ob er bereit ist mich aufzunehmen.
+ //Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt
+ //sein (DocBody bzw. Footnote.)
+ if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
+ { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
+ pLayLeaf = 0;
+ continue;
+ }
+ if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
+ || pLayLeaf->IsInSct() )
+ {
+ //Er will mich nicht; neuer Versuch, neues Glueck
+ pOldLayLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ continue;
+ }
+ //Er will mich, also ist er der gesuchte und ich bin fertig.
+ //Bei einem Seitenwechsel kann es allerdings noch sein, dass
+ //Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen
+ //wir eine Seite des richtigen Typs einfuegen.
+
+ if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
+ eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
+ return pLayLeaf;
+
+ SwPageFrm *pNew = pLayLeaf->FindPageFrm();
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ // #111704# The pagedesc check does not make sense for frames in fly frames
+ if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
+ // --> FME 2005-05-10 #i46683#
+ // Do not consider page descriptions in browse mode (since
+ // MoveBwd ignored them)
+ !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ // <--
+ {
+ if( WrongPageDesc( pNew ) )
+ {
+ SwFtnContFrm *pCont = pNew->FindFtnCont();
+ if( pCont )
+ {
+ // Falls die Referenz der ersten Fussnote dieser Seite
+ // vor der Seite liegt, fuegen wir lieber keine neue Seite
+ // ein (Bug #55620#)
+ SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
+ if( pFtn && pFtn->GetRef() )
+ {
+ const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
+ if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
+ break;
+ }
+ }
+ //Erwischt, die folgende Seite ist verkehrt, also
+ //muss eine neue eingefuegt werden.
+ if ( eMakePage == MAKEPAGE_INSERT )
+ {
+ bNewPg = sal_True;
+
+ SwPageFrm *pPg = pOldLayLeaf ?
+ pOldLayLeaf->FindPageFrm() : 0;
+ if ( pPg && pPg->IsEmptyPage() )
+ //Nicht hinter, sondern vor der EmptyPage einfuegen.
+ pPg = (SwPageFrm*)pPg->GetPrev();
+
+ if ( !pPg || pPg == pNew )
+ pPg = FindPageFrm();
+
+ InsertPage( pPg, sal_False );
+ pLayLeaf = GetNextLayoutLeaf();
+ pOldLayLeaf = 0;
+ continue;
+ }
+ else
+ pLayLeaf = 0;
+ }
+ }
+ break;
+ }
+ else
+ {
+ //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
+ //neue Seite her.
+ if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
+ {
+ InsertPage(
+ pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
+ sal_False );
+
+ //und nochmal das ganze
+ pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
+ }
+ else
+ break;
+ }
+ }
+ return pLayLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
+{
+ OSL_ENSURE( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
+
+ const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
+ //will ich auch im Body landen.
+ const sal_Bool bFly = IsInFly();
+
+ SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
+ SwLayoutFrm *pPrevLeaf = 0;
+
+ while ( pLayLeaf )
+ {
+ if ( pLayLeaf->IsInTab() || //In Tabellen geht's niemals hinein.
+ pLayLeaf->IsInSct() ) //In Bereiche natuerlich auch nicht!
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ else if ( bBody && pLayLeaf->IsInDocBody() )
+ {
+ if ( pLayLeaf->Lower() )
+ break;
+ pPrevLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ if ( pLayLeaf )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ else if ( bFly )
+ break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein.
+ else
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ return pLayLeaf ? pLayLeaf : pPrevLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::IsPrevObjMove()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsPrevObjMove() const
+{
+ //sal_True der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen
+ // und fuer diesen ggf. Umbrechen.
+
+ //!!!!!!!!!!!Hack!!!!!!!!!!!
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ return sal_False;
+
+ SwFrm *pPre = rThis.FindPrev();
+
+ if ( pPre && pPre->GetDrawObjs() )
+ {
+ OSL_ENSURE( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" );
+ if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
+ return sal_False;
+ SwLayoutFrm* pPreUp = pPre->GetUpper();
+ // Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist,
+ // duerfen wir aus diesem durchaus heraushaengen,
+ // es muss stattdessen der Upper des SectionFrms beruecksichtigt werden.
+ if( pPreUp->IsInSct() )
+ {
+ if( pPreUp->IsSctFrm() )
+ pPreUp = pPreUp->GetUpper();
+ else if( pPreUp->IsColBodyFrm() &&
+ pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
+ pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
+ }
+ // --> OD 2004-10-15 #i26945# - re-factoring:
+ // use <GetVertPosOrientFrm()> to determine, if object has followed the
+ // text flow to the next layout frame
+ for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-07-01 #i28701# - consider changed type of
+ // <SwSortedObjs> entries.
+ const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
+ // OD 2004-01-20 #110582# - do not consider hidden objects
+ // --> OD 2004-10-15 #i26945# - do not consider object, which
+ // doesn't follow the text flow.
+ if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
+ pObj->GetDrawObj()->GetLayer() ) &&
+ pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
+ // <--
+ {
+ const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
+ if ( pVertPosOrientFrm &&
+ pPreUp != pVertPosOrientFrm &&
+ !pPreUp->IsAnLower( pVertPosOrientFrm ) )
+ {
+ return sal_True;
+ }
+ }
+ }
+ // <--
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::IsPageBreak()
+|*
+|* Beschreibung Wenn vor dem Frm ein harter Seitenumbruch steht UND
+|* es einen Vorgaenger auf der gleichen Seite gibt, wird sal_True
+|* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
+|* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
+|* zurueck, wenn ein PageBreak besteht.
+|* Fuer Follows wird der harte Seitenumbruch natuerlich nicht
+|* ausgewertet.
+|* Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
+|* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite
+|* gibt ist jede weitere Ueberlegung ueberfluessig.
+|* Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn
+|* im FrmFmt ein PageDesc angegeben wird.
+|* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
+|* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const
+{
+ if ( !IsFollow() && rThis.IsInDocBody() &&
+ ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968
+ {
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ return sal_False;
+ const SwAttrSet *pSet = rThis.GetAttrSet();
+
+ //Vorgaenger ermitteln
+ const SwFrm *pPrev = rThis.FindPrev();
+ while ( pPrev && ( !pPrev->IsInDocBody() ||
+ ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
+ pPrev = pPrev->FindPrev();
+
+ if ( pPrev )
+ {
+ OSL_ENSURE( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
+ if ( bAct )
+ { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
+ return sal_False;
+ }
+ else
+ { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
+ return sal_False;
+ }
+
+ const SvxBreak eBreak = pSet->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
+ return sal_True;
+ else
+ {
+ const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
+ if ( ePrB == SVX_BREAK_PAGE_AFTER ||
+ ePrB == SVX_BREAK_PAGE_BOTH ||
+ pSet->GetPageDesc().GetPageDesc() )
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::IsColBreak()
+|*
+|* Beschreibung Wenn vor dem Frm ein harter Spaltenumbruch steht UND
+|* es einen Vorgaenger in der gleichen Spalte gibt, wird sal_True
+|* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
+|* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
+|* zurueck, wenn ein ColBreak besteht.
+|* Fuer Follows wird der harte Spaltenumbruch natuerlich nicht
+|* ausgewertet.
+|* Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
+|* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte
+|* gibt ist jede weitere Ueberlegung ueberfluessig.
+|* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
+|* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const
+{
+ if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
+ {
+ const SwFrm *pCol = rThis.FindColFrm();
+ if ( pCol )
+ {
+ //Vorgaenger ermitteln
+ const SwFrm *pPrev = rThis.FindPrev();
+ while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
+ ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
+ pPrev = pPrev->FindPrev();
+
+ if ( pPrev )
+ {
+ if ( bAct )
+ { if ( pCol == pPrev->FindColFrm() )
+ return sal_False;
+ }
+ else
+ { if ( pCol != pPrev->FindColFrm() )
+ return sal_False;
+ }
+
+ const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
+ eBreak == SVX_BREAK_COLUMN_BOTH )
+ return sal_True;
+ else
+ {
+ const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
+ if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
+ ePrB == SVX_BREAK_COLUMN_BOTH )
+ return sal_True;
+ }
+ }
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const
+{
+ if( rThis.IsInSct() )
+ {
+ const SwFrm* pTmp = rThis.GetUpper();
+ while( pTmp )
+ {
+ if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
+ pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
+ ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
+ return sal_True;
+ if( pTmp->IsPageFrm() )
+ return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True;
+ if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
+ return IsColBreak( sal_True );
+ if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
+ return sal_False;
+ pTmp = pTmp->GetUpper();
+ }
+ OSL_FAIL( "HasParaSpaceAtPages: Where's my page?" );
+ return sal_False;
+ }
+ if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
+ IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) )
+ return sal_True;
+ const SwFrm* pTmp = rThis.FindColFrm();
+ if( pTmp )
+ {
+ if( pTmp->GetPrev() )
+ return sal_False;
+ }
+ else
+ pTmp = &rThis;
+ pTmp = pTmp->FindPageFrm();
+ return pTmp && !pTmp->GetPrev();
+}
+
+/** helper method to determine previous frame for calculation of the
+ upper space
+
+ OD 2004-03-10 #i11860#
+
+ @author OD
+*/
+const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
+{
+ const SwFrm* pPrevFrm = _pProposedPrevFrm
+ ? _pProposedPrevFrm
+ : rThis.GetPrev();
+
+ // Skip hidden paragraphs and empty sections
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
+ ( pPrevFrm->IsSctFrm() &&
+ !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+
+ // Special case: no direct previous frame is found but frame is in footnote
+ // Search for a previous frame in previous footnote,
+ // if frame isn't in a section, which is also in the footnote
+ if ( !pPrevFrm && rThis.IsInFtn() &&
+ ( rThis.IsSctFrm() ||
+ !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
+ {
+ const SwFtnFrm* pPrevFtnFrm =
+ static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
+ if ( pPrevFtnFrm )
+ {
+ pPrevFrm = pPrevFtnFrm->GetLastLower();
+
+ // Skip hidden paragraphs and empty sections
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
+ ( pPrevFrm->IsSctFrm() &&
+ !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ }
+ }
+ // Special case: found previous frame is a section
+ // Search for the last content in the section
+ if( pPrevFrm && pPrevFrm->IsSctFrm() )
+ {
+ const SwSectionFrm* pPrevSectFrm =
+ static_cast<const SwSectionFrm*>(pPrevFrm);
+ pPrevFrm = pPrevSectFrm->FindLastCntnt();
+ // If the last content is in a table _inside_ the section,
+ // take the table herself.
+ // OD 2004-02-18 #106629# - correction:
+ // Check directly, if table is inside table, instead of indirectly
+ // by checking, if section isn't inside a table
+ if ( pPrevFrm && pPrevFrm->IsInTab() )
+ {
+ const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
+ if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
+ {
+ pPrevFrm = pTableFrm;
+ }
+ }
+ // OD 2004-02-18 #106629# correction: skip hidden text frames
+ while ( pPrevFrm &&
+ pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ }
+
+ return pPrevFrm;
+}
+
+// OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
+SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
+ const SwFrm* pPr,
+ const bool _bConsiderGrid ) const
+{
+ // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
+ const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
+
+ SwBorderAttrAccess *pAccess;
+ SwFrm* pOwn;
+ if( !pAttrs )
+ {
+ if( rThis.IsSctFrm() )
+ {
+ SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
+ do
+ pOwn = pFoll->ContainsAny();
+ while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
+ if( !pOwn )
+ return 0;
+ }
+ else
+ pOwn = &rThis;
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
+ pAttrs = pAccess->Get();
+ }
+ else
+ {
+ pAccess = NULL;
+ pOwn = &rThis;
+ }
+ SwTwips nUpper = 0;
+ // OD 06.01.2004 #i11859#
+ {
+ const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
+ if( pPrevFrm )
+ {
+ // OD 2004-03-10 #i11860# - use new method to determine needed spacing
+ // values of found previous frame and use these values.
+ SwTwips nPrevLowerSpace = 0;
+ SwTwips nPrevLineSpacing = 0;
+ // --> OD 2009-08-28 #i102458#
+ bool bPrevLineSpacingPorportional = false;
+ GetSpacingValuesOfFrm( (*pPrevFrm),
+ nPrevLowerSpace, nPrevLineSpacing,
+ bPrevLineSpacingPorportional );
+ // <--
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
+ {
+ nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
+ SwTwips nAdd = nPrevLineSpacing;
+ // OD 07.01.2004 #i11859# - consideration of the line spacing
+ // for the upper spacing of a text frame
+ if ( bUseFormerLineSpacing )
+ {
+ // former consideration
+ if ( pOwn->IsTxtFrm() )
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
+ }
+ nUpper += nAdd;
+ }
+ else
+ {
+ // new consideration:
+ // Only the proportional line spacing of the previous
+ // text frame is considered for the upper spacing and
+ // the line spacing values are add up instead of
+ // building its maximum.
+ if ( pOwn->IsTxtFrm() )
+ {
+ // --> OD 2009-08-28 #i102458#
+ // Correction:
+ // A proportional line spacing of the previous text frame
+ // is added up to a own leading line spacing.
+ // Otherwise, the maximum of the leading line spacing
+ // of the previous text frame and the own leading line
+ // spacing is built.
+ if ( bPrevLineSpacingPorportional )
+ {
+ nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
+ }
+ else
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
+ }
+ // <--
+ }
+ nUpper += nAdd;
+ }
+ }
+ else
+ {
+ nUpper = Max( static_cast<long>(nPrevLowerSpace),
+ static_cast<long>(pAttrs->GetULSpace().GetUpper()) );
+ // OD 07.01.2004 #i11859# - consideration of the line spacing
+ // for the upper spacing of a text frame
+ if ( bUseFormerLineSpacing )
+ {
+ // former consideration
+ if ( pOwn->IsTxtFrm() )
+ nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
+ if ( nPrevLineSpacing != 0 )
+ {
+ nUpper = Max( nUpper, nPrevLineSpacing );
+ }
+ }
+ else
+ {
+ // new consideration:
+ // Only the proportional line spacing of the previous
+ // text frame is considered for the upper spacing and
+ // the line spacing values are add up and added to
+ // the paragraph spacing instead of building the
+ // maximum of the line spacings and the paragraph spacing.
+ SwTwips nAdd = nPrevLineSpacing;
+ if ( pOwn->IsTxtFrm() )
+ {
+ // --> OD 2009-08-28 #i102458#
+ // Correction:
+ // A proportional line spacing of the previous text frame
+ // is added up to a own leading line spacing.
+ // Otherwise, the maximum of the leading line spacing
+ // of the previous text frame and the own leading line
+ // spacing is built.
+ if ( bPrevLineSpacingPorportional )
+ {
+ nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
+ }
+ else
+ {
+ nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
+ }
+ // <--
+ }
+ nUpper += nAdd;
+ }
+ }
+ }
+ else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
+ CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
+ {
+ nUpper = pAttrs->GetULSpace().GetUpper();
+ }
+ }
+
+ // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
+ // to method <GetTopLine(..)>, if parameter <pPr> is set.
+ // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
+ nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
+
+ // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
+ // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
+
+ //consider grid in square page mode
+ if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
+ {
+ nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
+ }
+
+ delete pAccess;
+ return nUpper;
+}
+
+/** method to detemine the upper space amount, which is considered for
+ the page grid
+
+ OD 2004-03-12 #i11860#
+ Precondition: Position of frame is valid.
+
+ @author OD
+*/
+SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
+ const SwTwips _nUpperSpaceWithoutGrid ) const
+{
+ SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
+
+ if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
+ {
+ const SwPageFrm* pPageFrm = rThis.FindPageFrm();
+ GETGRID( pPageFrm )
+ if( pGrid )
+ {
+ const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
+ if ( pBodyFrm )
+ {
+ const long nGridLineHeight =
+ pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
+
+ SWRECTFN( (&rThis) )
+ const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
+ const SwTwips nProposedPrtTop =
+ (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
+ _nUpperSpaceWithoutGrid );
+
+ const SwTwips nSpaceAbovePrtTop =
+ (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
+ const SwTwips nSpaceOfCompleteLinesAbove =
+ nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
+ SwTwips nNewPrtTop =
+ (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
+ if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
+ {
+ nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
+ }
+
+ const SwTwips nNewUpperSpace =
+ (*fnRect->fnYDiff)( nNewPrtTop,
+ (rThis.Frm().*fnRect->fnGetTop)() );
+
+ nUpperSpaceAmountConsideredForPageGrid =
+ nNewUpperSpace - _nUpperSpaceWithoutGrid;
+
+ OSL_ENSURE( nUpperSpaceAmountConsideredForPageGrid >= 0,
+ "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
+ }
+ }
+ }
+ return nUpperSpaceAmountConsideredForPageGrid;
+}
+
+/** method to determent the upper space amount, which is considered for
+ the previous frame
+
+ OD 2004-03-11 #i11860#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
+{
+ SwTwips nUpperSpaceAmountOfPrevFrm = 0;
+
+ const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
+ if ( pPrevFrm )
+ {
+ SwTwips nPrevLowerSpace = 0;
+ SwTwips nPrevLineSpacing = 0;
+ // --> OD 2009-08-28 #i102458#
+ bool bDummy = false;
+ GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
+ // <--
+ if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
+ {
+ const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
+ !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
+ {
+ nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
+ }
+ else
+ {
+ nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
+ }
+ }
+ }
+
+ return nUpperSpaceAmountOfPrevFrm;
+}
+
+/** method to determine the upper space amount, which is considered for
+ the previous frame and the page grid, if option 'Use former object
+ positioning' is OFF
+
+ OD 2004-03-18 #i11860#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
+{
+ SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
+
+ if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
+ {
+ nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
+ _GetUpperSpaceAmountConsideredForPrevFrm() +
+ _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) );
+ }
+
+ return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+}
+
+/** calculation of lower space
+
+ OD 2004-03-02 #106629#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
+{
+ SwTwips nLowerSpace = 0;
+
+ SwBorderAttrAccess* pAttrAccess = 0L;
+ if ( !_pAttrs )
+ {
+ pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
+ _pAttrs = pAttrAccess->Get();
+ }
+
+ sal_Bool bCommonBorder = sal_True;
+ if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
+ {
+ const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
+ bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
+ }
+ nLowerSpace = bCommonBorder ?
+ _pAttrs->GetBottomLine( rThis ) :
+ _pAttrs->CalcBottomLine();
+
+ // --> OD 2004-07-16 #i26250#
+ // - correct consideration of table frames
+ // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
+ if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
+ // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
+ ( rThis.IsInTab() && !GetFollow() ) ) &&
+ // <--
+ !rThis.GetIndNext() )
+ {
+ nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
+ }
+ // <--
+
+ delete pAttrAccess;
+
+ return nLowerSpace;
+}
+
+/** calculation of the additional space to be considered, if flow frame
+ is the last inside a table cell
+
+ OD 2004-07-16 #i26250#
+
+ @author OD
+*/
+SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
+ const SwBorderAttrs* _pAttrs ) const
+{
+ SwTwips nAdditionalLowerSpace = 0;
+
+ if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
+ {
+ const SwFrm* pFrm = &rThis;
+ if ( pFrm->IsSctFrm() )
+ {
+ const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
+ pFrm = pSectFrm->FindLastCntnt();
+ if ( pFrm && pFrm->IsInTab() )
+ {
+ const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
+ if ( pSectFrm->IsAnLower( pTableFrm ) )
+ {
+ pFrm = pTableFrm;
+ }
+ }
+ }
+
+ SwBorderAttrAccess* pAttrAccess = 0L;
+ if ( !_pAttrs || pFrm != &rThis )
+ {
+ pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
+ _pAttrs = pAttrAccess->Get();
+ }
+
+ nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
+
+ delete pAttrAccess;
+ }
+
+ return nAdditionalLowerSpace;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::CheckMoveFwd()
+|*
+|* Beschreibung Moved den Frm vorwaerts wenn es durch die aktuellen
+|* Bedingungen und Attribute notwendig erscheint.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool )
+{
+ const SwFrm* pNxt = rThis.GetIndNext();
+
+ if ( bKeep && //!bMovedBwd &&
+ ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
+ ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
+ {
+ if( pNxt->IsSctFrm() )
+ { // Nicht auf leere SectionFrms hereinfallen
+ const SwFrm* pTmp = NULL;
+ while( pNxt && pNxt->IsSctFrm() &&
+ ( !((SwSectionFrm*)pNxt)->GetSection() ||
+ 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
+ {
+ pNxt = pNxt->FindNext();
+ pTmp = NULL;
+ }
+ if( pTmp )
+ pNxt = pTmp; // the content of the next notempty sectionfrm
+ }
+ if( pNxt && pNxt->GetValidPosFlag() )
+ {
+ sal_Bool bMove = sal_False;
+ const SwSectionFrm *pSct = rThis.FindSctFrm();
+ if( pSct && !pSct->GetValidSizeFlag() )
+ {
+ const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
+ if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
+ bMove = sal_True;
+ }
+ else
+ bMove = sal_True;
+ if( bMove )
+ {
+ //Keep together with the following frame
+ MoveFwd( rbMakePage, sal_False );
+ return sal_True;
+ }
+ }
+ }
+
+ sal_Bool bMovedFwd = sal_False;
+
+ if ( rThis.GetIndPrev() )
+ {
+ if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
+ {
+ bMovedFwd = sal_True;
+ if ( !MoveFwd( rbMakePage, sal_False ) )
+ rbMakePage = sal_False;
+ }
+ else
+ {
+ if ( IsPageBreak( sal_False ) )
+ {
+ while ( MoveFwd( rbMakePage, sal_True ) )
+ /* do nothing */;
+ rbMakePage = sal_False;
+ bMovedFwd = sal_True;
+ }
+ else if ( IsColBreak ( sal_False ) )
+ {
+ const SwPageFrm *pPage = rThis.FindPageFrm();
+ SwFrm *pCol = rThis.FindColFrm();
+ do
+ { MoveFwd( rbMakePage, sal_False );
+ SwFrm *pTmp = rThis.FindColFrm();
+ if( pTmp != pCol )
+ {
+ bMovedFwd = sal_True;
+ pCol = pTmp;
+ }
+ else
+ break;
+ } while ( IsColBreak( sal_False ) );
+ if ( pPage != rThis.FindPageFrm() )
+ rbMakePage = sal_False;
+ }
+ }
+ }
+ return bMovedFwd;
+}
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::MoveFwd()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm die Seite gewechselt hat.
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
+{
+//!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
+ SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
+ if ( rThis.IsInFtn() )
+ return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
+
+ if( !IsFwdMoveAllowed() && !bMoveAlways )
+ {
+ sal_Bool bNoFwd = sal_True;
+ if( rThis.IsInSct() )
+ {
+ SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
+ bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
+ !pBoss->GetPrev() );
+ }
+
+ // Allow the MoveFwd even if we do not have an IndPrev in these cases:
+ if ( rThis.IsInTab() &&
+ ( !rThis.IsTabFrm() ||
+ ( rThis.GetUpper()->IsInTab() &&
+ rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
+ 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
+ {
+ bNoFwd = sal_False;
+ }
+
+ if( bNoFwd )
+ {
+ //Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
+ //bereits der erste der Seite ist.
+ if ( !bPageBreak )
+ return sal_False;
+
+ const SwFrm *pCol = rThis.FindColFrm();
+ if ( !pCol || !pCol->GetPrev() )
+ return sal_False;
+ }
+ }
+
+ sal_Bool bSamePage = sal_True;
+ SwLayoutFrm *pNewUpper =
+ rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
+
+ if ( pNewUpper )
+ {
+ PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
+ SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
+ //Wir moven uns und alle direkten Nachfolger vor den ersten
+ //CntntFrm unterhalb des neuen Uppers.
+
+ // Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
+ // verhindern, dass sich dieser im Calc selbst zerstoert
+ SwSectionFrm* pSect = pNewUpper->FindSctFrm();
+ sal_Bool bUnlock = sal_False;
+ if( pSect )
+ {
+ // Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
+ // rufen wir lieber kein Calc, sonst wird noch der SectionFrm
+ // formatiert, der wiederum uns ruft etc.
+ if( pSect != rThis.FindSctFrm() )
+ {
+ bUnlock = !pSect->IsColLocked();
+ pSect->ColLock();
+ pNewUpper->Calc();
+ if( bUnlock )
+ pSect->ColUnlock();
+ }
+ }
+ // Do not calculate split cell frames.
+ else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
+ pNewUpper->Calc();
+
+ SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
+ sal_Bool bBossChg = pNewBoss != pOldBoss;
+ pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
+ pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
+ SwPageFrm* pNewPage = pOldPage;
+
+ // First, we move the footnotes.
+ sal_Bool bFtnMoved = sal_False;
+
+ // --> FME 2004-07-15 #i26831#
+ // If pSect has just been created, the printing area of pSect has
+ // been calculated based on the first content of its follow.
+ // In this case we prefer to call a SimpleFormat for this new
+ // section after we inserted the contents. Otherwise the section
+ // frame will invalidate its lowers, if its printing area changes
+ // in SwSectionFrm::Format, which can cause loops.
+ const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
+ !pSect->ContainsAny();
+ // <--
+
+ if ( pNewBoss != pOldBoss )
+ {
+ pNewPage = pNewBoss->FindPageFrm();
+ bSamePage = pNewPage == pOldPage;
+ //Damit die Fussnoten nicht auf dumme Gedanken kommen
+ //setzen wir hier die Deadline.
+ SWRECTFN( pOldBoss )
+ SwSaveFtnHeight aHeight( pOldBoss,
+ (pOldBoss->Frm().*fnRect->fnGetBottom)() );
+ SwCntntFrm* pStart = rThis.IsCntntFrm() ?
+ (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
+ OSL_ENSURE( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
+ "MoveFwd: Missing Content" );
+ SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
+ (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
+ if( pBody )
+ bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
+ sal_False);
+ }
+ // Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
+ // bewegt wurden, z. B. in den pNewUpper.
+ // MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
+ if( pNewUpper != rThis.GetUpper() )
+ {
+ // --> FME 2004-04-19 #i27145#
+ SwSectionFrm* pOldSct = 0;
+ if ( rThis.GetUpper()->IsSctFrm() )
+ {
+ pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
+ }
+ // <--
+
+ MoveSubTree( pNewUpper, pNewUpper->Lower() );
+
+ // --> FME 2004-04-19 #i27145#
+ if ( pOldSct && pOldSct->GetSection() )
+ {
+ // Prevent loops by setting the new height at
+ // the section frame if footnotes have been moved.
+ // Otherwise the call of SwLayNotify::~SwLayNotify() for
+ // the (invalid) section frame will invalidate the first
+ // lower of its follow, because it grows due to the removed
+ // footnotes.
+ // Note: If pOldSct has become empty during MoveSubTree, it
+ // has already been scheduled for removal. No SimpleFormat
+ // for these.
+ pOldSct->SimpleFormat();
+ }
+ // <--
+
+ // --> FME 2004-07-15 #i26831#
+ if ( bForceSimpleFormat )
+ {
+ pSect->SimpleFormat();
+ }
+ // <--
+
+ if ( bFtnMoved && !bSamePage )
+ {
+ pOldPage->UpdateFtnNum();
+ pNewPage->UpdateFtnNum();
+ }
+
+ if( bBossChg )
+ {
+ rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
+ if( !bSamePage )
+ {
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher erledigt!
+
+ pNewPage->InvalidateSpelling();
+ pNewPage->InvalidateSmartTags(); // SMARTTAGS
+ pNewPage->InvalidateAutoCompleteWords();
+ pNewPage->InvalidateWordCount();
+ }
+ }
+ }
+ // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
+ const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+
+ if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ {
+ // --> OD 2009-12-31 #i106452#
+ // check page description not only in situation with sections.
+ if ( !bSamePage &&
+ ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
+ pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
+ {
+ SwFrm::CheckPageDescs( pNewPage, sal_False );
+ }
+ // <--
+ }
+ }
+ return bSamePage;
+}
+
+
+/*************************************************************************
+|*
+|* sal_Bool SwFlowFrm::MoveBwd()
+|*
+|* Beschreibung Returnwert sagt, ob der Frm die Seite wechseln soll.
+|* Sollte von abgeleiteten Klassen gerufen werden.
+|* Das moven selbst muessen die abgeleiteten uebernehmen.
+|*
+|*************************************************************************/
+
+sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
+{
+ SwFlowFrm::SetMoveBwdJump( sal_False );
+
+ SwFtnFrm* pFtn = rThis.FindFtnFrm();
+ if ( pFtn && pFtn->IsBackMoveLocked() )
+ return sal_False;
+
+ // --> OD 2004-11-29 #115759# - text frames, which are directly inside
+ // tables aren't allowed to move backward.
+ if ( rThis.IsTxtFrm() && rThis.IsInTab() )
+ {
+ const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
+ while ( pUpperFrm )
+ {
+ if ( pUpperFrm->IsTabFrm() )
+ {
+ return sal_False;
+ }
+ else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
+ {
+ break;
+ }
+ pUpperFrm = pUpperFrm->GetUpper();
+ }
+ }
+ // <--
+
+ SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
+ SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
+ SwLayoutFrm *pNewUpper = 0;
+ sal_Bool bCheckPageDescs = sal_False;
+ bool bCheckPageDescOfNextPage = false;
+
+ if ( pFtn )
+ {
+ //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
+ //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
+ //Fussnoten nicht geprueft zu werden.
+
+ // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
+ // have to have a result != 0
+ SwFrm* pRef = 0;
+ const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
+ if( bEndnote && pFtn->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFtn->FindSctFrm();
+ if( pSect->IsEndnAtEnd() )
+ pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
+ }
+ if( !pRef )
+ pRef = pFtn->GetRef();
+ // <--
+
+ OSL_ENSURE( pRef, "MoveBwd: Endnote for an empty section?" );
+
+ if( !bEndnote )
+ pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
+ SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
+ if ( pOldBoss != pRefBoss &&
+ // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
+ ( !bEndnote ||
+ pRefBoss->IsBefore( pOldBoss ) )
+ )
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
+ }
+ else if ( IsPageBreak( sal_True ) ) //PageBreak zu beachten?
+ {
+ //Wenn auf der vorhergehenden Seite kein Frm im Body steht,
+ //so ist das Zurueckfliessen trotz Pagebreak sinnvoll
+ //(sonst: leere Seite).
+ //Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
+ const SwFrm *pFlow = &rThis;
+ do
+ {
+ pFlow = pFlow->FindPrev();
+ } while ( pFlow &&
+ ( pFlow->FindPageFrm() == pOldPage ||
+ !pFlow->IsInDocBody() ) );
+ if ( pFlow )
+ {
+ long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
+ if ( nDiff > 1 )
+ {
+ if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
+ nDiff -= 1;
+ if ( nDiff > 1 )
+ {
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ // --> OD 2006-05-08 #i53139#
+ // Now <pNewUpper> is a previous layout frame, which contains
+ // content. But the new upper layout frame has to be the next one.
+ // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
+ // --> OD 2006-05-17 #136024# - correct fix for i53139:
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-06-08 #136538# - another correction of fix for i53139
+ // Assumption, that in all cases <pNewUpper> is a previous
+ // layout frame, which contains content, is wrong.
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ // --> OD 2007-01-10 #i73194# - and yet another correction
+ // of fix for i53139:
+ // Assure that the new next upper layout frame doesn't
+ // equal the current one.
+ // E.g.: content is on page 3, on page 2 is only a 'ghost'
+ // section and on page 1 is normal content. Method <FindPrev(..)>
+ // will find the last content of page 1, but <GetLeaf(..)>
+ // returns new upper on page 2.
+ if ( pNewUpper->Lower() )
+ {
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper != rThis.GetUpper() &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ bCheckPageDescOfNextPage = true;
+ }
+ }
+ // <--
+
+ bCheckPageDescs = sal_True;
+ }
+ }
+ }
+ }
+ else if ( IsColBreak( sal_True ) )
+ {
+ //Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
+ //das Zurueckfliessen trotz ColumnBreak sinnvoll
+ //(sonst: leere Spalte).
+ if( rThis.IsInSct() )
+ {
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
+ ( pNewUpper->ContainsCntnt() ||
+ ( ( !pNewUpper->IsColBodyFrm() ||
+ !pNewUpper->GetUpper()->GetPrev() ) &&
+ !pNewUpper->FindSctFrm()->GetPrev() ) ) )
+ {
+ pNewUpper = 0;
+ }
+ // --> OD 2006-05-08 #i53139#
+ // --> OD 2006-09-11 #i69409# - check <pNewUpper>
+ // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
+ else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
+ // <--
+ {
+ // Now <pNewUpper> is a previous layout frame, which
+ // contains content. But the new upper layout frame
+ // has to be the next one.
+ // --> OD 2006-05-17 #136024# - correct fix for i53139
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ }
+ }
+ // <--
+ }
+ else
+ {
+ const SwFrm *pCol = rThis.FindColFrm();
+ sal_Bool bGoOn = sal_True;
+ sal_Bool bJump = sal_False;
+ do
+ {
+ if ( pCol->GetPrev() )
+ pCol = pCol->GetPrev();
+ else
+ {
+ bGoOn = sal_False;
+ pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+ }
+ if ( pCol )
+ {
+ // ColumnFrms jetzt mit BodyFrm
+ SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
+ (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
+ (SwLayoutFrm*)pCol;
+ if ( pColBody->ContainsCntnt() )
+ {
+ bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese
+ // nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
+ if( SwFlowFrm::IsMoveBwdJump() )
+ {
+ pNewUpper = pColBody;
+ // --> OD 2006-05-08 #i53139#
+ // Now <pNewUpper> is a previous layout frame, which
+ // contains content. But the new upper layout frame
+ // has to be the next one.
+ // --> OD 2006-05-17 #136024# - correct fix for i53139
+ // Check for wrong page description before using next new upper.
+ // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
+ // Check for correct type of new next upper layout frame
+ // --> OD 2006-07-05 #136538# - another correction of fix for i53139
+ // Beside type check, check also, if proposed new next upper
+ // frame is inside the same frame types.
+ // --> OD 2006-11-02 #i71065#
+ // Check that the proposed new next upper layout
+ // frame isn't the current one.
+ SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
+ if ( pNewNextUpper &&
+ pNewNextUpper != rThis.GetUpper() &&
+ pNewNextUpper->GetType() == pNewUpper->GetType() &&
+ pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
+ pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
+ pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
+ pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
+ !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
+ {
+ pNewUpper = pNewNextUpper;
+ }
+ // <--
+ }
+ }
+ else
+ {
+ if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
+ bJump = sal_True; // also eine uebersprungen
+ pNewUpper = pColBody; // Diese leere Spalte kommt in Frage,
+ // trotzdem weitersuchen
+ }
+ }
+ } while( bGoOn );
+ if( bJump )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ }
+ else //Keine Breaks also kann ich zurueckfliessen
+ pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
+
+ // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
+ // if - due to its object positioning - it isn't allowed to be on the new page frame
+ // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
+ // If one of its objects has restarted the layout process, moving backward
+ // isn't sensible either.
+ // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
+ // - allow move backward as long as the anchored object is only temporarily
+ // positions considering its wrapping style.
+ if ( pNewUpper &&
+ rThis.IsTxtFrm() && !IsFollow() )
+ {
+ sal_uInt32 nToPageNum( 0L );
+ const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
+ *(pOldPage->GetFmt()->GetDoc()),
+ static_cast<SwTxtFrm&>(rThis),
+ nToPageNum );
+ if ( bMoveFwdByObjPos &&
+ pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
+ {
+ pNewUpper = 0;
+ }
+ // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
+ // has restarted the layout process.
+ else if ( rThis.GetDrawObjs() )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
+ // --> OD 2005-04-19 #i47697# - refine condition - see above
+ if ( pAnchoredObj->RestartLayoutProcess() &&
+ !pAnchoredObj->IsTmpConsiderWrapInfluence() )
+ // <--
+ {
+ pNewUpper = 0;
+ break;
+ }
+ }
+ }
+ // <--
+ }
+ // <--
+
+ //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
+ //neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
+ //(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
+ if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
+ {
+ // --> OD 2007-09-05 #i79774#, #b6596954#
+ // neglect empty sections in proposed new upper frame
+ bool bProposedNewUpperContainsOnlyEmptySections( true );
+ {
+ const SwFrm* pLower( pNewUpper->Lower() );
+ while ( pLower )
+ {
+ if ( pLower->IsSctFrm() &&
+ !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
+ {
+ pLower = pLower->GetNext();
+ continue;
+ }
+ else
+ {
+ bProposedNewUpperContainsOnlyEmptySections = false;
+ break;
+ }
+ }
+ }
+ if ( !bProposedNewUpperContainsOnlyEmptySections )
+ {
+ if ( SwFlowFrm::IsMoveBwdJump() )
+ {
+ //Nicht hinter den Master sondern in das naechstfolgende leere
+ //Blatt moven.
+ SwFrm *pFrm = pNewUpper->Lower();
+ while ( pFrm->GetNext() )
+ pFrm = pFrm->GetNext();
+ pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
+ if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
+ pNewUpper = NULL; //dann eruebrigt sich das Moven
+ }
+ else
+ pNewUpper = 0;
+ }
+ // <--
+ }
+ if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
+ {
+ if( !pNewUpper->Lower() )
+ {
+ if( pNewUpper->IsFtnContFrm() )
+ {
+ pNewUpper->Cut();
+ delete pNewUpper;
+ }
+ else
+ {
+ SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( pSectFrm && !pSectFrm->IsColLocked() &&
+ !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
+ // <--
+ {
+ pSectFrm->DelEmpty( sal_True );
+ delete pSectFrm;
+ rThis.bValidPos = sal_True;
+ }
+ }
+ }
+ pNewUpper = 0;
+ }
+
+ // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
+ // keep with next frame and next frame is locked.
+ // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
+ // if it's locked.
+ if ( pNewUpper && !IsFollow() &&
+ rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
+ {
+ SwFrm* pIndNext = rThis.GetIndNext();
+ // --> OD 2004-12-08 #i38232#
+ if ( !pIndNext->IsTabFrm() )
+ {
+ // get first content of section, while empty sections are skipped
+ while ( pIndNext && pIndNext->IsSctFrm() )
+ {
+ if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
+ {
+ SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
+ if ( pTmp )
+ {
+ pIndNext = pTmp;
+ break;
+ }
+ }
+ pIndNext = pIndNext->GetIndNext();
+ }
+ OSL_ENSURE( !pIndNext || pIndNext->ISA(SwTxtFrm),
+ "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
+ if ( pIndNext && pIndNext->IsFlowFrm() &&
+ SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
+ {
+ pNewUpper = 0L;
+ }
+ }
+ // <--
+ }
+
+ // --> OD 2006-05-10 #i65250#
+ // layout loop control for flowing content again and again moving
+ // backward under the same layout condition.
+ if ( pNewUpper && !IsFollow() &&
+ pNewUpper != rThis.GetUpper() &&
+ SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
+ *this, *pNewUpper ) )
+ {
+ SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
+ ( !rThis.IsSctFrm() && rThis.IsInSct() )
+ ? MAKEPAGE_NOSECTION
+ : MAKEPAGE_NONE,
+ sal_True );
+ // --> OD 2007-01-10 #i73194# - make code robust
+ OSL_ENSURE( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
+ if ( pNextNewUpper &&
+ ( pNextNewUpper == rThis.GetUpper() ||
+ pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
+ // <--
+ {
+ pNewUpper = 0L;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
+#endif
+ }
+ }
+ // <--
+
+ OSL_ENSURE( pNewUpper != rThis.GetUpper(),
+ "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
+ if ( pNewUpper )
+ {
+ PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
+ if ( pNewUpper->IsFtnContFrm() )
+ {
+ //Kann sein, dass ich einen Container bekam.
+ SwFtnFrm *pOld = rThis.FindFtnFrm();
+ SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
+ pOld->GetRef(), pOld->GetAttr() );
+ if ( pOld->GetMaster() )
+ {
+ pNew->SetMaster( pOld->GetMaster() );
+ pOld->GetMaster()->SetFollow( pNew );
+ }
+ pNew->SetFollow( pOld );
+ pOld->SetMaster( pNew );
+ pNew->Paste( pNewUpper );
+ pNewUpper = pNew;
+ }
+ if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
+ {
+ SwSectionFrm* pSct = rThis.FindSctFrm();
+ //Wenn wir in einem Bereich in einer Fussnote stecken, muss im
+ //neuen Upper ggf. ein SwSectionFrm angelegt werden
+ if( pSct->IsInFtn() )
+ {
+ SwFrm* pTmp = pNewUpper->Lower();
+ if( pTmp )
+ {
+ while( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ if( !pTmp->IsSctFrm() ||
+ ((SwSectionFrm*)pTmp)->GetFollow() != pSct )
+ pTmp = NULL;
+ }
+ if( pTmp )
+ pNewUpper = (SwSectionFrm*)pTmp;
+ else
+ {
+ pSct = new SwSectionFrm( *pSct, sal_True );
+ pSct->Paste( pNewUpper );
+ pSct->Init();
+ pNewUpper = pSct;
+ pSct->SimpleFormat();
+ }
+ }
+ }
+ sal_Bool bUnlock = sal_False;
+ sal_Bool bFollow = sal_False;
+ //Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
+ //von zweiter in die erste Spalte zerstoert werden.
+ SwSectionFrm* pSect = pNewUpper->FindSctFrm();
+ if( pSect )
+ {
+ bUnlock = !pSect->IsColLocked();
+ pSect->ColLock();
+ bFollow = pSect->HasFollow();
+ }
+ pNewUpper->Calc();
+ rThis.Cut();
+ // --> OD 2005-02-23 #b6229852#
+ // optimization: format section, if its size is invalidated and if it's
+ // the new parent of moved backward frame.
+ bool bFormatSect( false );
+ // <--
+ if( bUnlock )
+ {
+ pSect->ColUnlock();
+ if( pSect->HasFollow() != bFollow )
+ {
+ pSect->InvalidateSize();
+ // --> OD 2005-02-23 #b6229852# - optimization
+ if ( pSect == pNewUpper )
+ bFormatSect = true;
+ // <--
+ }
+ }
+
+ rThis.Paste( pNewUpper );
+ // --> OD 2005-02-23 #b6229852# - optimization
+ if ( bFormatSect )
+ pSect->Calc();
+ // <--
+
+ SwPageFrm *pNewPage = rThis.FindPageFrm();
+ if( pNewPage != pOldPage )
+ {
+ rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
+ ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
+ if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
+ pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher eledigt!
+
+ pNewPage->InvalidateSpelling();
+ pNewPage->InvalidateSmartTags(); // SMARTTAGS
+ pNewPage->InvalidateAutoCompleteWords();
+ pNewPage->InvalidateWordCount();
+
+ // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
+ if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
+ {
+ if ( bCheckPageDescs && pNewPage->GetNext() )
+ {
+ SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
+ pNewPage :
+ (SwPageFrm*)pNewPage->GetNext();
+ SwFrm::CheckPageDescs( pStartPage, sal_False);
+ }
+ else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
+ {
+ //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
+ SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
+ }
+ }
+ }
+ }
+ return pNewUpper != 0;
+}
+
+/*************************************************************************
+|*
+|* SwFlowFrm::CastFlowFrm
+|*
+|*************************************************************************/
+
+SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
+{
+ if ( pFrm->IsCntntFrm() )
+ return (SwCntntFrm*)pFrm;
+ if ( pFrm->IsTabFrm() )
+ return (SwTabFrm*)pFrm;
+ if ( pFrm->IsSctFrm() )
+ return (SwSectionFrm*)pFrm;
+ return 0;
+}
+
+const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
+{
+ if ( pFrm->IsCntntFrm() )
+ return (SwCntntFrm*)pFrm;
+ if ( pFrm->IsTabFrm() )
+ return (SwTabFrm*)pFrm;
+ if ( pFrm->IsSctFrm() )
+ return (SwSectionFrm*)pFrm;
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
new file mode 100644
index 000000000000..5b265942d561
--- /dev/null
+++ b/sw/source/core/layout/fly.cxx
@@ -0,0 +1,2882 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "hintids.hxx"
+#include <svl/itemiter.hxx>
+#include <svtools/imap.hxx>
+#include <vcl/graph.hxx>
+#include <tools/poly.hxx>
+#include <svx/contdlg.hxx>
+#include <editeng/protitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/keepitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtclds.hxx>
+#include <fmtcntnt.hxx>
+#include <fmturl.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtcnct.hxx>
+#include <layhelp.hxx>
+#include <ndtxt.hxx>
+#include <svx/svdogrp.hxx>
+#include <ndgrf.hxx>
+#include <tolayoutanchoredobjectposition.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <anchoredobject.hxx>
+#include <ndole.hxx>
+#include <swtable.hxx>
+#include <svx/svdpage.hxx>
+#include "doc.hxx"
+#include "viewsh.hxx"
+#include "layouter.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "pam.hxx"
+#include "frmatr.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "dcontact.hxx"
+#include "dflyobj.hxx"
+#include "dview.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include "swregion.hxx"
+#include "tabfrm.hxx"
+#include "txtfrm.hxx"
+#include "ndnotxt.hxx"
+#include "notxtfrm.hxx" // GetGrfArea
+#include "flyfrms.hxx"
+#include "ndindex.hxx" // GetGrfArea
+#include "sectfrm.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/salbtype.hxx> // FRound
+#include "switerator.hxx"
+
+using namespace ::com::sun::star;
+
+
+// OD 2004-03-23 #i26791
+TYPEINIT2(SwFlyFrm,SwLayoutFrm,SwAnchoredObject);
+
+/*************************************************************************
+|*
+|* SwFlyFrm::SwFlyFrm()
+|*
+|*************************************************************************/
+
+SwFlyFrm::SwFlyFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwLayoutFrm( pFmt, pSib ),
+ // OD 2004-03-22 #i26791#
+ SwAnchoredObject(),
+ // OD 2004-05-27 #i26791# - moved to <SwAnchoredObject>
+// aRelPos(),
+ pPrevLink( 0 ),
+ pNextLink( 0 ),
+ bInCnt( sal_False ),
+ bAtCnt( sal_False ),
+ bLayout( sal_False ),
+ bAutoPosition( sal_False ),
+ bNoShrink( sal_False ),
+ bLockDeleteContent( sal_False )
+{
+ nType = FRMC_FLY;
+
+ bInvalid = bNotifyBack = sal_True;
+ bLocked = bMinHeight =
+ bHeightClipped = bWidthClipped = bFormatHeightOnly = sal_False;
+
+ //Grosseneinstellung, Fixe groesse ist immer die Breite
+ const SwFmtFrmSize &rFrmSize = pFmt->GetFrmSize();
+ sal_Bool bVert = sal_False;
+ sal_uInt16 nDir =
+ ((SvxFrameDirectionItem&)pFmt->GetFmtAttr( RES_FRAMEDIR )).GetValue();
+ if( FRMDIR_ENVIRONMENT == nDir )
+ {
+ bDerivedVert = 1;
+ bDerivedR2L = 1;
+ if( pAnch && pAnch->IsVertical() )
+ bVert = sal_True;
+ }
+ else
+ {
+ bInvalidVert = 0;
+ bDerivedVert = 0;
+ bDerivedR2L = 0;
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( FRMDIR_VERT_TOP_LEFT == nDir )
+ bVertLR = 1;
+ else
+ bVertLR = 0;
+ }
+ }
+
+ bVert = bVertical;
+ bInvalidR2L = 0;
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ }
+
+ Frm().Width( rFrmSize.GetWidth() );
+ Frm().Height( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrmSize.GetHeight() );
+
+ //Hoehe Fix oder Variabel oder was?
+ if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ bMinHeight = sal_True;
+ else if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ bFixSize = sal_True;
+
+ // OD 2004-02-12 #110582#-2 - insert columns, if necessary
+ InsertColumns();
+
+ //Erst das Init, dann den Inhalt, denn zum Inhalt koennen widerum
+ //Objekte/Rahmen gehoeren die dann angemeldet werden.
+ InitDrawObj( sal_False );
+
+ // OD 2004-01-19 #110582#
+ Chain( pAnch );
+
+ // OD 2004-01-19 #110582#
+ InsertCnt();
+
+ //Und erstmal in den Wald stellen die Kiste, damit bei neuen Dokument nicht
+ //unnoetig viel formatiert wird.
+ Frm().Pos().X() = Frm().Pos().Y() = WEIT_WECH;
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::Chain( SwFrm* _pAnch )
+{
+ // Connect to chain neighboors.
+ // No problem, if a neighboor doesn't exist - the construction of the
+ // neighboor will make the connection
+ const SwFmtChain& rChain = GetFmt()->GetChain();
+ if ( rChain.GetPrev() || rChain.GetNext() )
+ {
+ if ( rChain.GetNext() )
+ {
+ SwFlyFrm* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
+ if ( pFollow )
+ {
+ OSL_ENSURE( !pFollow->GetPrevLink(), "wrong chain detected" );
+ if ( !pFollow->GetPrevLink() )
+ SwFlyFrm::ChainFrames( this, pFollow );
+ }
+ }
+ if ( rChain.GetPrev() )
+ {
+ SwFlyFrm *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
+ if ( pMaster )
+ {
+ OSL_ENSURE( !pMaster->GetNextLink(), "wrong chain detected" );
+ if ( !pMaster->GetNextLink() )
+ SwFlyFrm::ChainFrames( pMaster, this );
+ }
+ }
+ }
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::InsertCnt()
+{
+ if ( !GetPrevLink() )
+ {
+ const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), ":-( no content prepared." );
+ sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
+ // Lower() bedeutet SwColumnFrm, eingefuegt werden muss der Inhalt dann in den (Column)BodyFrm
+ ::_InsertCnt( Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower() : (SwLayoutFrm*)this,
+ GetFmt()->GetDoc(), nIndex );
+
+ //NoTxt haben immer eine FixHeight.
+ if ( Lower() && Lower()->IsNoTxtFrm() )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ }
+}
+
+ // OD 2004-02-12 #110582#-2
+ void SwFlyFrm::InsertColumns()
+ {
+ // --> OD 2009-08-12 #i97379#
+ // Check, if column are allowed.
+ // Columns are not allowed for fly frames, which represent graphics or embedded objects.
+ const SwFmtCntnt& rCntnt = GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "<SwFlyFrm::InsertColumns()> - no content prepared." );
+ SwNodeIndex aFirstCntnt( *(rCntnt.GetCntntIdx()), 1 );
+ if ( aFirstCntnt.GetNode().IsNoTxtNode() )
+ {
+ return;
+ }
+ // <--
+
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ if ( rCol.GetNumCols() > 1 )
+ {
+ //PrtArea ersteinmal so gross wie der Frm, damit die Spalten
+ //vernuenftig eingesetzt werden koennen; das schaukelt sich dann
+ //schon zurecht.
+ Prt().Width( Frm().Width() );
+ Prt().Height( Frm().Height() );
+ const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass auch ein
+ //Old-Wert hereingereicht wird.
+ ChgColumns( aOld, rCol );
+ }
+ }
+
+/*************************************************************************
+|*
+|* SwFlyFrm::~SwFlyFrm()
+|*
+|*************************************************************************/
+
+SwFlyFrm::~SwFlyFrm()
+{
+ // Accessible objects for fly frames will be destroyed in this destructor.
+ // For frames bound as char or frames that don't have an anchor we have
+ // to do that ourselves. For any other frame the call RemoveFly at the
+ // anchor will do that.
+ if( IsAccessibleFrm() && GetFmt() && (IsFlyInCntFrm() || !GetAnchorFrm()) )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ // Lowers aren't disposed already, so we have to do a recursive
+ // dispose
+ pVSh->Imp()->DisposeAccessibleFrm( this, sal_True );
+ }
+ }
+ }
+
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ // OD 2004-01-19 #110582#
+ Unchain();
+
+ // OD 2004-01-19 #110582#
+ DeleteCnt();
+
+ //Tschuess sagen.
+ if ( GetAnchorFrm() )
+ AnchorFrm()->RemoveFly( this );
+ }
+
+ FinitDrawObj();
+}
+
+const IDocumentDrawModelAccess* SwFlyFrm::getIDocumentDrawModelAccess()
+{
+ return GetFmt()->getIDocumentDrawModelAccess();
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::Unchain()
+{
+ if ( GetPrevLink() )
+ UnchainFrames( GetPrevLink(), this );
+ if ( GetNextLink() )
+ UnchainFrames( this, GetNextLink() );
+}
+
+// OD 2004-01-19 #110582#
+void SwFlyFrm::DeleteCnt()
+{
+ // #110582#-2
+ if ( IsLockDeleteContent() )
+ return;
+
+ SwFrm* pFrm = pLower;
+ while ( pFrm )
+ {
+ while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
+ {
+ SwAnchoredObject *pAnchoredObj = (*pFrm->GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
+ SdrObject* pObj = pAnchoredObj->DrawObj();
+ if ( pObj->ISA(SwDrawVirtObj) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ }
+ else
+ {
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(::GetUserCall( pObj ));
+ if ( pContact )
+ {
+ pContact->DisconnectFromLayout();
+ }
+ }
+ }
+ }
+
+ pFrm->Remove();
+ delete pFrm;
+ pFrm = pLower;
+ }
+
+ InvalidatePage();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::InitDrawObj()
+|*
+|*************************************************************************/
+
+sal_uInt32 SwFlyFrm::_GetOrdNumForNewRef( const SwFlyDrawContact* pContact )
+{
+ sal_uInt32 nOrdNum( 0L );
+
+ // search for another Writer fly frame registered at same frame format
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pContact->GetFmt() );
+ const SwFlyFrm* pFlyFrm( 0L );
+ for ( pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
+ {
+ if ( pFlyFrm != this )
+ {
+ break;
+ }
+ }
+
+ if ( pFlyFrm )
+ {
+ // another Writer fly frame found. Take its order number
+ nOrdNum = pFlyFrm->GetVirtDrawObj()->GetOrdNum();
+ }
+ else
+ {
+ // no other Writer fly frame found. Take order number of 'master' object
+ // --> OD 2004-11-11 #i35748# - use method <GetOrdNumDirect()> instead
+ // of method <GetOrdNum()> to avoid a recalculation of the order number,
+ // which isn't intended.
+ nOrdNum = pContact->GetMaster()->GetOrdNumDirect();
+ // <--
+ }
+
+ return nOrdNum;
+}
+
+SwVirtFlyDrawObj* SwFlyFrm::CreateNewRef( SwFlyDrawContact *pContact )
+{
+ SwVirtFlyDrawObj *pDrawObj = new SwVirtFlyDrawObj( *pContact->GetMaster(), this );
+ pDrawObj->SetModel( pContact->GetMaster()->GetModel() );
+ pDrawObj->SetUserCall( pContact );
+
+ //Der Reader erzeugt die Master und setzt diese, um die Z-Order zu
+ //transportieren, in die Page ein. Beim erzeugen der ersten Referenz werden
+ //die Master aus der Liste entfernt und fuehren von da an ein
+ //Schattendasein.
+ SdrPage* pPg( 0L );
+ if ( 0 != ( pPg = pContact->GetMaster()->GetPage() ) )
+ {
+ const sal_uInt32 nOrdNum = pContact->GetMaster()->GetOrdNum();
+ pPg->ReplaceObject( pDrawObj, nOrdNum );
+ }
+ // --> OD 2004-08-16 #i27030# - insert new <SwVirtFlyDrawObj> instance
+ // into drawing page with correct order number
+ else
+ {
+ pContact->GetFmt()->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage( 0 )->
+ InsertObject( pDrawObj, _GetOrdNumForNewRef( pContact ) );
+ }
+ // <--
+ // --> OD 2004-12-13 #i38889# - assure, that new <SwVirtFlyDrawObj> instance
+ // is in a visible layer.
+ pContact->MoveObjToVisibleLayer( pDrawObj );
+ // <--
+ return pDrawObj;
+}
+
+
+
+void SwFlyFrm::InitDrawObj( sal_Bool bNotify )
+{
+ //ContactObject aus dem Format suchen. Wenn bereits eines existiert, so
+ //braucht nur eine neue Ref erzeugt werden, anderfalls ist es jetzt an
+ //der Zeit das Contact zu erzeugen.
+
+ IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ SwFlyDrawContact *pContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
+ if ( !pContact )
+ {
+ // --> OD 2005-08-08 #i52858# - method name changed
+ pContact = new SwFlyDrawContact( (SwFlyFrmFmt*)GetFmt(),
+ pIDDMA->GetOrCreateDrawModel() );
+ // <--
+ }
+ OSL_ENSURE( pContact, "InitDrawObj failed" );
+ // OD 2004-03-22 #i26791#
+ SetDrawObj( *(CreateNewRef( pContact )) );
+
+ //Den richtigen Layer setzen.
+ // OD 2004-01-19 #110582#
+ SdrLayerID nHeavenId = pIDDMA->GetHeavenId();
+ SdrLayerID nHellId = pIDDMA->GetHellId();
+ // OD 2004-03-22 #i26791#
+ GetVirtDrawObj()->SetLayer( GetFmt()->GetOpaque().GetValue()
+ ? nHeavenId
+ : nHellId );
+ if ( bNotify )
+ NotifyDrawObj();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FinitDrawObj()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::FinitDrawObj()
+{
+ if ( !GetVirtDrawObj() )
+ return;
+
+ //Bei den SdrPageViews abmelden falls das Objekt dort noch selektiert ist.
+ if ( !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ ViewShell *p1St = getRootFrm()->GetCurrShell();
+ if ( p1St )
+ {
+ ViewShell *pSh = p1St;
+ do
+ { //z.Zt. kann das Drawing nur ein Unmark auf alles, weil das
+ //Objekt bereits Removed wurde.
+ if( pSh->HasDrawView() )
+ pSh->Imp()->GetDrawView()->UnmarkAll();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != p1St );
+ }
+ }
+
+ //VirtObject mit in das Grab nehmen. Wenn das letzte VirObject
+ //zerstoert wird, mussen das DrawObject und DrawContact ebenfalls
+ //zerstoert werden.
+ SwFlyDrawContact *pMyContact = 0;
+ if ( GetFmt() )
+ {
+ bool bContinue = true;
+ SwIterator<SwFrm,SwFmt> aFrmIter( *GetFmt() );
+ for ( SwFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
+ if ( pFrm != this )
+ {
+ // don't delete Contact if there is still a Frm
+ bContinue = false;
+ break;
+ }
+
+ if ( bContinue )
+ // no Frm left, find Contact object to destroy
+ pMyContact = SwIterator<SwFlyDrawContact,SwFmt>::FirstElement( *GetFmt() );
+ }
+
+ // OD, OS 2004-03-31 #116203# - clear user call of Writer fly frame 'master'
+ // <SdrObject> to assure, that a <SwXFrame::dispose()> doesn't delete the
+ // Writer fly frame again.
+ if ( pMyContact )
+ {
+ pMyContact->GetMaster()->SetUserCall( 0 );
+ }
+ GetVirtDrawObj()->SetUserCall( 0 ); //Ruft sonst Delete des ContactObj
+ delete GetVirtDrawObj(); //Meldet sich selbst beim Master ab.
+ if ( pMyContact )
+ delete pMyContact; //zerstoert den Master selbst.
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChainFrames()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::ChainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
+{
+ OSL_ENSURE( pMaster && pFollow, "uncomplete chain" );
+ OSL_ENSURE( !pMaster->GetNextLink(), "link can not be changed" );
+ OSL_ENSURE( !pFollow->GetPrevLink(), "link can not be changed" );
+
+ pMaster->pNextLink = pFollow;
+ pFollow->pPrevLink = pMaster;
+
+ if ( pMaster->ContainsCntnt() )
+ {
+ //Damit ggf. ein Textfluss zustande kommt muss invalidiert werden.
+ SwFrm *pInva = pMaster->FindLastLower();
+ SWRECTFN( pMaster )
+ const long nBottom = (pMaster->*fnRect->fnGetPrtBottom)();
+ while ( pInva )
+ {
+ if( (pInva->Frm().*fnRect->fnBottomDist)( nBottom ) <= 0 )
+ {
+ pInva->InvalidateSize();
+ pInva->Prepare( PREP_CLEAR );
+ pInva = pInva->FindPrev();
+ }
+ else
+ pInva = 0;
+ }
+ }
+
+ if ( pFollow->ContainsCntnt() )
+ {
+ //Es gibt nur noch den Inhalt des Masters, der Inhalt vom Follow
+ //hat keine Frames mehr (sollte immer nur genau ein leerer TxtNode sein).
+ SwFrm *pFrm = pFollow->ContainsCntnt();
+ OSL_ENSURE( !pFrm->IsTabFrm() && !pFrm->FindNext(), "follow in chain contains content" );
+ pFrm->Cut();
+ delete pFrm;
+ }
+
+ // invalidate accessible relation set (accessibility wrapper)
+ ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = pMaster->getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
+ }
+}
+
+void SwFlyFrm::UnchainFrames( SwFlyFrm *pMaster, SwFlyFrm *pFollow )
+{
+ pMaster->pNextLink = 0;
+ pFollow->pPrevLink = 0;
+
+ if ( pFollow->ContainsCntnt() )
+ {
+ //Der Master saugt den Inhalt vom Follow auf
+ SwLayoutFrm *pUpper = pMaster;
+ if ( pUpper->Lower()->IsColumnFrm() )
+ {
+ pUpper = static_cast<SwLayoutFrm*>(pUpper->GetLastLower());
+ pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower()); // der (Column)BodyFrm
+ OSL_ENSURE( pUpper && pUpper->IsColBodyFrm(), "Missing ColumnBody" );
+ }
+ SwFlyFrm *pFoll = pFollow;
+ while ( pFoll )
+ {
+ SwFrm *pTmp = ::SaveCntnt( pFoll );
+ if ( pTmp )
+ ::RestoreCntnt( pTmp, pUpper, pMaster->FindLastLower(), true );
+ pFoll->SetCompletePaint();
+ pFoll->InvalidateSize();
+ pFoll = pFoll->GetNextLink();
+ }
+ }
+
+ //Der Follow muss mit seinem eigenen Inhalt versorgt werden.
+ const SwFmtCntnt &rCntnt = pFollow->GetFmt()->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), ":-( Kein Inhalt vorbereitet." );
+ sal_uLong nIndex = rCntnt.GetCntntIdx()->GetIndex();
+ // Lower() bedeutet SwColumnFrm, dieser beinhaltet wieder einen SwBodyFrm
+ ::_InsertCnt( pFollow->Lower() ? (SwLayoutFrm*)((SwLayoutFrm*)pFollow->Lower())->Lower()
+ : (SwLayoutFrm*)pFollow,
+ pFollow->GetFmt()->GetDoc(), ++nIndex );
+
+ // invalidate accessible relation set (accessibility wrapper)
+ ViewShell* pSh = pMaster->getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = pMaster->getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
+}
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FindChainNeighbour()
+|*
+|*************************************************************************/
+
+SwFlyFrm *SwFlyFrm::FindChainNeighbour( SwFrmFmt &rChain, SwFrm *pAnch )
+{
+ //Wir suchen denjenigen Fly, der in dem selben Bereich steht.
+ //Bereiche koennen zunaechst nur Kopf-/Fusszeilen oder Flys sein.
+
+ if ( !pAnch ) //Wenn ein Anchor uebergeben Wurde zaehlt dieser: Ctor!
+ pAnch = AnchorFrm();
+
+ SwLayoutFrm *pLay;
+ if ( pAnch->IsInFly() )
+ pLay = pAnch->FindFlyFrm();
+ else
+ {
+ //FindFooterOrHeader taugt hier nicht, weil evtl. noch keine Verbindung
+ //zum Anker besteht.
+ pLay = pAnch->GetUpper();
+ while ( pLay && !(pLay->GetType() & (FRM_HEADER|FRM_FOOTER)) )
+ pLay = pLay->GetUpper();
+ }
+
+ SwIterator<SwFlyFrm,SwFmt> aIter( rChain );
+ SwFlyFrm *pFly = aIter.First();
+ if ( pLay )
+ {
+ while ( pFly )
+ {
+ if ( pFly->GetAnchorFrm() )
+ {
+ if ( pFly->GetAnchorFrm()->IsInFly() )
+ {
+ if ( pFly->AnchorFrm()->FindFlyFrm() == pLay )
+ break;
+ }
+ else if ( pLay == pFly->FindFooterOrHeader() )
+ break;
+ }
+ pFly = aIter.Next();
+ }
+ }
+ else if ( pFly )
+ {
+ OSL_ENSURE( !aIter.Next(), "chain with more than one inkarnation" );
+ }
+ return pFly;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FindLastLower()
+|*
+|*************************************************************************/
+
+SwFrm *SwFlyFrm::FindLastLower()
+{
+ SwFrm *pRet = ContainsAny();
+ if ( pRet && pRet->IsInTab() )
+ pRet = pRet->FindTabFrm();
+ SwFrm *pNxt = pRet;
+ while ( pNxt && IsAnLower( pNxt ) )
+ { pRet = pNxt;
+ pNxt = pNxt->FindNext();
+ }
+ return pRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwFlyFrm::FrmSizeChg()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::FrmSizeChg( const SwFmtFrmSize &rFrmSize )
+{
+ sal_Bool bRet = sal_False;
+ SwTwips nDiffHeight = Frm().Height();
+ if ( rFrmSize.GetHeightSizeType() == ATT_VAR_SIZE )
+ bFixSize = bMinHeight = sal_False;
+ else
+ {
+ if ( rFrmSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ else if ( rFrmSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ {
+ bFixSize = sal_False;
+ bMinHeight = sal_True;
+ }
+ nDiffHeight -= rFrmSize.GetHeight();
+ }
+ //Wenn der Fly Spalten enthaehlt muessen der Fly und
+ //die Spalten schon einmal auf die Wunschwerte gebracht
+ //werden, sonst haben wir ein kleines Problem.
+ if ( Lower() )
+ {
+ if ( Lower()->IsColumnFrm() )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ const Size aOldSz( Prt().SSize() );
+ const SwTwips nDiffWidth = Frm().Width() - rFrmSize.GetWidth();
+ aFrm.Height( aFrm.Height() - nDiffHeight );
+ aFrm.Width ( aFrm.Width() - nDiffWidth );
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ aPrt.Height( aPrt.Height() - nDiffHeight );
+ aPrt.Width ( aPrt.Width() - nDiffWidth );
+ ChgLowersProp( aOldSz );
+ ::Notify( this, FindPageFrm(), aOld );
+ bValidPos = sal_False;
+ bRet = sal_True;
+ }
+ else if ( Lower()->IsNoTxtFrm() )
+ {
+ bFixSize = sal_True;
+ bMinHeight = sal_False;
+ }
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ _Invalidate();
+ if ( nInvFlags & 0x01 )
+ {
+ _InvalidatePos();
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ if ( nInvFlags & 0x02 )
+ {
+ _InvalidateSize();
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+ if ( nInvFlags & 0x04 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x08 )
+ SetNotifyBack();
+ if ( nInvFlags & 0x10 )
+ SetCompletePaint();
+ if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTxtFrm() )
+ ClrContourCache( GetVirtDrawObj() );
+ SwRootFrm *pRoot;
+ if ( nInvFlags & 0x20 && 0 != (pRoot = getRootFrm()) )
+ pRoot->InvalidateBrowseWidth();
+ // --> OD 2004-06-28 #i28701#
+ if ( nInvFlags & 0x80 )
+ {
+ // update sorted object lists, the Writer fly frame is registered at.
+ UpdateObjInSortedList();
+ }
+ // <--
+ }
+
+ // --> OD 2005-07-18 #i51474# - reset flags for the layout process
+ ResetLayoutProcessBools();
+ // <--
+}
+
+void SwFlyFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ switch( nWhich )
+ {
+ case RES_VERT_ORIENT:
+ case RES_HORI_ORIENT:
+ // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
+ case RES_FOLLOW_TEXT_FLOW:
+ {
+ //Achtung! _immer_ Aktion in ChgRePos() mitpflegen.
+ rInvFlags |= 0x09;
+ }
+ break;
+ // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ {
+ rInvFlags |= 0x89;
+ }
+ break;
+ case RES_SURROUND:
+ {
+ // OD 2004-05-13 #i28701# - invalidate position on change of
+ // wrapping style.
+ //rInvFlags |= 0x40;
+ rInvFlags |= 0x41;
+ //Der Hintergrund muss benachrichtigt und Invalidiert werden.
+ const SwRect aTmp( GetObjRectWithSpaces() );
+ NotifyBackground( FindPageFrm(), aTmp, PREP_FLY_ATTR_CHG );
+
+ // Durch eine Umlaufaenderung von rahmengebundenen Rahmen kann eine
+ // vertikale Ausrichtung aktiviert/deaktiviert werden => MakeFlyPos
+ if( FLY_AT_FLY == GetFmt()->GetAnchor().GetAnchorId() )
+ rInvFlags |= 0x09;
+
+ //Ggf. die Kontur am Node loeschen.
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ !GetFmt()->GetSurround().IsContour() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ if ( pNd->HasContour() )
+ pNd->SetContour( 0 );
+ }
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+ }
+ break;
+
+ case RES_PROTECT:
+ {
+ const SvxProtectItem *pP = (SvxProtectItem*)pNew;
+ GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected() );
+ GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+ break;
+ }
+
+ case RES_COL:
+ {
+ ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
+ if ( FrmSizeChg( rNew ) )
+ NotifyDrawObj();
+ rInvFlags |= 0x1A;
+ break;
+ }
+
+ case RES_FRM_SIZE:
+ case RES_FMT_CHG:
+ {
+ const SwFmtFrmSize &rNew = GetFmt()->GetFrmSize();
+ if ( FrmSizeChg( rNew ) )
+ NotifyDrawObj();
+ rInvFlags |= 0x7F;
+ if ( RES_FMT_CHG == nWhich )
+ {
+ SwRect aNew( GetObjRectWithSpaces() );
+ SwRect aOld( aFrm );
+ const SvxULSpaceItem &rUL = ((SwFmtChg*)pOld)->pChangedFmt->GetULSpace();
+ aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
+ aOld.SSize().Height()+= rUL.GetLower();
+ const SvxLRSpaceItem &rLR = ((SwFmtChg*)pOld)->pChangedFmt->GetLRSpace();
+ aOld.Left ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
+ aOld.SSize().Width() += rLR.GetRight();
+ aNew.Union( aOld );
+ NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );
+
+ //Dummer Fall. Bei der Zusweisung einer Vorlage k?nnen wir uns
+ //nicht auf das alte Spaltenattribut verlassen. Da diese
+ //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
+ //bleibt uns nur einen temporaeres Attribut zu basteln.
+ SwFmtCol aCol;
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ sal_uInt16 nCol = 0;
+ SwFrm *pTmp = Lower();
+ do
+ { ++nCol;
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ aCol.Init( nCol, 0, 1000 );
+ }
+ ChgColumns( aCol, GetFmt()->GetCol() );
+ }
+
+ SwFmtURL aURL( GetFmt()->GetURL() );
+ if ( aURL.GetMap() )
+ {
+ const SwFmtFrmSize &rOld = nWhich == RES_FRM_SIZE ?
+ *(SwFmtFrmSize*)pNew :
+ ((SwFmtChg*)pOld)->pChangedFmt->GetFrmSize();
+ //#35091# Kann beim Laden von Vorlagen mal 0 sein
+ if ( rOld.GetWidth() && rOld.GetHeight() )
+ {
+
+ Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
+ Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ SwFrmFmt *pFmt = GetFmt();
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aURL );
+ pFmt->UnlockModify();
+ }
+ }
+ const SvxProtectItem &rP = GetFmt()->GetProtect();
+ GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected() );
+ GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );
+
+ if ( pSh )
+ pSh->InvalidateWindows( Frm() );
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ const sal_uInt8 nId = GetFmt()->GetOpaque().GetValue() ?
+ pIDDMA->GetHeavenId() :
+ pIDDMA->GetHellId();
+ GetVirtDrawObj()->SetLayer( nId );
+
+ if ( Lower() )
+ {
+ //Ggf. die Kontur am Node loeschen.
+ if( Lower()->IsNoTxtFrm() &&
+ !GetFmt()->GetSurround().IsContour() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ if ( pNd->HasContour() )
+ pNd->SetContour( 0 );
+ }
+ else if( !Lower()->IsColumnFrm() )
+ {
+ SwFrm* pFrm = GetLastLower();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ }
+ }
+
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+
+ break;
+ }
+ case RES_UL_SPACE:
+ case RES_LR_SPACE:
+ {
+ rInvFlags |= 0x41;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ getRootFrm()->InvalidateBrowseWidth();
+ SwRect aNew( GetObjRectWithSpaces() );
+ SwRect aOld( aFrm );
+ if ( RES_UL_SPACE == nWhich )
+ {
+ const SvxULSpaceItem &rUL = *(SvxULSpaceItem*)pNew;
+ aOld.Top( Max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
+ aOld.SSize().Height()+= rUL.GetLower();
+ }
+ else
+ {
+ const SvxLRSpaceItem &rLR = *(SvxLRSpaceItem*)pNew;
+ aOld.Left ( Max( aOld.Left() - long(rLR.GetLeft()), 0L ) );
+ aOld.SSize().Width() += rLR.GetRight();
+ }
+ aNew.Union( aOld );
+ NotifyBackground( FindPageFrm(), aNew, PREP_CLEAR );
+ }
+ break;
+
+ case RES_BOX:
+ case RES_SHADOW:
+ rInvFlags |= 0x17;
+ break;
+
+ case RES_FRAMEDIR :
+ SetDerivedVert( sal_False );
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+
+ case RES_OPAQUE:
+ {
+ if ( pSh )
+ pSh->InvalidateWindows( Frm() );
+
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+ const sal_uInt8 nId = ((SvxOpaqueItem*)pNew)->GetValue() ?
+ pIDDMA->GetHeavenId() :
+ pIDDMA->GetHellId();
+ GetVirtDrawObj()->SetLayer( nId );
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ {
+ pSh->Imp()->DisposeAccessibleFrm( this );
+ pSh->Imp()->AddAccessibleFrm( this );
+ }
+ }
+ // --> OD 2004-06-28 #i28701# - perform reorder of object lists
+ // at anchor frame and at page frame.
+ rInvFlags |= 0x80;
+ }
+ break;
+
+ case RES_URL:
+ //Das Interface arbeitet bei Textrahmen auf der Rahmengroesse,
+ //die Map muss sich aber auf die FrmSize beziehen
+ if ( (!Lower() || !Lower()->IsNoTxtFrm()) &&
+ ((SwFmtURL*)pNew)->GetMap() && ((SwFmtURL*)pOld)->GetMap() )
+ {
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ if ( rSz.GetHeight() != Frm().Height() ||
+ rSz.GetWidth() != Frm().Width() )
+ {
+ SwFmtURL aURL( GetFmt()->GetURL() );
+ Fraction aScaleX( Frm().Width(), rSz.GetWidth() );
+ Fraction aScaleY( Frm().Height(), rSz.GetHeight() );
+ aURL.GetMap()->Scale( aScaleX, aScaleY );
+ SwFrmFmt *pFmt = GetFmt();
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aURL );
+ pFmt->UnlockModify();
+ }
+ }
+ /* Keine Invalidierung notwendig */
+ break;
+
+ case RES_CHAIN:
+ {
+ SwFmtChain *pChain = (SwFmtChain*)pNew;
+ if ( pChain->GetNext() )
+ {
+ SwFlyFrm *pFollow = FindChainNeighbour( *pChain->GetNext() );
+ if ( GetNextLink() && pFollow != GetNextLink() )
+ SwFlyFrm::UnchainFrames( this, GetNextLink());
+ if ( pFollow )
+ {
+ if ( pFollow->GetPrevLink() &&
+ pFollow->GetPrevLink() != this )
+ SwFlyFrm::UnchainFrames( pFollow->GetPrevLink(),
+ pFollow );
+ if ( !GetNextLink() )
+ SwFlyFrm::ChainFrames( this, pFollow );
+ }
+ }
+ else if ( GetNextLink() )
+ SwFlyFrm::UnchainFrames( this, GetNextLink() );
+ if ( pChain->GetPrev() )
+ {
+ SwFlyFrm *pMaster = FindChainNeighbour( *pChain->GetPrev() );
+ if ( GetPrevLink() && pMaster != GetPrevLink() )
+ SwFlyFrm::UnchainFrames( GetPrevLink(), this );
+ if ( pMaster )
+ {
+ if ( pMaster->GetNextLink() &&
+ pMaster->GetNextLink() != this )
+ SwFlyFrm::UnchainFrames( pMaster,
+ pMaster->GetNextLink() );
+ if ( !GetPrevLink() )
+ SwFlyFrm::ChainFrames( pMaster, this );
+ }
+ }
+ else if ( GetPrevLink() )
+ SwFlyFrm::UnchainFrames( GetPrevLink(), this );
+ }
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+
+ // erfrage vom Modify Informationen
+sal_Bool SwFlyFrm::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
+ return sal_False; // es gibt einen FlyFrm also wird er benutzt
+ return sal_True; // weiter suchen
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::_Invalidate()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::_Invalidate( SwPageFrm *pPage )
+{
+ InvalidatePage( pPage );
+ bNotifyBack = bInvalid = sal_True;
+
+ SwFlyFrm *pFrm;
+ if ( GetAnchorFrm() && 0 != (pFrm = AnchorFrm()->FindFlyFrm()) )
+ {
+ //Gaanz dumm: Wenn der Fly innerhalb eines Fly gebunden ist, der
+ //Spalten enthaehlt, sollte das Format von diesem ausgehen.
+ if ( !pFrm->IsLocked() && !pFrm->IsColLocked() &&
+ pFrm->Lower() && pFrm->Lower()->IsColumnFrm() )
+ pFrm->InvalidateSize();
+ }
+
+ // --> OD 2008-01-21 #i85216#
+ // if vertical position is oriented at a layout frame inside a ghost section,
+ // assure that the position is invalidated and that the information about
+ // the vertical position oriented frame is cleared
+ if ( GetVertPosOrientFrm() && GetVertPosOrientFrm()->IsLayoutFrm() )
+ {
+ const SwSectionFrm* pSectFrm( GetVertPosOrientFrm()->FindSctFrm() );
+ if ( pSectFrm && pSectFrm->GetSection() == 0 )
+ {
+ InvalidatePos();
+ ClearVertPosOrientFrm();
+ }
+ }
+ // <--
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChgRelPos()
+|*
+|* Beschreibung Aenderung der relativen Position, die Position wird
+|* damit automatisch Fix, das Attribut wird entprechend angepasst.
+|*
+|*************************************************************************/
+
+void SwFlyFrm::ChgRelPos( const Point &rNewPos )
+{
+ if ( GetCurrRelPos() != rNewPos )
+ {
+ SwFrmFmt *pFmt = GetFmt();
+ const bool bVert = GetAnchorFrm()->IsVertical();
+ const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
+ SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
+ if( bVert )
+ nTmpY = -nTmpY;
+ SfxItemSet aSet( pFmt->GetDoc()->GetAttrPool(),
+ RES_VERT_ORIENT, RES_HORI_ORIENT);
+
+ SwFmtVertOrient aVert( pFmt->GetVertOrient() );
+ SwTxtFrm *pAutoFrm = NULL;
+ // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
+ // Writer fly frames
+ const RndStdIds eAnchorType = GetFrmFmt().GetAnchor().GetAnchorId();
+ if ( eAnchorType == FLY_AT_PAGE )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ }
+ else if ( eAnchorType == FLY_AT_FLY )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::FRAME );
+ }
+ // <--
+ else if ( IsFlyAtCntFrm() || text::VertOrientation::NONE != aVert.GetVertOrient() )
+ {
+ if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
+ {
+ if( LONG_MAX != nNewY )
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ xub_StrLen nOfs =
+ pFmt->GetAnchor().GetCntntAnchor()->nContent.GetIndex();
+ OSL_ENSURE( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected" );
+ pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
+ while( pAutoFrm->GetFollow() &&
+ pAutoFrm->GetFollow()->GetOfst() <= nOfs )
+ {
+ if( pAutoFrm == GetAnchorFrm() )
+ nTmpY += pAutoFrm->GetRelPos().Y();
+ nTmpY -= pAutoFrm->GetUpper()->Prt().Height();
+ pAutoFrm = pAutoFrm->GetFollow();
+ }
+ nTmpY = ((SwFlyAtCntFrm*)this)->GetRelCharY(pAutoFrm)-nTmpY;
+ }
+ else
+ aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
+ }
+ else
+ {
+ aVert.SetVertOrient( text::VertOrientation::NONE );
+ aVert.SetRelationOrient( text::RelOrientation::FRAME );
+ }
+ }
+ aVert.SetPos( nTmpY );
+ aSet.Put( aVert );
+
+ //Fuer Flys im Cnt ist die horizontale Ausrichtung uninteressant,
+ //den sie ist stets 0.
+ if ( !IsFlyInCntFrm() )
+ {
+ const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
+ SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
+ SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
+ // --> OD 2004-11-12 #i34948# - handle also at-page and at-fly anchored
+ // Writer fly frames
+ if ( eAnchorType == FLY_AT_PAGE )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ else if ( eAnchorType == FLY_AT_FLY )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ aHori.SetRelationOrient( text::RelOrientation::FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ // <--
+ else if ( IsFlyAtCntFrm() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
+ {
+ aHori.SetHoriOrient( text::HoriOrientation::NONE );
+ if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
+ {
+ if( LONG_MAX != nNewX )
+ {
+ if( !pAutoFrm )
+ {
+ xub_StrLen nOfs = pFmt->GetAnchor().GetCntntAnchor()
+ ->nContent.GetIndex();
+ OSL_ENSURE( GetAnchorFrm()->IsTxtFrm(), "TxtFrm expected");
+ pAutoFrm = (SwTxtFrm*)GetAnchorFrm();
+ while( pAutoFrm->GetFollow() &&
+ pAutoFrm->GetFollow()->GetOfst() <= nOfs )
+ pAutoFrm = pAutoFrm->GetFollow();
+ }
+ nTmpX -= ((SwFlyAtCntFrm*)this)->GetRelCharX(pAutoFrm);
+ }
+ }
+ else
+ aHori.SetRelationOrient( text::RelOrientation::FRAME );
+ aHori.SetPosToggle( sal_False );
+ }
+ aHori.SetPos( nTmpX );
+ aSet.Put( aHori );
+ }
+ SetCurrRelPos( rNewPos );
+ pFmt->GetDoc()->SetAttr( aSet, *pFmt );
+ }
+}
+/*************************************************************************
+|*
+|* SwFlyFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "FlyFrm::Format, pAttrs ist 0." );
+
+ ColLock();
+
+ if ( !bValidSize )
+ {
+ if ( Frm().Top() == WEIT_WECH && Frm().Left() == WEIT_WECH )
+ {
+ //Sicherheitsschaltung wegnehmen (siehe SwFrm::CTor)
+ Frm().Pos().X() = Frm().Pos().Y() = 0;
+ // --> OD 2006-08-16 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+
+ //Breite der Spalten pruefen und ggf. einstellen.
+ if ( Lower() && Lower()->IsColumnFrm() )
+ AdjustColumns( 0, sal_False );
+
+ bValidSize = sal_True;
+
+ const SwTwips nUL = pAttrs->CalcTopLine() + pAttrs->CalcBottomLine();
+ const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
+ const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize();
+ Size aRelSize( CalcRel( rFrmSz ) );
+
+ OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrmSz.GetHeightPercent(), "Hoehe des RahmenAttr ist 0." );
+ OSL_ENSURE( pAttrs->GetSize().Width() != 0 || rFrmSz.GetWidthPercent(), "Breite des RahmenAttr ist 0." );
+
+ SWRECTFN( this )
+ if( !HasFixSize() )
+ {
+ SwTwips nRemaining = 0;
+
+ long nMinHeight = 0;
+ if( IsMinHeight() )
+ nMinHeight = bVert ? aRelSize.Width() : aRelSize.Height();
+
+ if ( Lower() )
+ {
+ if ( Lower()->IsColumnFrm() )
+ {
+ FormatWidthCols( *pAttrs, nUL, nMinHeight );
+ nRemaining = (Lower()->Frm().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ {
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - (pFrm->Prt().*fnRect->fnGetHeight)();
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ // --> OD 2006-02-09 #130878#
+ // Do not keep old height, if content has no height.
+ // The old height could be wrong due to wrong layout cache
+ // and isn't corrected in the further formatting, because
+ // the fly frame doesn't become invalid anymore.
+// if( !nRemaining )
+// nRemaining = nOldHeight - nUL;
+ // <--
+ }
+ if ( GetDrawObjs() )
+ {
+ sal_uInt32 nCnt = GetDrawObjs()->Count();
+ SwTwips nTop = (Frm().*fnRect->fnGetTop)();
+ SwTwips nBorder = (Frm().*fnRect->fnGetHeight)() -
+ (Prt().*fnRect->fnGetHeight)();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ // OD 06.11.2003 #i22305# - consider
+ // only Writer fly frames, which follow the text flow.
+ if ( pFly->IsFlyLayFrm() &&
+ pFly->Frm().Top() != WEIT_WECH &&
+ pFly->GetFmt()->GetFollowTextFlow().GetValue() )
+ {
+ SwTwips nDist = -(pFly->Frm().*fnRect->
+ fnBottomDist)( nTop );
+ if( nDist > nBorder + nRemaining )
+ nRemaining = nDist - nBorder;
+ }
+ }
+ }
+ }
+ }
+
+ if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
+ nRemaining = nMinHeight - nUL;
+ //Weil das Grow/Shrink der Flys die Groessen nicht direkt
+ //einstellt, sondern indirekt per Invalidate ein Format
+ //ausloesst, muessen die Groessen hier direkt eingestellt
+ //werden. Benachrichtung laeuft bereits mit.
+ //Weil bereits haeufiger 0en per Attribut hereinkamen wehre
+ //ich mich ab sofort dagegen.
+ if ( nRemaining < MINFLY )
+ nRemaining = MINFLY;
+ (Prt().*fnRect->fnSetHeight)( nRemaining );
+ nRemaining -= (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nRemaining + nUL );
+ // --> OD 2006-08-16 #i68520#
+ if ( nRemaining + nUL != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ bValidSize = sal_True;
+ }
+ else
+ {
+ bValidSize = sal_True; //Fixe Frms formatieren sich nicht.
+ //Flys stellen ihre Groesse anhand des Attr ein.
+ SwTwips nNewSize = bVert ? aRelSize.Width() : aRelSize.Height();
+ nNewSize -= nUL;
+ if( nNewSize < MINFLY )
+ nNewSize = MINFLY;
+ (Prt().*fnRect->fnSetHeight)( nNewSize );
+ nNewSize += nUL - (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nNewSize );
+ // --> OD 2006-08-16 #i68520#
+ if ( nNewSize != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ }
+
+ if ( !bFormatHeightOnly )
+ {
+ OSL_ENSURE( aRelSize == CalcRel( rFrmSz ), "SwFlyFrm::Format CalcRel problem" );
+ SwTwips nNewSize = bVert ? aRelSize.Height() : aRelSize.Width();
+
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ // #i9046# Autowidth for fly frames
+ const SwTwips nAutoWidth = CalcAutoWidth();
+ if ( nAutoWidth )
+ {
+ if( ATT_MIN_SIZE == rFrmSz.GetWidthSizeType() )
+ nNewSize = Max( nNewSize - nLR, nAutoWidth );
+ else
+ nNewSize = nAutoWidth;
+ }
+ }
+ else
+ nNewSize -= nLR;
+
+ if( nNewSize < MINFLY )
+ nNewSize = MINFLY;
+ (Prt().*fnRect->fnSetWidth)( nNewSize );
+ nNewSize += nLR - (Frm().*fnRect->fnGetWidth)();
+ (Frm().*fnRect->fnAddRight)( nNewSize );
+ // --> OD 2006-08-16 #i68520#
+ if ( nNewSize != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ }
+ }
+ ColUnlock();
+}
+
+// OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
+// default value = false.
+// OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
+// default value = false.
+// OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
+// <FormatWidthCols(..)> to avoid follow formatting
+// for text frames. But, unformatted follows causes
+// problems in method <SwCntntFrm::_WouldFit(..)>,
+// which assumes that the follows are formatted.
+// Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
+//void CalcCntnt( SwLayoutFrm *pLay, sal_Bool bNoColl )
+void CalcCntnt( SwLayoutFrm *pLay,
+ bool bNoColl,
+ bool bNoCalcFollow )
+{
+ SwSectionFrm* pSect;
+ sal_Bool bCollect = sal_False;
+ if( pLay->IsSctFrm() )
+ {
+ pSect = (SwSectionFrm*)pLay;
+ if( pSect->IsEndnAtEnd() && !bNoColl )
+ {
+ bCollect = sal_True;
+ SwLayouter::CollectEndnotes( pLay->GetFmt()->GetDoc(), pSect );
+ }
+ pSect->CalcFtnCntnt();
+ }
+ else
+ pSect = NULL;
+ SwFrm *pFrm = pLay->ContainsAny();
+ if ( !pFrm )
+ {
+ if( pSect )
+ {
+ if( pSect->HasFollow() )
+ pFrm = pSect->GetFollow()->ContainsAny();
+ if( !pFrm )
+ {
+ if( pSect->IsEndnAtEnd() )
+ {
+ if( bCollect )
+ pLay->GetFmt()->GetDoc()->GetLayouter()->
+ InsertEndnotes( pSect );
+ sal_Bool bLock = pSect->IsFtnLock();
+ pSect->SetFtnLock( sal_True );
+ pSect->CalcFtnCntnt();
+ pSect->CalcFtnCntnt();
+ pSect->SetFtnLock( bLock );
+ }
+ return;
+ }
+ pFrm->_InvalidatePos();
+ }
+ else
+ return;
+ }
+ pFrm->InvalidatePage();
+
+ do
+ {
+ // local variables to avoid loops caused by anchored object positioning
+ SwAnchoredObject* pAgainObj1 = 0;
+ SwAnchoredObject* pAgainObj2 = 0;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+ const SwFrm* pLoopControlCond = 0;
+
+ SwFrm* pLast;
+ do
+ {
+ pLast = pFrm;
+ if( pFrm->IsVertical() ?
+ ( pFrm->GetUpper()->Prt().Height() != pFrm->Frm().Height() )
+ : ( pFrm->GetUpper()->Prt().Width() != pFrm->Frm().Width() ) )
+ {
+ pFrm->Prepare( PREP_FIXSIZE_CHG );
+ pFrm->_InvalidateSize();
+ }
+
+ if ( pFrm->IsTabFrm() )
+ {
+ ((SwTabFrm*)pFrm)->bCalcLowers = sal_True;
+ // OD 26.08.2003 #i18103# - lock move backward of follow table,
+ // if no section content is formatted or follow table belongs
+ // to the section, which content is formatted.
+ if ( ((SwTabFrm*)pFrm)->IsFollow() &&
+ ( !pSect || pSect == pFrm->FindSctFrm() ) )
+ {
+ ((SwTabFrm*)pFrm)->bLockBackMove = sal_True;
+ }
+ }
+
+ // OD 14.03.2003 #i11760# - forbid format of follow, if requested.
+ if ( bNoCalcFollow && pFrm->IsTxtFrm() )
+ static_cast<SwTxtFrm*>(pFrm)->ForbidFollowFormat();
+
+ pFrm->Calc();
+
+ // OD 14.03.2003 #i11760# - reset control flag for follow format.
+ if ( pFrm->IsTxtFrm() )
+ {
+ static_cast<SwTxtFrm*>(pFrm)->AllowFollowFormat();
+ }
+
+ // #111937# The keep-attribute can cause the position
+ // of the prev to be invalid:
+ // OD 2004-03-15 #116560# - Do not consider invalid previous frame
+ // due to its keep-attribute, if current frame is a follow or is locked.
+ // --> OD 2005-03-08 #i44049# - do not consider invalid previous
+ // frame due to its keep-attribute, if it can't move forward.
+ // --> OD 2006-01-27 #i57765# - do not consider invalid previous
+ // frame, if current frame has a column/page break before attribute.
+ SwFrm* pTmpPrev = pFrm->FindPrev();
+ SwFlowFrm* pTmpPrevFlowFrm = pTmpPrev && pTmpPrev->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pTmpPrev) : 0;
+ SwFlowFrm* pTmpFlowFrm = pFrm->IsFlowFrm() ? SwFlowFrm::CastFlowFrm(pFrm) : 0;
+
+ bool bPrevInvalid = pTmpPrevFlowFrm && pTmpFlowFrm &&
+ !pTmpFlowFrm->IsFollow() &&
+ !StackHack::IsLocked() && // #i76382#
+ !pTmpFlowFrm->IsJoinLocked() &&
+ !pTmpPrev->GetValidPosFlag() &&
+ pLay->IsAnLower( pTmpPrev ) &&
+ pTmpPrevFlowFrm->IsKeep( *pTmpPrev->GetAttrSet() ) &&
+ pTmpPrevFlowFrm->IsKeepFwdMoveAllowed();
+ // <--
+
+ // format floating screen objects anchored to the frame.
+ bool bRestartLayoutProcess = false;
+ if ( !bPrevInvalid && pFrm->GetDrawObjs() && pLay->IsAnLower( pFrm ) )
+ {
+ bool bAgain = false;
+ SwPageFrm* pPageFrm = pFrm->FindPageFrm();
+ sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ // --> OD 2004-07-01 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ // determine, if anchored object has to be formatted.
+ if ( pAnchoredObj->PositionLocked() )
+ {
+ continue;
+ }
+
+ // format anchored object
+ if ( pAnchoredObj->IsFormatPossible() )
+ {
+ // --> OD 2005-05-17 #i43737# - no invalidation of
+ // anchored object needed - causes loops for as-character
+ // anchored objects.
+ //pAnchoredObj->InvalidateObjPos();
+ // <--
+ SwRect aRect( pAnchoredObj->GetObjRect() );
+ if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrm, pPageFrm ) )
+ {
+ bRestartLayoutProcess = true;
+ break;
+ }
+ // --> OD 2004-08-25 #i3317# - restart layout process,
+ // if the position of the anchored object is locked now.
+ if ( pAnchoredObj->PositionLocked() )
+ {
+ bRestartLayoutProcess = true;
+ break;
+ }
+ // <--
+
+ if ( aRect != pAnchoredObj->GetObjRect() )
+ {
+ bAgain = true;
+ if ( pAgainObj2 == pAnchoredObj )
+ {
+ OSL_FAIL( "::CalcCntnt(..) - loop detected, perform attribute changes to avoid the loop" );
+ //Oszillation unterbinden.
+ SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ SwFmtSurround aAttr( rFmt.GetSurround() );
+ if( SURROUND_THROUGHT != aAttr.GetSurround() )
+ {
+ // Bei autopositionierten hilft manchmal nur
+ // noch, auf Durchlauf zu schalten
+ if ((rFmt.GetAnchor().GetAnchorId() ==
+ FLY_AT_CHAR) &&
+ (SURROUND_PARALLEL ==
+ aAttr.GetSurround()))
+ {
+ aAttr.SetSurround( SURROUND_THROUGHT );
+ }
+ else
+ {
+ aAttr.SetSurround( SURROUND_PARALLEL );
+ }
+ rFmt.LockModify();
+ rFmt.SetFmtAttr( aAttr );
+ rFmt.UnlockModify();
+ }
+ }
+ else
+ {
+ if ( pAgainObj1 == pAnchoredObj )
+ pAgainObj2 = pAnchoredObj;
+ pAgainObj1 = pAnchoredObj;
+ }
+ }
+
+ if ( !pFrm->GetDrawObjs() )
+ break;
+ if ( pFrm->GetDrawObjs()->Count() < nCnt )
+ {
+ --i;
+ --nCnt;
+ }
+ }
+ }
+
+ // --> OD 2004-06-11 #i28701# - restart layout process, if
+ // requested by floating screen object formatting
+ if ( bRestartLayoutProcess )
+ {
+ pFrm = pLay->ContainsAny();
+ pAgainObj1 = 0L;
+ pAgainObj2 = 0L;
+ continue;
+ }
+
+ // OD 2004-05-17 #i28701# - format anchor frame after its objects
+ // are formatted, if the wrapping style influence has to be considered.
+ if ( pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ pFrm->Calc();
+ }
+ // <--
+
+ if ( bAgain )
+ {
+ pFrm = pLay->ContainsCntnt();
+ if ( pFrm && pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+ if( pFrm && pFrm->IsInSct() )
+ {
+ SwSectionFrm* pTmp = pFrm->FindSctFrm();
+ if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
+ pFrm = pTmp;
+ }
+
+ if ( pFrm == pLoopControlCond )
+ ++nLoopControlRuns;
+ else
+ {
+ nLoopControlRuns = 0;
+ pLoopControlCond = pFrm;
+ }
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ continue;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in CalcCntnt" );
+#endif
+ }
+ }
+ if ( pFrm->IsTabFrm() )
+ {
+ if ( ((SwTabFrm*)pFrm)->IsFollow() )
+ ((SwTabFrm*)pFrm)->bLockBackMove = sal_False;
+ }
+
+ pFrm = bPrevInvalid ? pTmpPrev : pFrm->FindNext();
+ if( !bPrevInvalid && pFrm && pFrm->IsSctFrm() && pSect )
+ {
+ // Es koennen hier leere SectionFrms herumspuken
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->FindNext();
+ // Wenn FindNext den Follow des urspruenglichen Bereichs liefert,
+ // wollen wir mit dessen Inhalt weitermachen, solange dieser
+ // zurueckfliesst.
+ if( pFrm && pFrm->IsSctFrm() && ( pFrm == pSect->GetFollow() ||
+ ((SwSectionFrm*)pFrm)->IsAnFollow( pSect ) ) )
+ {
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->_InvalidatePos();
+ }
+ }
+ // Im pLay bleiben, Ausnahme, bei SectionFrms mit Follow wird der erste
+ // CntntFrm des Follows anformatiert, damit er die Chance erhaelt, in
+ // pLay zu landen. Solange diese Frames in pLay landen, geht's weiter.
+ } while ( pFrm &&
+ ( pLay->IsAnLower( pFrm ) ||
+ ( pSect &&
+ ( ( pSect->HasFollow() &&
+ ( pLay->IsAnLower( pLast ) ||
+ ( pLast->IsInSct() &&
+ pLast->FindSctFrm()->IsAnFollow(pSect) ) ) &&
+ pSect->GetFollow()->IsAnLower( pFrm ) ) ||
+ ( pFrm->IsInSct() &&
+ pFrm->FindSctFrm()->IsAnFollow( pSect ) ) ) ) ) );
+ if( pSect )
+ {
+ if( bCollect )
+ {
+ pLay->GetFmt()->GetDoc()->GetLayouter()->InsertEndnotes(pSect);
+ pSect->CalcFtnCntnt();
+ }
+ if( pSect->HasFollow() )
+ {
+ SwSectionFrm* pNxt = pSect->GetFollow();
+ while( pNxt && !pNxt->ContainsCntnt() )
+ pNxt = pNxt->GetFollow();
+ if( pNxt )
+ pNxt->CalcFtnCntnt();
+ }
+ if( bCollect )
+ {
+ pFrm = pLay->ContainsAny();
+ bCollect = sal_False;
+ if( pFrm )
+ continue;
+ }
+ }
+ break;
+ }
+ while( sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::MakeFlyPos()
+|*
+|*************************************************************************/
+// OD 2004-03-23 #i26791#
+//void SwFlyFrm::MakeFlyPos()
+void SwFlyFrm::MakeObjPos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+
+ // OD 29.10.2003 #113049# - use new class to position object
+ GetAnchorFrm()->Calc();
+ objectpositioning::SwToLayoutAnchoredObjectPosition
+ aObjPositioning( *GetVirtDrawObj() );
+ aObjPositioning.CalcPosition();
+
+ // --> OD 2006-10-05 #i58280#
+ // update relative position
+ SetCurrRelPos( aObjPositioning.GetRelPos() );
+ // <--
+
+ SWRECTFN( GetAnchorFrm() );
+ aFrm.Pos( aObjPositioning.GetRelPos() );
+ aFrm.Pos() += (GetAnchorFrm()->Frm().*fnRect->fnGetPos)();
+ // --> OD 2006-09-11 #i69335#
+ InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::MakePrtArea()
+|*
+|*************************************************************************/
+void SwFlyFrm::MakePrtArea( const SwBorderAttrs &rAttrs )
+{
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ // OD 31.07.2003 #110978# - consider vertical layout
+ SWRECTFN( this )
+ (this->*fnRect->fnSetXMargins)( rAttrs.CalcLeftLine(),
+ rAttrs.CalcRightLine() );
+ (this->*fnRect->fnSetYMargins)( rAttrs.CalcTopLine(),
+ rAttrs.CalcBottomLine() );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::_Grow(), _Shrink()
+|*
+|*************************************************************************/
+
+SwTwips SwFlyFrm::_Grow( SwTwips nDist, sal_Bool bTst )
+{
+ SWRECTFN( this )
+ if ( Lower() && !IsColLocked() && !HasFixSize() )
+ {
+ SwTwips nSize = (Frm().*fnRect->fnGetHeight)();
+ if( nSize > 0 && nDist > ( LONG_MAX - nSize ) )
+ nDist = LONG_MAX - nSize;
+
+ if ( nDist <= 0L )
+ return 0L;
+
+ if ( Lower()->IsColumnFrm() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ {
+ // --> OD 2004-06-09 #i28701# - unlock position of Writer fly frame
+ UnlockPosition();
+ _InvalidatePos();
+ InvalidateSize();
+ }
+ return 0L;
+ }
+
+ if ( !bTst )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ _InvalidateSize();
+ const sal_Bool bOldLock = bLocked;
+ Unlock();
+ if ( IsFlyFreeFrm() )
+ {
+ // --> OD 2004-11-12 #i37068# - no format of position here
+ // and prevent move in method <CheckClip(..)>.
+ // This is needed to prevent layout loop caused by nested
+ // Writer fly frames - inner Writer fly frames format its
+ // anchor, which grows/shrinks the outer Writer fly frame.
+ // Note: position will be invalidated below.
+ bValidPos = sal_True;
+ // --> OD 2005-10-10 #i55416#
+ // Suppress format of width for autowidth frame, because the
+ // format of the width would call <SwTxtFrm::CalcFitToContent()>
+ // for the lower frame, which initiated this grow.
+ const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
+ const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = sal_True;
+ }
+ // <--
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
+ ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
+ // --> OD 2005-10-10 #i55416#
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = bOldFormatHeightOnly;
+ }
+ // <--
+ // <--
+ }
+ else
+ MakeAll();
+ _InvalidateSize();
+ InvalidatePos();
+ if ( bOldLock )
+ Lock();
+ const SwRect aNew( GetObjRectWithSpaces() );
+ if ( aOld != aNew )
+ ::Notify( this, FindPageFrm(), aOld );
+ return (aNew.*fnRect->fnGetHeight)()-(aOld.*fnRect->fnGetHeight)();
+ }
+ return nDist;
+ }
+ return 0L;
+}
+
+SwTwips SwFlyFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
+{
+ if( Lower() && !IsColLocked() && !HasFixSize() && !IsNoShrink() )
+ {
+ SWRECTFN( this )
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nHeight )
+ nDist = nHeight;
+
+ SwTwips nVal = nDist;
+ if ( IsMinHeight() )
+ {
+ const SwFmtFrmSize& rFmtSize = GetFmt()->GetFrmSize();
+ SwTwips nFmtHeight = bVert ? rFmtSize.GetWidth() : rFmtSize.GetHeight();
+
+ nVal = Min( nDist, nHeight - nFmtHeight );
+ }
+
+ if ( nVal <= 0L )
+ return 0L;
+
+ if ( Lower()->IsColumnFrm() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ {
+ SwRect aOld( GetObjRectWithSpaces() );
+ (Frm().*fnRect->fnSetHeight)( nHeight - nVal );
+ // --> OD 2006-08-16 #i68520#
+ if ( nHeight - nVal != 0 )
+ {
+ InvalidateObjRectWithSpaces();
+ }
+ // <--
+ nHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nHeight - nVal );
+ _InvalidatePos();
+ InvalidateSize();
+ ::Notify( this, FindPageFrm(), aOld );
+ NotifyDrawObj();
+ if ( GetAnchorFrm()->IsInFly() )
+ AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
+ }
+ return 0L;
+ }
+
+ if ( !bTst )
+ {
+ const SwRect aOld( GetObjRectWithSpaces() );
+ _InvalidateSize();
+ const sal_Bool bOldLocked = bLocked;
+ Unlock();
+ if ( IsFlyFreeFrm() )
+ {
+ // --> OD 2004-11-12 #i37068# - no format of position here
+ // and prevent move in method <CheckClip(..)>.
+ // This is needed to prevent layout loop caused by nested
+ // Writer fly frames - inner Writer fly frames format its
+ // anchor, which grows/shrinks the outer Writer fly frame.
+ // Note: position will be invalidated below.
+ bValidPos = sal_True;
+ // --> OD 2005-10-10 #i55416#
+ // Suppress format of width for autowidth frame, because the
+ // format of the width would call <SwTxtFrm::CalcFitToContent()>
+ // for the lower frame, which initiated this shrink.
+ const sal_Bool bOldFormatHeightOnly = bFormatHeightOnly;
+ const SwFmtFrmSize& rFrmSz = GetFmt()->GetFrmSize();
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = sal_True;
+ }
+ // <--
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( true );
+ ((SwFlyFreeFrm*)this)->SwFlyFreeFrm::MakeAll();
+ static_cast<SwFlyFreeFrm*>(this)->SetNoMoveOnCheckClip( false );
+ // --> OD 2005-10-10 #i55416#
+ if ( rFrmSz.GetWidthSizeType() != ATT_FIX_SIZE )
+ {
+ bFormatHeightOnly = bOldFormatHeightOnly;
+ }
+ // <--
+ // <--
+ }
+ else
+ MakeAll();
+ _InvalidateSize();
+ InvalidatePos();
+ if ( bOldLocked )
+ Lock();
+ const SwRect aNew( GetObjRectWithSpaces() );
+ if ( aOld != aNew )
+ {
+ ::Notify( this, FindPageFrm(), aOld );
+ if ( GetAnchorFrm()->IsInFly() )
+ AnchorFrm()->FindFlyFrm()->Shrink( nDist, bTst );
+ }
+ return (aOld.*fnRect->fnGetHeight)() -
+ (aNew.*fnRect->fnGetHeight)();
+ }
+ return nVal;
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::ChgSize()
+|*
+|*************************************************************************/
+
+Size SwFlyFrm::ChgSize( const Size& aNewSize )
+{
+ // --> OD 2006-01-19 #i53298#
+ // If the fly frame anchored at-paragraph or at-character contains an OLE
+ // object, assure that the new size fits into the current clipping area
+ // of the fly frame
+ Size aAdjustedNewSize( aNewSize );
+ {
+ if ( dynamic_cast<SwFlyAtCntFrm*>(this) &&
+ Lower() && dynamic_cast<SwNoTxtFrm*>(Lower()) &&
+ static_cast<SwNoTxtFrm*>(Lower())->GetNode()->GetOLENode() )
+ {
+ SwRect aClipRect;
+ ::CalcClipRect( GetVirtDrawObj(), aClipRect, sal_False );
+ if ( aAdjustedNewSize.Width() > aClipRect.Width() )
+ {
+ aAdjustedNewSize.setWidth( aClipRect.Width() );
+ }
+ if ( aAdjustedNewSize.Height() > aClipRect.Height() )
+ {
+ aAdjustedNewSize.setWidth( aClipRect.Height() );
+ }
+ }
+ }
+ // <--
+ if ( aAdjustedNewSize != Frm().SSize() )
+ {
+ SwFrmFmt *pFmt = GetFmt();
+ SwFmtFrmSize aSz( pFmt->GetFrmSize() );
+ aSz.SetWidth( aAdjustedNewSize.Width() );
+ // --> OD 2006-01-19 #i53298# - no tolerance any more.
+ // If it reveals that the tolerance is still needed, then suppress a
+ // <SetAttr> call, if <aSz> equals the current <SwFmtFrmSize> attribute.
+// if ( Abs(aAdjustedNewSize.Height() - aSz.GetHeight()) > 1 )
+ aSz.SetHeight( aAdjustedNewSize.Height() );
+ // <--
+ // uebers Doc fuers Undo!
+ pFmt->GetDoc()->SetAttr( aSz, *pFmt );
+ return aSz.GetSize();
+ }
+ else
+ return Frm().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::IsLowerOf()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::IsLowerOf( const SwLayoutFrm* pUpperFrm ) const
+{
+ OSL_ENSURE( GetAnchorFrm(), "8-( Fly is lost in Space." );
+ const SwFrm* pFrm = GetAnchorFrm();
+ do
+ {
+ if ( pFrm == pUpperFrm )
+ return sal_True;
+ pFrm = pFrm->IsFlyFrm()
+ ? ((const SwFlyFrm*)pFrm)->GetAnchorFrm()
+ : pFrm->GetUpper();
+ } while ( pFrm );
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Cut()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::Cut()
+{
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AppendFly(), RemoveFly()
+|*
+|*************************************************************************/
+
+void SwFrm::AppendFly( SwFlyFrm *pNew )
+{
+ if ( !pDrawObjs )
+ pDrawObjs = new SwSortedObjs();
+ pDrawObjs->Insert( *pNew );
+ pNew->ChgAnchorFrm( this );
+
+ //Bei der Seite anmelden; kann sein, dass noch keine da ist - die
+ //Anmeldung wird dann in SwPageFrm::PreparePage durch gefuehrt.
+ SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pNew->IsFlyAtCntFrm() && pNew->Frm().Top() == WEIT_WECH )
+ {
+ //Versuch die Seitenformatierung von neuen Dokumenten etwas
+ //guenstiger zu gestalten.
+ //Wir haengen die Flys erstenmal nach hinten damit sie bei heftigem
+ //Fluss der Anker nicht unoetig oft formatiert werden.
+ //Damit man noch brauchbar an das Ende des Dokumentes springen
+ //kann werden die Flys nicht ganz an das Ende gehaengt.
+ SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ if( !SwLayHelper::CheckPageFlyCache( pPage, pNew ) )
+ {
+ SwPageFrm *pTmp = pRoot->GetLastPage();
+ if ( pTmp->GetPhyPageNum() > 30 )
+ {
+ for ( sal_uInt16 i = 0; i < 10; ++i )
+ {
+ pTmp = (SwPageFrm*)pTmp->GetPrev();
+ if( pTmp->GetPhyPageNum() <= pPage->GetPhyPageNum() )
+ break; // damit wir nicht vor unserem Anker landen
+ }
+ if ( pTmp->IsEmptyPage() )
+ pTmp = (SwPageFrm*)pTmp->GetPrev();
+ pPage = pTmp;
+ }
+ }
+ pPage->AppendFlyToPage( pNew );
+ }
+ else
+ pPage->AppendFlyToPage( pNew );
+ }
+}
+
+void SwFrm::RemoveFly( SwFlyFrm *pToRemove )
+{
+ //Bei der Seite Abmelden - kann schon passiert sein weil die Seite
+ //bereits destruiert wurde.
+ SwPageFrm *pPage = pToRemove->FindPageFrm();
+ if ( pPage && pPage->GetSortedObjs() )
+ {
+ pPage->RemoveFlyFromPage( pToRemove );
+ }
+ // --> OD 2008-05-19 #i73201#
+ else
+ {
+ if ( pToRemove->IsAccessibleFrm() &&
+ pToRemove->GetFmt() &&
+ !pToRemove->IsFlyInCntFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ pVSh->Imp()->DisposeAccessibleFrm( pToRemove );
+ }
+ }
+ }
+ }
+ // <--
+
+ pDrawObjs->Remove( *pToRemove );
+ if ( !pDrawObjs->Count() )
+ DELETEZ( pDrawObjs );
+
+ pToRemove->ChgAnchorFrm( 0 );
+
+ if ( !pToRemove->IsFlyInCntFrm() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
+ GetUpper()->InvalidateSize();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AppendDrawObj(), RemoveDrawObj()
+|*
+|* --> OD 2004-07-06 #i28701# - new methods
+|*
+|*************************************************************************/
+void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
+{
+ if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwFrm::AppendDrawObj(..) - anchored object of unexcepted type -> object not appended" );
+ return;
+ }
+
+ if ( !_rNewObj.GetDrawObj()->ISA(SwDrawVirtObj) &&
+ _rNewObj.GetAnchorFrm() && _rNewObj.GetAnchorFrm() != this )
+ {
+ // perform disconnect from layout, if 'master' drawing object is appended
+ // to a new frame.
+ static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
+ DisconnectFromLayout( false );
+ }
+
+ if ( _rNewObj.GetAnchorFrm() != this )
+ {
+ if ( !pDrawObjs )
+ pDrawObjs = new SwSortedObjs();
+ pDrawObjs->Insert( _rNewObj );
+ _rNewObj.ChgAnchorFrm( this );
+ }
+
+ // --> OD 2010-09-14 #i113730#
+ // Assure the control objects and group objects containing controls are on the control layer
+ if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
+ {
+ const IDocumentDrawModelAccess* pIDDMA = getIDocumentDrawModelAccess();
+ const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
+ const SdrLayerID aControlLayerID(pIDDMA->GetControlsId());
+ const SdrLayerID aInvisibleControlLayerID(pIDDMA->GetInvisibleControlsId());
+
+ if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
+ {
+ if ( aCurrentLayer == pIDDMA->GetInvisibleHellId() ||
+ aCurrentLayer == pIDDMA->GetInvisibleHeavenId() )
+ {
+ _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
+ }
+ else
+ {
+ _rNewObj.DrawObj()->SetLayer(aControlLayerID);
+ }
+ }
+ }
+ // <--
+
+ // no direct positioning needed, but invalidate the drawing object position
+ _rNewObj.InvalidateObjPos();
+
+ // register at page frame
+ SwPageFrm* pPage = FindPageFrm();
+ if ( pPage )
+ {
+ pPage->AppendDrawObjToPage( _rNewObj );
+ }
+
+ // Notify accessible layout.
+ ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
+ }
+}
+
+void SwFrm::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
+{
+ // Notify accessible layout.
+ ViewShell* pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ {
+ SwRootFrm* pLayout = getRootFrm();
+ if( pLayout && pLayout->IsAnyShellAccessible() )
+ pSh->Imp()->DisposeAccessibleObj( _rToRemoveObj.GetDrawObj() );
+ }
+
+ // deregister from page frame
+ SwPageFrm* pPage = _rToRemoveObj.GetPageFrm();
+ if ( pPage && pPage->GetSortedObjs() )
+ pPage->RemoveDrawObjFromPage( _rToRemoveObj );
+
+ pDrawObjs->Remove( _rToRemoveObj );
+ if ( !pDrawObjs->Count() )
+ DELETEZ( pDrawObjs );
+
+ _rToRemoveObj.ChgAnchorFrm( 0 );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InvalidateObjs()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - change purpose of method and adjust its name
+void SwFrm::InvalidateObjs( const bool _bInvaPosOnly,
+ const bool _bNoInvaOfAsCharAnchoredObjs )
+{
+ if ( GetDrawObjs() )
+ {
+ // --> OD 2004-10-08 #i26945# - determine page the frame is on,
+ // in order to check, if anchored object is registered at the same
+ // page.
+ const SwPageFrm* pPageFrm = FindPageFrm();
+ // <--
+ // --> OD 2004-07-01 #i28701# - re-factoring
+ sal_uInt32 i = 0;
+ for ( ; i < GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
+ if ( _bNoInvaOfAsCharAnchoredObjs &&
+ (pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR) )
+ {
+ continue;
+ }
+ // --> OD 2004-10-08 #i26945# - no invalidation, if anchored object
+ // isn't registered at the same page and instead is registered at
+ // the page, where its anchor character text frame is on.
+ if ( pAnchoredObj->GetPageFrm() &&
+ pAnchoredObj->GetPageFrm() != pPageFrm )
+ {
+ SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
+ if ( pAnchorCharFrm &&
+ pAnchoredObj->GetPageFrm() == pAnchorCharFrm->FindPageFrm() )
+ {
+ continue;
+ }
+ // --> OD 2004-11-24 #115759# - unlock its position, if anchored
+ // object isn't registered at the page, where its anchor
+ // character text frame is on, respectively if it has no
+ // anchor character text frame.
+ else
+ {
+ pAnchoredObj->UnlockPosition();
+ }
+ // <--
+ }
+ // <--
+ // --> OD 2005-07-18 #i51474# - reset flag, that anchored object
+ // has cleared environment, and unlock its position, if the anchored
+ // object is registered at the same page as the anchor frame is on.
+ if ( pAnchoredObj->ClearedEnvironment() &&
+ pAnchoredObj->GetPageFrm() &&
+ pAnchoredObj->GetPageFrm() == pPageFrm )
+ {
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->SetClearedEnvironment( false );
+ }
+ // <--
+ // distinguish between writer fly frames and drawing objects
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFly->_Invalidate();
+ pFly->_InvalidatePos();
+ if ( !_bInvaPosOnly )
+ pFly->_InvalidateSize();
+ }
+ else
+ {
+ pAnchoredObj->InvalidateObjPos();
+ } // end of distinction between writer fly frames and drawing objects
+
+ } // end of loop on objects, which are connected to the frame
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::NotifyLowerObjs()
+|*
+|*************************************************************************/
+// --> OD 2004-07-01 #i28701# - change purpose of method and its name
+// --> OD 2004-10-08 #i26945# - correct check, if anchored object is a lower
+// of the layout frame. E.g., anchor character text frame can be a follow text
+// frame.
+// --> OD 2005-03-11 #i44016# - add parameter <_bUnlockPosOfObjs> to
+// force an unlockposition call for the lower objects.
+void SwLayoutFrm::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
+{
+ // invalidate lower floating screen objects
+ SwPageFrm* pPageFrm = FindPageFrm();
+ if ( pPageFrm && pPageFrm->GetSortedObjs() )
+ {
+ SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ // --> OD 2004-10-08 #i26945# - check, if anchored object is a lower
+ // of the layout frame is changed to check, if its anchor frame
+ // is a lower of the layout frame.
+ // determine the anchor frame - usually it's the anchor frame,
+ // for at-character/as-character anchored objects the anchor character
+ // text frame is taken.
+ const SwFrm* pAnchorFrm = pObj->GetAnchorFrmContainingAnchPos();
+ // <--
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+
+ if ( pFly->Frm().Left() == WEIT_WECH )
+ continue;
+
+ if ( pFly->IsAnLower( this ) )
+ continue;
+
+ // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
+ // fly frame is lower of layout frame resp. if fly frame is
+ // at a different page registered as its anchor frame is on.
+ const bool bLow = IsAnLower( pAnchorFrm );
+ if ( bLow || pAnchorFrm->FindPageFrm() != pPageFrm )
+ // <--
+ {
+ pFly->_Invalidate( pPageFrm );
+ if ( !bLow || pFly->IsFlyAtCntFrm() )
+ {
+ // --> OD 2005-03-11 #i44016#
+ if ( _bUnlockPosOfObjs )
+ {
+ pFly->UnlockPosition();
+ }
+ // <--
+ pFly->_InvalidatePos();
+ }
+ else
+ pFly->_InvalidatePrt();
+ }
+ }
+ else
+ {
+ OSL_ENSURE( pObj->ISA(SwAnchoredDrawObject),
+ "<SwLayoutFrm::NotifyFlys() - anchored object of unexcepted type" );
+ // --> OD 2004-10-08 #i26945# - use <pAnchorFrm> to check, if
+ // fly frame is lower of layout frame resp. if fly frame is
+ // at a different page registered as its anchor frame is on.
+ if ( IsAnLower( pAnchorFrm ) ||
+ pAnchorFrm->FindPageFrm() != pPageFrm )
+ // <--
+ {
+ // --> OD 2005-03-11 #i44016#
+ if ( _bUnlockPosOfObjs )
+ {
+ pObj->UnlockPosition();
+ }
+ // <--
+ pObj->InvalidateObjPos();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::NotifyDrawObj()
+|*
+|*************************************************************************/
+
+void SwFlyFrm::NotifyDrawObj()
+{
+ SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
+ pObj->SetRect();
+ pObj->SetRectsDirty();
+ pObj->SetChanged();
+ pObj->BroadcastObjectChange();
+ if ( GetFmt()->GetSurround().IsContour() )
+ ClrContourCache( pObj );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::CalcRel()
+|*
+|*************************************************************************/
+
+Size SwFlyFrm::CalcRel( const SwFmtFrmSize &rSz ) const
+{
+ Size aRet( rSz.GetSize() );
+
+ const SwFrm *pRel = IsFlyLayFrm() ? GetAnchorFrm() : GetAnchorFrm()->GetUpper();
+ if( pRel ) // LAYER_IMPL
+ {
+ long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( ( pRel->IsBodyFrm() || pRel->IsPageFrm() ) &&
+ pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ pSh->VisArea().HasArea() )
+ {
+ nRelWidth = pSh->GetBrowseWidth();
+ nRelHeight = pSh->VisArea().Height();
+ Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
+ long nDiff = nRelWidth - pRel->Prt().Width();
+ if ( nDiff > 0 )
+ nRelWidth -= nDiff;
+ nRelHeight -= 2*aBorder.Height();
+ nDiff = nRelHeight - pRel->Prt().Height();
+ if ( nDiff > 0 )
+ nRelHeight -= nDiff;
+ }
+ nRelWidth = Min( nRelWidth, pRel->Prt().Width() );
+ nRelHeight = Min( nRelHeight, pRel->Prt().Height() );
+ if( !pRel->IsPageFrm() )
+ {
+ const SwPageFrm* pPage = FindPageFrm();
+ if( pPage )
+ {
+ nRelWidth = Min( nRelWidth, pPage->Prt().Width() );
+ nRelHeight = Min( nRelHeight, pPage->Prt().Height() );
+ }
+ }
+
+ if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != 0xFF )
+ aRet.Width() = nRelWidth * rSz.GetWidthPercent() / 100;
+ if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != 0xFF )
+ aRet.Height() = nRelHeight * rSz.GetHeightPercent() / 100;
+
+ if ( rSz.GetWidthPercent() == 0xFF )
+ {
+ aRet.Width() *= aRet.Height();
+ aRet.Width() /= rSz.GetHeight();
+ }
+ else if ( rSz.GetHeightPercent() == 0xFF )
+ {
+ aRet.Height() *= aRet.Width();
+ aRet.Height() /= rSz.GetWidth();
+ }
+ }
+ return aRet;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::CalcAutoWidth()
+|*
+|*************************************************************************/
+
+SwTwips lcl_CalcAutoWidth( const SwLayoutFrm& rFrm )
+{
+ SwTwips nRet = 0;
+ SwTwips nMin = 0;
+ const SwFrm* pFrm = rFrm.Lower();
+
+ // No autowidth defined for columned frames
+ if ( !pFrm || pFrm->IsColumnFrm() )
+ return nRet;
+
+ while ( pFrm )
+ {
+ if ( pFrm->IsSctFrm() )
+ {
+ nMin = lcl_CalcAutoWidth( *(SwSectionFrm*)pFrm );
+ }
+ if ( pFrm->IsTxtFrm() )
+ {
+ nMin = ((SwTxtFrm*)pFrm)->CalcFitToContent();
+ const SvxLRSpaceItem &rSpace =
+ ((SwTxtFrm*)pFrm)->GetTxtNode()->GetSwAttrSet().GetLRSpace();
+ nMin += rSpace.GetRight() + rSpace.GetTxtLeft() + rSpace.GetTxtFirstLineOfst();
+ }
+ else if ( pFrm->IsTabFrm() )
+ {
+ const SwFmtFrmSize& rTblFmtSz = ((SwTabFrm*)pFrm)->GetTable()->GetFrmFmt()->GetFrmSize();
+ if ( USHRT_MAX == rTblFmtSz.GetSize().Width() ||
+ text::HoriOrientation::NONE == ((SwTabFrm*)pFrm)->GetFmt()->GetHoriOrient().GetHoriOrient() )
+ {
+ const SwPageFrm* pPage = rFrm.FindPageFrm();
+ // auto width table
+ nMin = pFrm->GetUpper()->IsVertical() ?
+ pPage->Prt().Height() :
+ pPage->Prt().Width();
+ }
+ else
+ {
+ nMin = rTblFmtSz.GetSize().Width();
+ }
+ }
+
+ if ( nMin > nRet )
+ nRet = nMin;
+
+ pFrm = pFrm->GetNext();
+ }
+
+ return nRet;
+}
+
+SwTwips SwFlyFrm::CalcAutoWidth() const
+{
+ return lcl_CalcAutoWidth( *this );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetContour()
+|*
+|*************************************************************************/
+/// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTxtFrm> contains
+/// a graphic, load of intrinsic graphic has to be avoided.
+sal_Bool SwFlyFrm::GetContour( PolyPolygon& rContour,
+ const sal_Bool _bForPaint ) const
+{
+ sal_Bool bRet = sal_False;
+ if( GetFmt()->GetSurround().IsContour() && Lower() &&
+ Lower()->IsNoTxtFrm() )
+ {
+ SwNoTxtNode *pNd = (SwNoTxtNode*)((SwCntntFrm*)Lower())->GetNode();
+ // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
+ // in order to avoid load of graphic, if <SwNoTxtNode> contains a graphic
+ // node and method is called for paint.
+ const GraphicObject* pGrfObj = NULL;
+ sal_Bool bGrfObjCreated = sal_False;
+ const SwGrfNode* pGrfNd = pNd->GetGrfNode();
+ if ( pGrfNd && _bForPaint )
+ {
+ pGrfObj = &(pGrfNd->GetGrfObj());
+ }
+ else
+ {
+ pGrfObj = new GraphicObject( pNd->GetGraphic() );
+ bGrfObjCreated = sal_True;
+ }
+ OSL_ENSURE( pGrfObj, "SwFlyFrm::GetContour() - No Graphic/GraphicObject found at <SwNoTxtNode>." );
+ if ( pGrfObj && pGrfObj->GetType() != GRAPHIC_NONE )
+ {
+ if( !pNd->HasContour() )
+ {
+ // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
+ // during paint. Thus, return (value of <bRet> should be <sal_False>).
+ if ( pGrfNd && _bForPaint )
+ {
+ OSL_FAIL( "SwFlyFrm::GetContour() - No Contour found at <SwNoTxtNode> during paint." );
+ return bRet;
+ }
+ pNd->CreateContour();
+ }
+ pNd->GetContour( rContour );
+ //Der Node haelt das Polygon passend zur Originalgroesse der Grafik
+ //hier muss die Skalierung einkalkuliert werden.
+ SwRect aClip;
+ SwRect aOrig;
+ Lower()->Calc();
+ ((SwNoTxtFrm*)Lower())->GetGrfArea( aClip, &aOrig, sal_False );
+ // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
+ // in order to avoid that graphic has to be loaded for contour scale.
+ //SvxContourDlg::ScaleContour( rContour, aGrf, MAP_TWIP, aOrig.SSize() );
+ {
+ OutputDevice* pOutDev = Application::GetDefaultDevice();
+ const MapMode aDispMap( MAP_TWIP );
+ const MapMode aGrfMap( pGrfObj->GetPrefMapMode() );
+ const Size aGrfSize( pGrfObj->GetPrefSize() );
+ Size aOrgSize;
+ Point aNewPoint;
+ sal_Bool bPixelMap = aGrfMap.GetMapUnit() == MAP_PIXEL;
+
+ if ( bPixelMap )
+ aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
+ else
+ aOrgSize = pOutDev->LogicToLogic( aGrfSize, aGrfMap, aDispMap );
+
+ if ( aOrgSize.Width() && aOrgSize.Height() )
+ {
+ double fScaleX = (double) aOrig.Width() / aOrgSize.Width();
+ double fScaleY = (double) aOrig.Height() / aOrgSize.Height();
+
+ for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
+ {
+ Polygon& rPoly = rContour[ j ];
+
+ for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+ {
+ if ( bPixelMap )
+ aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap );
+ else
+ aNewPoint = pOutDev->LogicToLogic( rPoly[ i ], aGrfMap, aDispMap );
+
+ rPoly[ i ] = Point( FRound( aNewPoint.X() * fScaleX ), FRound( aNewPoint.Y() * fScaleY ) );
+ }
+ }
+ }
+ }
+ // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
+ if ( bGrfObjCreated )
+ {
+ delete pGrfObj;
+ }
+ rContour.Move( aOrig.Left(), aOrig.Top() );
+ if( !aClip.Width() )
+ aClip.Width( 1 );
+ if( !aClip.Height() )
+ aClip.Height( 1 );
+ rContour.Clip( aClip.SVRect() );
+ rContour.Optimize(POLY_OPTIMIZE_CLOSE);
+ bRet = sal_True;
+ }
+ }
+ return bRet;
+}
+
+// OD 2004-03-25 #i26791#
+const SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj() const
+{
+ return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
+}
+SwVirtFlyDrawObj* SwFlyFrm::GetVirtDrawObj()
+{
+ return static_cast<SwVirtFlyDrawObj*>(DrawObj());
+}
+
+// =============================================================================
+// OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
+// base class <SwAnchoredObject>
+// =============================================================================
+void SwFlyFrm::InvalidateObjPos()
+{
+ InvalidatePos();
+ // --> OD 2006-08-10 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+}
+
+SwFrmFmt& SwFlyFrm::GetFrmFmt()
+{
+ OSL_ENSURE( GetFmt(),
+ "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
+ return *GetFmt();
+}
+const SwFrmFmt& SwFlyFrm::GetFrmFmt() const
+{
+ OSL_ENSURE( GetFmt(),
+ "<SwFlyFrm::GetFrmFmt()> - missing frame format -> crash." );
+ return *GetFmt();
+}
+
+const SwRect SwFlyFrm::GetObjRect() const
+{
+ return Frm();
+}
+
+// --> OD 2006-10-05 #i70122#
+// for Writer fly frames the bounding rectangle equals the object rectangles
+const SwRect SwFlyFrm::GetObjBoundRect() const
+{
+ return GetObjRect();
+}
+// <--
+
+// --> OD 2006-08-10 #i68520#
+bool SwFlyFrm::_SetObjTop( const SwTwips _nTop )
+{
+ const bool bChanged( Frm().Pos().Y() != _nTop );
+
+ Frm().Pos().Y() = _nTop;
+
+ return bChanged;
+}
+bool SwFlyFrm::_SetObjLeft( const SwTwips _nLeft )
+{
+ const bool bChanged( Frm().Pos().X() != _nLeft );
+
+ Frm().Pos().X() = _nLeft;
+
+ return bChanged;
+}
+// <--
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ OD 2004-07-02 #i28701#
+
+ @author OD
+*/
+void SwFlyFrm::RegisterAtCorrectPage()
+{
+ // default behaviour is to do nothing.
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+
+ OD 2004-05-11 #i28701#
+
+ @author OD
+*/
+bool SwFlyFrm::IsFormatPossible() const
+{
+ return SwAnchoredObject::IsFormatPossible() &&
+ !IsLocked() && !IsColLocked();
+}
+
+void SwFlyFrm::GetAnchoredObjects( std::list<SwAnchoredObject*>& aList, const SwFmt& rFmt )
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( rFmt );
+ for( SwFlyFrm* pFlyFrm = aIter.First(); pFlyFrm; pFlyFrm = aIter.Next() )
+ aList.push_back( pFlyFrm );
+}
+
+const SwFlyFrmFmt * SwFlyFrm::GetFmt() const
+{
+ return static_cast< const SwFlyFrmFmt * >( GetDep() );
+}
+
+SwFlyFrmFmt * SwFlyFrm::GetFmt()
+{
+ return static_cast< SwFlyFrmFmt * >( GetDep() );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
new file mode 100644
index 000000000000..7db5677f7403
--- /dev/null
+++ b/sw/source/core/layout/flycnt.cxx
@@ -0,0 +1,1541 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/bigint.hxx>
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "txtfrm.hxx"
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include "viewsh.hxx"
+#include "viewimp.hxx"
+#include "pam.hxx"
+#include "frmfmt.hxx"
+#include "frmtool.hxx"
+#include "dflyobj.hxx"
+#include "hints.hxx"
+#include "ndtxt.hxx"
+#include "swundo.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+
+#include "tabfrm.hxx"
+#include "flyfrms.hxx"
+#include "crstate.hxx"
+#include "sectfrm.hxx"
+
+#include <tocntntanchoredobjectposition.hxx>
+#include <dcontact.hxx>
+#include <sortedobjs.hxx>
+#include <layouter.hxx>
+#include <objectformattertxtfrm.hxx>
+#include <HandleAnchorNodeChg.hxx>
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::SwFlyAtCntFrm()
+|*
+|*************************************************************************/
+
+SwFlyAtCntFrm::SwFlyAtCntFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFreeFrm( pFmt, pSib, pAnch )
+{
+ bAtCnt = sal_True;
+ bAutoPosition = (FLY_AT_CHAR == pFmt->GetAnchor().GetAnchorId());
+}
+
+// #i28701#
+TYPEINIT1(SwFlyAtCntFrm,SwFlyFreeFrm);
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyAtCntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+ const SwFmtAnchor *pAnch = 0;
+
+ if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnch ))
+ ; // Beim GetItemState wird der AnkerPointer gesetzt !
+
+ else if( RES_ANCHOR == nWhich )
+ {
+ //Ankerwechsel, ich haenge mich selbst um.
+ //Es darf sich nicht um einen Wechsel des Ankertyps handeln,
+ //dies ist nur ueber die SwFEShell moeglich.
+ pAnch = (const SwFmtAnchor*)pNew;
+ }
+
+ if( pAnch )
+ {
+ OSL_ENSURE( pAnch->GetAnchorId() == GetFmt()->GetAnchor().GetAnchorId(),
+ "Unzulaessiger Wechsel des Ankertyps." );
+
+ //Abmelden, neuen Anker besorgen und 'dranhaengen.
+ SwRect aOld( GetObjRectWithSpaces() );
+ SwPageFrm *pOldPage = FindPageFrm();
+ const SwFrm *pOldAnchor = GetAnchorFrm();
+ SwCntntFrm *pCntnt = (SwCntntFrm*)GetAnchorFrm();
+ AnchorFrm()->RemoveFly( this );
+
+ const sal_Bool bBodyFtn = (pCntnt->IsInDocBody() || pCntnt->IsInFtn());
+
+ //Den neuen Anker anhand des NodeIdx suchen, am alten und
+ //neuen NodeIdx kann auch erkannt werden, in welche Richtung
+ //gesucht werden muss.
+ const SwNodeIndex aNewIdx( pAnch->GetCntntAnchor()->nNode );
+ SwNodeIndex aOldIdx( *pCntnt->GetNode() );
+
+ //fix: Umstellung, ehemals wurde in der do-while-Schleife nach vorn bzw.
+ //nach hinten gesucht; je nachdem wie welcher Index kleiner war.
+ //Das kann aber u.U. zu einer Endlosschleife fuehren. Damit
+ //wenigstens die Schleife unterbunden wird suchen wir nur in eine
+ //Richtung. Wenn der neue Anker nicht gefunden wird koennen wir uns
+ //immer noch vom Node einen Frame besorgen. Die Change, dass dies dann
+ //der richtige ist, ist gut.
+ const bool bNext = aOldIdx < aNewIdx;
+ // consider the case that at found anchor frame candidate already a
+ // fly frame of the given fly format is registered.
+ // consider, that <pCntnt> is the already
+ // the new anchor frame.
+ bool bFound( aOldIdx == aNewIdx );
+ while ( pCntnt && !bFound )
+ {
+ do
+ {
+ if ( bNext )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ else
+ pCntnt = pCntnt->GetPrevCntntFrm();
+ } while ( pCntnt &&
+ !( bBodyFtn == ( pCntnt->IsInDocBody() ||
+ pCntnt->IsInFtn() ) ) );
+ if ( pCntnt )
+ aOldIdx = *pCntnt->GetNode();
+
+ // check, if at found anchor frame candidate already a fly frame
+ // of the given fly frame format is registered.
+ bFound = aOldIdx == aNewIdx;
+ if ( bFound && pCntnt->GetDrawObjs() )
+ {
+ SwFrmFmt* pMyFlyFrmFmt( &GetFrmFmt() );
+ SwSortedObjs &rObjs = *pCntnt->GetDrawObjs();
+ for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
+ {
+ SwFlyFrm* pFlyFrm = dynamic_cast<SwFlyFrm*>(rObjs[i]);
+ if ( pFlyFrm &&
+ &(pFlyFrm->GetFrmFmt()) == pMyFlyFrmFmt )
+ {
+ bFound = false;
+ break;
+ }
+ }
+ }
+ }
+ if ( !pCntnt )
+ {
+ SwCntntNode *pNode = aNewIdx.GetNode().GetCntntNode();
+ pCntnt = pNode->getLayoutFrm( getRootFrm(), &pOldAnchor->Frm().Pos(), 0, sal_False );
+ OSL_ENSURE( pCntnt, "Neuen Anker nicht gefunden" );
+ }
+ //Flys haengen niemals an einem Follow sondern immer am
+ //Master, den suchen wir uns jetzt.
+ SwCntntFrm* pFlow = pCntnt;
+ while ( pFlow->IsFollow() )
+ pFlow = pFlow->FindMaster();
+ pCntnt = pFlow;
+
+ //und schwupp angehaengt das teil...
+ pCntnt->AppendFly( this );
+ if ( pOldPage && pOldPage != FindPageFrm() )
+ NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
+
+ //Fix(3495)
+ _InvalidatePos();
+ InvalidatePage();
+ SetNotifyBack();
+ // #i28701# - reset member <maLastCharRect> and
+ // <mnLastTopOfLine> for to-character anchored objects.
+ ClearCharRectAndTopOfLine();
+ }
+ else
+ SwFlyFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::MakeAll()
+|*
+|* Beschreibung Bei einem Absatzgebunden Fly kann es durchaus sein,
+|* das der Anker auf die Veraenderung des Flys reagiert. Auf diese
+|* Reaktion hat der Fly natuerlich auch wieder zu reagieren.
+|* Leider kann dies zu Oszillationen fuehren z.b. Der Fly will nach
+|* unten, dadurch kann der Inhalt nach oben, der TxtFrm wird kleiner,
+|* der Fly muss wieder hoeher woduch der Text wieder nach unten
+|* verdraengt wird...
+|* Um derartige Oszillationen zu vermeiden, wird ein kleiner Positions-
+|* stack aufgebaut. Wenn der Fly ein Position erreicht, die er bereits
+|* einmal einnahm, so brechen wir den Vorgang ab. Um keine Risiken
+|* einzugehen, wird der Positionsstack so aufgebaut, dass er fuenf
+|* Positionen zurueckblickt.
+|* Wenn der Stack ueberlaeuft, wird ebenfalls abgebrochen.
+|* Der Abbruch fuer dazu, dass der Fly am Ende eine unguenste Position
+|* einnimmt. Damit es nicht durch einen wiederholten Aufruf von
+|* Aussen zu einer 'grossen Oszillation' kommen kann wird im Abbruch-
+|* fall das Attribut des Rahmens auf automatische Ausrichtung oben
+|* eingestellt.
+|*
+|*************************************************************************/
+//Wir brauchen ein Paar Hilfsklassen zur Kontrolle der Ozillation und ein paar
+//Funktionen um die Uebersicht zu gewaehrleisten.
+// #i3317# - re-factoring of the position stack
+class SwOszControl
+{
+ static const SwFlyFrm *pStk1;
+ static const SwFlyFrm *pStk2;
+ static const SwFlyFrm *pStk3;
+ static const SwFlyFrm *pStk4;
+ static const SwFlyFrm *pStk5;
+
+ const SwFlyFrm *pFly;
+ // #i3317#
+ sal_uInt8 mnPosStackSize;
+ std::vector<Point*> maObjPositions;
+
+public:
+ SwOszControl( const SwFlyFrm *pFrm );
+ ~SwOszControl();
+ bool ChkOsz();
+ static sal_Bool IsInProgress( const SwFlyFrm *pFly );
+};
+const SwFlyFrm *SwOszControl::pStk1 = 0;
+const SwFlyFrm *SwOszControl::pStk2 = 0;
+const SwFlyFrm *SwOszControl::pStk3 = 0;
+const SwFlyFrm *SwOszControl::pStk4 = 0;
+const SwFlyFrm *SwOszControl::pStk5 = 0;
+
+SwOszControl::SwOszControl( const SwFlyFrm *pFrm )
+ : pFly( pFrm ),
+ // #i3317#
+ mnPosStackSize( 20 )
+{
+ if ( !SwOszControl::pStk1 )
+ SwOszControl::pStk1 = pFly;
+ else if ( !SwOszControl::pStk2 )
+ SwOszControl::pStk2 = pFly;
+ else if ( !SwOszControl::pStk3 )
+ SwOszControl::pStk3 = pFly;
+ else if ( !SwOszControl::pStk4 )
+ SwOszControl::pStk4 = pFly;
+ else if ( !SwOszControl::pStk5 )
+ SwOszControl::pStk5 = pFly;
+}
+
+SwOszControl::~SwOszControl()
+{
+ if ( SwOszControl::pStk1 == pFly )
+ SwOszControl::pStk1 = 0;
+ else if ( SwOszControl::pStk2 == pFly )
+ SwOszControl::pStk2 = 0;
+ else if ( SwOszControl::pStk3 == pFly )
+ SwOszControl::pStk3 = 0;
+ else if ( SwOszControl::pStk4 == pFly )
+ SwOszControl::pStk4 = 0;
+ else if ( SwOszControl::pStk5 == pFly )
+ SwOszControl::pStk5 = 0;
+ // #i3317#
+ while ( !maObjPositions.empty() )
+ {
+ Point* pPos = maObjPositions.back();
+ delete pPos;
+
+ maObjPositions.pop_back();
+ }
+}
+
+sal_Bool SwOszControl::IsInProgress( const SwFlyFrm *pFly )
+{
+ if ( SwOszControl::pStk1 && !pFly->IsLowerOf( SwOszControl::pStk1 ) )
+ return sal_True;
+ if ( SwOszControl::pStk2 && !pFly->IsLowerOf( SwOszControl::pStk2 ) )
+ return sal_True;
+ if ( SwOszControl::pStk3 && !pFly->IsLowerOf( SwOszControl::pStk3 ) )
+ return sal_True;
+ if ( SwOszControl::pStk4 && !pFly->IsLowerOf( SwOszControl::pStk4 ) )
+ return sal_True;
+ if ( SwOszControl::pStk5 && !pFly->IsLowerOf( SwOszControl::pStk5 ) )
+ return sal_True;
+ return sal_False;
+}
+
+bool SwOszControl::ChkOsz()
+{
+ bool bOscillationDetected = false;
+
+ if ( maObjPositions.size() == mnPosStackSize )
+ {
+ // position stack is full -> oscillation
+ bOscillationDetected = true;
+ }
+ else
+ {
+ Point* pNewObjPos = new Point( pFly->GetObjRect().Pos() );
+ for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
+ aObjPosIter != maObjPositions.end();
+ ++aObjPosIter )
+ {
+ if ( *(pNewObjPos) == *(*aObjPosIter) )
+ {
+ // position already occurred -> oscillation
+ bOscillationDetected = true;
+ delete pNewObjPos;
+ break;
+ }
+ }
+ if ( !bOscillationDetected )
+ {
+ maObjPositions.push_back( pNewObjPos );
+ }
+ }
+
+ return bOscillationDetected;
+}
+
+void SwFlyAtCntFrm::MakeAll()
+{
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !SwOszControl::IsInProgress( this ) && !IsLocked() && !IsColLocked() )
+ {
+ // #i28701# - use new method <GetPageFrm()>
+ if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
+ {
+ SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
+ SwPageFrm *pTmpPage = pFly ? pFly->FindPageFrm() : NULL;
+ if( pTmpPage )
+ pTmpPage->AppendFlyToPage( this );
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ if( GetPageFrm() )
+ {
+ bSetCompletePaintOnInvalidate = sal_True;
+ {
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize();
+ if( rFrmSz.GetHeightPercent() != 0xFF &&
+ rFrmSz.GetHeightPercent() >= 100 )
+ {
+ pFmt->LockModify();
+ SwFmtSurround aMain( pFmt->GetSurround() );
+ if ( aMain.GetSurround() == SURROUND_NONE )
+ {
+ aMain.SetSurround( SURROUND_THROUGHT );
+ pFmt->SetFmtAttr( aMain );
+ }
+ pFmt->UnlockModify();
+ }
+ }
+
+ SwOszControl aOszCntrl( this );
+
+ // #i43255#
+ // #i50356# - format the anchor frame, which
+ // contains the anchor position. E.g., for at-character anchored
+ // object this can be the follow frame of the anchor frame.
+ const bool bFormatAnchor =
+ !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
+ !ConsiderObjWrapInfluenceOnObjPos() &&
+ !ConsiderObjWrapInfluenceOfOtherObjs();
+
+ const SwFrm* pFooter = GetAnchorFrm()->FindFooterOrHeader();
+ if( pFooter && !pFooter->IsFooterFrm() )
+ pFooter = NULL;
+ bool bOsz = false;
+ sal_Bool bExtra = Lower() && Lower()->IsColumnFrm();
+ // #i3317# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to its
+ // overlapping with a previous column.
+ bool bConsiderWrapInfluenceDueToOverlapPrevCol( false );
+ // #i35911# - boolean, to apply temporarly the
+ // 'straightforward positioning process' for the frame due to fact
+ // that it causes the complete content of its layout environment
+ // to move forward.
+ // #i40444# - extend usage of this boolean:
+ // apply temporarly the 'straightforward positioning process' for
+ // the frame due to the fact that the frame clears the area for
+ // the anchor frame, thus it has to move forward.
+ bool bConsiderWrapInfluenceDueToMovedFwdAnchor( false );
+ do {
+ SWRECTFN( this )
+ Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ SwFlyFreeFrm::MakeAll();
+ const bool bPosChgDueToOwnFormat =
+ aOldPos != (Frm().*fnRect->fnGetPos)();
+ // #i3317#
+ if ( !ConsiderObjWrapInfluenceOnObjPos() &&
+ OverlapsPrevColumn() )
+ {
+ bConsiderWrapInfluenceDueToOverlapPrevCol = true;
+ }
+ // #i28701# - no format of anchor frame, if
+ // wrapping style influence is considered on object positioning
+ if ( bFormatAnchor )
+ {
+ SwTxtFrm* pAnchPosAnchorFrm =
+ dynamic_cast<SwTxtFrm*>(GetAnchorFrmContainingAnchPos());
+ OSL_ENSURE( pAnchPosAnchorFrm,
+ "<SwFlyAtCntFrm::MakeAll()> - anchor frame of wrong type -> crash" );
+ // #i58182# - For the usage of new method
+ // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)>
+ // to check move forward of anchor frame due to the object
+ // positioning it's needed to know, if the object is anchored
+ // at the master frame before the anchor frame is formatted.
+ const bool bAnchoredAtMaster( !pAnchPosAnchorFrm->IsFollow() );
+
+ // #i56300#
+ // perform complete format of anchor text frame and its
+ // previous frames, which have become invalid due to the
+ // fly frame format.
+ SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( *pAnchPosAnchorFrm );
+ // #i35911#
+ // #i40444#
+ // #i58182# - usage of new method
+ // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)>
+ sal_uInt32 nToPageNum( 0L );
+ bool bDummy( false );
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
+ *this, GetPageFrm()->GetPhyPageNum(),
+ bAnchoredAtMaster, nToPageNum, bDummy ) )
+ {
+ bConsiderWrapInfluenceDueToMovedFwdAnchor = true;
+ // mark anchor text frame
+ // directly, that it is moved forward by object positioning.
+ SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
+ bool bInsert( true );
+ sal_uInt32 nAnchorFrmToPageNum( 0L );
+ const SwDoc& rDoc = *(GetFrmFmt().GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, *pAnchorTxtFrm, nAnchorFrmToPageNum ) )
+ {
+ if ( nAnchorFrmToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, *pAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, *pAnchorTxtFrm,
+ nToPageNum );
+ }
+ }
+ }
+
+ if ( aOldPos != (Frm().*fnRect->fnGetPos)() ||
+ ( !GetValidPosFlag() &&
+ ( pFooter || bPosChgDueToOwnFormat ) ) )
+ {
+ bOsz = aOszCntrl.ChkOsz();
+
+ // special loop prevention for dedicated document:
+ if ( bOsz &&
+ HasFixSize() && IsClipped() &&
+ GetAnchorFrm()->GetUpper()->IsCellFrm() )
+ {
+ SwFrmFmt* pFmt = GetFmt();
+ const SwFmtFrmSize& rFrmSz = pFmt->GetFrmSize();
+ if ( rFrmSz.GetWidthPercent() &&
+ rFrmSz.GetHeightPercent() == 0xFF )
+ {
+ SwFmtSurround aSurround( pFmt->GetSurround() );
+ if ( aSurround.GetSurround() == SURROUND_NONE )
+ {
+ pFmt->LockModify();
+ aSurround.SetSurround( SURROUND_THROUGHT );
+ pFmt->SetFmtAttr( aSurround );
+ pFmt->UnlockModify();
+ bOsz = false;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwFlyAtCntFrm::MakeAll()> - special loop prevention for dedicated document of b6403541 applied" );
+#endif
+ }
+ }
+ }
+ }
+
+ if ( bExtra && Lower() && !Lower()->GetValidPosFlag() )
+ {
+ // Wenn ein mehrspaltiger Rahmen wg. Positionswechsel ungueltige
+ // Spalten hinterlaesst, so drehen wir lieber hier eine weitere
+ // Runde und formatieren unseren Inhalt via FormatWidthCols nochmal.
+ _InvalidateSize();
+ bExtra = sal_False; // Sicherhaltshalber gibt es nur eine Ehrenrunde.
+ }
+ } while ( !IsValid() && !bOsz &&
+ // #i3317#
+ !bConsiderWrapInfluenceDueToOverlapPrevCol &&
+ // #i40444#
+ !bConsiderWrapInfluenceDueToMovedFwdAnchor &&
+ GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) );
+
+ // #i3317# - instead of attribute change apply
+ // temporarly the 'straightforward positioning process'.
+ // #i80924#
+ // handle special case during splitting of table rows
+ if ( bConsiderWrapInfluenceDueToMovedFwdAnchor &&
+ GetAnchorFrm()->IsInTab() &&
+ GetAnchorFrm()->IsInFollowFlowRow() )
+ {
+ const SwFrm* pCellFrm = GetAnchorFrm();
+ while ( pCellFrm && !pCellFrm->IsCellFrm() )
+ {
+ pCellFrm = pCellFrm->GetUpper();
+ }
+ if ( pCellFrm )
+ {
+ SWRECTFN( pCellFrm )
+ if ( (pCellFrm->Frm().*fnRect->fnGetTop)() == 0 &&
+ (pCellFrm->Frm().*fnRect->fnGetHeight)() == 0 )
+ {
+ bConsiderWrapInfluenceDueToMovedFwdAnchor = false;
+ }
+ }
+ }
+ if ( bOsz || bConsiderWrapInfluenceDueToOverlapPrevCol ||
+ // #i40444#
+ bConsiderWrapInfluenceDueToMovedFwdAnchor )
+ {
+ SetTmpConsiderWrapInfluence( true );
+ SetRestartLayoutProcess( true );
+ SetTmpConsiderWrapInfluenceOfOtherObjs( true );
+ }
+ bSetCompletePaintOnInvalidate = sal_False;
+ }
+ }
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+
+ #i28701#
+*/
+bool SwFlyAtCntFrm::IsFormatPossible() const
+{
+ return SwFlyFreeFrm::IsFormatPossible() &&
+ !SwOszControl::IsInProgress( this );
+}
+
+/*************************************************************************
+|*
+|* FindAnchor() und Hilfsfunktionen.
+|*
+|* Beschreibung: Sucht ausgehend von pOldAnch einen Anker fuer
+|* Absatzgebundene Objekte.
+|* Wird beim Draggen von Absatzgebundenen Objekten zur Ankeranzeige sowie
+|* fuer Ankerwechsel benoetigt.
+|*
+|*************************************************************************/
+
+class SwDistance
+{
+public:
+ SwTwips nMain, nSub;
+ SwDistance() { nMain = nSub = 0; }
+ SwDistance& operator=( const SwDistance &rTwo )
+ { nMain = rTwo.nMain; nSub = rTwo.nSub; return *this; }
+ sal_Bool operator<( const SwDistance& rTwo )
+ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && nSub &&
+ rTwo.nSub && nSub < rTwo.nSub ); }
+ sal_Bool operator<=( const SwDistance& rTwo )
+ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && ( !nSub ||
+ !rTwo.nSub || nSub <= rTwo.nSub ) ); }
+};
+
+const SwFrm * MA_FASTCALL lcl_CalcDownDist( SwDistance &rRet,
+ const Point &rPt,
+ const SwCntntFrm *pCnt )
+{
+ rRet.nSub = 0;
+ //Wenn der Point direkt innerhalb des Cnt steht ist die Sache klar und
+ //der Cntnt hat automatisch eine Entfernung von 0
+ if ( pCnt->Frm().IsInside( rPt ) )
+ {
+ rRet.nMain = 0;
+ return pCnt;
+ }
+ else
+ {
+ const SwLayoutFrm *pUp = pCnt->IsInTab() ? pCnt->FindTabFrm()->GetUpper() : pCnt->GetUpper();
+ // einspaltige Bereiche muessen zu ihrem Upper durchschalten
+ while( pUp->IsSctFrm() )
+ pUp = pUp->GetUpper();
+ const bool bVert = pUp->IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const bool bVertL2R = pUp->IsVertLR();
+
+ //Dem Textflus folgen.
+ // #i70582#
+ // --> OD 2009-03-05 - adopted for Support for Classical Mongolian Script
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if ( pUp->Frm().IsInside( rPt ) )
+ {
+ // <rPt> point is inside environment of given content frame
+ // #i70582#
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ rRet.nMain = rPt.X() - nTopForObjPos;
+ else
+ rRet.nMain = nTopForObjPos - rPt.X();
+ }
+ else
+ rRet.nMain = rPt.Y() - nTopForObjPos;
+ return pCnt;
+ }
+ else if ( rPt.Y() <= pUp->Frm().Top() )
+ {
+ // <rPt> point is above environment of given content frame
+ // correct for vertical layout?
+ rRet.nMain = LONG_MAX;
+ }
+ else if( rPt.X() < pUp->Frm().Left() &&
+ rPt.Y() <= ( bVert ? pUp->Frm().Top() : pUp->Frm().Bottom() ) )
+ {
+ // <rPt> point is left of environment of given content frame
+ // seems not to be correct for vertical layout!?
+ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_False, pCnt );
+ if( !pLay ||
+ (bVert && (pLay->Frm().Top() + pLay->Prt().Bottom()) <rPt.Y())||
+ (!bVert && (pLay->Frm().Left() + pLay->Prt().Right())<rPt.X()) )
+ {
+ // <rPt> point is in left border of environment
+ // #i70582#
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ rRet.nMain = rPt.X() - nTopForObjPos;
+ else
+ rRet.nMain = nTopForObjPos - rPt.X();
+ }
+ else
+ rRet.nMain = rPt.Y() - nTopForObjPos;
+ return pCnt;
+ }
+ else
+ rRet.nMain = LONG_MAX;
+ }
+ else
+ {
+ // Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ rRet.nMain = bVert
+ ? ( bVertL2R
+ ? ( (pUp->Frm().Left() + pUp->Prt().Right()) - nTopForObjPos )
+ : ( nTopForObjPos - (pUp->Frm().Left() + pUp->Prt().Left() ) ) )
+ : ( (pUp->Frm().Top() + pUp->Prt().Bottom()) - nTopForObjPos );
+
+ const SwFrm *pPre = pCnt;
+ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt );
+ SwTwips nFrmTop = 0;
+ SwTwips nPrtHeight = 0;
+ sal_Bool bSct = sal_False;
+ const SwSectionFrm *pSect = pUp->FindSctFrm();
+ if( pSect )
+ {
+ rRet.nSub = rRet.nMain;
+ rRet.nMain = 0;
+ }
+ if( pSect && !pSect->IsAnLower( pLay ) )
+ {
+ bSct = sal_False;
+ const SwSectionFrm* pNxtSect = pLay ? pLay->FindSctFrm() : 0;
+ if( pSect->IsAnFollow( pNxtSect ) )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ nFrmTop = pLay->Frm().Left();
+ else
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ pSect = pNxtSect;
+ }
+ else
+ {
+ pLay = pSect->GetUpper();
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pSect->Frm().Right();
+ nPrtHeight = pLay->Frm().Left() + pLay->Prt().Left()
+ + pLay->Prt().Width() - pSect->Frm().Left()
+ - pSect->Frm().Width();
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Left();
+ nPrtHeight = pSect->Frm().Left() - pLay->Frm().Left()
+ - pLay->Prt().Left();
+ }
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Bottom();
+ nPrtHeight = pLay->Frm().Top() + pLay->Prt().Top()
+ + pLay->Prt().Height() - pSect->Frm().Top()
+ - pSect->Frm().Height();
+ }
+ pSect = 0;
+ }
+ }
+ else if( pLay )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ bSct = 0 != pSect;
+ }
+ while ( pLay && !pLay->Frm().IsInside( rPt ) &&
+ ( pLay->Frm().Top() <= rPt.Y() || pLay->IsInFly() ||
+ ( pLay->IsInSct() &&
+ pLay->FindSctFrm()->GetUpper()->Frm().Top() <= rPt.Y())) )
+ {
+ if ( pLay->IsFtnContFrm() )
+ {
+ if ( !((SwLayoutFrm*)pLay)->Lower() )
+ {
+ SwFrm *pDel = (SwFrm*)pLay;
+ pDel->Cut();
+ delete pDel;
+ return pPre;
+ }
+ return 0;
+ }
+ else
+ {
+ if( bSct || pSect )
+ rRet.nSub += nPrtHeight;
+ else
+ rRet.nMain += nPrtHeight;
+ pPre = pLay;
+ pLay = pLay->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt );
+ if( pSect && !pSect->IsAnLower( pLay ) )
+ { // If we're leaving a SwSectionFrm, the next Leaf-Frm
+ // is the part of the upper below the SectionFrm.
+ const SwSectionFrm* pNxtSect = pLay ?
+ pLay->FindSctFrm() : NULL;
+ bSct = sal_False;
+ if( pSect->IsAnFollow( pNxtSect ) )
+ {
+ pSect = pNxtSect;
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ }
+ else
+ {
+ pLay = pSect->GetUpper();
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pSect->Frm().Right();
+ nPrtHeight = pLay->Frm().Left()+pLay->Prt().Left()
+ + pLay->Prt().Width() - pSect->Frm().Left()
+ - pSect->Frm().Width();
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Left();
+ nPrtHeight = pSect->Frm().Left() -
+ pLay->Frm().Left() - pLay->Prt().Left();
+ }
+ }
+ else
+ {
+ nFrmTop = pSect->Frm().Bottom();
+ nPrtHeight = pLay->Frm().Top()+pLay->Prt().Top()
+ + pLay->Prt().Height() - pSect->Frm().Top()
+ - pSect->Frm().Height();
+ }
+ pSect = 0;
+ }
+ }
+ else if( pLay )
+ {
+ if( pLay->IsVertical() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( pLay->IsVertLR() )
+ {
+ nFrmTop = pLay->Frm().Left();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width();
+ nPrtHeight = pLay->Prt().Width();
+ }
+ }
+ else
+ {
+ nFrmTop = pLay->Frm().Top();
+ nPrtHeight = pLay->Prt().Height();
+ }
+ bSct = 0 != pSect;
+ }
+ }
+ }
+ if ( pLay )
+ {
+ if ( pLay->Frm().IsInside( rPt ) )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwTwips nDiff = pLay->IsVertical() ? ( pLay->IsVertLR() ? ( rPt.X() - nFrmTop ) : ( nFrmTop - rPt.X() ) )
+ : ( rPt.Y() - nFrmTop );
+ if( bSct || pSect )
+ rRet.nSub += nDiff;
+ else
+ rRet.nMain += nDiff;
+ }
+ if ( pLay->IsFtnContFrm() && !((SwLayoutFrm*)pLay)->Lower() )
+ {
+ SwFrm *pDel = (SwFrm*)pLay;
+ pDel->Cut();
+ delete pDel;
+ return 0;
+ }
+ return pLay;
+ }
+ else
+ rRet.nMain = LONG_MAX;
+ }
+ }
+ return 0;
+}
+
+sal_uLong MA_FASTCALL lcl_FindCntDiff( const Point &rPt, const SwLayoutFrm *pLay,
+ const SwCntntFrm *& rpCnt,
+ const sal_Bool bBody, const sal_Bool bFtn )
+{
+ //Sucht unterhalb von pLay den dichtesten Cnt zum Point. Der Bezugspunkt
+ //der Cntnts ist immer die linke obere Ecke.
+ //Der Cnt soll moeglichst ueber dem Point liegen.
+
+#if OSL_DEBUG_LEVEL > 1
+ Point arPoint( rPt );
+#endif
+
+ rpCnt = 0;
+ sal_uLong nDistance = ULONG_MAX;
+ sal_uLong nNearest = ULONG_MAX;
+ const SwCntntFrm *pCnt = pLay->ContainsCntnt();
+
+ while ( pCnt && (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn()))
+ {
+ pCnt = pCnt->GetNextCntntFrm();
+ if ( !pLay->IsAnLower( pCnt ) )
+ pCnt = 0;
+ }
+ const SwCntntFrm *pNearest = pCnt;
+ if ( pCnt )
+ {
+ do
+ {
+ //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
+ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
+ sal_uInt32 dX = Max( pCnt->Frm().Left(), rPt.X() ) -
+ Min( pCnt->Frm().Left(), rPt.X() ),
+ dY = Max( pCnt->Frm().Top(), rPt.Y() ) -
+ Min( pCnt->Frm().Top(), rPt.Y() );
+ BigInt dX1( dX ), dY1( dY );
+ dX1 *= dX1; dY1 *= dY1;
+ const sal_uLong nDiff = ::SqRt( dX1 + dY1 );
+ if ( pCnt->Frm().Top() <= rPt.Y() )
+ {
+ if ( nDiff < nDistance )
+ { //Der ist dichter dran
+ nDistance = nNearest = nDiff;
+ rpCnt = pNearest = pCnt;
+ }
+ }
+ else if ( nDiff < nNearest )
+ {
+ nNearest = nDiff;
+ pNearest = pCnt;
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ while ( pCnt &&
+ (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn()))
+ pCnt = pCnt->GetNextCntntFrm();
+
+ } while ( pCnt && pLay->IsAnLower( pCnt ) );
+ }
+ if ( nDistance == ULONG_MAX )
+ { rpCnt = pNearest;
+ return nNearest;
+ }
+ return nDistance;
+}
+
+const SwCntntFrm * MA_FASTCALL lcl_FindCnt( const Point &rPt, const SwCntntFrm *pCnt,
+ const sal_Bool bBody, const sal_Bool bFtn )
+{
+ //Sucht ausgehen von pCnt denjenigen CntntFrm, dessen linke obere
+ //Ecke am dichtesten am Point liegt.
+ //Liefert _immer_ einen CntntFrm zurueck.
+
+ //Zunaechst wird versucht den dichtesten Cntnt innerhalt derjenigen
+ //Seite zu suchen innerhalb derer der Cntnt steht.
+ //Ausgehend von der Seite muessen die Seiten in beide
+ //Richtungen beruecksichtigt werden.
+ //Falls moeglich wird ein Cntnt geliefert, dessen Y-Position ueber der
+ //des Point sitzt.
+ const SwCntntFrm *pRet, *pNew;
+ const SwLayoutFrm *pLay = pCnt->FindPageFrm();
+ sal_uLong nDist;
+
+ nDist = ::lcl_FindCntDiff( rPt, pLay, pNew, bBody, bFtn );
+ if ( pNew )
+ pRet = pNew;
+ else
+ { pRet = pCnt;
+ nDist = ULONG_MAX;
+ }
+ const SwCntntFrm *pNearest = pRet;
+ sal_uLong nNearest = nDist;
+
+ if ( pLay )
+ {
+ const SwLayoutFrm *pPge = pLay;
+ sal_uLong nOldNew = ULONG_MAX;
+ for ( sal_uInt16 i = 0; pPge->GetPrev() && (i < 3); ++i )
+ {
+ pPge = (SwLayoutFrm*)pPge->GetPrev();
+ const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn );
+ if ( nNew < nDist )
+ {
+ if ( pNew->Frm().Top() <= rPt.Y() )
+ {
+ pRet = pNearest = pNew;
+ nDist = nNearest = nNew;
+ }
+ else if ( nNew < nNearest )
+ {
+ pNearest = pNew;
+ nNearest = nNew;
+ }
+ }
+ else if ( nOldNew != ULONG_MAX && nNew > nOldNew )
+ break;
+ else
+ nOldNew = nNew;
+
+ }
+ pPge = pLay;
+ nOldNew = ULONG_MAX;
+ for ( sal_uInt16 j = 0; pPge->GetNext() && (j < 3); ++j )
+ {
+ pPge = (SwLayoutFrm*)pPge->GetNext();
+ const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn );
+ if ( nNew < nDist )
+ {
+ if ( pNew->Frm().Top() <= rPt.Y() )
+ {
+ pRet = pNearest = pNew;
+ nDist = nNearest = nNew;
+ }
+ else if ( nNew < nNearest )
+ {
+ pNearest = pNew;
+ nNearest = nNew;
+ }
+ }
+ else if ( nOldNew != ULONG_MAX && nNew > nOldNew )
+ break;
+ else
+ nOldNew = nNew;
+ }
+ }
+ if ( (pRet->Frm().Top() > rPt.Y()) )
+ return pNearest;
+ else
+ return pRet;
+}
+
+void lcl_PointToPrt( Point &rPoint, const SwFrm *pFrm )
+{
+ SwRect aTmp( pFrm->Prt() );
+ aTmp += pFrm->Frm().Pos();
+ if ( rPoint.X() < aTmp.Left() )
+ rPoint.X() = aTmp.Left();
+ else if ( rPoint.X() > aTmp.Right() )
+ rPoint.X() = aTmp.Right();
+ if ( rPoint.Y() < aTmp.Top() )
+ rPoint.Y() = aTmp.Top();
+ else if ( rPoint.Y() > aTmp.Bottom() )
+ rPoint.Y() = aTmp.Bottom();
+
+}
+
+const SwCntntFrm *FindAnchor( const SwFrm *pOldAnch, const Point &rNew,
+ const sal_Bool bBodyOnly )
+{
+ //Zu der angegebenen DokumentPosition wird der dichteste Cnt im
+ //Textfluss gesucht. AusgangsFrm ist der uebergebene Anker.
+ const SwCntntFrm* pCnt;
+ if ( pOldAnch->IsCntntFrm() )
+ {
+ pCnt = (const SwCntntFrm*)pOldAnch;
+ }
+ else
+ {
+ Point aTmp( rNew );
+ SwLayoutFrm *pTmpLay = (SwLayoutFrm*)pOldAnch;
+ if( pTmpLay->IsRootFrm() )
+ {
+ SwRect aTmpRect( aTmp, Size(0,0) );
+ pTmpLay = (SwLayoutFrm*)::FindPage( aTmpRect, pTmpLay->Lower() );
+ }
+ pCnt = pTmpLay->GetCntntPos( aTmp, sal_False, bBodyOnly );
+ }
+
+ //Beim Suchen darauf achten, dass die Bereiche sinnvoll erhalten
+ //bleiben. D.h. in diesem Fall nicht in Header/Footer hinein und
+ //nicht aus Header/Footer hinaus.
+ const sal_Bool bBody = pCnt->IsInDocBody() || bBodyOnly;
+ const sal_Bool bFtn = !bBodyOnly && pCnt->IsInFtn();
+
+ Point aNew( rNew );
+ if ( bBody )
+ {
+ //#38848 Vom Seitenrand in den Body ziehen.
+ const SwFrm *pPage = pCnt->FindPageFrm();
+ ::lcl_PointToPrt( aNew, pPage->GetUpper() );
+ SwRect aTmp( aNew, Size( 0, 0 ) );
+ pPage = ::FindPage( aTmp, pPage );
+ ::lcl_PointToPrt( aNew, pPage );
+ }
+
+ if ( pCnt->IsInDocBody() == bBody && pCnt->Frm().IsInside( aNew ) )
+ return pCnt;
+ else if ( pOldAnch->IsInDocBody() || pOldAnch->IsPageFrm() )
+ {
+ //Vielleicht befindet sich der gewuenschte Anker ja auf derselben
+ //Seite wie der aktuelle Anker.
+ //So gibt es kein Problem mit Spalten.
+ Point aTmp( aNew );
+ const SwCntntFrm *pTmp = pCnt->FindPageFrm()->
+ GetCntntPos( aTmp, sal_False, sal_True, sal_False );
+ if ( pTmp && pTmp->Frm().IsInside( aNew ) )
+ return pTmp;
+ }
+
+ //Ausgehend vom Anker suche ich jetzt in beide Richtungen bis ich
+ //den jeweils dichtesten gefunden habe.
+ //Nicht die direkte Entfernung ist relevant sondern die Strecke die
+ //im Textfluss zurueckgelegt werden muss.
+ const SwCntntFrm *pUpLst;
+ const SwCntntFrm *pUpFrm = pCnt;
+ SwDistance nUp, nUpLst;
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ SwDistance nDown = nUp;
+ sal_Bool bNegAllowed = sal_True;//Einmal aus dem negativen Bereich heraus lassen.
+ do
+ {
+ pUpLst = pUpFrm; nUpLst = nUp;
+ pUpFrm = pUpLst->GetPrevCntntFrm();
+ while ( pUpFrm &&
+ (bBody != pUpFrm->IsInDocBody() || bFtn != pUpFrm->IsInFtn()))
+ pUpFrm = pUpFrm->GetPrevCntntFrm();
+ if ( pUpFrm )
+ {
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es
+ //sich weiter zu suchen.
+ if ( pUpLst->IsInTab() && pUpFrm->IsInTab() )
+ {
+ while ( pUpFrm && ((nUpLst < nUp && pUpFrm->IsInTab()) ||
+ bBody != pUpFrm->IsInDocBody()) )
+ {
+ pUpFrm = pUpFrm->GetPrevCntntFrm();
+ if ( pUpFrm )
+ ::lcl_CalcDownDist( nUp, aNew, pUpFrm );
+ }
+ }
+ }
+ if ( !pUpFrm )
+ nUp.nMain = LONG_MAX;
+ if ( nUp.nMain >= 0 && LONG_MAX != nUp.nMain )
+ {
+ bNegAllowed = sal_False;
+ if ( nUpLst.nMain < 0 ) //nicht den falschen erwischen, wenn der Wert
+ //gerade von negativ auf positiv gekippt ist.
+ { pUpLst = pUpFrm;
+ nUpLst = nUp;
+ }
+ }
+ } while ( pUpFrm && ( ( bNegAllowed && nUp.nMain < 0 ) || ( nUp <= nUpLst ) ) );
+
+ const SwCntntFrm *pDownLst;
+ const SwCntntFrm *pDownFrm = pCnt;
+ SwDistance nDownLst;
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ do
+ {
+ pDownLst = pDownFrm; nDownLst = nDown;
+ pDownFrm = pDownLst->GetNextCntntFrm();
+ while ( pDownFrm &&
+ (bBody != pDownFrm->IsInDocBody() || bFtn != pDownFrm->IsInFtn()))
+ pDownFrm = pDownFrm->GetNextCntntFrm();
+ if ( pDownFrm )
+ {
+ ::lcl_CalcDownDist( nDown, aNew, pDownFrm );
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es
+ //sich weiter zu suchen.
+ if ( pDownLst->IsInTab() && pDownFrm->IsInTab() )
+ {
+ while ( pDownFrm && ( ( nDown.nMain != LONG_MAX && nDownLst < nDownLst
+ && pDownFrm->IsInTab()) || bBody != pDownFrm->IsInDocBody() ) )
+ {
+ pDownFrm = pDownFrm->GetNextCntntFrm();
+ if ( pDownFrm )
+ ::lcl_CalcDownDist( nDown, aNew, pDownFrm );
+ if ( nDown.nMain < 0 )
+ nDown.nMain = LONG_MAX;
+ }
+ }
+ }
+ if ( !pDownFrm )
+ nDown.nMain = LONG_MAX;
+
+ } while ( pDownFrm && nDown <= nDownLst &&
+ nDown.nMain != LONG_MAX && nDownLst.nMain != LONG_MAX );
+
+ //Wenn ich in beide Richtungen keinen gefunden habe, so suche ich mir
+ //denjenigen Cntnt dessen linke obere Ecke dem Point am naechsten liegt.
+ //Eine derartige Situation tritt z.b. auf, wenn der Point nicht im Text-
+ //fluss sondern in irgendwelchen Raendern steht.
+ if ( nDownLst.nMain == LONG_MAX && nUpLst.nMain == LONG_MAX )
+ {
+ // If an OLE objects, which is contained in a fly frame
+ // is resized in inplace mode and the new Position is outside the
+ // fly frame, we do not want to leave our fly frame.
+ if ( pCnt->IsInFly() )
+ return pCnt;
+
+ return ::lcl_FindCnt( aNew, pCnt, bBody, bFtn );
+ }
+ else
+ return nDownLst < nUpLst ? pDownLst : pUpLst;
+}
+
+/*************************************************************************
+|*
+|* SwFlyAtCntFrm::SetAbsPos()
+|*
+|*************************************************************************/
+
+void SwFlyAtCntFrm::SetAbsPos( const Point &rNew )
+{
+ SwPageFrm *pOldPage = FindPageFrm();
+ const SwRect aOld( GetObjRectWithSpaces() );
+ Point aNew( rNew );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( ( GetAnchorFrm()->IsVertical() && !GetAnchorFrm()->IsVertLR() ) || GetAnchorFrm()->IsRightToLeft() )
+ aNew.X() += Frm().Width();
+ SwCntntFrm *pCnt = (SwCntntFrm*)::FindAnchor( GetAnchorFrm(), aNew );
+ if( pCnt->IsProtected() )
+ pCnt = (SwCntntFrm*)GetAnchorFrm();
+
+ SwPageFrm *pTmpPage = 0;
+ const bool bVert = pCnt->IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ const bool bVertL2R = pCnt->IsVertLR();
+ const sal_Bool bRTL = pCnt->IsRightToLeft();
+
+ if( ( !bVert != !GetAnchorFrm()->IsVertical() ) ||
+ ( !bRTL != !GetAnchorFrm()->IsRightToLeft() ) )
+ {
+ if( bVert || bRTL )
+ aNew.X() += Frm().Width();
+ else
+ aNew.X() -= Frm().Width();
+ }
+
+ if ( pCnt->IsInDocBody() )
+ {
+ //#38848 Vom Seitenrand in den Body ziehen.
+ pTmpPage = pCnt->FindPageFrm();
+ ::lcl_PointToPrt( aNew, pTmpPage->GetUpper() );
+ SwRect aTmp( aNew, Size( 0, 0 ) );
+ pTmpPage = (SwPageFrm*)::FindPage( aTmp, pTmpPage );
+ ::lcl_PointToPrt( aNew, pTmpPage );
+ }
+
+ //RelPos einstellen, nur auf Wunsch invalidieren.
+ //rNew ist eine Absolute Position. Um die RelPos korrekt einzustellen
+ //muessen wir uns die Entfernung von rNew zum Anker im Textfluss besorgen.
+//!!!!!Hier kann Optimiert werden: FindAnchor koennte die RelPos mitliefern!
+ const SwFrm *pFrm = 0;
+ SwTwips nY;
+ if ( pCnt->Frm().IsInside( aNew ) )
+ {
+ // #i70582#
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ nY = rNew.X() - nTopForObjPos;
+ else
+ nY = nTopForObjPos - rNew.X() - Frm().Width();
+ }
+ else
+ {
+ nY = rNew.Y() - nTopForObjPos;
+ }
+ }
+ else
+ {
+ SwDistance aDist;
+ pFrm = ::lcl_CalcDownDist( aDist, aNew, pCnt );
+ nY = aDist.nMain + aDist.nSub;
+ }
+
+ SwTwips nX = 0;
+
+ if ( pCnt->IsFollow() )
+ {
+ //Flys haengen niemals an einem Follow sondern immer am
+ //Master, den suchen wir uns jetzt.
+ const SwCntntFrm *pOriginal = pCnt;
+ const SwCntntFrm *pFollow = pCnt;
+ while ( pCnt->IsFollow() )
+ {
+ do
+ { pCnt = pCnt->GetPrevCntntFrm();
+ } while ( pCnt->GetFollow() != pFollow );
+ pFollow = pCnt;
+ }
+ SwTwips nDiff = 0;
+ do
+ { const SwFrm *pUp = pFollow->GetUpper();
+ if( pUp->IsVertical() )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( pUp->IsVertLR() )
+ nDiff += pUp->Prt().Width() - pFollow->GetRelPos().X();
+ else
+ nDiff += pFollow->Frm().Left() + pFollow->Frm().Width()
+ - pUp->Frm().Left() - pUp->Prt().Left();
+ }
+ else
+ nDiff += pUp->Prt().Height() - pFollow->GetRelPos().Y();
+ pFollow = pFollow->GetFollow();
+ } while ( pFollow != pOriginal );
+ nY += nDiff;
+ if( bVert )
+ nX = pCnt->Frm().Top() - pOriginal->Frm().Top();
+ else
+ nX = pCnt->Frm().Left() - pOriginal->Frm().Left();
+ }
+
+ if ( nY == LONG_MAX )
+ {
+ // #i70582#
+ const SwTwips nTopForObjPos =
+ bVert
+ ? ( bVertL2R
+ ? ( pCnt->Frm().Left() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() )
+ : ( pCnt->Frm().Left() +
+ pCnt->Frm().Width() -
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) )
+ : ( pCnt->Frm().Top() +
+ pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() );
+ if( bVert )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ if ( bVertL2R )
+ nY = rNew.X() - nTopForObjPos;
+ else
+ nY = nTopForObjPos - rNew.X();
+ }
+ else
+ {
+ nY = rNew.Y() - nTopForObjPos;
+ }
+ }
+
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtSurround& rSurround = pFmt->GetSurround();
+ const sal_Bool bWrapThrough =
+ rSurround.GetSurround() == SURROUND_THROUGHT;
+ SwTwips nBaseOfstForFly = 0;
+ const SwFrm* pTmpFrm = pFrm ? pFrm : pCnt;
+ if ( pTmpFrm->IsTxtFrm() )
+ nBaseOfstForFly =
+ ((SwTxtFrm*)pTmpFrm)->GetBaseOfstForFly( !bWrapThrough );
+
+ if( bVert )
+ {
+ if( !pFrm )
+ nX += rNew.Y() - pCnt->Frm().Top() - nBaseOfstForFly;
+ else
+ nX = rNew.Y() - pFrm->Frm().Top() - nBaseOfstForFly;
+ }
+ else
+ {
+ if( !pFrm )
+ {
+ if ( pCnt->IsRightToLeft() )
+ nX += pCnt->Frm().Right() - rNew.X() - Frm().Width() +
+ nBaseOfstForFly;
+ else
+ nX += rNew.X() - pCnt->Frm().Left() - nBaseOfstForFly;
+ }
+ else
+ {
+ if ( pFrm->IsRightToLeft() )
+ nX += pFrm->Frm().Right() - rNew.X() - Frm().Width() +
+ nBaseOfstForFly;
+ else
+ nX = rNew.X() - pFrm->Frm().Left() - nBaseOfstForFly;
+ }
+ }
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
+
+ if( pCnt != GetAnchorFrm() || ( IsAutoPos() && pCnt->IsTxtFrm() &&
+ GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE)) )
+ {
+ //Das Ankerattribut auf den neuen Cnt setzen.
+ SwFmtAnchor aAnch( pFmt->GetAnchor() );
+ SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor();
+ if( IsAutoPos() && pCnt->IsTxtFrm() )
+ {
+ SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
+ Point aPt( rNew );
+ if( pCnt->GetCrsrOfst( pPos, aPt, &eTmpState )
+ && pPos->nNode == *pCnt->GetNode() )
+ {
+ ResetLastCharRectHeight();
+ if( text::RelOrientation::CHAR == pFmt->GetVertOrient().GetRelationOrient() )
+ nY = LONG_MAX;
+ if( text::RelOrientation::CHAR == pFmt->GetHoriOrient().GetRelationOrient() )
+ nX = LONG_MAX;
+ }
+ else
+ {
+ pPos->nNode = *pCnt->GetNode();
+ pPos->nContent.Assign( pCnt->GetNode(), 0 );
+ }
+ }
+ else
+ {
+ pPos->nNode = *pCnt->GetNode();
+ pPos->nContent.Assign( pCnt->GetNode(), 0 );
+ }
+
+ // handle change of anchor node:
+ // if count of the anchor frame also change, the fly frames have to be
+ // re-created. Thus, delete all fly frames except the <this> before the
+ // anchor attribute is change and re-create them afterwards.
+ {
+ SwHandleAnchorNodeChg aHandleAnchorNodeChg( *pFmt, aAnch, this );
+ pFmt->GetDoc()->SetAttr( aAnch, *pFmt );
+ }
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ else if ( pTmpPage && pTmpPage != GetPageFrm() )
+ GetPageFrm()->MoveFly( this, pTmpPage );
+
+ const Point aRelPos = bVert ? Point( -nY, nX ) : Point( nX, nY );
+
+ ChgRelPos( aRelPos );
+
+ GetFmt()->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
+
+ if ( pOldPage != FindPageFrm() )
+ ::Notify_Background( GetVirtDrawObj(), pOldPage, aOld, PREP_FLY_LEAVE,
+ sal_False );
+}
+
+/** method to assure that anchored object is registered at the correct
+ page frame
+
+ #i28701#
+ takes over functionality of deleted method <SwFlyAtCntFrm::AssertPage()>
+*/
+void SwFlyAtCntFrm::RegisterAtCorrectPage()
+{
+ SwPageFrm* pPageFrm( 0L );
+ if ( GetVertPosOrientFrm() )
+ {
+ pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
+ }
+ if ( pPageFrm && GetPageFrm() != pPageFrm )
+ {
+ if ( GetPageFrm() )
+ GetPageFrm()->MoveFly( this, pPageFrm );
+ else
+ pPageFrm->AppendFlyToPage( this );
+ }
+}
+
+// #i26791#
+//void SwFlyAtCntFrm::MakeFlyPos()
+void SwFlyAtCntFrm::MakeObjPos()
+{
+ // if fly frame position is valid, nothing is to do. Thus, return
+ if ( bValidPos )
+ {
+ return;
+ }
+
+ // #i26791# - validate position flag here.
+ bValidPos = sal_True;
+
+ // #i35911# - no calculation of new position, if
+ // anchored object is marked that it clears its environment and its
+ // environment is already cleared.
+ // before checking for cleared environment
+ // check, if member <mpVertPosOrientFrm> is set.
+ if ( GetVertPosOrientFrm() &&
+ ClearedEnvironment() && HasClearedEnvironment() )
+ {
+ return;
+ }
+
+ // use new class to position object
+ objectpositioning::SwToCntntAnchoredObjectPosition
+ aObjPositioning( *GetVirtDrawObj() );
+ aObjPositioning.CalcPosition();
+
+ SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
+}
+
+// #i28701#
+bool SwFlyAtCntFrm::_InvalidationAllowed( const InvalidationType _nInvalid ) const
+{
+ bool bAllowed( SwFlyFreeFrm::_InvalidationAllowed( _nInvalid ) );
+
+ // forbiddance of base instance can't be over ruled.
+ if ( bAllowed )
+ {
+ if ( _nInvalid == INVALID_POS ||
+ _nInvalid == INVALID_ALL )
+ {
+ bAllowed = InvalidationOfPosAllowed();
+ }
+ }
+
+ return bAllowed;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flyincnt.cxx b/sw/source/core/layout/flyincnt.cxx
new file mode 100644
index 000000000000..3a84f4948758
--- /dev/null
+++ b/sw/source/core/layout/flyincnt.cxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "cntfrm.hxx"
+#include "doc.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include "txtfrm.hxx" //fuer IsLocked()
+#include "flyfrms.hxx"
+// OD 2004-01-19 #110582#
+#include <dflyobj.hxx>
+
+//aus FlyCnt.cxx
+void DeepCalc( const SwFrm *pFrm );
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::SwFlyInCntFrm(), ~SwFlyInCntFrm()
+|*
+|*************************************************************************/
+SwFlyInCntFrm::SwFlyInCntFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFrm( pFmt, pSib, pAnch )
+{
+ bInCnt = bInvalidLayout = bInvalidCntnt = sal_True;
+ SwTwips nRel = pFmt->GetVertOrient().GetPos();
+ // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
+ Point aRelPos;
+ if( pAnch && pAnch->IsVertical() )
+ aRelPos.X() = pAnch->IsReverse() ? nRel : -nRel;
+ else
+ aRelPos.Y() = nRel;
+ SetCurrRelPos( aRelPos );
+}
+
+SwFlyInCntFrm::~SwFlyInCntFrm()
+{
+ //und Tschuess.
+ if ( !GetFmt()->GetDoc()->IsInDtor() && GetAnchorFrm() )
+ {
+ SwRect aTmp( GetObjRectWithSpaces() );
+ SwFlyInCntFrm::NotifyBackground( FindPageFrm(), aTmp, PREP_FLY_LEAVE );
+ }
+}
+
+// --> OD 2004-06-29 #i28701#
+TYPEINIT1(SwFlyInCntFrm,SwFlyFrm);
+// <--
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::SetRefPoint(),
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::SetRefPoint( const Point& rPoint,
+ const Point& rRelAttr,
+ const Point& rRelPos )
+{
+ // OD 2004-05-27 #i26791# - member <aRelPos> moved to <SwAnchoredObject>
+ OSL_ENSURE( rPoint != aRef || rRelAttr != GetCurrRelPos(), "SetRefPoint: no change" );
+ SwFlyNotify *pNotify = NULL;
+ // No notify at a locked fly frame, if a fly frame is locked, there's
+ // already a SwFlyNotify object on the stack (MakeAll).
+ if( !IsLocked() )
+ pNotify = new SwFlyNotify( this );
+ aRef = rPoint;
+ SetCurrRelPos( rRelAttr );
+ SWRECTFN( GetAnchorFrm() )
+ (Frm().*fnRect->fnSetPos)( rPoint + rRelPos );
+ // --> OD 2006-08-25 #i68520#
+ InvalidateObjRectWithSpaces();
+ // <--
+ if( pNotify )
+ {
+ InvalidatePage();
+ bValidPos = sal_False;
+ bInvalid = sal_True;
+ Calc();
+ delete pNotify;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::Modify()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_Bool bCallPrepare = sal_False;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ if( RES_ATTRSET_CHG == nWhich )
+ {
+ if( SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->
+ GetItemState( RES_SURROUND, sal_False ) ||
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->
+ GetItemState( RES_FRMMACRO, sal_False ) )
+ {
+ SwAttrSetChg aOld( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNew( *(SwAttrSetChg*)pNew );
+
+ aOld.ClearItem( RES_SURROUND );
+ aNew.ClearItem( RES_SURROUND );
+ aOld.ClearItem( RES_FRMMACRO );
+ aNew.ClearItem( RES_FRMMACRO );
+ if( aNew.Count() )
+ {
+ SwFlyFrm::Modify( &aOld, &aNew );
+ bCallPrepare = sal_True;
+ }
+ }
+ else if( ((SwAttrSetChg*)pNew)->GetChgSet()->Count())
+ {
+ SwFlyFrm::Modify( pOld, pNew );
+ bCallPrepare = sal_True;
+ }
+ }
+ else if( nWhich != RES_SURROUND && RES_FRMMACRO != nWhich )
+ {
+ SwFlyFrm::Modify( pOld, pNew );
+ bCallPrepare = sal_True;
+ }
+
+ if ( bCallPrepare && GetAnchorFrm() )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, GetFmt() );
+}
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::Format()
+|*
+|* Beschreibung: Hier wird der Inhalt initial mit Formatiert.
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ if ( !Frm().Height() )
+ {
+ Lock(); //nicht hintenherum den Anker formatieren.
+ SwCntntFrm *pCntnt = ContainsCntnt();
+ while ( pCntnt )
+ { pCntnt->Calc();
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ Unlock();
+ }
+ SwFlyFrm::Format( pAttrs );
+}
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::MakeFlyPos()
+|*
+|* Beschreibung Im Unterschied zu anderen Frms wird hier nur die
+|* die RelPos berechnet. Die absolute Position wird ausschliesslich
+|* per SetAbsPos errechnet.
+|*
+|*************************************************************************/
+// OD 2004-03-23 #i26791#
+//void SwFlyInCntFrm::MakeFlyPos()
+void SwFlyInCntFrm::MakeObjPos()
+{
+ if ( !bValidPos )
+ {
+ bValidPos = sal_True;
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+ //Und ggf. noch die aktuellen Werte im Format updaten, dabei darf
+ //zu diesem Zeitpunkt natuerlich kein Modify verschickt werden.
+ const bool bVert = GetAnchorFrm()->IsVertical();
+ const bool bRev = GetAnchorFrm()->IsReverse();
+ SwTwips nOld = rVert.GetPos();
+ SwTwips nAct = bVert ? -GetCurrRelPos().X() : GetCurrRelPos().Y();
+ if( bRev )
+ nAct = -nAct;
+ if( nAct != nOld )
+ {
+ SwFmtVertOrient aVert( rVert );
+ aVert.SetPos( nAct );
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aVert );
+ pFmt->UnlockModify();
+ }
+ }
+}
+
+// --> OD 2004-12-02 #115759#
+void SwFlyInCntFrm::_ActionOnInvalidation( const InvalidationType _nInvalid )
+{
+ if ( INVALID_POS == _nInvalid || INVALID_ALL == _nInvalid )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
+}
+// <--
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::NotifyBackground()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::NotifyBackground( SwPageFrm *, const SwRect& rRect,
+ PrepareHint eHint)
+{
+ if ( eHint == PREP_FLY_ATTR_CHG )
+ AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG );
+ else
+ AnchorFrm()->Prepare( eHint, (void*)&rRect );
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::GetRelPos()
+|*
+|*************************************************************************/
+const Point SwFlyInCntFrm::GetRelPos() const
+{
+ Calc();
+ return GetCurrRelPos();
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::RegistFlys()
+{
+ // vgl. SwRowFrm::RegistFlys()
+ SwPageFrm *pPage = FindPageFrm();
+ OSL_ENSURE( pPage, "Flys ohne Seite anmelden?" );
+ ::RegistFlys( pPage, this );
+}
+
+/*************************************************************************
+|*
+|* SwFlyInCntFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwFlyInCntFrm::MakeAll()
+{
+ // OD 2004-01-19 #110582#
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !GetAnchorFrm() || IsLocked() || IsColLocked() || !FindPageFrm() )
+ return;
+
+ Lock(); //Der Vorhang faellt
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwFlyNotify aNotify( this );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ if ( IsClipped() )
+ bValidSize = bHeightClipped = bWidthClipped = sal_False;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ //Nur einstellen wenn das Flag gesetzt ist!!
+ if ( !bValidSize )
+ {
+ bValidPrtArea = sal_False;
+/*
+ // This is also done in the Format function, so I think
+ // this code is not necessary anymore:
+ long nOldWidth = aFrm.Width();
+ const Size aRelSize( CalcRel( rFrmSz ) );
+ aFrm.Width( aRelSize.Width() );
+
+ if ( aFrm.Width() > nOldWidth )
+ //Damit sich der Inhalt anpasst
+ aFrm.Height( aRelSize.Height() );
+*/
+ }
+
+ if ( !bValidPrtArea )
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize )
+ Format( &rAttrs );
+
+ if ( !bValidPos )
+ {
+ // OD 2004-03-23 #i26791#
+ //MakeFlyPos();
+ MakeObjPos();
+ }
+
+ // --> OD 2006-04-13 #b6402800#
+ // re-activate clipping of as-character anchored Writer fly frames
+ // depending on compatibility option <ClipAsCharacterAnchoredWriterFlyFrames>
+ if ( bValidPos && bValidSize &&
+ GetFmt()->getIDocumentSettingAccess()->get( IDocumentSettingAccess::CLIP_AS_CHARACTER_ANCHORED_WRITER_FLY_FRAME ) )
+ {
+ SwFrm* pFrm = AnchorFrm();
+ if ( Frm().Left() == (pFrm->Frm().Left()+pFrm->Prt().Left()) &&
+ Frm().Width() > pFrm->Prt().Width() )
+ {
+ Frm().Width( pFrm->Prt().Width() );
+ bValidPrtArea = sal_False;
+ bWidthClipped = sal_True;
+ }
+ }
+ // <--
+ }
+ Unlock();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
new file mode 100644
index 000000000000..170779683097
--- /dev/null
+++ b/sw/source/core/layout/flylay.cxx
@@ -0,0 +1,1319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "doc.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "flyfrm.hxx"
+#include "ftnfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "hints.hxx"
+#include "pam.hxx"
+#include "sectfrm.hxx"
+
+
+#include <svx/svdpage.hxx>
+#include <editeng/ulspitem.hxx>
+#include <fmtanchr.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include "ndole.hxx"
+#include "tabfrm.hxx"
+#include "flyfrms.hxx"
+// #i18732#
+#include <fmtfollowtextflow.hxx>
+#include <environmentofanchoredobject.hxx>
+// #i28701#
+#include <sortedobjs.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::SwFlyFreeFrm(), ~SwFlyFreeFrm()
+|*
+|*************************************************************************/
+
+SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFrm( pFmt, pSib, pAnch ),
+ pPage( 0 ),
+ // #i34753#
+ mbNoMakePos( false ),
+ // #i37068#
+ mbNoMoveOnCheckClip( false )
+{
+}
+
+SwFlyFreeFrm::~SwFlyFreeFrm()
+{
+ //und Tschuess.
+ // #i28701# - use new method <GetPageFrm()>
+ if( GetPageFrm() )
+ {
+ if( GetFmt()->GetDoc()->IsInDtor() )
+ {
+ // #i29879# - remove also to-frame anchored Writer
+ // fly frame from page.
+ const bool bRemoveFromPage =
+ GetPageFrm()->GetSortedObjs() &&
+ ( IsFlyAtCntFrm() ||
+ ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
+ if ( bRemoveFromPage )
+ {
+ GetPageFrm()->GetSortedObjs()->Remove( *this );
+ }
+ }
+ else
+ {
+ SwRect aTmp( GetObjRectWithSpaces() );
+ SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
+ }
+ }
+}
+
+// #i28701#
+TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::NotifyBackground()
+|*
+|* Beschreibung Benachrichtigt den Hintergrund (alle CntntFrms die
+|* gerade ueberlappt werden. Ausserdem wird das Window in einigen
+|* Faellen direkt invalidiert (vor allem dort, wo keine CntntFrms
+|* ueberlappt werden.
+|* Es werden auch die CntntFrms innerhalb von anderen Flys
+|* beruecksichtigt.
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
+ const SwRect& rRect, PrepareHint eHint )
+{
+ ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::MakeAll()
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::MakeAll()
+{
+ if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
+ {
+ return;
+ }
+
+ if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
+ return;
+ // #i28701# - use new method <GetPageFrm()>
+ if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
+ {
+ SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
+ SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
+ if( pPageFrm )
+ pPageFrm->AppendFlyToPage( this );
+ }
+ if( !GetPageFrm() )
+ return;
+
+ Lock(); //Der Vorhang faellt
+
+ //uebernimmt im DTor die Benachrichtigung
+ const SwFlyNotify aNotify( this );
+
+ if ( IsClipped() )
+ {
+ bValidSize = bHeightClipped = bWidthClipped = sal_False;
+ // no invalidation of position,
+ // if anchored object is anchored inside a Writer fly frame,
+ // its position is already locked, and it follows the text flow.
+ // #i34753# - add condition:
+ // no invalidation of position, if no direct move is requested in <CheckClip(..)>
+ if ( !IsNoMoveOnCheckClip() &&
+ !( PositionLocked() &&
+ GetAnchorFrm()->IsInFly() &&
+ GetFrmFmt().GetFollowTextFlow().GetValue() ) )
+ {
+ bValidPos = sal_False;
+ }
+ }
+
+ // #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+
+ while ( !bValidPos || !bValidSize || !bValidPrtArea || bFormatHeightOnly )
+ {
+ SWRECTFN( this )
+ const SwFmtFrmSize *pSz;
+ { //Zusaetzlicher Scope, damit aAccess vor dem Check zerstoert wird!
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ pSz = &rAttrs.GetAttrSet().GetFrmSize();
+
+ //Nur einstellen wenn das Flag gesetzt ist!!
+ if ( !bValidSize )
+ {
+ bValidPrtArea = sal_False;
+ }
+
+ if ( !bValidPrtArea )
+ MakePrtArea( rAttrs );
+
+ if ( !bValidSize || bFormatHeightOnly )
+ {
+ bValidSize = sal_False;
+ Format( &rAttrs );
+ bFormatHeightOnly = sal_False;
+ }
+
+ if ( !bValidPos )
+ {
+ const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ // #i26791# - use new method <MakeObjPos()>
+ // #i34753# - no positioning, if requested.
+ if ( IsNoMakePos() )
+ bValidPos = sal_True;
+ else
+ // #i26791# - use new method <MakeObjPos()>
+ MakeObjPos();
+ if( aOldPos == (Frm().*fnRect->fnGetPos)() )
+ {
+ if( !bValidPos && GetAnchorFrm()->IsInSct() &&
+ !GetAnchorFrm()->FindSctFrm()->IsValid() )
+ bValidPos = sal_True;
+ }
+ else
+ bValidSize = sal_False;
+ }
+ }
+
+ if ( bValidPos && bValidSize )
+ {
+ ++nLoopControlRuns;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" );
+#endif
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ CheckClip( *pSz );
+ }
+ else
+ nLoopControlRuns = 0;
+ }
+ Unlock();
+
+#if OSL_DEBUG_LEVEL > 1
+ SWRECTFN( this )
+ OSL_ENSURE( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
+ (Prt().*fnRect->fnGetHeight)() > 0),
+ "SwFlyFreeFrm::Format(), flipping Fly." );
+
+#endif
+}
+
+/** determines, if direct environment of fly frame has 'auto' size
+
+ #i17297#
+ start with anchor frame and search via <GetUpper()> for a header, footer,
+ row or fly frame stopping at page frame.
+ return <true>, if such a frame is found and it has 'auto' size.
+ otherwise <false> is returned.
+
+ @return boolean indicating, that direct environment has 'auto' size
+*/
+bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
+{
+ bool bRetVal = false;
+
+ const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
+ while ( pToBeCheckedFrm &&
+ !pToBeCheckedFrm->IsPageFrm() )
+ {
+ if ( pToBeCheckedFrm->IsHeaderFrm() ||
+ pToBeCheckedFrm->IsFooterFrm() ||
+ pToBeCheckedFrm->IsRowFrm() ||
+ pToBeCheckedFrm->IsFlyFrm() )
+ {
+ bRetVal = ATT_FIX_SIZE !=
+ pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
+ break;
+ }
+ else
+ {
+ pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
+ }
+ }
+
+ return bRetVal;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFreeFrm::CheckClip()
+|*
+|*************************************************************************/
+
+void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
+{
+ //Jetzt ist es ggf. an der Zeit geignete Massnahmen zu ergreifen wenn
+ //der Fly nicht in seine Umgebung passt.
+ //Zuerst gibt der Fly seine Position auf. Danach wird er zunaechst
+ //formatiert. Erst wenn er auch durch die Aufgabe der Position nicht
+ //passt wird die Breite oder Hoehe aufgegeben - der Rahmen wird soweit
+ //wie notwendig zusammengequetscht.
+
+ const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
+ SwRect aClip, aTmpStretch;
+ ::CalcClipRect( pObj, aClip, sal_True );
+ ::CalcClipRect( pObj, aTmpStretch, sal_False );
+ aClip._Intersection( aTmpStretch );
+
+ const long nBot = Frm().Top() + Frm().Height();
+ const long nRig = Frm().Left() + Frm().Width();
+ const long nClipBot = aClip.Top() + aClip.Height();
+ const long nClipRig = aClip.Left() + aClip.Width();
+
+ const sal_Bool bBot = nBot > nClipBot;
+ const sal_Bool bRig = nRig > nClipRig;
+ if ( bBot || bRig )
+ {
+ sal_Bool bAgain = sal_False;
+ // #i37068# - no move, if it's requested
+ if ( bBot && !IsNoMoveOnCheckClip() &&
+ !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
+ {
+ SwFrm* pHeader = FindFooterOrHeader();
+ // In a header, correction of the position is no good idea.
+ // If the fly moves, some paragraphs has to be formatted, this
+ // could cause a change of the height of the headerframe,
+ // now the flyframe can change its position and so on ...
+ if ( !pHeader || !pHeader->IsHeaderFrm() )
+ {
+ const long nOld = Frm().Top();
+ Frm().Pos().Y() = Max( aClip.Top(), nClipBot - Frm().Height() );
+ if ( Frm().Top() != nOld )
+ bAgain = sal_True;
+ bHeightClipped = sal_True;
+ }
+ }
+ if ( bRig )
+ {
+ const long nOld = Frm().Left();
+ Frm().Pos().X() = Max( aClip.Left(), nClipRig - Frm().Width() );
+ if ( Frm().Left() != nOld )
+ {
+ const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
+ // Links ausgerichtete duerfen nicht nach links verschoben werden,
+ // wenn sie einem anderen ausweichen.
+ if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
+ Frm().Pos().X() = nOld;
+ else
+ bAgain = sal_True;
+ }
+ bWidthClipped = sal_True;
+ }
+ if ( bAgain )
+ bValidSize = sal_False;
+ else
+ {
+ //Wenn wir hier ankommen ragt der Frm in unerlaubte Bereiche
+ //hinein, und eine Positionskorrektur ist nicht erlaubt bzw.
+ //moeglich oder noetig.
+
+ //Fuer Flys mit OLE-Objekten als Lower sorgen wir dafuer, dass
+ //immer proportional Resized wird.
+ Size aOldSize( Frm().SSize() );
+
+ //Zuerst wird das FrmRect eingestellt, und dann auf den Frm
+ //uebertragen.
+ SwRect aFrmRect( Frm() );
+
+ if ( bBot )
+ {
+ long nDiff = nClipBot;
+ nDiff -= aFrmRect.Top(); //nDiff ist die verfuegbare Strecke.
+ nDiff = aFrmRect.Height() - nDiff;
+ aFrmRect.Height( aFrmRect.Height() - nDiff );
+ bHeightClipped = sal_True;
+ }
+ if ( bRig )
+ {
+ long nDiff = nClipRig;
+ nDiff -= aFrmRect.Left();//nDiff ist die verfuegbare Strecke.
+ nDiff = aFrmRect.Width() - nDiff;
+ aFrmRect.Width( aFrmRect.Width() - nDiff );
+ bWidthClipped = sal_True;
+ }
+
+ // #i17297# - no proportional
+ // scaling of graphics in environments, which determines its size
+ // by its content ('auto' size). Otherwise layout loops can occur and
+ // layout sizes of the environment can be incorrect.
+ // Such environment are:
+ // (1) header and footer frames with 'auto' size
+ // (2) table row frames with 'auto' size
+ // (3) fly frames with 'auto' size
+ // Note: section frames seems to be not critical - didn't found
+ // any critical layout situation so far.
+ if ( Lower() && Lower()->IsNoTxtFrm() &&
+ ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
+ !HasEnvironmentAutoSize() ) )
+ {
+ //Wenn Breite und Hoehe angepasst wurden, so ist die
+ //groessere Veraenderung massgeblich.
+ if ( aFrmRect.Width() != aOldSize.Width() &&
+ aFrmRect.Height()!= aOldSize.Height() )
+ {
+ if ( (aOldSize.Width() - aFrmRect.Width()) >
+ (aOldSize.Height()- aFrmRect.Height()) )
+ aFrmRect.Height( aOldSize.Height() );
+ else
+ aFrmRect.Width( aOldSize.Width() );
+ }
+
+ //Breite angepasst? - Hoehe dann proportional verkleinern
+ if( aFrmRect.Width() != aOldSize.Width() )
+ {
+ aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
+ aOldSize.Width() );
+ bHeightClipped = sal_True;
+ }
+ //Hoehe angepasst? - Breite dann proportional verkleinern
+ else if( aFrmRect.Height() != aOldSize.Height() )
+ {
+ aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
+ aOldSize.Height() );
+ bWidthClipped = sal_True;
+ }
+
+ // #i17297# - reactivate change
+ // of size attribute for fly frames containing an ole object.
+
+ // Added the aFrmRect.HasArea() hack, because
+ // the environment of the ole object does not have to be valid
+ // at this moment, or even worse, it does not have to have a
+ // resonable size. In this case we do not want to change to
+ // attributes permanentely. Maybe one day somebody dares to remove
+ // this code.
+ if ( aFrmRect.HasArea() &&
+ static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
+ ( bWidthClipped || bHeightClipped ) )
+ {
+ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
+ pFmt->LockModify();
+ SwFmtFrmSize aFrmSize( rSz );
+ aFrmSize.SetWidth( aFrmRect.Width() );
+ aFrmSize.SetHeight( aFrmRect.Height() );
+ pFmt->SetFmtAttr( aFrmSize );
+ pFmt->UnlockModify();
+ }
+ }
+
+ //Jetzt die Einstellungen am Frm vornehmen, bei Spalten werden
+ //die neuen Werte in die Attribute eingetragen, weil es sonst
+ //ziemlich fiese Oszillationen gibt.
+ const long nPrtHeightDiff = Frm().Height() - Prt().Height();
+ const long nPrtWidthDiff = Frm().Width() - Prt().Width();
+ Frm().Height( aFrmRect.Height() );
+ Frm().Width ( Max( long(MINLAY), aFrmRect.Width() ) );
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ ColLock(); //Grow/Shrink locken.
+ const Size aTmpOldSize( Prt().SSize() );
+ Prt().Height( Frm().Height() - nPrtHeightDiff );
+ Prt().Width ( Frm().Width() - nPrtWidthDiff );
+ ChgLowersProp( aTmpOldSize );
+ SwFrm *pLow = Lower();
+ do
+ { pLow->Calc();
+ // auch den (Column)BodyFrm mitkalkulieren
+ ((SwLayoutFrm*)pLow)->Lower()->Calc();
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ ::CalcCntnt( this );
+ ColUnlock();
+ if ( !bValidSize && !bWidthClipped )
+ bFormatHeightOnly = bValidSize = sal_True;
+ }
+ else
+ {
+ Prt().Height( Frm().Height() - nPrtHeightDiff );
+ Prt().Width ( Frm().Width() - nPrtWidthDiff );
+ }
+ }
+ }
+
+ // #i26945#
+ OSL_ENSURE( Frm().Height() >= 0,
+ "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
+}
+
+/** method to determine, if a <MakeAll()> on the Writer fly frame is possible
+ #i43771#
+*/
+bool SwFlyFreeFrm::IsFormatPossible() const
+{
+ return SwFlyFrm::IsFormatPossible() &&
+ ( GetPageFrm() ||
+ ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
+}
+
+/*************************************************************************
+|*
+|* SwFlyLayFrm::SwFlyLayFrm()
+|*
+|*************************************************************************/
+
+SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
+ SwFlyFreeFrm( pFmt, pSib, pAnch )
+{
+ bLayout = sal_True;
+}
+
+// #i28701#
+TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
+/*************************************************************************
+|*
+|* SwFlyLayFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
+
+ SwFmtAnchor *pAnch = 0;
+ if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
+ (const SfxPoolItem**)&pAnch ))
+ ; // Beim GetItemState wird der AnkerPointer gesetzt !
+
+ else if( RES_ANCHOR == nWhich )
+ {
+ //Ankerwechsel, ich haenge mich selbst um.
+ //Es darf sich nicht um einen Wechsel des Ankertyps handeln,
+ //dies ist nur ueber die SwFEShell moeglich.
+ pAnch = (SwFmtAnchor*)pNew;
+ }
+
+ if( pAnch )
+ {
+ OSL_ENSURE( pAnch->GetAnchorId() ==
+ GetFmt()->GetAnchor().GetAnchorId(),
+ "8-) Unzulaessiger Wechsel des Ankertyps." );
+
+ //Abmelden, Seite besorgen, an den entsprechenden LayoutFrm
+ //haengen.
+ SwRect aOld( GetObjRectWithSpaces() );
+ // #i28701# - use new method <GetPageFrm()>
+ SwPageFrm *pOldPage = GetPageFrm();
+ AnchorFrm()->RemoveFly( this );
+
+ if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
+ {
+ sal_uInt16 nPgNum = pAnch->GetPageNum();
+ SwRootFrm *pRoot = getRootFrm();
+ SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
+ for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
+ pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
+ {
+ if ( i == nPgNum )
+ {
+ // #i50432# - adjust synopsis of <PlaceFly(..)>
+ pTmpPage->PlaceFly( this, 0 );
+ }
+ }
+ if( !pTmpPage )
+ {
+ pRoot->SetAssertFlyPages();
+ pRoot->AssertFlyPages();
+ }
+ }
+ else
+ {
+ SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
+ SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
+ GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, sal_False );
+ if( pCntnt )
+ {
+ SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
+ if( pTmp )
+ pTmp->AppendFly( this );
+ }
+ }
+ // #i28701# - use new method <GetPageFrm()>
+ if ( pOldPage && pOldPage != GetPageFrm() )
+ NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
+ SetCompletePaint();
+ InvalidateAll();
+ SetNotifyBack();
+ }
+ else
+ SwFlyFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::AppendFly()
+|*
+|*************************************************************************/
+
+void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
+{
+ if ( !pNew->GetVirtDrawObj()->IsInserted() )
+ getRootFrm()->GetDrawPage()->InsertObject(
+ (SdrObject*)pNew->GetVirtDrawObj(),
+ pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
+
+ InvalidateSpelling();
+ InvalidateSmartTags(); // SMARTTAGS
+ InvalidateAutoCompleteWords();
+ InvalidateWordCount();
+
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->SetIdleFlags();
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ SdrObject* pObj = pNew->GetVirtDrawObj();
+ OSL_ENSURE( pNew->GetAnchorFrm(), "Fly without Anchor" );
+ const SwFlyFrm* pFly = pNew->GetAnchorFrm()->FindFlyFrm();
+ if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
+ {
+ sal_uInt32 nNewNum = pFly->GetVirtDrawObj()->GetOrdNumDirect();
+ if ( pObj->GetPage() )
+ pObj->GetPage()->SetObjectOrdNum( pObj->GetOrdNumDirect(), nNewNum);
+ else
+ pObj->SetOrdNum( nNewNum );
+ }
+
+ //Flys die im Cntnt sitzen beachten wir nicht weiter.
+ if ( pNew->IsFlyInCntFrm() )
+ InvalidateFlyInCnt();
+ else
+ {
+ InvalidateFlyCntnt();
+
+ if ( !pSortedObjs )
+ pSortedObjs = new SwSortedObjs();
+
+#if OSL_DEBUG_LEVEL > 1
+ const bool bSucessInserted =
+#endif
+ pSortedObjs->Insert( *pNew );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSucessInserted, "Fly nicht in Sorted eingetragen." );
+ (void) bSucessInserted;
+#endif
+
+ // #i87493#
+ OSL_ENSURE( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
+ "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
+ // #i28701# - use new method <SetPageFrm(..)>
+ pNew->SetPageFrm( this );
+ pNew->InvalidatePage( this );
+ // #i28701#
+ pNew->UnlockPosition();
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->AddAccessibleFrm( pNew );
+ }
+ }
+
+ // #i28701# - correction: consider also drawing objects
+ if ( pNew->GetDrawObjs() )
+ {
+ SwSortedObjs &rObjs = *pNew->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pTmpObj = rObjs[i];
+ if ( pTmpObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
+ // #i28701# - use new method <GetPageFrm()>
+ if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
+ AppendFlyToPage( pTmpFly );
+ }
+ else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
+ {
+ // #i87493#
+ if ( pTmpObj->GetPageFrm() != this )
+ {
+ if ( pTmpObj->GetPageFrm() != 0 )
+ {
+ pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
+ }
+ AppendDrawObjToPage( *pTmpObj );
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RemoveFly()
+|*
+|*************************************************************************/
+
+void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
+{
+ const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
+ getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
+ pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
+
+ if ( GetUpper() )
+ {
+ if ( !pToRemove->IsFlyInCntFrm() )
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ //Flys die im Cntnt sitzen beachten wir nicht weiter.
+ if ( pToRemove->IsFlyInCntFrm() )
+ return;
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->DisposeAccessibleFrm( pToRemove, sal_True );
+ }
+
+ //Collections noch nicht loeschen. Das passiert am Ende
+ //der Action im RemoveSuperfluous der Seite - angestossen von gleich-
+ //namiger Methode der Root.
+ //Die FlyColl kann bereits weg sein, weil der DTor der Seite
+ //gerade 'laeuft'
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( *pToRemove );
+ if ( !pSortedObjs->Count() )
+ { DELETEZ( pSortedObjs );
+ }
+ }
+ // #i28701# - use new method <SetPageFrm(..)>
+ pToRemove->SetPageFrm( 0L );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::MoveFly
+|*
+|*************************************************************************/
+
+void SwPageFrm::MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest )
+{
+ //Invalidierungen
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->SetIdleFlags();
+ if ( !pToMove->IsFlyInCntFrm() && pDest->GetPhyPageNum() < GetPhyPageNum() )
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ }
+
+ pDest->InvalidateSpelling();
+ pDest->InvalidateSmartTags(); // SMARTTAGS
+ pDest->InvalidateAutoCompleteWords();
+ pDest->InvalidateWordCount();
+
+ if ( pToMove->IsFlyInCntFrm() )
+ {
+ pDest->InvalidateFlyInCnt();
+ return;
+ }
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->DisposeAccessibleFrm( pToMove, sal_True );
+ }
+
+ //Die FlyColl kann bereits weg sein, weil der DTor der Seite
+ //gerade 'laeuft'
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( *pToMove );
+ if ( !pSortedObjs->Count() )
+ { DELETEZ( pSortedObjs );
+ }
+ }
+
+ //Anmelden
+ if ( !pDest->GetSortedObjs() )
+ pDest->pSortedObjs = new SwSortedObjs();
+
+#if OSL_DEBUG_LEVEL > 1
+ const bool bSucessInserted =
+#endif
+ pDest->GetSortedObjs()->Insert( *pToMove );
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( bSucessInserted, "Fly nicht in Sorted eingetragen." );
+ (void) bSucessInserted;
+#endif
+
+ // #i28701# - use new method <SetPageFrm(..)>
+ pToMove->SetPageFrm( pDest );
+ pToMove->InvalidatePage( pDest );
+ pToMove->SetNotifyBack();
+ pDest->InvalidateFlyCntnt();
+ // #i28701#
+ pToMove->UnlockPosition();
+
+ // Notify accessible layout. That's required at this place for
+ // frames only where the anchor is moved. Creation of new frames
+ // is additionally handled by the SwFrmNotify class.
+ if( GetUpper() &&
+ static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
+ {
+ static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
+ ->AddAccessibleFrm( pToMove );
+ }
+
+ // #i28701# - correction: move lowers of Writer fly frame
+ if ( pToMove->GetDrawObjs() )
+ {
+ SwSortedObjs &rObjs = *pToMove->GetDrawObjs();
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyFreeFrm() )
+ {
+ // #i28701# - use new method <GetPageFrm()>
+ SwPageFrm* pPageFrm = pFly->GetPageFrm();
+ if ( pPageFrm )
+ pPageFrm->MoveFly( pFly, pDest );
+ else
+ pDest->AppendFlyToPage( pFly );
+ }
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ RemoveDrawObjFromPage( *pObj );
+ pDest->AppendDrawObjToPage( *pObj );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::AppendDrawObjToPage(), RemoveDrawObjFromPage()
+|*
+|* #i28701# - new methods
+|*
+|*************************************************************************/
+void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
+{
+ if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexcepted type -> object not appended" );
+ return;
+ }
+
+ if ( GetUpper() )
+ {
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+
+ OSL_ENSURE( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
+ const SwFlyFrm* pFlyFrm = _rNewObj.GetAnchorFrm()->FindFlyFrm();
+ if ( pFlyFrm &&
+ _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
+ {
+ sal_uInt32 nNewNum = pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect();
+ if ( _rNewObj.GetDrawObj()->GetPage() )
+ _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum(
+ _rNewObj.GetDrawObj()->GetOrdNumDirect(), nNewNum);
+ else
+ _rNewObj.DrawObj()->SetOrdNum( nNewNum );
+ }
+
+ if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
+ {
+ return;
+ }
+
+ if ( !pSortedObjs )
+ {
+ pSortedObjs = new SwSortedObjs();
+ }
+ if ( !pSortedObjs->Insert( _rNewObj ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pSortedObjs->Contains( _rNewObj ),
+ "Drawing object not appended into list <pSortedObjs>." );
+#endif
+ }
+ // #i87493#
+ OSL_ENSURE( _rNewObj.GetPageFrm() == 0 || _rNewObj.GetPageFrm() == this,
+ "<SwPageFrm::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect -> please inform OD." );
+ _rNewObj.SetPageFrm( this );
+
+ // invalidate page in order to force a reformat of object layout of the page.
+ InvalidateFlyLayout();
+}
+
+void SwPageFrm::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj )
+{
+ if ( !_rToRemoveObj.ISA(SwAnchoredDrawObject) )
+ {
+ OSL_FAIL( "SwPageFrm::RemoveDrawObjFromPage(..) - anchored object of unexcepted type -> object not removed" );
+ return;
+ }
+
+ if ( pSortedObjs )
+ {
+ pSortedObjs->Remove( _rToRemoveObj );
+ if ( !pSortedObjs->Count() )
+ {
+ DELETEZ( pSortedObjs );
+ }
+ if ( GetUpper() )
+ {
+ if (FLY_AS_CHAR !=
+ _rToRemoveObj.GetFrmFmt().GetAnchor().GetAnchorId())
+ {
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ InvalidatePage();
+ }
+ ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
+ }
+ }
+ _rToRemoveObj.SetPageFrm( 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PlaceFly
+|*
+|*************************************************************************/
+
+// #i50432# - adjust method description and synopsis.
+void SwPageFrm::PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt )
+{
+ // #i50432# - consider the case that page is an empty page:
+ // In this case append the fly frame at the next page
+ OSL_ENSURE( !IsEmptyPage() || GetNext(),
+ "<SwPageFrm::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
+ if ( IsEmptyPage() && GetNext() )
+ {
+ static_cast<SwPageFrm*>(GetNext())->PlaceFly( pFly, pFmt );
+ }
+ else
+ {
+ //Wenn ein Fly uebergeben wurde, so benutzen wir diesen, ansonsten wird
+ //mit dem Format einer erzeugt.
+ if ( pFly )
+ AppendFly( pFly );
+ else
+ { OSL_ENSURE( pFmt, ":-( kein Format fuer Fly uebergeben." );
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
+ AppendFly( pFly );
+ ::RegistFlys( this, pFly );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* ::CalcClipRect
+|*
+|*************************************************************************/
+// #i18732# - adjustments for following text flow or not
+// AND alignment at 'page areas' for to paragraph/to character anchored objects
+// #i22305# - adjustment for following text flow
+// for to frame anchored objects
+// #i29778# - Because the calculation of the position of the
+// floating screen object (Writer fly frame or drawing object) doesn't perform
+// a calculation on its upper frames and its anchor frame, a calculation of
+// the upper frames in this method no longer sensible.
+// #i28701# - if document compatibility option 'Consider
+// wrapping style influence on object positioning' is ON, the clip area
+// corresponds to the one as the object doesn't follows the text flow.
+sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove )
+{
+ sal_Bool bRet = sal_True;
+ if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
+ const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
+ // #i28701#
+ const bool bConsiderWrapOnObjPos =
+ pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
+ const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
+ if( pFly->IsFlyLayFrm() )
+ {
+ const SwFrm* pClip;
+ // #i22305#
+ // #i28701#
+ if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
+ {
+ pClip = pFly->GetAnchorFrm()->FindPageFrm();
+ }
+ else
+ {
+ pClip = pFly->GetAnchorFrm();
+ }
+
+ rRect = pClip->Frm();
+ SWRECTFN( pClip )
+
+ //Vertikales clipping: Top und Bottom, ggf. an PrtArea
+ if( rV.GetVertOrient() != text::VertOrientation::NONE &&
+ rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
+ (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
+ }
+ //Horizontales clipping: Left und Right, ggf. an PrtArea
+ const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
+ if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
+ rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
+ {
+ (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
+ (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
+ }
+ }
+ else if( pFly->IsFlyAtCntFrm() )
+ {
+ // #i18732# - consider following text flow or not
+ // AND alignment at 'page areas'
+ const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
+ if ( !pVertPosOrientFrm )
+ {
+ OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
+ pVertPosOrientFrm = pFly->GetAnchorFrm();
+ }
+
+ if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
+ {
+ const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
+ rRect = bMove ? pClipFrm->GetUpper()->Frm()
+ : pClipFrm->Frm();
+ // #i26945# - consider that a table, during
+ // its format, can exceed its upper printing area bottom.
+ // Thus, enlarge the clip rectangle, if such a case occurred
+ if ( pFly->GetAnchorFrm()->IsInTab() )
+ {
+ const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
+ ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
+ SwRect aTmp( pTabFrm->Prt() );
+ aTmp += pTabFrm->Frm().Pos();
+ rRect.Union( aTmp );
+ // #i43913# - consider also the cell frame
+ const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
+ ->GetAnchorFrmContainingAnchPos()->GetUpper();
+ while ( pCellFrm && !pCellFrm->IsCellFrm() )
+ {
+ pCellFrm = pCellFrm->GetUpper();
+ }
+ if ( pCellFrm )
+ {
+ aTmp = pCellFrm->Prt();
+ aTmp += pCellFrm->Frm().Pos();
+ rRect.Union( aTmp );
+ }
+ }
+ }
+ else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
+ rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // new class <SwEnvironmentOfAnchoredObject>
+ objectpositioning::SwEnvironmentOfAnchoredObject
+ aEnvOfObj( bFollowTextFlow );
+ const SwLayoutFrm& rVertClipFrm =
+ aEnvOfObj.GetVertEnvironmentLayoutFrm( *pVertPosOrientFrm );
+ if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
+ {
+ rRect = rVertClipFrm.Frm();
+ }
+ else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ if ( rVertClipFrm.IsPageFrm() )
+ {
+ rRect = static_cast<const SwPageFrm&>(rVertClipFrm).PrtWithoutHeaderAndFooter();
+ }
+ else
+ {
+ rRect = rVertClipFrm.Frm();
+ }
+ }
+ const SwLayoutFrm* pHoriClipFrm =
+ pFly->GetAnchorFrm()->FindPageFrm()->GetUpper();
+ SWRECTFN( pFly->GetAnchorFrm() )
+ (rRect.*fnRect->fnSetLeft)( (pHoriClipFrm->Frm().*fnRect->fnGetLeft)() );
+ (rRect.*fnRect->fnSetRight)((pHoriClipFrm->Frm().*fnRect->fnGetRight)());
+ }
+ else
+ {
+ // #i26945#
+ const SwFrm *pClip =
+ const_cast<SwFlyFrm*>(pFly)->GetAnchorFrmContainingAnchPos();
+ SWRECTFN( pClip )
+ const SwLayoutFrm *pUp = pClip->GetUpper();
+ const SwFrm *pCell = pUp->IsCellFrm() ? pUp : 0;
+ sal_uInt16 nType = bMove ? FRM_ROOT | FRM_FLY | FRM_HEADER |
+ FRM_FOOTER | FRM_FTN
+ : FRM_BODY | FRM_FLY | FRM_HEADER |
+ FRM_FOOTER | FRM_CELL| FRM_FTN;
+
+ while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrm() )
+ {
+ pUp = pUp->GetUpper();
+ if ( !pCell && pUp->IsCellFrm() )
+ pCell = pUp;
+ }
+ if ( bMove )
+ {
+ if ( pUp->IsRootFrm() )
+ {
+ rRect = pUp->Prt();
+ rRect += pUp->Frm().Pos();
+ pUp = 0;
+ }
+ }
+ if ( pUp )
+ {
+ if ( pUp->GetType() & FRM_BODY )
+ {
+ const SwPageFrm *pPg;
+ if ( pUp->GetUpper() != (pPg = pFly->FindPageFrm()) )
+ pUp = pPg->FindBodyCont();
+ rRect = pUp->GetUpper()->Frm();
+ (rRect.*fnRect->fnSetTop)( (pUp->*fnRect->fnGetPrtTop)() );
+ (rRect.*fnRect->fnSetBottom)((pUp->*fnRect->fnGetPrtBottom)());
+ }
+ else
+ {
+ if( ( pUp->GetType() & (FRM_FLY | FRM_FTN ) ) &&
+ !pUp->Frm().IsInside( pFly->Frm().Pos() ) )
+ {
+ if( pUp->IsFlyFrm() )
+ {
+ SwFlyFrm *pTmpFly = (SwFlyFrm*)pUp;
+ while( pTmpFly->GetNextLink() )
+ {
+ pTmpFly = pTmpFly->GetNextLink();
+ if( pTmpFly->Frm().IsInside( pFly->Frm().Pos() ) )
+ break;
+ }
+ pUp = pTmpFly;
+ }
+ else if( pUp->IsInFtn() )
+ {
+ const SwFtnFrm *pTmp = pUp->FindFtnFrm();
+ while( pTmp->GetFollow() )
+ {
+ pTmp = pTmp->GetFollow();
+ if( pTmp->Frm().IsInside( pFly->Frm().Pos() ) )
+ break;
+ }
+ pUp = pTmp;
+ }
+ }
+ rRect = pUp->Prt();
+ rRect.Pos() += pUp->Frm().Pos();
+ if ( pUp->GetType() & (FRM_HEADER | FRM_FOOTER) )
+ {
+ rRect.Left ( pUp->GetUpper()->Frm().Left() );
+ rRect.Width( pUp->GetUpper()->Frm().Width());
+ }
+ else if ( pUp->IsCellFrm() ) //MA_FLY_HEIGHT
+ {
+ const SwFrm *pTab = pUp->FindTabFrm();
+ (rRect.*fnRect->fnSetBottom)(
+ (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ // expand to left and right cell border
+ rRect.Left ( pUp->Frm().Left() );
+ rRect.Width( pUp->Frm().Width() );
+ }
+ }
+ }
+ if ( pCell )
+ {
+ //CellFrms koennen auch in 'unerlaubten' Bereichen stehen, dann
+ //darf der Fly das auch.
+ SwRect aTmp( pCell->Prt() );
+ aTmp += pCell->Frm().Pos();
+ rRect.Union( aTmp );
+ }
+ }
+ }
+ else
+ {
+ const SwFrm *pUp = pFly->GetAnchorFrm()->GetUpper();
+ SWRECTFN( pFly->GetAnchorFrm() )
+ while( pUp->IsColumnFrm() || pUp->IsSctFrm() || pUp->IsColBodyFrm())
+ pUp = pUp->GetUpper();
+ rRect = pUp->Frm();
+ if( !pUp->IsBodyFrm() )
+ {
+ rRect += pUp->Prt().Pos();
+ rRect.SSize( pUp->Prt().SSize() );
+ if ( pUp->IsCellFrm() )
+ {
+ const SwFrm *pTab = pUp->FindTabFrm();
+ (rRect.*fnRect->fnSetBottom)(
+ (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ }
+ }
+ else if ( pUp->GetUpper()->IsPageFrm() )
+ {
+ // Objects anchored as character may exceed right margin
+ // of body frame:
+ (rRect.*fnRect->fnSetRight)( (pUp->GetUpper()->Frm().*fnRect->fnGetRight)() );
+ }
+ long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
+ long nTop;
+ const SwFmt *pFmt = ((SwContact*)GetUserCall(pSdrObj))->GetFmt();
+ const SvxULSpaceItem &rUL = pFmt->GetULSpace();
+ if( bMove )
+ {
+ nTop = bVert ? ((SwFlyInCntFrm*)pFly)->GetRefPoint().X() :
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y();
+ nTop = (*fnRect->fnYInc)( nTop, -nHeight );
+ long nWidth = (pFly->Frm().*fnRect->fnGetWidth)();
+ (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y() :
+ ((SwFlyInCntFrm*)pFly)->GetRefPoint().X(), nWidth );
+ nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper();
+ }
+ else
+ {
+ nTop = (*fnRect->fnYInc)( (pFly->Frm().*fnRect->fnGetBottom)(),
+ rUL.GetLower() - nHeight );
+ nHeight = 2*nHeight - (pFly->Frm().*fnRect->fnGetHeight)()
+ - rUL.GetLower() - rUL.GetUpper();
+ }
+ (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
+ }
+ }
+ else
+ {
+ const SwDrawContact *pC = (const SwDrawContact*)GetUserCall(pSdrObj);
+ const SwFrmFmt *pFmt = (const SwFrmFmt*)pC->GetFmt();
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( FLY_AS_CHAR == rAnch.GetAnchorId() )
+ {
+ const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
+ if( !pAnchorFrm )
+ {
+ OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." );
+ ((SwDrawContact*)pC)->ConnectToLayout();
+ pAnchorFrm = pC->GetAnchorFrm();
+ }
+ const SwFrm* pUp = pAnchorFrm->GetUpper();
+ rRect = pUp->Prt();
+ rRect += pUp->Frm().Pos();
+ SWRECTFN( pAnchorFrm )
+ long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
+ long nTop;
+ const SvxULSpaceItem &rUL = pFmt->GetULSpace();
+ SwRect aSnapRect( pSdrObj->GetSnapRect() );
+ long nTmpH = 0;
+ if( bMove )
+ {
+ nTop = (*fnRect->fnYInc)( bVert ? pSdrObj->GetAnchorPos().X() :
+ pSdrObj->GetAnchorPos().Y(), -nHeight );
+ long nWidth = (aSnapRect.*fnRect->fnGetWidth)();
+ (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
+ pSdrObj->GetAnchorPos().Y() :
+ pSdrObj->GetAnchorPos().X(), nWidth );
+ }
+ else
+ {
+ // #i26791# - value of <nTmpH> is needed to
+ // calculate value of <nTop>.
+ nTmpH = bVert ? pSdrObj->GetCurrentBoundRect().GetWidth() :
+ pSdrObj->GetCurrentBoundRect().GetHeight();
+ nTop = (*fnRect->fnYInc)( (aSnapRect.*fnRect->fnGetTop)(),
+ rUL.GetLower() + nTmpH - nHeight );
+ }
+ nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper();
+ (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
+ }
+ else
+ {
+ // restrict clip rectangle for drawing
+ // objects in header/footer to the page frame.
+ // #i26791#
+ const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
+ if ( pAnchorFrm && pAnchorFrm->FindFooterOrHeader() )
+ {
+ // clip frame is the page frame the header/footer is on.
+ const SwFrm* pClipFrm = pAnchorFrm->FindPageFrm();
+ rRect = pClipFrm->Frm();
+ }
+ else
+ {
+ bRet = sal_False;
+ }
+ }
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flypos.cxx b/sw/source/core/layout/flypos.cxx
new file mode 100644
index 000000000000..2c9c4e1b20f4
--- /dev/null
+++ b/sw/source/core/layout/flypos.cxx
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "doc.hxx"
+#include "node.hxx"
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include "flypos.hxx"
+#include "frmfmt.hxx"
+#include "dcontact.hxx"
+#include "dview.hxx"
+#include "flyfrm.hxx"
+#include "dflyobj.hxx"
+#include "ndindex.hxx"
+#include "switerator.hxx"
+
+SV_IMPL_OP_PTRARR_SORT( SwPosFlyFrms, SwPosFlyFrmPtr )
+
+SwPosFlyFrm::SwPosFlyFrm( const SwNodeIndex& rIdx, const SwFrmFmt* pFmt,
+ sal_uInt16 nArrPos )
+ : pFrmFmt( pFmt ), pNdIdx( (SwNodeIndex*) &rIdx )
+{
+ bool bFnd = false;
+ const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
+ if (FLY_AT_PAGE == rAnchor.GetAnchorId())
+ {
+ pNdIdx = new SwNodeIndex( rIdx );
+ }
+ else if( pFmt->GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
+ {
+ if( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwFlyFrm* pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement(*pFmt);
+ if( pFly )
+ {
+ nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
+ bFnd = true;
+ }
+ }
+ else if( RES_DRAWFRMFMT == pFmt->Which() )
+ {
+ // Schauen, ob es ein SdrObject dafuer gibt
+ SwDrawContact* pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
+ if( pContact )
+ {
+ nOrdNum = pContact->GetMaster()->GetOrdNum();
+ bFnd = true;
+ }
+ }
+ }
+
+ if( !bFnd )
+ {
+ nOrdNum = pFmt->GetDoc()->GetSpzFrmFmts()->Count();
+ nOrdNum += nArrPos;
+ }
+}
+
+SwPosFlyFrm::~SwPosFlyFrm()
+{
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ if (FLY_AT_PAGE == rAnchor.GetAnchorId())
+ {
+ delete pNdIdx;
+ }
+}
+
+sal_Bool SwPosFlyFrm::operator==( const SwPosFlyFrm& )
+{
+ return sal_False; // FlyFrames koennen auf der gleichen Position stehen
+}
+
+sal_Bool SwPosFlyFrm::operator<( const SwPosFlyFrm& rPosFly )
+{
+ if( pNdIdx->GetIndex() == rPosFly.pNdIdx->GetIndex() )
+ {
+ // dann entscheidet die Ordnungsnummer!
+ return nOrdNum < rPosFly.nOrdNum;
+ }
+ return pNdIdx->GetIndex() < rPosFly.pNdIdx->GetIndex();
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
new file mode 100644
index 000000000000..56059a4aaf26
--- /dev/null
+++ b/sw/source/core/layout/frmtool.cxx
@@ -0,0 +1,3604 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <hintids.hxx>
+#include <tools/bigint.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/lspcitem.hxx>
+
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtsrnd.hxx>
+#include <docary.hxx>
+#include <lineinfo.hxx>
+#include <swmodule.hxx>
+#include "pagefrm.hxx"
+#include "colfrm.hxx"
+#include "doc.hxx"
+#include "fesh.hxx"
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "pam.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmtool.hxx"
+#include "docsh.hxx"
+#include "tabfrm.hxx"
+#include "rowfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "notxtfrm.hxx"
+#include "flyfrms.hxx"
+#include "layact.hxx"
+#include "pagedesc.hxx"
+#include "section.hxx"
+#include "sectfrm.hxx"
+#include "node2lay.hxx"
+#include "ndole.hxx"
+#include "ndtxt.hxx"
+#include "swtable.hxx"
+#include "hints.hxx"
+#include <layhelp.hxx>
+#include <laycache.hxx>
+#include <rootfrm.hxx>
+#include "mdiexp.hxx"
+#include "statstr.hrc"
+#include <paratr.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <switerator.hxx>
+
+// ftnfrm.cxx:
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
+
+using namespace ::com::sun::star;
+
+
+sal_Bool bObjsDirect = sal_True;
+sal_Bool bDontCreateObjects = sal_False;
+sal_Bool bSetCompletePaintOnInvalidate = sal_False;
+
+sal_uInt8 StackHack::nCnt = 0;
+sal_Bool StackHack::bLocked = sal_False;
+
+
+
+/*************************************************************************/
+
+SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
+ pFrm( pF ),
+ aFrm( pF->Frm() ),
+ aPrt( pF->Prt() ),
+ bInvaKeep( sal_False ),
+ bValidSize( pF->GetValidSizeFlag() ),
+ mbFrmDeleted( false ) // #i49383#
+{
+ if ( pF->IsTxtFrm() )
+ {
+ mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
+ mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
+ }
+ else
+ {
+ mnFlyAnchorOfst = 0;
+ mnFlyAnchorOfstNoWrap = 0;
+ }
+
+ bHadFollow = pF->IsCntntFrm() ?
+ (((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
+ sal_False;
+}
+
+/*************************************************************************/
+
+SwFrmNotify::~SwFrmNotify()
+{
+ // #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+
+ SWRECTFN( pFrm )
+ const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
+ const sal_Bool bChgWidth =
+ (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
+ const sal_Bool bChgHeight =
+ (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
+ const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
+ ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
+ ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );
+
+ if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
+ {
+ SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
+
+ if ( !pFlow->IsFollow() )
+ {
+ if ( !pFrm->GetIndPrev() )
+ {
+ if ( bInvaKeep )
+ {
+ SwFrm *pPre = pFrm->FindPrev();
+ if ( pPre && pPre->IsFlowFrm() )
+ {
+ // 1. pPre wants to keep with me:
+ bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
+
+ // 2. pPre is a table and the last row wants to keep with me:
+ if ( !bInvalidPrePos && pPre->IsTabFrm() )
+ {
+ SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
+ if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
+ {
+ SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
+ if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
+ bInvalidPrePos = true;
+ }
+ }
+
+ if ( bInvalidPrePos )
+ pPre->InvalidatePos();
+ }
+ }
+ }
+ else if ( !pFlow->HasFollow() )
+ {
+ long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
+ long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
+ pFlow->CheckKeep();
+ }
+ }
+ }
+
+ if ( bAbsP )
+ {
+ pFrm->SetCompletePaint();
+
+ SwFrm* pNxt = pFrm->GetIndNext();
+ // #121888# - skip empty section frames
+ while ( pNxt &&
+ pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
+ {
+ pNxt = pNxt->GetIndNext();
+ }
+
+ if ( pNxt )
+ pNxt->InvalidatePos();
+ else
+ {
+ // #104100# - correct condition for setting retouche
+ // flag for vertical layout.
+ if( pFrm->IsRetoucheFrm() &&
+ (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
+ {
+ pFrm->SetRetouche();
+ }
+
+ // A fresh follow frame does not have to be invalidated, because
+ // it is already formatted:
+ if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
+ {
+ if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
+ pFrm->InvalidateNextPos();
+ }
+ }
+ }
+
+ //Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
+ const sal_Bool bPrtWidth =
+ (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
+ const sal_Bool bPrtHeight =
+ (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
+ if ( bPrtWidth || bPrtHeight )
+ {
+ const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ pFrm->SetCompletePaint();
+ }
+ else
+ {
+ // #97597# - consider case that *only* margins between
+ // frame and printing area has changed. Then, frame has to be repainted,
+ // in order to force paint of the margin areas.
+ if ( !bAbsP && (bChgWidth || bChgHeight) )
+ {
+ pFrm->SetCompletePaint();
+ }
+ }
+
+ const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
+ if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
+ bPrtWidth || bPrtHeight || bChgFlyBasePos )
+ {
+ if( pFrm->IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
+ }
+ }
+
+ // Notification of anchored objects
+ if ( pFrm->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
+ SwPageFrm* pPageFrm = 0;
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ // OD 2004-03-31 #i26791# - no general distinction between
+ // Writer fly frames and drawing objects
+ bool bNotify = false;
+ bool bNotifySize = false;
+ SwAnchoredObject* pObj = rObjs[i];
+ SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
+ // --> OD 2004-12-08 #115759#
+ const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
+ if ( !bAnchoredAsChar )
+ // <--
+ {
+ // Notify object, which aren't anchored as-character:
+
+ // always notify objects, if frame position has changed
+ // or if the object is to-page|to-fly anchored.
+ if ( bAbsP ||
+ pContact->ObjAnchoredAtPage() ||
+ pContact->ObjAnchoredAtFly() )
+ {
+ bNotify = true;
+
+ // assure that to-fly anchored Writer fly frames are
+ // registered at the correct page frame, if frame
+ // position has changed.
+ if ( bAbsP && pContact->ObjAnchoredAtFly() &&
+ pObj->ISA(SwFlyFrm) )
+ {
+ // determine to-fly anchored Writer fly frame
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ // determine page frame of to-fly anchored
+ // Writer fly frame
+ SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
+ // determine page frame, if needed.
+ if ( !pPageFrm )
+ {
+ pPageFrm = pFrm->FindPageFrm();
+ }
+ if ( pPageFrm != pFlyPageFrm )
+ {
+ OSL_ENSURE( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
+ if( pFlyPageFrm )
+ pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
+ else
+ pPageFrm->AppendFlyToPage( pFlyFrm );
+ }
+ }
+ }
+ // otherwise the objects are notified in dependence to
+ // its positioning and alignment
+ else
+ {
+ const SwFmtVertOrient& rVert =
+ pContact->GetFmt()->GetVertOrient();
+ if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
+ rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
+ rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
+ ( bChgHeight || bPrtHeight ) )
+ {
+ bNotify = true;
+ }
+ if ( !bNotify )
+ {
+ const SwFmtHoriOrient& rHori =
+ pContact->GetFmt()->GetHoriOrient();
+ if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
+ rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
+ rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
+ ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
+ {
+ bNotify = true;
+ }
+ }
+ }
+ }
+ else if ( bPrtWidth )
+ {
+ // Notify as-character anchored objects, if printing area
+ // width has changed.
+ bNotify = true;
+ bNotifySize = true;
+ }
+
+ // perform notification via the corresponding invalidations
+ if ( bNotify )
+ {
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( bNotifySize )
+ pFlyFrm->_InvalidateSize();
+ // --> OD 2004-12-08 #115759# - no invalidation of
+ // position for as-character anchored objects.
+ if ( !bAnchoredAsChar )
+ {
+ pFlyFrm->_InvalidatePos();
+ }
+ // <--
+ pFlyFrm->_Invalidate();
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ // --> OD 2004-12-08 #115759# - no invalidation of
+ // position for as-character anchored objects.
+ if ( !bAnchoredAsChar )
+ {
+ pObj->InvalidateObjPos();
+ }
+ // <--
+ }
+ else
+ {
+ OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
+ }
+ }
+ }
+ }
+ }
+ else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
+ }
+ }
+
+ // #i9046# Automatic frame width
+ SwFlyFrm* pFly = 0;
+ // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
+ // necessarily have to have an upper!
+ if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
+ // <--
+ {
+ // --> OD 2006-05-08 #i61999#
+ // no invalidation of columned Writer fly frames, because automatic
+ // width doesn't make sense for such Writer fly frames.
+ if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
+ {
+ const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
+
+ // This could be optimized. Basically the fly frame only has to
+ // be invalidated, if the first line of pFrm (if pFrm is a content
+ // frame, for other frame types its the print area) has changed its
+ // size and pFrm was responsible for the current width of pFly. On
+ // the other hand, this is only rarely used and re-calculation of
+ // the fly frame does not cause too much trouble. So we keep it this
+ // way:
+ if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
+ {
+ // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
+ // of as-character anchored fly frames not needed and can cause
+ // layout loops
+ if ( !pFly->ISA(SwFlyInCntFrm) )
+ {
+ pFly->InvalidatePos();
+ }
+ // <--
+ pFly->InvalidateSize();
+ }
+ }
+ // <--
+ }
+}
+
+/*************************************************************************/
+
+SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
+ SwFrmNotify( pLayFrm ),
+ bLowersComplete( sal_False )
+{
+}
+
+/*************************************************************************/
+
+// OD 2004-05-11 #i28701# - local method to invalidate the position of all
+// frames inclusive its floating screen objects, which are lowers of the given
+// layout frame
+void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
+{
+ if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
+ {
+ _rLayoutFrm.InvalidateObjs( true, false );
+ }
+
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ pLowerFrm->InvalidatePos();
+ if ( pLowerFrm->IsTxtFrm() )
+ {
+ static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
+ }
+ else if ( pLowerFrm->IsTabFrm() )
+ {
+ pLowerFrm->InvalidatePrt();
+ }
+
+ pLowerFrm->InvalidateObjs( true, false );
+
+ pLowerFrm = pLowerFrm->GetNext();
+ };
+}
+
+SwLayNotify::~SwLayNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwLayoutFrm *pLay = GetLay();
+ SWRECTFN( pLay )
+ sal_Bool bNotify = sal_False;
+ if ( pLay->Prt().SSize() != aPrt.SSize() )
+ {
+ if ( !IsLowersComplete() )
+ {
+ sal_Bool bInvaPercent;
+
+ if ( pLay->IsRowFrm() )
+ {
+ bInvaPercent = sal_True;
+ long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
+ if( nNew != (aPrt.*fnRect->fnGetHeight)() )
+ ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
+ if( (pLay->Prt().*fnRect->fnGetWidth)()
+ != (aPrt.*fnRect->fnGetWidth)() )
+ ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
+ }
+ else
+ {
+ //Proportionale Anpassung der innenliegenden.
+ //1. Wenn der Formatierte kein Fly ist
+ //2. Wenn er keine Spalten enthaelt
+ //3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
+ // Hoehe danebenliegen.
+ //4. niemals bei SectionFrms.
+ sal_Bool bLow;
+ if( pLay->IsFlyFrm() )
+ {
+ if ( pLay->Lower() )
+ {
+ bLow = !pLay->Lower()->IsColumnFrm() ||
+ (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
+ != (pLay->Prt().*fnRect->fnGetHeight)();
+ }
+ else
+ bLow = sal_False;
+ }
+ else if( pLay->IsSctFrm() )
+ {
+ if ( pLay->Lower() )
+ {
+ if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
+ bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
+ else
+ bLow = pLay->Prt().Width() != aPrt.Width();
+ }
+ else
+ bLow = sal_False;
+ }
+ else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
+ bLow = pLay->Prt().Width() != aPrt.Width();
+ else
+ bLow = sal_True;
+ bInvaPercent = bLow;
+ if ( bLow )
+ {
+ pLay->ChgLowersProp( aPrt.SSize() );
+ }
+ //Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
+ //Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
+ //mithin muss also der 'moeglicherweise passende' Invalidiert werden.
+ //Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
+ //Uppers um eine Moveable-Section handelt.
+ //Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
+ //geworden ist.
+ if ( (pLay->Prt().Height() > aPrt.Height() ||
+ pLay->Prt().Width() > aPrt.Width()) &&
+ (pLay->IsMoveable() || pLay->IsFlyFrm()) )
+ {
+ SwFrm *pTmpFrm = pLay->Lower();
+ if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
+ {
+ while ( pTmpFrm->GetNext() )
+ pTmpFrm = pTmpFrm->GetNext();
+ pTmpFrm->InvalidateNextPos();
+ }
+ }
+ }
+ bNotify = sal_True;
+ //TEUER!! aber wie macht man es geschickter?
+ if( bInvaPercent )
+ pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
+ }
+ if ( pLay->IsTabFrm() )
+ //Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird.
+ ((SwTabFrm*)pLay)->SetComplete();
+ else
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
+ !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
+ //Damit die untergeordneten sauber retouchiert werden.
+ //Problembsp: Flys an den Henkeln packen und verkleinern.
+ //Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
+ pLay->SetCompletePaint();
+ }
+ }
+ //Lower benachrichtigen wenn sich die Position veraendert hat.
+ const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
+ const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
+ const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize();
+
+ if ( bPos && pLay->Lower() && !IsLowersComplete() )
+ pLay->Lower()->InvalidatePos();
+
+ if ( bPrtPos )
+ pLay->SetCompletePaint();
+
+ //Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
+ if ( bSize )
+ {
+ if( pLay->GetNext() )
+ {
+ if ( pLay->GetNext()->IsLayoutFrm() )
+ pLay->GetNext()->_InvalidatePos();
+ else
+ pLay->GetNext()->InvalidatePos();
+ }
+ else if( pLay->IsSctFrm() )
+ pLay->InvalidateNextPos();
+ }
+ if ( !IsLowersComplete() &&
+ !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
+ pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
+ (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ {
+ // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
+ // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
+ // if <pLay> is a cell frame, and its table frame resp. its parent table
+ // frame is locked.
+ // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
+ // only if position of layout frame has changed.
+ bool bUnlockPosOfObjs( bPos );
+ if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
+ {
+ SwTabFrm* pTabFrm( pLay->FindTabFrm() );
+ if ( pTabFrm &&
+ ( pTabFrm->IsJoinLocked() ||
+ ( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsJoinLocked() ) ) )
+ {
+ bUnlockPosOfObjs = false;
+ }
+ }
+ // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
+ // of position of lower objects is allowed.
+ else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
+ {
+ bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
+ }
+ // <--
+ // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
+ else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
+ {
+ bUnlockPosOfObjs = false;
+ }
+ // <--
+ pLay->NotifyLowerObjs( bUnlockPosOfObjs );
+ // <--
+ }
+ if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
+ {
+ // OD 2004-05-11 #i28701#
+ ::lcl_InvalidatePosOfLowers( *pLay );
+ }
+ if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
+ && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
+ ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
+}
+
+/*************************************************************************/
+
+SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
+ SwLayNotify( pFlyFrm ),
+ // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
+ // the Writer fly frame is currently registered at.
+ pOldPage( pFlyFrm->GetPageFrm() ),
+ // <--
+ aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
+{
+}
+
+/*************************************************************************/
+
+SwFlyNotify::~SwFlyNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwFlyFrm *pFly = GetFly();
+ if ( pFly->IsNotifyBack() )
+ {
+ ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
+ {
+ //Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
+ //dass die alte Seite inzwischen vernichtet wurde!
+ ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
+ // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
+ // if Writer fly frame has changed its page
+ if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
+ pFly->GetPageFrm() != pOldPage )
+ {
+ pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+ }
+ pFly->ResetNotifyBack();
+ }
+
+ //Haben sich Groesse oder Position geaendert, so sollte die View
+ //das wissen.
+ SWRECTFN( pFly )
+ const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
+ const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
+ const bool bPrtChgd = aPrt != pFly->Prt();
+ if ( bPosChgd || bFrmChgd || bPrtChgd )
+ {
+ pFly->NotifyDrawObj();
+ }
+ if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
+ {
+ // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
+ // reason: New positioning and alignment (e.g. to-paragraph anchored,
+ // but aligned at page) are introduced.
+ // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
+ // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
+
+ if ( pFly->IsFlyAtCntFrm() )
+ {
+ SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
+ if ( pNxt )
+ {
+ pNxt->InvalidatePos();
+ }
+ }
+
+ // --> OD 2004-11-05 #i26945# - notify anchor.
+ // Needed for negative positioned Writer fly frames
+ if ( pFly->GetAnchorFrm()->IsTxtFrm() )
+ {
+ pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
+ }
+ // <--
+ }
+
+ // OD 2004-05-13 #i28701#
+ // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
+ // further notifications/invalidations, if format is called by grow/shrink
+ if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
+ ( !pFly->ISA(SwFlyFreeFrm) ||
+ !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
+ // <--
+ {
+ // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
+ // on changed frame height.
+ // Note: It doesn't seem to be necessary and can cause layout loops.
+ if ( bPosChgd )
+ // <--
+ {
+ // indicate a restart of the layout process
+ pFly->SetRestartLayoutProcess( true );
+ }
+ else
+ {
+ // lock position
+ pFly->LockPosition();
+
+ if ( !pFly->ConsiderForTextWrap() )
+ {
+ // indicate that object has to be considered for text wrap
+ pFly->SetConsiderForTextWrap( true );
+ // invalidate 'background' in order to allow its 'background'
+ // to wrap around it.
+ pFly->NotifyBackground( pFly->GetPageFrm(),
+ pFly->GetObjRectWithSpaces(),
+ PREP_FLY_ARRIVE );
+ // invalidate position of anchor frame in order to force
+ // a re-format of the anchor frame, which also causes a
+ // re-format of the invalid previous frames of the anchor frame.
+ pFly->AnchorFrm()->InvalidatePos();
+ }
+ }
+ }
+}
+
+/*************************************************************************/
+
+SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
+ SwFrmNotify( pCntntFrm ),
+ // OD 08.01.2004 #i11859#
+ mbChkHeightOfLastLine( false ),
+ mnHeightOfLastLine( 0L ),
+ // OD 2004-02-26 #i25029#
+ mbInvalidatePrevPrtArea( false ),
+ mbBordersJoinedWithPrev( false )
+{
+ // OD 08.01.2004 #i11859#
+ if ( pCntntFrm->IsTxtFrm() )
+ {
+ SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
+ if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
+ {
+ const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
+ const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
+ if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
+ {
+ mbChkHeightOfLastLine = true;
+ mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
+ }
+ }
+ }
+}
+
+/*************************************************************************/
+
+SwCntntNotify::~SwCntntNotify()
+{
+ // --> OD 2005-07-29 #i49383#
+ if ( mbFrmDeleted )
+ {
+ return;
+ }
+ // <--
+
+ SwCntntFrm *pCnt = GetCnt();
+ if ( bSetCompletePaintOnInvalidate )
+ pCnt->SetCompletePaint();
+
+ SWRECTFN( pCnt )
+ if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
+ pCnt->Frm().SSize() != aFrm.SSize()))
+ {
+ SwLayoutFrm* pCell = pCnt->GetUpper();
+ while( !pCell->IsCellFrm() && pCell->GetUpper() )
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell->IsCellFrm(), "Where's my cell?" );
+ if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
+ pCell->InvalidatePrt(); //fuer vertikale Ausrichtung.
+ }
+
+ // OD 2004-02-26 #i25029#
+ if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
+ pCnt->IsTxtFrm() &&
+ !pCnt->IsFollow() && !pCnt->GetIndPrev() )
+ {
+ // determine previous frame
+ SwFrm* pPrevFrm = pCnt->FindPrev();
+ // skip empty section frames and hidden text frames
+ {
+ while ( pPrevFrm &&
+ ( ( pPrevFrm->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
+ ( pPrevFrm->IsTxtFrm() &&
+ static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
+ {
+ pPrevFrm = pPrevFrm->FindPrev();
+ }
+ }
+
+ // Invalidate printing area of found previous frame
+ if ( pPrevFrm )
+ {
+ if ( pPrevFrm->IsSctFrm() )
+ {
+ if ( pCnt->IsInSct() )
+ {
+ // Note: found previous frame is a section frame and
+ // <pCnt> is also inside a section.
+ // Thus due to <mbBordersJoinedWithPrev>,
+ // <pCnt> had joined its borders/shadow with the
+ // last content of the found section.
+ // Invalidate printing area of last content in found section.
+ SwFrm* pLstCntntOfSctFrm =
+ static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
+ if ( pLstCntntOfSctFrm )
+ {
+ pLstCntntOfSctFrm->InvalidatePrt();
+ }
+ }
+ }
+ else
+ {
+ pPrevFrm->InvalidatePrt();
+ }
+ }
+ }
+
+ sal_Bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
+
+ if ( pCnt->IsNoTxtFrm() )
+ {
+ //Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
+ //mitbekommen, damit sie Ihr Window entsprechend verschieben.
+ ViewShell *pSh = pCnt->getRootFrm()->GetCurrShell();
+ if ( pSh )
+ {
+ SwOLENode *pNd;
+ if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
+ (pNd->GetOLEObj().IsOleRef() ||
+ pNd->IsOLESizeInvalid()) )
+ {
+ OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrm" );
+ SwFlyFrm *pFly = pCnt->FindFlyFrm();
+ svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
+ SwFEShell *pFESh = 0;
+ ViewShell *pTmp = pSh;
+ do
+ { if ( pTmp->ISA( SwCrsrShell ) )
+ {
+ pFESh = (SwFEShell*)pTmp;
+ // #108369#: Here used to be the condition if (!bFirst).
+ // I think this should mean "do not call CalcAndSetScale"
+ // if the frame is formatted for the first time.
+ // Unfortunately this is not valid anymore since the
+ // SwNoTxtFrm already gets a width during CalcLowerPreps.
+ // Nevertheless, the indention of !bFirst seemed to be
+ // to assure that the OLE objects have already been notified
+ // if necessary before calling CalcAndSetScale.
+ // So I replaced !bFirst by !IsOLESizeInvalid. There is
+ // one additional problem specific to the word import:
+ // The layout is calculated _before_ calling PrtOLENotify,
+ // and the OLE objects are not invalidated during import.
+ // Therefore I added the condition !IsUpdateExpFld,
+ // have a look at the occurrence of CalcLayout in
+ // uiview/view.cxx.
+ if ( !pNd->IsOLESizeInvalid() &&
+ !pSh->GetDoc()->IsUpdateExpFld() )
+ pFESh->CalcAndSetScale( xObj, &pFly->Prt(), &pFly->Frm());
+ }
+ pTmp = (ViewShell*)pTmp->GetNext();
+ } while ( pTmp != pSh );
+
+ if ( pFESh && pNd->IsOLESizeInvalid() )
+ {
+ pNd->SetOLESizeInvalid( sal_False );
+ //TODO/LATER: needs OnDocumentPrinterChanged
+ //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
+ pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
+ }
+ }
+ //dito Animierte Grafiken
+ if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
+ {
+ ((SwNoTxtFrm*)pCnt)->StopAnimation();
+ pSh->InvalidateWindows( Frm() );
+ }
+ }
+ }
+
+ if ( bFirst )
+ {
+ pCnt->SetRetouche(); //fix(13870)
+
+ SwDoc *pDoc = pCnt->GetNode()->GetDoc();
+ if ( pDoc->GetSpzFrmFmts()->Count() &&
+ !pDoc->IsLoaded() && !pDoc->IsNewDoc() )
+ {
+ //Der Frm wurde wahrscheinlich zum ersten mal formatiert.
+ //Wenn ein Filter Flys oder Zeichenobjekte einliest und diese
+ //Seitengebunden sind, hat er ein Problem, weil er i.d.R. die
+ //Seitennummer nicht kennt. Er weiss lediglich welches der Inhalt
+ //(CntntNode) an dieser Stelle ist.
+ //Die Filter stellen dazu das Ankerattribut der Objekte so ein, dass
+ //sie vom Typ zwar Seitengebunden sind, aber der Index des Ankers
+ //auf diesen CntntNode zeigt.
+ //Hier werden diese vorlauefigen Verbindungen aufgeloest.
+
+ const SwPageFrm *pPage = 0;
+ SwNodeIndex *pIdx = 0;
+ SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ if ( !pPage )
+ pPage = pCnt->FindPageFrm();
+ SwFrmFmt *pFmt = (*pTbl)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+
+ if ((FLY_AT_PAGE != rAnch.GetAnchorId()) &&
+ (FLY_AT_PARA != rAnch.GetAnchorId()))
+ {
+ continue; //#60878# nicht etwa zeichengebundene.
+ }
+
+ if ( rAnch.GetCntntAnchor() )
+ {
+ if ( !pIdx )
+ {
+ pIdx = new SwNodeIndex( *pCnt->GetNode() );
+ }
+ if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
+ {
+ if (FLY_AT_PAGE == rAnch.GetAnchorId())
+ {
+ OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
+ SwFmtAnchor aAnch( rAnch );
+ aAnch.SetAnchor( 0 );
+ aAnch.SetPageNum( pPage->GetPhyPageNum() );
+ pFmt->SetFmtAttr( aAnch );
+ if ( RES_DRAWFRMFMT != pFmt->Which() )
+ pFmt->MakeFrms();
+ }
+ }
+ }
+ }
+ delete pIdx;
+ }
+ }
+
+ // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
+ // if height of last line has changed.
+ if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
+ {
+ if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
+ {
+ pCnt->InvalidateNextPrtArea();
+ }
+ }
+
+ // --> OD 2005-03-07 #i44049#
+ if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
+ {
+ pCnt->InvalidateObjs( true );
+ }
+ // <--
+
+ // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
+ // anchored objects due to a change of its anchor character from
+ // method <SwTxtFrm::Format(..)>.
+ if ( pCnt->IsTxtFrm() )
+ {
+ SwTxtFrm* pMasterFrm = pCnt->IsFollow()
+ ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
+ : static_cast<SwTxtFrm*>(pCnt);
+ if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
+ pMasterFrm->GetDrawObjs() )
+ {
+ SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
+ for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AT_CHAR )
+ {
+ pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
+ }
+ }
+ }
+ }
+ // <--
+}
+
+/*************************************************************************/
+
+void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
+ SwFrm *pFrm, SwPageFrm *pPage )
+{
+ for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetCntntAnchor() &&
+ (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
+ {
+ const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
+ //Wird ein Rahmen oder ein SdrObject beschrieben?
+ const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
+ // OD 23.06.2003 #108784# - append also drawing objects anchored
+ // as character.
+ const bool bDrawObjInCntnt = bSdrObj &&
+ (rAnch.GetAnchorId() == FLY_AS_CHAR);
+
+ if( bFlyAtFly ||
+ (rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
+ bDrawObjInCntnt )
+ {
+ SdrObject* pSdrObj = 0;
+ if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
+ {
+ OSL_ENSURE( !bSdrObj, "DrawObject not found." );
+ pFmt->GetDoc()->DelFrmFmt( pFmt );
+ --i;
+ continue;
+ }
+ if ( pSdrObj )
+ {
+ if ( !pSdrObj->GetPage() )
+ {
+ pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
+ InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
+ }
+
+ SwDrawContact* pNew =
+ static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
+ if ( !pNew->GetAnchorFrm() )
+ {
+ pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
+ }
+ // OD 19.06.2003 #108784# - add 'virtual' drawing object,
+ // if necessary. But control objects have to be excluded.
+ else if ( !::CheckControlLayer( pSdrObj ) &&
+ pNew->GetAnchorFrm() != pFrm &&
+ !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
+ pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
+
+ // for repaint, use new ActionChanged()
+ // pDrawVirtObj->SendRepaintBroadcast();
+ pDrawVirtObj->ActionChanged();
+ }
+
+ }
+ else
+ {
+ SwFlyFrm *pFly;
+ if( bFlyAtFly )
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
+ else
+ pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
+ pFly->Lock();
+ pFrm->AppendFly( pFly );
+ pFly->Unlock();
+ if ( pPage )
+ ::RegistFlys( pPage, pFly );
+ }
+ }
+ }
+ }
+}
+
+bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
+{
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
+ if ( RES_FLYFRMFMT == pFmt->Which() )
+ {
+ const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
+ const SwFlyFrm* pTmpFrm;
+ for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
+ {
+ if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
+ return true;
+ }
+ }
+ else
+ {
+ SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
+ if ( pContact )
+ return pContact->GetAnchorFrm() != 0;
+ }
+ return false;
+}
+
+/** helper method to determine, if a <SwFrmFmt>, which has an object connected,
+ is located in header or footer.
+
+ OD 23.06.2003 #108784#
+
+ @author OD
+*/
+bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
+{
+ bool bRetVal = false;
+
+ const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
+
+ if (rAnch.GetAnchorId() != FLY_AT_PAGE)
+ {
+ bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
+ }
+
+ return bRetVal;
+}
+
+void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib )
+{
+ //Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
+ //Layout.
+ //Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate
+ //uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch
+ //Objecte die in zeichengebundenen verankert sind.
+
+ SwSpzFrmFmts aCpy( 255, 255 );
+ aCpy.Insert( pTbl, 0 );
+
+ sal_uInt16 nOldCnt = USHRT_MAX;
+
+ while ( aCpy.Count() && aCpy.Count() != nOldCnt )
+ {
+ nOldCnt = aCpy.Count();
+ for ( int i = 0; i < int(aCpy.Count()); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ sal_Bool bRemove = sal_False;
+ if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
+ (rAnch.GetAnchorId() == FLY_AS_CHAR))
+ {
+ //Seitengebunde sind bereits verankert, zeichengebundene
+ //will ich hier nicht.
+ bRemove = sal_True;
+ }
+ else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
+ ::lcl_InHeaderOrFooter( *pFmt ) )
+ {
+ // OD 23.06.2003 #108784# - correction: for objects in header
+ // or footer create frames, in spite of the fact that an connected
+ // objects already exists.
+ //Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
+ //keine abhaengigen Existieren, andernfalls, oder wenn das
+ //MakeFrms keine abhaengigen erzeugt, entfernen.
+ pFmt->MakeFrms();
+ bRemove = ::lcl_ObjConnected( pFmt, pSib );
+ }
+ if ( bRemove )
+ {
+ aCpy.Remove( sal_uInt16(i) );
+ --i;
+ }
+ }
+ }
+ aCpy.Remove( 0, aCpy.Count() );
+}
+
+/** local method to set 'working' position for newly inserted frames
+
+ OD 12.08.2003 #i17969#
+
+ @author OD
+*/
+void lcl_SetPos( SwFrm& _rNewFrm,
+ const SwLayoutFrm& _rLayFrm )
+{
+ SWRECTFN( (&_rLayFrm) )
+ (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
+ // move position by one SwTwip in text flow direction in order to get
+ // notifications for a new calculated position after its formatting.
+ if ( bVert )
+ _rNewFrm.Frm().Pos().X() -= 1;
+ else
+ _rNewFrm.Frm().Pos().Y() += 1;
+}
+
+void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
+ sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
+ SwFrm *pPrv )
+{
+ pDoc->BlockIdling();
+ SwRootFrm* pLayout = pLay->getRootFrm();
+ const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
+ if( bOldCallbackActionEnabled )
+ pLayout->SetCallbackActionEnabled( sal_False );
+
+ //Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann
+ //werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
+ //und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
+ //angelegt.
+ //Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
+ //Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
+ //lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
+ //ertraegliches mass reduziert hat.
+ //Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
+ //Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach
+ //Node noch etwas drauf.
+ //Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist
+ //(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
+ //ausgegengen.
+ const sal_Bool bStartPercent = bPages && !nEndIndex;
+
+ SwPageFrm *pPage = pLay->FindPageFrm();
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+ SwFrm *pFrm = 0;
+ sal_Bool bBreakAfter = sal_False;
+
+ SwActualSection *pActualSection = 0;
+ SwLayHelper *pPageMaker;
+
+ //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress
+ //an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
+ //passiert erst am Ende der Funktion.
+ if ( bPages )
+ {
+ // Attention: the SwLayHelper class uses references to the content-,
+ // page-, layout-frame etc. and may change them!
+ pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
+ pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
+ if( bStartPercent )
+ {
+ const sal_uLong nPageCount = pPageMaker->CalcPageCount();
+ if( nPageCount )
+ bObjsDirect = sal_False;
+ }
+ }
+ else
+ pPageMaker = NULL;
+
+ if( pLay->IsInSct() &&
+ ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
+ // abgefangen, deren Flags noch nicht ermittelt werden koennen,
+ // so z.B. beim Einfuegen einer Tabelle
+ {
+ SwSectionFrm* pSct = pLay->FindSctFrm();
+ // Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
+ // Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
+ // Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
+ // Kandidat fuer pActualSection.
+ // Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
+ // eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
+ // aufgebrochen werden.
+ if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
+ ( !pLay->IsInTab() || pSct->IsInTab() ) )
+ {
+ pActualSection = new SwActualSection( 0, pSct, 0 );
+ OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
+ "_InsertCnt: Wrong Call" );
+ }
+ }
+
+ //If a section is "open", the pActualSection points to an SwActualSection.
+ //If the page breaks, for "open" sections a follow will created.
+ //For nested sections (which have, however, not a nested layout),
+ //the SwActualSection class has a member, which points to an upper(section).
+ //When the "inner" section finishs, the upper will used instead.
+
+ while( sal_True )
+ {
+ SwNode *pNd = pDoc->GetNodes()[nIndex];
+ if ( pNd->IsCntntNode() )
+ {
+ SwCntntNode* pNode = (SwCntntNode*)pNd;
+ pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) :
+ pNode->MakeFrm( pLay );
+ if( pPageMaker )
+ pPageMaker->CheckInsert( nIndex );
+
+ pFrm->InsertBehind( pLay, pPrv );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ if ( pFrm->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ // --> OD 2006-08-28 #i68958#
+ // The information flags of the text frame are validated
+ // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
+ // The information flags have to be invalidated, because
+ // it is possible, that the one of its upper frames
+ // isn't inserted into the layout.
+ pFrm->InvalidateInfFlags();
+ // <--
+ }
+ }
+ // <--
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+ pPrv = pFrm;
+
+ if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
+ AppendObjs( pTbl, nIndex, pFrm, pPage );
+ }
+ else if ( pNd->IsTableNode() )
+ { //Sollten wir auf eine Tabelle gestossen sein?
+ SwTableNode *pTblNode = (SwTableNode*)pNd;
+
+ // #108116# loading may produce table structures that GCLines
+ // needs to clean up. To keep table formulas correct, change
+ // all table formulas to internal (BOXPTR) representation.
+ SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+ pTblNode->GetTable().GCLines();
+
+ pFrm = pTblNode->MakeFrm( pLay );
+
+ if( pPageMaker )
+ pPageMaker->CheckInsert( nIndex );
+
+ pFrm->InsertBehind( pLay, pPrv );
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ if ( bObjsDirect && pTbl->Count() )
+ ((SwTabFrm*)pFrm)->RegistFlys();
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ pPrv = pFrm;
+ //Index auf den Endnode der Tabellensection setzen.
+ nIndex = pTblNode->EndOfSectionIndex();
+
+ SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
+ while ( pTmpFrm )
+ {
+ pTmpFrm->CheckDirChange();
+ pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
+ }
+
+ }
+ else if ( pNd->IsSectionNode() )
+ {
+ SwSectionNode *pNode = (SwSectionNode*)pNd;
+ if( pNode->GetSection().CalcHiddenFlag() )
+ // ist versteckt, ueberspringe den Bereich
+ nIndex = pNode->EndOfSectionIndex();
+ else
+ {
+ pFrm = pNode->MakeFrm( pLay );
+ pActualSection = new SwActualSection( pActualSection,
+ (SwSectionFrm*)pFrm, pNode );
+ if ( pActualSection->GetUpper() )
+ {
+ //Hinter den Upper einsetzen, beim EndNode wird der "Follow"
+ //des Uppers erzeugt.
+ SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
+ pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
+ // OD 25.03.2003 #108339# - direct initialization of section
+ // after insertion in the layout
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+ }
+ else
+ {
+ pFrm->InsertBehind( pLay, pPrv );
+ // OD 25.03.2003 #108339# - direct initialization of section
+ // after insertion in the layout
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+
+ // --> FME 2004-09-08 #i33963#
+ // Do not trust the IsInFtn flag. If we are currently
+ // building up a table, the upper of pPrv may be a cell
+ // frame, but the cell frame does not have an upper yet.
+ if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
+ // <--
+ {
+ if( pPrv->IsSctFrm() )
+ pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
+ if( pPrv && pPrv->IsTxtFrm() )
+ ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ }
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for next paragraph will change
+ // and relation CONTENT_FLOWS_TO for previous paragraph will change.
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ // no notification, if <ViewShell> is in construction
+ if ( pViewShell && !pViewShell->IsInConstructor() &&
+ pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ pFrm->CheckDirChange();
+
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ // OD 20.11.2002 #105405# - no page, no invalidate.
+ if ( pPage )
+ {
+ // OD 18.09.2002 #100522#
+ // invalidate page in order to force format and paint of
+ // inserted section frame
+ pFrm->InvalidatePage( pPage );
+
+ // FME 10.11.2003 #112243#
+ // Invalidate fly content flag:
+ if ( pFrm->IsInFly() )
+ pPage->InvalidateFlyCntnt();
+
+ // OD 14.11.2002 #104684# - invalidate page content in order to
+ // force format and paint of section content.
+ pPage->InvalidateCntnt();
+ }
+
+ pLay = (SwLayoutFrm*)pFrm;
+ if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = pLay->GetNextLayoutLeaf();
+ pPrv = 0;
+ }
+ }
+ else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ OSL_ENSURE( pActualSection, "Sectionende ohne Anfang?" );
+ OSL_ENSURE( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
+ "Sectionende mit falschen Start Node?" );
+
+ //Section schliessen, ggf. die umgebende Section wieder
+ //aktivieren.
+ SwActualSection *pTmp = pActualSection->GetUpper();
+ delete pActualSection;
+ pLay = pLay->FindSctFrm();
+ if ( 0 != (pActualSection = pTmp) )
+ {
+ //Koennte noch sein, das der letzte SectionFrm leer geblieben
+ //ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
+ if ( !pLay->ContainsCntnt() )
+ {
+ SwFrm *pTmpFrm = pLay;
+ pLay = pTmpFrm->GetUpper();
+ pPrv = pTmpFrm->GetPrev();
+ pTmpFrm->Remove();
+ delete pTmpFrm;
+ }
+ else
+ {
+ pPrv = pLay;
+ pLay = pLay->GetUpper();
+ }
+
+ // new section frame
+ pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
+ pFrm->InsertBehind( pLay, pPrv );
+ static_cast<SwSectionFrm*>(pFrm)->Init();
+
+ // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
+ // for setting position at newly inserted frame
+ lcl_SetPos( *pFrm, *pLay );
+
+ SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
+
+ // a follow has to be appended to the new section frame
+ SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
+ if ( pFollow )
+ {
+ pOuterSectionFrm->SetFollow( NULL );
+ pOuterSectionFrm->InvalidateSize();
+ ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
+ }
+
+ // Wir wollen keine leeren Teile zuruecklassen
+ if( ! pOuterSectionFrm->IsColLocked() &&
+ ! pOuterSectionFrm->ContainsCntnt() )
+ {
+ pOuterSectionFrm->DelEmpty( sal_True );
+ delete pOuterSectionFrm;
+ }
+ pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
+
+ pLay = (SwLayoutFrm*)pFrm;
+ if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = pLay->GetNextLayoutLeaf();
+ pPrv = 0;
+ }
+ else
+ {
+ //Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
+ //weiter.
+ pPrv = pLay;
+ pLay = pLay->GetUpper();
+ }
+ }
+ else if( pNd->IsStartNode() &&
+ SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() )
+ {
+ if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
+ {
+ SwFlyFrm* pFly = pLay->FindFlyFrm();
+ if( pFly )
+ AppendObjs( pTbl, nIndex, pFly, pPage );
+ }
+ }
+ else
+ // Weder Cntnt noch Tabelle noch Section,
+ // also muessen wir fertig sein.
+ break;
+
+ ++nIndex;
+ // Der Endnode wird nicht mehr mitgenommen, es muss vom
+ // Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
+ // des Bereichs vor dem EndIndex liegt!
+ if ( nEndIndex && nIndex >= nEndIndex )
+ break;
+ }
+
+ if ( pActualSection )
+ {
+ //Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
+ if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
+ {
+ pLay->Remove();
+ delete pLay;
+ }
+ delete pActualSection;
+ }
+
+ if ( bPages ) //Jetzt noch die Flys verbinden lassen.
+ {
+ if ( !bDontCreateObjects )
+ AppendAllObjs( pTbl, pLayout );
+ bObjsDirect = sal_True;
+ }
+
+ if( pPageMaker )
+ {
+ pPageMaker->CheckFlyCache( pPage );
+ delete pPageMaker;
+ if( pDoc->GetLayoutCache() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ pDoc->GetLayoutCache()->CompareLayout( *pDoc );
+#endif
+ pDoc->GetLayoutCache()->ClearImpl();
+ }
+ }
+
+ pDoc->UnblockIdling();
+ if( bOldCallbackActionEnabled )
+ pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
+}
+
+
+void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
+ const SwNodeIndex &rEndIdx )
+{
+ bObjsDirect = sal_False;
+
+ SwNodeIndex aTmp( rSttIdx );
+ sal_uLong nEndIdx = rEndIdx.GetIndex();
+ SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
+ pDoc->GetNodes()[ nEndIdx-1 ]);
+ if ( pNd )
+ {
+ sal_Bool bApres = aTmp < rSttIdx;
+ SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
+ SwFrm* pFrm;
+ while( 0 != (pFrm = aNode2Layout.NextFrm()) )
+ {
+ SwLayoutFrm *pUpper = pFrm->GetUpper();
+ SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
+ sal_Bool bOldLock, bOldFtn;
+ if( pFtnFrm )
+ {
+ bOldFtn = pFtnFrm->IsColLocked();
+ pFtnFrm->ColLock();
+ }
+ else
+ bOldFtn = sal_True;
+ SwSectionFrm* pSct = pUpper->FindSctFrm();
+ // Es sind innerhalb von Fussnoten nur die Bereiche interessant,
+ // die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
+ // in denen die Fussnoten(Container) liegen.
+ // #109767# Table frame is in section, insert section in cell frame.
+ if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
+ pSct = NULL;
+ if( pSct )
+ { // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
+ bOldLock = pSct->IsColLocked();
+ pSct->ColLock();
+ }
+ else
+ bOldLock = sal_True;
+
+ // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
+ // auf die naechste Seite schieben. Innerhalb eines Rahmens auch
+ // nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
+ // Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
+ sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
+ sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
+ (!pFrm->IsInTab() || pFrm->IsTabFrm() );
+ if ( bMoveNext && bAllowMove )
+ {
+ SwFrm *pMove = pFrm;
+ SwFrm *pPrev = pFrm->GetPrev();
+ SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ OSL_ENSURE( pTmp, "Missing FlowFrm" );
+
+ if ( bApres )
+ {
+ // Wir wollen, dass der Rest der Seite leer ist, d.h.
+ // der naechste muss auf die naechste Seite wandern.
+ // Dieser kann auch in der naechsten Spalte stehen!
+ OSL_ENSURE( !pTmp->HasFollow(), "Follows forbidden" );
+ pPrev = pFrm;
+ // Wenn unser umgebender SectionFrm einen Next besitzt,
+ // so soll dieser ebenfalls gemoved werden!
+ pMove = pFrm->GetIndNext();
+ SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
+ if( pCol )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ do
+ {
+ if( pCol && !pMove )
+ { // Bisher haben wir keinen Nachfolger gefunden
+ // jetzt gucken wir in die naechste Spalte
+ pMove = pCol->ContainsAny();
+ if( pCol->GetNext() )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ else if( pCol->IsInSct() )
+ { // Wenn es keine naechste Spalte gibt, wir aber
+ // innerhalb eines spaltigen Bereichs sind,
+ // koennte es noch ausserhalb des Bereich
+ // (Seiten-)Spalten geben
+ pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
+ if( pCol )
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ }
+ else
+ pCol = NULL;
+ }
+ // Falls hier verschrottete SectionFrms herumgammeln,
+ // muessen diese uebersprungen werden.
+ while( pMove && pMove->IsSctFrm() &&
+ !((SwSectionFrm*)pMove)->GetSection() )
+ pMove = pMove->GetNext();
+ } while( !pMove && pCol );
+
+ if( pMove )
+ {
+ if ( pMove->IsCntntFrm() )
+ pTmp = (SwCntntFrm*)pMove;
+ else if ( pMove->IsTabFrm() )
+ pTmp = (SwTabFrm*)pMove;
+ else if ( pMove->IsSctFrm() )
+ {
+ pMove = ((SwSectionFrm*)pMove)->ContainsAny();
+ if( pMove )
+ pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ else
+ pTmp = NULL;
+ }
+ }
+ else
+ pTmp = 0;
+ }
+ else
+ {
+ OSL_ENSURE( !pTmp->IsFollow(), "Follows really forbidden" );
+ // Bei Bereichen muss natuerlich der Inhalt auf die Reise
+ // geschickt werden.
+ if( pMove->IsSctFrm() )
+ {
+ while( pMove && pMove->IsSctFrm() &&
+ !((SwSectionFrm*)pMove)->GetSection() )
+ pMove = pMove->GetNext();
+ if( pMove && pMove->IsSctFrm() )
+ pMove = ((SwSectionFrm*)pMove)->ContainsAny();
+ if( pMove )
+ pTmp = SwFlowFrm::CastFlowFrm( pMove );
+ else
+ pTmp = NULL;
+ }
+ }
+
+ if( pTmp )
+ {
+ SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
+ // MoveFwd==sal_True bedeutet, dass wir auf der gleichen
+ // Seite geblieben sind, wir wollen aber die Seite wechseln,
+ // sofern dies moeglich ist
+ sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
+ pTmp->LockJoin();
+ while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
+ {
+ if( pOldUp == pTmp->GetFrm()->GetUpper() )
+ break;
+ pOldUp = pTmp->GetFrm()->GetUpper();
+ }
+ if( !bTmpOldLock )
+ pTmp->UnlockJoin();
+ }
+ ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
+ pFrm->IsInDocBody(), nEndIdx, pPrev );
+ }
+ else
+ {
+ sal_Bool bSplit;
+ SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
+ // Wenn in einen SectionFrm ein anderer eingefuegt wird,
+ // muss dieser aufgebrochen werden
+ if( pSct && rSttIdx.GetNode().IsSectionNode() )
+ {
+ bSplit = pSct->SplitSect( pFrm, bApres );
+ // Wenn pSct nicht aufgespalten werden konnte
+ if( !bSplit && !bApres )
+ {
+ pUpper = pSct->GetUpper();
+ pPrv = pSct->GetPrev();
+ }
+ }
+ else
+ bSplit = sal_False;
+ ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
+ nEndIdx, pPrv );
+ // OD 23.06.2003 #108784# - correction: append objects doesn't
+ // depend on value of <bAllowMove>
+ if( !bDontCreateObjects )
+ {
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+ if( pTbl->Count() )
+ AppendAllObjs( pTbl, pUpper );
+ }
+
+ // Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
+ // muss das Splitten rueckgaengig gemacht werden
+ if( bSplit && pSct && pSct->GetNext()
+ && pSct->GetNext()->IsSctFrm() )
+ pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
+ if( pFrm->IsInFly() )
+ pFrm->FindFlyFrm()->_Invalidate();
+ if( pFrm->IsInTab() )
+ pFrm->InvalidateSize();
+ }
+
+ SwPageFrm *pPage = pUpper->FindPageFrm();
+ SwFrm::CheckPageDescs( pPage, sal_False );
+ if( !bOldFtn )
+ pFtnFrm->ColUnlock();
+ if( !bOldLock )
+ {
+ pSct->ColUnlock();
+ // Zum Beispiel beim Einfuegen von gelinkten Bereichen,
+ // die wiederum Bereiche enthalten, kann pSct jetzt leer sein
+ // und damit ruhig zerstoert werden.
+ if( !pSct->ContainsCntnt() )
+ {
+ pSct->DelEmpty( sal_True );
+ pUpper->getRootFrm()->RemoveFromList( pSct );
+ delete pSct;
+ }
+ }
+ }
+ }
+
+ bObjsDirect = sal_True;
+}
+
+
+/*************************************************************************/
+
+SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
+ SwCacheObj( pMod ),
+ rAttrSet( pConstructor->IsCntntFrm()
+ ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
+ : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
+ rUL ( rAttrSet.GetULSpace() ),
+ // --> OD 2008-12-04 #i96772#
+ // LRSpaceItem is copied due to the possibility that it is adjusted - see below
+ rLR ( rAttrSet.GetLRSpace() ),
+ // <--
+ rBox ( rAttrSet.GetBox() ),
+ rShadow ( rAttrSet.GetShadow() ),
+ aFrmSize( rAttrSet.GetFrmSize().GetSize() )
+{
+ // --> OD 2008-12-02 #i96772#
+ const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
+ if ( pTxtFrm )
+ {
+ pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
+ }
+
+ //Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
+ //nicht initialisiert!
+
+ //Muessen alle einmal berechnet werden:
+ bTopLine = bBottomLine = bLeftLine = bRightLine =
+ bTop = bBottom = bLine = sal_True;
+
+ bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
+ // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
+ // and <bJoinedWithNext>, which aren't initialized by default.
+ bCachedJoinedWithPrev = sal_False;
+ bCachedJoinedWithNext = sal_False;
+
+ bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
+}
+
+SwBorderAttrs::~SwBorderAttrs()
+{
+ ((SwModify*)pOwner)->SetInCache( sal_False );
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
+|*
+|* Beschreibung Die Calc-Methoden errechnen zusaetzlich zu den
+|* von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
+|* der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
+|* Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
+|* groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
+|*
+|*************************************************************************/
+
+void SwBorderAttrs::_CalcTop()
+{
+ nTop = CalcTopLine() + rUL.GetUpper();
+ bTop = sal_False;
+}
+
+void SwBorderAttrs::_CalcBottom()
+{
+ nBottom = CalcBottomLine() + rUL.GetLower();
+ bBottom = sal_False;
+}
+
+long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
+{
+ long nRight=0;
+
+ if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
+ // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
+ // and right border are painted on the right respectively left.
+ if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
+ nRight = CalcLeftLine();
+ else
+ nRight = CalcRightLine();
+
+ }
+ // for paragraphs, "left" is "before text" and "right" is "after text"
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ nRight += rLR.GetLeft();
+ else
+ nRight += rLR.GetRight();
+
+ // correction: retrieve left margin for numbering in R2L-layout
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ {
+ nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
+ }
+
+ return nRight;
+}
+
+long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
+{
+ long nLeft=0;
+
+ if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
+ // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
+ // and right border are painted on the right respectively left.
+ if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
+ nLeft = CalcRightLine();
+ else
+ nLeft = CalcLeftLine();
+ }
+
+ // for paragraphs, "left" is "before text" and "right" is "after text"
+ if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
+ nLeft += rLR.GetRight();
+ else
+ nLeft += rLR.GetLeft();
+
+
+ // correction: do not retrieve left margin for numbering in R2L-layout
+// if ( pCaller->IsTxtFrm() )
+ if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
+ {
+ nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
+ }
+
+ return nLeft;
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
+|* CalcLeftLine(), CalcRightLine()
+|*
+|* Beschreibung Berechnung der Groessen fuer Umrandung und Schatten.
+|* Es kann auch ohne Linien ein Abstand erwuenscht sein,
+|* dieser wird dann nicht vom Attribut sondern hier
+|* beruecksichtigt (bBorderDist, z.B. fuer Zellen).
+|*
+|*************************************************************************/
+
+void SwBorderAttrs::_CalcTopLine()
+{
+ nTopLine = (bBorderDist && !rBox.GetTop())
+ ? rBox.GetDistance (BOX_LINE_TOP)
+ : rBox.CalcLineSpace(BOX_LINE_TOP);
+ nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
+ bTopLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcBottomLine()
+{
+ nBottomLine = (bBorderDist && !rBox.GetBottom())
+ ? rBox.GetDistance (BOX_LINE_BOTTOM)
+ : rBox.CalcLineSpace(BOX_LINE_BOTTOM);
+ nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
+ bBottomLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcLeftLine()
+{
+ nLeftLine = (bBorderDist && !rBox.GetLeft())
+ ? rBox.GetDistance (BOX_LINE_LEFT)
+ : rBox.CalcLineSpace(BOX_LINE_LEFT);
+ nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
+ bLeftLine = sal_False;
+}
+
+void SwBorderAttrs::_CalcRightLine()
+{
+ nRightLine = (bBorderDist && !rBox.GetRight())
+ ? rBox.GetDistance (BOX_LINE_RIGHT)
+ : rBox.CalcLineSpace(BOX_LINE_RIGHT);
+ nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
+ bRightLine = sal_False;
+}
+
+/*************************************************************************/
+
+void SwBorderAttrs::_IsLine()
+{
+ bIsLine = rBox.GetTop() || rBox.GetBottom() ||
+ rBox.GetLeft()|| rBox.GetRight();
+ bLine = sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
+|*
+|* Die Umrandungen benachbarter Absaetze werden nach folgendem
+|* Algorithmus zusammengefasst:
+|*
+|* 1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
+|* Umrandung oben aufweist und 3. Zutrifft.
+|* Zusaetzlich muss der Absatz mindestens rechts oder links oder
+|* unten eine Umrandung haben.
+|* 2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
+|* Umrandung untern aufweist und 3. Zustrifft.
+|* Zusaetzlich muss der Absatz mindestens rechts oder links oder
+|* oben eine Umrandung haben.
+|* 3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
+|* sind identisch.
+|*
+|*************************************************************************/
+inline int CmpLines( const editeng::SvxBorderLine *pL1, const editeng::SvxBorderLine *pL2 )
+{
+ return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
+}
+
+// OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
+// OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
+// instead of only the right LR-spacing, because R2L-layout has to be
+// considered.
+sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
+ const SwFrm *pCaller,
+ const SwFrm *pCmp ) const
+{
+ return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) &&
+ CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
+ CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
+ // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
+ CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
+}
+
+sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
+ const SwFrm& _rCmpFrm ) const
+{
+ sal_Bool bReturnVal = sal_False;
+
+ SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
+ const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
+ if ( rShadow == rCmpAttrs.GetShadow() &&
+ CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
+ CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
+ CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
+ )
+ {
+ bReturnVal = sal_True;
+ }
+
+ return bReturnVal;
+}
+
+// OD 21.05.2003 #108789# - method to determine, if borders are joined with
+// previous frame. Calculated value saved in cached value <bJoinedWithPrev>
+// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
+void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm )
+{
+ // set default
+ bJoinedWithPrev = sal_False;
+
+ if ( _rFrm.IsTxtFrm() )
+ {
+ // text frame can potentially join with previous text frame, if
+ // corresponding attribute set is set at previous text frame.
+ // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
+ // one as previous frame.
+ const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
+ // OD 2004-02-13 #i25029# - skip hidden text frames.
+ while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
+ {
+ pPrevFrm = pPrevFrm->GetPrev();
+ }
+ if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
+ pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
+ )
+ {
+ bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
+ }
+ }
+
+ // valid cache status, if demanded
+ // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
+ // is set.
+ bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
+}
+
+// OD 21.05.2003 #108789# - method to determine, if borders are joined with
+// next frame. Calculated value saved in cached value <bJoinedWithNext>
+void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
+{
+ // set default
+ bJoinedWithNext = sal_False;
+
+ if ( _rFrm.IsTxtFrm() )
+ {
+ // text frame can potentially join with next text frame, if
+ // corresponding attribute set is set at current text frame.
+ // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
+ const SwFrm* pNextFrm = _rFrm.GetNext();
+ while ( pNextFrm && pNextFrm->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
+ {
+ pNextFrm = pNextFrm->GetNext();
+ }
+ if ( pNextFrm && pNextFrm->IsTxtFrm() &&
+ _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
+ )
+ {
+ bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
+ }
+ }
+
+ // valid cache status, if demanded
+ bCachedJoinedWithNext = bCacheGetLine;
+}
+
+// OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
+// OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
+// method <_CalcJoindWithPrev(..)>.
+sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm ) const
+{
+ if ( !bCachedJoinedWithPrev || _pPrevFrm )
+ {
+ // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
+ const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
+ }
+
+ return bJoinedWithPrev;
+}
+
+sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
+{
+ if ( !bCachedJoinedWithNext )
+ {
+ const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
+ }
+
+ return bJoinedWithNext;
+}
+
+// OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
+// method <JoinedWithPrev>
+void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
+ const SwFrm* _pPrevFrm )
+{
+ sal_uInt16 nRet = CalcTopLine();
+
+ // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
+ // OD 2004-02-26 #i25029# - add 2nd parameter
+ if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
+ {
+ nRet = 0;
+ }
+
+ bCachedGetTopLine = bCacheGetLine;
+
+ nGetTopLine = nRet;
+}
+
+void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
+{
+ sal_uInt16 nRet = CalcBottomLine();
+
+ // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
+ if ( JoinedWithNext( _rFrm ) )
+ {
+ nRet = 0;
+ }
+
+ bCachedGetBottomLine = bCacheGetLine;
+
+ nGetBottomLine = nRet;
+}
+
+/*************************************************************************/
+
+SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
+ SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
+ (void*)((SwCntntFrm*)pFrm)->GetNode() :
+ (void*)((SwLayoutFrm*)pFrm)->GetFmt()),
+ (sal_Bool)(pFrm->IsCntntFrm() ?
+ ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
+ ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
+ pConstructor( pFrm )
+{
+}
+
+/*************************************************************************/
+
+SwCacheObj *SwBorderAttrAccess::NewObj()
+{
+ ((SwModify*)pOwner)->SetInCache( sal_True );
+ return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
+}
+
+SwBorderAttrs *SwBorderAttrAccess::Get()
+{
+ return (SwBorderAttrs*)SwCacheAccess::Get();
+}
+
+/*************************************************************************/
+
+SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
+ pPage( pPg ),
+ pCurrent( 0 ),
+ bFlysOnly( bFlys )
+{
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Top()
+{
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ sal_uInt32 nTopOrd = 0;
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp >= nTopOrd )
+ {
+ nTopOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Bottom()
+{
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nBotOrd = USHRT_MAX;
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp < nBotOrd )
+ {
+ nBotOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Next()
+{
+ const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ sal_uInt32 nOrd = USHRT_MAX;
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp > nCurOrd && nTmp < nOrd )
+ {
+ nOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+const SdrObject *SwOrderIter::Prev()
+{
+ const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
+ pCurrent = 0;
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs *pObjs = pPage->GetSortedObjs();
+ if ( pObjs->Count() )
+ {
+ sal_uInt32 nOrd = 0;
+ (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
+ if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
+ continue;
+ sal_uInt32 nTmp = pObj->GetOrdNumDirect();
+ if ( nTmp < nCurOrd && nTmp >= nOrd )
+ {
+ nOrd = nTmp;
+ pCurrent = pObj;
+ }
+ }
+ }
+ }
+ return pCurrent;
+}
+
+/*************************************************************************/
+
+//Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
+//restaurieren.
+//Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
+//die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
+//Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
+//Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
+//angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
+//die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
+//auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
+//Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
+//verboten.
+//Unterwegs werden die Flys bei der Seite abgemeldet.
+
+// --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
+// at-fly anchored objects from page
+void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
+{
+ OSL_ENSURE( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
+ SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ // --> OD 2004-11-29 #115759# - reset member, at which the anchored
+ // object orients its vertical position
+ pObj->ClearVertPosOrientFrm();
+ // <--
+ // --> OD 2005-03-03 #i43913#
+ pObj->ResetLayoutProcessBools();
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
+ // anchored Writer fly frames from page
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+
+ // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
+ // fly frame from page
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ ::lcl_RemoveObjsFromPage( pFlyFrm );
+ }
+ // <--
+
+ SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( pCnt->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if ( pFlyFrm->IsFlyFreeFrm() )
+ {
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
+ }
+ }
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also drawing objects from page
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
+ {
+ pObj->GetPageFrm()->RemoveDrawObjFromPage(
+ *(static_cast<SwAnchoredDrawObject*>(pObj)) );
+ }
+ }
+ // <--
+ }
+}
+
+SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
+{
+ if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
+ lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );
+
+ SwFrm *pSav;
+ if ( 0 == (pSav = pLay->ContainsAny()) )
+ return 0;
+
+ if( pSav->IsInFtn() && !pLay->IsInFtn() )
+ {
+ do
+ pSav = pSav->FindNext();
+ while( pSav && pSav->IsInFtn() );
+ if( !pSav || !pLay->IsAnLower( pSav ) )
+ return NULL;
+ }
+
+ // Tables should be saved as a whole, expection:
+ // The contents of a section or a cell inside a table should be saved
+ if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
+ while ( !pSav->IsTabFrm() )
+ pSav = pSav->GetUpper();
+
+ if( pSav->IsInSct() )
+ { // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
+ SwFrm* pSect = pLay->FindSctFrm();
+ SwFrm *pTmp = pSav;
+ do
+ {
+ pSav = pTmp;
+ pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
+ } while ( pTmp != pSect );
+ }
+
+ SwFrm *pFloat = pSav;
+ if( !pStart )
+ pStart = pSav;
+ sal_Bool bGo = pStart == pSav;
+ do
+ {
+ if( bGo )
+ pFloat->GetUpper()->pLower = 0; //Die Teilkette ausklinken.
+
+ //Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
+ do
+ {
+ if( bGo )
+ {
+ if ( pFloat->IsCntntFrm() )
+ {
+ if ( pFloat->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
+ }
+ else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
+ {
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
+ if( pCnt )
+ {
+ do
+ { if ( pCnt->GetDrawObjs() )
+ ::lcl_RemoveObjsFromPage( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
+ }
+ }
+ else {
+ OSL_ENSURE( !pFloat, "Neuer Float-Frame?" );
+ }
+ }
+ if ( pFloat->GetNext() )
+ {
+ if( bGo )
+ pFloat->pUpper = NULL;
+ pFloat = pFloat->GetNext();
+ if( !bGo && pFloat == pStart )
+ {
+ bGo = sal_True;
+ pFloat->pPrev->pNext = NULL;
+ pFloat->pPrev = NULL;
+ }
+ }
+ else
+ break;
+
+ } while ( pFloat );
+
+ //Die naechste Teilkette suchen und die Ketten miteinander verbinden.
+ SwFrm *pTmp = pFloat->FindNext();
+ if( bGo )
+ pFloat->pUpper = NULL;
+
+ if( !pLay->IsInFtn() )
+ while( pTmp && pTmp->IsInFtn() )
+ pTmp = pTmp->FindNext();
+
+ if ( !pLay->IsAnLower( pTmp ) )
+ pTmp = 0;
+
+ if ( pTmp && bGo )
+ {
+ pFloat->pNext = pTmp; //Die beiden Ketten verbinden.
+ pFloat->pNext->pPrev = pFloat;
+ }
+ pFloat = pTmp;
+ bGo = bGo || ( pStart == pFloat );
+ } while ( pFloat );
+
+ return bGo ? pStart : NULL;
+}
+
+// --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
+// anchored objects to page
+void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
+{
+ OSL_ENSURE( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
+ SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+
+ // --> OD 2004-11-29 #115759# - unlock position of anchored object
+ // in order to get the object's position calculated.
+ pObj->UnlockPosition();
+ // <--
+ // --> OD 2004-11-29 #115759# - add also lower objects of as-character
+ // anchored Writer fly frames from page
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( pObj->ISA(SwFlyFreeFrm) )
+ {
+ _pPage->AppendFlyToPage( pFlyFrm );
+ }
+ pFlyFrm->_InvalidatePos();
+ pFlyFrm->_InvalidateSize();
+ pFlyFrm->InvalidatePage( _pPage );
+
+ // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
+ // to page
+ if ( pFlyFrm->GetDrawObjs() )
+ {
+ ::lcl_AddObjsToPage( pFlyFrm, _pPage );
+ }
+ // <--
+
+ SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( pCnt->GetDrawObjs() )
+ ::lcl_AddObjsToPage( pCnt, _pPage );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ // <--
+ // --> OD 2004-11-29 #115759# - remove also drawing objects from page
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
+ {
+ pObj->InvalidateObjPos();
+ _pPage->AppendDrawObjToPage(
+ *(static_cast<SwAnchoredDrawObject*>(pObj)) );
+ }
+ }
+ // <--
+ }
+}
+
+void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
+{
+ OSL_ENSURE( pSav && pParent, "Kein Save oder Parent fuer Restore." );
+ SWRECTFN( pParent )
+
+ //Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
+ //Kette, beginnend mit pSav, hinter dem letzten angehaengt.
+ //Die Teile werden kurzerhand insertet und geeignet invalidiert.
+ //Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.
+
+ SwPageFrm *pPage = pParent->FindPageFrm();
+
+ if ( pPage )
+ pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.
+
+ //Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren.
+ pSav->pPrev = pSibling;
+ SwFrm* pNxt;
+ if ( pSibling )
+ {
+ pNxt = pSibling->pNext;
+ pSibling->pNext = pSav;
+ pSibling->_InvalidatePrt();
+ ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
+ if ( ((SwCntntFrm*)pSibling)->GetFollow() )
+ pSibling->Prepare( PREP_CLEAR, 0, sal_False );
+ }
+ else
+ { pNxt = pParent->pLower;
+ pParent->pLower = pSav;
+ pSav->pUpper = pParent; //Schon mal setzen, sonst ist fuer das
+ //invalidate der Parent (z.B. ein Fly) nicht klar.
+ //Invaliden Cntnt anmelden.
+ if ( pSav->IsCntntFrm() )
+ ((SwCntntFrm*)pSav)->InvalidatePage( pPage );
+ else
+ { // pSav koennte auch ein leerer SectFrm sein
+ SwCntntFrm* pCnt = pParent->ContainsCntnt();
+ if( pCnt )
+ pCnt->InvalidatePage( pPage );
+ }
+ }
+
+ //Der Parent muss entsprechend gegrow'ed werden.
+ SwTwips nGrowVal = 0;
+ SwFrm* pLast;
+ do
+ { pSav->pUpper = pParent;
+ nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
+ pSav->_InvalidateAll();
+
+ //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
+ if ( pSav->IsCntntFrm() )
+ {
+ if ( pSav->IsTxtFrm() &&
+ ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pSav)->Init(); //Ich bin sein Freund.
+
+ if ( pPage && pSav->GetDrawObjs() )
+ ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
+ }
+ else
+ { SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
+ if( pBlub )
+ {
+ do
+ { if ( pPage && pBlub->GetDrawObjs() )
+ ::lcl_AddObjsToPage( pBlub, pPage );
+ if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
+ ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
+ ((SwTxtFrm*)pBlub)->Init(); //Ich bin sein Freund.
+ pBlub = pBlub->GetNextCntntFrm();
+ } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
+ }
+ }
+ pLast = pSav;
+ pSav = pSav->GetNext();
+
+ } while ( pSav );
+
+ if( pNxt )
+ {
+ pLast->pNext = pNxt;
+ pNxt->pPrev = pLast;
+ }
+
+ if ( bGrow )
+ pParent->Grow( nGrowVal );
+}
+
+/*************************************************************************
+|*
+|* SqRt() Berechnung der Quadratwurzel, damit die math.lib
+|* nicht auch noch dazugelinkt werden muss.
+|*
+|*************************************************************************/
+
+sal_uLong MA_FASTCALL SqRt( BigInt nX )
+{
+ BigInt nErg = 1;
+
+ if ( !nX.IsNeg() )
+ {
+ BigInt nOldErg = 1;
+ for ( int i = 0; i <= 5; i++ )
+ {
+ nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
+ nOldErg = nErg;
+ }
+ }
+ return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg;
+}
+
+/*************************************************************************/
+
+SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
+ sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
+ SwFrm *pSibling )
+{
+ SwPageFrm *pRet;
+ SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
+ SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
+ //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
+ //eine Leerseite einfuegen.
+ if ( !pFmt )
+ {
+ pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
+ OSL_ENSURE( pFmt, "Descriptor without any format?!" );
+ bInsertEmpty = !bInsertEmpty;
+ }
+ if( bInsertEmpty )
+ {
+ SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
+ ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
+ pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
+ pRet->Paste( pUpper, pSibling );
+ pRet->PreparePage( bFtn );
+ }
+ pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
+ pRet->Paste( pUpper, pSibling );
+ pRet->PreparePage( bFtn );
+ if ( pRet->GetNext() )
+ ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
+ return pRet;
+}
+
+
+/*************************************************************************
+|*
+|* RegistFlys(), Regist() Die beiden folgenden Methoden durchsuchen rekursiv
+|* eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
+|* innerhalb der Struktur als Anker haben bei der Seite an.
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
+{
+ SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ //Ggf. ummelden, nicht anmelden wenn bereits bekannt.
+ // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
+ SwPageFrm *pPg = pFly->IsFlyFreeFrm()
+ ? pFly->GetPageFrm() : pFly->FindPageFrm();
+ if ( pPg != pPage )
+ {
+ if ( pPg )
+ pPg->RemoveFlyFromPage( pFly );
+ pPage->AppendFlyToPage( pFly );
+ }
+ ::RegistFlys( pPage, pFly );
+ }
+ else
+ {
+ // --> OD 2008-04-22 #i87493#
+ if ( pPage != pObj->GetPageFrm() )
+ {
+ // --> OD 2004-07-02 #i28701#
+ if ( pObj->GetPageFrm() )
+ pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
+ pPage->AppendDrawObjToPage( *pObj );
+ // <--
+ }
+ // <--
+ }
+
+ const SwFlyFrm* pFly = pAnch->FindFlyFrm();
+ if ( pFly &&
+ pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
+ pObj->GetDrawObj()->GetPage() )
+ {
+ pObj->DrawObj()->GetPage()->SetObjectOrdNum(
+ pObj->GetDrawObj()->GetOrdNumDirect(),
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() + 1 );
+ }
+ }
+}
+
+void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
+{
+ if ( pLay->GetDrawObjs() )
+ ::lcl_Regist( pPage, pLay );
+ const SwFrm *pFrm = pLay->Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
+ else if ( pFrm->GetDrawObjs() )
+ ::lcl_Regist( pPage, pFrm );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* void Notify()
+|*
+|* Beschreibung Benachrichtigt den Hintergrund je nach der
+|* Veraenderung zwischen altem und neuem Rechteckt.
+|*
+|*************************************************************************/
+
+void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
+ const SwRect* pOldPrt )
+{
+ const SwRect aFrm( pFly->GetObjRectWithSpaces() );
+ if ( rOld.Pos() != aFrm.Pos() )
+ { //Positionsaenderung, alten und neuen Bereich invalidieren
+ if ( rOld.HasArea() &&
+ rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
+ {
+ pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
+ }
+ pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
+ }
+ else if ( rOld.SSize() != aFrm.SSize() )
+ { //Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
+ //ueberdeckt wird invalidieren.
+ //Der Einfachheit halber wird hier bewusst jeweils ein Twip
+ //unnoetig invalidiert.
+
+ ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
+ if( pSh && rOld.HasArea() )
+ pSh->InvalidateWindows( rOld );
+
+ // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
+ // registered at the old page <pOld>
+ SwPageFrm* pPageFrm = pFly->FindPageFrm();
+ if ( pOld != pPageFrm )
+ {
+ pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
+ }
+ // <--
+
+ if ( rOld.Left() != aFrm.Left() )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Left( Min(aFrm.Left(), rOld.Left()) );
+ aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ SwTwips nOld = rOld.Right();
+ SwTwips nNew = aFrm.Right();
+ if ( nOld != nNew )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Left( Min(nNew, nOld) );
+ aTmp.Right( Max(nNew, nOld) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ if ( rOld.Top() != aFrm.Top() )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Top( Min(aFrm.Top(), rOld.Top()) );
+ aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ nOld = rOld.Bottom();
+ nNew = aFrm.Bottom();
+ if ( nOld != nNew )
+ {
+ SwRect aTmp( rOld );
+ aTmp.Union( aFrm );
+ aTmp.Top( Min(nNew, nOld) );
+ aTmp.Bottom( Max(nNew, nOld) );
+ pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
+ }
+ }
+ else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
+ pFly->GetFmt()->GetSurround().IsContour() )
+ {
+ // #i24097#
+ pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
+ }
+}
+
+/*************************************************************************/
+
+void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
+{
+ SwTwips nBottom = rRect.Bottom();
+ while( pFrm )
+ {
+ if( pFrm->IsLayoutFrm() )
+ {
+ if( rRect.IsOver( pFrm->Frm() ) )
+ lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
+ }
+ else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
+ {
+ if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
+ pFrm->InvalidateSize();
+ else
+ pFrm->InvalidateNextPos();
+ }
+ pFrm = pFrm->GetNext();
+ }
+}
+
+void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
+ const SwRect &rRect, const PrepareHint eHint )
+{
+ if ( pCnt->IsTxtFrm() )
+ {
+ SwRect aCntPrt( pCnt->Prt() );
+ aCntPrt.Pos() += pCnt->Frm().Pos();
+ if ( eHint == PREP_FLY_ATTR_CHG )
+ {
+ // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
+ // of current bound rectangle
+ if ( aCntPrt.IsOver( rRect ) )
+ // <--
+ pCnt->Prepare( PREP_FLY_ATTR_CHG );
+ }
+ // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
+ // printing area overlaps with the given rectangle.
+ else if ( aCntPrt.IsOver( rRect ) )
+ // <--
+ pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ SwCntntFrm *pCntnt = pFly->ContainsCntnt();
+ while ( pCntnt )
+ {
+ ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Notify_Background( const SdrObject* pObj,
+ SwPageFrm* pPage,
+ const SwRect& rRect,
+ const PrepareHint eHint,
+ const sal_Bool bInva )
+{
+
+ //Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
+ //alte Bereich nicht benachrichtigt werden.
+ if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
+ return;
+
+ SwLayoutFrm* pArea;
+ SwFlyFrm *pFlyFrm = 0;
+ SwFrm* pAnchor;
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ pAnchor = pFlyFrm->AnchorFrm();
+ }
+ else
+ {
+ pFlyFrm = NULL;
+ pAnchor = const_cast<SwFrm*>(
+ GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
+ }
+ if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
+ pArea = pAnchor->FindFlyFrm();
+ else
+ pArea = pPage;
+ SwCntntFrm *pCnt = 0;
+ if ( pArea )
+ {
+ if( PREP_FLY_ARRIVE != eHint )
+ lcl_CheckFlowBack( pArea, rRect );
+
+ //Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
+ //brauchen diese nicht abgeklappert werden.
+ //Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
+ //"oben" kommen.
+ // Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
+ // die gesamte Seite abgearbeitet werden. (47722)
+ // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
+ // on the object positioning, the complete area has to be processed,
+ // because content frames before the anchor frame also have to consider
+ // the object for the text wrapping.
+ // --> OD 2004-08-25 #i3317# - The complete area has always been
+ // processed.
+ {
+ pCnt = pArea->ContainsCntnt();
+ }
+ // <--
+ }
+ SwFrm *pLastTab = 0;
+
+ while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
+ {
+ ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
+ if ( pCnt->IsInTab() )
+ {
+ SwLayoutFrm* pCell = pCnt->GetUpper();
+ // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
+ // instead of <GetCurrentBoundRect()>, because a recalculation
+ // of the bounding rectangle isn't intended here.
+ if ( pCell->IsCellFrm() &&
+ ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
+ pCell->Frm().IsOver( rRect ) ) )
+ // <--
+ {
+ const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
+ if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
+ pCell->InvalidatePrt();
+ }
+ SwTabFrm *pTab = pCnt->FindTabFrm();
+ if ( pTab != pLastTab )
+ {
+ pLastTab = pTab;
+ // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
+ // instead of <GetCurrentBoundRect()>, because a recalculation
+ // of the bounding rectangle isn't intended here.
+ if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
+ pTab->Frm().IsOver( rRect ) )
+ // <--
+ {
+ if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
+ pTab->InvalidatePrt();
+ }
+ }
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+// #108745# Sorry, but this causes nothing but trouble. I remove these lines
+// taking the risk that the footer frame will have a wrong height
+// if( pPage->Lower() )
+// {
+// SwFrm* pFrm = pPage->Lower();
+// while( pFrm->GetNext() )
+// pFrm = pFrm->GetNext();
+// if( pFrm->IsFooterFrm() &&
+// ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
+// pFrm->Frm().IsOver( rRect ) ) ) )
+// pFrm->InvalidateSize();
+// }
+ // --> OD 2007-07-24 #128702# - make code robust
+ if ( pPage && pPage->GetSortedObjs() )
+ // <--
+ {
+ pObj->GetOrdNum();
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ if( pAnchoredObj->GetDrawObj() == pObj )
+ continue;
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->Frm().Top() == WEIT_WECH )
+ continue;
+
+ if ( !pFlyFrm ||
+ (!pFly->IsLowerOf( pFlyFrm ) &&
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
+ {
+ pCnt = pFly->ContainsCntnt();
+ while ( pCnt )
+ {
+ ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ if( pFly->IsFlyLayFrm() )
+ {
+ if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
+ pFly->Frm().Bottom() >= rRect.Top() &&
+ pFly->Frm().Top() <= rRect.Bottom() &&
+ pFly->Frm().Right() >= rRect.Left() &&
+ pFly->Frm().Left() <= rRect.Right() )
+ {
+ pFly->InvalidateSize();
+ }
+ }
+ //Flys, die ueber mir liegen muessen/mussten evtl.
+ //ausweichen, wenn sie eine automatische Ausrichtung haben.
+ //das ist unabhaengig von meinem Attribut, weil dies sich
+ //gerade geaendert haben kann und eben deshalb
+ //umformatiert wurde.
+ else if ( pFly->IsFlyAtCntFrm() &&
+ pObj->GetOrdNumDirect() <
+ pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
+ pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
+ {
+ const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
+ if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
+ text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
+ ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
+ (pFly->Frm().Bottom() >= rRect.Top() &&
+ pFly->Frm().Top() <= rRect.Bottom()) )
+ pFly->InvalidatePos();
+ }
+ }
+ }
+ }
+ if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
+ pAnchor->GetUpper()->InvalidateSize();
+
+ // --> OD 2008-01-30 #i82258# - make code robust
+ ViewShell* pSh = 0;
+ if ( bInva && pPage &&
+ 0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
+ {
+ pSh->InvalidateWindows( rRect );
+ }
+ // <--
+}
+
+/*************************************************************************
+|*
+|* GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
+|* des Ankers. Falls es sich dabei um verkettete Rahmen oder
+|* Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
+|*
+|*************************************************************************/
+
+const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
+{
+ if( pFrm->IsTxtFrm() )
+ {
+ pFrm = pFrm->GetUpper();
+ if( !pFrm->Frm().IsInside( rPos ) )
+ {
+ if( pFrm->IsFtnFrm() )
+ {
+ const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
+ while( pTmp )
+ {
+ if( pTmp->Frm().IsInside( rPos ) )
+ return pTmp;
+ pTmp = pTmp->GetFollow();
+ }
+ }
+ else
+ {
+ SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
+ while( pTmp )
+ {
+ if( pTmp->Frm().IsInside( rPos ) )
+ return pTmp;
+ pTmp = pTmp->GetNextLink();
+ }
+ }
+ }
+ }
+ return pFrm;
+}
+
+/*************************************************************************/
+
+sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
+{
+ Point aPos;
+ const SwFrm* pFrm;
+ if( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
+ pFrm = pFly->GetAnchorFrm();
+ aPos = pFly->Frm().Pos();
+ }
+ else
+ {
+ pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
+ aPos = pObj->GetCurrentBoundRect().TopLeft();
+ }
+ OSL_ENSURE( pFrm, "8-( Fly is lost in Space." );
+ pFrm = GetVirtualUpper( pFrm, aPos );
+ do
+ { if ( pFrm == pCurrFrm )
+ return sal_True;
+ if( pFrm->IsFlyFrm() )
+ {
+ aPos = pFrm->Frm().Pos();
+ pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
+ }
+ else
+ pFrm = pFrm->GetUpper();
+ } while ( pFrm );
+ return sal_False;
+}
+
+const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
+{
+ //Liefert die Umgebung des Frm in die kein Fly aus einer anderen
+ //Umgebung hineinragen kann.
+ const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
+ FRM_FTN | FRM_FLY |
+ FRM_TAB | FRM_ROW | FRM_CELL |
+ nAdditionalKontextTyp;
+ do
+ { if ( pFrm->GetType() & nTyp )
+ break;
+ pFrm = pFrm->GetUpper();
+ } while( pFrm );
+ return pFrm;
+}
+
+sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
+{
+ const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
+
+ const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
+ FRM_FTN | FRM_FLY |
+ FRM_TAB | FRM_ROW | FRM_CELL;
+ do
+ { if ( pFrm->GetType() & nTyp )
+ {
+ if( pFrm == pKontext )
+ return sal_True;
+ if( pFrm->IsCellFrm() )
+ return sal_False;
+ }
+ if( pFrm->IsFlyFrm() )
+ {
+ Point aPos( pFrm->Frm().Pos() );
+ pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
+ }
+ else
+ pFrm = pFrm->GetUpper();
+ } while( pFrm );
+
+ return sal_False;
+}
+
+
+//---------------------------------
+
+SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
+{
+ if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
+ {
+ SwFrm *pLow = pCell->Lower();
+ long nHeight = 0, nFlyAdd = 0;
+ do
+ {
+ long nLow = pLow->Frm().Height();
+ if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
+ nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
+ else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
+ nLow += ((SwSectionFrm*)pLow)->Undersize();
+ nFlyAdd = Max( 0L, nFlyAdd - nLow );
+ nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
+ nHeight += nLow;
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ if ( nFlyAdd )
+ nHeight += nFlyAdd;
+
+ //Der Border will natuerlich auch mitspielen, er kann leider nicht
+ //aus PrtArea und Frm errechnet werden, da diese in beliebiger
+ //Kombination ungueltig sein koennen.
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
+
+ return pCell->Frm().Height() - nHeight;
+ }
+ else
+ {
+ long nRstHeight = 0;
+ SwFrm *pLow = pCell->Lower();
+ do
+ { nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
+ pLow = pLow->GetNext();
+
+ } while ( pLow );
+
+ return nRstHeight;
+ }
+}
+
+SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
+{
+ SwTwips nRstHeight = LONG_MAX;
+ SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
+ while ( pLow )
+ {
+ nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ return nRstHeight;
+}
+
+const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
+{
+ if ( !rRect.IsOver( pPage->Frm() ) )
+ {
+ const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
+ const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
+ if ( pTmpPage )
+ pPage = pTmpPage;
+ }
+
+ return pPage;
+}
+
+#include <svl/smplhint.hxx>
+class SwFrmHolder : private SfxListener
+{
+ SwFrm* pFrm;
+ bool bSet;
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+public:
+ SwFrmHolder() : pFrm(0), bSet(false) {}
+ void SetFrm( SwFrm* pHold );
+ SwFrm* GetFrm() { return pFrm; }
+ void Reset();
+ bool IsSet() { return bSet; }
+};
+
+void SwFrmHolder::SetFrm( SwFrm* pHold )
+{
+ bSet = true;
+ pFrm = pHold;
+ StartListening(*pHold);
+}
+
+void SwFrmHolder::Reset()
+{
+ if (pFrm)
+ EndListening(*pFrm);
+ bSet = false;
+ pFrm = 0;
+}
+
+void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if ( rHint.IsA(TYPE(SfxSimpleHint)) )
+ {
+ if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
+ pFrm = 0;
+ }
+}
+
+SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
+ const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
+{
+ SwFrm *pMinFrm = 0, *pTmpFrm;
+ SwFrmHolder aHolder;
+ SwRect aCalcRect;
+ bool bClientIterChanged = false;
+
+ SwIterator<SwFrm,SwModify> aIter( rMod );
+ do {
+ pMinFrm = 0;
+ aHolder.Reset();
+ sal_uInt64 nMinDist = 0;
+ bClientIterChanged = false;
+
+ for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
+ {
+ if( pTmpFrm->GetType() & nFrmType &&
+ ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
+ (!pTmpFrm->IsFlowFrm() ||
+ !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
+ {
+ if( pPoint )
+ {
+ // watch for Frm being deleted
+ if ( pMinFrm )
+ aHolder.SetFrm( pMinFrm );
+ else
+ aHolder.Reset();
+
+ if( bCalcFrm )
+ {
+ // --> OD 2005-03-04 #b6234250# - format parent Writer
+ // fly frame, if it isn't been formatted yet.
+ // Note: The Writer fly frame could be the frame itself.
+ SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
+ if ( pFlyFrm &&
+ pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
+ pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
+ {
+ SwObjectFormatter::FormatObj( *pFlyFrm );
+ }
+ // <--
+ pTmpFrm->Calc();
+ }
+
+ // #127369#
+ // aIter.IsChanged checks if the current pTmpFrm has been deleted while
+ // it is the current iterator
+ // FrmHolder watches for deletion of the current pMinFrm
+ if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
+ {
+ // restart iteration
+ bClientIterChanged = true;
+ break;
+ }
+
+ // bei Flys ggfs. ueber den Parent gehen wenn sie selbst
+ // nocht nicht "formatiert" sind
+ if( !bCalcFrm && nFrmType & FRM_FLY &&
+ ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
+ WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
+ WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
+ aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
+ else
+ aCalcRect = pTmpFrm->Frm();
+
+ if ( aCalcRect.IsInside( *pPoint ) )
+ {
+ pMinFrm = pTmpFrm;
+ break;
+ }
+
+ // Point not in rectangle. Compare distances:
+ const Point aCalcRectCenter = aCalcRect.Center();
+ const Point aDiff = aCalcRectCenter - *pPoint;
+ const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
+ if ( !pMinFrm || nCurrentDist < nMinDist )
+ {
+ pMinFrm = pTmpFrm;
+ nMinDist = nCurrentDist;
+ }
+ }
+ else
+ {
+ // Wenn kein pPoint angegeben ist, dann reichen
+ // wir irgendeinen raus: den ersten!
+ pMinFrm = pTmpFrm;
+ break;
+ }
+ }
+ }
+ } while( bClientIterChanged );
+
+ if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
+ return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
+
+ return pMinFrm;
+}
+
+sal_Bool IsExtraData( const SwDoc *pDoc )
+{
+ const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
+ return rInf.IsPaintLineNumbers() ||
+ rInf.IsCountInFlys() ||
+ ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
+ pDoc->GetRedlineTbl().Count());
+}
+
+// OD 22.09.2003 #110978#
+const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
+{
+ SwRect aPrtWithoutHeaderFooter( Prt() );
+ aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
+
+ const SwFrm* pLowerFrm = Lower();
+ while ( pLowerFrm )
+ {
+ // Note: independent on text direction page header and page footer are
+ // always at top respectively at bottom of the page frame.
+ if ( pLowerFrm->IsHeaderFrm() )
+ {
+ aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
+ pLowerFrm->Frm().Height() );
+ }
+ if ( pLowerFrm->IsFooterFrm() )
+ {
+ aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
+ pLowerFrm->Frm().Height() );
+ }
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+
+ return aPrtWithoutHeaderFooter;
+}
+
+/** method to determine the spacing values of a frame
+
+ OD 2004-03-10 #i28701#
+ OD 2009-08-28 #i102458#
+ Add output parameter <obIsLineSpacingProportional>
+
+ @author OD
+*/
+void GetSpacingValuesOfFrm( const SwFrm& rFrm,
+ SwTwips& onLowerSpacing,
+ SwTwips& onLineSpacing,
+ bool& obIsLineSpacingProportional )
+{
+ if ( !rFrm.IsFlowFrm() )
+ {
+ onLowerSpacing = 0;
+ onLineSpacing = 0;
+ }
+ else
+ {
+ const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
+ onLowerSpacing = rULSpace.GetLower();
+
+ onLineSpacing = 0;
+ obIsLineSpacingProportional = false;
+ if ( rFrm.IsTxtFrm() )
+ {
+ onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
+ obIsLineSpacingProportional =
+ onLineSpacing != 0 &&
+ static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
+ }
+
+ OSL_ENSURE( onLowerSpacing >= 0 && onLineSpacing >= 0,
+ "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
+ }
+}
+
+/** method to get the content of the table cell, skipping content from nested tables
+*/
+const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
+{
+ const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
+ const SwTabFrm* pTab = rCell.FindTabFrm();
+
+ while ( pCntnt && rCell.IsAnLower( pCntnt ) )
+ {
+ const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
+ if ( pTmpTab != pTab )
+ {
+ pCntnt = pTmpTab->FindLastCntnt();
+ if ( pCntnt )
+
+ pCntnt = pCntnt->FindNextCnt();
+
+ }
+ else
+ break;
+ }
+ return pCntnt;
+}
+
+/** Can be used to check if a frame has been deleted
+ */
+bool SwDeletionChecker::HasBeenDeleted()
+{
+ if ( !mpFrm || !mpRegIn )
+ return false;
+
+ SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
+ SwFrm* pLast = aIter.First();
+ while ( pLast )
+ {
+ if ( pLast == mpFrm )
+ return false;
+ pLast = aIter.Next();
+ }
+
+ return true;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
new file mode 100644
index 000000000000..608ecb57ddd5
--- /dev/null
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -0,0 +1,3241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <ftnidx.hxx>
+#include <pagefrm.hxx>
+#include <colfrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx>
+#include <frmtool.hxx>
+#include <swtable.hxx>
+#include <ftnfrm.hxx>
+#include <txtfrm.hxx>
+#include <tabfrm.hxx>
+#include <pagedesc.hxx>
+#include <ftninfo.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <pam.hxx>
+#include <objectformatter.hxx>
+#include "viewopt.hxx"
+#include "viewsh.hxx"
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* lcl_FindFtnPos() Sucht die Position des Attributes im FtnArray am
+|* Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem
+|* Index sortiert.
+|*
+|*************************************************************************/
+
+#define ENDNOTE 0x80000000
+
+sal_uLong MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr )
+{
+ const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs();
+
+ sal_uInt16 nRet;
+ SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr;
+ if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) )
+ {
+ if( pAttr->GetFtn().IsEndNote() )
+ return sal_uLong(nRet) + ENDNOTE;
+ return nRet;
+ }
+ OSL_ENSURE( !pDoc, "FtnPos not found." );
+ return 0;
+}
+
+sal_Bool SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const
+{
+ const SwDoc* pDoc = GetFmt()->GetDoc();
+ OSL_ENSURE( pDoc, "SwFtnFrm: Missing doc!" );
+ return lcl_FindFtnPos( pDoc, GetAttr() ) <
+ lcl_FindFtnPos( pDoc, pTxtFtn );
+}
+
+/*************************************************************************
+|*
+|* sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage)
+|* setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte
+|* oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird
+|* enthaelt pPage die neue Seite und die Funktion liefert sal_True.
+|*
+|*************************************************************************/
+
+sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage,
+ sal_Bool bDontLeave )
+{
+ if( rpBoss->IsColumnFrm() )
+ {
+ if( rpBoss->GetNext() )
+ {
+ rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte
+ return sal_False;
+ }
+ if( rpBoss->IsInSct() )
+ {
+ SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
+ if( pSct )
+ {
+ OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
+ "Where's the column?" );
+ rpBoss = (SwColumnFrm*)pSct->Lower();
+ SwPageFrm* pOld = rpPage;
+ rpPage = pSct->FindPageFrm();
+ return pOld != rpPage;
+ }
+ else if( bDontLeave )
+ {
+ rpPage = NULL;
+ rpBoss = NULL;
+ return sal_False;
+ }
+ }
+ }
+ rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite
+ rpBoss = rpPage;
+ if( rpPage )
+ {
+ SwLayoutFrm* pBody = rpPage->FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* sal_uInt16 lcl_ColumnNum( SwFrm* pBoss )
+|* liefert die Spaltennummer, wenn pBoss eine Spalte ist,
+|* sonst eine Null (bei Seiten).
+|*
+|*************************************************************************/
+
+sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss )
+{
+ sal_uInt16 nRet = 0;
+ if( !pBoss->IsColumnFrm() )
+ return 0;
+ const SwFrm* pCol;
+ if( pBoss->IsInSct() )
+ {
+ pCol = pBoss->GetUpper()->FindColFrm();
+ if( pBoss->GetNext() || pBoss->GetPrev() )
+ {
+ while( pBoss )
+ {
+ ++nRet; // Section columns
+ pBoss = pBoss->GetPrev();
+ }
+ }
+ }
+ else
+ pCol = pBoss;
+ while( pCol )
+ {
+ nRet += 256; // Page columns
+ pCol = pCol->GetPrev();
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnContFrm::SwFtnContFrm()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwLayoutFrm( pFmt, pSib )
+{
+ nType = FRMC_FTNCONT;
+}
+
+
+// lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab
+// und liefert die Summe aller TxtFrm-Vergroesserungswuensche
+
+long lcl_Undersize( const SwFrm* pFrm )
+{
+ long nRet = 0;
+ SWRECTFN( pFrm )
+ if( pFrm->IsTxtFrm() )
+ {
+ if( ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRet = ((SwTxtFrm*)pFrm)->GetParHeight() -
+ (pFrm->Prt().*fnRect->fnGetHeight)();
+ if( nRet < 0 )
+ nRet = 0;
+ }
+ }
+ else if( pFrm->IsLayoutFrm() )
+ {
+ const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower();
+ while( pNxt )
+ {
+ nRet += lcl_Undersize( pNxt );
+ pNxt = pNxt->GetNext();
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnContFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame;
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+
+
+void SwFtnContFrm::Format( const SwBorderAttrs * )
+{
+ //GesamtBorder ermitteln, es gibt nur einen Abstand nach oben.
+ const SwPageFrm* pPage = FindPageFrm();
+ const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
+ const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
+ rInf.GetLineWidth();
+ SWRECTFN( this )
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+ (Prt().*fnRect->fnSetTop)( nBorder );
+ (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
+ if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() )
+ bValidSize = sal_False;
+ }
+
+ if ( !bValidSize )
+ {
+ bool bGrow = pPage->IsFtnPage();
+ if( bGrow )
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ bGrow = false;
+ }
+ if( bGrow )
+ Grow( LONG_MAX, sal_False );
+ else
+ {
+ //Die Groesse in der VarSize wird durch den Inhalt plus den
+ //Raendern bestimmt.
+ SwTwips nRemaining = 0;
+ SwFrm *pFrm = pLower;
+ while ( pFrm )
+ { // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne
+ // groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen,
+ // wenn diese noch nicht ihre maximale Groesse haben.
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)()
+ + lcl_Undersize( pFrm );
+ pFrm = pFrm->GetNext();
+ }
+ //Jetzt noch den Rand addieren
+ nRemaining += nBorder;
+
+ SwTwips nDiff;
+ if( IsInSct() )
+ {
+ nDiff = -(Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if( nDiff > 0 )
+ {
+ if( nDiff > (Frm().*fnRect->fnGetHeight)() )
+ nDiff = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( -nDiff );
+ (Prt().*fnRect->fnAddHeight)( -nDiff );
+ }
+ }
+ nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff > 0 )
+ Shrink( nDiff );
+ else if ( nDiff < 0 )
+ {
+ Grow( -nDiff );
+ //Es kann passieren, dass weniger Platz zur Verfuegung steht,
+ //als der bereits der Border benoetigt - die Groesse der
+ //PrtArea wird dann negativ.
+ SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( nPrtHeight < 0 )
+ {
+ const SwTwips nTmpDiff = Max( (Prt().*fnRect->fnGetTop)(),
+ -nPrtHeight );
+ (Prt().*fnRect->fnSubTop)( nTmpDiff );
+ }
+ }
+ }
+ bValidSize = sal_True;
+ }
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::GrowFrm(), ShrinkFrm()
+|*
+|*************************************************************************/
+
+SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ //Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis
+ //zur Maximalhoehe variabel.
+ //Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben
+ //moeglich.
+ //Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch
+ //soviel Platz wie eben moeglich.
+#if OSL_DEBUG_LEVEL > 1
+ if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() )
+ { OSL_ENSURE( !this, "Keine FtnBoss." );
+ return 0;
+ }
+#endif
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetHeight)() > 0 &&
+ nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
+ nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
+
+ SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSect = FindSctFrm();
+ OSL_ENSURE( pSect, "GrowFrm: Missing SectFrm" );
+ // In a section, which has to maximize, a footnotecontainer is allowed
+ // to grow, when the section can't grow anymore.
+ if( !bTst && !pSect->IsColLocked() &&
+ pSect->ToMaximize( sal_False ) && pSect->Growable() )
+ {
+ pSect->InvalidateSize();
+ return 0;
+ }
+ }
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ SwPageFrm *pPage = pBoss->FindPageFrm();
+ if ( bBrowseMode || !pPage->IsFtnPage() )
+ {
+ if ( pBoss->GetMaxFtnHeight() != LONG_MAX )
+ {
+ nDist = Min( nDist, pBoss->GetMaxFtnHeight()
+ - (Frm().*fnRect->fnGetHeight)() );
+ if ( nDist <= 0 )
+ return 0L;
+ }
+ //Der FtnBoss will bezueglich des MaxWerts auch noch mitreden.
+ if( !IsInSct() )
+ {
+ const SwTwips nMax = pBoss->GetVarSpace();
+ if ( nDist > nMax )
+ nDist = nMax;
+ if ( nDist <= 0 )
+ return 0L;
+ }
+ }
+ else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
+ //aber mehr als der Body kann koennen und wollen wir nun auch wieder
+ //nicht herausruecken.
+ nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
+
+ long nAvail = 0;
+ if ( bBrowseMode )
+ {
+ nAvail = GetUpper()->Prt().Height();
+ const SwFrm *pAvail = GetUpper()->Lower();
+ do
+ { nAvail -= pAvail->Frm().Height();
+ pAvail = pAvail->GetNext();
+ } while ( pAvail );
+ if ( nAvail > nDist )
+ nAvail = nDist;
+ }
+
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ }
+ long nGrow = nDist - nAvail,
+ nReal = 0;
+ if ( nGrow > 0 )
+ {
+ sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this );
+ if( NA_ONLY_ADJUST == nAdjust )
+ nReal = AdjustNeighbourhood( nGrow, bTst );
+ else
+ {
+ if( NA_GROW_ADJUST == nAdjust )
+ {
+ SwFrm* pFtn = Lower();
+ if( pFtn )
+ {
+ while( pFtn->GetNext() )
+ pFtn = pFtn->GetNext();
+ if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() )
+ {
+ nReal = AdjustNeighbourhood( nGrow, bTst );
+ nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood
+ }
+ }
+ }
+ nReal += pBoss->Grow( nGrow - nReal, bTst );
+ if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
+ && nReal < nGrow )
+ nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
+ }
+ }
+
+ nReal += nAvail;
+
+ if ( !bTst )
+ {
+ if ( nReal != nDist )
+ {
+ nDist -= nReal;
+ //Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen.
+ Frm().SSize().Height() -= nDist;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() += nDist;
+ }
+
+ //Nachfolger braucht nicht invalidiert werden, denn wir wachsen
+ //immer nach oben.
+ if( nReal )
+ {
+ _InvalidateSize();
+ _InvalidatePos();
+ InvalidatePage( pPage );
+ }
+ }
+ return nReal;
+}
+
+
+SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwPageFrm *pPage = FindPageFrm();
+ bool bShrink = false;
+ if ( pPage )
+ {
+ if( !pPage->IsFtnPage() )
+ bShrink = true;
+ else
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ bShrink = true;
+ }
+ }
+ if( bShrink )
+ {
+ SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
+ if( IsInSct() && !bTst )
+ FindSctFrm()->InvalidateNextPos();
+ if ( !bTst && nRet )
+ {
+ _InvalidatePos();
+ InvalidatePage( pPage );
+ }
+ return nRet;
+ }
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnFrm::SwFtnFrm()
+|*
+|*************************************************************************/
+
+
+SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ):
+ SwLayoutFrm( pFmt, pSib ),
+ pFollow( 0 ),
+ pMaster( 0 ),
+ pRef( pCnt ),
+ pAttr( pAt ),
+ bBackMoveLocked( sal_False ),
+ // --> OD 2005-08-11 #i49383#
+ mbUnlockPosOfLowerObjs( true )
+ // <--
+{
+ nType = FRMC_FTN;
+}
+
+/*************************************************************************
+|*
+|* SwFtnFrm::InvalidateNxtFtnCnts()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage )
+{
+ if ( GetNext() )
+ {
+ SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->InvalidatePage( pPage );
+ pCnt->_InvalidatePrt();
+ do
+ { pCnt->_InvalidatePos();
+ if( pCnt->IsSctFrm() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pTmp->_InvalidatePos();
+ }
+ pCnt->GetUpper()->_InvalidateSize();
+ pCnt = pCnt->FindNext();
+ } while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
+ }
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ static sal_uInt16 nNum = USHRT_MAX;
+ SwTxtFtn* pTxtFtn = GetAttr();
+ if ( pTxtFtn->GetFtn().GetNumber() == nNum )
+ {
+ int bla = 5;
+ (void)bla;
+
+ }
+ return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
+}
+
+
+SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ static sal_uInt16 nNum = USHRT_MAX;
+ if( nNum != USHRT_MAX )
+ {
+ SwTxtFtn* pTxtFtn = GetAttr();
+ if( &pTxtFtn->GetAttr() && pTxtFtn->GetFtn().GetNumber() == nNum )
+ {
+ int bla = 5;
+ (void)bla;
+ }
+ }
+ return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
+}
+#endif
+
+/*************************************************************************
+|*
+|* SwFtnFrm::Cut()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::Cut()
+{
+ if ( GetNext() )
+ GetNext()->InvalidatePos();
+ else if ( GetPrev() )
+ GetPrev()->SetRetouche();
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+
+ //Verkettung korrigieren.
+ SwFtnFrm *pFtn = (SwFtnFrm*)this;
+ if ( pFtn->GetFollow() )
+ pFtn->GetFollow()->SetMaster( pFtn->GetMaster() );
+ if ( pFtn->GetMaster() )
+ pFtn->GetMaster()->SetFollow( pFtn->GetFollow() );
+ pFtn->SetFollow( 0 );
+ pFtn->SetMaster( 0 );
+
+ // Alle Verbindungen kappen.
+ Remove();
+
+ if ( pUp )
+ {
+ //Die letzte Fussnote nimmt ihren Container mit.
+ if ( !pUp->Lower() )
+ {
+ SwPageFrm *pPage = pUp->FindPageFrm();
+ if ( pPage )
+ {
+ SwLayoutFrm *pBody = pPage->FindBodyCont();
+ if( pBody && !pBody->ContainsCntnt() )
+ pPage->getRootFrm()->SetSuperfluous();
+ }
+ SwSectionFrm* pSect = pUp->FindSctFrm();
+ pUp->Cut();
+ delete pUp;
+ // Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet,
+ // so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen.
+ if( pSect && !pSect->ToMaximize( sal_False ) && !pSect->IsColLocked() )
+ pSect->_InvalidateSize();
+ }
+ else
+ { if ( Frm().Height() )
+ pUp->Shrink( Frm().Height() );
+ pUp->SetCompletePaint();
+ pUp->InvalidatePage();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnFrm::Paste()
+|*
+|*************************************************************************/
+
+
+void SwFtnFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
+ _InvalidateSize();
+ _InvalidatePos();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+ if( (Frm().*fnRect->fnGetHeight)() )
+ pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
+
+ //Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein
+ //Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten.
+ if ( GetPrev() && GetPrev() == GetMaster() )
+ { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ),
+ "Fussnote ohne Inhalt?" );
+ (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))->
+ MoveSubTree( this, GetLower() );
+ SwFrm *pDel = GetPrev();
+ pDel->Cut();
+ delete pDel;
+ }
+ if ( GetNext() && GetNext() == GetFollow() )
+ { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ),
+ "Fussnote ohne Inhalt?" );
+ (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this );
+ SwFrm *pDel = GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( GetPrev() )
+ {
+ OSL_ENSURE( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <=
+ lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" );
+ }
+ if ( GetNext() )
+ {
+ OSL_ENSURE( lcl_FindFtnPos( pDoc, GetAttr() ) <=
+ lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ),
+ "Next is not FtnNext" );
+ }
+#endif
+ InvalidateNxtFtnCnts( pPage );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextFtnLeaf()
+|*
+|* Beschreibung Liefert das naechste LayoutBlatt in den das
+|* Frame gemoved werden kann.
+|* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage )
+{
+ SwFtnBossFrm *pOldBoss = FindFtnBossFrm();
+ SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
+ SwPageFrm* pPage;
+ SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ?
+ (SwFtnBossFrm*)pOldBoss->GetNext() : 0; // naechste Spalte, wenn vorhanden
+ if( pBoss )
+ pPage = NULL;
+ else
+ {
+ if( pOldBoss->GetUpper()->IsSctFrm() )
+ { // Das kann nur in einem spaltigen Bereich sein
+ SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
+ if( pNxt )
+ {
+ OSL_ENSURE( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" );
+ pBoss = (SwFtnBossFrm*)pNxt->GetUpper();
+ pPage = pBoss->FindPageFrm();
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ // naechste Seite
+ pPage = (SwPageFrm*)pOldPage->GetNext();
+ // Leerseiten ueberspringen
+ if( pPage && pPage->IsEmptyPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pBoss = pPage;
+ }
+ }
+ // Was haben wir jetzt?
+ // pBoss != NULL, pPage==NULL => pBoss ist die auf der gleichen Seite folgende Spalte
+ // pBoss != NULL, pPage!=NULL => pBoss und pPage sind die folgende Seite (Empty uebersprungen)
+ // pBoss == NULL => pPage == NULL, es gibt keine folgende Seite
+
+ //Wenn die Fussnote bereits einen Follow hat brauchen wir nicht zu suchen.
+ //Wenn allerdings zwischen Ftn und Follow unerwuenschte Leerseiten/spalten
+ //herumlungern, so legen wir auf der naechstbesten Seite/Spalte einen weiteren
+ //Follow an, der Rest wird sich schon finden.
+ SwFtnFrm *pFtn = FindFtnFrm();
+ if ( pFtn && pFtn->GetFollow() )
+ {
+ SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm();
+ // Folgende Faelle werden hier erkannt und akzeptiert
+ // 1. Die FtnBosse sind benachbarte Seiten oder benachbarte Spalten
+ // 2. Der neue ist die erste Spalte der benachbarten Seite
+ // 3. Der neue ist die erste Spalte in einem Bereich in der naechsten Spalte/Seite
+ while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
+ pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm();
+ if( pTmpBoss == pBoss )
+ return pFtn->GetFollow();
+ }
+
+ // Wenn wir keinen pBoss gefunden haben oder es sich um eine "falsche" Seite handelt,
+ // muss eine neue Seite her
+ if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
+ {
+ if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
+ {
+ pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() );
+ ((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
+ }
+ else
+ return 0;
+ }
+ if( pBoss->IsPageFrm() )
+ { // Wenn wir auf einer spaltigen Seite gelandet sind,
+ // gehen wir in die erste Spalte
+ SwLayoutFrm* pLay = pBoss->FindBodyCont();
+ if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pLay->Lower();
+ }
+ //Seite/Spalte gefunden, da schummeln wir uns doch gleich mal 'rein
+ SwFtnContFrm *pCont = pBoss->FindFtnCont();
+ if ( !pCont && pBoss->GetMaxFtnHeight() &&
+ ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
+ pCont = pBoss->MakeFtnCont();
+ return pCont;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevFtnLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn )
+{
+ //Der Vorgaenger fuer eine Fussnote ist falls moeglich der Master
+ //in der Fussnoteneigenen Verkettung.
+ SwLayoutFrm *pRet = 0;
+ SwFtnFrm *pFtn = FindFtnFrm();
+ pRet = pFtn->GetMaster();
+
+ SwFtnBossFrm* pOldBoss = FindFtnBossFrm();
+ SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
+
+ if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
+ return pRet; // es gibt weder eine Spalte noch eine Seite vor uns
+
+ if ( !pRet )
+ {
+ bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote();
+ SwFrm* pTmpRef = NULL;
+ if( bEndn && pFtn->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFtn->FindSctFrm();
+ if( pSect->IsEndnAtEnd() )
+ pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
+ }
+ if( !pTmpRef )
+ pTmpRef = pFtn->GetRef();
+ SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn );
+
+ const sal_uInt16 nNum = pStop->GetPhyPageNum();
+
+ //Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir
+ //die Entsprechenden Seiten nicht.
+ //Selbiges gilt analog fuer die Endnotenseiten.
+ const sal_Bool bEndNote = pOldPage->IsEndNotePage();
+ const sal_Bool bFtnEndDoc = pOldPage->IsFtnPage();
+ SwFtnBossFrm* pNxtBoss = pOldBoss;
+ SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ?
+ (SwSectionFrm*)pNxtBoss->GetUpper() : 0;
+
+ do
+ {
+ if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() )
+ pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev(); // eine Spalte zurueck
+ else // oder eine Seite zurueck
+ {
+ SwLayoutFrm* pBody = 0;
+ if( pSect )
+ {
+ if( pSect->IsFtnLock() )
+ {
+ if( pNxtBoss == pOldBoss )
+ return 0;
+ pStop = pNxtBoss;
+ }
+ else
+ {
+ pSect = (SwSectionFrm*)pSect->FindMaster();
+ if( !pSect || !pSect->Lower() )
+ return 0;
+ OSL_ENSURE( pSect->Lower()->IsColumnFrm(),
+ "GetPrevFtnLeaf: Where's the column?" );
+ pNxtBoss = (SwFtnBossFrm*)pSect->Lower();
+ pBody = pSect;
+ }
+ }
+ else
+ {
+ SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev();
+ if( !pPage || pPage->GetPhyPageNum() < nNum ||
+ bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() )
+ return NULL; // Keine in Frage kommende Seite mehr gefunden
+ pNxtBoss = pPage;
+ pBody = pPage->FindBodyCont();
+ }
+ // Die vorherige Seite haben wir nun, ggf. sollten wir in die letzte Spalte
+ // der Seite wechseln
+ if( pBody )
+ {
+ if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
+ }
+ }
+ }
+ SwFtnContFrm *pCont = pNxtBoss->FindFtnCont();
+ if ( pCont )
+ {
+ pRet = pCont;
+ break;
+ }
+ if ( pStop == pNxtBoss )
+ { //Die Seite/Spalte auf der sich auch die Referenz tummelt, ist erreicht.
+ //Wir koennen jetzt probehalber mal einen Container erzeugen und
+ //uns hineinpasten.
+ if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() )
+ pRet = pNxtBoss->MakeFtnCont();
+ break;
+ }
+ } while( !pRet );
+ }
+ if ( pRet )
+ {
+ const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm();
+ sal_Bool bJump = sal_False;
+ if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // es gibt eine vorherige Spalte
+ bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss; // sind wir darin gelandet?
+ else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() )
+ bJump = sal_True; // es gibt hinter dem neuen Boss noch eine Spalte, die aber nicht
+ // der alte Boss sein kann, das haben wir ja bereits geprueft.
+ else // hier landen wir nur, wenn neuer und alter Boss entweder Seiten oder letzte (neu)
+ { // bzw. erste (alt) Spalten einer Seite sind. In diesem Fall muss noch geprueft
+ // werden, ob Seiten ueberspringen wurden.
+ sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum();
+ if ( nDiff > 2 ||
+ (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) )
+ bJump = sal_True;
+ }
+ if( bJump )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::IsFtnAllowed()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwFrm::IsFtnAllowed() const
+{
+ if ( !IsInDocBody() )
+ return sal_False;
+
+ if ( IsInTab() )
+ {
+ //Keine Ftns in wiederholten Headlines.
+ const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm();
+ if ( pTab->IsFollow() )
+ return !pTab->IsInHeadline( *this );
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::UpdateFtnNums()
+|*
+|*************************************************************************/
+
+
+void SwRootFrm::UpdateFtnNums()
+{
+ //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
+ if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ {
+ pPage->UpdateFtnNum();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* RemoveFtns() Entfernen aller Fussnoten (nicht etwa die Referenzen)
+|* und Entfernen aller Fussnotenseiten.
+|*
+|*************************************************************************/
+
+void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes )
+{
+ do
+ {
+ SwFtnContFrm *pCont = pBoss->FindFtnCont();
+ if ( pCont )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
+ OSL_ENSURE( pFtn, "FtnCont ohne Ftn." );
+ if ( bPageOnly )
+ while ( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ do
+ {
+ SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext();
+ if ( !pFtn->GetAttr()->GetFtn().IsEndNote() ||
+ bEndNotes )
+ {
+ pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() );
+ if ( bPageOnly && !pNxt )
+ pNxt = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ }
+ pFtn = pNxt;
+
+ } while ( pFtn );
+ }
+ if( !pBoss->IsInSct() )
+ {
+ // A sectionframe with the Ftn/EndnAtEnd-flags may contain
+ // foot/endnotes. If the last lower frame of the bodyframe is
+ // a multicolumned sectionframe, it may contain footnotes, too.
+ SwLayoutFrm* pBody = pBoss->FindBodyCont();
+ if( pBody && pBody->Lower() )
+ {
+ SwFrm* pLow = pBody->Lower();
+ while( pLow->GetNext() )
+ {
+ if( pLow->IsSctFrm() && ( !pLow->GetNext() ||
+ ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) &&
+ ((SwSectionFrm*)pLow)->Lower() &&
+ ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() )
+ lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(),
+ bPageOnly, bEndNotes );
+ pLow = pLow->GetNext();
+ }
+ }
+ }
+ // noch 'ne Spalte?
+ pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL;
+ } while( pBoss );
+}
+
+void SwRootFrm::RemoveFtns( SwPageFrm *pPage, sal_Bool bPageOnly, sal_Bool bEndNotes )
+{
+ if ( !pPage )
+ pPage = (SwPageFrm*)Lower();
+
+ do
+ { // Bei spaltigen Seiten muessen wir in allen Spalten aufraeumen
+ SwFtnBossFrm* pBoss;
+ SwLayoutFrm* pBody = pPage->FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pBody->Lower(); // die erste Spalte
+ else
+ pBoss = pPage; // keine Spalten
+ lcl_RemoveFtns( pBoss, bPageOnly, bEndNotes );
+ if ( !bPageOnly )
+ {
+ if ( pPage->IsFtnPage() &&
+ (!pPage->IsEndNotePage() || bEndNotes) )
+ {
+ SwFrm *pDel = pPage;
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ else
+ break;
+
+ } while ( pPage );
+}
+
+/*************************************************************************
+|*
+|* SetFtnPageDescs() Seitenvorlagen der Fussnotenseiten aendern
+|*
+|*************************************************************************/
+
+void SwRootFrm::CheckFtnPageDescs( sal_Bool bEndNote )
+{
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->IsEndNotePage() != bEndNote )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ if ( pPage )
+ SwFrm::CheckPageDescs( pPage, sal_False );
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::MakeFtnCont()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm *SwFtnBossFrm::MakeFtnCont()
+{
+ //Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt
+ //immer direkt hinter dem Bodytext.
+ //Sein FrmFmt ist immer das DefaultFrmFmt.
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( FindFtnCont() )
+ { OSL_ENSURE( !this, "Fussnotencontainer bereits vorhanden." );
+ return 0;
+ }
+#endif
+
+ SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt(), this );
+ SwLayoutFrm *pLay = FindBodyCont();
+ pNew->Paste( this, pLay->GetNext() );
+ return pNew;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFtnCont()
+|*
+|*************************************************************************/
+
+
+SwFtnContFrm *SwFtnBossFrm::FindFtnCont()
+{
+ SwFrm *pFrm = Lower();
+ while( pFrm && !pFrm->IsFtnContFrm() )
+ pFrm = pFrm->GetNext();
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( pFrm )
+ {
+ SwFrm *pFtn = pFrm->GetLower();
+ OSL_ENSURE( pFtn, "Cont ohne Fussnote." );
+ while ( pFtn )
+ {
+ OSL_ENSURE( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." );
+ pFtn = pFtn->GetNext();
+ }
+ }
+#endif
+
+ return (SwFtnContFrm*)pFrm;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindNearestFtnCont() Sucht den naechst greifbaren Fussnotencontainer.
+|*
+|*************************************************************************/
+
+SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( sal_Bool bDontLeave )
+{
+ SwFtnContFrm *pCont = 0;
+ if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ pCont = FindFtnCont();
+ if ( !pCont )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ SwFtnBossFrm* pBoss = this;
+ sal_Bool bEndNote = pPage->IsEndNotePage();
+ do
+ {
+ sal_Bool bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave );
+ // Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss
+ // zudem noch das EndNotenFlag uebereinstimmen
+ if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
+ pCont = pBoss->FindFtnCont();
+ } while ( !pCont && pPage );
+ }
+ }
+ return pCont;
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFirstFtn()
+|*
+|* Beschreibung Erste Fussnote des Fussnotenbosses suchen.
+|*
+|*************************************************************************/
+
+
+SwFtnFrm *SwFtnBossFrm::FindFirstFtn()
+{
+ //Erstmal den naechsten FussnotenContainer suchen.
+ SwFtnContFrm *pCont = FindNearestFtnCont();
+ if ( !pCont )
+ return 0;
+
+ //Ab der ersten Fussnote im Container die erste suchen, die
+ //von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird.
+
+ SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower();
+ const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nRefCol = lcl_ColumnNum( this );
+ sal_uInt16 nPgNum, nColNum; //Seitennummer, Spaltennummer
+ SwFtnBossFrm* pBoss;
+ SwPageFrm* pPage;
+ if( pRet )
+ {
+ pBoss = pRet->GetRef()->FindFtnBossFrm();
+ OSL_ENSURE( pBoss, "FindFirstFtn: No boss found" );
+ if( !pBoss )
+ return sal_False; // ?There must be a bug, but no GPF
+ pPage = pBoss->FindPageFrm();
+ nPgNum = pPage->GetPhyPageNum();
+ if ( nPgNum == nRefNum )
+ {
+ nColNum = lcl_ColumnNum( pBoss );
+ if( nColNum == nRefCol )
+ return pRet; //hat ihn.
+ else if( nColNum > nRefCol )
+ return NULL; //mind. eine Spalte zu weit.
+ }
+ else if ( nPgNum > nRefNum )
+ return NULL; //mind. eine Seite zu weit.
+ }
+ else
+ return NULL;
+ // Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer
+ // spaeteren Spalte liegt
+
+ do
+ {
+ while ( pRet->GetFollow() )
+ pRet = pRet->GetFollow();
+
+ SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext();
+ if ( !pNxt )
+ {
+ pBoss = pRet->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
+ pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
+ if ( pCont )
+ pNxt = (SwFtnFrm*)pCont->Lower();
+ }
+ if ( pNxt )
+ {
+ pRet = pNxt;
+ pBoss = pRet->GetRef()->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ nPgNum = pPage->GetPhyPageNum();
+ if ( nPgNum == nRefNum )
+ {
+ nColNum = lcl_ColumnNum( pBoss );
+ if( nColNum == nRefCol )
+ break; //hat ihn.
+ else if( nColNum > nRefCol )
+ pRet = 0; //mind. eine Spalte zu weit.
+ }
+ else if ( nPgNum > nRefNum )
+ pRet = 0; //mind. eine Seite zu weit.
+ }
+ else
+ pRet = 0; //Gibt eben keinen.
+ } while( pRet );
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFirstFtn()
+|*
+|* Beschreibunt Erste Fussnote zum Cnt suchen.
+|*
+|*************************************************************************/
+
+
+const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const
+{
+ const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn();
+ if ( pRet )
+ {
+ const sal_uInt16 nColNum = lcl_ColumnNum( this ); //Spaltennummer
+ const sal_uInt16 nPageNum = GetPhyPageNum();
+ while ( pRet && (pRet->GetRef() != pCnt) )
+ {
+ while ( pRet->GetFollow() )
+ pRet = pRet->GetFollow();
+
+ if ( pRet->GetNext() )
+ pRet = (const SwFtnFrm*)pRet->GetNext();
+ else
+ { SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm();
+ SwPageFrm *pPage = pBoss->FindPageFrm();
+ lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
+ SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
+ pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0;
+ }
+ if ( pRet )
+ {
+ const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm();
+ if( pBoss->GetPhyPageNum() != nPageNum ||
+ nColNum != lcl_ColumnNum( pBoss ) )
+ pRet = 0;
+ }
+ }
+ }
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::ResetFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck )
+{
+ //Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht
+ //zu pAssumed gehoeren.
+ OSL_ENSURE( !pCheck->GetMaster(), "Master not an Master." );
+
+ SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pCheck->GetFmt()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
+ SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
+ SwFrm* pFrm = aIter.First();
+ while( pFrm )
+ {
+ if( pFrm->getRootFrm() == pCheck->getRootFrm() )
+ {
+ SwFrm *pTmp = pFrm->GetUpper();
+ while ( pTmp && !pTmp->IsFtnFrm() )
+ pTmp = pTmp->GetUpper();
+
+ SwFtnFrm *pFtn = (SwFtnFrm*)pTmp;
+ while ( pFtn && pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ if ( pFtn != pCheck )
+ {
+ while ( pFtn )
+ {
+ SwFtnFrm *pNxt = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ pFtn = pNxt;
+ }
+ }
+ }
+
+ pFrm = aIter.Next();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::InsertFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew )
+{
+ //Die Fussnote haben wir, sie muss jetzt nur noch irgendwo
+ //hin und zwar vor die Fussnote, deren Attribut vor das
+ //der neuen zeigt (Position wird ueber das Doc ermittelt)
+ //Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein
+ //Container erzeugt werden.
+ //Gibt es bereits einen Container aber noch keine Fussnote zu diesem
+ //Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten
+ //Vorseite/spalte.
+
+ ResetFtn( pNew );
+ SwFtnFrm *pSibling = FindFirstFtn();
+ sal_Bool bDontLeave = sal_False;
+
+ // Ok, a sibling has been found, but is the sibling in an acceptable
+ // environment?
+ if( IsInSct() )
+ {
+ SwSectionFrm* pMySect = ImplFindSctFrm();
+ bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote();
+ if( bEndnt )
+ {
+ const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt();
+ bDontLeave = 0 != pEndFmt;
+ if( pSibling )
+ {
+ if( pEndFmt )
+ {
+ if( !pSibling->IsInSct() ||
+ !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) )
+ pSibling = NULL;
+ }
+ else if( pSibling->IsInSct() )
+ pSibling = NULL;
+ }
+ }
+ else
+ {
+ bDontLeave = pMySect->IsFtnAtEnd();
+ if( pSibling )
+ {
+ if( pMySect->IsFtnAtEnd() )
+ {
+ if( !pSibling->IsInSct() ||
+ !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
+ pSibling = NULL;
+ }
+ else if( pSibling->IsInSct() )
+ pSibling = NULL;
+ }
+ }
+ }
+
+ if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
+ FindPageFrm()->IsEndNotePage() )
+ pSibling = NULL;
+
+ //Damit die Position herausgefunden werden kann.
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() );
+
+ sal_uLong nCmpPos = 0;
+ sal_uLong nLastPos = 0;
+ SwFtnContFrm *pParent = 0;
+ if( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if( nCmpPos > nStPos )
+ pSibling = NULL;
+ }
+
+ if ( !pSibling )
+ { pParent = FindFtnCont();
+ if ( !pParent )
+ {
+ //Es gibt noch keinen FussnotenContainer, also machen wir einen.
+ //HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann
+ //sein, dass irgendeine naechste Fussnote existiert die vor der
+ //einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig
+ //Seiten aufgespalten ist usw.
+ pParent = FindNearestFtnCont( bDontLeave );
+ if ( pParent )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower();
+ if ( pFtn )
+ {
+
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() );
+ if ( nCmpPos > nStPos )
+ pParent = 0;
+ }
+ else
+ pParent = 0;
+ }
+ }
+ if ( !pParent )
+ //Jetzt kann aber ein Fussnotencontainer gebaut werden.
+ pParent = MakeFtnCont();
+ else
+ {
+ //Ausgehend von der ersten Fussnote unterhalb des Parents wird die
+ //erste Fussnote gesucht deren Index hinter dem Index der
+ //einzufuegenden liegt; vor dieser kann der neue dann gepastet
+ //werden.
+ pSibling = (SwFtnFrm*)pParent->Lower();
+ if ( !pSibling )
+ { OSL_ENSURE( !this, "Keinen Platz fuer Fussnote gefunden.");
+ return;
+ }
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+
+ SwFtnBossFrm *pNxtB = this; //Immer den letzten merken, damit wir nicht
+ SwFtnFrm *pLastSib = 0; //ueber das Ziel hinausschiessen.
+
+ while ( pSibling && nCmpPos <= nStPos )
+ {
+ pLastSib = pSibling; // der kommt schon mal in Frage
+ nLastPos = nCmpPos;
+
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+
+ if ( pSibling->GetNext() )
+ {
+ pSibling = (SwFtnFrm*)pSibling->GetNext();
+ OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
+ pSibling->GetAttr()->GetFtn().IsEndNote() ),
+ "InsertFtn: Master expected I" );
+ }
+ else
+ {
+ pNxtB = pSibling->FindFtnBossFrm();
+ SwPageFrm *pSibPage = pNxtB->FindPageFrm();
+ sal_Bool bEndNote = pSibPage->IsEndNotePage();
+ sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
+ // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
+ SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
+ pSibPage->IsEndNotePage() == bEndNote )
+ ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
+ if( pCont )
+ pSibling = (SwFtnFrm*)pCont->Lower();
+ else // kein weiterer FtnContainer, dann werden wir uns wohl hinter
+ break; // pSibling haengen
+ }
+ if ( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ OSL_ENSURE( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" );
+ }
+ }
+ // pLastSib ist jetzt die letzte Fussnote vor uns,
+ // pSibling leer oder die erste nach uns.
+ if ( pSibling && pLastSib && (pSibling != pLastSib) )
+ { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
+ if ( nCmpPos > nStPos )
+ pSibling = pLastSib;
+ }
+ else if ( !pSibling )
+ { //Eine Chance haben wir noch: wir nehmen einfach die letzte
+ //Fussnote im Parent. Ein Sonderfall, der z.B. beim
+ //zurueckfliessen von Absaetzen mit mehreren Fussnoten
+ //vorkommt.
+ //Damit wir nicht die Reihenfolge verwuerfeln muessen wir den
+ //Parent der letzten Fussnote, die wir an der Hand hatten benutzen.
+ pSibling = pLastSib;
+ while( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+ OSL_ENSURE( !pSibling->GetNext(), "InsertFtn: Who's that guy?" );
+ }
+ }
+ }
+ else
+ { //Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend
+ //von dieser die erste zur selben Spalte/Seite suchen deren Index hinter
+ //den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist
+ //dann der Vorgaenger.
+ SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm(
+ !pNew->GetAttr()->GetFtn().IsEndNote() );
+ sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // Die Seiten- und
+ sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // Spaltennummer der neuen Fussnote
+ sal_Bool bEnd = sal_False;
+ SwFtnFrm *pLastSib = 0;
+ while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
+ {
+ pLastSib = pSibling;
+ nLastPos = nCmpPos;
+
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+
+ SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext();
+ if ( pFoll )
+ {
+ pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling->
+ GetAttr()->GetFtn().IsEndNote() );
+ sal_uInt16 nTmpRef;
+ if( nStPos >= ENDNOTE ||
+ (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
+ ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
+ pSibling = pFoll;
+ else
+ bEnd = sal_True;
+ }
+ else
+ {
+ SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm();
+ SwPageFrm *pSibPage = pNxtB->FindPageFrm();
+ sal_Bool bEndNote = pSibPage->IsEndNotePage();
+ sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
+ // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
+ SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
+ pSibPage->IsEndNotePage() == bEndNote )
+ ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
+ if ( pCont )
+ pSibling = (SwFtnFrm*)pCont->Lower();
+ else
+ bEnd = sal_True;
+ }
+ if ( !bEnd && pSibling )
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if ( pSibling && pLastSib && (pSibling != pLastSib) )
+ { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
+ if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
+ {
+ pSibling = pLastSib;
+ bEnd = sal_True;
+ }
+ }
+ }
+ }
+ if ( pSibling )
+ {
+ nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
+ if ( nCmpPos < nStPos )
+ {
+ while ( pSibling->GetFollow() )
+ pSibling = pSibling->GetFollow();
+ pParent = (SwFtnContFrm*)pSibling->GetUpper();
+ pSibling = (SwFtnFrm*)pSibling->GetNext();
+ }
+ else
+ {
+ if( pSibling->GetMaster() )
+ {
+ if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
+ {
+ OSL_FAIL( "InsertFtn: Master expected II" );
+ do
+ pSibling = pSibling->GetMaster();
+ while ( pSibling->GetMaster() );
+ }
+ }
+ pParent = (SwFtnContFrm*)pSibling->GetUpper();
+ }
+ }
+ OSL_ENSURE( pParent, "paste in space?" );
+ pNew->Paste( pParent, pSibling );
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::AppendFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr )
+{
+ //Wenn es die Fussnote schon gibt tun wir nix.
+ if ( FindFtn( pRef, pAttr ) )
+ return;
+
+ //Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst
+ //ab der entsprechenden Seite zu suchen.
+ //Wenn es noch keine gibt, muss eben eine erzeugt werden.
+ //Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht
+ //bzw. erzeugt werden.
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ SwFtnBossFrm *pBoss = this;
+ SwPageFrm *pPage = FindPageFrm();
+ SwPageFrm *pMyPage = pPage;
+ sal_Bool bChgPage = sal_False;
+ sal_Bool bEnd = sal_False;
+ if ( pAttr->GetFtn().IsEndNote() )
+ {
+ bEnd = sal_True;
+ if( GetUpper()->IsSctFrm() &&
+ ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() )
+ {
+ SwFrm* pLast =
+ ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE );
+ if( pLast )
+ {
+ pBoss = pLast->FindFtnBossFrm();
+ pPage = pBoss->FindPageFrm();
+ }
+ }
+ else
+ {
+ while ( pPage->GetNext() && !pPage->IsEndNotePage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ bChgPage = sal_True;
+ }
+ if ( !pPage->IsEndNotePage() )
+ {
+ SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
+ pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
+ !pPage->OnRightPage(), sal_False, sal_True, 0 );
+ pPage->SetEndNotePage( sal_True );
+ bChgPage = sal_True;
+ }
+ else
+ {
+ //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
+ //suchen. Damit stellen wir sicher das wir auch bei hunderten
+ //Fussnoten noch in endlicher Zeit fertig werden.
+ SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
+ while ( pNxt && pNxt->IsEndNotePage() )
+ {
+ SwFtnContFrm *pCont = pNxt->FindFtnCont();
+ if ( pCont && pCont->Lower() )
+ {
+ OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
+ if ( nStPos > ::lcl_FindFtnPos( pDoc,
+ ((SwFtnFrm*)pCont->Lower())->GetAttr()))
+ {
+ pPage = pNxt;
+ pNxt = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()->
+ IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) )
+ {
+ while ( pPage->GetNext() && !pPage->IsFtnPage() &&
+ !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ bChgPage = sal_True;
+ }
+
+ if ( !pPage->IsFtnPage() )
+ {
+ SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc );
+ pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
+ !pPage->OnRightPage(), sal_False, sal_True, pPage->GetNext() );
+ bChgPage = sal_True;
+ }
+ else
+ {
+ //Wir koennen wenigstens schon mal ungefaehr die richtige Seite
+ //suchen. Damit stellen wir sicher das wir auch bei hunderten
+ //Fussnoten noch in endlicher Zeit fertig werden.
+ SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
+ const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
+ while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() )
+ {
+ SwFtnContFrm *pCont = pNxt->FindFtnCont();
+ if ( pCont && pCont->Lower() )
+ {
+ OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
+ if ( nStPos > ::lcl_FindFtnPos( pDoc,
+ ((SwFtnFrm*)pCont->Lower())->GetAttr()))
+ {
+ pPage = pNxt;
+ pNxt = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ //Erstmal eine Fussnote und die benoetigten CntntFrms anlegen.
+ if ( !pAttr->GetStartNode() )
+ { OSL_ENSURE( !this, "Kein Fussnoteninhalt." );
+ return;
+ }
+
+ // Wenn es auf der Seite/Spalte bereits einen FtnCont gibt,
+ // kann in einen spaltigen Bereich keiner erzeugt werden.
+ if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() )
+ {
+ SwSectionFrm* pSct = pBoss->FindSctFrm();
+ if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() )
+ {
+ SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont();
+ if( pFtnCont )
+ {
+ SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower();
+ if( bEnd )
+ while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() )
+ pTmp = (SwFtnFrm*)pTmp->GetNext();
+ if( pTmp && *pTmp < pAttr )
+ return;
+ }
+ }
+ }
+
+ SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), this, pRef, pAttr );
+ {
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
+ }
+ // Wenn die Seite gewechselt (oder gar neu angelegt) wurde,
+ // muessen wir uns dort in die erste Spalte setzen
+ if( bChgPage )
+ {
+ SwLayoutFrm* pBody = pPage->FindBodyCont();
+ OSL_ENSURE( pBody, "AppendFtn: NoPageBody?" );
+ if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ pBoss = (SwFtnBossFrm*)pBody->Lower();
+ else
+ pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst
+ }
+ pBoss->InsertFtn( pNew );
+ if ( pNew->GetUpper() ) //Eingesetzt oder nicht?
+ {
+ ::RegistFlys( pNew->FindPageFrm(), pNew );
+ SwSectionFrm* pSect = FindSctFrm();
+ // Der Inhalt des FtnContainers in einem (spaltigen) Bereich
+ // braucht nur kalkuliert zu werden,
+ // wenn der Bereich bereits bis zur Unterkante seines Uppers geht.
+ if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
+ !pSect->IsFtnAtEnd() ) && pSect->Growable() )
+ pSect->InvalidateSize();
+ else
+ {
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ const bool bOldFtnFrmLocked( pNew->IsColLocked() );
+ pNew->ColLock();
+ pNew->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify* pFtnFrmNotitfy = new SwLayNotify( pNew );
+ // <--
+ SwCntntFrm *pCnt = pNew->ContainsCntnt();
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pNew->ContainsCntnt();
+ continue;
+ }
+ }
+ // <--
+ pCnt = (SwCntntFrm*)pCnt->FindNextCnt();
+ }
+ // --> OD 2005-05-18 #i49383#
+ if ( !bOldFtnFrmLocked )
+ {
+ pNew->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pNew->UnlockPosOfLowerObjs();
+ // <--
+ pNew->Calc();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pNew->UnlockPosOfLowerObjs();
+// delete pFtnFrmNotitfy;
+ // <--
+ if ( !bOldFtnFrmLocked && !pNew->GetLower() &&
+ !pNew->IsColLocked() && !pNew->IsBackMoveLocked() )
+ {
+ pNew->Cut();
+ delete pNew;
+ }
+ // <--
+ }
+ pMyPage->UpdateFtnNum();
+ }
+ else
+ delete pNew;
+}
+/*************************************************************************
+|*
+|* SwFtnBossFrm::FindFtn()
+|*
+|*************************************************************************/
+
+
+SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr )
+{
+ //Der einfachste und sicherste Weg geht ueber das Attribut.
+ OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
+ SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
+ SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
+ if ( !pNd )
+ pNd = pRef->GetAttrSet()->GetDoc()->
+ GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
+ if ( !pNd )
+ return 0;
+ SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
+ SwFrm* pFrm = aIter.First();
+ if( pFrm )
+ do
+ {
+ pFrm = pFrm->GetUpper();
+ // #i28500#, #i27243# Due to the endnode collector, there are
+ // SwFtnFrms, which are not in the layout. Therefore the
+ // bInfFtn flags are not set correctly, and a cell of FindFtnFrm
+ // would return 0. Therefore we better call ImplFindFtnFrm().
+ SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm();
+ if ( pFtn && pFtn->GetRef() == pRef )
+ {
+ // The following condition becomes true, if the whole
+ // footnotecontent is a section. While no frames exist,
+ // the HiddenFlag of the section is set, this causes
+ // the GoNextSection-function leaves the footnote.
+ if( pFtn->GetAttr() != pAttr )
+ return 0;
+ while ( pFtn && pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ return pFtn;
+ }
+
+ } while ( 0 != (pFrm = aIter.Next()) );
+
+ return 0;
+}
+/*************************************************************************
+|*
+|* SwFtnBossFrm::RemoveFtn()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr,
+ sal_Bool bPrep )
+{
+ SwFtnFrm *pFtn = FindFtn( pRef, pAttr );
+ if( pFtn )
+ {
+ do
+ {
+ SwFtnFrm *pFoll = pFtn->GetFollow();
+ pFtn->Cut();
+ delete pFtn;
+ pFtn = pFoll;
+ } while ( pFtn );
+ if( bPrep && pRef->IsFollow() )
+ {
+ OSL_ENSURE( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" );
+ SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster();
+ if( !pMaster->IsLocked() )
+ pMaster->Prepare( PREP_FTN_GONE );
+ }
+ }
+ FindPageFrm()->UpdateFtnNum();
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::ChangeFtnRef()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr,
+ SwCntntFrm *pNew )
+{
+ SwFtnFrm *pFtn = FindFtn( pOld, pAttr );
+ while ( pFtn )
+ {
+ pFtn->SetRef( pNew );
+ pFtn = pFtn->GetFollow();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::CollectFtns()
+|*
+|*************************************************************************/
+
+
+/// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in
+/// order to control, if only footnotes, which are positioned before the
+/// footnote boss frame <this> have to be collected.
+void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnBossFrm* _pOld,
+ SvPtrarr& _rFtnArr,
+ const sal_Bool _bCollectOnlyPreviousFtns )
+{
+ SwFtnFrm *pFtn = _pOld->FindFirstFtn();
+ while( !pFtn )
+ {
+ if( _pOld->IsColumnFrm() )
+ { // Spalten abklappern
+ while ( !pFtn && _pOld->GetPrev() )
+ {
+ //Wenn wir keine Fussnote gefunden haben, ist noch nicht alles zu
+ //spaet. Die Schleife wird beim Aufnehmen von Follow-Zeilen durch
+ //Tabellen benoetigt. Fuer alle anderen Faelle ist sie in der Lage
+ //'krumme' Verhaeltnisse zu korrigieren.
+ _pOld = (SwFtnBossFrm*)_pOld->GetPrev();
+ pFtn = _pOld->FindFirstFtn();
+ }
+ }
+ if( !pFtn )
+ {
+ // vorherige Seite
+ SwPageFrm* pPg;
+ for ( SwFrm* pTmp = _pOld;
+ 0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev())
+ && pPg->IsEmptyPage() ;
+ )
+ {
+ pTmp = pPg;
+ }
+ if( !pPg )
+ return;
+
+ SwLayoutFrm* pBody = pPg->FindBodyCont();
+ if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ // mehrspaltige Seite => letzte Spalte suchen
+ _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
+ }
+ else
+ _pOld = pPg; // einspaltige Seite
+ pFtn = _pOld->FindFirstFtn();
+ }
+ }
+ // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns>
+ SwFtnBossFrm* pRefBossFrm = NULL;
+ if ( _bCollectOnlyPreviousFtns )
+ {
+ pRefBossFrm = this;
+ }
+ _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm );
+}
+
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::_CollectFtns()
+|*
+|*************************************************************************/
+inline void FtnInArr( SvPtrarr& rFtnArr, SwFtnFrm* pFtn )
+{
+ if ( USHRT_MAX == rFtnArr.GetPos( (VoidPtr)pFtn ) )
+ rFtnArr.Insert( (VoidPtr)pFtn, rFtnArr.Count() );
+}
+
+/// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and
+/// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned
+/// before the given reference footnote boss frame have to be collected.
+/// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter
+/// <_pRefFtnBossFrm> have to be referenced to an object.
+/// Adjust parameter names.
+void SwFtnBossFrm::_CollectFtns( const SwCntntFrm* _pRef,
+ SwFtnFrm* _pFtn,
+ SvPtrarr& _rFtnArr,
+ sal_Bool _bCollectOnlyPreviousFtns,
+ const SwFtnBossFrm* _pRefFtnBossFrm)
+{
+ // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame
+ // is set, in spite of the order, that only previous footnotes has to be
+ // collected.
+ OSL_ENSURE( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm,
+ "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" );
+
+ //Alle Fussnoten die von pRef referenziert werden nacheinander
+ //einsammeln (Attribut fuer Attribut), zusammengefuegen
+ //(der Inhalt zu einem Attribut kann ueber mehrere Seiten verteilt sein)
+ //und ausschneiden.
+
+ SvPtrarr aNotFtnArr( 20, 20 ); //Zur Robustheit werden hier die nicht
+ //dazugehoerigen Fussnoten eingetragen.
+ //Wenn eine Fussnote zweimal angefasst wird
+ //ists vorbei! So kommt die Funktion auch
+ //noch mit einem kaputten Layout
+ //einigermassen (ohne Schleife und Absturz)
+ //"klar".
+
+ //Hier sollte keiner mit einer Follow-Ftn ankommen, es sei denn er hat
+ //ernste Absichten (:-)); spricht er kommt mit einer Ftn an die vor der
+ //ersten der Referenz liegt.
+ OSL_ENSURE( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "FollowFtn moven?" );
+ while ( _pFtn->GetMaster() )
+ _pFtn = _pFtn->GetMaster();
+
+ sal_Bool bFound = sal_False;
+
+ while ( _pFtn )
+ {
+ //Erstmal die naechste Fussnote der Spalte/Seite suchen, damit wir nicht
+ //nach dem Cut jeder Fussnote von vorn anfangen muessen.
+ SwFtnFrm *pNxtFtn = _pFtn;
+ while ( pNxtFtn->GetFollow() )
+ pNxtFtn = pNxtFtn->GetFollow();
+ pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext();
+
+ if ( !pNxtFtn )
+ {
+ SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm();
+ SwPageFrm* pPage = pBoss->FindPageFrm();
+ do
+ {
+ lcl_NextFtnBoss( pBoss, pPage, sal_False );
+ if( pBoss )
+ {
+ SwLayoutFrm* pCont = pBoss->FindFtnCont();
+ if( pCont )
+ {
+ pNxtFtn = (SwFtnFrm*)pCont->Lower();
+ if( pNxtFtn )
+ {
+ while( pNxtFtn->GetMaster() )
+ pNxtFtn = pNxtFtn->GetMaster();
+ if( pNxtFtn == _pFtn )
+ pNxtFtn = NULL;
+ }
+ }
+ }
+ } while( !pNxtFtn && pBoss );
+ }
+ else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() )
+ { OSL_ENSURE( !pNxtFtn->GetMaster(), "_CollectFtn: Master exspected" );
+ while ( pNxtFtn->GetMaster() )
+ pNxtFtn = pNxtFtn->GetMaster();
+ }
+ if ( pNxtFtn == _pFtn )
+ {
+ OSL_FAIL( "_CollectFtn: Devil's circle" );
+ pNxtFtn = 0;
+ }
+
+ // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
+ sal_Bool bCollectFoundFtn = sal_False;
+ if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() )
+ {
+ if ( _bCollectOnlyPreviousFtns )
+ {
+ SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( sal_True );
+ OSL_ENSURE( pBossOfFoundFtn,
+ "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
+ if ( !pBossOfFoundFtn || // don't crash, if no footnote boss is found.
+ pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm )
+ )
+ {
+ bCollectFoundFtn = sal_True;
+ }
+ }
+ else
+ {
+ bCollectFoundFtn = sal_True;
+ }
+ }
+
+ if ( bCollectFoundFtn )
+ {
+ OSL_ENSURE( !_pFtn->GetMaster(), "FollowFtn moven?" );
+ SwFtnFrm *pNxt = _pFtn->GetFollow();
+ while ( pNxt )
+ {
+ SwFrm *pCnt = pNxt->ContainsAny();
+ if ( pCnt )
+ { //Unterwegs wird der Follow zerstoert weil er leer wird!
+ do
+ { SwFrm *pNxtCnt = pCnt->GetNext();
+ pCnt->Cut();
+ pCnt->Paste( _pFtn );
+ pCnt = pNxtCnt;
+ } while ( pCnt );
+ }
+ else
+ { OSL_ENSURE( !pNxt, "Fussnote ohne Inhalt?" );
+ pNxt->Cut();
+ delete pNxt;
+ }
+ pNxt = _pFtn->GetFollow();
+ }
+ _pFtn->Cut();
+ FtnInArr( _rFtnArr, _pFtn );
+ bFound = sal_True;
+ }
+ else
+ {
+ FtnInArr( aNotFtnArr, _pFtn );
+ if( bFound )
+ break;
+ }
+ if ( pNxtFtn &&
+ USHRT_MAX == _rFtnArr.GetPos( (VoidPtr)pNxtFtn ) &&
+ USHRT_MAX == aNotFtnArr.GetPos( (VoidPtr)pNxtFtn ) )
+ _pFtn = pNxtFtn;
+ else
+ break;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::_MoveFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, sal_Bool bCalc )
+{
+ //Alle Fussnoten die von pRef referenziert werden muessen von der
+ //aktuellen Position, die sich durch die alte Spalte/Seite ergab, auf eine
+ //neue Position, bestimmt durch die neue Spalte/Seite, gemoved werden.
+ const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nMyCol = lcl_ColumnNum( this );
+ SWRECTFN( this )
+
+ // --> OD 2004-06-11 #i21478# - keep last inserted footnote in order to
+ // format the content of the following one.
+ SwFtnFrm* pLastInsertedFtn = 0L;
+ for ( sal_uInt16 i = 0; i < rFtnArr.Count(); ++i )
+ {
+ SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i];
+
+ SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( sal_True );
+ if( pRefBoss != this )
+ {
+ const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum();
+ const sal_uInt16 nRefCol = lcl_ColumnNum( this );
+ if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
+ pRefBoss = this;
+ }
+ pRefBoss->InsertFtn( pFtn );
+
+ if ( pFtn->GetUpper() ) //Robust, z.B. bei doppelten
+ {
+ // Damit FtnFrms, die nicht auf die Seite passen, nicht fuer zuviel
+ // Unruhe sorgen (Loop 66312), wird ihr Inhalt zunaechst zusammengestaucht.
+ // Damit wird der FtnCont erst gegrowt, wenn der Inhalt formatiert wird
+ // und feststellt, dass er auf die Seite passt.
+ SwFrm *pCnt = pFtn->ContainsAny();
+ while( pCnt )
+ {
+ if( pCnt->IsLayoutFrm() )
+ {
+ SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny();
+ while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) )
+ {
+ pTmp->Prepare( PREP_MOVEFTN );
+ (pTmp->Frm().*fnRect->fnSetHeight)(0);
+ (pTmp->Prt().*fnRect->fnSetHeight)(0);
+ pTmp = pTmp->FindNext();
+ }
+ }
+ else
+ pCnt->Prepare( PREP_MOVEFTN );
+ (pCnt->Frm().*fnRect->fnSetHeight)(0);
+ (pCnt->Prt().*fnRect->fnSetHeight)(0);
+ pCnt = pCnt->GetNext();
+ }
+ (pFtn->Frm().*fnRect->fnSetHeight)(0);
+ (pFtn->Prt().*fnRect->fnSetHeight)(0);
+ pFtn->Calc();
+ pFtn->GetUpper()->Calc();
+
+ if( bCalc )
+ {
+ SwTxtFtn *pAttr = pFtn->GetAttr();
+ pCnt = pFtn->ContainsAny();
+ sal_Bool bUnlock = !pFtn->IsBackMoveLocked();
+ pFtn->LockBackMove();
+
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ pFtn->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify aFtnFrmNotitfy( pFtn );
+ // <--
+
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( pCnt->IsSctFrm() )
+ { // Wenn es sich um einen nichtleeren Bereich handelt,
+ // iterieren wir auch ueber seinen Inhalt
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pCnt = pTmp;
+ else
+ pCnt = pCnt->FindNext();
+ }
+ else
+ pCnt = pCnt->FindNext();
+ }
+ if( bUnlock )
+ {
+ pFtn->UnlockBackMove();
+ if( !pFtn->ContainsAny() && !pFtn->IsColLocked() )
+ {
+ pFtn->Cut();
+ delete pFtn;
+ // --> OD 2004-06-10 #i21478#
+ pFtn = 0L;
+ }
+ }
+ // --> OD 2005-05-18 #i49383#
+ if ( pFtn )
+ {
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pFtn->UnlockPosOfLowerObjs();
+ pFtn->Calc();
+// pFtn->UnlockPosOfLowerObjs();
+ // <--
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// else
+// {
+// aFtnFrmNotitfy.FrmDeleted();
+// }
+ // <--
+ }
+ }
+ else
+ { OSL_ENSURE( !pFtn->GetMaster() && !pFtn->GetFollow(),
+ "DelFtn und Master/Follow?" );
+ delete pFtn;
+ // --> OD 2004-06-10 #i21478#
+ pFtn = 0L;
+ }
+
+ // --> OD 2004-06-10 #i21478#
+ if ( pFtn )
+ {
+ pLastInsertedFtn = pFtn;
+ }
+ }
+
+ // --> OD 2004-06-10 #i21478# - format content of footnote following
+ // the new inserted ones.
+ if ( bCalc && pLastInsertedFtn )
+ {
+ if ( pLastInsertedFtn->GetNext() )
+ {
+ SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext());
+ SwTxtFtn* pAttr = pNextFtn->GetAttr();
+ SwFrm* pCnt = pNextFtn->ContainsAny();
+
+ sal_Bool bUnlock = !pNextFtn->IsBackMoveLocked();
+ pNextFtn->LockBackMove();
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote content.
+ pNextFtn->KeepLockPosOfLowerObjs();
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify aFtnFrmNotitfy( pNextFtn );
+ // <--
+
+ while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pNextFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( pCnt->IsSctFrm() )
+ { // Wenn es sich um einen nichtleeren Bereich handelt,
+ // iterieren wir auch ueber seinen Inhalt
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ pCnt = pTmp;
+ else
+ pCnt = pCnt->FindNext();
+ }
+ else
+ pCnt = pCnt->FindNext();
+ }
+ if( bUnlock )
+ {
+ pNextFtn->UnlockBackMove();
+ }
+ // --> OD 2005-05-18 #i49383#
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pNextFtn->UnlockPosOfLowerObjs();
+ pNextFtn->Calc();
+// pNextFtn->UnlockPosOfLowerObjs();
+ // <--
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::MoveFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest,
+ SwTxtFtn *pAttr )
+{
+ if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
+ (!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd()))
+ || pAttr->GetFtn().IsEndNote() )
+ return;
+
+ OSL_ENSURE( this == pSrc->FindFtnBossFrm( sal_True ),
+ "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" );
+
+ SwFtnFrm *pFtn = FindFirstFtn();
+ if( pFtn )
+ {
+ ChangeFtnRef( pSrc, pAttr, pDest );
+ SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( sal_True );
+ OSL_ENSURE( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" );
+ if( pDestBoss ) // robust
+ {
+ SvPtrarr aFtnArr( 5, 5 );
+ pDestBoss->_CollectFtns( pDest, pFtn, aFtnArr );
+ if ( aFtnArr.Count() )
+ {
+ pDestBoss->_MoveFtns( aFtnArr, sal_True );
+ SwPageFrm* pSrcPage = FindPageFrm();
+ SwPageFrm* pDestPage = pDestBoss->FindPageFrm();
+ // Nur beim Seitenwechsel FtnNum Updaten
+ if( pSrcPage != pDestPage )
+ {
+ if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
+ pSrcPage->UpdateFtnNum();
+ pDestPage->UpdateFtnNum();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::RearrangeFtns()
+|*
+|*************************************************************************/
+
+
+void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const sal_Bool bLock,
+ const SwTxtFtn *pAttr )
+{
+ //Alle Fussnoten der Spalte/Seite dergestalt anformatieren,
+ //dass sie ggf. die Spalte/Seite wechseln.
+
+ SwSaveFtnHeight aSave( this, nDeadLine );
+ SwFtnFrm *pFtn = FindFirstFtn();
+ if( pFtn && pFtn->GetPrev() && bLock )
+ {
+ SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower();
+ SwFrm* pCntnt = pFirst->ContainsAny();
+ if( pCntnt )
+ {
+ sal_Bool bUnlock = !pFirst->IsBackMoveLocked();
+ pFirst->LockBackMove();
+ pFirst->Calc();
+ pCntnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() )
+ {
+ SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
+ *(pCntnt->FindPageFrm()) );
+ }
+ // <--
+ if( bUnlock )
+ pFirst->UnlockBackMove();
+ }
+ pFtn = FindFirstFtn();
+ }
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0;
+ SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0;
+ if ( pCnt )
+ {
+ sal_Bool bMore = sal_True;
+ sal_Bool bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten
+ // --> OD 2005-05-18 #i49383# - disable unlock of position of
+ // lower objects during format of footnote and footnote content.
+ SwFtnFrm* pLastFtnFrm( 0L );
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// SwLayNotify* pFtnFrmNotify( 0L );
+ // footnote frame needs to be locked, if <bLock> isn't set.
+ bool bUnlockLastFtnFrm( false );
+ // <--
+ do
+ {
+ if( !bStart )
+ bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() )
+ == nFtnPos;
+ if( bStart )
+ {
+ pCnt->_InvalidatePos();
+ pCnt->_InvalidateSize();
+ pCnt->Prepare( PREP_ADJUST_FRM );
+ SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
+ // --> OD 2005-05-18 #i49383#
+ if ( pFtnFrm != pLastFtnFrm )
+ {
+ if ( pLastFtnFrm )
+ {
+ if ( !bLock && bUnlockLastFtnFrm )
+ {
+ pLastFtnFrm->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pLastFtnFrm->UnlockPosOfLowerObjs();
+ pLastFtnFrm->Calc();
+// pLastFtnFrm->UnlockPosOfLowerObjs();
+ // no extra notify for footnote frame
+// delete pFtnFrmNotify;
+ // <--
+ if ( !bLock && bUnlockLastFtnFrm &&
+ !pLastFtnFrm->GetLower() &&
+ !pLastFtnFrm->IsColLocked() &&
+ !pLastFtnFrm->IsBackMoveLocked() )
+ {
+ pLastFtnFrm->Cut();
+ delete pLastFtnFrm;
+ pLastFtnFrm = 0L;
+ }
+ }
+ if ( !bLock )
+ {
+ bUnlockLastFtnFrm = !pFtnFrm->IsColLocked();
+ pFtnFrm->ColLock();
+ }
+ pFtnFrm->KeepLockPosOfLowerObjs();
+ pLastFtnFrm = pFtnFrm;
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pFtnFrmNotify = new SwLayNotify( pLastFtnFrm );
+ // <--
+ }
+ // <--
+ // OD 30.10.2002 #97265# - invalidate position of footnote
+ // frame, if it's below its footnote container, in order to
+ // assure its correct position, probably calculating its previous
+ // footnote frames.
+ {
+ SWRECTFN( this );
+ SwFrm* aFtnContFrm = pFtnFrm->GetUpper();
+ if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
+ {
+ pFtnFrm->_InvalidatePos();
+ }
+ }
+ if ( bLock )
+ {
+ sal_Bool bUnlock = !pFtnFrm->IsBackMoveLocked();
+ pFtnFrm->LockBackMove();
+ pFtnFrm->Calc();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ if( bUnlock )
+ {
+ pFtnFrm->UnlockBackMove();
+ if( !pFtnFrm->Lower() &&
+ !pFtnFrm->IsColLocked() )
+ {
+ // --> OD 2005-08-10 #i49383#
+ OSL_ENSURE( pLastFtnFrm == pFtnFrm,
+ "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" );
+ pLastFtnFrm = 0L;
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // no extra notify for footnote frame
+// pFtnFrmNotify->FrmDeleted();
+// delete pFtnFrmNotify;
+ // <--
+ pFtnFrm->Cut();
+ delete pFtnFrm;
+ }
+ }
+ }
+ else
+ {
+ pFtnFrm->Calc();
+ pCnt->Calc();
+ // --> OD 2005-05-17 #i49383# - format anchored objects
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pCnt = pFtn->ContainsAny();
+ continue;
+ }
+ }
+ // <--
+ }
+ }
+ SwSectionFrm *pDel = NULL;
+ if( pCnt->IsSctFrm() )
+ {
+ SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
+ if( pTmp )
+ {
+ pCnt = pTmp;
+ continue;
+ }
+ pDel = (SwSectionFrm*)pCnt;
+ }
+ if ( pCnt->GetNext() )
+ pCnt = pCnt->GetNext();
+ else
+ {
+ pCnt = pCnt->FindNext();
+ if ( pCnt )
+ {
+ SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
+ if( pFtnFrm->GetRef()->FindFtnBossFrm(
+ pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this )
+ bMore = sal_False;
+ }
+ else
+ bMore = sal_False;
+ }
+ if( pDel )
+ {
+ pDel->Cut();
+ delete pDel;
+ }
+ if ( bMore )
+ {
+ //Nicht weiter als bis zur angegebenen Fussnote, falls eine
+ //angegeben wurde.
+ if ( pAttr &&
+ (::lcl_FindFtnPos( pDoc,
+ pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) )
+ bMore = sal_False;
+ }
+ } while ( bMore );
+ // --> OD 2005-05-18 #i49383#
+ if ( pLastFtnFrm )
+ {
+ if ( !bLock && bUnlockLastFtnFrm )
+ {
+ pLastFtnFrm->ColUnlock();
+ }
+ // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
+ // enable lock of lower object position before format of footnote frame.
+ pLastFtnFrm->UnlockPosOfLowerObjs();
+ pLastFtnFrm->Calc();
+// pLastFtnFrm->UnlockPosOfLowerObjs();
+ // no extra notify for footnote frame
+// delete pFtnFrmNotify;
+ // <--
+ if ( !bLock && bUnlockLastFtnFrm &&
+ !pLastFtnFrm->GetLower() &&
+ !pLastFtnFrm->IsColLocked() &&
+ !pLastFtnFrm->IsBackMoveLocked() )
+ {
+ pLastFtnFrm->Cut();
+ delete pLastFtnFrm;
+ }
+ }
+ // <--
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::UpdateFtnNum()
+|*
+|*************************************************************************/
+
+void SwPageFrm::UpdateFtnNum()
+{
+ //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
+ if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE )
+ return;
+
+ SwLayoutFrm* pBody = FindBodyCont();
+ if( !pBody || !pBody->Lower() )
+ return;
+
+ SwCntntFrm* pCntnt = pBody->ContainsCntnt();
+ sal_uInt16 nNum = 0;
+
+ while( pCntnt && pCntnt->FindPageFrm() == this )
+ {
+ if( ((SwTxtFrm*)pCntnt)->HasFtn() )
+ {
+ SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( sal_True );
+ if( pBoss->GetUpper()->IsSctFrm() &&
+ ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() )
+ pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt();
+ else
+ {
+ SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt );
+ while( pFtn )
+ {
+ SwTxtFtn* pTxtFtn = pFtn->GetAttr();
+ if( !pTxtFtn->GetFtn().IsEndNote() &&
+ !pTxtFtn->GetFtn().GetNumStr().Len() &&
+ !pFtn->GetMaster() &&
+ (pTxtFtn->GetFtn().GetNumber() != ++nNum) )
+ pTxtFtn->SetNumber( nNum );
+ if ( pFtn->GetNext() )
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ else
+ {
+ SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( sal_True );
+ if( pTmpBoss )
+ {
+ SwPageFrm* pPage = pTmpBoss->FindPageFrm();
+ pFtn = NULL;
+ lcl_NextFtnBoss( pTmpBoss, pPage, sal_False );
+ SwFtnContFrm *pCont = pTmpBoss->FindNearestFtnCont();
+ if ( pCont )
+ pFtn = (SwFtnFrm*)pCont->Lower();
+ }
+ }
+ if( pFtn && pFtn->GetRef() != pCntnt )
+ pFtn = NULL;
+ }
+ }
+ }
+ pCntnt = pCntnt->FindNextCnt();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::SetFtnDeadLine()
+|*
+|*************************************************************************/
+
+void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine )
+{
+ SwFrm *pBody = FindBodyCont();
+ pBody->Calc();
+
+ SwFrm *pCont = FindFtnCont();
+ const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten.
+ SWRECTFN( this )
+ if ( pCont )
+ {
+ pCont->Calc();
+ nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
+ }
+ else
+ nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
+
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nMaxFtnHeight += pBody->Grow( LONG_MAX, sal_True );
+ if ( IsInSct() )
+ nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, sal_True );
+
+ if ( nMaxFtnHeight < 0 )
+ nMaxFtnHeight = 0;
+ if ( nMax != LONG_MAX && nMaxFtnHeight > nMax )
+ nMaxFtnHeight = nMax;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::GetVarSpace()
+|*
+|*************************************************************************/
+SwTwips SwFtnBossFrm::GetVarSpace() const
+{
+ //Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten
+ //werden (->AMA: was macht MS da?)
+ //->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)?
+ //AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus
+ // die ganze Seite/Spalte ein.
+
+ const SwPageFrm* pPg = FindPageFrm();
+ OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
+
+ const SwFrm *pBody = FindBodyCont();
+ SwTwips nRet;
+ if( pBody )
+ {
+ SWRECTFN( this )
+ if( IsInSct() )
+ {
+ nRet = 0;
+ SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(),
+ (Frm().*fnRect->fnGetTop)() );
+ const SwSectionFrm* pSect = FindSctFrm();
+ // Endnotes in a ftncontainer causes a deadline:
+ // the bottom of the last contentfrm
+ if( pSect->IsEndnAtEnd() ) // endnotes allowed?
+ {
+ OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
+ IsFtnContFrm(), "FtnContainer exspected" );
+ const SwFtnContFrm* pCont = Lower() ?
+ (SwFtnContFrm*)Lower()->GetNext() : 0;
+ if( pCont )
+ {
+ SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
+ while( pFtn)
+ {
+ if( pFtn->GetAttr()->GetFtn().IsEndNote() )
+ { // endnote found
+ SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower();
+ if( pFrm )
+ {
+ while( pFrm->GetNext() )
+ pFrm = pFrm->GetNext(); // last cntntfrm
+ nTmp += (*fnRect->fnYDiff)(
+ (Frm().*fnRect->fnGetTop)(),
+ (pFrm->Frm().*fnRect->fnGetBottom)() );
+ }
+ break;
+ }
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ }
+ }
+ }
+ if( nTmp < nRet )
+ nRet = nTmp;
+ }
+ else
+ nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
+ nRet += (pBody->Frm().*fnRect->fnGetHeight)();
+ if( nRet < 0 )
+ nRet = 0;
+ }
+ else
+ nRet = 0;
+ if ( IsPageFrm() )
+ {
+ const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nRet += BROWSE_HEIGHT - Frm().Height();
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFtnBossFrm::NeighbourhoodAdjustment(SwFrm*)
+|*
+|* gibt Auskunft, ob die Groessenveraenderung von pFrm von AdjustNeighbourhood(...)
+|* oder von Grow/Shrink(..) verarbeitet werden sollte.
+|* Bei einem PageFrm oder in Spalten direkt unterhalb der Seite muss AdjustNei..
+|* gerufen werden, in Rahmenspalten Grow/Shrink.
+|* Spannend sind die spaltigen Bereiche: Wenn es in der Spalte einen Fussnotencontainer
+|* gibt und die Fussnoten nicht vom Bereich eingesammelt werden, ist ein Adjust..,
+|* ansonsten ein Grow/Shrink notwendig.
+|*
+|*************************************************************************/
+
+sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const
+{
+ sal_uInt8 nRet = NA_ONLY_ADJUST;
+ if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
+ {
+ // Spaltige Rahmen erfordern Grow/Shrink
+ if( GetUpper()->IsFlyFrm() )
+ nRet = NA_GROW_SHRINK;
+ else
+ {
+ OSL_ENSURE( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" );
+ if( !GetNext() && !GetPrev() )
+ nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd)
+ else
+ {
+ const SwFrm* pTmp = Lower();
+ OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
+ if( !pTmp->GetNext() )
+ nRet = NA_GROW_SHRINK;
+ else if( !GetUpper()->IsColLocked() )
+ nRet = NA_ADJUST_GROW;
+ OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(),
+ "NeighbourhoodAdjustment: Who's that guy?" );
+ }
+ }
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SetColMaxFtnHeight()
+|*
+|*************************************************************************/
+void SwPageFrm::SetColMaxFtnHeight()
+{
+ SwLayoutFrm *pBody = FindBodyCont();
+ if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
+ {
+ SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower();
+ do
+ {
+ pCol->SetMaxFtnHeight( GetMaxFtnHeight() );
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ } while ( pCol );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MoveLowerFtns
+|*
+|*************************************************************************/
+
+
+sal_Bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss,
+ SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums )
+{
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( !pDoc->GetFtnIdxs().Count() )
+ return sal_False;
+ if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
+ ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) )
+ return sal_True;
+
+ if ( !pNewBoss )
+ pNewBoss = FindFtnBossFrm( sal_True );
+ if ( pNewBoss == pOldBoss )
+ return sal_False;
+
+ sal_Bool bMoved = sal_False;
+ if( !pStart )
+ pStart = ContainsCntnt();
+
+ SvPtrarr aFtnArr( 5, 5 );
+
+ while ( IsAnLower( pStart ) )
+ {
+ if ( ((SwTxtFrm*)pStart)->HasFtn() )
+ {
+ // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
+ // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of
+ // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only
+ // footnotes have to be collected, that are positioned before the
+ // new dedicated footnote boss frame.
+ pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, sal_True );
+ }
+ pStart = pStart->GetNextCntntFrm();
+ }
+
+ OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
+ "MoveLowerFtns: Section confusion" );
+ SvPtrarr *pFtnArr;
+ SwLayoutFrm* pNewChief = 0;
+ SwLayoutFrm* pOldChief = 0;
+ if( pStart && pOldBoss->IsInSct() && ( pOldChief = pOldBoss->FindSctFrm() )
+ != ( pNewChief = pNewBoss->FindSctFrm() ) )
+ {
+ pFtnArr = new SvPtrarr( 5, 5 );
+ pOldChief = pOldBoss->FindFtnBossFrm( sal_True );
+ pNewChief = pNewBoss->FindFtnBossFrm( sal_True );
+ while( pOldChief->IsAnLower( pStart ) )
+ {
+ if ( ((SwTxtFrm*)pStart)->HasFtn() )
+ ((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart,
+ (SwFtnBossFrm*)pOldBoss, *pFtnArr );
+ pStart = pStart->GetNextCntntFrm();
+ }
+ if( !pFtnArr->Count() )
+ {
+ delete pFtnArr;
+ pFtnArr = NULL;
+ }
+ }
+ else
+ pFtnArr = NULL;
+
+ if ( aFtnArr.Count() || pFtnArr )
+ {
+ if( aFtnArr.Count() )
+ pNewBoss->_MoveFtns( aFtnArr, sal_True );
+ if( pFtnArr )
+ {
+ ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, sal_True );
+ delete pFtnArr;
+ }
+ bMoved = sal_True;
+
+ // Nur bei einem Seitenwechsel muss die FtnNum neu berechnet werden
+ if ( bFtnNums )
+ {
+ SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
+ SwPageFrm* pNewPage =pNewBoss->FindPageFrm();
+ if( pOldPage != pNewPage )
+ {
+ pOldPage->UpdateFtnNum();
+ pNewPage->UpdateFtnNum();
+ }
+ }
+ }
+ return bMoved;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::MoveFtnCntFwd()
+|*
+|*************************************************************************/
+
+
+sal_Bool SwCntntFrm::MoveFtnCntFwd( sal_Bool bMakePage, SwFtnBossFrm *pOldBoss )
+{
+ OSL_ENSURE( IsInFtn(), "Keine Ftn." );
+ SwLayoutFrm *pFtn = FindFtnFrm();
+
+ // The first paragraph in the first footnote in the first column in the
+ // sectionfrm at the top of the page has not to move forward, if the
+ // columnbody is empty.
+ if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
+ !pFtn->GetPrev() )
+ {
+ SwLayoutFrm* pBody = pOldBoss->FindBodyCont();
+ if( !pBody || !pBody->Lower() )
+ return sal_True;
+ }
+
+ //fix(9538): Wenn die Ftn noch Nachbarn hinter sich hat, so muessen
+ //diese ersteinmal verschwinden.
+ SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext();
+ SwLayoutFrm *pLst = 0;
+ while ( pNxt )
+ {
+ while ( pNxt->GetNext() )
+ pNxt = (SwLayoutFrm*)pNxt->GetNext();
+ if ( pNxt == pLst )
+ pNxt = 0;
+ else
+ { pLst = pNxt;
+ SwCntntFrm *pCnt = pNxt->ContainsCntnt();
+ if( pCnt )
+ pCnt->MoveFtnCntFwd( sal_True, pOldBoss );
+ pNxt = (SwLayoutFrm*)pFtn->GetNext();
+ }
+ }
+
+ sal_Bool bSamePage = sal_True;
+ SwLayoutFrm *pNewUpper =
+ GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
+
+ if ( pNewUpper )
+ {
+ sal_Bool bSameBoss = sal_True;
+ SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm();
+ //Wechseln wir die Spalte/Seite?
+ if ( sal_False == ( bSameBoss = pNewBoss == pOldBoss ) )
+ {
+ bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // Seitenwechsel?
+ pNewUpper->Calc();
+ }
+
+ //Das Layoutblatt, dass wir fuer Fussnoten bekommen ist entweder
+ //ein Fussnotencontainer oder eine Fussnote
+ //Wenn es eine Fussnote ist, und sie die gleiche Fussnotenreferez
+ //wie der alte Upper hat, so moven wir uns direkt hinein.
+ //Ist die Referenz einen andere oder ist es ein Container, so wird
+ //eine neue Fussnote erzeugt und in den Container gestellt.
+ // Wenn wir in einem Bereich innerhalb der Fussnote sind, muss
+ // SectionFrame noch angelegt werden.
+ SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0;
+ if( !pTmpFtn )
+ {
+ OSL_ENSURE( pNewUpper->IsFtnContFrm(), "Neuer Upper kein FtnCont.");
+ SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper;
+
+ //Fussnote erzeugen.
+ SwFtnFrm *pOld = FindFtnFrm();
+ pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(),
+ pOld, pOld->GetRef(), pOld->GetAttr() );
+ //Verkettung der Fussnoten.
+ if ( pOld->GetFollow() )
+ {
+ pTmpFtn->SetFollow( pOld->GetFollow() );
+ pOld->GetFollow()->SetMaster( pTmpFtn );
+ }
+ pOld->SetFollow( pTmpFtn );
+ pTmpFtn->SetMaster( pOld );
+ SwFrm* pNx = pCont->Lower();
+ if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() )
+ while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote())
+ pNx = pNx->GetNext();
+ pTmpFtn->Paste( pCont, pNx );
+ pTmpFtn->Calc();
+ }
+ OSL_ENSURE( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" );
+ // Bereiche in Fussnoten beduerfen besonderer Behandlung
+ SwLayoutFrm *pNewUp = pTmpFtn;
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSect = FindSctFrm();
+ // Bereich in Fussnote (oder nur Fussnote in Bereich)?
+ if( pSect->IsInFtn() )
+ {
+ if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() &&
+ pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() )
+ pNewUp = (SwSectionFrm*)pTmpFtn->Lower();
+ else
+ {
+ pNewUp = new SwSectionFrm( *pSect, sal_False );
+ pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() );
+ static_cast<SwSectionFrm*>(pNewUp)->Init();
+ pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos();
+ pNewUp->Frm().Pos().Y() += 1; //wg. Benachrichtigungen.
+
+ // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
+ // umgehaengt werden hinter den neuen Follow der Bereichsframes.
+ SwFrm* pTmp = pSect->GetNext();
+ if( pTmp )
+ {
+ SwFlowFrm* pTmpNxt;
+ if( pTmp->IsCntntFrm() )
+ pTmpNxt = (SwCntntFrm*)pTmp;
+ else if( pTmp->IsSctFrm() )
+ pTmpNxt = (SwSectionFrm*)pTmp;
+ else
+ {
+ OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
+ pTmpNxt = (SwTabFrm*)pTmp;
+ }
+ pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() );
+ }
+ }
+ }
+ }
+
+ MoveSubTree( pNewUp, pNewUp->Lower() );
+
+ if( !bSameBoss )
+ Prepare( PREP_BOSS_CHGD );
+ }
+ return bSamePage;
+}
+
+/*************************************************************************
+|*
+|* class SwSaveFtnHeight
+|*
+|*************************************************************************/
+
+
+SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) :
+ pBoss( pBs ),
+ nOldHeight( pBs->GetMaxFtnHeight() )
+{
+ pBoss->SetFtnDeadLine( nDeadLine );
+ nNewHeight = pBoss->GetMaxFtnHeight();
+}
+
+
+
+SwSaveFtnHeight::~SwSaveFtnHeight()
+{
+ //Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir
+ //ihm seinen Spass!
+ if ( nNewHeight == pBoss->GetMaxFtnHeight() )
+ pBoss->nMaxFtnHeight = nOldHeight;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+//JP 15.10.2001: in a non pro version test if the attribute has the same
+// meaning which his reference is
+
+// Normally, the pRef member and the GetRefFromAttr() result has to be
+// identically. Sometimes footnote will be moved from a master to its follow,
+// but the GetRef() is called first, so we have to ignore a master/follow
+// mismatch.
+
+const SwCntntFrm* SwFtnFrm::GetRef() const
+{
+ const SwCntntFrm* pRefAttr = GetRefFromAttr();
+ OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
+ || pRefAttr->IsAnFollow( pRef ),
+ "access to deleted Frame? pRef != pAttr->GetRef()" );
+ return pRef;
+}
+
+SwCntntFrm* SwFtnFrm::GetRef()
+{
+ const SwCntntFrm* pRefAttr = GetRefFromAttr();
+ OSL_ENSURE( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
+ || pRefAttr->IsAnFollow( pRef ),
+ "access to deleted Frame? pRef != pAttr->GetRef()" );
+ return pRef;
+}
+
+#endif
+
+const SwCntntFrm* SwFtnFrm::GetRefFromAttr() const
+{
+ SwFtnFrm* pThis = (SwFtnFrm*)this;
+ return pThis->GetRefFromAttr();
+}
+
+SwCntntFrm* SwFtnFrm::GetRefFromAttr()
+{
+ OSL_ENSURE( pAttr, "invalid Attribute" );
+ SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode();
+ SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() ));
+ SwCntntFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, sal_False );
+ return pCFrm;
+}
+
+/** search for last content in the current footnote frame
+
+ OD 2005-12-02 #i27138#
+
+ @author OD
+*/
+SwCntntFrm* SwFtnFrm::FindLastCntnt()
+{
+ SwCntntFrm* pLastCntntFrm( 0L );
+
+ // find last lower, which is a content frame or contains content.
+ // hidden text frames, empty sections and empty tables have to be skipped.
+ SwFrm* pLastLowerOfFtn( GetLower() );
+ SwFrm* pTmpLastLower( pLastLowerOfFtn );
+ while ( pTmpLastLower && pTmpLastLower->GetNext() )
+ {
+ pTmpLastLower = pTmpLastLower->GetNext();
+ if ( ( pTmpLastLower->IsTxtFrm() &&
+ !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) ||
+ ( pTmpLastLower->IsSctFrm() &&
+ static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() &&
+ static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) ||
+ ( pTmpLastLower->IsTabFrm() &&
+ static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) )
+ {
+ pLastLowerOfFtn = pTmpLastLower;
+ }
+ }
+
+ // determine last content frame depending on type of found last lower.
+ if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() )
+ {
+ pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt();
+ }
+ else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() )
+ {
+ pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt();
+ }
+ else
+ {
+ pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn);
+ }
+
+ return pLastCntntFrm;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/hffrm.cxx b/sw/source/core/layout/hffrm.cxx
new file mode 100644
index 000000000000..b8168dca941a
--- /dev/null
+++ b/sw/source/core/layout/hffrm.cxx
@@ -0,0 +1,796 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "pagefrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include <fmtcntnt.hxx>
+#include <fmthdft.hxx>
+#include <fmtfsize.hxx>
+#include "viewopt.hxx"
+#include "hffrm.hxx"
+#include "rootfrm.hxx"
+#include "txtfrm.hxx"
+#include "sectfrm.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "dflyobj.hxx"
+#include "frmfmt.hxx"
+#include "ndindex.hxx"
+#include "hfspacingitem.hxx"
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+// --> OD 2005-03-03 #i43771#
+#include <objectformatter.hxx>
+// <--
+
+extern sal_Bool bObjsDirect; //frmtool.cxx
+
+static SwTwips lcl_GetFrmMinHeight(const SwLayoutFrm & rFrm)
+{
+ const SwFmtFrmSize &rSz = rFrm.GetFmt()->GetFrmSize();
+ SwTwips nMinHeight;
+
+ switch (rSz.GetHeightSizeType())
+ {
+ case ATT_MIN_SIZE:
+ nMinHeight = rSz.GetHeight();
+
+ break;
+
+ default:
+ nMinHeight = 0;
+ }
+
+
+ return nMinHeight;
+}
+
+
+static SwTwips lcl_CalcContentHeight(SwLayoutFrm & frm)
+{
+ SwFrm* pFrm = frm.Lower();
+
+ SwTwips nRemaining = 0;
+ sal_uInt16 nNum = 0;
+ pFrm = frm.Lower();
+ while ( pFrm )
+ {
+ SwTwips nTmp;
+
+ nTmp = pFrm->Frm().Height();
+ nRemaining += nTmp;
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ nTmp = ((SwTxtFrm*)pFrm)->GetParHeight()
+ - pFrm->Prt().Height();
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += nTmp;
+ }
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ {
+ nTmp = ((SwSectionFrm*)pFrm)->Undersize();
+ nRemaining += nTmp;
+ }
+ pFrm = pFrm->GetNext();
+
+ nNum++;
+ }
+
+ return nRemaining;
+}
+
+static void lcl_LayoutFrmEnsureMinHeight(SwLayoutFrm & rFrm,
+ const SwBorderAttrs * )
+{
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(rFrm);
+
+ if (rFrm.Frm().Height() < nMinHeight)
+ {
+ rFrm.Grow(nMinHeight - rFrm.Frm().Height());
+ }
+}
+
+SwHeadFootFrm::SwHeadFootFrm( SwFrmFmt * pFmt, SwFrm* pSib, sal_uInt16 nTypeIn)
+ : SwLayoutFrm( pFmt, pSib )
+{
+ nType = nTypeIn;
+ SetDerivedVert( sal_False );
+
+ const SwFmtCntnt &rCnt = pFmt->GetCntnt();
+
+ OSL_ENSURE( rCnt.GetCntntIdx(), "Kein Inhalt fuer Header." );
+
+ //Fuer Header Footer die Objekte gleich erzeugen lassen.
+ sal_Bool bOld = bObjsDirect;
+ bObjsDirect = sal_True;
+ sal_uLong nIndex = rCnt.GetCntntIdx()->GetIndex();
+ ::_InsertCnt( this, pFmt->GetDoc(), ++nIndex );
+ bObjsDirect = bOld;
+}
+
+void SwHeadFootFrm::FormatPrt(SwTwips & nUL, const SwBorderAttrs * pAttrs)
+{
+ if (GetEatSpacing())
+ {
+ /* The minimal height of the print area is the minimal height of the
+ frame without the height needed for borders and shadow. */
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+
+ nMinHeight -= pAttrs->CalcTop();
+ nMinHeight -= pAttrs->CalcBottom();
+
+ /* If the minimal height of the print area is negative, try to
+ compensate by overlapping */
+ SwTwips nOverlap = 0;
+ if (nMinHeight < 0)
+ {
+ nOverlap = -nMinHeight;
+ nMinHeight = 0;
+ }
+
+ /* Calculate desired height of content. The minimal height has to be
+ adhered. */
+ SwTwips nHeight;
+
+ if ( ! HasFixSize() )
+ nHeight = lcl_CalcContentHeight(*this);
+ else
+ nHeight = nMinHeight;
+
+ if (nHeight < nMinHeight)
+ nHeight = nMinHeight;
+
+ /* calculate initial spacing/line space */
+ SwTwips nSpace, nLine;
+
+ if (IsHeaderFrm())
+ {
+ nSpace = pAttrs->CalcBottom();
+ nLine = pAttrs->CalcBottomLine();
+ }
+ else
+ {
+ nSpace = pAttrs->CalcTop();
+ nLine = pAttrs->CalcTopLine();
+ }
+
+ /* calculate overlap and correct spacing */
+ nOverlap += nHeight - nMinHeight;
+ if (nOverlap < nSpace - nLine)
+ nSpace -= nOverlap;
+ else
+ nSpace = nLine;
+
+ /* calculate real vertical space between frame and print area */
+ if (IsHeaderFrm())
+ nUL = pAttrs->CalcTop() + nSpace;
+ else
+ nUL = pAttrs->CalcBottom() + nSpace;
+
+ /* set print area */
+ // OD 23.01.2003 #106895# - add first parameter to <SwBorderAttrs::CalcRight(..)>
+ SwTwips nLR = pAttrs->CalcLeft( this ) + pAttrs->CalcRight( this );
+
+ aPrt.Left(pAttrs->CalcLeft(this));
+
+ if (IsHeaderFrm())
+ aPrt.Top(pAttrs->CalcTop());
+ else
+ aPrt.Top(nSpace);
+
+ aPrt.Width(aFrm.Width() - nLR);
+
+ SwTwips nNewHeight;
+
+ if (nUL < aFrm.Height())
+ nNewHeight = aFrm.Height() - nUL;
+ else
+ nNewHeight = 0;
+
+ aPrt.Height(nNewHeight);
+
+ }
+ else
+ {
+ //Position einstellen.
+ aPrt.Left( pAttrs->CalcLeft( this ) );
+ aPrt.Top ( pAttrs->CalcTop() );
+
+ //Sizes einstellen; die Groesse gibt der umgebende Frm vor, die
+ //die Raender werden einfach abgezogen.
+ // OD 23.01.2003 #106895# - add first parameter to <SwBorderAttrs::CalcRight(..)>
+ SwTwips nLR = pAttrs->CalcLeft( this ) + pAttrs->CalcRight( this );
+ aPrt.Width ( aFrm.Width() - nLR );
+ aPrt.Height( aFrm.Height()- nUL );
+
+ }
+
+ bValidPrtArea = sal_True;
+}
+
+void SwHeadFootFrm::FormatSize(SwTwips nUL, const SwBorderAttrs * pAttrs)
+{
+ if ( !HasFixSize() )
+ {
+ if( !IsColLocked() )
+ {
+ bValidSize = bValidPrtArea = sal_True;
+
+ const SwTwips nBorder = nUL;
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ nMinHeight -= pAttrs->CalcTop();
+ nMinHeight -= pAttrs->CalcBottom();
+
+ if (nMinHeight < 0)
+ nMinHeight = 0;
+
+ ColLock();
+
+ SwTwips nMaxHeight = LONG_MAX;
+ SwTwips nRemaining, nOldHeight;
+ // --> OD 2006-05-24 #i64301#
+ // use the position of the footer printing area to control invalidation
+ // of the first footer content.
+ Point aOldFooterPrtPos;
+ // <--
+
+ do
+ {
+ nOldHeight = Prt().Height();
+ SwFrm* pFrm = Lower();
+ // --> OD 2006-05-24 #i64301#
+ if ( pFrm &&
+ aOldFooterPrtPos != ( Frm().Pos() + Prt().Pos() ) )
+ {
+ pFrm->_InvalidatePos();
+ aOldFooterPrtPos = Frm().Pos() + Prt().Pos();
+ }
+ // <--
+ while( pFrm )
+ {
+ pFrm->Calc();
+ // --> OD 2005-03-03 #i43771# - format also object anchored
+ // at the frame
+ // --> OD 2005-05-03 #i46941# - frame has to be valid.
+ // Note: frame could be invalid after calling its format,
+ // if it's locked
+ OSL_ENSURE( StackHack::IsLocked() || !pFrm->IsTxtFrm() ||
+ pFrm->IsValid() ||
+ static_cast<SwTxtFrm*>(pFrm)->IsJoinLocked(),
+ "<SwHeadFootFrm::FormatSize(..)> - text frame invalid and not locked." );
+ if ( pFrm->IsTxtFrm() && pFrm->IsValid() )
+ {
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pFrm,
+ *(pFrm->FindPageFrm()) ) )
+ {
+ // restart format with first content
+ pFrm = Lower();
+ continue;
+ }
+ }
+ // <--
+ pFrm = pFrm->GetNext();
+ }
+ nRemaining = 0;
+ pFrm = Lower();
+
+ while ( pFrm )
+ {
+ nRemaining += pFrm->Frm().Height();
+
+ if( pFrm->IsTxtFrm() &&
+ ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - pFrm->Prt().Height();
+ else if( pFrm->IsSctFrm() &&
+ ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ if ( nRemaining < nMinHeight )
+ nRemaining = nMinHeight;
+
+ SwTwips nDiff = nRemaining - nOldHeight;
+
+ if( !nDiff )
+ break;
+ if( nDiff < 0 )
+ {
+ nMaxHeight = nOldHeight;
+
+ if( nRemaining <= nMinHeight )
+ nRemaining = ( nMaxHeight + nMinHeight + 1 ) / 2;
+ }
+ else
+ {
+ if (nOldHeight > nMinHeight)
+ nMinHeight = nOldHeight;
+
+ if( nRemaining >= nMaxHeight )
+ nRemaining = ( nMaxHeight + nMinHeight + 1 ) / 2;
+ }
+
+ nDiff = nRemaining - nOldHeight;
+
+ if ( nDiff )
+ {
+ ColUnlock();
+ if ( nDiff > 0 )
+ {
+ if ( Grow( nDiff ) )
+ {
+ pFrm = Lower();
+
+ while ( pFrm )
+ {
+ if( pFrm->IsTxtFrm())
+ {
+ SwTxtFrm * pTmpFrm = (SwTxtFrm*) pFrm;
+ if (pTmpFrm->IsUndersized() )
+ {
+ pTmpFrm->InvalidateSize();
+ pTmpFrm->Prepare(PREP_ADJUST_FRM);
+ }
+ }
+ /* #i3568# Undersized sections need to be
+ invalidated too. */
+ else if (pFrm->IsSctFrm())
+ {
+ SwSectionFrm * pTmpFrm =
+ (SwSectionFrm*) pFrm;
+ if (pTmpFrm->IsUndersized() )
+ {
+ pTmpFrm->InvalidateSize();
+ pTmpFrm->Prepare(PREP_ADJUST_FRM);
+ }
+ }
+ pFrm = pFrm->GetNext();
+ }
+ }
+ }
+ else
+ Shrink( -nDiff );
+ //Schnell auf dem kurzen Dienstweg die Position updaten.
+
+ MakePos();
+ ColLock();
+ }
+ else
+ break;
+ //Unterkante des Uppers nicht ueberschreiten.
+ if ( GetUpper() && Frm().Height() )
+ {
+ const SwTwips nDeadLine = GetUpper()->Frm().Top() +
+ GetUpper()->Prt().Bottom();
+ const SwTwips nBot = Frm().Bottom();
+ if ( nBot > nDeadLine )
+ {
+ Frm().Bottom( nDeadLine );
+ Prt().SSize().Height() = Frm().Height() - nBorder;
+ }
+ }
+ bValidSize = bValidPrtArea = sal_True;
+ } while( nRemaining<=nMaxHeight && nOldHeight!=Prt().Height() );
+ ColUnlock();
+ }
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else //if ( GetType() & 0x0018 )
+ {
+ do
+ {
+ if ( Frm().Height() != pAttrs->GetSize().Height() )
+ ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
+ bValidSize = sal_True;
+ MakePos();
+ } while ( !bValidSize );
+ }
+}
+
+void SwHeadFootFrm::Format(const SwBorderAttrs * pAttrs)
+{
+ OSL_ENSURE( pAttrs, "SwFooterFrm::Format, pAttrs ist 0." );
+
+ if ( bValidPrtArea && bValidSize )
+ return;
+
+ if ( ! GetEatSpacing() && IsHeaderFrm())
+ {
+ SwLayoutFrm::Format(pAttrs);
+ }
+ else
+ {
+ lcl_LayoutFrmEnsureMinHeight(*this, pAttrs);
+
+ long nUL = pAttrs->CalcTop() + pAttrs->CalcBottom();
+
+ if ( !bValidPrtArea )
+ FormatPrt(nUL, pAttrs);
+
+ if ( !bValidSize )
+ FormatSize(nUL, pAttrs);
+ }
+}
+
+SwTwips SwHeadFootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nResult;
+
+ if ( IsColLocked() )
+ {
+ nResult = 0;
+ }
+ else if (!GetEatSpacing())
+ {
+ nResult = SwLayoutFrm::GrowFrm(nDist, bTst, bInfo);
+ }
+ else
+ {
+ nResult = 0;
+
+ SwBorderAttrAccess * pAccess =
+ new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ OSL_ENSURE(pAccess, "no border attributes");
+
+ SwBorderAttrs * pAttrs = pAccess->Get();
+
+ /* First assume the whole amount to grow can be provided by eating
+ spacing. */
+ SwTwips nEat = nDist;
+ SwTwips nMaxEat;
+
+ /* calculate maximum eatable spacing */
+ if (IsHeaderFrm())
+ nMaxEat = aFrm.Height() - aPrt.Top() - aPrt.Height() - pAttrs->CalcBottomLine();
+ else
+ nMaxEat = aPrt.Top() - pAttrs->CalcTopLine();
+
+ delete pAccess;
+
+ if (nMaxEat < 0)
+ nMaxEat = 0;
+
+ /* If the frame is too small, eat less spacing thus letting the frame
+ grow more. */
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ SwTwips nFrameTooSmall = nMinHeight - Frm().Height();
+
+ if (nFrameTooSmall > 0)
+ nEat -= nFrameTooSmall;
+
+ /* No negative eating, not eating more than allowed. */
+ if (nEat < 0)
+ nEat = 0;
+ else if (nEat > nMaxEat)
+ nEat = nMaxEat;
+
+ // OD 10.04.2003 #108719# - Notify fly frame, if header frame
+ // grows. Consider, that 'normal' grow of layout frame already notifys
+ // the fly frames.
+ sal_Bool bNotifyFlys = sal_False;
+ if (nEat > 0)
+ {
+ if ( ! bTst)
+ {
+ if (! IsHeaderFrm())
+ {
+ aPrt.Top(aPrt.Top() - nEat);
+ aPrt.Height(aPrt.Height() - nEat);
+ }
+
+ InvalidateAll();
+ }
+
+ nResult += nEat;
+ // OD 14.04.2003 #108719# - trigger fly frame notify.
+ if ( IsHeaderFrm() )
+ {
+ bNotifyFlys = sal_True;
+ }
+ }
+
+ if (nDist - nEat > 0)
+ {
+ SwTwips nFrmGrow =
+ SwLayoutFrm::GrowFrm( nDist - nEat, bTst, bInfo );
+
+ nResult += nFrmGrow;
+ if ( nFrmGrow > 0 )
+ {
+ bNotifyFlys = sal_False;
+ }
+ }
+
+ // OD 10.04.2003 #108719# - notify fly frames, if necessary and triggered.
+ if ( ( nResult > 0 ) && bNotifyFlys )
+ {
+ NotifyLowerObjs();
+ }
+ }
+
+ if ( nResult && !bTst )
+ SetCompletePaint();
+
+ return nResult;
+}
+
+SwTwips SwHeadFootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nResult;
+
+ if ( IsColLocked() )
+ {
+ nResult = 0;
+ }
+ else if (! GetEatSpacing())
+ {
+ nResult = SwLayoutFrm::ShrinkFrm(nDist, bTst, bInfo);
+ }
+ else
+ {
+ nResult = 0;
+
+ SwTwips nMinHeight = lcl_GetFrmMinHeight(*this);
+ SwTwips nOldHeight = Frm().Height();
+ SwTwips nRest = 0; // Amount to shrink by spitting out spacing
+
+ if ( nOldHeight >= nMinHeight )
+ {
+ /* If the frame's height is bigger than its minimum height, shrink
+ the frame towards its minimum height. If this is not sufficient
+ to provide the shrinking requested provide the rest by spitting
+ out spacing. */
+
+ SwTwips nBiggerThanMin = nOldHeight - nMinHeight;
+
+ if (nBiggerThanMin < nDist)
+ {
+ nRest = nDist - nBiggerThanMin;
+ }
+ /* info: declaration of nRest -> else nRest = 0 */
+ }
+ else
+ /* The frame cannot shrink. Provide shrinking by spitting out
+ spacing. */
+ nRest = nDist;
+
+ // OD 10.04.2003 #108719# - Notify fly frame, if header/footer frame
+ // shrinks. Consider, that 'normal' shrink of layout frame already notifys
+ // the fly frames.
+ sal_Bool bNotifyFlys = sal_False;
+ if (nRest > 0)
+ {
+
+ SwBorderAttrAccess * pAccess =
+ new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ OSL_ENSURE(pAccess, "no border attributes");
+
+ SwBorderAttrs * pAttrs = pAccess->Get();
+
+ /* minimal height of print area */
+ SwTwips nMinPrtHeight = nMinHeight
+ - pAttrs->CalcTop()
+ - pAttrs->CalcBottom();
+
+ if (nMinPrtHeight < 0)
+ nMinPrtHeight = 0;
+
+ delete pAccess;
+
+ /* assume all shrinking can be provided */
+ SwTwips nShrink = nRest;
+
+ /* calculate maximum shrinking */
+ SwTwips nMaxShrink = aPrt.Height() - nMinPrtHeight;
+
+ /* shrink no more than maximum shrinking */
+ if (nShrink > nMaxShrink)
+ {
+ //nRest -= nShrink - nMaxShrink;
+ nShrink = nMaxShrink;
+ }
+
+ if (!bTst)
+ {
+ if (! IsHeaderFrm() )
+ {
+ aPrt.Top(aPrt.Top() + nShrink);
+ aPrt.Height(aPrt.Height() - nShrink);
+ }
+
+ InvalidateAll();
+ }
+ nResult += nShrink;
+ // OD 14.04.2003 #108719# - trigger fly frame notify.
+ if ( IsHeaderFrm() )
+ {
+ bNotifyFlys = sal_True;
+ }
+ }
+
+ /* The shrinking not providable by spitting out spacing has to be done
+ by the frame. */
+ if (nDist - nRest > 0)
+ {
+ SwTwips nShrinkAmount = SwLayoutFrm::ShrinkFrm( nDist - nRest, bTst, bInfo );
+ nResult += nShrinkAmount;
+ if ( nShrinkAmount > 0 )
+ {
+ bNotifyFlys = sal_False;
+ }
+ }
+
+ // OD 10.04.2003 #108719# - notify fly frames, if necessary.
+ if ( ( nResult > 0 ) && bNotifyFlys )
+ {
+ NotifyLowerObjs();
+ }
+ }
+
+ return nResult;
+}
+
+sal_Bool SwHeadFootFrm::GetEatSpacing() const
+{
+ const SwFrmFmt * pFmt = GetFmt();
+ OSL_ENSURE(pFmt, "SwHeadFootFrm: no format?");
+
+ if (pFmt->GetHeaderAndFooterEatSpacing().GetValue())
+ return sal_True;
+
+ return sal_False;
+}
+
+
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareHeader()
+|*
+|* Beschreibung Erzeugt oder Entfernt Header
+|*
+|*************************************************************************/
+
+
+void DelFlys( SwLayoutFrm *pFrm, SwPageFrm *pPage )
+{
+ for ( int i = 0; pPage->GetSortedObjs() &&
+ pPage->GetSortedObjs()->Count() &&
+ i < (int)pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
+ if ( pFrm->IsAnLower( pFlyFrm ) )
+ {
+ delete pFlyFrm;
+ --i;
+ }
+ }
+ }
+}
+
+
+
+void SwPageFrm::PrepareHeader()
+{
+ SwLayoutFrm *pLay = (SwLayoutFrm*)Lower();
+ if ( !pLay )
+ return;
+
+ const SwFmtHeader &rH = ((SwFrmFmt*)GetRegisteredIn())->GetHeader();
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bOn = !(pSh && pSh->GetViewOptions()->getBrowseMode());
+
+ if ( bOn && rH.IsActive() )
+ { //Header einsetzen, vorher entfernen falls vorhanden.
+ OSL_ENSURE( rH.GetHeaderFmt(), "FrmFmt fuer Header nicht gefunden." );
+
+ if ( pLay->GetFmt() == (SwFrmFmt*)rH.GetHeaderFmt() )
+ return; //Der Footer ist bereits der richtige
+
+ if ( pLay->IsHeaderFrm() )
+ { SwLayoutFrm *pDel = pLay;
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ ::DelFlys( pDel, this );
+ pDel->Cut();
+ delete pDel;
+ }
+ OSL_ENSURE( pLay, "Wohin mit dem Header?" );
+ SwHeaderFrm *pH = new SwHeaderFrm( (SwFrmFmt*)rH.GetHeaderFmt(), this );
+ pH->Paste( this, pLay );
+ if ( GetUpper() )
+ ::RegistFlys( this, pH );
+ }
+ else if ( pLay && pLay->IsHeaderFrm() )
+ { //Header entfernen falls vorhanden.
+ ::DelFlys( pLay, this );
+ pLay->Cut();
+ delete pLay;
+ }
+}
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareFooter()
+|*
+|* Beschreibung Erzeugt oder Entfernt Footer
+|*
+|*************************************************************************/
+
+
+void SwPageFrm::PrepareFooter()
+{
+ SwLayoutFrm *pLay = (SwLayoutFrm*)Lower();
+ if ( !pLay )
+ return;
+
+ const SwFmtFooter &rF = ((SwFrmFmt*)GetRegisteredIn())->GetFooter();
+ while ( pLay->GetNext() )
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bOn = !(pSh && pSh->GetViewOptions()->getBrowseMode());
+
+ if ( bOn && rF.IsActive() )
+ { //Footer einsetzen, vorher entfernen falls vorhanden.
+ OSL_ENSURE( rF.GetFooterFmt(), "FrmFmt fuer Footer nicht gefunden." );
+
+ if ( pLay->GetFmt() == (SwFrmFmt*)rF.GetFooterFmt() )
+ return; //Der Footer ist bereits der richtige.
+
+ if ( pLay->IsFooterFrm() )
+ { ::DelFlys( pLay, this );
+ pLay->Cut();
+ delete pLay;
+ }
+ SwFooterFrm *pF = new SwFooterFrm( (SwFrmFmt*)rF.GetFooterFmt(), this );
+ pF->Paste( this );
+ if ( GetUpper() )
+ ::RegistFlys( this, pF );
+ }
+ else if ( pLay && pLay->IsFooterFrm() )
+ { //Footer entfernen falls vorhanden.
+ ::DelFlys( pLay, this );
+ ViewShell *pShell;
+ if ( pLay->GetPrev() && 0 != (pShell = getRootFrm()->GetCurrShell()) &&
+ pShell->VisArea().HasArea() )
+ pShell->InvalidateWindows( pShell->VisArea() );
+ pLay->Cut();
+ delete pLay;
+ }
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
new file mode 100644
index 000000000000..e0b4cd7432dc
--- /dev/null
+++ b/sw/source/core/layout/layact.cxx
@@ -0,0 +1,2546 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <time.h>
+#include "rootfrm.hxx"
+#include "pagefrm.hxx"
+#include "cntfrm.hxx"
+#include "doc.hxx"
+#include "IDocumentDrawModelAccess.hxx"
+#include "IDocumentSettingAccess.hxx"
+#include "IDocumentLayoutAccess.hxx"
+#include "IDocumentStatistics.hxx"
+#include "IDocumentTimerAccess.hxx"
+#include "viewimp.hxx"
+#include "crsrsh.hxx"
+#include "dflyobj.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "dcontact.hxx"
+#include "ndtxt.hxx" // OnlineSpelling
+#include "frmfmt.hxx"
+#include "swregion.hxx"
+#include "viewopt.hxx" // OnlineSpelling ueber Internal-TabPage testen.
+#include "pam.hxx" // OnlineSpelling wg. der aktuellen Cursorposition
+#include "dbg_lay.hxx"
+#include "layouter.hxx" // LoopControlling
+#include "docstat.hxx"
+#include "swevent.hxx"
+
+#include <sfx2/event.hxx>
+
+#include <ftnidx.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <SwSmartTagMgr.hxx>
+
+#define _LAYACT_CXX
+#include "layact.hxx"
+#include <swwait.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtanchr.hxx>
+#include <tools/shl.hxx>
+#include <sfx2/progress.hxx>
+#include <docsh.hxx>
+
+#include "swmodule.hxx"
+#include "fmtline.hxx"
+#include "tabfrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+#include "notxtfrm.hxx"
+#include "flyfrms.hxx"
+#include "mdiexp.hxx"
+#include "fmtornt.hxx"
+#include "sectfrm.hxx"
+#include "lineinfo.hxx"
+#include <acmplwrd.hxx>
+// --> OD 2004-06-28 #i28701#
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <PostItMgr.hxx>
+#include <vector>
+
+// <--
+//#pragma optimize("ity",on)
+
+/*************************************************************************
+|*
+|* SwLayAction Statisches Geraffel
+|*
+|*************************************************************************/
+
+#define IS_FLYS (pPage->GetSortedObjs())
+#define IS_INVAFLY (pPage->IsInvalidFly())
+
+
+//Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
+#if OSL_DEBUG_LEVEL > 1
+
+static void BreakPoint()
+{
+ return;
+}
+
+#define CHECKPAGE \
+ { if ( IsAgain() ) \
+ { BreakPoint(); \
+ return; \
+ } \
+ }
+
+#define XCHECKPAGE \
+ { if ( IsAgain() ) \
+ { BreakPoint(); \
+ if( bNoLoop ) \
+ pLayoutAccess->GetLayouter()->EndLoopControl(); \
+ return; \
+ } \
+ }
+#else
+#define CHECKPAGE \
+ { if ( IsAgain() ) \
+ return; \
+ }
+
+#define XCHECKPAGE \
+ { if ( IsAgain() ) \
+ { \
+ if( bNoLoop ) \
+ pLayoutAccess->GetLayouter()->EndLoopControl(); \
+ return; \
+ } \
+ }
+#endif
+
+#define RESCHEDULE \
+ { \
+ if ( IsReschedule() ) \
+ { \
+ if (pProgress) pProgress->Reschedule(); \
+ ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
+ } \
+ }
+
+inline sal_uLong Ticks()
+{
+ return 1000 * clock() / CLOCKS_PER_SEC;
+}
+
+void SwLayAction::CheckWaitCrsr()
+{
+ RESCHEDULE
+ if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
+ ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
+ {
+ pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), sal_True );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::CheckIdleEnd()
+|*
+|*************************************************************************/
+//Ist es wirklich schon soweit...
+inline void SwLayAction::CheckIdleEnd()
+{
+ if ( !IsInput() )
+ bInput = GetInputType() && Application::AnyInput( GetInputType() );
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::SetStatBar()
+|*
+|*************************************************************************/
+void SwLayAction::SetStatBar( sal_Bool bNew )
+{
+ if ( bNew )
+ {
+ nEndPage = pRoot->GetPageNum();
+ nEndPage += nEndPage * 10 / 100;
+ }
+ else
+ nEndPage = USHRT_MAX;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::PaintCntnt()
+|*
+|* Beschreibung Je nach Typ wird der Cntnt entsprechend seinen
+|* Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
+|* Region eingetragen.
+|* PaintCntnt: fuellt die Region,
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
+ const SwPageFrm *pPage )
+{
+ SwRegionRects aTmp( rRect );
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
+ sal_uInt16 i;
+
+ for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
+ {
+ SdrObject *pO = rObjs[i]->DrawObj();
+ if ( !pO->ISA(SwVirtFlyDrawObj) )
+ continue;
+
+ // OD 2004-01-15 #110582# - do not consider invisible objects
+ const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
+ if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
+ {
+ continue;
+ }
+
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
+
+ if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
+ continue;
+
+ if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
+ continue;
+
+ if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
+ continue;
+
+ if ( pSelfFly )
+ {
+ const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
+ if ( pO->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
+ if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ }
+ }
+
+ /// OD 19.08.2002 #99657#
+ /// Fly frame without a lower have to be subtracted from paint region.
+ /// For checking, if fly frame contains transparent graphic or
+ /// has surrounded contour, assure that fly frame has a lower
+ if ( pFly->Lower() &&
+ pFly->Lower()->IsNoTxtFrm() &&
+ ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
+ pFly->GetFmt()->GetSurround().IsContour() )
+ )
+ {
+ continue;
+ }
+
+ /// OD 19.08.2002 #99657#
+ /// Region of a fly frame with transparent background or a transparent
+ /// shadow have not to be subtracted from paint region
+ if ( pFly->IsBackgroundTransparent() ||
+ pFly->IsShadowTransparent() )
+ {
+ continue;
+ }
+
+ aTmp -= pFly->Frm();
+ }
+
+ sal_Bool bRetPaint = sal_False;
+ const SwRect *pData = aTmp.GetData();
+ for ( i = 0; i < aTmp.Count(); ++pData, ++i )
+ bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
+ return bRetPaint;
+}
+
+inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
+ const SwPageFrm *pPage,
+ const SwRect &rRect )
+{
+ if ( rRect.HasArea() )
+ {
+ if ( pPage->GetSortedObjs() )
+ return PaintWithoutFlys( rRect, pCntnt, pPage );
+ else
+ return pImp->GetShell()->AddPaintRect( rRect );
+ }
+ return sal_False;
+}
+
+void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
+ const SwPageFrm *pPage,
+ const SwRect &rOldRect,
+ long nOldBottom )
+{
+ SWRECTFN( pCnt )
+
+ if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
+ {
+ SwRect aPaint( pCnt->PaintArea() );
+ if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
+ pCnt->ResetCompletePaint();
+ }
+ else
+ {
+ // paint the area between printing bottom and frame bottom and
+ // the area left and right beside the frame, if its height changed.
+ long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
+ long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
+ const bool bHeightDiff = nOldHeight != nNewHeight;
+ if( bHeightDiff )
+ {
+ // OD 05.11.2002 #94454# - consider whole potential paint area.
+ //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
+ SwRect aDrawRect( pCnt->PaintArea() );
+ if( nOldHeight > nNewHeight )
+ nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
+ (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
+ _PaintCntnt( pCnt, pPage, aDrawRect );
+ }
+ // paint content area
+ SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
+ _PaintCntnt( pCnt, pPage, aPaintRect );
+ }
+
+ if ( pCnt->IsRetouche() && !pCnt->GetNext() )
+ {
+ const SwFrm *pTmp = pCnt;
+ if( pCnt->IsInSct() )
+ {
+ const SwSectionFrm* pSct = pCnt->FindSctFrm();
+ if( pSct->IsRetouche() && !pSct->GetNext() )
+ pTmp = pSct;
+ }
+ SwRect aRect( pTmp->GetUpper()->PaintArea() );
+ (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
+ if ( !_PaintCntnt( pCnt, pPage, aRect ) )
+ pCnt->ResetRetouche();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::SwLayAction()
+|*
+|*************************************************************************/
+SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
+ pRoot( pRt ),
+ pImp( pI ),
+ pOptTab( 0 ),
+ pWait( 0 ),
+ pProgress(NULL),
+ nPreInvaPage( USHRT_MAX ),
+ nStartTicks( Ticks() ),
+ nInputType( 0 ),
+ nEndPage( USHRT_MAX ),
+ nCheckPageNum( USHRT_MAX )
+{
+ bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
+ bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
+ bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
+ bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
+ // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
+ mbFormatCntntOnInterrupt = sal_False;
+
+ pImp->pLayAct = this; //Anmelden
+}
+
+SwLayAction::~SwLayAction()
+{
+ OSL_ENSURE( !pWait, "Wait object not destroyed" );
+ pImp->pLayAct = 0; //Abmelden
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::Reset()
+|*
+|*************************************************************************/
+void SwLayAction::Reset()
+{
+ pOptTab = 0;
+ nStartTicks = Ticks();
+ nInputType = 0;
+ nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
+ bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
+ bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
+ bUpdateExpFlds = bBrowseActionStop = sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::RemoveEmptyBrowserPages()
+|*
+|*************************************************************************/
+
+sal_Bool SwLayAction::RemoveEmptyBrowserPages()
+{
+ //Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
+ //unangenehm lange stehen. Diese beseiten wir mal schnell.
+ sal_Bool bRet = sal_False;
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
+ do
+ {
+ if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
+ pPage->ContainsCntnt() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ {
+ bRet = sal_True;
+ SwPageFrm *pDel = pPage;
+ pPage = (SwPageFrm*)pPage->GetNext();
+ pDel->Cut();
+ delete pDel;
+ }
+ } while ( pPage );
+ }
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwLayAction::Action()
+|*
+|*************************************************************************/
+void SwLayAction::Action()
+{
+ bActionInProgress = sal_True;
+
+ //TurboMode? Disqualifiziert fuer Idle-Format.
+ if ( IsPaint() && !IsIdle() && TurboAction() )
+ {
+ delete pWait, pWait = 0;
+ pRoot->ResetTurboFlag();
+ bActionInProgress = sal_False;
+ pRoot->DeleteEmptySct();
+ return;
+ }
+ else if ( pRoot->GetTurbo() )
+ {
+ pRoot->DisallowTurbo();
+ const SwFrm *pFrm = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pFrm->InvalidatePage();
+ }
+ pRoot->DisallowTurbo();
+
+ if ( IsCalcLayout() )
+ SetCheckPages( sal_False );
+
+ InternalAction();
+ bAgain |= RemoveEmptyBrowserPages();
+ while ( IsAgain() )
+ {
+ bAgain = bNextCycle = sal_False;
+ InternalAction();
+ bAgain |= RemoveEmptyBrowserPages();
+ }
+ pRoot->DeleteEmptySct();
+
+ delete pWait, pWait = 0;
+
+ //Turbo-Action ist auf jedenfall wieder erlaubt.
+ pRoot->ResetTurboFlag();
+ pRoot->ResetTurbo();
+
+ SetCheckPages( sal_True );
+
+ bActionInProgress = sal_False;
+}
+
+SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
+{
+ SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
+ SwCntntFrm *pChk = pCnt;
+ sal_Bool bPageChgd = sal_False;
+ while ( pCnt && pCnt->IsFollow() )
+ pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
+ if ( pCnt && pChk != pCnt )
+ { bPageChgd = sal_True;
+ pPage = pCnt->FindPageFrm();
+ }
+
+ if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ SwFtnContFrm *pCont = pPage->FindFtnCont();
+ if ( pCont )
+ {
+ pCnt = pCont->ContainsCntnt();
+ pChk = pCnt;
+ while ( pCnt && pCnt->IsFollow() )
+ pCnt = (SwCntntFrm*)pCnt->FindPrev();
+ if ( pCnt && pCnt != pChk )
+ {
+ if ( bPageChgd )
+ {
+ //Die 'oberste' Seite benutzten.
+ SwPageFrm *pTmp = pCnt->FindPageFrm();
+ if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
+ pPage = pTmp;
+ }
+ else
+ pPage = pCnt->FindPageFrm();
+ }
+ }
+ }
+ return pPage;
+}
+
+// OD 2004-05-12 #i28701#
+// --> OD 2004-11-03 #i114798# - unlock position on start and end of page
+// layout process.
+class NotifyLayoutOfPageInProgress
+{
+ private:
+ SwPageFrm& mrPageFrm;
+
+ void _UnlockPositionOfObjs()
+ {
+ SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ pObj->UnlockPosition();
+ }
+ }
+ }
+ public:
+ NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
+ : mrPageFrm( _rPageFrm )
+ {
+ _UnlockPositionOfObjs();
+ _rPageFrm.SetLayoutInProgress( true );
+ }
+ ~NotifyLayoutOfPageInProgress()
+ {
+ mrPageFrm.SetLayoutInProgress( false );
+ _UnlockPositionOfObjs();
+ }
+};
+// <--
+
+void SwLayAction::InternalAction()
+{
+ OSL_ENSURE( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
+
+ pRoot->Calc();
+
+ //Die erste ungueltige bzw. zu formatierende Seite ermitteln.
+ //Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
+ //erste zu formatierende Seite diejenige Seite mit der Numemr eins.
+ //Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
+ //der ersten Sichtbaren Seite.
+ SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
+ pImp->GetFirstVisPage();
+ if ( !pPage )
+ pPage = (SwPageFrm*)pRoot->Lower();
+
+ //Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
+ //ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
+ //Cntnt's
+ if ( !IsComplete() )
+ pPage = CheckFirstVisPage( pPage );
+ sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
+
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+
+ IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
+ sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
+ sal_uInt16 nPercentPageNum = 0;
+ while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
+ {
+ if ( !pPage && nCheckPageNum != USHRT_MAX &&
+ (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
+ {
+ if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
+ {
+ SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
+ while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
+ pPg = (SwPageFrm*)pPg->GetNext();
+ if ( pPg )
+ pPage = pPg;
+ if ( !pPage )
+ break;
+ }
+ SwPageFrm *pTmp = pPage->GetPrev() ?
+ (SwPageFrm*)pPage->GetPrev() : pPage;
+ SetCheckPages( sal_True );
+ SwFrm::CheckPageDescs( pPage );
+ SetCheckPages( sal_False );
+ nCheckPageNum = USHRT_MAX;
+ pPage = pTmp;
+ continue;
+ }
+
+ if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
+ {
+ nPercentPageNum = pPage->GetPhyPageNum();
+ ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
+ }
+ pOptTab = 0;
+ //Kein ShortCut fuer Idle oder CalcLayout
+ if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
+ {
+ pRoot->DeleteEmptySct();
+ XCHECKPAGE;
+ if ( !IsInterrupt() &&
+ (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
+ {
+ if ( pRoot->IsAssertFlyPages() )
+ pRoot->AssertFlyPages();
+ if ( pRoot->IsSuperfluous() )
+ {
+ sal_Bool bOld = IsAgain();
+ pRoot->RemoveSuperfluous();
+ bAgain = bOld;
+ }
+ if ( IsAgain() )
+ {
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+ return;
+ }
+ pPage = (SwPageFrm*)pRoot->Lower();
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->GetNext() &&
+ pPage->GetPhyPageNum() < nFirstPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ continue;
+ }
+ break;
+ }
+ else
+ {
+ pRoot->DeleteEmptySct();
+ XCHECKPAGE;
+
+ // OD 2004-05-12 #i28701# - scope for instance of class
+ // <NotifyLayoutOfPageInProgress>
+ {
+ NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
+
+ while ( !IsInterrupt() && !IsNextCycle() &&
+ ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
+ {
+ // OD 2004-05-10 #i28701#
+ SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
+ if ( !IS_FLYS )
+ {
+ //Wenn keine Flys (mehr) da sind, sind die Flags
+ //mehr als fluessig.
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ }
+ // OD 2004-05-10 #i28701# - change condition
+ while ( !IsInterrupt() && !IsNextCycle() &&
+ ( pPage->IsInvalid() ||
+ (IS_FLYS && IS_INVAFLY) ) )
+ {
+ PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
+ XCHECKPAGE;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_1 = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+
+ while ( !IsNextCycle() && pPage->IsInvalidLayout() )
+ {
+ pPage->ValidateLayout();
+
+ if ( ++nLoopControlRuns_1 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
+
+#endif
+ break;
+ }
+
+ FormatLayout( pPage );
+ XCHECKPAGE;
+ }
+ // OD 2004-05-10 #i28701# - change condition
+ if ( !IsNextCycle() &&
+ ( pPage->IsInvalidCntnt() ||
+ (IS_FLYS && IS_INVAFLY) ) )
+ {
+ pPage->ValidateFlyInCnt();
+ pPage->ValidateCntnt();
+ // --> OD 2004-05-10 #i28701#
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ // <--
+ if ( !FormatCntnt( pPage ) )
+ {
+ XCHECKPAGE;
+ pPage->InvalidateCntnt();
+ pPage->InvalidateFlyInCnt();
+ // --> OD 2004-05-10 #i28701#
+ pPage->InvalidateFlyLayout();
+ pPage->InvalidateFlyCntnt();
+ // <--
+ if ( IsBrowseActionStop() )
+ bInput = sal_True;
+ }
+ }
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
+ }
+ }
+ } // end of scope for instance of class <NotifyLayoutOfPageInProgress>
+
+
+ //Eine vorige Seite kann wieder invalid sein.
+ XCHECKPAGE;
+ if ( !IS_FLYS )
+ {
+ //Wenn keine Flys (mehr) da sind, sind die Flags
+ //mehr als fluessig.
+ pPage->ValidateFlyLayout();
+ pPage->ValidateFlyCntnt();
+ }
+ if ( !IsInterrupt() )
+ {
+ SetNextCycle( sal_False );
+
+ if ( nPreInvaPage != USHRT_MAX )
+ {
+ if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
+ {
+ pImp->SetFirstVisPageInvalid();
+ SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
+ nFirstPageNum = pTmpPage->GetPhyPageNum();
+ if( nPreInvaPage < nFirstPageNum )
+ {
+ nPreInvaPage = nFirstPageNum;
+ pPage = pTmpPage;
+ }
+ }
+ while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ nPreInvaPage = USHRT_MAX;
+ }
+
+ while ( pPage->GetPrev() &&
+ ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
+ ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
+ ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
+ (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
+ nFirstPageNum) )
+ {
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ }
+
+ //Weiter bis zur naechsten invaliden Seite.
+ while ( pPage && !pPage->IsInvalid() &&
+ (!IS_FLYS || !IS_INVAFLY) )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
+ }
+ CheckIdleEnd();
+ }
+ if ( !pPage && !IsInterrupt() &&
+ (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
+ {
+ if ( pRoot->IsAssertFlyPages() )
+ pRoot->AssertFlyPages();
+ if ( pRoot->IsSuperfluous() )
+ {
+ sal_Bool bOld = IsAgain();
+ pRoot->RemoveSuperfluous();
+ bAgain = bOld;
+ }
+ if ( IsAgain() )
+ {
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+ return;
+ }
+ pPage = (SwPageFrm*)pRoot->Lower();
+ while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while ( pPage && pPage->GetNext() &&
+ pPage->GetPhyPageNum() < nFirstPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ if ( IsInterrupt() && pPage )
+ {
+ //Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
+ //Das Layout muessen wir aber schon in Ordnung bringen.
+ //Andernfalls kann folgende Situation auftreten (Bug: 3244):
+ //Am Ende des Absatz der letzten Seite wird Text eingegeben, so das
+ //der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
+ //wird gleich schnell weitergetippt - Es liegt waehrend der
+ //Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
+ //bereits anformatiert, die neue Seite ist Formatiert und steht
+ //auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
+ //eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
+ //zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
+ //aber die Raender der Seite werden nicht gepaintet. Naja, bei der
+ //zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
+ //nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
+ //wurden -- Der Rand der Seite wird nie gepaintet.
+ SwPageFrm *pPg = pPage;
+ XCHECKPAGE;
+ const SwRect &rVis = pImp->GetShell()->VisArea();
+
+ while( pPg && pPg->Frm().Bottom() < rVis.Top() )
+ pPg = (SwPageFrm*)pPg->GetNext();
+ if( pPg != pPage )
+ pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
+
+ // OD 14.04.2003 #106346# - set flag for interrupt content formatting
+ mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
+ long nBottom = rVis.Bottom();
+ // --> OD 2005-02-15 #i42586# - format current page, if idle action is active
+ // This is an optimization for the case that the interrupt is created by
+ // the move of a form control object, which is represented by a window.
+ while ( pPg && ( pPg->Frm().Top() < nBottom ||
+ ( IsIdle() && pPg == pPage ) ) )
+ // <--
+ {
+ // --> OD 2004-10-11 #i26945# - follow-up of #i28701#
+ NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
+
+ XCHECKPAGE;
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_2 = 0;
+ const sal_uInt16 nLoopControlMax = 20;
+
+ // OD 14.04.2003 #106346# - special case: interrupt content formatting
+ // --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
+ // are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
+ // and are too strict.
+ // --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
+ // normal page formatting - see above.
+ while ( ( mbFormatCntntOnInterrupt &&
+ ( pPg->IsInvalid() ||
+ ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
+ ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
+ {
+ XCHECKPAGE;
+ // --> OD 2005-06-09 #i50432# - format also at-page anchored objects
+ SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
+ // <--
+ // --> OD 2005-06-09 #i50432#
+ if ( !pPg->GetSortedObjs() )
+ {
+ pPg->ValidateFlyLayout();
+ pPg->ValidateFlyCntnt();
+ }
+ // <--
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_3 = 0;
+
+ while ( pPg->IsInvalidLayout() )
+ {
+ pPg->ValidateLayout();
+
+ if ( ++nLoopControlRuns_3 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
+#endif
+ break;
+ }
+
+ FormatLayout( pPg );
+ XCHECKPAGE;
+ }
+
+ // --> OD 2005-06-09 #i50432#
+ if ( mbFormatCntntOnInterrupt &&
+ ( pPg->IsInvalidCntnt() ||
+ ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
+ // <--
+ {
+ pPg->ValidateFlyInCnt();
+ pPg->ValidateCntnt();
+ // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
+ pPg->ValidateFlyLayout();
+ pPg->ValidateFlyCntnt();
+ // <--
+
+ if ( ++nLoopControlRuns_2 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
+#endif
+ break;
+ }
+
+ if ( !FormatCntnt( pPg ) )
+ {
+ XCHECKPAGE;
+ pPg->InvalidateCntnt();
+ pPg->InvalidateFlyInCnt();
+ // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
+ pPg->InvalidateFlyLayout();
+ pPg->InvalidateFlyCntnt();
+ // <--
+ }
+ // --> OD 2005-04-06 #i46807# - we are statisfied, if the
+ // content is formatted once complete.
+ else
+ {
+ break;
+ }
+ // <--
+ }
+ }
+ // <--
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ // OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
+ mbFormatCntntOnInterrupt = sal_False;
+ }
+ pOptTab = 0;
+ if( bNoLoop )
+ pLayoutAccess->GetLayouter()->EndLoopControl();
+}
+/*************************************************************************
+|*
+|* SwLayAction::TurboAction(), _TurboAction()
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
+{
+
+ const SwPageFrm *pPage = 0;
+ if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
+ {
+ const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
+ const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
+ pCnt->Calc();
+ if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
+ pCnt->SetRetouche();
+
+ pPage = pCnt->FindPageFrm();
+ PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
+
+ if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
+ ((SwTxtFrm*)pCnt)->RecalcAllLines();
+ if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
+ {
+ if ( IsPaintExtraData() )
+ pImp->GetShell()->AddPaintRect( pCnt->Frm() );
+ //Damit die restlichen LineNums auf der Seite bereichnet werden
+ //und nicht hier abgebrochen wird.
+ //Das im RecalcAllLines zu erledigen waere teuer, weil dort
+ //auch in unnoetigen Faellen (normale Action) auch immer die
+ //Seite benachrichtigt werden muesste.
+ const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
+ while ( pNxt &&
+ (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
+ pNxt = pNxt->GetNextCntntFrm();
+ if ( pNxt )
+ pNxt->InvalidatePage();
+ }
+ return sal_False;
+ }
+
+ if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
+ return sal_False;
+ }
+ if ( !pPage )
+ pPage = pCnt->FindPageFrm();
+
+ // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
+ if ( pCnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
+ *pPage, this ) )
+ {
+ return sal_False;
+ }
+
+ if ( pPage->IsInvalidCntnt() )
+ return sal_False;
+ return sal_True;
+}
+
+sal_Bool SwLayAction::TurboAction()
+{
+ sal_Bool bRet = sal_True;
+
+ if ( pRoot->GetTurbo() )
+ {
+ if ( !_TurboAction( pRoot->GetTurbo() ) )
+ {
+ CheckIdleEnd();
+ bRet = sal_False;
+ }
+ pRoot->ResetTurbo();
+ }
+ else
+ bRet = sal_False;
+ return bRet;
+}
+/*************************************************************************
+|*
+|* SwLayAction::IsShortCut()
+|*
+|* Beschreibung: Liefert ein True, wenn die Seite vollstaendig unter
+|* oder rechts neben dem sichbaren Bereich liegt.
+|* Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
+|* die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
+|* uebergebenen Seite weitergefuehrt werden muss. Der Paramter wird also
+|* ggf. veraendert!
+|* Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
+|* wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
+|* bereiches liegt.
+|*
+|*************************************************************************/
+static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
+{
+ if (
+ !pFrm->IsValid() ||
+ (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
+ )
+ {
+ return true;
+ }
+ return false;
+}
+
+static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
+{
+ OSL_ENSURE( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
+
+ if (lcl_IsInvaLay(pFrm, nBottom))
+ return pFrm;
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ {
+ if (lcl_IsInvaLay(pFrm, nBottom))
+ return pFrm;
+ const SwFrm *pTmp;
+ if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
+ return pTmp;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ return 0;
+}
+
+static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
+ const SwCntntFrm *pFirst )
+{
+ const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
+ pLay->ContainsCntnt();
+ while ( pCnt )
+ {
+ if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
+ {
+ if ( pCnt->Frm().Top() <= nBottom )
+ return pCnt;
+ }
+
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
+ pFly->IsCompletePaint() )
+ {
+ if ( pFly->Frm().Top() <= nBottom )
+ return pFly;
+ }
+ const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
+ if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
+ return pFrm;
+ }
+ }
+ }
+ }
+ if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
+ return 0;
+ pCnt = pCnt->GetNextCntntFrm();
+ if ( !pLay->IsAnLower( pCnt ) )
+ break;
+ }
+ return 0;
+}
+
+// --> OD 2005-02-21 #i37877# - consider drawing objects
+static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
+ long _nBottom )
+{
+ OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
+
+ for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
+ if ( pFly->Frm().Top() <= _nBottom )
+ {
+ if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
+ return pFly;
+
+ const SwFrm* pTmp;
+ if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
+ pTmp->Frm().Top() <= _nBottom )
+ return pFly;
+ }
+ }
+ else if ( pObj->ISA(SwAnchoredDrawObject) )
+ {
+ if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
+ {
+ return pObj;
+ }
+ }
+ }
+ return 0;
+}
+// <--
+
+sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
+{
+ sal_Bool bRet = sal_False;
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ //Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
+ //gibts nix als Aerger.
+ if ( !prPage->IsValid() )
+ {
+ if ( bBrowse )
+ {
+ /// OD 15.10.2002 #103517# - format complete page
+ /// Thus, loop on all lowers of the page <prPage>, instead of only
+ /// format its first lower.
+ /// NOTE: In online layout (bBrowse == sal_True) a page can contain
+ /// a header frame and/or a footer frame beside the body frame.
+ prPage->Calc();
+ SwFrm* pPageLowerFrm = prPage->Lower();
+ while ( pPageLowerFrm )
+ {
+ pPageLowerFrm->Calc();
+ pPageLowerFrm = pPageLowerFrm->GetNext();
+ }
+ }
+ else
+ FormatLayout( prPage );
+ if ( IsAgain() )
+ return sal_False;
+ }
+
+
+ const SwRect &rVis = pImp->GetShell()->VisArea();
+ if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
+ (prPage->Frm().Left()>= rVis.Right()) )
+ {
+ bRet = sal_True;
+
+ //Jetzt wird es ein bischen unangenehm: Der erste CntntFrm dieser Seite
+ //im Bodytext muss Formatiert werden, wenn er dabei die Seite
+ //wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
+ //es wurde ein PageBreak verarbeitet.
+//Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
+ //Formatiert werden, denn es kann passieren, dass kurzfristig
+ //leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
+ //wird geloescht oder verkleinert).
+
+ //Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
+ //nicht mehr sichbar ist.
+
+ const SwPageFrm *p2ndPage = prPage;
+ const SwCntntFrm *pCntnt;
+ const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
+ if( p2ndPage->IsFtnPage() && pBody )
+ pBody = (SwLayoutFrm*)pBody->GetNext();
+ pCntnt = pBody ? pBody->ContainsCntnt() : 0;
+ while ( p2ndPage && !pCntnt )
+ {
+ p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
+ if( p2ndPage )
+ {
+ pBody = p2ndPage->FindBodyCont();
+ if( p2ndPage->IsFtnPage() && pBody )
+ pBody = (SwLayoutFrm*)pBody->GetNext();
+ pCntnt = pBody ? pBody->ContainsCntnt() : 0;
+ }
+ }
+ if ( pCntnt )
+ {
+ sal_Bool bTstCnt = sal_True;
+ if ( bBrowse )
+ {
+ //Der Cnt davor schon nicht mehr sichtbar?
+ const SwFrm *pLst = pCntnt;
+ if ( pLst->IsInTab() )
+ pLst = pCntnt->FindTabFrm();
+ if ( pLst->IsInSct() )
+ pLst = pCntnt->FindSctFrm();
+ pLst = pLst->FindPrev();
+ if ( pLst &&
+ (pLst->Frm().Top() >= rVis.Bottom() ||
+ pLst->Frm().Left()>= rVis.Right()) )
+ {
+ bTstCnt = sal_False;
+ }
+ }
+
+ if ( bTstCnt )
+ {
+ // --> OD 2004-06-04 #i27756# - check after each frame calculation,
+ // if the content frame has changed the page. If yes, no other
+ // frame calculation is performed
+ bool bPageChg = false;
+
+ if ( pCntnt->IsInSct() )
+ {
+ const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
+ if ( !pSct->IsValid() )
+ {
+ pSct->Calc();
+ pSct->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ if ( !bPageChg && !pCntnt->IsValid() )
+ {
+ pCntnt->Calc();
+ pCntnt->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+
+ if ( !bPageChg && pCntnt->IsInTab() )
+ {
+ const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
+ if ( !pTab->IsValid() )
+ {
+ pTab->Calc();
+ pTab->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ if ( !bPageChg && pCntnt->IsInSct() )
+ {
+ const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
+ if ( !pSct->IsValid() )
+ {
+ pSct->Calc();
+ pSct->SetCompletePaint();
+ if ( IsAgain() )
+ return sal_False;
+ // --> OD 2004-06-04 #i27756#
+ bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
+ prPage->GetPrev();
+ }
+ }
+
+ // --> OD 2004-06-04 #i27756#
+ if ( bPageChg )
+ {
+ bRet = sal_False;
+ const SwPageFrm* pTmp = pCntnt->FindPageFrm();
+ if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
+ pTmp->IsInvalid() )
+ {
+ prPage = (SwPageFrm*)pTmp;
+ }
+ else
+ {
+ prPage = (SwPageFrm*)prPage->GetPrev();
+ }
+ }
+ // --> OD 2005-04-25 #121980# - no shortcut, if at previous page
+ // an anchored object is registered, whose anchor is <pCntnt>.
+ else if ( prPage->GetPrev() &&
+ static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
+ {
+ SwSortedObjs* pObjs =
+ static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pObj = (*pObjs)[i];
+ if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ // <--
+ }
+ }
+ }
+
+ if ( !bRet && bBrowse )
+ {
+ const long nBottom = rVis.Bottom();
+ const SwAnchoredObject* pObj( 0L );
+ if ( prPage->GetSortedObjs() &&
+ (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
+ 0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
+ pObj->GetObjRect().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ const SwFrm* pFrm( 0L );
+ if ( prPage->IsInvalidLayout() &&
+ 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
+ pFrm->Frm().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
+ 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
+ pFrm->Frm().Top() <= nBottom )
+ {
+ return sal_False;
+ }
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
+|*
+|*************************************************************************/
+// OD 15.11.2002 #105155# - introduce support for vertical layout
+sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
+{
+ OSL_ENSURE( !IsAgain(), "Ungueltige Seite beachten." );
+ if ( IsAgain() )
+ return sal_False;
+
+ sal_Bool bChanged = sal_False;
+ sal_Bool bAlreadyPainted = sal_False;
+ // OD 11.11.2002 #104414# - remember frame at complete paint
+ SwRect aFrmAtCompletePaint;
+
+ if ( !pLay->IsValid() || pLay->IsCompletePaint() )
+ {
+ if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
+ pLay->GetPrev()->SetCompletePaint();
+
+ SwRect aOldFrame( pLay->Frm() );
+ SwRect aOldRect( aOldFrame );
+ if( pLay->IsPageFrm() )
+ {
+ aOldRect = static_cast<SwPageFrm*>(pLay)->GetBoundRect();
+ }
+
+ pLay->Calc();
+ if ( aOldFrame != pLay->Frm() )
+ bChanged = sal_True;
+
+ sal_Bool bNoPaint = sal_False;
+ if ( pLay->IsPageBodyFrm() &&
+ pLay->Frm().Pos() == aOldRect.Pos() &&
+ pLay->Lower() )
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ //Einschraenkungen wegen Kopf-/Fusszeilen
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
+ bNoPaint = sal_True;
+ }
+
+ if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
+ {
+ SwRect aPaint( pLay->Frm() );
+ // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
+ // page frames -> enlarge paint rectangle correspondingly.
+ if ( pLay->IsPageFrm() )
+ {
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
+ aPaint = pPageFrm->GetBoundRect();
+ }
+
+ sal_Bool bPageInBrowseMode = pLay->IsPageFrm();
+ if( bPageInBrowseMode )
+ {
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
+ bPageInBrowseMode = sal_False;
+ }
+ if( bPageInBrowseMode )
+ {
+ // NOTE: no vertical layout in online layout
+ //Ist die Aenderung ueberhaupt sichtbar?
+ if ( pLay->IsCompletePaint() )
+ {
+ pImp->GetShell()->AddPaintRect( aPaint );
+ bAddRect = sal_False;
+ }
+ else
+ {
+ sal_uInt16 i;
+
+ SwRegionRects aRegion( aOldRect );
+ aRegion -= aPaint;
+ for ( i = 0; i < aRegion.Count(); ++i )
+ pImp->GetShell()->AddPaintRect( aRegion[i] );
+ aRegion.ChangeOrigin( aPaint );
+ aRegion.Remove( 0, aRegion.Count() );
+ aRegion.Insert( aPaint, 0 );
+ aRegion -= aOldRect;
+ for ( i = 0; i < aRegion.Count(); ++i )
+ pImp->GetShell()->AddPaintRect( aRegion[i] );
+ }
+
+ }
+ else
+ {
+ pImp->GetShell()->AddPaintRect( aPaint );
+ bAlreadyPainted = sal_True;
+ // OD 11.11.2002 #104414# - remember frame at complete paint
+ aFrmAtCompletePaint = pLay->Frm();
+ }
+
+ // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
+ // between pages (not only for in online mode).
+ if ( pLay->IsPageFrm() )
+ {
+ const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
+ const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
+ const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
+ const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
+ const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
+ SwRect aPageRect( pLay->Frm() );
+
+ if(pSh)
+ {
+ SwPageFrm::GetBorderAndShadowBoundRect(aPageRect, pSh,
+ aPageRect, pPageFrm->IsLeftShadowNeeded(), pPageFrm->IsRightShadowNeeded(),
+ pPageFrm->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ }
+
+ if ( bPrev )
+ {
+ // top
+ SwRect aSpaceToPrevPage( aPageRect );
+ aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
+ aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
+ if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
+
+ pSh->GetOut()->DrawRect( aSpaceToPrevPage.SVRect() );
+
+ // left
+ aSpaceToPrevPage = aPageRect;
+ aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
+ aSpaceToPrevPage.Right( pLay->Frm().Left() );
+ if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
+ }
+ if ( bNext )
+ {
+ // bottom
+ SwRect aSpaceToNextPage( aPageRect );
+ aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
+ aSpaceToNextPage.Top( pLay->Frm().Bottom() );
+ if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
+
+ // right
+ aSpaceToNextPage = aPageRect;
+ aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
+ aSpaceToNextPage.Left( pLay->Frm().Right() );
+ if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
+ pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
+ }
+ }
+ }
+ pLay->ResetCompletePaint();
+ }
+
+ if ( IsPaint() && bAddRect &&
+ !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
+ {
+ // OD 15.11.2002 #105155# - vertical layout support
+ SWRECTFN( pLay );
+ SwRect aRect( pLay->GetUpper()->PaintArea() );
+ (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pLay->ResetRetouche();
+ }
+
+ if( bAlreadyPainted )
+ bAddRect = sal_False;
+
+ CheckWaitCrsr();
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
+
+ if ( pLay->IsFtnFrm() ) //Hat keine LayFrms als Lower.
+ return bChanged;
+
+ SwFrm *pLow = pLay->Lower();
+ sal_Bool bTabChanged = sal_False;
+ while ( pLow && pLow->GetUpper() == pLay )
+ {
+ if ( pLow->IsLayoutFrm() )
+ {
+ if ( pLow->IsTabFrm() )
+ bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
+ // bereits zum Loeschen angemeldete Ueberspringen
+ else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ }
+ else if ( pImp->GetShell()->IsPaintLocked() )
+ //Abkuerzung im die Zyklen zu minimieren, bei Lock kommt das
+ //Paint sowieso (Primaer fuer Browse)
+ pLow->OptCalc();
+
+ if ( IsAgain() )
+ return sal_False;
+ pLow = pLow->GetNext();
+ }
+ // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
+ // area has been already added and after formating its lowers the frame area
+ // is enlarged.
+ SwRect aBoundRect(pLay->IsPageFrm() ? static_cast<SwPageFrm*>(pLay)->GetBoundRect() : pLay->Frm() );
+
+ if ( bAlreadyPainted &&
+ ( aBoundRect.Width() > aFrmAtCompletePaint.Width() ||
+ aBoundRect.Height() > aFrmAtCompletePaint.Height() )
+ )
+ {
+ pImp->GetShell()->AddPaintRect( aBoundRect );
+ }
+ return bChanged || bTabChanged;
+}
+
+sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
+{
+ OSL_ENSURE( !IsAgain(), "Ungueltige Seite beachten." );
+ if ( IsAgain() )
+ return sal_False;
+
+ sal_Bool bChanged = false;
+ sal_Bool bAddRect = true;
+
+ if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
+ {
+ //Der Frame hat sich veraendert, er wird jetzt Formatiert
+ const SwRect aOldRect( pFly->Frm() );
+ pFly->Calc();
+ bChanged = aOldRect != pFly->Frm();
+
+ if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
+ pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
+ pImp->GetShell()->AddPaintRect( pFly->Frm() );
+
+ if ( bChanged )
+ pFly->Invalidate();
+ else
+ pFly->Validate();
+/*
+ //mba: it's unclear why we should invalidate always, so I remove it
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
+ pImp->GetShell()->AddPaintRect( pFly->Frm() );
+
+ pFly->Invalidate();
+*/
+ bAddRect = false;
+ pFly->ResetCompletePaint();
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
+ sal_Bool bTabChanged = false;
+ SwFrm *pLow = pFly->Lower();
+ while ( pLow )
+ {
+ if ( pLow->IsLayoutFrm() )
+ {
+ if ( pLow->IsTabFrm() )
+ bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
+ else
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ }
+ pLow = pLow->GetNext();
+ }
+ return bChanged || bTabChanged;
+}
+
+// OD 31.10.2002 #104100#
+// Implement vertical layout support
+sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
+{
+ OSL_ENSURE( !IsAgain(), "8-) Ungueltige Seite beachten." );
+ if ( IsAgain() || !pTab->Lower() )
+ return sal_False;
+
+ IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
+ pTimerAccess->BlockIdling();
+
+ sal_Bool bChanged = sal_False;
+ sal_Bool bPainted = sal_False;
+
+ const SwPageFrm *pOldPage = pTab->FindPageFrm();
+
+ // OD 31.10.2002 #104100# - vertical layout support
+ // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
+ // <SwRectFn fnRect> for table frame <pTab>.
+ SWRECTFN( pTab );
+
+ if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
+ {
+ if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
+ {
+ pTab->GetPrev()->SetCompletePaint();
+ }
+
+ const SwRect aOldRect( pTab->Frm() );
+ pTab->SetLowersFormatted( sal_False );
+ pTab->Calc();
+ if ( aOldRect != pTab->Frm() )
+ {
+ bChanged = sal_True;
+ }
+ const SwRect aPaintFrm = pTab->PaintArea();
+
+ if ( IsPaint() && bAddRect )
+ {
+ // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
+ if ( !pTab->IsCompletePaint() &&
+ pTab->IsComplete() &&
+ ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
+ // OD 31.10.2002 #104100# - vertical layout support
+ (pTab->*fnRect->fnGetLeftMargin)() ) &&
+ pTab->Frm().HasArea()
+ )
+ {
+ // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
+ SwRect aMarginRect;
+
+ SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
+ if ( nLeftMargin > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
+ if ( nTopMargin > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+
+ if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
+ {
+ aMarginRect = pTab->Frm();
+ (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ pImp->GetShell()->AddPaintRect( aMarginRect );
+ }
+ }
+ else if ( pTab->IsCompletePaint() )
+ {
+ pImp->GetShell()->AddPaintRect( aPaintFrm );
+ bAddRect = sal_False;
+ bPainted = sal_True;
+ }
+
+ if ( pTab->IsRetouche() && !pTab->GetNext() )
+ {
+ SwRect aRect( pTab->GetUpper()->PaintArea() );
+ // OD 04.11.2002 #104100# - vertical layout support
+ (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pTab->ResetRetouche();
+ }
+ }
+ else
+ bAddRect = sal_False;
+
+ if ( pTab->IsCompletePaint() && !pOptTab )
+ pOptTab = pTab;
+ pTab->ResetCompletePaint();
+ }
+ if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
+ {
+ // OD 04.10.2002 #102779#
+ // set correct rectangle for retouche: area between bottom of table frame
+ // and bottom of paint area of the upper frame.
+ SwRect aRect( pTab->GetUpper()->PaintArea() );
+ // OD 04.11.2002 #104100# - vertical layout support
+ (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
+ if ( !pImp->GetShell()->AddPaintRect( aRect ) )
+ pTab->ResetRetouche();
+ }
+
+ CheckWaitCrsr();
+
+ pTimerAccess->UnblockIdling();
+
+ //Heftige Abkuerzung!
+ if ( pTab->IsLowersFormatted() &&
+ (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
+ return sal_False;
+
+ //Jetzt noch die Lowers versorgen
+ if ( IsAgain() )
+ return sal_False;
+
+ // OD 20.10.2003 #112464# - for savety reasons:
+ // check page number before formatting lowers.
+ if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
+ SetNextCycle( sal_True );
+
+ // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
+ if ( pTab->IsValid() )
+ {
+ SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
+ while ( pLow )
+ {
+ bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
+ if ( IsAgain() )
+ return sal_False;
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ }
+
+ return bChanged;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatCntnt()
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
+{
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ const ViewShell *pSh = pRoot->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ while ( pCntnt && pPage->IsAnLower( pCntnt ) )
+ {
+ //Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
+ //Abkuerzungen nutzen.
+ const sal_Bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
+ pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
+ if ( bFull )
+ {
+ //Damit wir nacher nicht suchen muessen.
+ const sal_Bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
+ const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
+ const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
+
+ const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
+ const SwTabFrm *pTab = pCntnt->FindTabFrm();
+ const sal_Bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
+ const sal_Bool bOldPaint = IsPaint();
+ bPaint = bOldPaint && !(pTab && pTab == pOptTab);
+ _FormatCntnt( pCntnt, pPage );
+ // --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
+ bPaint = bOldPaint;
+ // <--
+
+ // OD 2004-05-10 #i28701# - format floating screen object at content frame.
+ // No format, if action flag <bAgain> is set or action is interrupted.
+ // OD 2004-08-30 #117736# - allow format on interruption of action, if
+ // it's the format for this interrupt
+ // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
+ // to the object formatter.
+ if ( !IsAgain() &&
+ ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
+ pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
+ *(pCntnt->FindPageFrm()), this ) )
+ // <--
+ {
+ return sal_False;
+ }
+
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
+ //vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
+ //das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
+ //Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
+ //Absatz verarbeitet wurde.
+ if ( (!pTab || (pTab && !bInValid)) )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
+ ( !bBrowse && pPage->IsInvalidLayout() ) ||
+ // OD 07.05.2003 #109435# - consider interrupt formatting
+ ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
+ )
+ return sal_False;
+ }
+ if ( pOldUpper != pCntnt->GetUpper() )
+ {
+ const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
+ if ( nCurNum < pPage->GetPhyPageNum() )
+ nPreInvaPage = nCurNum;
+
+ //Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
+ //fangen wir nocheinmal von vorn an damit wir nichts auslassen.
+ if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
+ {
+ SetNextCycle( sal_True );
+ // OD 07.05.2003 #109435# - consider interrupt formatting
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ //Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
+ //den Vorgaenger nocheinmal durchlaufen.
+ //So werden einerseits Vorgaenger erwischt, die jetzt f?r Retouche
+ //verantwortlich sind, andererseits werden die Fusszeilen
+ //auch angefasst.
+ sal_Bool bSetCntnt = sal_True;
+ if ( pCntntPrev )
+ {
+ if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
+ pPage->InvalidateCntnt();
+ if ( pOldUpper != pCntnt->GetUpper() &&
+ pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
+ {
+ pCntnt = pCntntPrev;
+ bSetCntnt = sal_False;
+ }
+ }
+ if ( bSetCntnt )
+ {
+ if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
+ pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
+ {
+ const long nBottom = pImp->GetShell()->VisArea().Bottom();
+ const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
+ nBottom, pCntnt );
+ if ( !pTmp )
+ {
+ if ( (!(IS_FLYS && IS_INVAFLY) ||
+ !lcl_FindFirstInvaObj( pPage, nBottom )) &&
+ (!pPage->IsInvalidLayout() ||
+ !lcl_FindFirstInvaLay( pPage, nBottom )))
+ SetBrowseActionStop( sal_True );
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
+ }
+
+ RESCHEDULE;
+ }
+ else
+ {
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ //Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
+ if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
+ IsPaint() )
+ PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
+ if ( IsIdle() )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
+ return sal_False;
+ }
+ if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
+ pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
+ {
+ const long nBottom = pImp->GetShell()->VisArea().Bottom();
+ const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
+ nBottom, pCntnt );
+ if ( !pTmp )
+ {
+ if ( (!(IS_FLYS && IS_INVAFLY) ||
+ !lcl_FindFirstInvaObj( pPage, nBottom )) &&
+ (!pPage->IsInvalidLayout() ||
+ !lcl_FindFirstInvaLay( pPage, nBottom )))
+ SetBrowseActionStop( sal_True );
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( !mbFormatCntntOnInterrupt )
+ {
+ return sal_False;
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ CheckWaitCrsr();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ return !IsInterrupt() || mbFormatCntntOnInterrupt;
+}
+/*************************************************************************
+|*
+|* SwLayAction::_FormatCntnt()
+|*
+|* Beschreibung Returnt sal_True wenn der Absatz verarbeitet wurde,
+|* sal_False wenn es nichts zu verarbeiten gab.
+|*
+|*************************************************************************/
+void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
+ const SwPageFrm *pPage )
+{
+ //wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
+ const bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
+ !pCntnt->IsRetouche();
+ SWRECTFN( pCntnt )
+ if ( !bDrawObjsOnly && IsPaint() )
+ {
+ const SwRect aOldRect( pCntnt->UnionFrm() );
+ const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
+ pCntnt->OptCalc();
+ if( IsAgain() )
+ return;
+ if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
+ (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
+ {
+ pCntnt->SetRetouche();
+ }
+ PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
+ }
+ else
+ {
+ if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
+ PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
+ (pCntnt->Frm().*fnRect->fnGetBottom)() );
+ pCntnt->OptCalc();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::_FormatFlyCntnt()
+|*
+|* Beschreibung:
+|* - Returnt sal_True wenn alle Cntnts des Flys vollstaendig verarbeitet
+|* wurden. sal_False wenn vorzeitig unterbrochen wurde.
+|*
+|*************************************************************************/
+sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
+{
+ const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
+
+ while ( pCntnt )
+ {
+ // OD 2004-05-10 #i28701#
+ _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
+
+ // --> OD 2004-07-23 #i28701# - format floating screen objects
+ // at content text frame
+ // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
+ // to the object formatter.
+ if ( pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm(
+ *(const_cast<SwCntntFrm*>(pCntnt)),
+ *(pCntnt->FindPageFrm()), this ) )
+ // <--
+ {
+ // restart format with first content
+ pCntnt = pFly->ContainsCntnt();
+ continue;
+ }
+ // <--
+
+ if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
+ {
+ const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
+ ((SwTxtFrm*)pCntnt)->RecalcAllLines();
+ if ( IsPaintExtraData() && IsPaint() &&
+ nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
+ pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
+ }
+
+ if ( IsAgain() )
+ return sal_False;
+
+ //wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
+ if ( !pFly->IsFlyInCntFrm() )
+ {
+ CheckIdleEnd();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
+ return sal_False;
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ CheckWaitCrsr();
+ // OD 14.04.2003 #106346# - consider interrupt formatting.
+ return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
+}
+
+sal_Bool SwLayAction::IsStopPrt() const
+{
+ sal_Bool bResult = sal_False;
+
+ if (pImp != NULL && pProgress != NULL)
+ bResult = pImp->IsStopPrt();
+
+ return bResult;
+}
+
+/*************************************************************************
+|*
+|* SwLayAction::FormatSpelling(), _FormatSpelling()
+|*
+|*************************************************************************/
+sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
+{
+ OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
+ // robust against misuse by e.g. #i52542#
+ if( !pCnt->IsTxtFrm() )
+ return sal_False;
+
+ const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
+
+ bool bProcess = false;
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ bProcess = pTxtNode->IsWrongDirty(); break;
+ case AUTOCOMPLETE_WORDS :
+ bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
+ case WORD_COUNT :
+ bProcess = pTxtNode->IsWordCountDirty(); break;
+ case SMART_TAGS : // SMARTTAGS
+ bProcess = pTxtNode->IsSmartTagDirty(); break;
+ }
+
+ if( bProcess )
+ {
+ ViewShell *pSh = pImp->GetShell();
+ if( STRING_LEN == nTxtPos )
+ {
+ --nTxtPos;
+ if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
+ {
+ SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
+ if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
+ {
+ pCntntNode = pCrsr->GetCntntNode();
+ nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
+ }
+ }
+ }
+
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ {
+ SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
+ bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
+ if( !bPageValid )
+ bAllValid = sal_False;
+ if ( aRepaint.HasArea() )
+ pImp->GetShell()->InvalidateWindows( aRepaint );
+ if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
+ return sal_True;
+ break;
+ }
+ case AUTOCOMPLETE_WORDS :
+ ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
+ if ( Application::AnyInput( INPUT_ANY ) )
+ return sal_True;
+ break;
+ case WORD_COUNT :
+ {
+ const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
+ SwDocStat aStat;
+ pTxtNode->CountWords( aStat, 0, nEnd );
+ if ( Application::AnyInput( INPUT_ANY ) )
+ return sal_True;
+ break;
+ }
+ case SMART_TAGS : // SMARTTAGS
+ {
+ const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
+ bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
+ if( !bPageValid )
+ bAllValid = sal_False;
+ if ( aRepaint.HasArea() )
+ pImp->GetShell()->InvalidateWindows( aRepaint );
+ if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
+ return sal_True;
+ break;
+ }
+ }
+ }
+
+ //Die im Absatz verankerten Flys wollen auch mitspielen.
+ if ( pCnt->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pObj = rObjs[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ const SwCntntFrm *pC = pFly->ContainsCntnt();
+ while( pC )
+ {
+ if ( pC->IsTxtFrm() )
+ {
+ if ( _DoIdleJob( pC, eJob ) )
+ return sal_True;
+ }
+ pC = pC->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+ }
+ return sal_False;
+}
+
+sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
+{
+ //Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
+ //Seiten oder eben aller.
+ const ViewShell* pViewShell = pImp->GetShell();
+ const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
+ const SwDoc* pDoc = pViewShell->GetDoc();
+
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING :
+ if( !pViewOptions->IsOnlineSpell() )
+ return sal_False;
+ break;
+ case AUTOCOMPLETE_WORDS :
+ if( !pViewOptions->IsAutoCompleteWords() ||
+ pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
+ return sal_False;
+ break;
+ case WORD_COUNT :
+ if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
+ return sal_False;
+ break;
+ case SMART_TAGS :
+ if ( pDoc->GetDocShell()->IsHelpDocument() ||
+ pDoc->isXForms() ||
+ !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
+ return sal_False;
+ break;
+ default: OSL_FAIL( "Unknown idle job type" );
+ }
+
+ SwPageFrm *pPage;
+ if ( bVisAreaOnly )
+ pPage = pImp->GetFirstVisPage();
+ else
+ pPage = (SwPageFrm*)pRoot->Lower();
+
+ pCntntNode = NULL;
+ nTxtPos = STRING_LEN;
+
+ while ( pPage )
+ {
+ bPageValid = sal_True;
+ const SwCntntFrm *pCnt = pPage->ContainsCntnt();
+ while( pCnt && pPage->IsAnLower( pCnt ) )
+ {
+ if ( _DoIdleJob( pCnt, eJob ) )
+ return sal_True;
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ if ( pPage->GetSortedObjs() )
+ {
+ for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
+ i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
+ if ( pObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
+ const SwCntntFrm *pC = pFly->ContainsCntnt();
+ while( pC )
+ {
+ if ( pC->IsTxtFrm() )
+ {
+ if ( _DoIdleJob( pC, eJob ) )
+ return sal_True;
+ }
+ pC = pC->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+
+ if( bPageValid )
+ {
+ switch ( eJob )
+ {
+ case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
+ case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
+ case WORD_COUNT : pPage->ValidateWordCount(); break;
+ case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
+ }
+ }
+
+ pPage = (SwPageFrm*)pPage->GetNext();
+ if ( pPage && bVisAreaOnly &&
+ !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
+ break;
+ }
+ return sal_False;
+}
+
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+|*
+|* void SwLayIdle::SwLayIdle()
+|*
+|*************************************************************************/
+void SwLayIdle::ShowIdle( ColorData eColorData )
+{
+ if ( !bIndicator )
+ {
+ bIndicator = sal_True;
+ Window *pWin = pImp->GetShell()->GetWin();
+ if ( pWin )
+ {
+ Rectangle aRect( 0, 0, 5, 5 );
+ aRect = pWin->PixelToLogic( aRect );
+ // OD 2004-04-23 #116347#
+ pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pWin->SetFillColor( eColorData );
+ pWin->SetLineColor();
+ pWin->DrawRect( aRect );
+ pWin->Pop();
+ }
+ }
+}
+#define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
+#else
+#define SHOW_IDLE( ColorData )
+#endif
+
+/*************************************************************************
+|*
+|* void SwLayIdle::SwLayIdle()
+|*
+|*************************************************************************/
+SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
+ pRoot( pRt ),
+ pImp( pI )
+#if OSL_DEBUG_LEVEL > 1
+ , bIndicator( sal_False )
+#endif
+{
+ pImp->pIdleAct = this;
+
+ SHOW_IDLE( COL_LIGHTRED );
+
+ pImp->GetShell()->EnableSmooth( sal_False );
+
+ //Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
+ //zu tun war wird das IdleFormat angestossen.
+ if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
+ !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
+ !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
+ {
+ //Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
+ //Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
+ //Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
+ //Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
+ //wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
+ std::vector<bool> aBools;
+ ViewShell *pSh = pImp->GetShell();
+ do
+ { ++pSh->nStartAction;
+ sal_Bool bVis = sal_False;
+ if ( pSh->ISA(SwCrsrShell) )
+ {
+#ifdef SW_CRSR_TIMER
+ ((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( sal_False );
+#endif
+ bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
+ }
+ aBools.push_back( bVis );
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != pImp->GetShell() );
+
+ SwLayAction aAction( pRoot, pImp );
+ aAction.SetInputType( INPUT_ANY );
+ aAction.SetIdle( sal_True );
+ aAction.SetWaitAllowed( sal_False );
+ aAction.Action();
+
+ //Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
+ //sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
+ sal_Bool bActions = sal_False;
+ sal_uInt16 nBoolIdx = 0;
+ do
+ {
+ --pSh->nStartAction;
+
+ if ( pSh->Imp()->GetRegion() )
+ bActions = sal_True;
+ else
+ {
+ SwRect aTmp( pSh->VisArea() );
+ pSh->UISizeNotify();
+
+ // --> FME 2006-08-03 #137134#
+ // Are we supposed to crash if pSh isn't a cursor shell?!
+ // bActions |= aTmp != pSh->VisArea() ||
+ // aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
+
+ // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
+ // and the cursor is visible.
+ bActions |= aTmp != pSh->VisArea();
+ if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
+ {
+ bActions |= aBools[nBoolIdx] !=
+ static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
+ }
+ }
+
+ pSh = (ViewShell*)pSh->GetNext();
+ ++nBoolIdx;
+ } while ( pSh != pImp->GetShell() );
+
+ if ( bActions )
+ {
+ //Start- EndActions aufsetzen. ueber die CrsrShell, damit der
+ //Cursor/Selektion und die VisArea korrekt gesetzt werden.
+ nBoolIdx = 0;
+ do
+ {
+ sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
+
+ if ( bCrsrShell )
+ ((SwCrsrShell*)pSh)->SttCrsrMove();
+// else
+// pSh->StartAction();
+
+ //Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
+ //gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
+ //deren Loesung unverhaeltnissmaessig aufwendig waere.
+ //fix(18176):
+ SwViewImp *pViewImp = pSh->Imp();
+ sal_Bool bUnlock = sal_False;
+ if ( pViewImp->GetRegion() )
+ {
+ pViewImp->DelRegion();
+
+ //Fuer Repaint mit virtuellem Device sorgen.
+ pSh->LockPaint();
+ bUnlock = sal_True;
+ }
+
+ if ( bCrsrShell )
+ //Wenn der Crsr sichbar war wieder sichbar machen, sonst
+ //EndCrsrMove mit sal_True fuer IdleEnd.
+ ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
+// else
+// pSh->EndAction();
+ if( bUnlock )
+ {
+ if( bCrsrShell )
+ {
+ // UnlockPaint overwrite the selection from the
+ // CrsrShell and calls the virtual method paint
+ // to fill the virtual device. This fill dont have
+ // paint the selection! -> Set the focus flag at
+ // CrsrShell and it dont paint the selection.
+ ((SwCrsrShell*)pSh)->ShLooseFcs();
+ pSh->UnlockPaint( sal_True );
+ ((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
+ }
+ else
+ pSh->UnlockPaint( sal_True );
+ }
+
+ pSh = (ViewShell*)pSh->GetNext();
+ ++nBoolIdx;
+
+ } while ( pSh != pImp->GetShell() );
+ }
+
+ if ( !aAction.IsInterrupt() )
+ {
+ if ( !DoIdleJob( WORD_COUNT, sal_False ) )
+ if ( !DoIdleJob( SMART_TAGS, sal_False ) )
+ if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
+ DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
+ }
+
+ bool bInValid = false;
+ const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
+ const ViewShell* pViewShell = pImp->GetShell();
+ // See conditions in DoIdleJob()
+ const sal_Bool bSpell = rVOpt.IsOnlineSpell();
+ const sal_Bool bACmplWrd = rVOpt.IsAutoCompleteWords();
+ const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
+ const sal_Bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
+ !pViewShell->GetDoc()->isXForms() &&
+ SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
+
+ SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
+ do
+ {
+ bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
+ pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
+ pPg->IsInvalidFlyInCnt() ||
+ (bSpell && pPg->IsInvalidSpelling()) ||
+ (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
+ (bWordCount && pPg->IsInvalidWordCount()) ||
+ (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
+
+ pPg = (SwPageFrm*)pPg->GetNext();
+
+ } while ( pPg && !bInValid );
+
+ if ( !bInValid )
+ {
+ pRoot->ResetIdleFormat();
+ SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
+ pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
+ }
+ }
+
+ pImp->GetShell()->EnableSmooth( sal_True );
+
+ if( pImp->IsAccessible() )
+ pImp->FireAccessibleEvents();
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( bIndicator && pImp->GetShell()->GetWin() )
+ {
+ // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
+ // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
+ // purposes, it is not urgent.
+ bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
+ }
+#endif
+}
+
+SwLayIdle::~SwLayIdle()
+{
+ pImp->pIdleAct = 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/laycache.cxx b/sw/source/core/layout/laycache.cxx
new file mode 100644
index 000000000000..60ac1238c19c
--- /dev/null
+++ b/sw/source/core/layout/laycache.cxx
@@ -0,0 +1,1338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <editeng/brkitem.hxx>
+#include <tools/stream.hxx>
+#include <doc.hxx>
+#include <docstat.hxx>
+#include <docary.hxx>
+#include <fmtpdsc.hxx>
+#include <laycache.hxx>
+#include <layhelp.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <colfrm.hxx>
+#include <bodyfrm.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <pagedesc.hxx>
+#include <frmtool.hxx>
+#include <dflyobj.hxx>
+#include <dcontact.hxx>
+#include "viewopt.hxx"
+#include "viewsh.hxx"
+#include <flyfrm.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+// --> OD 2006-03-22 #b6375613#
+#include <pam.hxx>
+#include <docsh.hxx>
+#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <set>
+
+
+using namespace ::com::sun::star;
+// <--
+
+SV_IMPL_PTRARR( SwPageFlyCache, SwFlyCachePtr )
+
+/*-----------------28.5.2001 10:06------------------
+ * Reading and writing of the layout cache.
+ * The layout cache is not necessary, but it improves
+ * the performance and reduces the text flow during
+ * the formatting.
+ * The layout cache contains the index of the paragraphs/tables
+ * at the top of every page, so it's possible to create
+ * the right count of pages and to distribute the document content
+ * to this pages before the formatting starts.
+ *--------------------------------------------------*/
+
+void SwLayoutCache::Read( SvStream &rStream )
+{
+ if( !pImpl )
+ {
+ pImpl = new SwLayCacheImpl;
+ if( !pImpl->Read( rStream ) )
+ {
+ delete pImpl;
+ pImpl = 0;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, xub_StrLen nOffset )
+{
+ aType.Insert( nType, aType.Count() );
+ SvULongs::Insert( nIndex, SvULongs::Count() );
+ aOffset.push_back( nOffset );
+}
+
+sal_Bool SwLayCacheImpl::Read( SvStream& rStream )
+{
+ SwLayCacheIoImpl aIo( rStream, sal_False );
+ if( aIo.GetMajorVersion() > SW_LAYCACHE_IO_VERSION_MAJOR )
+ return sal_False;
+
+ // Due to an evil bug in the layout cache (#102759#), we cannot trust the
+ // sizes of fly frames which have been written using the "old" layout cache.
+ // This flag should indicate that we do not want to trust the width and
+ // height of fly frames
+ bUseFlyCache = aIo.GetMinorVersion() >= 1;
+
+ sal_uInt8 cFlags;
+ sal_uInt32 nIndex, nOffset;
+
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
+ aIo.OpenFlagRec();
+ aIo.CloseFlagRec();
+ while( aIo.BytesLeft() && !aIo.HasError() )
+ {
+ switch( aIo.Peek() )
+ {
+ case SW_LAYCACHE_IO_REC_PARA:
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
+ cFlags = aIo.OpenFlagRec();
+ aIo.GetStream() >> nIndex;
+ if( (cFlags & 0x01) != 0 )
+ aIo.GetStream() >> nOffset;
+ else
+ nOffset = STRING_LEN;
+ aIo.CloseFlagRec();
+ Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, (xub_StrLen)nOffset );
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
+ break;
+ case SW_LAYCACHE_IO_REC_TABLE:
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
+ aIo.OpenFlagRec();
+ aIo.GetStream() >> nIndex
+ >> nOffset;
+ Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, (xub_StrLen)nOffset );
+ aIo.CloseFlagRec();
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
+ break;
+ case SW_LAYCACHE_IO_REC_FLY:
+ {
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
+ aIo.OpenFlagRec();
+ aIo.CloseFlagRec();
+ long nX, nY, nW, nH;
+ sal_uInt16 nPgNum;
+ aIo.GetStream() >> nPgNum >> nIndex
+ >> nX >> nY >> nW >> nH;
+ SwFlyCache* pFly = new SwFlyCache( nPgNum, nIndex, nX, nY, nW, nH );
+ aFlyCache.Insert( pFly, aFlyCache.Count() );
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
+ break;
+ }
+ default:
+ aIo.SkipRec();
+ break;
+ }
+ }
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
+
+ return !aIo.HasError();
+}
+
+/*-----------------28.5.2001 10:19------------------
+ * SwLayoutCache::Write(..)
+ * writes the index (more precise: the difference between
+ * the index and the first index of the document content)
+ * of the first paragraph/table at the top of every page.
+ * If at the top of a page is the rest of a paragraph/table
+ * from the bottom of the previous page, the character/row
+ * number is stored, too.
+ * The position, size and page number of the text frames
+ * are stored, too
+ * --------------------------------------------------*/
+
+void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
+{
+ if( rDoc.GetCurrentLayout() ) // the layout itself .. //swmod 080218
+ {
+ SwLayCacheIoImpl aIo( rStream, sal_True );
+ // We want to save the relative index, so we need the index
+ // of the first content
+ sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
+ StartOfSectionNode()->GetIndex();
+ // The first page..
+ SwPageFrm* pPage = (SwPageFrm*)rDoc.GetCurrentLayout()->Lower(); //swmod 080218
+
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
+ aIo.OpenFlagRec( 0, 0 );
+ aIo.CloseFlagRec();
+ while( pPage )
+ {
+ if( pPage->GetPrev() )
+ {
+ SwLayoutFrm* pLay = pPage->FindBodyCont();
+ SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
+ // We are only interested in paragraph or table frames,
+ // a section frames contains paragraphs/tables.
+ if( pTmp && pTmp->IsSctFrm() )
+ pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
+
+ if( pTmp ) // any content
+ {
+ if( pTmp->IsTxtFrm() )
+ {
+ sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ /* Open Paragraph Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
+ sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
+ aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
+ bFollow ? 8 : 4 );
+ nNdIdx -= nStartOfContent;
+ aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx);
+ if( bFollow )
+ aIo.GetStream() << static_cast<sal_uInt32>(((SwTxtFrm*)pTmp)->GetOfst());
+ aIo.CloseFlagRec();
+ /* Close Paragraph Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
+ }
+ }
+ else if( pTmp->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)pTmp;
+ sal_uLong nOfst = STRING_LEN;
+ if( pTab->IsFollow() )
+ {
+ // If the table is a follow, we have to look for the
+ // master and to count all rows to get the row number
+ nOfst = 0;
+ if( pTab->IsFollow() )
+ pTab = pTab->FindMaster( true );
+ while( pTab != pTmp )
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ OSL_ENSURE( pTab, "Table follow without master" );
+ }
+ }
+ do
+ {
+ sal_uLong nNdIdx =
+ pTab->GetTable()->GetTableNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ /* Open Table Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
+ aIo.OpenFlagRec( 0, 8 );
+ nNdIdx -= nStartOfContent;
+ aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx)
+ << static_cast<sal_uInt32>(nOfst);
+ aIo.CloseFlagRec();
+ /* Close Table Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
+ }
+ // If the table has a follow on the next page,
+ // we know already the row number and store this
+ // immediately.
+ if( pTab->GetFollow() )
+ {
+ if( nOfst == STRING_LEN )
+ nOfst = 0;
+ do
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ SwPageFrm *pTabPage = pTab->FindPageFrm();
+ if( pTabPage != pPage )
+ {
+ OSL_ENSURE( pPage->GetPhyPageNum() <
+ pTabPage->GetPhyPageNum(),
+ "Looping Tableframes" );
+ pPage = pTabPage;
+ break;
+ }
+ } while ( pTab->GetFollow() );
+ }
+ else
+ break;
+ } while( pTab );
+ }
+ }
+ }
+ if( pPage->GetSortedObjs() )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( pFly->Frm().Left() != WEIT_WECH &&
+ !pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ const SwContact *pC =
+ ::GetUserCall(pAnchoredObj->GetDrawObj());
+ if( pC )
+ {
+ sal_uInt32 nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum();
+ sal_uInt16 nPageNum = pPage->GetPhyPageNum();
+ /* Open Fly Record */
+ aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
+ aIo.OpenFlagRec( 0, 0 );
+ aIo.CloseFlagRec();
+ SwRect &rRct = pFly->Frm();
+ sal_Int32 nX = rRct.Left() - pPage->Frm().Left();
+ sal_Int32 nY = rRct.Top() - pPage->Frm().Top();
+ aIo.GetStream() << nPageNum << nOrdNum
+ << nX << nY << rRct.Width()
+ << rRct.Height();
+ /* Close Fly Record */
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
+ }
+ }
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
+ }
+}
+
+#if OSL_DEBUG_LEVEL > 1
+sal_Bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
+{
+ if( !pImpl )
+ return sal_True;
+ const SwRootFrm *pRootFrm = rDoc.GetCurrentLayout();
+ sal_Bool bRet = sal_True;
+ if( pRootFrm )
+ {
+ sal_uInt16 nIndex = 0;
+ sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
+ StartOfSectionNode()->GetIndex();
+ SwPageFrm* pPage = (SwPageFrm*)pRootFrm->Lower();
+ if( pPage )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ while( pPage )
+ {
+ if( nIndex >= pImpl->Count() )
+ {
+ if( bRet )
+ bRet = sal_False;
+ break;
+ }
+ SwLayoutFrm* pLay = pPage->FindBodyCont();
+ SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
+ if( pTmp && pTmp->IsSctFrm() )
+ pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
+ if( pTmp )
+ {
+ if( pTmp->IsTxtFrm() )
+ {
+ sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
+ nNdIdx -= nStartOfContent;
+ if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
+ SW_LAYCACHE_IO_REC_PARA !=
+ pImpl->GetBreakType( nIndex ) ||
+ ( bFollow ? ((SwTxtFrm*)pTmp)->GetOfst()
+ : STRING_LEN ) != pImpl->GetBreakOfst( nIndex ) )
+ {
+ if( bRet )
+ bRet = sal_False;
+ }
+ ++nIndex;
+ }
+ }
+ else if( pTmp->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)pTmp;
+ sal_uLong nOfst = STRING_LEN;
+ if( pTab->IsFollow() )
+ {
+ nOfst = 0;
+ if( pTab->IsFollow() )
+ pTab = pTab->FindMaster( true );
+ while( pTab != pTmp )
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ }
+ }
+ do
+ {
+ sal_uLong nNdIdx =
+ pTab->GetTable()->GetTableNode()->GetIndex();
+ if( nNdIdx > nStartOfContent )
+ {
+ nNdIdx -= nStartOfContent;
+ if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
+ SW_LAYCACHE_IO_REC_TABLE !=
+ pImpl->GetBreakType( nIndex ) ||
+ nOfst != pImpl->GetBreakOfst( nIndex ) )
+ {
+ if( bRet )
+ bRet = sal_False;
+ }
+ ++nIndex;
+ }
+ if( pTab->GetFollow() )
+ {
+ if( nOfst == STRING_LEN )
+ nOfst = 0;
+ do
+ {
+ SwFrm* pSub = pTab->Lower();
+ while( pSub )
+ {
+ ++nOfst;
+ pSub = pSub->GetNext();
+ }
+ pTab = pTab->GetFollow();
+ SwPageFrm *pTabPage = pTab->FindPageFrm();
+ if( pTabPage != pPage )
+ {
+ pPage = pTabPage;
+ break;
+ }
+ } while ( pTab->GetFollow() );
+ }
+ else
+ break;
+ } while( pTab );
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+ }
+ return bRet;
+}
+#endif
+
+void SwLayoutCache::ClearImpl()
+{
+ if( !IsLocked() )
+ {
+ delete pImpl;
+ pImpl = 0;
+ }
+}
+
+
+SwLayoutCache::~SwLayoutCache()
+{
+ OSL_ENSURE( !nLockCount, "Deleting a locked SwLayoutCache!?" );
+ delete pImpl;
+}
+
+/*-----------------28.5.2001 10:47------------------
+ * SwActualSection,
+ * a help class to create not nested section frames
+ * for nested sections.
+ * --------------------------------------------------*/
+
+SwActualSection::SwActualSection( SwActualSection *pUp,
+ SwSectionFrm *pSect,
+ SwSectionNode *pNd ) :
+ pUpper( pUp ),
+ pSectFrm( pSect ),
+ pSectNode( pNd )
+{
+ if ( !pSectNode )
+ {
+ const SwNodeIndex *pIndex = pSect->GetFmt()->GetCntnt().GetCntntIdx();
+ pSectNode = pIndex->GetNode().FindSectionNode();
+ }
+}
+
+/*-----------------28.5.2001 11:09------------------
+ * SwLayHelper
+ * is the helper class, which utilizes the layout cache information
+ * to distribute the document content to the rigth pages.
+ * It's used by the _InsertCnt(..)-function.
+ * If there's no layout cache, the distibution to the pages is more
+ * a guess, but a guess with statistical background.
+ * --------------------------------------------------*/
+
+SwLayHelper::SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
+ SwLayoutFrm* &rpL, SwActualSection* &rpA, sal_Bool &rB,
+ sal_uLong nNodeIndex, sal_Bool bCache )
+ : rpFrm( rpF ), rpPrv( rpP ), rpPage( rpPg ), rpLay( rpL ),
+ rpActualSection( rpA ), rbBreakAfter(rB), pDoc(pD), nMaxParaPerPage( 25 ),
+ nParagraphCnt( bCache ? 0 : USHRT_MAX ), bFirst( bCache )
+{
+ pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pImpl )
+ {
+ nMaxParaPerPage = 1000;
+ nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()
+ ->GetIndex();
+ nNodeIndex -= nStartOfContent;
+ nIndex = 0;
+ nFlyIdx = 0;
+ while( nIndex < pImpl->Count() && (*pImpl)[ nIndex ] < nNodeIndex )
+ ++nIndex;
+ if( nIndex >= pImpl->Count() )
+ {
+ pDoc->GetLayoutCache()->UnlockImpl();
+ pImpl = NULL;
+ }
+ }
+ else
+ {
+ nIndex = USHRT_MAX;
+ nStartOfContent = ULONG_MAX;
+ }
+}
+
+SwLayHelper::~SwLayHelper()
+{
+ if( pImpl )
+ {
+ OSL_ENSURE( pDoc && pDoc->GetLayoutCache(), "Missing layoutcache" );
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+}
+
+/*-----------------23.5.2001 16:40------------------
+ * SwLayHelper::CalcPageCount() does not really calculate the page count,
+ * it returns the page count value from the layout cache, if available,
+ * otherwise it estimates the page count.
+ * --------------------------------------------------*/
+
+sal_uLong SwLayHelper::CalcPageCount()
+{
+ sal_uLong nPgCount;
+ SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
+ pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pCache )
+ {
+ nPgCount = pCache->Count() + 1;
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+ else
+ {
+ nPgCount = pDoc->GetDocStat().nPage;
+ if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
+ nPgCount = 0;
+ sal_uLong nNdCount = pDoc->GetDocStat().nPara;
+ if ( nNdCount <= 1 )
+ {
+ //Estimates the number of paragraphs.
+ sal_uLong nTmp = pDoc->GetNodes().GetEndOfContent().GetIndex() -
+ pDoc->GetNodes().GetEndOfExtras().GetIndex();
+ //Tables have a little overhead..
+ nTmp -= pDoc->GetTblFrmFmts()->Count() * 25;
+ //Fly frames, too ..
+ nTmp -= (pDoc->GetNodes().GetEndOfAutotext().GetIndex() -
+ pDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
+ if ( nTmp > 0 )
+ nNdCount = nTmp;
+ }
+ if ( nNdCount > 100 ) // no estimation below this value
+ {
+ if ( nPgCount > 0 )
+ nMaxParaPerPage = nNdCount / nPgCount;
+ else
+ {
+ nMaxParaPerPage = Max( sal_uLong(20),
+ sal_uLong(20 + nNdCount / 1000 * 3) );
+#ifdef PM2
+ const sal_uLong nMax = 49;
+#else
+ const sal_uLong nMax = 53;
+#endif
+ nMaxParaPerPage = Min( nMaxParaPerPage, nMax );
+ nPgCount = nNdCount / nMaxParaPerPage;
+ }
+ if ( nNdCount < 1000 )
+ nPgCount = 0;// no progress bar for small documents
+ ViewShell *pSh = 0;
+ if( rpLay && rpLay->getRootFrm() )
+ pSh = rpLay->getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nMaxParaPerPage *= 6;
+ }
+ }
+ return nPgCount;
+}
+
+/*-----------------23.5.2001 16:44------------------
+ * SwLayHelper::CheckInsertPage()
+ * inserts a page and return sal_True, if
+ * - the break after flag is set
+ * - the actual content wants a break before
+ * - the maximum count of paragraph/rows is reached
+ *
+ * The break after flag is set, if the actual content
+ * wants a break after.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckInsertPage()
+{
+ sal_Bool bEnd = 0 == rpPage->GetNext();
+ const SwAttrSet* pAttr = rpFrm->GetAttrSet();
+ const SvxFmtBreakItem& rBrk = pAttr->GetBreak();
+ const SwFmtPageDesc& rDesc = pAttr->GetPageDesc();
+ // --> FME 2004-10-26 #118195# Do not evaluate page description if frame
+ // is a follow frame!
+ const SwPageDesc* pDesc = rpFrm->IsFlowFrm() &&
+ SwFlowFrm::CastFlowFrm( rpFrm )->IsFollow() ?
+ 0 :
+ rDesc.GetPageDesc();
+ // <--
+
+ sal_Bool bBrk = nParagraphCnt > nMaxParaPerPage || rbBreakAfter;
+ rbBreakAfter = rBrk.GetBreak() == SVX_BREAK_PAGE_AFTER ||
+ rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
+ if ( !bBrk )
+ bBrk = rBrk.GetBreak() == SVX_BREAK_PAGE_BEFORE ||
+ rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
+
+ if ( bBrk || pDesc )
+ {
+ sal_uInt16 nPgNum = 0;
+ if ( !pDesc )
+ pDesc = rpPage->GetPageDesc()->GetFollow();
+ else
+ {
+ if ( 0 != (nPgNum = rDesc.GetNumOffset()) )
+ ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(sal_True);
+ }
+ sal_Bool bNextPageOdd = !rpPage->OnRightPage();
+ sal_Bool bInsertEmpty = sal_False;
+ if( nPgNum && bNextPageOdd != ( ( nPgNum % 2 ) != 0 ) )
+ {
+ bNextPageOdd = !bNextPageOdd;
+ bInsertEmpty = sal_True;
+ }
+ ::InsertNewPage( (SwPageDesc&)*pDesc, rpPage->GetUpper(),
+ bNextPageOdd, bInsertEmpty, sal_False, rpPage->GetNext() );
+ if ( bEnd )
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ do
+ { rpPage = (SwPageFrm*)rpPage->GetNext();
+ } while ( rpPage->GetNext() );
+ }
+ else
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ rpPage = (SwPageFrm*)rpPage->GetNext();
+ if ( rpPage->IsEmptyPage() )
+ {
+ OSL_ENSURE( rpPage->GetNext(), "Keine neue Seite?" );
+ rpPage = (SwPageFrm*)rpPage->GetNext();
+ }
+ }
+ rpLay = rpPage->FindBodyCont();
+ while( rpLay->Lower() )
+ rpLay = (SwLayoutFrm*)rpLay->Lower();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// --> OD 2006-03-22 #b6375613#
+bool lcl_HasTextFrmAnchoredObjs( SwTxtFrm* p_pTxtFrm )
+{
+ bool bHasTextFrmAnchoredObjs( false );
+
+ const SwSpzFrmFmts* pSpzFrmFmts = p_pTxtFrm->GetTxtNode()->GetDoc()->GetSpzFrmFmts();
+ for ( sal_uInt16 i = 0; i < pSpzFrmFmts->Count(); ++i )
+ {
+ SwFrmFmt *pFmt = (SwFrmFmt*)(*pSpzFrmFmts)[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetCntntAnchor() &&
+ ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
+ (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
+ rAnch.GetCntntAnchor()->nNode.GetIndex() ==
+ p_pTxtFrm->GetTxtNode()->GetIndex() )
+ {
+ bHasTextFrmAnchoredObjs = true;
+ break;
+ }
+ }
+
+ return bHasTextFrmAnchoredObjs;
+}
+
+void lcl_ApplyWorkaroundForB6375613( SwFrm* p_pFirstFrmOnNewPage )
+{
+ SwTxtFrm* pFirstTextFrmOnNewPage = dynamic_cast<SwTxtFrm*>(p_pFirstFrmOnNewPage);
+ //
+ if ( pFirstTextFrmOnNewPage &&
+ !pFirstTextFrmOnNewPage->IsFollow() &&
+ pFirstTextFrmOnNewPage->GetTxt().Len() == 0 &&
+ lcl_HasTextFrmAnchoredObjs( pFirstTextFrmOnNewPage ) )
+ {
+ // apply page break before at this text frame to assure, that it doesn't flow backward.
+ const SvxBreak eBreak =
+ pFirstTextFrmOnNewPage->GetAttrSet()->GetBreak().GetBreak();
+ if ( eBreak == SVX_BREAK_NONE )
+ {
+ pFirstTextFrmOnNewPage->GetTxtNode()->LockModify();
+ SwDoc* pDoc( pFirstTextFrmOnNewPage->GetTxtNode()->GetDoc() );
+ IDocumentContentOperations* pIDCO = pFirstTextFrmOnNewPage->GetTxtNode()->getIDocumentContentOperations();
+ const SwPaM aTmpPaM( *(pFirstTextFrmOnNewPage->GetTxtNode()) );
+ pIDCO->InsertPoolItem( aTmpPaM,
+ SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ), 0 );
+ pFirstTextFrmOnNewPage->GetTxtNode()->UnlockModify();
+
+ uno::Reference< document::XDocumentInfoSupplier > xDoc(
+ pDoc->GetDocShell()->GetBaseModel(),
+ uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > xDocInfo(
+ xDoc->getDocumentInfo(),
+ uno::UNO_QUERY );
+ try
+ {
+ xDocInfo->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WorkaroundForB6375613Applied")), uno::makeAny( true ) );
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ }
+}
+// <--
+
+/*-----------------28.5.2001 11:31------------------
+ * SwLayHelper::CheckInsert
+ * is the entry point for the _InsertCnt-function.
+ * The document content index is checked either it is
+ * in the layout cache either it's time to insert a page
+ * cause the maximal estimation of content per page is reached.
+ * A really big table or long paragraph may contains more than
+ * one page, in this case the needed count of pages will inserted.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
+{
+ sal_Bool bRet = sal_False;
+ sal_Bool bLongTab = sal_False;
+ sal_uLong nMaxRowPerPage( 0 );
+ nNodeIndex -= nStartOfContent;
+ sal_uInt16 nRows( 0 );
+ if( rpFrm->IsTabFrm() )
+ {
+ //Inside a table counts every row as a paragraph
+ SwFrm *pLow = ((SwTabFrm*)rpFrm)->Lower();
+ nRows = 0;
+ do
+ {
+ ++nRows;
+ pLow = pLow->GetNext();
+ } while ( pLow );
+ nParagraphCnt += nRows;
+ if( !pImpl && nParagraphCnt > nMaxParaPerPage + 10 )
+ {
+ // OD 09.04.2003 #108698# - improve heuristics:
+ // Assume that a table, which has more than three times the quantity
+ // of maximal paragraphs per page rows, consists of rows, which have
+ // the height of a normal paragraph. Thus, allow as much rows per page
+ // as much paragraphs are allowed.
+ if ( nRows > ( 3*nMaxParaPerPage ) )
+ {
+ nMaxRowPerPage = nMaxParaPerPage;
+ }
+ else
+ {
+ SwFrm *pTmp = ((SwTabFrm*)rpFrm)->Lower();
+ if( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ pTmp = ((SwRowFrm*)pTmp)->Lower();
+ sal_uInt16 nCnt = 0;
+ do
+ {
+ ++nCnt;
+ pTmp = pTmp->GetNext();
+ } while( pTmp );
+ nMaxRowPerPage = Max( sal_uLong(2), nMaxParaPerPage / nCnt );
+ }
+ bLongTab = sal_True;
+ }
+ }
+ else
+ ++nParagraphCnt;
+ if( bFirst && pImpl && nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex( nIndex ) == nNodeIndex &&
+ ( pImpl->GetBreakOfst( nIndex ) < STRING_LEN ||
+ ( ++nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) ) )
+ bFirst = sal_False;
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong nBreakIndex = ( pImpl && nIndex < pImpl->Count() ) ?
+ pImpl->GetBreakIndex(nIndex) : 0xffff;
+ (void)nBreakIndex;
+#endif
+ // OD 09.04.2003 #108698# - always split a big tables.
+ if ( !bFirst ||
+ ( rpFrm->IsTabFrm() && bLongTab )
+ )
+ {
+ sal_uLong nRowCount = 0;
+ do
+ {
+ if( pImpl || bLongTab )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_uLong nBrkIndex = ( pImpl && nIndex < pImpl->Count() ) ?
+ pImpl->GetBreakIndex(nIndex) : 0xffff;
+ (void)nBrkIndex;
+#endif
+ xub_StrLen nOfst = STRING_LEN;
+ sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
+ if( bLongTab )
+ {
+ rbBreakAfter = sal_True;
+ nOfst = static_cast<xub_StrLen>(nRowCount + nMaxRowPerPage);
+ }
+ else
+ {
+ while( nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex(nIndex) < nNodeIndex)
+ ++nIndex;
+ if( nIndex < pImpl->Count() &&
+ pImpl->GetBreakIndex(nIndex) == nNodeIndex )
+ {
+ nType = pImpl->GetBreakType( nIndex );
+ nOfst = pImpl->GetBreakOfst( nIndex++ );
+ rbBreakAfter = sal_True;
+ }
+ }
+
+ if( nOfst < STRING_LEN )
+ {
+ sal_Bool bSplit = sal_False;
+ sal_uInt16 nRepeat( 0 );
+ if( !bLongTab && rpFrm->IsTxtFrm() &&
+ SW_LAYCACHE_IO_REC_PARA == nType &&
+ nOfst<((SwTxtFrm*)rpFrm)->GetTxtNode()->GetTxt().Len() )
+ bSplit = sal_True;
+ else if( rpFrm->IsTabFrm() && nRowCount < nOfst &&
+ ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
+ {
+ nRepeat = ((SwTabFrm*)rpFrm)->
+ GetTable()->GetRowsToRepeat();
+ bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
+ bLongTab = bLongTab && bSplit;
+ }
+ if( bSplit )
+ {
+ rpFrm->InsertBehind( rpLay, rpPrv );
+ rpFrm->Frm().Pos() = rpLay->Frm().Pos();
+ rpFrm->Frm().Pos().Y() += 1;
+ rpPrv = rpFrm;
+ if( rpFrm->IsTabFrm() )
+ {
+ SwTabFrm* pTab = (SwTabFrm*)rpFrm;
+ // --> OD 2004-09-23 #i33629#, #i29955#
+ ::RegistFlys( pTab->FindPageFrm(), pTab );
+ // <--
+ SwFrm *pRow = pTab->Lower();
+ SwTabFrm *pFoll = new SwTabFrm( *pTab );
+
+ SwFrm *pPrv;
+ if( nRepeat > 0 )
+ {
+ bDontCreateObjects = sal_True; //frmtool
+
+ // Insert new headlines:
+ sal_uInt16 nRowIdx = 0;
+ SwRowFrm* pHeadline = 0;
+ while( nRowIdx < nRepeat )
+ {
+ OSL_ENSURE( pTab->GetTable()->GetTabLines()[ nRowIdx ], "Table ohne Zeilen?" );
+ pHeadline =
+ new SwRowFrm( *pTab->GetTable()->GetTabLines()[ nRowIdx ], pTab );
+ pHeadline->SetRepeatedHeadline( true );
+ pHeadline->InsertBefore( pFoll, 0 );
+ pHeadline->RegistFlys();
+
+ ++nRowIdx;
+ }
+
+ bDontCreateObjects = sal_False;
+ pPrv = pHeadline;
+ nRows = nRows + nRepeat;
+ }
+ else
+ pPrv = 0;
+ while( pRow && nRowCount < nOfst )
+ {
+ pRow = pRow->GetNext();
+ ++nRowCount;
+ }
+ while ( pRow )
+ {
+ SwFrm* pNxt = pRow->GetNext();
+ pRow->Remove();
+ pRow->InsertBehind( pFoll, pPrv );
+ pPrv = pRow;
+ pRow = pNxt;
+ }
+ rpFrm = pFoll;
+ }
+ else
+ {
+ SwTxtFrm *pNew = new SwTxtFrm( ((SwTxtFrm*)rpFrm)->
+ GetTxtNode(), rpFrm );
+ pNew->_SetIsFollow( sal_True );
+ pNew->ManipOfst( nOfst );
+ pNew->SetFollow( ((SwTxtFrm*)rpFrm)->GetFollow() );
+ ((SwTxtFrm*)rpFrm)->SetFollow( pNew );
+ rpFrm = pNew;
+ }
+ }
+ }
+ }
+
+ SwPageFrm* pLastPage = rpPage;
+ if( CheckInsertPage() )
+ {
+ // --> OD 2006-03-21 #b6375613#
+ if ( pDoc->ApplyWorkaroundForB6375613() )
+ {
+ lcl_ApplyWorkaroundForB6375613( rpFrm );
+ }
+ // <--
+ _CheckFlyCache( pLastPage );
+ if( rpPrv && rpPrv->IsTxtFrm() && !rpPrv->GetValidSizeFlag() )
+ rpPrv->Frm().Height( rpPrv->GetUpper()->Prt().Height() );
+
+ bRet = sal_True;
+ rpPrv = 0;
+ nParagraphCnt = 0;
+
+ if ( rpActualSection )
+ {
+ //Hatte der SectionFrm ueberhaupt Inhalt? Wenn
+ //nicht kann er gleich umgehaengt werden.
+ SwSectionFrm *pSct;
+ bool bInit = false;
+ if ( !rpActualSection->GetSectionFrm()->ContainsCntnt())
+ {
+ pSct = rpActualSection->GetSectionFrm();
+ pSct->Remove();
+ }
+ else
+ {
+ pSct = new SwSectionFrm(
+ *rpActualSection->GetSectionFrm(), sal_False );
+ rpActualSection->GetSectionFrm()->SimpleFormat();
+ bInit = true;
+ }
+ rpActualSection->SetSectionFrm( pSct );
+ pSct->InsertBehind( rpLay, 0 );
+ if( bInit )
+ pSct->Init();
+ pSct->Frm().Pos() = rpLay->Frm().Pos();
+ pSct->Frm().Pos().Y() += 1; //wg. Benachrichtigungen.
+
+ rpLay = pSct;
+ if ( rpLay->Lower() && rpLay->Lower()->IsLayoutFrm() )
+ rpLay = rpLay->GetNextLayoutLeaf();
+ }
+ }
+ } while( bLongTab || ( pImpl && nIndex < pImpl->Count() &&
+ (*pImpl)[ nIndex ] == nNodeIndex ) );
+ }
+ bFirst = sal_False;
+ return bRet;
+}
+
+struct SdrObjectCompare
+{
+ bool operator()( const SdrObject* pF1, const SdrObject* pF2 ) const
+ {
+ return pF1->GetOrdNum() < pF2->GetOrdNum();
+ }
+};
+
+struct FlyCacheCompare
+{
+ bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
+ {
+ return pC1->nOrdNum < pC2->nOrdNum;
+ }
+};
+
+ /*-----------------28.6.2001 14:40------------------
+ * SwLayHelper::_CheckFlyCache(..)
+ * If a new page is inserted, the last page is analysed.
+ * If there are text frames with default position, the fly cache
+ * is checked, if these frames are stored in the cache.
+ * --------------------------------------------------*/
+
+void SwLayHelper::_CheckFlyCache( SwPageFrm* pPage )
+{
+ if( !pImpl || !pPage )
+ return;
+ sal_uInt16 nFlyCount = pImpl->GetFlyCount();
+ // Any text frames at the page, fly cache avaiable?
+ if( pPage->GetSortedObjs() && nFlyIdx < nFlyCount )
+ {
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ sal_uInt16 nPgNum = pPage->GetPhyPageNum();
+
+ //
+ // NOTE: Here we do not use the absolute ordnums but
+ // relative ordnums for the objects on this page.
+
+ // skip fly frames from pages before the current page
+ SwFlyCache* pFlyC;
+ while( nFlyIdx < nFlyCount && ( pFlyC = pImpl->
+ GetFlyCache(nFlyIdx) )->nPageNum < nPgNum)
+ ++nFlyIdx;
+
+ // sort cached objects on this page by ordnum
+ std::set< const SwFlyCache*, FlyCacheCompare > aFlyCacheSet;
+ sal_uInt16 nIdx = nFlyIdx;
+
+ while( nIdx < nFlyCount && ( pFlyC = pImpl->
+ GetFlyCache( nIdx ) )->nPageNum == nPgNum )
+ {
+ aFlyCacheSet.insert( pFlyC );
+ ++nIdx;
+ }
+
+ // sort objects on this page by ordnum
+ std::set< const SdrObject*, SdrObjectCompare > aFlySet;
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) ) // a text frame?
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if( pFly->GetAnchorFrm() &&
+ !pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
+ if( pC )
+ {
+ aFlySet.insert( pAnchoredObj->GetDrawObj() );
+ }
+ }
+ }
+ }
+
+ if ( aFlyCacheSet.size() == aFlySet.size() )
+ {
+ std::set< const SwFlyCache*, FlyCacheCompare >::iterator aFlyCacheSetIt =
+ aFlyCacheSet.begin();
+ std::set< const SdrObject*, SdrObjectCompare >::iterator aFlySetIt =
+ aFlySet.begin();
+
+ while ( aFlyCacheSetIt != aFlyCacheSet.end() )
+ {
+ const SwFlyCache* pFlyCache = *aFlyCacheSetIt;
+ SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)*aFlySetIt)->GetFlyFrm();
+
+ if ( pFly->Frm().Left() == WEIT_WECH )
+ {
+ // we get the stored information
+ pFly->Frm().Pos().X() = pFlyCache->Left() +
+ pPage->Frm().Left();
+ pFly->Frm().Pos().Y() = pFlyCache->Top() +
+ pPage->Frm().Top();
+ if ( pImpl->IsUseFlyCache() )
+ {
+ pFly->Frm().Width( pFlyCache->Width() );
+ pFly->Frm().Height( pFlyCache->Height() );
+ }
+ }
+
+ ++aFlyCacheSetIt;
+ ++aFlySetIt;
+ }
+ }
+ }
+}
+
+/*-----------------28.6.2001 14:48------------------
+ * SwLayHelper::CheckPageFlyCache(..)
+ * looks for the given text frame in the fly cache and sets
+ * the position and size, if possible.
+ * The fly cache is sorted by pages and we start searching with the given page.
+ * If we found the page number in the fly cache, we set
+ * the rpPage parameter to the right page, if possible.
+ * --------------------------------------------------*/
+
+sal_Bool SwLayHelper::CheckPageFlyCache( SwPageFrm* &rpPage, SwFlyFrm* pFly )
+{
+ if( !pFly->GetAnchorFrm() || !pFly->GetVirtDrawObj() ||
+ pFly->GetAnchorFrm()->FindFooterOrHeader() )
+ return sal_False;
+ sal_Bool bRet = sal_False;
+ SwDoc* pDoc = rpPage->GetFmt()->GetDoc();
+ SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
+ pDoc->GetLayoutCache()->LockImpl() : NULL;
+ if( pCache )
+ {
+ sal_uInt16 nPgNum = rpPage->GetPhyPageNum();
+ sal_uInt16 nIdx = 0;
+ sal_uInt16 nCnt = pCache->GetFlyCount();
+ sal_uLong nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
+ SwFlyCache* pFlyC = 0;
+
+ // skip fly frames from pages before the current page
+ while( nIdx < nCnt &&
+ nPgNum > (pFlyC = pCache->GetFlyCache( nIdx ))->nPageNum )
+ ++nIdx;
+
+ while( nIdx < nCnt &&
+ nOrdNum != (pFlyC = pCache->GetFlyCache( nIdx ))->nOrdNum )
+ ++nIdx;
+ if( nIdx < nCnt )
+ {
+ SwPageFrm *pPage = rpPage;
+ while( pPage && pPage->GetPhyPageNum() < pFlyC->nPageNum )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ // --> OD 2005-02-22 #i43266# - if the found page is an empty page,
+ // take the previous one (take next one, if previous one doesn't exists)
+ if ( pPage && pPage->IsEmptyPage() )
+ {
+ pPage = static_cast<SwPageFrm*>( pPage->GetPrev()
+ ? pPage->GetPrev()
+ : pPage->GetNext() );
+ }
+ // <--
+ if( pPage )
+ {
+ rpPage = pPage;
+ pFly->Frm().Pos().X() = pFlyC->Left() + pPage->Frm().Left();
+ pFly->Frm().Pos().Y() = pFlyC->Top() + pPage->Frm().Top();
+ if ( pCache->IsUseFlyCache() )
+ {
+ pFly->Frm().Width( pFlyC->Width() );
+ pFly->Frm().Height( pFlyC->Height() );
+ }
+ bRet = sal_True;
+ }
+ }
+ pDoc->GetLayoutCache()->UnlockImpl();
+ }
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+SwLayCacheIoImpl::SwLayCacheIoImpl( SvStream& rStrm, sal_Bool bWrtMd ) :
+ pStream( &rStrm ),
+ nMajorVersion(SW_LAYCACHE_IO_VERSION_MAJOR),
+ nMinorVersion(SW_LAYCACHE_IO_VERSION_MINOR),
+ bWriteMode( bWrtMd ),
+ bError( sal_False )
+{
+ if( bWriteMode )
+ *pStream << nMajorVersion
+ << nMinorVersion;
+
+ else
+ *pStream >> nMajorVersion
+ >> nMinorVersion;
+}
+
+sal_Bool SwLayCacheIoImpl::OpenRec( sal_uInt8 cType )
+{
+ sal_Bool bRes = sal_True;
+ sal_uInt32 nPos = pStream->Tell();
+ if( bWriteMode )
+ {
+ aRecords.push_back( RecTypeSize(cType, nPos) );
+ *pStream << (sal_uInt32) 0;
+ }
+ else
+ {
+ sal_uInt32 nVal;
+ *pStream >> nVal;
+ sal_uInt8 cRecTyp = (sal_uInt8)nVal;
+ if( !nVal || cRecTyp != cType ||
+ pStream->GetErrorCode() != SVSTREAM_OK || pStream->IsEof() )
+ {
+ OSL_ENSURE( nVal, "OpenRec: Record-Header is 0" );
+ OSL_ENSURE( cRecTyp == cType, "OpenRec: Wrong Record Type" );
+ aRecords.push_back( RecTypeSize(0, pStream->Tell()) );
+ bRes = sal_False;
+ bError = sal_True;
+ }
+ else
+ {
+ sal_uInt32 nSize = nVal >> 8;
+ aRecords.push_back( RecTypeSize(cRecTyp, nPos+nSize) );
+ }
+ }
+ return bRes;
+}
+
+// Close record
+
+sal_Bool SwLayCacheIoImpl::CloseRec( sal_uInt8 )
+{
+ sal_Bool bRes = sal_True;
+ OSL_ENSURE( !aRecords.empty(), "CloseRec: no levels" );
+ if( !aRecords.empty() )
+ {
+ sal_uInt32 nPos = pStream->Tell();
+ if( bWriteMode )
+ {
+ sal_uInt32 nBgn = aRecords.back().size;
+ pStream->Seek( nBgn );
+ sal_uInt32 nSize = nPos - nBgn;
+ sal_uInt32 nVal = ( nSize << 8 ) | aRecords.back().type;
+ *pStream << nVal;
+ pStream->Seek( nPos );
+ if( pStream->GetError() != SVSTREAM_OK )
+ bRes = sal_False;
+ }
+ else
+ {
+ sal_uInt32 n = aRecords.back().size;
+ OSL_ENSURE( n >= nPos, "CloseRec: to much data read" );
+ if( n != nPos )
+ {
+ pStream->Seek( n );
+ if( n < nPos )
+ bRes = sal_False;
+ }
+ if( pStream->GetErrorCode() != SVSTREAM_OK )
+ bRes = sal_False;
+ }
+ aRecords.pop_back();
+ }
+
+ if( !bRes )
+ bError = sal_True;
+
+ return bRes;
+}
+
+sal_uInt32 SwLayCacheIoImpl::BytesLeft()
+{
+ sal_uInt32 n = 0;
+ if( !bError && !aRecords.empty() )
+ {
+ sal_uInt32 nEndPos = aRecords.back().size;
+ sal_uInt32 nPos = pStream->Tell();
+ if( nEndPos > nPos )
+ n = nEndPos - nPos;
+ }
+ return n;
+}
+
+sal_uInt8 SwLayCacheIoImpl::Peek()
+{
+ sal_uInt8 c = 0;
+ if( !bError )
+ {
+ sal_uInt32 nPos = pStream->Tell();
+ *pStream >> c;
+ pStream->Seek( nPos );
+ if( pStream->GetErrorCode() != SVSTREAM_OK )
+ {
+ c = 0;
+ bError = sal_True;
+ }
+ }
+ return c;
+}
+
+void SwLayCacheIoImpl::SkipRec()
+{
+ sal_uInt8 c = Peek();
+ OpenRec( c );
+ pStream->Seek( aRecords.back().size );
+ CloseRec( c );
+}
+
+sal_uInt8 SwLayCacheIoImpl::OpenFlagRec()
+{
+ OSL_ENSURE( !bWriteMode, "OpenFlagRec illegal in write mode" );
+ sal_uInt8 cFlags;
+ *pStream >> cFlags;
+ nFlagRecEnd = pStream->Tell() + ( cFlags & 0x0F );
+ return (cFlags >> 4);
+}
+
+void SwLayCacheIoImpl::OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen )
+{
+ OSL_ENSURE( bWriteMode, "OpenFlagRec illegal in read mode" );
+ OSL_ENSURE( (nFlags & 0xF0) == 0, "illegal flags set" );
+ OSL_ENSURE( nLen < 16, "wrong flag record length" );
+ sal_uInt8 cFlags = (nFlags << 4) + nLen;
+ *pStream << cFlags;
+ nFlagRecEnd = pStream->Tell() + nLen;
+}
+
+void SwLayCacheIoImpl::CloseFlagRec()
+{
+ if( bWriteMode )
+ {
+ OSL_ENSURE( pStream->Tell() == nFlagRecEnd, "Wrong amount of data written" );
+ }
+ else
+ {
+ OSL_ENSURE( pStream->Tell() <= nFlagRecEnd, "To many data read" );
+ if( pStream->Tell() != nFlagRecEnd )
+ pStream->Seek( nFlagRecEnd );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layhelp.hxx b/sw/source/core/layout/layhelp.hxx
new file mode 100644
index 000000000000..d690940320d7
--- /dev/null
+++ b/sw/source/core/layout/layhelp.hxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _LAYHELP_HXX
+#define _LAYHELP_HXX
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_USHORTS
+#define _SVSTDARR_ULONGS
+#define _SVSTDARR_XUB_STRLEN
+#include <svl/svstdarr.hxx>
+#endif
+#include <swrect.hxx>
+#include <vector>
+
+class SwDoc;
+class SwFrm;
+class SwLayoutFrm;
+class SwPageFrm;
+class SwFlyFrm;
+class SwSectionFrm;
+class SwSectionNode;
+class SvStream;
+
+/*************************************************************************
+ * class SwLayCacheImpl
+ * contains the page break information and the text frame positions
+ * of the document (after loading)
+ * and is used inside the constructor of the layout rootframe to
+ * insert content and text frames at the right pages.
+ * For every page of the main text (body content, no footnotes, text frames etc.)
+ * we have the nodeindex of the first content at the page,
+ * the type of content ( table or paragraph )
+ * and if it's not the first part of the table/paragraph,
+ * the row/character-offset inside the table/paragraph.
+ * The text frame positions are stored in the SwPageFlyCache array.
+ *************************************************************************/
+
+class SwFlyCache;
+typedef SwFlyCache* SwFlyCachePtr;
+SV_DECL_PTRARR_DEL( SwPageFlyCache, SwFlyCachePtr, 0, 4 )
+
+class SwLayCacheImpl : public SvULongs
+{
+ SvXub_StrLens aOffset;
+ SvUShorts aType;
+ SwPageFlyCache aFlyCache;
+ sal_Bool bUseFlyCache;
+ void Insert( sal_uInt16 nType, sal_uLong nIndex, xub_StrLen nOffset );
+
+public:
+ SwLayCacheImpl() : SvULongs( 20, 10 ), aType( 20, 10 ) {}
+ sal_Bool Read( SvStream& rStream );
+
+ sal_uLong GetBreakIndex( sal_uInt16 nIdx ) const { return GetObject( nIdx ); }
+ xub_StrLen GetBreakOfst( size_t nIdx ) const { return aOffset[ nIdx ]; }
+ sal_uInt16 GetBreakType( sal_uInt16 nIdx ) const { return aType[ nIdx ]; }
+
+ sal_uInt16 GetFlyCount() const { return aFlyCache.Count(); }
+ SwFlyCache *GetFlyCache( sal_uInt16 nIdx ) const { return aFlyCache[ nIdx ]; }
+
+ sal_Bool IsUseFlyCache() const { return bUseFlyCache; }
+};
+
+/*************************************************************************
+ * class SwActualSection
+ * helps to create the sectionframes during the _InsertCnt-function
+ * by controlling nested sections.
+ *************************************************************************/
+
+class SwActualSection
+{
+ SwActualSection *pUpper;
+ SwSectionFrm *pSectFrm;
+ SwSectionNode *pSectNode;
+public:
+ SwActualSection( SwActualSection *pUpper,
+ SwSectionFrm *pSect,
+ SwSectionNode *pNd );
+
+ SwSectionFrm *GetSectionFrm() { return pSectFrm; }
+ void SetSectionFrm( SwSectionFrm *p ) { pSectFrm = p; }
+ SwSectionNode *GetSectionNode() { return pSectNode;}
+ SwActualSection *GetUpper() { return pUpper; }
+};
+
+/*************************************************************************
+ * class SwLayHelper
+ * helps during the _InsertCnt-function to create new pages.
+ * If there's a layoutcache available, this information is used.
+ *************************************************************************/
+
+class SwLayHelper
+{
+ SwFrm* &rpFrm;
+ SwFrm* &rpPrv;
+ SwPageFrm* &rpPage;
+ SwLayoutFrm* &rpLay;
+ SwActualSection* &rpActualSection;
+ sal_Bool &rbBreakAfter;
+ SwDoc* pDoc;
+ SwLayCacheImpl* pImpl;
+ sal_uLong nMaxParaPerPage;
+ sal_uLong nParagraphCnt;
+ sal_uLong nStartOfContent;
+ sal_uInt16 nIndex; // the index in the page break array
+ sal_uInt16 nFlyIdx; // the index in the fly cache array
+ sal_Bool bFirst : 1;
+ void _CheckFlyCache( SwPageFrm* pPage );
+public:
+ SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
+ SwLayoutFrm* &rpL, SwActualSection* &rpA, sal_Bool &rBrk,
+ sal_uLong nNodeIndex, sal_Bool bCache );
+ ~SwLayHelper();
+ sal_uLong CalcPageCount();
+ sal_Bool CheckInsert( sal_uLong nNodeIndex );
+
+ sal_Bool BreakPage( xub_StrLen& rOffs, sal_uLong nNodeIndex );
+ sal_Bool CheckInsertPage();
+
+ // Look for fresh text frames at this (new) page and set them to the right
+ // position, if they are in the fly cache.
+ void CheckFlyCache( SwPageFrm* pPage )
+ { if( pImpl && nFlyIdx < pImpl->GetFlyCount() ) _CheckFlyCache( pPage ); }
+
+ // Look for this text frame and set it to the right position,
+ // if it's in the fly cache.
+ static sal_Bool CheckPageFlyCache( SwPageFrm* &rpPage, SwFlyFrm* pFly );
+};
+
+/*************************************************************************
+ * class SwLayCacheIoImpl
+ * contains the data structures that are required to read and write a
+ * layout cache.
+ *************************************************************************/
+
+#define SW_LAYCACHE_IO_REC_PAGES 'p'
+#define SW_LAYCACHE_IO_REC_PARA 'P'
+#define SW_LAYCACHE_IO_REC_TABLE 'T'
+#define SW_LAYCACHE_IO_REC_FLY 'F'
+
+#define SW_LAYCACHE_IO_VERSION_MAJOR 1
+#define SW_LAYCACHE_IO_VERSION_MINOR 1
+
+class SwLayCacheIoImpl
+{
+private:
+ struct RecTypeSize {
+ sal_uInt8 type;
+ sal_uLong size;
+ RecTypeSize(sal_uInt8 typ, sal_uLong siz) : type(typ), size(siz) {}
+ };
+ std::vector<RecTypeSize> aRecords;
+
+ SvStream *pStream;
+
+ sal_uLong nFlagRecEnd;
+
+ sal_uInt16 nMajorVersion;
+ sal_uInt16 nMinorVersion;
+
+ sal_Bool bWriteMode : 1;
+ sal_Bool bError : 1;
+
+public:
+ SwLayCacheIoImpl( SvStream& rStrm, sal_Bool bWrtMd );
+
+ // Get input or output stream
+ SvStream& GetStream() const { return *pStream; }
+
+ // Open a record of type "nType"
+ sal_Bool OpenRec( sal_uInt8 nType );
+
+ // Close a record of type "nType". This skips any unread data that
+ // remains in the record.
+ sal_Bool CloseRec( sal_uInt8 nType );
+
+ // Return the number of bytes contained in the current record that
+ // haven't been read by now.
+ sal_uInt32 BytesLeft();
+
+ // Return the current record's type
+ sal_uInt8 Peek();
+
+ // Skip the current record
+ void SkipRec();
+
+ // Open a flag record for reading. The uppermost four bits are flags,
+ // while the lowermost are the flag record's size. Flag records cannot
+ // be nested.
+ sal_uInt8 OpenFlagRec();
+
+ // Open flag record for writing;
+ void OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen );
+
+ // Close a flag record. Any bytes left are skipped.
+ void CloseFlagRec();
+
+ sal_Bool HasError() const { return bError; }
+
+ sal_uInt16 GetMajorVersion() const { return nMajorVersion; }
+ sal_uInt16 GetMinorVersion() const { return nMinorVersion; }
+};
+
+// Stored information about text frames:
+class SwFlyCache : public SwRect // position and size
+{
+public:
+ sal_uLong nOrdNum; // Id to recognize text frames
+ sal_uInt16 nPageNum; // page number
+ SwFlyCache( sal_uInt16 nP, sal_uLong nO, long nXL, long nYL, long nWL, long nHL ) :
+ SwRect( nXL, nYL, nWL, nHL ), nOrdNum( nO ), nPageNum( nP ){}
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/layouter.cxx b/sw/source/core/layout/layouter.cxx
new file mode 100644
index 000000000000..a02b17401c01
--- /dev/null
+++ b/sw/source/core/layout/layouter.cxx
@@ -0,0 +1,565 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "layouter.hxx"
+#include "doc.hxx"
+#include "sectfrm.hxx"
+#include "ftnboss.hxx"
+#include "cntfrm.hxx"
+#include "pagefrm.hxx"
+#include "ftnfrm.hxx"
+#include "txtfrm.hxx"
+
+// --> OD 2004-06-23 #i28701#
+#include <movedfwdfrmsbyobjpos.hxx>
+// <--
+// --> OD 2004-10-22 #i35911#
+#include <objstmpconsiderwrapinfl.hxx>
+// <--
+
+#define LOOP_DETECT 250
+
+class SwLooping
+{
+ sal_uInt16 nMinPage;
+ sal_uInt16 nMaxPage;
+ sal_uInt16 nCount;
+ sal_uInt16 mnLoopControlStage;
+public:
+ SwLooping( SwPageFrm* pPage );
+ void Control( SwPageFrm* pPage );
+ void Drastic( SwFrm* pFrm );
+ bool IsLoopingLouieLight() const { return nCount > LOOP_DETECT - 30; };
+};
+
+class SwEndnoter
+{
+ SwLayouter* pMaster;
+ SwSectionFrm* pSect;
+ SvPtrarr* pEndArr;
+public:
+ SwEndnoter( SwLayouter* pLay )
+ : pMaster( pLay ), pSect( NULL ), pEndArr( NULL ) {}
+ ~SwEndnoter() { delete pEndArr; }
+ void CollectEndnotes( SwSectionFrm* pSct );
+ void CollectEndnote( SwFtnFrm* pFtn );
+ const SwSectionFrm* GetSect() const { return pSect; }
+ void InsertEndnotes();
+ sal_Bool HasEndnotes() const { return pEndArr && pEndArr->Count(); }
+};
+
+void SwEndnoter::CollectEndnotes( SwSectionFrm* pSct )
+{
+ OSL_ENSURE( pSct, "CollectEndnotes: Which section?" );
+ if( !pSect )
+ pSect = pSct;
+ else if( pSct != pSect )
+ return;
+ pSect->CollectEndnotes( pMaster );
+}
+
+void SwEndnoter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ if( pEndArr && USHRT_MAX != pEndArr->GetPos( (VoidPtr)pFtn ) )
+ return;
+
+ if( pFtn->GetUpper() )
+ {
+ // pFtn is the master, he incorporates its follows
+ SwFtnFrm *pNxt = pFtn->GetFollow();
+ while ( pNxt )
+ {
+ SwFrm *pCnt = pNxt->ContainsAny();
+ if ( pCnt )
+ {
+ do
+ { SwFrm *pNxtCnt = pCnt->GetNext();
+ pCnt->Cut();
+ pCnt->Paste( pFtn );
+ pCnt = pNxtCnt;
+ } while ( pCnt );
+ }
+ else
+ { OSL_ENSURE( pNxt->Lower() && pNxt->Lower()->IsSctFrm(),
+ "Endnote without content?" );
+ pNxt->Cut();
+ delete pNxt;
+ }
+ pNxt = pFtn->GetFollow();
+ }
+ if( pFtn->GetMaster() )
+ return;
+ pFtn->Cut();
+ }
+ else if( pEndArr )
+ {
+ for ( sal_uInt16 i = 0; i < pEndArr->Count(); ++i )
+ {
+ SwFtnFrm *pEndFtn = (SwFtnFrm*)((*pEndArr)[i]);
+ if( pEndFtn->GetAttr() == pFtn->GetAttr() )
+ {
+ delete pFtn;
+ return;
+ }
+ }
+ }
+ if( !pEndArr )
+ pEndArr = new SvPtrarr( 5, 5 ); // deleted from the SwLayouter
+ pEndArr->Insert( (VoidPtr)pFtn, pEndArr->Count() );
+}
+
+void SwEndnoter::InsertEndnotes()
+{
+ if( !pSect )
+ return;
+ if( !pEndArr || !pEndArr->Count() )
+ {
+ pSect = NULL;
+ return;
+ }
+ OSL_ENSURE( pSect->Lower() && pSect->Lower()->IsFtnBossFrm(),
+ "InsertEndnotes: Where's my column?" );
+ SwFrm* pRef = pSect->FindLastCntnt( FINDMODE_MYLAST );
+ SwFtnBossFrm *pBoss = pRef ? pRef->FindFtnBossFrm()
+ : (SwFtnBossFrm*)pSect->Lower();
+ pBoss->_MoveFtns( *pEndArr );
+ delete pEndArr;
+ pEndArr = NULL;
+ pSect = NULL;
+}
+
+SwLooping::SwLooping( SwPageFrm* pPage )
+{
+ OSL_ENSURE( pPage, "Where's my page?" );
+ nMinPage = pPage->GetPhyPageNum();
+ nMaxPage = nMinPage;
+ nCount = 0;
+ mnLoopControlStage = 0;
+}
+
+void SwLooping::Drastic( SwFrm* pFrm )
+{
+ while( pFrm )
+ {
+ pFrm->ValidateThisAndAllLowers( mnLoopControlStage );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+void SwLooping::Control( SwPageFrm* pPage )
+{
+ if( !pPage )
+ return;
+ sal_uInt16 nNew = pPage->GetPhyPageNum();
+ if( nNew > nMaxPage )
+ nMaxPage = nNew;
+ if( nNew < nMinPage )
+ {
+ nMinPage = nNew;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( nNew > nMinPage + 2 )
+ {
+ nMinPage = nNew - 2;
+ nMaxPage = nNew;
+ nCount = 0;
+ mnLoopControlStage = 0;
+ }
+ else if( ++nCount > LOOP_DETECT )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ static sal_Bool bNoLouie = sal_False;
+ if( bNoLouie )
+ return;
+
+ // FME 2007-08-30 #i81146# new loop control
+ OSL_ENSURE( 0 != mnLoopControlStage, "Looping Louie: Stage 1!" );
+ OSL_ENSURE( 1 != mnLoopControlStage, "Looping Louie: Stage 2!!" );
+ OSL_ENSURE( 2 > mnLoopControlStage, "Looping Louie: Stage 3!!!" );
+#endif
+
+ Drastic( pPage->Lower() );
+ if( nNew > nMinPage && pPage->GetPrev() )
+ Drastic( ((SwPageFrm*)pPage->GetPrev())->Lower() );
+ if( nNew < nMaxPage && pPage->GetNext() )
+ Drastic( ((SwPageFrm*)pPage->GetNext())->Lower() );
+
+ ++mnLoopControlStage;
+ nCount = 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayouter::SwLayouter()
+|*
+|*************************************************************************/
+
+SwLayouter::SwLayouter()
+ : pEndnoter( NULL ),
+ pLooping( NULL ),
+ // --> OD 2004-06-23 #i28701#
+ mpMovedFwdFrms( 0L ),
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ mpObjsTmpConsiderWrapInfl( 0L )
+ // <--
+{
+}
+
+SwLayouter::~SwLayouter()
+{
+ delete pEndnoter;
+ delete pLooping;
+ // --> OD 2004-06-23 #i28701#
+ delete mpMovedFwdFrms;
+ mpMovedFwdFrms = 0L;
+ // <--
+ // --> OD 2004-10-22 #i35911#
+ delete mpObjsTmpConsiderWrapInfl;
+ mpObjsTmpConsiderWrapInfl = 0L;
+ // <--
+}
+
+void SwLayouter::_CollectEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter )
+ pEndnoter = new SwEndnoter( this );
+ pEndnoter->CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::HasEndnotes() const
+{
+ return pEndnoter->HasEndnotes();
+}
+
+void SwLayouter::CollectEndnote( SwFtnFrm* pFtn )
+{
+ pEndnoter->CollectEndnote( pFtn );
+}
+
+void SwLayouter::InsertEndnotes( SwSectionFrm* pSect )
+{
+ if( !pEndnoter || pEndnoter->GetSect() != pSect )
+ return;
+ pEndnoter->InsertEndnotes();
+}
+
+void SwLayouter::LoopControl( SwPageFrm* pPage, sal_uInt8 )
+{
+ OSL_ENSURE( pLooping, "Looping: Lost control" );
+ pLooping->Control( pPage );
+}
+
+void SwLayouter::LoopingLouieLight( const SwDoc& rDoc, const SwTxtFrm& rFrm )
+{
+ if ( pLooping && pLooping->IsLoopingLouieLight() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "Looping Louie (Light): Fixating fractious frame" );
+#endif
+ SwLayouter::InsertMovedFwdFrm( rDoc, rFrm, rFrm.FindPageFrm()->GetPhyPageNum() );
+ }
+}
+
+sal_Bool SwLayouter::StartLooping( SwPageFrm* pPage )
+{
+ if( pLooping )
+ return sal_False;
+ pLooping = new SwLooping( pPage );
+ return sal_True;
+}
+
+void SwLayouter::EndLoopControl()
+{
+ delete pLooping;
+ pLooping = NULL;
+}
+
+void SwLayouter::CollectEndnotes( SwDoc* pDoc, SwSectionFrm* pSect )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ pDoc->GetLayouter()->_CollectEndnotes( pSect );
+}
+
+sal_Bool SwLayouter::Collecting( SwDoc* pDoc, SwSectionFrm* pSect, SwFtnFrm* pFtn )
+{
+ if( !pDoc->GetLayouter() )
+ return sal_False;
+ SwLayouter *pLayouter = pDoc->GetLayouter();
+ if( pLayouter->pEndnoter && pLayouter->pEndnoter->GetSect() && pSect &&
+ ( pLayouter->pEndnoter->GetSect()->IsAnFollow( pSect ) ||
+ pSect->IsAnFollow( pLayouter->pEndnoter->GetSect() ) ) )
+ {
+ if( pFtn )
+ pLayouter->CollectEndnote( pFtn );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwLayouter::StartLoopControl( SwDoc* pDoc, SwPageFrm *pPage )
+{
+ OSL_ENSURE( pDoc, "No doc, no fun" );
+ if( !pDoc->GetLayouter() )
+ pDoc->SetLayouter( new SwLayouter() );
+ return !pDoc->GetLayouter()->pLooping &&
+ pDoc->GetLayouter()->StartLooping( pPage );
+}
+
+// --> OD 2004-06-23 #i28701#
+// -----------------------------------------------------------------------------
+// methods to manage text frames, which are moved forward by the positioning
+// of its anchored objects
+// -----------------------------------------------------------------------------
+void SwLayouter::ClearMovedFwdFrms( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Clear();
+ }
+}
+
+void SwLayouter::InsertMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpMovedFwdFrms =
+ new SwMovedFwdFrmsByObjPos();
+ }
+
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Insert( _rMovedFwdFrmByObjPos,
+ _nToPageNum );
+}
+
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::RemoveMovedFwdFrm( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm )
+{
+ sal_uInt32 nDummy;
+ if ( SwLayouter::FrmMovedFwdByObjPos( _rDoc, _rTxtFrm, nDummy ) )
+ {
+ _rDoc.GetLayouter()->mpMovedFwdFrms->Remove( _rTxtFrm );
+ }
+}
+// <--
+
+bool SwLayouter::FrmMovedFwdByObjPos( const SwDoc& _rDoc,
+ const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ _ornToPageNum = 0;
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->mpMovedFwdFrms->
+ FrmMovedFwdByObjPos( _rTxtFrm, _ornToPageNum );
+ }
+}
+// <--
+// --> OD 2004-10-05 #i26945#
+bool SwLayouter::DoesRowContainMovedFwdFrm( const SwDoc& _rDoc,
+ const SwRowFrm& _rRowFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ return false;
+ }
+ else if ( !_rDoc.GetLayouter()->mpMovedFwdFrms )
+ {
+ return false;
+ }
+ else
+ {
+ return _rDoc.GetLayouter()->
+ mpMovedFwdFrms->DoesRowContainMovedFwdFrm( _rRowFrm );
+ }
+}
+// <--
+
+// --> OD 2004-10-22 #i35911#
+void SwLayouter::ClearObjsTmpConsiderWrapInfluence( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() &&
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Clear();
+ }
+}
+void SwLayouter::InsertObjForTmpConsiderWrapInfluence(
+ const SwDoc& _rDoc,
+ SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !_rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->mpObjsTmpConsiderWrapInfl =
+ new SwObjsMarkedAsTmpConsiderWrapInfluence();
+ }
+
+ _rDoc.GetLayouter()->mpObjsTmpConsiderWrapInfl->Insert( _rAnchoredObj );
+}
+// <--
+// --> OD 2005-01-12 #i40155#
+void SwLayouter::ClearFrmsNotToWrap( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.clear();
+ }
+}
+
+void SwLayouter::InsertFrmNotToWrap( const SwDoc& _rDoc,
+ const SwFrm& _rFrm )
+{
+ if ( !_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ if ( !SwLayouter::FrmNotToWrap( _rDoc, _rFrm ) )
+ {
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maFrmsNotToWrap.push_back( &_rFrm );
+ }
+}
+
+bool SwLayouter::FrmNotToWrap( const IDocumentLayoutAccess& _rDLA,
+ const SwFrm& _rFrm )
+{
+ const SwLayouter* pLayouter = _rDLA.GetLayouter();
+ if ( !pLayouter )
+ {
+ return false;
+ }
+ else
+ {
+ bool bFrmNotToWrap( false );
+ std::vector< const SwFrm* >::const_iterator aIter =
+ pLayouter->maFrmsNotToWrap.begin();
+ for ( ; aIter != pLayouter->maFrmsNotToWrap.end(); ++aIter )
+ {
+ const SwFrm* pFrm = *(aIter);
+ if ( pFrm == &_rFrm )
+ {
+ bFrmNotToWrap = true;
+ break;
+ }
+ }
+ return bFrmNotToWrap;
+ }
+}
+// <--
+
+void LOOPING_LOUIE_LIGHT( bool bCondition, const SwTxtFrm& rTxtFrm )
+{
+ if ( bCondition )
+ {
+ const SwDoc& rDoc = *rTxtFrm.GetAttrSet()->GetDoc();
+ if ( rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(rDoc).GetLayouter()->LoopingLouieLight( rDoc, rTxtFrm );
+ }
+ }
+}
+
+// --> OD 2006-05-10 #i65250#
+bool SwLayouter::MoveBwdSuppressed( const SwDoc& p_rDoc,
+ const SwFlowFrm& p_rFlowFrm,
+ const SwLayoutFrm& p_rNewUpperFrm )
+{
+ bool bMoveBwdSuppressed( false );
+
+ if ( !p_rDoc.GetLayouter() )
+ {
+ const_cast<SwDoc&>(p_rDoc).SetLayouter( new SwLayouter() );
+ }
+
+ // create hash map key
+ tMoveBwdLayoutInfoKey aMoveBwdLayoutInfo;
+ aMoveBwdLayoutInfo.mnFrmId = p_rFlowFrm.GetFrm()->GetFrmId();
+ aMoveBwdLayoutInfo.mnNewUpperPosX = p_rNewUpperFrm.Frm().Pos().X();
+ aMoveBwdLayoutInfo.mnNewUpperPosY = p_rNewUpperFrm.Frm().Pos().Y();
+ aMoveBwdLayoutInfo.mnNewUpperWidth = p_rNewUpperFrm.Frm().Width();
+ aMoveBwdLayoutInfo.mnNewUpperHeight = p_rNewUpperFrm.Frm().Height();
+ SWRECTFN( (&p_rNewUpperFrm) )
+ const SwFrm* pLastLower( p_rNewUpperFrm.Lower() );
+ while ( pLastLower && pLastLower->GetNext() )
+ {
+ pLastLower = pLastLower->GetNext();
+ }
+ aMoveBwdLayoutInfo.mnFreeSpaceInNewUpper =
+ pLastLower
+ ? (pLastLower->Frm().*fnRect->fnBottomDist)( (p_rNewUpperFrm.*fnRect->fnGetPrtBottom)() )
+ : (p_rNewUpperFrm.Frm().*fnRect->fnGetHeight)();
+
+ // check for moving backward suppress threshold
+ const sal_uInt16 cMoveBwdCountSuppressThreshold = 20;
+ if ( ++const_cast<SwDoc&>(p_rDoc).GetLayouter()->maMoveBwdLayoutInfo[ aMoveBwdLayoutInfo ] >
+ cMoveBwdCountSuppressThreshold )
+ {
+ bMoveBwdSuppressed = true;
+ }
+
+ return bMoveBwdSuppressed;
+}
+
+void SwLayouter::ClearMoveBwdLayoutInfo( const SwDoc& _rDoc )
+{
+ if ( _rDoc.GetLayouter() )
+ const_cast<SwDoc&>(_rDoc).GetLayouter()->maMoveBwdLayoutInfo.clear();
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx b/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx
new file mode 100644
index 000000000000..7ce3bf320579
--- /dev/null
+++ b/sw/source/core/layout/movedfwdfrmsbyobjpos.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <movedfwdfrmsbyobjpos.hxx>
+#include <txtfrm.hxx>
+#include <rowfrm.hxx>
+#include <pagefrm.hxx>
+#include <ndtxt.hxx>
+#include <switerator.hxx>
+
+SwMovedFwdFrmsByObjPos::SwMovedFwdFrmsByObjPos()
+{
+}
+
+SwMovedFwdFrmsByObjPos::~SwMovedFwdFrmsByObjPos()
+{
+ Clear();
+}
+
+void SwMovedFwdFrmsByObjPos::Insert( const SwTxtFrm& _rMovedFwdFrmByObjPos,
+ const sal_uInt32 _nToPageNum )
+{
+ if ( maMovedFwdFrms.end() ==
+ maMovedFwdFrms.find( _rMovedFwdFrmByObjPos.GetTxtNode() ) )
+ {
+ const NodeMapEntry aEntry( _rMovedFwdFrmByObjPos.GetTxtNode(), _nToPageNum );
+ maMovedFwdFrms.insert( aEntry );
+ }
+}
+
+void SwMovedFwdFrmsByObjPos::Remove( const SwTxtFrm& _rTxtFrm )
+{
+ maMovedFwdFrms.erase( _rTxtFrm.GetTxtNode() );
+};
+
+bool SwMovedFwdFrmsByObjPos::FrmMovedFwdByObjPos( const SwTxtFrm& _rTxtFrm,
+ sal_uInt32& _ornToPageNum ) const
+{
+ NodeMapIter aIter = maMovedFwdFrms.find( _rTxtFrm.GetTxtNode() );
+ if ( maMovedFwdFrms.end() != aIter )
+ {
+ _ornToPageNum = (*aIter).second;
+ return true;
+ }
+
+ return false;
+}
+
+// --> OD 2004-10-05 #i26945#
+bool SwMovedFwdFrmsByObjPos::DoesRowContainMovedFwdFrm( const SwRowFrm& _rRowFrm ) const
+{
+ bool bDoesRowContainMovedFwdFrm( false );
+
+ const sal_uInt32 nPageNumOfRow = _rRowFrm.FindPageFrm()->GetPhyPageNum();
+
+ NodeMapIter aIter = maMovedFwdFrms.begin();
+ for ( ; aIter != maMovedFwdFrms.end(); ++aIter )
+ {
+ const NodeMapEntry& rEntry = *(aIter);
+ if ( rEntry.second >= nPageNumOfRow )
+ {
+ SwIterator<SwTxtFrm,SwTxtNode> aFrmIter( *rEntry.first );
+ for( SwTxtFrm* pTxtFrm = aFrmIter.First(); pTxtFrm; pTxtFrm = (SwTxtFrm*)aFrmIter.Next() )
+ {
+ // --> OD 2004-12-03 #115759# - assure that found text frame
+ // is the first one.
+ if ( _rRowFrm.IsAnLower( pTxtFrm ) && !pTxtFrm->GetIndPrev() )
+ // <--
+ {
+ bDoesRowContainMovedFwdFrm = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return bDoesRowContainMovedFwdFrm;
+}
+// <--
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/newfrm.cxx b/sw/source/core/layout/newfrm.cxx
new file mode 100644
index 000000000000..faefa9c3e8b0
--- /dev/null
+++ b/sw/source/core/layout/newfrm.cxx
@@ -0,0 +1,679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <fmtfordr.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <swtable.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewsh.hxx>
+#include <doc.hxx>
+#include <node.hxx>
+#include <dflyobj.hxx>
+#include <frmtool.hxx>
+#include <virtoutp.hxx>
+#include <blink.hxx>
+#include <ndindex.hxx>
+#include <sectfrm.hxx>
+#include <notxtfrm.hxx>
+#include <pagedesc.hxx>
+#include "viewimp.hxx"
+#include "IDocumentTimerAccess.hxx"
+#include "IDocumentLayoutAccess.hxx"
+#include "IDocumentFieldsAccess.hxx"
+#include "IDocumentSettingAccess.hxx"
+#include "IDocumentDrawModelAccess.hxx"
+#include <hints.hxx>
+#include <viewopt.hxx>
+
+SwLayVout *SwRootFrm::pVout = 0;
+sal_Bool SwRootFrm::bInPaint = sal_False;
+sal_Bool SwRootFrm::bNoVirDev = sal_False;
+
+SwCache *SwFrm::pCache = 0;
+
+long FirstMinusSecond( long nFirst, long nSecond )
+ { return nFirst - nSecond; }
+long SecondMinusFirst( long nFirst, long nSecond )
+ { return nSecond - nFirst; }
+long SwIncrement( long nA, long nAdd )
+ { return nA + nAdd; }
+long SwDecrement( long nA, long nSub )
+ { return nA - nSub; }
+
+static SwRectFnCollection aHorizontal = {
+ /* fnRectGet */
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+ &SwRect::TopLeft,
+ &SwRect::_Size,
+ /* fnRectSet */
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::AddWidth,
+ &SwRect::AddHeight,
+
+ &SwRect::SetPosX,
+ &SwRect::SetPosY,
+
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwFrm::SetMaxBottom,
+ &SwRect::OverStepBottom,
+
+ &SwRect::SetUpperLeftCorner,
+ &SwFrm::MakeBelowPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwIncrement,
+ &SwIncrement,
+ &SwRect::SetLeftAndWidth,
+ &SwRect::SetTopAndHeight
+};
+
+static SwRectFnCollection aVertical = {
+ /* fnRectGet */
+ &SwRect::_Right,
+ &SwRect::_Left,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::TopRight,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Right,
+ &SwRect::_Left,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::AddRight,
+ &SwRect::SubLeft,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetRightLeftMargins,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwRect::GetRightDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwFrm::SetMinLeft,
+ &SwRect::OverStepLeft,
+
+ &SwRect::SetUpperRightCorner,
+ &SwFrm::MakeLeftPos,
+ &FirstMinusSecond,
+ &SecondMinusFirst,
+ &SwIncrement,
+ &SwDecrement,
+ &SwRect::SetTopAndHeight,
+ &SwRect::SetRightAndWidth
+};
+
+static SwRectFnCollection aBottomToTop = {
+ /* fnRectGet */
+ &SwRect::_Bottom,
+ &SwRect::_Top,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+ &SwRect::BottomLeft,
+ &SwRect::_Size,
+ /* fnRectSet */
+ &SwRect::_Bottom,
+ &SwRect::_Top,
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Width,
+ &SwRect::_Height,
+
+ &SwRect::AddBottom,
+ &SwRect::SubTop,
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::AddWidth,
+ &SwRect::AddHeight,
+
+ &SwRect::SetPosX,
+ &SwRect::SetPosY,
+
+ &SwFrm::GetBottomMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::SetBottomTopMargins,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwFrm::SetMinTop,
+ &SwRect::OverStepTop,
+
+ &SwRect::SetLowerLeftCorner,
+ &SwFrm::MakeUpperPos,
+ &FirstMinusSecond,
+ &SecondMinusFirst,
+ &SwIncrement,
+ &SwDecrement,
+ &SwRect::SetLeftAndWidth,
+ &SwRect::SetBottomAndHeight
+};
+
+static SwRectFnCollection aVerticalRightToLeft = {
+ /* fnRectGet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::BottomRight,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtBottom,
+ &SwFrm::GetPrtTop,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwRect::GetBottomDistance,
+ &SwRect::GetTopDistance,
+ &SwFrm::SetMaxRight,
+ &SwRect::OverStepRight,
+
+ &SwRect::SetLowerLeftCorner,
+ &SwFrm::MakeRightPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwDecrement,
+ &SwIncrement,
+ &SwRect::SetBottomAndHeight,
+ &SwRect::SetLeftAndWidth
+};
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+static SwRectFnCollection aVerticalLeftToRight = {
+ /* fnRectGet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+ &SwRect::TopLeft,
+ &SwRect::SwappedSize,
+ /* fnRectSet */
+ &SwRect::_Left,
+ &SwRect::_Right,
+ &SwRect::_Top,
+ &SwRect::_Bottom,
+ &SwRect::_Height,
+ &SwRect::_Width,
+
+ &SwRect::SubLeft,
+ &SwRect::AddRight,
+ &SwRect::SubTop,
+ &SwRect::AddBottom,
+ &SwRect::AddHeight,
+ &SwRect::AddWidth,
+
+ &SwRect::SetPosY,
+ &SwRect::SetPosX,
+
+ &SwFrm::GetLeftMargin,
+ &SwFrm::GetRightMargin,
+ &SwFrm::GetTopMargin,
+ &SwFrm::GetBottomMargin,
+ &SwFrm::SetTopBottomMargins,
+ &SwFrm::SetLeftRightMargins,
+ &SwFrm::GetPrtLeft,
+ &SwFrm::GetPrtRight,
+ &SwFrm::GetPrtTop,
+ &SwFrm::GetPrtBottom,
+ &SwRect::GetLeftDistance,
+ &SwRect::GetRightDistance,
+ &SwRect::GetTopDistance,
+ &SwRect::GetBottomDistance,
+ &SwFrm::SetMaxRight,
+ &SwRect::OverStepRight,
+
+ &SwRect::SetUpperLeftCorner,
+ &SwFrm::MakeRightPos,
+ &FirstMinusSecond,
+ &FirstMinusSecond,
+ &SwIncrement,
+ &SwIncrement,
+ &SwRect::SetTopAndHeight,
+ &SwRect::SetLeftAndWidth
+};
+//End of SCMS
+SwRectFn fnRectHori = &aHorizontal;
+SwRectFn fnRectVert = &aVertical;
+//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+SwRectFn fnRectVertL2R = &aVerticalLeftToRight;
+//End of SCMS
+SwRectFn fnRectB2T = &aBottomToTop;
+SwRectFn fnRectVL2R = &aVerticalRightToLeft;
+
+// --> OD 2006-05-10 #i65250#
+sal_uInt32 SwFrm::mnLastFrmId=0;
+// <--
+
+TYPEINIT1(SwFrm,SwClient); //rtti fuer SwFrm
+TYPEINIT1(SwCntntFrm,SwFrm); //rtti fuer SwCntntFrm
+
+
+void _FrmInit()
+{
+ SwRootFrm::pVout = new SwLayVout();
+ SwCache *pNew = new SwCache( 100, 100
+#if OSL_DEBUG_LEVEL > 1
+ , "static SwBorderAttrs::pCache"
+#endif
+ );
+ SwFrm::SetCache( pNew );
+}
+
+
+
+void _FrmFinit()
+{
+#if OSL_DEBUG_LEVEL > 1
+ // im Chache duerfen nur noch 0-Pointer stehen
+ for( sal_uInt16 n = SwFrm::GetCachePtr()->Count(); n; )
+ if( (*SwFrm::GetCachePtr())[ --n ] )
+ {
+ SwCacheObj* pObj = (*SwFrm::GetCachePtr())[ n ];
+ OSL_ENSURE( !pObj, "Wer hat sich nicht ausgetragen?");
+ }
+#endif
+ delete SwRootFrm::pVout;
+ delete SwFrm::GetCachePtr();
+}
+
+/*************************************************************************
+|*
+|* RootFrm::Alles was so zur CurrShell gehoert
+|*
+|*************************************************************************/
+
+typedef CurrShell* CurrShellPtr;
+SV_DECL_PTRARR_SORT(SwCurrShells,CurrShellPtr,4,4)
+SV_IMPL_PTRARR_SORT(SwCurrShells,CurrShellPtr)
+
+CurrShell::CurrShell( ViewShell *pNew )
+{
+ OSL_ENSURE( pNew, "0-Shell einsetzen?" );
+ pRoot = pNew->GetLayout();
+ if ( pRoot )
+ {
+ pPrev = pRoot->pCurrShell;
+ pRoot->pCurrShell = pNew;
+ pRoot->pCurrShells->Insert( this );
+ }
+ else
+ pPrev = 0;
+}
+
+CurrShell::~CurrShell()
+{
+ if ( pRoot )
+ {
+ pRoot->pCurrShells->Remove( this );
+ if ( pPrev )
+ pRoot->pCurrShell = pPrev;
+ if ( !pRoot->pCurrShells->Count() && pRoot->pWaitingCurrShell )
+ {
+ pRoot->pCurrShell = pRoot->pWaitingCurrShell;
+ pRoot->pWaitingCurrShell = 0;
+ }
+ }
+}
+
+void SetShell( ViewShell *pSh )
+{
+ SwRootFrm *pRoot = pSh->GetLayout();
+ if ( !pRoot->pCurrShells->Count() )
+ pRoot->pCurrShell = pSh;
+ else
+ pRoot->pWaitingCurrShell = pSh;
+}
+
+void SwRootFrm::DeRegisterShell( ViewShell *pSh )
+{
+ //Wenn moeglich irgendeine Shell aktivieren
+ if ( pCurrShell == pSh )
+ pCurrShell = pSh->GetNext() != pSh ? (ViewShell*)pSh->GetNext() : 0;
+
+ //Das hat sich eruebrigt
+ if ( pWaitingCurrShell == pSh )
+ pWaitingCurrShell = 0;
+
+ //Referenzen entfernen.
+ for ( sal_uInt16 i = 0; i < pCurrShells->Count(); ++i )
+ {
+ CurrShell *pC = (*pCurrShells)[i];
+ if (pC->pPrev == pSh)
+ pC->pPrev = 0;
+ }
+}
+
+void InitCurrShells( SwRootFrm *pRoot )
+{
+ pRoot->pCurrShells = new SwCurrShells;
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::SwRootFrm()
+|*
+|* Beschreibung:
+|* Der RootFrm laesst sich grundsaetzlich vom Dokument ein eigenes
+|* FrmFmt geben. Dieses loescht er dann selbst im DTor.
+|* Das eigene FrmFmt wird vom uebergebenen Format abgeleitet.
+|*
+|*************************************************************************/
+
+
+SwRootFrm::SwRootFrm( SwFrmFmt *pFmt, ViewShell * pSh ) :
+ SwLayoutFrm( pFmt->GetDoc()->MakeFrmFmt(
+ XubString( "Root", RTL_TEXTENCODING_MS_1252 ), pFmt ), 0 ),
+ // --> PAGES01
+ maPagesArea(),
+ mnViewWidth( -1 ),
+ mnColumns( 0 ),
+ mbBookMode( false ),
+ mbSidebarChanged( false ),
+ mbNeedGrammarCheck( false ),
+ // <--
+ nBrowseWidth( MM50*4 ), //2cm Minimum
+ pTurbo( 0 ),
+ pLastPage( 0 ),
+ pCurrShell( pSh ),
+ pWaitingCurrShell( 0 ),
+ pDrawPage( 0 ),
+ pDestroy( 0 ),
+ nPhyPageNums( 0 ),
+ nAccessibleShells( 0 )
+{
+ nType = FRMC_ROOT;
+ bIdleFormat = bTurboAllowed = bAssertFlyPages = bIsNewLayout = sal_True;
+ bCheckSuperfluous = bBrowseWidthValid = sal_False;
+ setRootFrm( this );
+}
+
+void SwRootFrm::Init( SwFrmFmt* pFmt )
+{
+ InitCurrShells( this );
+
+ IDocumentTimerAccess *pTimerAccess = pFmt->getIDocumentTimerAccess();
+ IDocumentLayoutAccess *pLayoutAccess = pFmt->getIDocumentLayoutAccess();
+ IDocumentFieldsAccess *pFieldsAccess = pFmt->getIDocumentFieldsAccess();
+ const IDocumentSettingAccess *pSettingAccess = pFmt->getIDocumentSettingAccess();
+ pTimerAccess->StopIdling();
+ pLayoutAccess->SetCurrentViewShell( this->GetCurrShell() ); //Fuer das Erzeugen der Flys durch MakeFrms() //swmod 071108//swmod 071225
+ bCallbackActionEnabled = sal_False; //vor Verlassen auf sal_True setzen!
+
+ SdrModel *pMd = pFmt->getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pMd )
+ {
+ // Disable "multiple layout"
+ pDrawPage = pMd->GetPage(0); //pMd->AllocPage( FALSE );
+ //pMd->InsertPage( pDrawPage );
+ // end of disabling
+
+ pDrawPage->SetSize( Frm().SSize() );
+ }
+
+ //Initialisierung des Layouts: Seiten erzeugen. Inhalt mit cntnt verbinden
+ //usw.
+ //Zuerst einiges initialiseren und den ersten Node besorgen (der wird
+ //fuer den PageDesc benoetigt).
+
+ SwDoc* pDoc = pFmt->GetDoc();
+ SwNodeIndex aIndex( *pDoc->GetNodes().GetEndOfContent().StartOfSectionNode() );
+ SwCntntNode *pNode = pDoc->GetNodes().GoNextSection( &aIndex, sal_True, sal_False );
+ // --> FME 2005-05-25 #123067# pNode = 0 can really happen:
+ SwTableNode *pTblNd= pNode ? pNode->FindTableNode() : 0;
+ // <--
+
+ //PageDesc besorgen (entweder vom FrmFmt des ersten Node oder den
+ //initialen.)
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nPgNum = 1;
+
+ if ( pTblNd )
+ {
+ const SwFmtPageDesc &rDesc = pTblNd->GetTable().GetFrmFmt()->GetPageDesc();
+ pDesc = (SwPageDesc*)rDesc.GetPageDesc();
+ //#19104# Seitennummeroffset beruecksictigen!!
+ bIsVirtPageNum = 0 != ( nPgNum = rDesc.GetNumOffset() );
+ }
+ else if ( pNode )
+ {
+ const SwFmtPageDesc &rDesc = pNode->GetSwAttrSet().GetPageDesc();
+ pDesc = (SwPageDesc*)rDesc.GetPageDesc();
+ //#19104# Seitennummeroffset beruecksictigen!!
+ bIsVirtPageNum = 0 != ( nPgNum = rDesc.GetNumOffset() );
+ }
+ else
+ bIsVirtPageNum = sal_False;
+ if ( !pDesc )
+ pDesc = (SwPageDesc*)
+ &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
+ const sal_Bool bOdd = !nPgNum || 0 != ( nPgNum % 2 );
+
+ //Eine Seite erzeugen und in das Layout stellen
+ SwPageFrm *pPage = ::InsertNewPage( *pDesc, this, bOdd, sal_False, sal_False, 0 );
+
+ //Erstes Blatt im Bodytext-Bereich suchen.
+ SwLayoutFrm *pLay = pPage->FindBodyCont();
+ while( pLay->Lower() )
+ pLay = (SwLayoutFrm*)pLay->Lower();
+
+ SwNodeIndex aTmp( *pDoc->GetNodes().GetEndOfContent().StartOfSectionNode(), 1 );
+ ::_InsertCnt( pLay, pDoc, aTmp.GetIndex(), sal_True );
+ //Noch nicht ersetzte Master aus der Liste entfernen.
+ RemoveMasterObjs( pDrawPage );
+ if( pSettingAccess->get(IDocumentSettingAccess::GLOBAL_DOCUMENT) )
+ pFieldsAccess->UpdateRefFlds( NULL );
+ //b6433357: Update page fields after loading
+ // --->
+ if ( !pCurrShell || !pCurrShell->Imp()->IsUpdateExpFlds() )
+ {
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ pFieldsAccess->UpdatePageFlds( &aMsgHnt );
+ }
+ // <---
+
+ pTimerAccess->StartIdling();
+ bCallbackActionEnabled = sal_True;
+
+ ViewShell *pViewSh = GetCurrShell();
+ if (pViewSh)
+ mbNeedGrammarCheck = pViewSh->GetViewOptions()->IsOnlineSpell();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::~SwRootFrm()
+|*
+|*************************************************************************/
+
+
+
+SwRootFrm::~SwRootFrm()
+{
+ bTurboAllowed = sal_False;
+ pTurbo = 0;
+ if(pBlink)
+ pBlink->FrmDelete( this );
+ static_cast<SwFrmFmt*>(GetRegisteredInNonConst())->GetDoc()->DelFrmFmt( static_cast<SwFrmFmt*>(GetRegisteredInNonConst()) );
+ delete pDestroy;
+ pDestroy = 0;
+
+ //Referenzen entfernen.
+ for ( sal_uInt16 i = 0; i < pCurrShells->Count(); ++i )
+ (*pCurrShells)[i]->pRoot = 0;
+
+ delete pCurrShells;
+
+ OSL_ENSURE( 0==nAccessibleShells, "Some accessible shells are left" );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::RemoveMasterObjs()
+|*
+|*************************************************************************/
+
+
+void SwRootFrm::RemoveMasterObjs( SdrPage *pPg )
+{
+ //Alle Masterobjekte aus der Page entfernen. Nicht loeschen!!
+ for( sal_uLong i = pPg ? pPg->GetObjCount() : 0; i; )
+ {
+ SdrObject* pObj = pPg->GetObj( --i );
+ if( pObj->ISA(SwFlyDrawObj ) )
+ pPg->RemoveObject( i );
+ }
+}
+
+
+void SwRootFrm::AllCheckPageDescs() const
+{
+ CheckPageDescs( (SwPageFrm*)this->Lower() );
+}
+//swmod 080226
+void SwRootFrm::AllInvalidateAutoCompleteWords() const
+{
+ SwPageFrm *pPage = (SwPageFrm*)this->Lower();
+ while ( pPage )
+ {
+ pPage->InvalidateAutoCompleteWords();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}//swmod 080305
+void SwRootFrm::AllAddPaintRect() const
+{
+ GetCurrShell()->AddPaintRect( this->Frm() );
+}//swmod 080305
+void SwRootFrm::AllRemoveFtns()
+{
+ RemoveFtns();
+}
+void SwRootFrm::AllInvalidateSmartTagsOrSpelling(sal_Bool bSmartTags) const
+{
+ SwPageFrm *pPage = (SwPageFrm*)this->Lower();
+ while ( pPage )
+ {
+ if ( bSmartTags )
+ pPage->InvalidateSmartTags();
+
+ pPage->InvalidateSpelling();
+ pPage = (SwPageFrm*)pPage->GetNext();
+ } //swmod 080218
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatter.cxx b/sw/source/core/layout/objectformatter.cxx
new file mode 100644
index 000000000000..c9cebfd93ce6
--- /dev/null
+++ b/sw/source/core/layout/objectformatter.cxx
@@ -0,0 +1,580 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformatter.hxx>
+#include <objectformattertxtfrm.hxx>
+#include <objectformatterlayfrm.hxx>
+#include <anchoredobject.hxx>
+#include <anchoreddrawobject.hxx>
+#include <sortedobjs.hxx>
+#include <pagefrm.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx>
+#include <layact.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <doc.hxx>
+
+#include <vector>
+
+// =============================================================================
+// helper class <SwPageNumAndTypeOfAnchors>
+// --> #i26945# - Additionally the type of the anchor text frame
+// is collected - by type is meant 'master' or 'follow'.
+// =============================================================================
+class SwPageNumAndTypeOfAnchors
+{
+ private:
+ struct tEntry
+ {
+ SwAnchoredObject* mpAnchoredObj;
+ sal_uInt32 mnPageNumOfAnchor;
+ bool mbAnchoredAtMaster;
+ };
+
+ std::vector< tEntry* > maObjList;
+
+ public:
+ inline SwPageNumAndTypeOfAnchors()
+ {
+ }
+ inline ~SwPageNumAndTypeOfAnchors()
+ {
+ for ( std::vector< tEntry* >::iterator aIter = maObjList.begin();
+ aIter != maObjList.end(); ++aIter )
+ {
+ delete (*aIter);
+ }
+ maObjList.clear();
+ }
+
+ inline void Collect( SwAnchoredObject& _rAnchoredObj )
+ {
+ tEntry* pNewEntry = new tEntry();
+ pNewEntry->mpAnchoredObj = &_rAnchoredObj;
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor )
+ {
+ pNewEntry->mnPageNumOfAnchor = pPageFrmOfAnchor->GetPhyPageNum();
+ }
+ else
+ {
+ pNewEntry->mnPageNumOfAnchor = 0;
+ }
+ // <--
+ // --> #i26945# - collect type of anchor
+ SwTxtFrm* pAnchorCharFrm = _rAnchoredObj.FindAnchorCharFrm();
+ if ( pAnchorCharFrm )
+ {
+ pNewEntry->mbAnchoredAtMaster = !pAnchorCharFrm->IsFollow();
+ }
+ else
+ {
+ pNewEntry->mbAnchoredAtMaster = true;
+ }
+ // <--
+ maObjList.push_back( pNewEntry );
+ }
+
+ inline SwAnchoredObject* operator[]( sal_uInt32 _nIndex )
+ {
+ SwAnchoredObject* bRetObj = 0L;
+
+ if ( _nIndex < Count())
+ {
+ bRetObj = maObjList[_nIndex]->mpAnchoredObj;
+ }
+
+ return bRetObj;
+ }
+
+ inline sal_uInt32 GetPageNum( sal_uInt32 _nIndex ) const
+ {
+ sal_uInt32 nRetPgNum = 0L;
+
+ if ( _nIndex < Count())
+ {
+ nRetPgNum = maObjList[_nIndex]->mnPageNumOfAnchor;
+ }
+
+ return nRetPgNum;
+ }
+
+ // --> #i26945#
+ inline bool AnchoredAtMaster( sal_uInt32 _nIndex )
+ {
+ bool bAnchoredAtMaster( true );
+
+ if ( _nIndex < Count())
+ {
+ bAnchoredAtMaster = maObjList[_nIndex]->mbAnchoredAtMaster;
+ }
+
+ return bAnchoredAtMaster;
+ }
+ // <--
+
+ inline sal_uInt32 Count() const
+ {
+ return maObjList.size();
+ }
+};
+
+// =============================================================================
+// implementation of class <SwObjectFormatter>
+// =============================================================================
+SwObjectFormatter::SwObjectFormatter( const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction,
+ const bool _bCollectPgNumOfAnchors )
+ : mrPageFrm( _rPageFrm ),
+ mbFormatOnlyAsCharAnchored( false ),
+ mbConsiderWrapOnObjPos( _rPageFrm.GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ),
+ mpLayAction( _pLayAction ),
+ // --> #i26945#
+ mpPgNumAndTypeOfAnchors( _bCollectPgNumOfAnchors ? new SwPageNumAndTypeOfAnchors() : 0L )
+ // <--
+{
+}
+
+SwObjectFormatter::~SwObjectFormatter()
+{
+ delete mpPgNumAndTypeOfAnchors;
+}
+
+SwObjectFormatter* SwObjectFormatter::CreateObjFormatter(
+ SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ SwObjectFormatter* pObjFormatter = 0L;
+ if ( _rAnchorFrm.IsTxtFrm() )
+ {
+ pObjFormatter = SwObjectFormatterTxtFrm::CreateObjFormatter(
+ static_cast<SwTxtFrm&>(_rAnchorFrm),
+ _rPageFrm, _pLayAction );
+ }
+ else if ( _rAnchorFrm.IsLayoutFrm() )
+ {
+ pObjFormatter = SwObjectFormatterLayFrm::CreateObjFormatter(
+ static_cast<SwLayoutFrm&>(_rAnchorFrm),
+ _rPageFrm, _pLayAction );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatter::CreateObjFormatter(..)> - unexcepted type of anchor frame" );
+ }
+
+ return pObjFormatter;
+}
+
+/** method to format all floating screen objects at the given anchor frame
+
+ @author OD
+*/
+bool SwObjectFormatter::FormatObjsAtFrm( SwFrm& _rAnchorFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ bool bSuccess( true );
+
+ // create corresponding object formatter
+ SwObjectFormatter* pObjFormatter =
+ SwObjectFormatter::CreateObjFormatter( _rAnchorFrm, _rPageFrm, _pLayAction );
+
+ if ( pObjFormatter )
+ {
+ // format anchored floating screen objects
+ bSuccess = pObjFormatter->DoFormatObjs();
+ }
+ delete pObjFormatter;
+
+ return bSuccess;
+}
+
+/** method to format a given floating screen object
+
+ @author OD
+*/
+bool SwObjectFormatter::FormatObj( SwAnchoredObject& _rAnchoredObj,
+ SwFrm* _pAnchorFrm,
+ const SwPageFrm* _pPageFrm,
+ SwLayAction* _pLayAction )
+{
+ bool bSuccess( true );
+
+ OSL_ENSURE( _pAnchorFrm || _rAnchoredObj.GetAnchorFrm(),
+ "<SwObjectFormatter::FormatObj(..)> - missing anchor frame" );
+ SwFrm& rAnchorFrm = _pAnchorFrm ? *(_pAnchorFrm) : *(_rAnchoredObj.AnchorFrm());
+
+ OSL_ENSURE( _pPageFrm || rAnchorFrm.FindPageFrm(),
+ "<SwObjectFormatter::FormatObj(..)> - missing page frame" );
+ const SwPageFrm& rPageFrm = _pPageFrm ? *(_pPageFrm) : *(rAnchorFrm.FindPageFrm());
+
+ // create corresponding object formatter
+ SwObjectFormatter* pObjFormatter =
+ SwObjectFormatter::CreateObjFormatter( rAnchorFrm, rPageFrm, _pLayAction );
+
+ if ( pObjFormatter )
+ {
+ // format given floating screen object
+ // --> #i40147# - check for moved forward anchor frame
+ bSuccess = pObjFormatter->DoFormatObj( _rAnchoredObj, true );
+ // <--
+ }
+ delete pObjFormatter;
+
+ return bSuccess;
+}
+
+/** helper method for method <_FormatObj(..)> - performs the intrinsic format
+ of the layout of the given layout frame and all its lower layout frames.
+
+ #i28701#
+ IMPORTANT NOTE:
+ Method corresponds to methods <SwLayAction::FormatLayoutFly(..)> and
+ <SwLayAction::FormatLayout(..)>. Thus, its code for the formatting have
+ to be synchronised.
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatLayout( SwLayoutFrm& _rLayoutFrm )
+{
+ _rLayoutFrm.Calc();
+
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsLayoutFrm() )
+ {
+ _FormatLayout( *(static_cast<SwLayoutFrm*>(pLowerFrm)) );
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+
+/** helper method for method <_FormatObj(..)> - performs the intrinsic
+ format of the content of the given floating screen object.
+
+ #i28701#
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatObjCntnt( SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !_rAnchoredObj.ISA(SwFlyFrm) )
+ {
+ // only Writer fly frames have content
+ return;
+ }
+
+ SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
+ SwCntntFrm* pCntnt = rFlyFrm.ContainsCntnt();
+
+ while ( pCntnt )
+ {
+ // format content
+ pCntnt->OptCalc();
+
+ // format floating screen objects at content text frame
+ // --> #i23129#, #i36347# - pass correct page frame to
+ // the object formatter
+ if ( pCntnt->IsTxtFrm() &&
+ !SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
+ *(pCntnt->FindPageFrm()),
+ GetLayAction() ) )
+ // <--
+ {
+ // restart format with first content
+ pCntnt = rFlyFrm.ContainsCntnt();
+ continue;
+ }
+
+ // continue with next content
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+}
+
+/** performs the intrinsic format of a given floating screen object and its content.
+
+ #i28701#
+
+ @author OD
+*/
+void SwObjectFormatter::_FormatObj( SwAnchoredObject& _rAnchoredObj )
+{
+ // check, if only as-character anchored object have to be formatted, and
+ // check the anchor type
+ if ( FormatOnlyAsCharAnchored() &&
+ !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ return;
+ }
+
+ // collect anchor object and its 'anchor' page number, if requested
+ if ( mpPgNumAndTypeOfAnchors )
+ {
+ mpPgNumAndTypeOfAnchors->Collect( _rAnchoredObj );
+ }
+
+ if ( _rAnchoredObj.ISA(SwFlyFrm) )
+ {
+ SwFlyFrm& rFlyFrm = static_cast<SwFlyFrm&>(_rAnchoredObj);
+ // --> #i34753# - reset flag, which prevents a positioning
+ if ( rFlyFrm.IsFlyLayFrm() )
+ {
+ static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( false );
+ }
+ // <--
+
+ // #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 15;
+
+ do {
+ if ( mpLayAction )
+ {
+ mpLayAction->FormatLayoutFly( &rFlyFrm );
+ // --> consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( mpLayAction->IsAgain() )
+ {
+ break;
+ }
+ // <--
+ }
+ else
+ {
+ _FormatLayout( rFlyFrm );
+ }
+ // --> #i34753# - prevent further positioning, if
+ // to-page|to-fly anchored Writer fly frame is already clipped.
+ if ( rFlyFrm.IsFlyLayFrm() && rFlyFrm.IsClipped() )
+ {
+ static_cast<SwFlyLayFrm&>(rFlyFrm).SetNoMakePos( true );
+ }
+ // <--
+ // --> #i23129#, #i36347# - pass correct page frame
+ // to the object formatter
+ SwObjectFormatter::FormatObjsAtFrm( rFlyFrm,
+ *(rFlyFrm.FindPageFrm()),
+ mpLayAction );
+ // <--
+ if ( mpLayAction )
+ {
+ mpLayAction->_FormatFlyCntnt( &rFlyFrm );
+ // --> consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( mpLayAction->IsAgain() )
+ {
+ break;
+ }
+ // <--
+ }
+ else
+ {
+ _FormatObjCntnt( rFlyFrm );
+ }
+
+ if ( ++nLoopControlRuns >= nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwObjectFormatter::_FormatObj: Stage 3!!!" );
+#endif
+ rFlyFrm.ValidateThisAndAllLowers( 2 );
+ nLoopControlRuns = 0;
+ }
+
+ // --> #i57917#
+ // stop formatting of anchored object, if restart of layout process is requested.
+ } while ( !rFlyFrm.IsValid() &&
+ !_rAnchoredObj.RestartLayoutProcess() &&
+ rFlyFrm.GetAnchorFrm() == &GetAnchorFrm() );
+ // <--
+ }
+ else if ( _rAnchoredObj.ISA(SwAnchoredDrawObject) )
+ {
+ _rAnchoredObj.MakeObjPos();
+ }
+}
+
+/** invokes the intrinsic format method for all floating screen objects,
+ anchored at anchor frame on the given page frame
+
+ #i28701#
+ #i26945# - for format of floating screen objects for
+ follow text frames, the 'master' text frame is passed to the method.
+ Thus, the objects, whose anchor character is inside the follow text
+ frame can be formatted.
+
+ @author OD
+*/
+bool SwObjectFormatter::_FormatObjsAtFrm( SwTxtFrm* _pMasterTxtFrm )
+{
+ // --> #i26945#
+ SwFrm* pAnchorFrm( 0L );
+ if ( GetAnchorFrm().IsTxtFrm() &&
+ static_cast<SwTxtFrm&>(GetAnchorFrm()).IsFollow() &&
+ _pMasterTxtFrm )
+ {
+ pAnchorFrm = _pMasterTxtFrm;
+ }
+ else
+ {
+ pAnchorFrm = &GetAnchorFrm();
+ }
+ // <--
+ if ( !pAnchorFrm->GetDrawObjs() )
+ {
+ // nothing to do, if no floating screen object is registered at the anchor frame.
+ return true;
+ }
+
+ bool bSuccess( true );
+
+ sal_uInt32 i = 0;
+ for ( ; i < pAnchorFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pAnchorFrm->GetDrawObjs())[i];
+
+ // check, if object's anchor is on the given page frame or
+ // object is registered at the given page frame.
+ // --> #i26945# - check, if the anchor character of the
+ // anchored object is located in a follow text frame. If this anchor
+ // follow text frame differs from the given anchor frame, the given
+ // anchor frame is a 'master' text frame of the anchor follow text frame.
+ // If the anchor follow text frame is in the same body as its 'master'
+ // text frame, do not format the anchored object.
+ // E.g., this situation can occur during the table row splitting algorithm.
+ SwTxtFrm* pAnchorCharFrm = pAnchoredObj->FindAnchorCharFrm();
+ const bool bAnchoredAtFollowInSameBodyAsMaster =
+ pAnchorCharFrm && pAnchorCharFrm->IsFollow() &&
+ pAnchorCharFrm != pAnchoredObj->GetAnchorFrm() &&
+ pAnchorCharFrm->FindBodyFrm() ==
+ static_cast<SwTxtFrm*>(pAnchoredObj->AnchorFrm())->FindBodyFrm();
+ if ( bAnchoredAtFollowInSameBodyAsMaster )
+ {
+ continue;
+ }
+ // <--
+ // --> #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor();
+ OSL_ENSURE( pPageFrmOfAnchor,
+ "<SwObjectFormatter::_FormatObjsAtFrm()> - missing page frame." );
+ // --> #i26945#
+ if ( pPageFrmOfAnchor && pPageFrmOfAnchor == &mrPageFrm )
+ // <--
+ {
+ // if format of object fails, stop formatting and pass fail to
+ // calling method via the return value.
+ if ( !DoFormatObj( *pAnchoredObj ) )
+ {
+ bSuccess = false;
+ break;
+ }
+
+ // considering changes at <pAnchorFrm->GetDrawObjs()> during
+ // format of the object.
+ if ( !pAnchorFrm->GetDrawObjs() ||
+ i > pAnchorFrm->GetDrawObjs()->Count() )
+ {
+ break;
+ }
+ else
+ {
+ sal_uInt32 nActPosOfObj =
+ pAnchorFrm->GetDrawObjs()->ListPosOf( *pAnchoredObj );
+ if ( nActPosOfObj == pAnchorFrm->GetDrawObjs()->Count() ||
+ nActPosOfObj > i )
+ {
+ --i;
+ }
+ else if ( nActPosOfObj < i )
+ {
+ i = nActPosOfObj;
+ }
+ }
+ }
+ } // end of loop on <pAnchorFrm->.GetDrawObjs()>
+
+ return bSuccess;
+}
+
+/** accessor to collected anchored object
+
+ #i28701#
+
+ @author OD
+*/
+SwAnchoredObject* SwObjectFormatter::GetCollectedObj( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors ? (*mpPgNumAndTypeOfAnchors)[_nIndex] : 0L;
+}
+
+/** accessor to 'anchor' page number of collected anchored object
+
+ #i28701#
+
+ @author OD
+*/
+sal_uInt32 SwObjectFormatter::GetPgNumOfCollected( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->GetPageNum(_nIndex) : 0L;
+}
+
+/** accessor to 'anchor' type of collected anchored object
+
+ #i26945#
+
+ @author OD
+*/
+bool SwObjectFormatter::IsCollectedAnchoredAtMaster( const sal_uInt32 _nIndex )
+{
+ return mpPgNumAndTypeOfAnchors
+ ? mpPgNumAndTypeOfAnchors->AnchoredAtMaster(_nIndex)
+ : true;
+}
+
+/** accessor to total number of collected anchored objects
+
+ #i28701#
+
+ @author OD
+*/
+sal_uInt32 SwObjectFormatter::CountOfCollected()
+{
+ return mpPgNumAndTypeOfAnchors ? mpPgNumAndTypeOfAnchors->Count() : 0L;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatterlayfrm.cxx b/sw/source/core/layout/objectformatterlayfrm.cxx
new file mode 100644
index 000000000000..80fc372eb2f6
--- /dev/null
+++ b/sw/source/core/layout/objectformatterlayfrm.cxx
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformatterlayfrm.hxx>
+#include <anchoredobject.hxx>
+#include <sortedobjs.hxx>
+#include <layfrm.hxx>
+#include <pagefrm.hxx>
+
+// --> OD 2005-07-13 #124218#
+#include <layact.hxx>
+// <--
+
+// =============================================================================
+// implementation of class <SwObjectFormatterLayFrm>
+// =============================================================================
+SwObjectFormatterLayFrm::SwObjectFormatterLayFrm( SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+ : SwObjectFormatter( _rPageFrm, _pLayAction ),
+ mrAnchorLayFrm( _rAnchorLayFrm )
+{
+}
+
+SwObjectFormatterLayFrm::~SwObjectFormatterLayFrm()
+{
+}
+
+SwObjectFormatterLayFrm* SwObjectFormatterLayFrm::CreateObjFormatter(
+ SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ if ( !_rAnchorLayFrm.IsPageFrm() &&
+ !_rAnchorLayFrm.IsFlyFrm() )
+ {
+ OSL_FAIL( "<SwObjectFormatterLayFrm::CreateObjFormatter(..)> - unexcepted type of anchor frame " );
+ return 0L;
+ }
+
+ SwObjectFormatterLayFrm* pObjFormatter = 0L;
+
+ // create object formatter, if floating screen objects are registered at
+ // given anchor layout frame.
+ if ( _rAnchorLayFrm.GetDrawObjs() ||
+ ( _rAnchorLayFrm.IsPageFrm() &&
+ static_cast<SwPageFrm&>(_rAnchorLayFrm).GetSortedObjs() ) )
+ {
+ pObjFormatter =
+ new SwObjectFormatterLayFrm( _rAnchorLayFrm, _rPageFrm, _pLayAction );
+ }
+
+ return pObjFormatter;
+}
+
+SwFrm& SwObjectFormatterLayFrm::GetAnchorFrm()
+{
+ return mrAnchorLayFrm;
+}
+
+// --> OD 2005-01-10 #i40147# - add parameter <_bCheckForMovedFwd>.
+// Not relevant for objects anchored at layout frame.
+bool SwObjectFormatterLayFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool )
+// <--
+{
+ _FormatObj( _rAnchoredObj );
+
+ // --> OD 2005-07-13 #124218# - consider that the layout action has to be
+ // restarted due to a deleted page frame.
+ return GetLayAction() ? !GetLayAction()->IsAgain() : true;
+ // <--
+}
+
+bool SwObjectFormatterLayFrm::DoFormatObjs()
+{
+ bool bSuccess( true );
+
+ bSuccess = _FormatObjsAtFrm();
+
+ if ( bSuccess && GetAnchorFrm().IsPageFrm() )
+ {
+ // anchor layout frame is a page frame.
+ // Thus, format also all anchored objects, which are registered at
+ // this page frame, whose 'anchor' isn't on this page frame and whose
+ // anchor frame is valid.
+ bSuccess = _AdditionalFormatObjsOnPage();
+ }
+
+ return bSuccess;
+}
+
+/** method to format all anchored objects, which are registered at
+ the page frame, whose 'anchor' isn't on this page frame and whose
+ anchor frame is valid.
+
+ OD 2004-07-02 #i28701#
+
+ @author
+*/
+bool SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()
+{
+ if ( !GetAnchorFrm().IsPageFrm() )
+ {
+ OSL_FAIL( "<SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()> - mis-usage of method, call only for anchor frames of type page frame" );
+ return true;
+ }
+
+ // --> OD 2005-07-13 #124218# - consider, if the layout action
+ // has to be restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+ // <--
+
+
+ SwPageFrm& rPageFrm = static_cast<SwPageFrm&>(GetAnchorFrm());
+
+ if ( !rPageFrm.GetSortedObjs() )
+ {
+ // nothing to do, if no floating screen object is registered at the anchor frame.
+ return true;
+ }
+
+ bool bSuccess( true );
+
+ sal_uInt32 i = 0;
+ for ( ; i < rPageFrm.GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*rPageFrm.GetSortedObjs())[i];
+
+ // --> OD 2005-08-18 #i51941# - do not format object, which are anchored
+ // inside or at fly frame.
+ if ( pAnchoredObj->GetAnchorFrm()->FindFlyFrm() )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor = pAnchoredObj->FindPageFrmOfAnchor();
+ // --> OD 2004-10-08 #i26945# - check, if the page frame of the
+ // object's anchor frame isn't the given page frame
+ OSL_ENSURE( pPageFrmOfAnchor,
+ "<SwObjectFormatterLayFrm::_AdditionalFormatObjsOnPage()> - missing page frame" );
+ if ( pPageFrmOfAnchor &&
+ // --> OD 2004-10-22 #i35911#
+ pPageFrmOfAnchor->GetPhyPageNum() < rPageFrm.GetPhyPageNum() )
+ // <--
+ // <--
+ {
+ // if format of object fails, stop formatting and pass fail to
+ // calling method via the return value.
+ if ( !DoFormatObj( *pAnchoredObj ) )
+ {
+ bSuccess = false;
+ break;
+ }
+
+ // considering changes at <GetAnchorFrm().GetDrawObjs()> during
+ // format of the object.
+ if ( !rPageFrm.GetSortedObjs() ||
+ i > rPageFrm.GetSortedObjs()->Count() )
+ {
+ break;
+ }
+ else
+ {
+ sal_uInt32 nActPosOfObj =
+ rPageFrm.GetSortedObjs()->ListPosOf( *pAnchoredObj );
+ if ( nActPosOfObj == rPageFrm.GetSortedObjs()->Count() ||
+ nActPosOfObj > i )
+ {
+ --i;
+ }
+ else if ( nActPosOfObj < i )
+ {
+ i = nActPosOfObj;
+ }
+ }
+ }
+ } // end of loop on <rPageFrm.GetSortedObjs()>
+
+ return bSuccess;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformatterlayfrm.hxx b/sw/source/core/layout/objectformatterlayfrm.hxx
new file mode 100644
index 000000000000..a2199030a61c
--- /dev/null
+++ b/sw/source/core/layout/objectformatterlayfrm.hxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJECTFORMATTERLAYFRM_HXX
+#define _OBJECTFORMATTERLAYFRM_HXX
+
+#include <objectformatter.hxx>
+
+class SwLayoutFrm;
+
+// -----------------------------------------------------------------------------
+// Format floating screen objects, which are anchored at a given anchor text frame
+// and registered at the given page frame.
+// -----------------------------------------------------------------------------
+class SwObjectFormatterLayFrm : public SwObjectFormatter
+{
+ private:
+ // anchor layout frame
+ SwLayoutFrm& mrAnchorLayFrm;
+
+ SwObjectFormatterLayFrm( SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to format all anchored objects, which are registered at
+ the page frame, whose 'anchor' isn't on this page frame and whose
+ anchor frame is valid.
+
+ OD 2004-07-02 #i28701#
+
+ @author OD
+
+ @return boolean
+ indicates, if format was successfull
+ */
+ bool _AdditionalFormatObjsOnPage();
+
+ protected:
+
+ virtual SwFrm& GetAnchorFrm();
+
+ public:
+ virtual ~SwObjectFormatterLayFrm();
+
+ // --> OD 2005-01-10 #i40147# - add parameter <_bCheckForMovedFwd>.
+ // Not relevant for objects anchored at layout frame.
+ virtual bool DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd = false );
+ // <--
+ virtual bool DoFormatObjs();
+
+ static SwObjectFormatterLayFrm* CreateObjFormatter(
+ SwLayoutFrm& _rAnchorLayFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx b/sw/source/core/layout/objectformattertxtfrm.cxx
new file mode 100644
index 000000000000..a3593f5cc479
--- /dev/null
+++ b/sw/source/core/layout/objectformattertxtfrm.cxx
@@ -0,0 +1,814 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objectformattertxtfrm.hxx>
+#include <anchoredobject.hxx>
+#include <sortedobjs.hxx>
+#include <flyfrms.hxx>
+#include <txtfrm.hxx>
+#include <pagefrm.hxx>
+#include <rowfrm.hxx>
+#include <layouter.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <fmtfollowtextflow.hxx>
+#include <layact.hxx>
+
+using namespace ::com::sun::star;
+
+// =============================================================================
+
+// little helper class to forbid follow formatting for the given text frame
+class SwForbidFollowFormat
+{
+private:
+ SwTxtFrm& mrTxtFrm;
+ const bool bOldFollowFormatAllowed;
+
+public:
+ SwForbidFollowFormat( SwTxtFrm& _rTxtFrm )
+ : mrTxtFrm( _rTxtFrm ),
+ bOldFollowFormatAllowed( _rTxtFrm.FollowFormatAllowed() )
+ {
+ mrTxtFrm.ForbidFollowFormat();
+ }
+
+ ~SwForbidFollowFormat()
+ {
+ if ( bOldFollowFormatAllowed )
+ {
+ mrTxtFrm.AllowFollowFormat();
+ }
+ }
+};
+
+// =============================================================================
+// implementation of class <SwObjectFormatterTxtFrm>
+// =============================================================================
+SwObjectFormatterTxtFrm::SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwTxtFrm* _pMasterAnchorTxtFrm,
+ SwLayAction* _pLayAction )
+ : SwObjectFormatter( _rPageFrm, _pLayAction, true ),
+ mrAnchorTxtFrm( _rAnchorTxtFrm ),
+ mpMasterAnchorTxtFrm( _pMasterAnchorTxtFrm )
+{
+}
+
+SwObjectFormatterTxtFrm::~SwObjectFormatterTxtFrm()
+{
+}
+
+SwObjectFormatterTxtFrm* SwObjectFormatterTxtFrm::CreateObjFormatter(
+ SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction )
+{
+ SwObjectFormatterTxtFrm* pObjFormatter = 0L;
+
+ // determine 'master' of <_rAnchorTxtFrm>, if anchor frame is a follow text frame.
+ SwTxtFrm* pMasterOfAnchorFrm = 0L;
+ if ( _rAnchorTxtFrm.IsFollow() )
+ {
+ pMasterOfAnchorFrm = _rAnchorTxtFrm.FindMaster();
+ while ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->IsFollow() )
+ {
+ pMasterOfAnchorFrm = pMasterOfAnchorFrm->FindMaster();
+ }
+ }
+
+ // create object formatter, if floating screen objects are registered
+ // at anchor frame (or at 'master' anchor frame)
+ if ( _rAnchorTxtFrm.GetDrawObjs() ||
+ ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->GetDrawObjs() ) )
+ {
+ pObjFormatter =
+ new SwObjectFormatterTxtFrm( _rAnchorTxtFrm, _rPageFrm,
+ pMasterOfAnchorFrm, _pLayAction );
+ }
+
+ return pObjFormatter;
+}
+
+SwFrm& SwObjectFormatterTxtFrm::GetAnchorFrm()
+{
+ return mrAnchorTxtFrm;
+}
+
+// #i40147# - add parameter <_bCheckForMovedFwd>.
+bool SwObjectFormatterTxtFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd )
+{
+ // check, if only as-character anchored object have to be formatted, and
+ // check the anchor type
+ if ( FormatOnlyAsCharAnchored() &&
+ !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ return true;
+ }
+
+ // consider, if the layout action has to be
+ // restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+
+ bool bSuccess( true );
+
+ if ( _rAnchoredObj.IsFormatPossible() )
+ {
+ _rAnchoredObj.SetRestartLayoutProcess( false );
+
+ _FormatObj( _rAnchoredObj );
+ // consider, if the layout action has to be
+ // restarted due to a delete of a page frame.
+ if ( GetLayAction() && GetLayAction()->IsAgain() )
+ {
+ return false;
+ }
+
+ // check, if layout process has to be restarted.
+ // if yes, perform needed invalidations.
+
+ // no restart of layout process,
+ // if anchored object is anchored inside a Writer fly frame,
+ // its position is already locked, and it follows the text flow.
+ const bool bRestart =
+ _rAnchoredObj.RestartLayoutProcess() &&
+ !( _rAnchoredObj.PositionLocked() &&
+ _rAnchoredObj.GetAnchorFrm()->IsInFly() &&
+ _rAnchoredObj.GetFrmFmt().GetFollowTextFlow().GetValue() );
+ if ( bRestart )
+ {
+ bSuccess = false;
+ _InvalidatePrevObjs( _rAnchoredObj );
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+
+ // format anchor text frame, if wrapping style influence of the object
+ // has to be considered and it's <NONE_SUCCESSIVE_POSITIONED>
+ // #i3317# - consider also anchored objects, whose
+ // wrapping style influence is temporarly considered.
+ // #i40147# - consider also anchored objects, for
+ // whose the check of a moved forward anchor frame is requested.
+ // revise decision made for i3317:
+ // anchored objects, whose wrapping style influence is temporarly considered,
+ // have to be considered in method <SwObjectFormatterTxtFrm::DoFormatObjs()>
+ if ( bSuccess &&
+ _rAnchoredObj.ConsiderObjWrapInfluenceOnObjPos() &&
+ ( _bCheckForMovedFwd ||
+ _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) )
+ {
+ // #i26945# - check conditions for move forward of
+ // anchor text frame
+ // determine, if anchor text frame has previous frame
+ const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
+
+ // #i40141# - use new method - it also formats the
+ // section the anchor frame is in.
+ _FormatAnchorFrmForCheckMoveFwd();
+
+ // #i35911#
+ if ( _rAnchoredObj.HasClearedEnvironment() )
+ {
+ _rAnchoredObj.SetClearedEnvironment( true );
+ // #i44049# - consider, that anchor frame
+ // could already been marked to move forward.
+ SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
+ if ( pAnchorPageFrm != _rAnchoredObj.GetPageFrm() )
+ {
+ bool bInsert( true );
+ sal_uInt32 nToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nToPageNum ) )
+ {
+ if ( nToPageNum < pAnchorPageFrm->GetPhyPageNum() )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ pAnchorPageFrm->GetPhyPageNum() );
+ mrAnchorTxtFrm.InvalidatePos();
+ bSuccess = false;
+ _InvalidatePrevObjs( _rAnchoredObj );
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ else if ( !mrAnchorTxtFrm.IsFollow() && bDoesAnchorHadPrev )
+ {
+ // index of anchored object in collection of page numbers and
+ // anchor types
+ sal_uInt32 nIdx( CountOfCollected() );
+ OSL_ENSURE( nIdx > 0,
+ "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchored object not collected!?" );
+ --nIdx;
+
+ sal_uInt32 nToPageNum( 0L );
+ // #i43913#
+ bool bDummy( false );
+ // #i58182# - consider new method signature
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( nIdx ),
+ GetPgNumOfCollected( nIdx ),
+ IsCollectedAnchoredAtMaster( nIdx ),
+ nToPageNum, bDummy ) )
+ {
+ // #i49987# - consider, that anchor frame
+ // could already been marked to move forward.
+ bool bInsert( true );
+ sal_uInt32 nMovedFwdToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
+ {
+ if ( nMovedFwdToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ // Indicate that anchor text frame has to move forward and
+ // invalidate its position to force a re-format.
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ nToPageNum );
+ mrAnchorTxtFrm.InvalidatePos();
+
+ // Indicate restart of the layout process
+ bSuccess = false;
+
+ // If needed, invalidate previous objects anchored at same anchor
+ // text frame.
+ _InvalidatePrevObjs( _rAnchoredObj );
+
+ // Invalidate object and following objects for the restart of the
+ // layout process
+ _InvalidateFollowObjs( _rAnchoredObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ // i40155# - mark anchor frame not to wrap around
+ // objects under the condition, that its follow contains all its text.
+ else if ( !mrAnchorTxtFrm.IsFollow() &&
+ mrAnchorTxtFrm.GetFollow() &&
+ mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
+ {
+ SwLayouter::InsertFrmNotToWrap(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ SwLayouter::RemoveMovedFwdFrm(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ }
+ }
+ }
+
+ return bSuccess;
+}
+
+bool SwObjectFormatterTxtFrm::DoFormatObjs()
+{
+ if ( !mrAnchorTxtFrm.IsValid() )
+ {
+ if ( GetLayAction() &&
+ mrAnchorTxtFrm.FindPageFrm() != &GetPageFrm() )
+ {
+ // notify layout action, thus is can restart the layout process on
+ // a previous page.
+ GetLayAction()->SetAgain();
+ }
+ else
+ {
+ // the anchor text frame has to be valid, thus assert.
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs()> called for invalidate anchor text frame." );
+ }
+
+ return false;
+ }
+
+ bool bSuccess( true );
+
+ if ( mrAnchorTxtFrm.IsFollow() )
+ {
+ // Only floating screen objects anchored as-character are directly
+ // registered at a follow text frame. The other floating screen objects
+ // are registered at the 'master' anchor text frame.
+ // Thus, format the other floating screen objects through the 'master'
+ // anchor text frame
+ OSL_ENSURE( mpMasterAnchorTxtFrm,
+ "SwObjectFormatterTxtFrm::DoFormatObjs() - missing 'master' anchor text frame" );
+ bSuccess = _FormatObjsAtFrm( mpMasterAnchorTxtFrm );
+
+ if ( bSuccess )
+ {
+ // format of as-character anchored floating screen objects - no failure
+ // excepted on the format of these objects.
+ bSuccess = _FormatObjsAtFrm();
+ }
+ }
+ else
+ {
+ bSuccess = _FormatObjsAtFrm();
+ }
+
+ // consider anchored objects, whose wrapping style influence are temporarly
+ // considered.
+ if ( bSuccess &&
+ ( ConsiderWrapOnObjPos() ||
+ ( !mrAnchorTxtFrm.IsFollow() &&
+ _AtLeastOneObjIsTmpConsiderWrapInfluence() ) ) )
+ {
+ const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
+
+ // Format anchor text frame after its objects are formatted.
+ // Note: The format of the anchor frame also formats the invalid
+ // previous frames of the anchor frame. The format of the previous
+ // frames is needed to get a correct result of format of the
+ // anchor frame for the following check for moved forward anchors
+ // #i40141# - use new method - it also formats the
+ // section the anchor frame is in.
+ _FormatAnchorFrmForCheckMoveFwd();
+
+ sal_uInt32 nToPageNum( 0L );
+ // #i43913#
+ bool bInFollow( false );
+ SwAnchoredObject* pObj = 0L;
+ if ( !mrAnchorTxtFrm.IsFollow() )
+ {
+ pObj = _GetFirstObjWithMovedFwdAnchor(
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
+ nToPageNum, bInFollow );
+ }
+ // #i35911#
+ if ( pObj && pObj->HasClearedEnvironment() )
+ {
+ pObj->SetClearedEnvironment( true );
+ // #i44049# - consider, that anchor frame
+ // could already been marked to move forward.
+ SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
+ // #i43913# - consider, that anchor frame
+ // is a follow or is in a follow row, which will move forward.
+ if ( pAnchorPageFrm != pObj->GetPageFrm() ||
+ bInFollow )
+ {
+ bool bInsert( true );
+ sal_uInt32 nTmpToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nTmpToPageNum ) )
+ {
+ if ( nTmpToPageNum < pAnchorPageFrm->GetPhyPageNum() )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
+ pAnchorPageFrm->GetPhyPageNum() );
+ mrAnchorTxtFrm.InvalidatePos();
+ bSuccess = false;
+ _InvalidatePrevObjs( *pObj );
+ _InvalidateFollowObjs( *pObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ }
+ else if ( pObj && bDoesAnchorHadPrev )
+ {
+ // Object found, whose anchor is moved forward
+
+ // #i49987# - consider, that anchor frame
+ // could already been marked to move forward.
+ bool bInsert( true );
+ sal_uInt32 nMovedFwdToPageNum( 0L );
+ const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
+ if ( SwLayouter::FrmMovedFwdByObjPos(
+ rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
+ {
+ if ( nMovedFwdToPageNum < nToPageNum )
+ SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
+ else
+ bInsert = false;
+ }
+ if ( bInsert )
+ {
+ // Indicate that anchor text frame has to move forward and
+ // invalidate its position to force a re-format.
+ SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm, nToPageNum );
+ mrAnchorTxtFrm.InvalidatePos();
+
+ // Indicate restart of the layout process
+ bSuccess = false;
+
+ // If needed, invalidate previous objects anchored at same anchor
+ // text frame.
+ _InvalidatePrevObjs( *pObj );
+
+ // Invalidate object and following objects for the restart of the
+ // layout process
+ _InvalidateFollowObjs( *pObj, true );
+ }
+ else
+ {
+ OSL_FAIL( "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
+ }
+ }
+ // #i40155# - mark anchor frame not to wrap around
+ // objects under the condition, that its follow contains all its text.
+ else if ( !mrAnchorTxtFrm.IsFollow() &&
+ mrAnchorTxtFrm.GetFollow() &&
+ mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
+ {
+ SwLayouter::InsertFrmNotToWrap(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ SwLayouter::RemoveMovedFwdFrm(
+ *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
+ mrAnchorTxtFrm );
+ }
+ }
+
+ return bSuccess;
+}
+
+void SwObjectFormatterTxtFrm::_InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj )
+{
+ // invalidate all previous objects, whose wrapping influence on the object
+ // positioning is <NONE_CONCURRENT_POSIITIONED>.
+ // Note: list of objects at anchor frame is sorted by this property.
+ if ( _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
+ {
+ const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
+ if ( pObjs )
+ {
+ // determine start index
+ sal_Int32 i = pObjs->ListPosOf( _rAnchoredObj ) - 1;
+ for ( ; i >= 0; --i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) ==
+ // #i35017# - constant name has changed
+ text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
+ {
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+ }
+ }
+ }
+}
+
+void SwObjectFormatterTxtFrm::_InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
+ const bool _bInclObj )
+{
+ if ( _bInclObj )
+ {
+ _rAnchoredObj.InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+
+ const SwSortedObjs* pObjs = GetPageFrm().GetSortedObjs();
+ if ( pObjs )
+ {
+ // determine start index
+ sal_uInt32 i = pObjs->ListPosOf( _rAnchoredObj ) + 1;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ }
+ }
+}
+
+SwAnchoredObject* SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(
+ const sal_Int16 _nWrapInfluenceOnPosition,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow )
+{
+ // #i35017# - constant names have changed
+ OSL_ENSURE( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
+ _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
+ "<SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(..)> - invalid value for parameter <_nWrapInfluenceOnPosition>" );
+
+ SwAnchoredObject* pRetAnchoredObj = 0L;
+
+ sal_uInt32 i = 0L;
+ for ( ; i < CountOfCollected(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = GetCollectedObj(i);
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() &&
+ pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
+ // #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ GetWrapInfluenceOnObjPos( true ) == _nWrapInfluenceOnPosition )
+ {
+ // #i26945# - use new method <_CheckMovedFwdCondition(..)>
+ // #i43913#
+ // #i58182# - consider new method signature
+ if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( i ),
+ GetPgNumOfCollected( i ),
+ IsCollectedAnchoredAtMaster( i ),
+ _noToPageNum, _boInFollow ) )
+ {
+ pRetAnchoredObj = pAnchoredObj;
+ break;
+ }
+ }
+ }
+
+ return pRetAnchoredObj;
+}
+
+// #i58182#
+// - replace private method by corresponding static public method
+bool SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
+ SwAnchoredObject& _rAnchoredObj,
+ const sal_uInt32 _nFromPageNum,
+ const bool _bAnchoredAtMasterBeforeFormatAnchor,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow )
+{
+ bool bAnchorIsMovedForward( false );
+
+ SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor )
+ {
+ const sal_uInt32 nPageNum = pPageFrmOfAnchor->GetPhyPageNum();
+ if ( nPageNum > _nFromPageNum )
+ {
+ _noToPageNum = nPageNum;
+ // Handling of special case:
+ // If anchor frame is move forward into a follow flow row,
+ // <_noToPageNum> is set to <_nFromPageNum + 1>, because it is
+ // possible that the anchor page frame isn't valid, because the
+ // page distance between master row and follow flow row is greater
+ // than 1.
+ if ( _noToPageNum > (_nFromPageNum + 1) )
+ {
+ SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
+ if ( pAnchorFrm->IsInTab() &&
+ pAnchorFrm->IsInFollowFlowRow() )
+ {
+ _noToPageNum = _nFromPageNum + 1;
+ }
+ }
+ bAnchorIsMovedForward = true;
+ }
+ }
+ // #i26945# - check, if an at-paragraph|at-character
+ // anchored object is now anchored at a follow text frame, which will be
+ // on the next page. Also check, if an at-character anchored object
+ // is now anchored at a text frame, which is in a follow flow row,
+ // which will be on the next page.
+ if ( !bAnchorIsMovedForward &&
+ _bAnchoredAtMasterBeforeFormatAnchor &&
+ ((_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) ||
+ (_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_PARA)))
+ {
+ SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
+ OSL_ENSURE( pAnchorFrm->IsTxtFrm(),
+ "<SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..) - wrong type of anchor frame>" );
+ SwTxtFrm* pAnchorTxtFrm = static_cast<SwTxtFrm*>(pAnchorFrm);
+ bool bCheck( false );
+ if ( pAnchorTxtFrm->IsFollow() )
+ {
+ bCheck = true;
+ }
+ else if( pAnchorTxtFrm->IsInTab() )
+ {
+ const SwRowFrm* pMasterRow = pAnchorTxtFrm->IsInFollowFlowRow();
+ if ( pMasterRow &&
+ pMasterRow->FindPageFrm() == pPageFrmOfAnchor )
+ {
+ bCheck = true;
+ }
+ }
+ if ( bCheck )
+ {
+ // check, if found text frame will be on the next page
+ // by checking, if it's in a column, which has no next.
+ SwFrm* pColFrm = pAnchorTxtFrm->FindColFrm();
+ while ( pColFrm && !pColFrm->GetNext() )
+ {
+ pColFrm = pColFrm->FindColFrm();
+ }
+ if ( !pColFrm || !pColFrm->GetNext() )
+ {
+ _noToPageNum = _nFromPageNum + 1;
+ bAnchorIsMovedForward = true;
+ // #i43913#
+ _boInFollow = true;
+ }
+ }
+ }
+
+ return bAnchorIsMovedForward;
+}
+
+// #i40140# - helper method to format layout frames used by
+// method <SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()>
+// #i44049# - format till a certain lower frame, if provided.
+void lcl_FormatCntntOfLayoutFrm( SwLayoutFrm* pLayFrm,
+ SwFrm* pLastLowerFrm = 0L )
+{
+ SwFrm* pLowerFrm = pLayFrm->GetLower();
+ while ( pLowerFrm )
+ {
+ // #i44049#
+ if ( pLastLowerFrm && pLowerFrm == pLastLowerFrm )
+ {
+ break;
+ }
+ if ( pLowerFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pLowerFrm),
+ pLastLowerFrm );
+ else
+ pLowerFrm->Calc();
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+
+/** method to format given anchor text frame and its previous frames
+
+ #i56300#
+ Usage: Needed to check, if the anchor text frame is moved forward
+ due to the positioning and wrapping of its anchored objects, and
+ to format the frames, which have become invalid due to the anchored
+ object formatting in the iterative object positioning algorithm
+*/
+void SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm )
+{
+ // #i47014# - no format of section and previous columns
+ // for follow text frames.
+ if ( !_rAnchorTxtFrm.IsFollow() )
+ {
+ // if anchor frame is directly inside a section, format this section and
+ // its previous frames.
+ // Note: It's a very simple format without formatting objects.
+ if ( _rAnchorTxtFrm.IsInSct() )
+ {
+ SwFrm* pSectFrm = _rAnchorTxtFrm.GetUpper();
+ while ( pSectFrm )
+ {
+ if ( pSectFrm->IsSctFrm() || pSectFrm->IsCellFrm() )
+ {
+ break;
+ }
+ pSectFrm = pSectFrm->GetUpper();
+ }
+ if ( pSectFrm && pSectFrm->IsSctFrm() )
+ {
+ // #i44049#
+ _rAnchorTxtFrm.LockJoin();
+ SwFrm* pFrm = pSectFrm->GetUpper()->GetLower();
+ // #i49605# - section frame could move forward
+ // by the format of its previous frame.
+ // Thus, check for valid <pFrm>.
+ while ( pFrm && pFrm != pSectFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
+ else
+ pFrm->Calc();
+
+ pFrm = pFrm->GetNext();
+ }
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pSectFrm),
+ &_rAnchorTxtFrm );
+ // #i44049#
+ _rAnchorTxtFrm.UnlockJoin();
+ }
+ }
+
+ // #i40140# - if anchor frame is inside a column,
+ // format the content of the previous columns.
+ // Note: It's a very simple format without formatting objects.
+ SwFrm* pColFrmOfAnchor = _rAnchorTxtFrm.FindColFrm();
+ if ( pColFrmOfAnchor )
+ {
+ // #i44049#
+ _rAnchorTxtFrm.LockJoin();
+ SwFrm* pColFrm = pColFrmOfAnchor->GetUpper()->GetLower();
+ while ( pColFrm != pColFrmOfAnchor )
+ {
+ SwFrm* pFrm = pColFrm->GetLower();
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
+ else
+ pFrm->Calc();
+
+ pFrm = pFrm->GetNext();
+ }
+
+ pColFrm = pColFrm->GetNext();
+ }
+ // #i44049#
+ _rAnchorTxtFrm.UnlockJoin();
+ }
+ }
+
+ // format anchor frame - format of its follow not needed
+ // #i43255# - forbid follow format, only if anchor text
+ // frame is in table
+ if ( _rAnchorTxtFrm.IsInTab() )
+ {
+ SwForbidFollowFormat aForbidFollowFormat( _rAnchorTxtFrm );
+ _rAnchorTxtFrm.Calc();
+ }
+ else
+ {
+ _rAnchorTxtFrm.Calc();
+ }
+}
+
+/** method to format the anchor frame for checking of the move forward condition
+
+ #i40141#
+*/
+void SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()
+{
+ SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( mrAnchorTxtFrm );
+}
+
+/** method to determine if at least one anchored object has state
+ <temporarly consider wrapping style influence> set.
+*/
+bool SwObjectFormatterTxtFrm::_AtLeastOneObjIsTmpConsiderWrapInfluence()
+{
+ bool bRet( false );
+
+ const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
+ if ( pObjs && pObjs->Count() > 1 )
+ {
+ sal_uInt32 i = 0;
+ for ( ; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformattertxtfrm.hxx b/sw/source/core/layout/objectformattertxtfrm.hxx
new file mode 100644
index 000000000000..3d526f9dd214
--- /dev/null
+++ b/sw/source/core/layout/objectformattertxtfrm.hxx
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJECTFORMATTERTXTFRM_HXX
+#define _OBJECTFORMATTERTXTFRM_HXX
+
+#include <objectformatter.hxx>
+#include <sal/types.h>
+
+class SwTxtFrm;
+
+// -----------------------------------------------------------------------------
+// #i28701#
+// Format floating screen objects, which are anchored at a given anchor text frame
+// and registered at the given page frame.
+// -----------------------------------------------------------------------------
+class SwObjectFormatterTxtFrm : public SwObjectFormatter
+{
+ private:
+ // anchor text frame
+ SwTxtFrm& mrAnchorTxtFrm;
+
+ // 'master' anchor text frame
+ SwTxtFrm* mpMasterAnchorTxtFrm;
+
+ SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwTxtFrm* _pMasterAnchorTxtFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to invalidate objects, anchored previous to given object at
+ the anchor text frame
+
+ @param _rAnchoredObj
+ reference to anchored object - objects, anchored previous to
+ this one will be invalidated.
+ */
+ void _InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj );
+
+ /** method to invalidate objects, anchored after the given object at
+ the page frame
+
+ @param _rAnchoredObj
+ reference to anchored object - objects, anchored after this one will
+ be invalidated.
+
+ @param _bInclObj
+ boolean indicates, if given anchored object <_rAnchoredObj> also have
+ to be invalidated.
+ */
+ void _InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
+ const bool _bInclObj );
+
+ /** method to determine first anchored object, whose 'anchor is moved
+ forward'.
+
+ 'anchor (of an object) is moved forward', if the anchor frame
+ respectively the anchor character of the object isn't on the
+ proposed page frame. Instead its on a following page
+
+ #i26945# - For at-character anchored objects,
+ it has also to be checked, if the anchor character is in a follow
+ text frame, which would move to the next page.
+
+ #i43913# - add output parameter <_boInFollow>
+
+ @param _nWrapInfluenceOnPosition
+ input parameter - only object with this given wrapping style
+ influence are investigated.
+
+ @param _nFromPageNum
+ input parameter - number of page frame, the 'anchor' should be
+
+ @param _noToPageNum
+ output parameter - number of page frame, the 'anchor' of the returned
+ anchored object is.
+
+ @param _boInFollow
+ output parameter - boolean, indicating that anchor text frame is
+ currently on the same page, but it's a follow of in a follow row,
+ which will move forward. value only relevant, if method returns
+ an anchored object
+
+ @return SwAnchoredObject*
+ anchored object with a 'moved forward anchor'. If NULL, no such
+ anchored object is found.
+ */
+ SwAnchoredObject* _GetFirstObjWithMovedFwdAnchor(
+ const sal_Int16 _nWrapInfluenceOnPosition,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow );
+
+ /** method to format the anchor frame for checking of the move forward condition
+
+ #i40141#
+ */
+ void _FormatAnchorFrmForCheckMoveFwd();
+
+ /** method to determine if at least one anchored object has state
+ <temporarly consider wrapping style influence> set.
+ */
+ bool _AtLeastOneObjIsTmpConsiderWrapInfluence();
+
+ protected:
+
+ virtual SwFrm& GetAnchorFrm();
+
+ public:
+ virtual ~SwObjectFormatterTxtFrm();
+
+ // #i40147# - add parameter <_bCheckForMovedFwd>.
+ virtual bool DoFormatObj( SwAnchoredObject& _rAnchoredObj,
+ const bool _bCheckForMovedFwd = false );
+ virtual bool DoFormatObjs();
+
+ /** method to create an instance of <SwObjectFormatterTxtFrm> is
+ necessary.
+ */
+ static SwObjectFormatterTxtFrm* CreateObjFormatter(
+ SwTxtFrm& _rAnchorTxtFrm,
+ const SwPageFrm& _rPageFrm,
+ SwLayAction* _pLayAction );
+
+ /** method to format given anchor text frame and its previous frames
+
+ #i56300#
+ Usage: Needed to check, if the anchor text frame is moved forward
+ due to the positioning and wrapping of its anchored objects, and
+ to format the frames, which have become invalid due to the anchored
+ object formatting in the iterative object positioning algorithm
+
+ @param _rAnchorTxtFrm
+ input parameter - reference to anchor text frame, which has to be
+ formatted including its previous frames of the page.
+ */
+ static void FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm );
+
+ /** method to check the conditions, if 'anchor is moved forward'
+
+ #i26945#
+ #i43913# - add output parameter <_boInFollow>
+ #i58182# - replace method by a corresponding static
+ method, because it's needed for the iterative positioning algorithm.
+
+ @param _rAnchoredObj
+ input parameter - anchored object, for which the condition has to checked.
+
+ @param _nFromPageNum
+ input parameter - number of the page, on which the check is performed
+
+ @param _bAnchoredAtMasterBeforeFormatAnchor
+ input parameter - boolean indicating, that the given anchored object
+ was anchored at the master frame before the anchor frame has been
+ formatted.
+
+ @param _noToPageNum
+ output parameter - number of page frame, the 'anchor' of the returned
+ anchored object is.
+
+ @param _boInFollow
+ output parameter - boolean, indicating that anchor text frame is
+ currently on the same page, but it's a follow of in a follow row,
+ which will move forward. value only relevant, if method return <true>.
+
+ @return boolean
+ indicating, if 'anchor is moved forward'
+ */
+ static bool CheckMovedFwdCondition( SwAnchoredObject& _rAnchoredObj,
+ const sal_uInt32 _nFromPageNum,
+ const bool _bAnchoredAtMasterBeforeFormatAnchor,
+ sal_uInt32& _noToPageNum,
+ bool& _boInFollow );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objstmpconsiderwrapinfl.cxx b/sw/source/core/layout/objstmpconsiderwrapinfl.cxx
new file mode 100644
index 000000000000..1c32c9c75f26
--- /dev/null
+++ b/sw/source/core/layout/objstmpconsiderwrapinfl.cxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <objstmpconsiderwrapinfl.hxx>
+#include <anchoredobject.hxx>
+
+SwObjsMarkedAsTmpConsiderWrapInfluence::SwObjsMarkedAsTmpConsiderWrapInfluence()
+{
+}
+
+SwObjsMarkedAsTmpConsiderWrapInfluence::~SwObjsMarkedAsTmpConsiderWrapInfluence()
+{
+ Clear();
+}
+
+void SwObjsMarkedAsTmpConsiderWrapInfluence::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+
+ bool bAlreadyInserted( false );
+ std::vector< SwAnchoredObject* >::const_iterator aIter = maObjsTmpConsiderWrapInfl.begin();
+ for ( ; aIter != maObjsTmpConsiderWrapInfl.end(); ++aIter )
+ {
+ const SwAnchoredObject* pAnchoredObj = *(aIter);
+ if ( pAnchoredObj == &_rAnchoredObj )
+ {
+ bAlreadyInserted = true;
+ break;
+ }
+ }
+
+ if ( !bAlreadyInserted )
+ {
+ maObjsTmpConsiderWrapInfl.push_back( &_rAnchoredObj );
+ }
+}
+
+void SwObjsMarkedAsTmpConsiderWrapInfluence::Clear()
+{
+ while ( maObjsTmpConsiderWrapInfl.size() )
+ {
+ SwAnchoredObject* pAnchoredObj = maObjsTmpConsiderWrapInfl.back();
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ pAnchoredObj->SetClearedEnvironment( false );
+
+ maObjsTmpConsiderWrapInfl.pop_back();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objstmpconsiderwrapinfl.hxx b/sw/source/core/layout/objstmpconsiderwrapinfl.hxx
new file mode 100644
index 000000000000..f5fd89b3b435
--- /dev/null
+++ b/sw/source/core/layout/objstmpconsiderwrapinfl.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _OBJSTMPCONSIDERWRAPINFL_HXX
+#define _OBJSTMPCONSIDERWRAPINFL_HXX
+
+#include <vector>
+
+class SwAnchoredObject;
+
+class SwObjsMarkedAsTmpConsiderWrapInfluence
+{
+ private:
+ std::vector< SwAnchoredObject* > maObjsTmpConsiderWrapInfl;
+
+ public:
+ SwObjsMarkedAsTmpConsiderWrapInfluence();
+ ~SwObjsMarkedAsTmpConsiderWrapInfluence();
+
+ void Insert( SwAnchoredObject& _rAnchoredObj );
+ void Clear();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx
new file mode 100644
index 000000000000..aa7aa23e02c0
--- /dev/null
+++ b/sw/source/core/layout/pagechg.cxx
@@ -0,0 +1,2454 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <ndole.hxx>
+#include <docary.hxx>
+#include <svl/itemiter.hxx>
+#include <fmtfsize.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <fmtanchr.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtfordr.hxx>
+#include <fmtfld.hxx>
+#include <fmtornt.hxx>
+#include <ftninfo.hxx>
+#include <tgrditem.hxx>
+#include <viewopt.hxx>
+#include <docsh.hxx>
+
+#include "viewimp.hxx"
+#include "viewopt.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+#include "doc.hxx"
+#include "fesh.hxx"
+#include "dview.hxx"
+#include "dflyobj.hxx"
+#include "dcontact.hxx"
+#include "frmtool.hxx"
+#include "fldbas.hxx"
+#include "hints.hxx"
+#include "swtable.hxx"
+
+#include "ftnidx.hxx"
+#include "bodyfrm.hxx"
+#include "ftnfrm.hxx"
+#include "tabfrm.hxx"
+#include "txtfrm.hxx"
+#include "layact.hxx"
+#include "flyfrms.hxx"
+#include "htmltbl.hxx"
+#include "pagedesc.hxx"
+#include "poolfmt.hxx"
+#include <editeng/frmdiritem.hxx>
+#include <swfntcch.hxx> // SwFontAccess
+#include <sortedobjs.hxx>
+#include <switerator.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwBodyFrm::SwBodyFrm()
+|*
+|*************************************************************************/
+SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
+ SwLayoutFrm( pFmt, pSib )
+{
+ nType = FRMC_BODY;
+}
+
+/*************************************************************************
+|*
+|* SwBodyFrm::Format()
+|*
+|*************************************************************************/
+void SwBodyFrm::Format( const SwBorderAttrs * )
+{
+ //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes
+ //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen.
+ //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea
+ //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber
+ //Vorsicht ist die Mutter der Robustheit).
+ //Die PrtArea ist stets so gross wie der Frm itself.
+
+ if ( !bValidSize )
+ {
+ SwTwips nHeight = GetUpper()->Prt().Height();
+ SwTwips nWidth = GetUpper()->Prt().Width();
+ const SwFrm *pFrm = GetUpper()->Lower();
+ do
+ {
+ if ( pFrm != this )
+ {
+ if( pFrm->IsVertical() )
+ nWidth -= pFrm->Frm().Width();
+ else
+ nHeight -= pFrm->Frm().Height();
+ }
+ pFrm = pFrm->GetNext();
+ } while ( pFrm );
+ if ( nHeight < 0 )
+ nHeight = 0;
+ Frm().Height( nHeight );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() )
+ Frm().Pos().X() += Frm().Width() - nWidth;
+ Frm().Width( nWidth );
+ }
+
+ sal_Bool bNoGrid = sal_True;
+ if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() )
+ {
+ GETGRID( ((SwPageFrm*)GetUpper()) )
+ if( pGrid )
+ {
+ bNoGrid = sal_False;
+ long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
+ SWRECTFN( this )
+ long nSize = (Frm().*fnRect->fnGetWidth)();
+ long nBorder = 0;
+ if( GRID_LINES_CHARS == pGrid->GetGridType() )
+ {
+ //for textgrid refactor
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ nBorder = nSize % (GETGRIDWIDTH(pGrid, pDoc));
+ nSize -= nBorder;
+ nBorder /= 2;
+ }
+ (Prt().*fnRect->fnSetPosX)( nBorder );
+ (Prt().*fnRect->fnSetWidth)( nSize );
+
+ // Height of body frame:
+ nBorder = (Frm().*fnRect->fnGetHeight)();
+
+ // Number of possible lines in area of body frame:
+ long nNumberOfLines = nBorder / nSum;
+ if( nNumberOfLines > pGrid->GetLines() )
+ nNumberOfLines = pGrid->GetLines();
+
+ // Space required for nNumberOfLines lines:
+ nSize = nNumberOfLines * nSum;
+ nBorder -= nSize;
+ nBorder /= 2;
+
+ // #i21774# Footnotes and centering the grid does not work together:
+ const bool bAdjust = 0 == ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()->
+ GetFtnIdxs().Count();
+
+ (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 );
+ (Prt().*fnRect->fnSetHeight)( nSize );
+ }
+ }
+ if( bNoGrid )
+ {
+ Prt().Pos().X() = Prt().Pos().Y() = 0;
+ Prt().Height( Frm().Height() );
+ Prt().Width( Frm().Width() );
+ }
+ bValidSize = bValidPrtArea = sal_True;
+}
+
+void SwBodyFrm::Paint( const SwRect& rRect, const SwPrintData* ) const
+{
+#if OSL_DEBUG_LAYOUT > 1
+ // Paint a red border around the SwBodyFrm in debug mode
+ ViewShell *pSh = GetShell();
+ OutputDevice* pOut = pSh->GetOut();
+ pOut->Push();
+ pOut->SetLineColor(Color(255, 0, 0));
+ pOut->SetFillColor(COL_TRANSPARENT);
+ SwRect aRect = Frm();
+ pOut->DrawRect(aRect.SVRect());
+ pOut->Pop();
+#endif
+ SwLayoutFrm::Paint(rRect);
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SwPageFrm(), ~SwPageFrm()
+|*
+|*************************************************************************/
+SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwPageDesc *pPgDsc ) :
+ SwFtnBossFrm( pFmt, pSib ),
+ pSortedObjs( 0 ),
+ pDesc( pPgDsc ),
+ nPhyPageNum( 0 ),
+ // OD 2004-05-17 #i28701#
+ mbLayoutInProgress( false )
+{
+ SetDerivedVert( sal_False );
+ SetDerivedR2L( sal_False );
+ if( pDesc )
+ {
+ bHasGrid = sal_True;
+ GETGRID( this )
+ if( !pGrid )
+ bHasGrid = sal_False;
+ }
+ else
+ bHasGrid = sal_False;
+ SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
+ pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
+ nType = FRMC_PAGE;
+ bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True;
+ bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False;
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if ( bBrowseMode )
+ {
+ Frm().Height( 0 );
+ long nWidth = pSh->VisArea().Width();
+ if ( !nWidth )
+ nWidth = 5000L; //aendert sich sowieso
+ Frm().Width ( nWidth );
+ }
+ else
+ Frm().SSize( pFmt->GetFrmSize().GetSize() );
+
+ //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
+ //eine Leerseite bin.
+ SwDoc *pDoc = pFmt->GetDoc();
+ if ( sal_False == (bEmptyPage = pFmt == pDoc->GetEmptyPageFmt()) )
+ {
+ bEmptyPage = sal_False;
+ Calc(); //Damit die PrtArea stimmt.
+ SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this );
+ pBodyFrm->ChgSize( Prt().SSize() );
+ pBodyFrm->Paste( this );
+ pBodyFrm->Calc(); //Damit die Spalten korrekt
+ //eingesetzt werden koennen.
+ pBodyFrm->InvalidatePos();
+
+ if ( bBrowseMode )
+ _InvalidateSize(); //Alles nur gelogen
+
+ //Header/Footer einsetzen, nur rufen wenn aktiv.
+ if ( pFmt->GetHeader().IsActive() )
+ PrepareHeader();
+ if ( pFmt->GetFooter().IsActive() )
+ PrepareFooter();
+
+ const SwFmtCol &rCol = pFmt->GetCol();
+ if ( rCol.GetNumCols() > 1 )
+ {
+ const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein
+ //Old-Wert hereingereicht wird.
+ pBodyFrm->ChgColumns( aOld, rCol );
+ }
+ }
+}
+
+SwPageFrm::~SwPageFrm()
+{
+ //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
+ //(Basisklasse SwFrm)
+ if ( pSortedObjs )
+ {
+ //Objekte koennen (warum auch immer) auch an Seiten verankert sein,
+ //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen
+ //Speicher zugegriffen.
+ for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
+ pAnchoredObj->SetPageFrm( 0L );
+ }
+ delete pSortedObjs;
+ pSortedObjs = 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
+ }
+
+ //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
+ if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if( pDoc && !pDoc->IsInDtor() )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ {
+ SwViewImp *pImp = pSh->Imp();
+ pImp->SetFirstVisPageInvalid();
+ if ( pImp->IsAction() )
+ pImp->GetLayAction().SetAgain();
+ // OD 12.02.2003 #i9719#, #105645# - retouche area of page
+ // including border and shadow area.
+ const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ SwRect aRetoucheRect;
+ SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
+ pSh->AddPaintRect( aRetoucheRect );
+ }
+ }
+ }
+}
+
+
+void SwPageFrm::CheckGrid( sal_Bool bInvalidate )
+{
+ sal_Bool bOld = bHasGrid;
+ bHasGrid = sal_True;
+ GETGRID( this )
+ bHasGrid = 0 != pGrid;
+ if( bInvalidate || bOld != bHasGrid )
+ {
+ SwLayoutFrm* pBody = FindBodyCont();
+ if( pBody )
+ {
+ pBody->InvalidatePrt();
+ SwCntntFrm* pFrm = pBody->ContainsCntnt();
+ while( pBody->IsAnLower( pFrm ) )
+ {
+ ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR );
+ pFrm = pFrm->GetNextCntntFrm();
+ }
+ }
+ SetCompletePaint();
+ }
+}
+
+
+void SwPageFrm::CheckDirection( sal_Bool bVert )
+{
+ sal_uInt16 nDir =
+ ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
+ if( bVert )
+ {
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bVertLR = 0;
+ bVertical = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if(FRMDIR_VERT_TOP_RIGHT == nDir)
+ bVertLR = 0;
+ else if(FRMDIR_VERT_TOP_LEFT==nDir)
+ bVertLR = 1;
+ }
+ }
+
+ bReverse = 0;
+ bInvalidVert = 0;
+ }
+ else
+ {
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ bInvalidR2L = 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PreparePage()
+|*
+|* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert
+|* generischen Cntnt
+|*
+|*************************************************************************/
+void MA_FASTCALL lcl_FormatLay( SwLayoutFrm *pLay )
+{
+ //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
+
+ SwFrm *pTmp = pLay->Lower();
+ //Erst die untergeordneten
+ while ( pTmp )
+ {
+ if ( pTmp->GetType() & 0x00FF )
+ ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
+ pTmp = pTmp->GetNext();
+ }
+ pLay->Calc();
+}
+
+void MA_FASTCALL lcl_MakeObjs( const SwSpzFrmFmts &rTbl, SwPageFrm *pPage )
+{
+ //Anlegen bzw. registrieren von Flys und Drawobjekten.
+ //Die Formate stehen in der SpzTbl (vom Dokument).
+ //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet.
+
+ for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ {
+ SdrObject *pSdrObj;
+ SwFrmFmt *pFmt = rTbl[i];
+ const SwFmtAnchor &rAnch = pFmt->GetAnchor();
+ if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
+ {
+ if( rAnch.GetCntntAnchor() )
+ {
+ if (FLY_AT_PAGE == rAnch.GetAnchorId())
+ {
+ SwFmtAnchor aAnch( rAnch );
+ aAnch.SetAnchor( 0 );
+ pFmt->SetFmtAttr( aAnch );
+ }
+ else
+ continue;
+ }
+
+ //Wird ein Rahmen oder ein SdrObject beschrieben?
+ sal_Bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
+ pSdrObj = 0;
+ if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
+ {
+ OSL_FAIL( "DrawObject not found." );
+ pFmt->GetDoc()->DelFrmFmt( pFmt );
+ --i;
+ continue;
+ }
+ //Das Objekt kann noch an einer anderen Seite verankert sein.
+ //Z.B. beim Einfuegen einer neuen Seite aufgrund eines
+ //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt
+ //werden.
+ //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen
+ //Seite verankert. Das wird hier automatisch erledigt und braucht
+ //- wenngleich performater machbar - nicht extra codiert werden.
+ SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
+ if ( bSdrObj )
+ {
+ // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
+ SwDrawContact *pContact =
+ static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
+ if ( pSdrObj->ISA(SwDrawVirtObj) )
+ {
+ SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
+ if ( pContact )
+ {
+ pDrawVirtObj->RemoveFromWriterLayout();
+ pDrawVirtObj->RemoveFromDrawingPage();
+ pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
+ }
+ }
+ else
+ {
+ if ( pContact->GetAnchorFrm() )
+ pContact->DisconnectFromLayout( false );
+ pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
+ }
+ }
+ else
+ {
+ SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
+ SwFlyFrm *pFly = aIter.First();
+ if ( pFly)
+ {
+ if( pFly->GetAnchorFrm() )
+ pFly->AnchorFrm()->RemoveFly( pFly );
+ }
+ else
+ pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg, pPg );
+ pPg->AppendFly( pFly );
+ ::RegistFlys( pPg, pFly );
+ }
+ }
+ }
+}
+
+void SwPageFrm::PreparePage( sal_Bool bFtn )
+{
+ SetFtnPage( bFtn );
+
+ // --> OD 2008-01-30 #i82258#
+ // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
+ // the side effect, that the content of page header and footer are formatted.
+ // For this formatting it is needed that the anchored objects are registered
+ // at the <SwPageFrm> instance.
+ // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
+ ::RegistFlys( this, this );
+
+ if ( Lower() )
+ {
+ ::lcl_FormatLay( this );
+ }
+ // <--
+
+ //Flys und DrawObjekte die noch am Dokument bereitstehen.
+ //Fussnotenseiten tragen keine Seitengebundenen Flys!
+ //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig)
+ //stehen wollen, diese werden jedoch von den Leerseiten ignoriert;
+ //sie werden von den Folgeseiten aufgenommen.
+ if ( !bFtn && !IsEmptyPage() )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+
+ if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
+ lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
+ lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
+
+ //Kopf-/Fusszeilen) formatieren.
+ SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
+ while ( pLow )
+ {
+ if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) )
+ {
+ SwCntntFrm *pCntnt = pLow->ContainsCntnt();
+ while ( pCntnt && pLow->IsAnLower( pCntnt ) )
+ {
+ pCntnt->OptCalc(); //Nicht die Vorgaenger
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ }
+ pLow = (SwLayoutFrm*)pLow->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Modify()
+|*
+|*************************************************************************/
+void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ pSh->SetFirstVisPageInvalid();
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ InvalidatePage( this );
+ if ( nInvFlags & 0x01 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x02 )
+ SetCompletePaint();
+ if ( nInvFlags & 0x04 && GetNext() )
+ GetNext()->InvalidatePos();
+ if ( nInvFlags & 0x08 )
+ PrepareHeader();
+ if ( nInvFlags & 0x10 )
+ PrepareFooter();
+ if ( nInvFlags & 0x20 )
+ CheckGrid( nInvFlags & 0x40 );
+ }
+}
+
+void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_FMT_CHG:
+ {
+ //Wenn sich das FrmFmt aendert kann hier einiges passieren.
+ //Abgesehen von den Grossenverhaeltnissen sind noch andere
+ //Dinge betroffen.
+ //1. Spaltigkeit.
+ OSL_ENSURE( pOld && pNew, "FMT_CHG Missing Format." );
+ const SwFmt* pOldFmt = ((SwFmtChg*)pOld)->pChangedFmt;
+ const SwFmt* pNewFmt = ((SwFmtChg*)pNew)->pChangedFmt;
+ OSL_ENSURE( pOldFmt && pNewFmt, "FMT_CHG Missing Format." );
+
+ const SwFmtCol &rOldCol = pOldFmt->GetCol();
+ const SwFmtCol &rNewCol = pNewFmt->GetCol();
+ if( rOldCol != rNewCol )
+ {
+ SwLayoutFrm *pB = FindBodyCont();
+ OSL_ENSURE( pB, "Seite ohne Body." );
+ pB->ChgColumns( rOldCol, rNewCol );
+ rInvFlags |= 0x20;
+ }
+
+ //2. Kopf- und Fusszeilen.
+ const SwFmtHeader &rOldH = pOldFmt->GetHeader();
+ const SwFmtHeader &rNewH = pNewFmt->GetHeader();
+ if( rOldH != rNewH )
+ rInvFlags |= 0x08;
+
+ const SwFmtFooter &rOldF = pOldFmt->GetFooter();
+ const SwFmtFooter &rNewF = pNewFmt->GetFooter();
+ if( rOldF != rNewF )
+ rInvFlags |= 0x10;
+ CheckDirChange();
+ }
+ /* kein break hier */
+ case RES_FRM_SIZE:
+ {
+ const SwRect aOldPageFrmRect( Frm() );
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ bValidSize = sal_False;
+ // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
+ // Calculation of the page is not necessary, because its size is
+ // is invalidated here and further invalidation is done in the
+ // calling method <SwPageFrm::Modify(..)> and probably by calling
+ // <SwLayoutFrm::Modify(..)> at the end.
+ // It can also causes inconsistences, because the lowers are
+ // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
+ // a next page is called. This is performed on the switch to the
+ // online layout.
+ //MakeAll();
+ }
+ else
+ {
+ const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ?
+ ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() :
+ (const SwFmtFrmSize&)*pNew;
+
+ Frm().Height( Max( rSz.GetHeight(), long(MINLAY) ) );
+ Frm().Width ( Max( rSz.GetWidth(), long(MINLAY) ) );
+
+ // PAGES01
+ if ( GetUpper() )
+ static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
+ }
+ //Window aufraeumen.
+ if( pSh && pSh->GetWin() && aOldPageFrmRect.HasArea() )
+ {
+ // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
+ // page frame for determine 'old' rectangle - it's used for invalidating.
+ const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
+ SwRect aOldRectWithBorderAndShadow;
+ SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow,
+ IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
+ pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
+ }
+ rInvFlags |= 0x03;
+ if ( aOldPageFrmRect.Height() != Frm().Height() )
+ rInvFlags |= 0x04;
+ }
+ break;
+
+ case RES_COL:
+ {
+ SwLayoutFrm *pB = FindBodyCont();
+ OSL_ENSURE( pB, "Seite ohne Body." );
+ pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ rInvFlags |= 0x22;
+ }
+ break;
+
+ case RES_HEADER:
+ rInvFlags |= 0x08;
+ break;
+
+ case RES_FOOTER:
+ rInvFlags |= 0x10;
+ break;
+ case RES_TEXTGRID:
+ rInvFlags |= 0x60;
+ break;
+
+ case RES_PAGEDESC_FTNINFO:
+ //Die derzeit einzig sichere Methode:
+ ((SwRootFrm*)GetUpper())->SetSuperfluous();
+ SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() );
+ if ( !GetMaxFtnHeight() )
+ SetMaxFtnHeight( LONG_MAX );
+ SetColMaxFtnHeight();
+ //Hier wird die Seite ggf. zerstoert!
+ ((SwRootFrm*)GetUpper())->RemoveFtns( 0, sal_False, sal_True );
+ break;
+ case RES_FRAMEDIR :
+ CheckDirChange();
+ break;
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+ // erfrage vom Modify Informationen
+sal_Bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
+ {
+ // es gibt einen PageFrm also wird er benutzt
+ return sal_False;
+ }
+ return sal_True; // weiter suchen
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::SetPageDesc()
+|*
+|*************************************************************************/
+void SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt )
+{
+ pDesc = pNew;
+ if ( pFmt )
+ SetFrmFmt( pFmt );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::FindPageDesc()
+|*
+|* Beschreibung Der richtige PageDesc wird bestimmt:
+|* 0. Vom Dokument bei Fussnotenseiten und Endnotenseiten
+|* 1. vom ersten BodyCntnt unterhalb der Seite.
+|* 2. vom PageDesc der vorstehenden Seite.
+|* 3. bei Leerseiten vom PageDesc der vorigen Seite.
+|* 3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt.
+|* 4. es ist der Default-PageDesc sonst.
+|* 5. Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im
+|* Dokument oder Standard (der 0-te) wenn der erste Absatz keinen
+|* wuenscht.
+|* (6. Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.)
+|*
+|*************************************************************************/
+SwPageDesc *SwPageFrm::FindPageDesc()
+{
+ //0.
+ if ( IsFtnPage() )
+ {
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ if ( IsEndNotePage() )
+ return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
+ else
+ return pDoc->GetFtnInfo().GetPageDesc( *pDoc );
+ }
+
+ //6.
+ //if ( GetFmt()->GetDoc()->IsHTMLMode() )
+ // return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML );
+
+ SwPageDesc *pRet = 0;
+
+ //5.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ {
+ SwCntntFrm *pFrm = GetUpper()->ContainsCntnt();
+ while ( !pFrm->IsInDocBody() )
+ pFrm = pFrm->GetNextCntntFrm();
+ SwFrm *pFlow = pFrm;
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
+ if ( !pRet )
+ pRet = &GetFmt()->GetDoc()->_GetPageDesc( 0 );
+ return pRet;
+ }
+
+ SwFrm *pFlow = FindFirstBodyCntnt();
+ if ( pFlow && pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+
+ //1.
+ if ( pFlow )
+ {
+ SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
+ if ( !pTmp->IsFollow() )
+ pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
+ }
+
+ //3. und 3.1
+ if ( !pRet && IsEmptyPage() )
+ // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
+ // the same page description as its prev, just like after construction
+ // of the empty page.
+ pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() :
+ GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0;
+
+ //2.
+ if ( !pRet )
+ pRet = GetPrev() ?
+ ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
+
+ //4.
+ if ( !pRet )
+ pRet = (SwPageDesc*)&(const_cast<const SwDoc *>(GetFmt()->GetDoc())
+ ->GetPageDesc( 0 ));
+
+
+ OSL_ENSURE( pRet, "Kein Descriptor gefunden." );
+ return pRet;
+}
+
+//Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
+void AdjustSizeChgNotify( SwRootFrm *pRoot )
+{
+ const sal_Bool bOld = pRoot->IsSuperfluous();
+ pRoot->bCheckSuperfluous = sal_False;
+ ViewShell *pSh = pRoot->GetCurrShell();
+ if ( pSh )
+ {
+ do
+ {
+ if( pRoot == pSh->GetLayout() )
+ {
+ pSh->SizeChgNotify();
+ pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );
+ }
+ pSh = (ViewShell*)pSh->GetNext();
+ } while ( pSh != pRoot->GetCurrShell() );
+ }
+ pRoot->bCheckSuperfluous = bOld;
+}
+
+
+inline void SetLastPage( SwPageFrm *pPage )
+{
+ ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Cut()
+|*
+|*************************************************************************/
+void SwPageFrm::Cut()
+{
+ // PAGES01
+ //AdjustRootSize( CHG_CUTPAGE, 0 );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !IsEmptyPage() )
+ {
+ if ( GetNext() )
+ GetNext()->InvalidatePos();
+
+ //Flys deren Anker auf anderen Seiten stehen umhaengen.
+ //DrawObjecte spielen hier keine Rolle.
+ if ( GetSortedObjs() )
+ {
+ for ( int i = 0; GetSortedObjs() &&
+ (sal_uInt16)i < GetSortedObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+
+ if ( pAnchoredObj->ISA(SwFlyAtCntFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj);
+ SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ?
+ pFly->AnchorFrm()->FindPageFrm() : 0;
+ if ( pAnchPage && (pAnchPage != this) )
+ {
+ MoveFly( pFly, pAnchPage );
+ --i;
+ pFly->InvalidateSize();
+ pFly->_InvalidatePos();
+ }
+ }
+ // <--
+ }
+ }
+ //Window aufraeumen
+ if ( pSh && pSh->GetWin() )
+ pSh->InvalidateWindows( Frm() );
+ }
+
+ // die Seitennummer der Root runterzaehlen.
+ ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
+ SwPageFrm *pPg = (SwPageFrm*)GetNext();
+ if ( pPg )
+ {
+ while ( pPg )
+ {
+ pPg->DecrPhyPageNum(); //inline --nPhyPageNum
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ }
+ else
+ ::SetLastPage( (SwPageFrm*)GetPrev() );
+
+ SwFrm* pRootFrm = GetUpper();
+
+ // Alle Verbindungen kappen.
+ Remove();
+
+ // PAGES01
+ if ( pRootFrm )
+ static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::Paste()
+|*
+|*************************************************************************/
+void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent->IsRootFrm(), "Parent ist keine Root." );
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ // die Seitennummer am Root hochzaehlen.
+ ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
+ if( GetPrev() )
+ SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
+ else
+ SetPhyPageNum( 1 );
+ SwPageFrm *pPg = (SwPageFrm*)GetNext();
+ if ( pPg )
+ {
+ while ( pPg )
+ {
+ pPg->IncrPhyPageNum(); //inline ++nPhyPageNum
+ pPg->_InvalidatePos();
+ pPg->InvalidateLayout();
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+ }
+ else
+ ::SetLastPage( this );
+
+ if( Frm().Width() != pParent->Prt().Width() )
+ _InvalidateSize();
+
+ InvalidatePos();
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( pSh )
+ pSh->SetFirstVisPageInvalid();
+ // PAGES01
+ getRootFrm()->CheckViewLayout( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::PrepareRegisterChg()
+|*
+|*************************************************************************/
+void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm )
+{
+ pFrm->Prepare( PREP_REGISTER );
+ if( pFrm->GetDrawObjs() )
+ {
+ for( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyInCntFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj);
+ SwCntntFrm *pCnt = pFly->ContainsCntnt();
+ while ( pCnt )
+ {
+ lcl_PrepFlyInCntRegister( pCnt );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ // <--
+ }
+ }
+}
+
+void SwPageFrm::PrepareRegisterChg()
+{
+ SwCntntFrm *pFrm = FindFirstBodyCntnt();
+ while( pFrm )
+ {
+ lcl_PrepFlyInCntRegister( pFrm );
+ pFrm = pFrm->GetNextCntntFrm();
+ if( !IsAnLower( pFrm ) )
+ break;
+ }
+ if( GetSortedObjs() )
+ {
+ for( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFrm = pFly->ContainsCntnt();
+ while ( pFrm )
+ {
+ ::lcl_PrepFlyInCntRegister( pFrm );
+ pFrm = pFrm->GetNextCntntFrm();
+ }
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::CheckPageDescs()
+|*
+|* Beschreibung Prueft alle Seiten ab der uebergebenen, daraufhin,
+|* ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten
+|* aufgespuehrt werden, so wird versucht die Situation moeglichst
+|* einfache zu bereinigen.
+|*
+|*************************************************************************/
+void SwFrm::CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields )
+{
+ OSL_ENSURE( pStart, "Keine Startpage." );
+
+ ViewShell *pSh = pStart->getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+
+ if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
+ {
+ pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
+ return;
+ }
+
+ //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
+ //die Seitenposition an, _ab_ der invalidiert werden soll.
+ SwTwips nDocPos = LONG_MAX;
+
+ SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper();
+ SwDoc* pDoc = pStart->GetFmt()->GetDoc();
+ const sal_Bool bFtns = 0 != pDoc->GetFtnIdxs().Count();
+
+ SwPageFrm *pPage = pStart;
+ if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ while ( pPage )
+ {
+ //gewuenschten PageDesc und FrmFmt festellen.
+ SwPageDesc *pDesc = pPage->FindPageDesc();
+ sal_Bool bCheckEmpty = pPage->IsEmptyPage();
+ sal_Bool bActOdd = pPage->OnRightPage();
+ sal_Bool bOdd = pPage->WannaRightPage();
+ SwFrmFmt *pFmtWish = bOdd ? pDesc->GetRightFmt()
+ : pDesc->GetLeftFmt();
+
+ if ( bActOdd != bOdd ||
+ pDesc != pPage->GetPageDesc() || //falscher Desc
+ ( pFmtWish != pPage->GetFmt() && //falsches Format und
+ ( !pPage->IsEmptyPage() || pFmtWish ) //nicht Leerseite
+ )
+ )
+ {
+ //Wenn wir schon ein Seite veraendern muessen kann das eine
+ //Weile dauern, deshalb hier den WaitCrsr pruefen.
+ if( pImp )
+ pImp->CheckWaitCrsr();
+
+ //Ab hier muessen die Felder invalidiert werden!
+ if ( nDocPos == LONG_MAX )
+ nDocPos = pPage->GetPrev() ?
+ pPage->GetPrev()->Frm().Top() : pPage->Frm().Top();
+
+ //Faelle:
+ //1. Wir haben eine EmptyPage und wollen eine "Normalseite".
+ // ->EmptyPage wegwerfen und weiter mit der naechsten.
+ //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit
+ // anderem Descriptor.
+ // ->Descriptor austauschen.
+ //3. Wir haben eine "Normalseite" und wollen eine EmptyPage.
+ // ->Emptypage einfuegen, nicht aber wenn die Vorseite
+ // bereits eine EmptyPage ist -> 6.
+ //4. Wir haben eine "Normalseite" und wollen eine "Normalseite"
+ // mit anderem Descriptor
+ // ->Descriptor und Format austauschen
+ //5. Wir haben eine "Normalseite" und wollen eine "Normalseite"
+ // mit anderem Format
+ // ->Format austauschen.
+ //6. Wir haben kein Wunschformat erhalten, also nehmen wir das
+ // 'andere' Format (rechts/links) des PageDesc.
+
+ if ( pPage->IsEmptyPage() && ( pFmtWish || //1.
+ ( !bOdd && !pPage->GetPrev() ) ) )
+ {
+ SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
+ pPage->Cut();
+ delete pPage;
+ if ( pStart == pPage )
+ pStart = pTmp;
+ pPage = pTmp;
+ continue;
+ }
+ else if ( pPage->IsEmptyPage() && !pFmtWish && //2.
+ pDesc != pPage->GetPageDesc() )
+ {
+ pPage->SetPageDesc( pDesc, 0 );
+ }
+ else if ( !pPage->IsEmptyPage() && //3.
+ bActOdd != bOdd &&
+ ( ( !pPage->GetPrev() && !bOdd ) ||
+ ( pPage->GetPrev() &&
+ !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ )
+ )
+ {
+ if ( pPage->GetPrev() )
+ pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc();
+ SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pRoot,pDesc);
+ pTmp->Paste( pRoot, pPage );
+ pTmp->PreparePage( sal_False );
+ pPage = pTmp;
+ }
+ else if ( pPage->GetPageDesc() != pDesc ) //4.
+ {
+ SwPageDesc *pOld = pPage->GetPageDesc();
+ pPage->SetPageDesc( pDesc, pFmtWish );
+ if ( bFtns )
+ {
+ //Wenn sich bestimmte Werte der FtnInfo veraendert haben
+ //muss etwas passieren. Wir versuchen den Schaden zu
+ //begrenzen.
+ //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches
+ //ein Problem denkbar, aber das ignorieren wir mit aller Kraft.
+ //Bei Aenderungen hoffen wir mal, dass eine Invalidierung
+ //ausreicht, denn alles andere wuerde viel Kraft kosten.
+ SwFtnContFrm *pCont = pPage->FindFtnCont();
+ if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) )
+ pCont->_InvalidateAll();
+ }
+ }
+ else if ( pFmtWish && pPage->GetFmt() != pFmtWish ) //5.
+ {
+ pPage->SetFrmFmt( pFmtWish );
+ }
+ else if ( !pFmtWish ) //6.
+ {
+ //Format mit verdrehter Logic besorgen.
+ pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
+ if ( pPage->GetFmt() != pFmtWish )
+ pPage->SetFrmFmt( pFmtWish );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "CheckPageDescs, missing solution" );
+ }
+#endif
+ }
+ if ( bCheckEmpty )
+ {
+ //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist.
+ //Obiger Algorithmus kann dies leider nicht feststellen.
+ //Eigentlich muesste die Leerseite einfach praeventiv entfernt
+ //werden; sie wuerde ja ggf. wieder eingefuegt.
+ //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
+ //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
+ //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
+ //Seitennummer manuell.
+ SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
+ if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
+ {
+ //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
+ //Nachfolger, also ist die Leerseite ueberfluessig.
+ SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
+ pPage->Cut();
+ delete pPage;
+ if ( pStart == pPage )
+ pStart = pTmp;
+ pPage = pTmp;
+ continue;
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ pRoot->SetAssertFlyPages();
+ pRoot->AssertPageFlys( pStart );
+
+ if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
+ {
+ SwDocPosUpdate aMsgHnt( nDocPos );
+ pDoc->UpdatePageFlds( &aMsgHnt );
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ //Ein paar Pruefungen muessen schon erlaubt sein.
+
+ //1. Keine zwei EmptyPages hintereinander.
+ //2. Alle PageDescs richtig?
+ sal_Bool bEmpty = sal_False;
+ SwPageFrm *pPg = pStart;
+ while ( pPg )
+ {
+ if ( pPg->IsEmptyPage() )
+ {
+ if ( bEmpty )
+ {
+ OSL_FAIL( "Doppelte Leerseiten." );
+ break; //Einmal reicht.
+ }
+ bEmpty = sal_True;
+ }
+ else
+ bEmpty = sal_False;
+
+//MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
+//moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
+//rechte als folge der ersten, linke als folge der rechten, rechte als
+//folge der linken.
+// OSL_ENSURE( pPg->GetPageDesc() == pPg->FindPageDesc(),
+// "Seite mit falschem Descriptor." );
+
+ pPg = (SwPageFrm*)pPg->GetNext();
+ }
+#endif
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertPage()
+|*
+|*************************************************************************/
+SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn )
+{
+ SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
+ SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
+ SwPageDesc *pDesc = pSibling->GetPageDesc();
+
+ pSibling = (SwPageFrm*)pPrevPage->GetNext();
+ //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
+ sal_Bool bNextOdd = !pPrevPage->OnRightPage();
+ sal_Bool bWishedOdd = bNextOdd;
+
+ //Welcher PageDesc gilt?
+ //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
+ //der Follow vom bereits in der PrevPage gueltigen sonst.
+ pDesc = 0;
+ if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
+ { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
+ pDesc = rDesc.GetPageDesc();
+ if ( rDesc.GetNumOffset() )
+ {
+ bWishedOdd = rDesc.GetNumOffset() % 2 ? sal_True : sal_False;
+ //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
+ pRoot->SetVirtPageNum( sal_True );
+ }
+ }
+ if ( !pDesc )
+ pDesc = pPrevPage->GetPageDesc()->GetFollow();
+
+ OSL_ENSURE( pDesc, "Missing PageDesc" );
+ if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
+ bWishedOdd = !bWishedOdd;
+
+ SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
+ SwFrmFmt *pFmt;
+ sal_Bool bCheckPages = sal_False;
+ //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
+ //Leerseite einfuegen.
+ if( bWishedOdd != bNextOdd )
+ { pFmt = pDoc->GetEmptyPageFmt();
+ SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
+ SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pTmpDesc );
+ pPage->Paste( pRoot, pSibling );
+ pPage->PreparePage( bFtn );
+ //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
+ //Es sei denn, es ist eine Fussnotenseite
+ if ( pSibling && !pSibling->IsFtnPage() &&
+ !pSibling->FindFirstBodyCntnt() )
+ {
+ SwPageFrm *pDel = pSibling;
+ pSibling = (SwPageFrm*)pSibling->GetNext();
+ if ( pDoc->GetFtnIdxs().Count() )
+ pRoot->RemoveFtns( pDel, sal_True );
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ bCheckPages = sal_True;
+ }
+ pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
+ OSL_ENSURE( pFmt, "Descriptor without format." );
+ SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc );
+ pPage->Paste( pRoot, pSibling );
+ pPage->PreparePage( bFtn );
+ //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
+ //Es sei denn es ist eine Fussnotenseite.
+ if ( pSibling && !pSibling->IsFtnPage() &&
+ !pSibling->FindFirstBodyCntnt() )
+ {
+ SwPageFrm *pDel = pSibling;
+ pSibling = (SwPageFrm*)pSibling->GetNext();
+ if ( pDoc->GetFtnIdxs().Count() )
+ pRoot->RemoveFtns( pDel, sal_True );
+ pDel->Cut();
+ delete pDel;
+ }
+ else
+ bCheckPages = sal_True;
+
+ if ( pSibling )
+ {
+ if ( bCheckPages )
+ {
+ CheckPageDescs( pSibling, sal_False );
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
+ {
+ const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
+ if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
+ pImp->GetLayAction().SetCheckPageNumDirect(
+ pSibling->GetPhyPageNum() );
+ return pPage;
+ }
+ }
+ else
+ pRoot->AssertPageFlys( pSibling );
+ }
+
+ //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
+ //die Seitenposition an, _ab_ der invalidiert werden soll.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
+ {
+ SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
+ pDoc->UpdatePageFlds( &aMsgHnt );
+ }
+ return pPage;
+}
+
+sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
+ {
+ return sw::sidebarwindows::SIDEBAR_RIGHT;
+ }
+ else
+ {
+ const bool bLTR = getRootFrm()->IsLeftToRightViewLayout();
+ const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
+ const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
+
+ return bRightSidebar
+ ? sw::sidebarwindows::SIDEBAR_RIGHT
+ : sw::sidebarwindows::SIDEBAR_LEFT;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GrowFrm()
+|*
+|*************************************************************************/
+
+SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ if ( !bTst )
+ Frm().SSize().Height() += nDist;
+ return nDist;
+}
+/*************************************************************************
+|*
+|* SwRootFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
+{
+ OSL_ENSURE( nDist >= 0, "nDist < 0." );
+ OSL_ENSURE( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
+
+ if ( !bTst )
+ Frm().SSize().Height() -= nDist;
+ return nDist;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::RemoveSuperfluous()
+|*
+|* Beschreibung: Entfernung von ueberfluessigen Seiten.
+|* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
+|* Definition: Eine Seite ist genau dann leer, wenn der
+|* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
+|* mindestens ein Fly an der Seite klebt.
+|* Die Seite ist auch dann nicht leer, wenn sie noch eine
+|* Fussnote enthaelt.
+|* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
+|* - einmal fuer die Endnotenseiten.
+|* - und einmal fuer die Seiten des Bodytextes.
+|*
+|*************************************************************************/
+void SwRootFrm::RemoveSuperfluous()
+{
+ if ( !IsSuperfluous() )
+ return;
+ bCheckSuperfluous = sal_False;
+
+ SwPageFrm *pPage = GetLastPage();
+ long nDocPos = LONG_MAX;
+
+ //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
+ //bei der ersten nicht leeren Seite wird die Schleife beendet.
+ do
+ {
+ bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
+ if ( bExistEssentialObjs )
+ {
+ //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
+ //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
+ //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
+ // OD 19.06.2003 #108784# - consider that drawing objects in
+ // header/footer are supported now.
+ bool bOnlySuperfluosObjs = true;
+ SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ // OD 2004-01-19 #110582# - do not consider hidden objects
+ if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
+ pAnchoredObj->GetDrawObj()->GetLayer() ) &&
+ !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
+ {
+ bOnlySuperfluosObjs = false;
+ }
+ // <--
+ }
+ bExistEssentialObjs = !bOnlySuperfluosObjs;
+ }
+
+ // OD 19.06.2003 #108784# - optimization: check first, if essential objects
+ // exists.
+ const SwLayoutFrm* pBody = 0;
+ if ( bExistEssentialObjs ||
+ pPage->FindFtnCont() ||
+ ( 0 != ( pBody = pPage->FindBodyCont() ) &&
+ ( pBody->ContainsCntnt() ||
+ // --> FME 2005-05-18 #i47580#
+ // Do not delete page if there's an empty tabframe
+ // left. I think it might be correct to use ContainsAny()
+ // instead of ContainsCntnt() to cover the empty-table-case,
+ // but I'm not fully sure, since ContainsAny() also returns
+ // SectionFrames. Therefore I prefer to do it the safe way:
+ ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
+ // <--
+ {
+ if ( pPage->IsFtnPage() )
+ {
+ while ( pPage->IsFtnPage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ OSL_ENSURE( pPage, "Nur noch Endnotenseiten uebrig." );
+ }
+ continue;
+ }
+ else
+ pPage = 0;
+ }
+
+ if ( pPage )
+ {
+ SwPageFrm *pEmpty = pPage;
+ pPage = (SwPageFrm*)pPage->GetPrev();
+ if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ RemoveFtns( pEmpty, sal_True );
+ pEmpty->Cut();
+ delete pEmpty;
+ nDocPos = pPage ? pPage->Frm().Top() : 0;
+ }
+ } while ( pPage );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( nDocPos != LONG_MAX &&
+ (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
+ {
+ SwDocPosUpdate aMsgHnt( nDocPos );
+ GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::AssertFlyPages()
+|*
+|* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden
+|* sind, damit alle Seitengebundenen Rahmen und DrawObject
+|* untergebracht sind.
+|*
+|*************************************************************************/
+void SwRootFrm::AssertFlyPages()
+{
+ if ( !IsAssertFlyPages() )
+ return;
+ bAssertFlyPages = sal_False;
+
+ SwDoc *pDoc = GetFmt()->GetDoc();
+ const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
+
+ //Auf welche Seite will der 'letzte' Fly?
+ sal_uInt16 nMaxPg = 0;
+ sal_uInt16 i;
+
+ for ( i = 0; i < pTbl->Count(); ++i )
+ {
+ const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
+ if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
+ nMaxPg = rAnch.GetPageNum();
+ }
+ //Wieviele Seiten haben wir derzeit?
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while ( pPage && pPage->GetNext() &&
+ !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
+ {
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ if ( nMaxPg > pPage->GetPhyPageNum() )
+ {
+ //Die Seiten werden ausgehend von der letzten Seite konsequent
+ //nach den Regeln der PageDescs weitergefuehrt.
+ sal_Bool bOdd = pPage->GetPhyPageNum() % 2 ? sal_True : sal_False;
+ SwPageDesc *pDesc = pPage->GetPageDesc();
+ SwFrm *pSibling = pPage->GetNext();
+ for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
+ {
+ if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
+ {
+ //Leerseite einfuegen, die Flys werden aber erst von
+ //der naechsten Seite aufgenommen!
+ pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc );
+ pPage->Paste( this, pSibling );
+ pPage->PreparePage( sal_False );
+ bOdd = bOdd ? sal_False : sal_True;
+ ++i;
+ }
+ pPage = new
+ SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
+ pDesc->GetLeftFmt()), this, pDesc );
+ pPage->Paste( this, pSibling );
+ pPage->PreparePage( sal_False );
+ bOdd = bOdd ? sal_False : sal_True;
+ pDesc = pDesc->GetFollow();
+ }
+ //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
+ //in diesem Fall werden sie vernichtet.
+ if ( pDoc->GetFtnIdxs().Count() )
+ {
+ pPage = (SwPageFrm*)Lower();
+ while ( pPage && !pPage->IsFtnPage() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+
+ if ( pPage )
+ {
+ SwPageDesc *pTmpDesc = pPage->FindPageDesc();
+ bOdd = pPage->OnRightPage();
+ if ( pPage->GetFmt() !=
+ (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
+ RemoveFtns( pPage, sal_False, sal_True );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::AssertPageFlys()
+|*
+|* Beschreibung Stellt sicher, dass ab der uebergebenen Seite
+|* auf allen Seiten die Seitengebunden Objecte auf der richtigen
+|* Seite (Seitennummer stehen).
+|*
+|*************************************************************************/
+void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
+{
+ while ( pPage )
+ {
+ if ( pPage->GetSortedObjs() )
+ {
+ pPage->GetSortedObjs();
+ for ( int i = 0;
+ pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count();
+ ++i)
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
+ const SwFmtAnchor &rAnch = rFmt.GetAnchor();
+ const sal_uInt16 nPg = rAnch.GetPageNum();
+ if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
+ nPg != pPage->GetPhyPageNum() )
+ {
+ //Das er auf der falschen Seite steht muss noch nichts
+ //heissen, wenn er eigentlich auf der Vorseite
+ //stehen will und diese eine EmptyPage ist.
+ if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
+ ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
+ {
+ //Umhaengen kann er sich selbst, indem wir ihm
+ //einfach ein Modify mit seinem AnkerAttr schicken.
+#if OSL_DEBUG_LEVEL > 1
+ const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
+ rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
+ OSL_ENSURE( !pPage->GetSortedObjs() ||
+ nCnt != pPage->GetSortedObjs()->Count(),
+ "Object couldn't be reattached!" );
+#else
+ rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
+#endif
+ --i;
+ }
+ }
+ }
+ }
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ChgSize()
+|*
+|*************************************************************************/
+Size SwRootFrm::ChgSize( const Size& aNewSize )
+{
+ Frm().SSize() = aNewSize;
+ _InvalidatePrt();
+ bFixSize = sal_False;
+ return Frm().SSize();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwRootFrm::MakeAll()
+{
+ if ( !bValidPos )
+ { bValidPos = sal_True;
+ aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER;
+ }
+ if ( !bValidPrtArea )
+ { bValidPrtArea = sal_True;
+ aPrt.Pos().X() = aPrt.Pos().Y() = 0;
+ aPrt.SSize( aFrm.SSize() );
+ }
+ if ( !bValidSize )
+ //SSize wird von den Seiten (Cut/Paste) eingestellt.
+ bValidSize = sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ImplInvalidateBrowseWidth()
+|*
+|*************************************************************************/
+void SwRootFrm::ImplInvalidateBrowseWidth()
+{
+ bBrowseWidthValid = sal_False;
+ SwFrm *pPg = Lower();
+ while ( pPg )
+ {
+ pPg->InvalidateSize();
+ pPg = pPg->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::ImplCalcBrowseWidth()
+|*
+|*************************************************************************/
+void SwRootFrm::ImplCalcBrowseWidth()
+{
+ OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
+ "CalcBrowseWidth and not in BrowseView" );
+
+ //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
+ //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
+ //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
+ //sind, sondern wie breit sie sein wollen.
+ //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
+ //Zaehlen nicht.
+ //Seitenraender und Spalten werden hier nicht beruecksichtigt.
+
+ SwFrm *pFrm = ContainsCntnt();
+ while ( pFrm && !pFrm->IsInDocBody() )
+ pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
+ if ( !pFrm )
+ return;
+
+ bBrowseWidthValid = sal_True;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ nBrowseWidth = pSh
+ ? MINLAY + 2 * pSh->GetOut()->
+ PixelToLogic( pSh->GetBrowseBorder() ).Width()
+ : 5000;
+ do
+ {
+ if ( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+
+ if ( pFrm->IsTabFrm() &&
+ !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
+ long nWidth = rAttrs.GetSize().Width();
+ if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per
+ //Zuppeln das USHRT_MAX verlorengeht!
+ text::HoriOrientation::FULL != rHori.GetHoriOrient() )
+ {
+ const SwHTMLTableLayout *pLayoutInfo =
+ ((const SwTabFrm *)pFrm)->GetTable()
+ ->GetHTMLTableLayout();
+ if ( pLayoutInfo )
+ nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
+
+ switch ( rHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
+ break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ nWidth += rAttrs.CalcLeft( pFrm );
+ break;
+ default:
+ break;
+
+ }
+ nBrowseWidth = Max( nBrowseWidth, nWidth );
+ }
+ }
+ else if ( pFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ // --> OD 2004-06-29 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm);
+ if ((bFly && (WEIT_WECH == pAnchoredObj->GetObjRect().Width()))
+ || rFmt.GetFrmSize().GetWidthPercent())
+ {
+ continue;
+ }
+
+ long nWidth = 0;
+ switch ( rFmt.GetAnchor().GetAnchorId() )
+ {
+ case FLY_AS_CHAR:
+ nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
+ pAnchoredObj->GetObjRect().Width();
+ break;
+ case FLY_AT_PARA:
+ {
+ // --> FME 2004-09-13 #i33170#
+ // Reactivated old code because
+ // nWidth = pAnchoredObj->GetObjRect().Right()
+ // gives wrong results for objects that are still
+ // at position WEIT_WECH.
+ if ( bFly )
+ {
+ nWidth = rFmt.GetFrmSize().GetWidth();
+ const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
+ switch ( rHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ nWidth += rHori.GetPos();
+ break;
+ case text::HoriOrientation::INSIDE:
+ case text::HoriOrientation::LEFT:
+ if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
+ nWidth += pFrm->Prt().Left();
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ //Fuer Zeichenobjekte ist die Auswahl sehr klein,
+ //weil sie keine Attribute haben, also durch ihre
+ //aktuelle Groesse bestimmt werden.
+ nWidth = pAnchoredObj->GetObjRect().Right() -
+ pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
+ // <--
+ }
+ break;
+ default: /* do nothing */;
+ }
+ nBrowseWidth = Max( nBrowseWidth, nWidth );
+ }
+ }
+ pFrm = pFrm->FindNextCnt();
+ } while ( pFrm );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::StartAllAction()
+|*
+|*************************************************************************/
+
+void SwRootFrm::StartAllAction()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ { if ( pSh->ISA( SwCrsrShell ) )
+ ((SwCrsrShell*)pSh)->StartAction();
+ else
+ pSh->StartAction();
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::EndAllAction( sal_Bool bVirDev )
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
+ pSh->SetEndActionByVirDev( bVirDev );
+ if ( pSh->ISA( SwCrsrShell ) )
+ {
+ ((SwCrsrShell*)pSh)->EndAction();
+ ((SwCrsrShell*)pSh)->CallChgLnk();
+ if ( pSh->ISA( SwFEShell ) )
+ ((SwFEShell*)pSh)->SetChainMarker();
+ }
+ else
+ pSh->EndAction();
+ pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::UnoRemoveAllActions()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ // --> OD 2008-05-16 #i84729#
+ // No end action, if <ViewShell> instance is currently in its end action.
+ // Recursives calls to <::EndAction()> are not allowed.
+ if ( !pSh->IsInEndAction() )
+ {
+ DBG_ASSERT(!pSh->GetRestoreActions(), "Restore action count is already set!");
+ sal_Bool bCrsr = pSh->ISA( SwCrsrShell );
+ sal_Bool bFE = pSh->ISA( SwFEShell );
+ sal_uInt16 nRestore = 0;
+ while( pSh->ActionCount() )
+ {
+ if( bCrsr )
+ {
+ ((SwCrsrShell*)pSh)->EndAction();
+ ((SwCrsrShell*)pSh)->CallChgLnk();
+ if ( bFE )
+ ((SwFEShell*)pSh)->SetChainMarker();
+ }
+ else
+ pSh->EndAction();
+ nRestore++;
+ }
+ pSh->SetRestoreActions(nRestore);
+ }
+ // <--
+ pSh->LockView(sal_True);
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+void SwRootFrm::UnoRestoreAllActions()
+{
+ ViewShell *pSh = GetCurrShell();
+ if ( pSh )
+ do
+ {
+ sal_uInt16 nActions = pSh->GetRestoreActions();
+ while( nActions-- )
+ {
+ if ( pSh->ISA( SwCrsrShell ) )
+ ((SwCrsrShell*)pSh)->StartAction();
+ else
+ pSh->StartAction();
+ }
+ pSh->SetRestoreActions(0);
+ pSh->LockView(sal_False);
+ pSh = (ViewShell*)pSh->GetNext();
+
+ } while ( pSh != GetCurrShell() );
+}
+
+// PAGES01: Helper functions for SwRootFrm::CheckViewLayout
+void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
+
+void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
+{
+ SwSortedObjs* pSortedObj = 0;
+ const bool bPage = pFrm->IsPageFrm();
+
+ if ( bPage )
+ pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
+ else
+ pSortedObj = pFrm->GetDrawObjs();
+
+ for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
+ {
+ SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
+
+ const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
+
+ // all except from the as character anchored objects are moved
+ // when processing the page frame:
+ const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR);
+ if ( !bPage && !bAsChar )
+ continue;
+
+ SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
+
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
+ lcl_MoveAllLowers( pFlyFrm, rOffset );
+ pFlyFrm->NotifyDrawObj();
+ // --> let the active embedded object be moved
+ if ( pFlyFrm->Lower() )
+ {
+ if ( pFlyFrm->Lower()->IsNoTxtFrm() )
+ {
+ SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
+ SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm();
+ ViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0;
+ if ( pSh )
+ {
+ SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
+ if ( pNode )
+ {
+ svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
+ if ( xObj.is() )
+ {
+ ViewShell* pTmp = pSh;
+ do
+ {
+ SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
+ if ( pFEShell )
+ pFEShell->MoveObjectIfActive( xObj, rOffset );
+ pTmp = static_cast<ViewShell*>( pTmp->GetNext() );
+ } while( pTmp != pSh );
+ }
+ }
+ }
+ }
+ }
+ // <--
+ }
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
+
+ // don't touch objects that are not yet positioned:
+ const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
+ if ( bNotYetPositioned )
+ continue;
+
+ const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
+ const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
+ pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
+ pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
+ }
+ // --> OD 2009-08-20 #i92511#
+ // cache for object rectangle inclusive spaces has to be invalidated.
+ pAnchoredObj->InvalidateObjRectWithSpaces();
+ // <--
+ }
+}
+
+void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
+{
+ const SwRect aFrm( pFrm->Frm() );
+
+ // first move the current frame
+ pFrm->Frm().Pos() += rOffset;
+
+ // Don't forget accessibility:
+ if( pFrm->IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = pFrm->getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
+ }
+ }
+
+ // the move any objects
+ lcl_MoveAllLowerObjs( pFrm, rOffset );
+
+ // finally, for layout frames we have to call this function recursively:
+ if ( pFrm->ISA(SwLayoutFrm) )
+ {
+ SwFrm* pLowerFrm = pFrm->GetLower();
+ while ( pLowerFrm )
+ {
+ lcl_MoveAllLowers( pLowerFrm, rOffset );
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+ }
+}
+
+// PAGES01: Calculate how the pages have to be positioned
+void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
+{
+ // --> OD 2008-07-07 #i91432#
+ // No calculation of page positions, if only an empty page is present.
+ // This situation occurs when <SwRootFrm> instance is in construction
+ // and the document contains only left pages.
+ if ( Lower()->GetNext() == 0 &&
+ static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
+ {
+ return;
+ }
+ // <--
+
+ if ( !pVisArea )
+ {
+ // no early return for bNewPage
+ if ( mnViewWidth < 0 )
+ mnViewWidth = 0;
+ }
+ else
+ {
+ OSL_ENSURE( pViewOpt, "CheckViewLayout required ViewOptions" );
+
+ const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns();
+ const bool bBookMode = pViewOpt->IsViewLayoutBookMode();
+
+ if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
+ return;
+
+ mnColumns = nColumns;
+ mbBookMode = bBookMode;
+ mnViewWidth = pVisArea->Width();
+ mbSidebarChanged = false;
+ }
+
+ if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
+ {
+ mnColumns = 1;
+ mbBookMode = false;
+ }
+
+ Calc();
+
+ const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
+ SetCallbackActionEnabled( sal_False );
+
+ maPageRects.clear();
+
+ const long nBorder = Frm().Pos().X();
+ const long nVisWidth = mnViewWidth - 2 * nBorder;
+ const long nGapBetweenPages = GAPBETWEENPAGES;
+
+ // check how many pages fit into the first page layout row:
+ SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
+
+ // will contain the number of pages per row. 0 means that
+ // the page does not fit.
+ long nWidthRemain = nVisWidth;
+
+ // after one row has been processed, these variables contain
+ // the width of the row and the maxium of the page heights
+ long nCurrentRowHeight = 0;
+ long nCurrentRowWidth = 0;
+
+ // these variables are used to finally set the size of the
+ // root frame
+ long nSumRowHeight = 0;
+ SwTwips nMinPageLeft = TWIPS_MAX;
+ SwTwips nMaxPageRight = 0;
+ SwPageFrm* pStartOfRow = pPageFrm;
+ sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
+ bool bFirstRow = true;
+
+ bool bPageChanged = false;
+ const bool bRTL = !IsLeftToRightViewLayout();
+ const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() );
+
+ while ( pPageFrm )
+ {
+ // we consider the current page to be "start of row" if
+ // 1. it is the first page in the current row or
+ // 2. it is the second page in the row and the first page is an empty page in non-book view:
+ const bool bStartOfRow = pPageFrm == pStartOfRow ||
+ ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
+
+ const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
+
+ // no half doc border space for first page in each row and
+ long nPageWidth = 0;
+ long nPageHeight = 0;
+
+ if ( mbBookMode )
+ {
+ const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
+
+ nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
+ nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
+ }
+ else
+ {
+ SwRect aPageFrm;
+ if ( !pPageFrm->IsEmptyPage() )
+ {
+ nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
+ nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
+ }
+ }
+
+ if ( !bEmptyPage )
+ ++nNumberOfPagesInRow;
+
+ // finish current row if
+ // 1. in dynamic mode the current page does not fit anymore or
+ // 2. the current page exceeds the maximum number of columns
+ bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
+ (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
+
+ // make sure that at least one page goes to the current row:
+ if ( !bRowFinished || bStartOfRow )
+ {
+ // current page is allowed to be in current row
+ nWidthRemain = nWidthRemain - nPageWidth;
+
+ nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
+ nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight );
+
+ pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
+
+ if ( !pPageFrm )
+ bRowFinished = true;
+ }
+
+ if ( bRowFinished )
+ {
+ // pPageFrm now points to the first page in the new row or null
+ // pStartOfRow points to the first page in the current row
+
+ // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
+ if ( !pPageFrm && nWidthRemain > 0 )
+ {
+ // find last page in current row:
+ const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
+ while( pLastPageInCurrentRow->GetNext() )
+ pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
+
+ if ( pLastPageInCurrentRow->IsEmptyPage() )
+ pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
+
+ // check how many times the last page would still fit into the remaining space:
+ sal_uInt16 nNumberOfVirtualPages = 0;
+ const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
+ SwTwips nRemain = nWidthRemain;
+ SwTwips nVirtualPagesWidth = 0;
+ SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
+
+ while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
+ {
+ SwTwips nLastPageWidthWithGap = nLastPageWidth;
+ if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
+ nLastPageWidthWithGap += nGapBetweenPages;
+
+ if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
+ {
+ ++nNumberOfVirtualPages;
+ nVirtualPagesWidth += nLastPageWidthWithGap;
+ }
+ nRemain = nRemain - nLastPageWidthWithGap;
+ }
+
+ nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
+ }
+
+ // first page in book mode is always special:
+ if ( bFirstRow && mbBookMode )
+ {
+ // #i88036#
+ nCurrentRowWidth +=
+ pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
+ }
+
+ // center page if possible
+ const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
+ ( nVisWidth - nCurrentRowWidth ) / 2 :
+ 0;
+
+ // adjust positions of pages in current row
+ long nX = nSizeDiff;
+
+ const long nRowStart = nBorder + nSizeDiff;
+ const long nRowEnd = nRowStart + nCurrentRowWidth;
+
+ if ( bFirstRow && mbBookMode )
+ {
+ // #i88036#
+ nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
+ }
+
+ SwPageFrm* pEndOfRow = pPageFrm;
+ SwPageFrm* pPageToAdjust = pStartOfRow;
+
+ do
+ {
+ const SwPageFrm* pFormatPage = pPageToAdjust;
+ if ( mbBookMode )
+ pFormatPage = &pPageToAdjust->GetFormatPage();
+
+ const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
+ const Point aOldPagePos = pPageToAdjust->Frm().Pos();
+ const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT;
+ const SwTwips nLeftPageAddOffset = bLeftSidebar ?
+ nSidebarWidth :
+ 0;
+
+ Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
+ Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
+
+ // RTL view layout: Calculate mirrored page position
+ if ( bRTL )
+ {
+ const long nXOffsetInRow = aNewPagePos.X() - nRowStart;
+ aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth;
+ aNewPagePosWithLeftOffset = aNewPagePos;
+ aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset;
+ }
+
+ if ( aNewPagePosWithLeftOffset != aOldPagePos )
+ {
+ lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
+ pPageToAdjust->SetCompletePaint();
+ bPageChanged = true;
+ }
+
+ // calculate area covered by the current page and store to
+ // maPageRects. This is used e.g., for cursor setting
+ const bool bFirstColumn = pPageToAdjust == pStartOfRow;
+ const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
+ const bool bLastRow = !pEndOfRow;
+
+ nMinPageLeft = Min( nMinPageLeft, aNewPagePos.X() );
+ nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth);
+
+ // border of nGapBetweenPages around the current page:
+ SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages,
+ aNewPagePos.Y(),
+ pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
+ nCurrentRowHeight );
+
+ static const long nOuterClickDiff = 1000000;
+
+ // adjust borders for these special cases:
+ if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
+ aPageRectWithBorders.SubLeft( nOuterClickDiff );
+ if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
+ aPageRectWithBorders.AddRight( nOuterClickDiff );
+ if ( bFirstRow )
+ aPageRectWithBorders.SubTop( nOuterClickDiff );
+ if ( bLastRow )
+ aPageRectWithBorders.AddBottom( nOuterClickDiff );
+
+ maPageRects.push_back( aPageRectWithBorders );
+
+ nX = nX + nCurrentPageWidth;
+ pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
+
+ // distance to next page
+ if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
+ {
+ // in book view, we add the x gap before left (even) pages:
+ if ( mbBookMode )
+ {
+ if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
+ nX = nX + nGapBetweenPages;
+ }
+ else
+ {
+ // in non-book view, dont add x gap before
+ // 1. the last empty page in a row
+ // 2. after an empty page
+ const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
+ ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
+
+ if ( !bDontAddGap )
+ nX = nX + nGapBetweenPages;
+ }
+ }
+ }
+ while ( pPageToAdjust != pEndOfRow );
+
+ // adjust values for root frame size
+ nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
+
+ // start new row:
+ nCurrentRowHeight = 0;
+ nCurrentRowWidth = 0;
+ pStartOfRow = pEndOfRow;
+ nWidthRemain = nVisWidth;
+ nNumberOfPagesInRow = 0;
+ bFirstRow = false;
+ } // end row finished
+ } // end while
+
+ // set size of root frame:
+ const Size aOldSize( Frm().SSize() );
+ const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
+
+ if ( bPageChanged || aNewSize != aOldSize )
+ {
+ ChgSize( aNewSize );
+ ::AdjustSizeChgNotify( this );
+ Calc();
+
+ ViewShell* pSh = GetCurrShell();
+
+ if ( pSh && pSh->GetDoc()->GetDocShell() )
+ {
+ pSh->SetFirstVisPageInvalid();
+ if (bOldCallbackActionEnabled)
+ {
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+ pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
+ }
+ }
+ }
+
+ maPagesArea.Pos( Frm().Pos() );
+ maPagesArea.SSize( aNewSize );
+ if ( TWIPS_MAX != nMinPageLeft )
+ maPagesArea._Left( nMinPageLeft );
+
+ SetCallbackActionEnabled( bOldCallbackActionEnabled );
+}
+
+bool SwRootFrm::IsLeftToRightViewLayout() const
+{
+ // Layout direction determined by layout direction of the first page.
+ // --> OD 2008-04-08 #i88036#
+ // Only ask a non-empty page frame for its layout direction
+// const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
+// return !pPage->IsRightToLeft() && !pPage->IsVertical();
+ const SwPageFrm& rPage =
+ dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
+ return !rPage.IsRightToLeft() && !rPage.IsVertical();
+ // <--
+}
+
+const SwPageFrm& SwPageFrm::GetFormatPage() const
+{
+ const SwPageFrm* pRet = this;
+ if ( IsEmptyPage() )
+ {
+ pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
+ // --> OD 2008-04-08 #i88035#
+ // Typically a right empty page frame has a next non-empty page frame and
+ // a left empty page frame has a previous non-empty page frame.
+ // But under certain cirsumstances this assumption is not true -
+ // e.g. during insertion of a left page at the end of the document right
+ // after a left page in an intermediate state a right empty page does not
+ // have a next page frame.
+ if ( pRet == 0 )
+ {
+ if ( OnRightPage() )
+ {
+ pRet = static_cast<const SwPageFrm*>( GetPrev() );
+ }
+ else
+ {
+ pRet = static_cast<const SwPageFrm*>( GetNext() );
+ }
+ }
+ OSL_ENSURE( pRet,
+ "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
+ // <--
+ }
+ return *pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagedesc.cxx b/sw/source/core/layout/pagedesc.cxx
new file mode 100644
index 000000000000..dec5a75becf5
--- /dev/null
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -0,0 +1,487 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+
+#include <hintids.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include "editeng/frmdiritem.hxx"
+#include <fmtclds.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <pagefrm.hxx>
+#include <pagedesc.hxx>
+#include <frmfmt.hxx>
+#include <fmtcol.hxx> // SwTxtFmtColl
+#include <node.hxx>
+#include <swtable.hxx>
+#include <frmtool.hxx>
+#include <doc.hxx> // fuer GetAttrPool
+#include <poolfmt.hxx>
+#include <switerator.hxx>
+
+/*************************************************************************
+|*
+|* SwPageDesc::SwPageDesc()
+|*
+|*************************************************************************/
+
+
+
+SwPageDesc::SwPageDesc( const String& rName, SwFrmFmt *pFmt, SwDoc *pDc ) :
+ SwModify( 0 ),
+ aDescName( rName ),
+ aMaster( pDc->GetAttrPool(), rName, pFmt ),
+ aLeft( pDc->GetAttrPool(), rName, pFmt ),
+ aDepend( this, 0 ),
+ pFollow( this ),
+ nRegHeight( 0 ),
+ nRegAscent( 0 ),
+ eUse( (UseOnPage)(nsUseOnPage::PD_ALL | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE) ),
+ bLandscape( sal_False ),
+ aFtnInfo()
+{
+}
+
+SwPageDesc::SwPageDesc( const SwPageDesc &rCpy ) :
+ SwModify( 0 ),
+ aDescName( rCpy.GetName() ),
+ aNumType( rCpy.GetNumType() ),
+ aMaster( rCpy.GetMaster() ),
+ aLeft( rCpy.GetLeft() ),
+ aDepend( this, (SwModify*)rCpy.aDepend.GetRegisteredIn() ),
+ pFollow( rCpy.pFollow ),
+ nRegHeight( rCpy.GetRegHeight() ),
+ nRegAscent( rCpy.GetRegAscent() ),
+ eUse( rCpy.ReadUseOn() ),
+ bLandscape( rCpy.GetLandscape() ),
+ aFtnInfo( rCpy.GetFtnInfo() )
+{
+}
+
+SwPageDesc & SwPageDesc::operator = (const SwPageDesc & rSrc)
+{
+ aDescName = rSrc.aDescName;
+ aNumType = rSrc.aNumType;
+ aMaster = rSrc.aMaster;
+ aLeft = rSrc.aLeft;
+
+ if (rSrc.pFollow == &rSrc)
+ pFollow = this;
+ else
+ pFollow = rSrc.pFollow;
+
+ nRegHeight = rSrc.nRegHeight;
+ nRegAscent = rSrc.nRegAscent;
+ eUse = rSrc.eUse;
+ bLandscape = rSrc.bLandscape;
+ return *this;
+}
+
+SwPageDesc::~SwPageDesc()
+{
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::Mirror()
+|*
+|* Beschreibung Gespiegelt werden nur die Raender.
+|* Attribute wie Umrandung und dergleichen werden 1:1 kopiert.
+|*
+|*************************************************************************/
+
+
+
+void SwPageDesc::Mirror()
+{
+ //Das Spiegeln findet nur beim RandAttribut statt, alle anderen Werte
+ //werden schlicht uebertragen.
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ const SvxLRSpaceItem &rLR = aMaster.GetLRSpace();
+ aLR.SetLeft( rLR.GetRight() );
+ aLR.SetRight( rLR.GetLeft() );
+
+ SfxItemSet aSet( *aMaster.GetAttrSet().GetPool(),
+ aMaster.GetAttrSet().GetRanges() );
+ aSet.Put( aLR );
+ aSet.Put( aMaster.GetFrmSize() );
+ aSet.Put( aMaster.GetPaperBin() );
+ aSet.Put( aMaster.GetULSpace() );
+ aSet.Put( aMaster.GetBox() );
+ aSet.Put( aMaster.GetBackground() );
+ aSet.Put( aMaster.GetShadow() );
+ aSet.Put( aMaster.GetCol() );
+ aSet.Put( aMaster.GetFrmDir() ); // #112217#
+ aLeft.SetFmtAttr( aSet );
+}
+
+void SwPageDesc::ResetAllAttr( sal_Bool bLeft )
+{
+ SwFrmFmt& rFmt = bLeft ? GetLeft() : GetMaster();
+
+ // --> OD 2007-01-25 #i73790# - method renamed
+ rFmt.ResetAllFmtAttr();
+ // <--
+ rFmt.SetFmtAttr( SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR) );
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::GetInfo()
+|*
+|* Beschreibung erfragt Informationen
+|*
+*************************************************************************/
+
+
+ // erfrage vom Modify Informationen
+sal_Bool SwPageDesc::GetInfo( SfxPoolItem & rInfo ) const
+{
+ if( !aMaster.GetInfo( rInfo ) )
+ return sal_False; // found
+ return aLeft.GetInfo( rInfo );
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::SetRegisterFmtColl()
+|*
+|* Beschreibung setzt die Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+void SwPageDesc::SetRegisterFmtColl( const SwTxtFmtColl* pFmt )
+{
+ if( pFmt != GetRegisterFmtColl() )
+ {
+ if( pFmt )
+ ((SwTxtFmtColl*)pFmt)->Add( &aDepend );
+ else
+ ((SwTxtFmtColl*)GetRegisterFmtColl())->Remove( &aDepend );
+
+ RegisterChange();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::GetRegisterFmtColl()
+|*
+|* Beschreibung holt die Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+const SwTxtFmtColl* SwPageDesc::GetRegisterFmtColl() const
+{
+ const SwModify* pReg = aDepend.GetRegisteredIn();
+ return (SwTxtFmtColl*)pReg;
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::RegisterChange()
+|*
+|* Beschreibung benachrichtigt alle betroffenen PageFrames
+|*
+*************************************************************************/
+
+
+void SwPageDesc::RegisterChange()
+{
+ // --> OD 2004-06-15 #117072# - During destruction of the document <SwDoc>
+ // the page description is modified. Thus, do nothing, if the document
+ // is in destruction respectively if no viewshell exists.
+ SwDoc* pDoc = GetMaster().GetDoc();
+ if ( !pDoc || pDoc->IsInDtor() )
+ {
+ return;
+ }
+ ViewShell* pSh = 0L;
+ pDoc->GetEditShell( &pSh );
+ if ( !pSh )
+ {
+ return;
+ }
+
+ nRegHeight = 0;
+ {
+ SwIterator<SwFrm,SwFmt> aIter( GetMaster() );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->IsPageFrm() )
+ ((SwPageFrm*)pLast)->PrepareRegisterChg();
+ }
+ }
+ {
+ SwIterator<SwFrm,SwFmt> aIter( GetLeft() );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->IsPageFrm() )
+ ((SwPageFrm*)pLast)->PrepareRegisterChg();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageDesc::Modify()
+|*
+|* Beschreibung reagiert insbesondere auf Aenderungen
+|* der Vorlage fuer die Registerhaltigkeit
+|*
+*************************************************************************/
+
+
+void SwPageDesc::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+{
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ NotifyClients( pOld, pNew );
+
+ if ( (RES_ATTRSET_CHG == nWhich) || (RES_FMT_CHG == nWhich)
+ || isCHRATR(nWhich) || (RES_PARATR_LINESPACING == nWhich) )
+ {
+ RegisterChange();
+ }
+}
+
+static const SwFrm* lcl_GetFrmOfNode( const SwNode& rNd )
+{
+ SwModify* pMod;
+ sal_uInt16 nFrmType = FRM_CNTNT;
+
+ if( rNd.IsCntntNode() )
+ {
+ pMod = &(SwCntntNode&)rNd;
+ }
+ else if( rNd.IsTableNode() )
+ {
+ pMod = ((SwTableNode&)rNd).GetTable().GetFrmFmt();
+ nFrmType = FRM_TAB;
+ }
+ else
+ pMod = 0;
+
+ Point aNullPt;
+ return pMod ? ::GetFrmOfModify( 0, *pMod, nFrmType, &aNullPt, 0, sal_False )
+ : 0;
+}
+
+const SwPageDesc* SwPageDesc::GetPageDescOfNode(const SwNode& rNd)
+{
+ const SwPageDesc* pRet = 0;
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+ if (pChkFrm && 0 != (pChkFrm = pChkFrm->FindPageFrm()))
+ pRet = ((const SwPageFrm*)pChkFrm)->GetPageDesc();
+ return pRet;
+}
+
+const SwFrmFmt* SwPageDesc::GetPageFmtOfNode( const SwNode& rNd,
+ sal_Bool bCheckForThisPgDc ) const
+{
+ // welches PageDescFormat ist fuer diesen Node gueltig?
+ const SwFrmFmt* pRet;
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+
+ if( pChkFrm && 0 != ( pChkFrm = pChkFrm->FindPageFrm() ))
+ {
+ const SwPageDesc* pPd = bCheckForThisPgDc ? this :
+ ((SwPageFrm*)pChkFrm)->GetPageDesc();
+ pRet = &pPd->GetMaster();
+ OSL_ENSURE( ((SwPageFrm*)pChkFrm)->GetPageDesc() == pPd, "Wrong node for detection of page format!" );
+ // an welchem Format haengt diese Seite?
+ if( !pChkFrm->KnowsFormat(*pRet) )
+ {
+ pRet = &pPd->GetLeft();
+ OSL_ENSURE( pChkFrm->KnowsFormat(*pRet), "Wrong node for detection of page format!" );
+ }
+ }
+ else
+ pRet = &GetMaster();
+ return pRet;
+}
+
+sal_Bool SwPageDesc::IsFollowNextPageOfNode( const SwNode& rNd ) const
+{
+ sal_Bool bRet = sal_False;
+ if( GetFollow() && this != GetFollow() )
+ {
+ const SwFrm* pChkFrm = lcl_GetFrmOfNode( rNd );
+ if( pChkFrm && 0 != ( pChkFrm = pChkFrm->FindPageFrm() ) &&
+ pChkFrm->IsPageFrm() &&
+ ( !pChkFrm->GetNext() || GetFollow() ==
+ ((SwPageFrm*)pChkFrm->GetNext())->GetPageDesc() ))
+ // die Seite gefunden, auf die der Follow verweist
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFtnInfo::SwPageFtnInfo()
+|*
+|*************************************************************************/
+
+
+
+SwPageFtnInfo::SwPageFtnInfo() :
+ nMaxHeight( 0 ),
+// aPen( PEN_SOLID ),
+ nLineWidth(10),
+ eLineStyle( editeng::SOLID ),
+ aWidth( 25, 100 ),
+ nTopDist( 57 ), //1mm
+ nBottomDist( 57 )
+{
+ eAdj = FRMDIR_HORI_RIGHT_TOP == GetDefaultFrameDirection(GetAppLanguage()) ?
+ FTNADJ_RIGHT :
+ FTNADJ_LEFT;
+// aPen.SetWidth( 10 );
+}
+
+
+
+SwPageFtnInfo::SwPageFtnInfo( const SwPageFtnInfo &rCpy ) :
+ nMaxHeight( rCpy.GetHeight() ),
+ nLineWidth(rCpy.nLineWidth),
+ eLineStyle(rCpy.eLineStyle),
+ aLineColor(rCpy.aLineColor),
+ aWidth( rCpy.GetWidth() ),
+ eAdj( rCpy.GetAdj() ),
+ nTopDist( rCpy.GetTopDist() ),
+ nBottomDist( rCpy.GetBottomDist() )
+{
+}
+
+/*************************************************************************
+|*
+|* SwPageFtnInfo::operator=
+|*
+|*************************************************************************/
+
+
+
+SwPageFtnInfo &SwPageFtnInfo::operator=( const SwPageFtnInfo& rCpy )
+{
+ nMaxHeight = rCpy.GetHeight();
+ nLineWidth = rCpy.nLineWidth;
+ eLineStyle = rCpy.eLineStyle;
+ aLineColor = rCpy.aLineColor;
+ aWidth = rCpy.GetWidth();
+ eAdj = rCpy.GetAdj();
+ nTopDist = rCpy.GetTopDist();
+ nBottomDist = rCpy.GetBottomDist();
+ return *this;
+}
+/*************************************************************************
+|*
+|* SwPageFtnInfo::operator==
+|*
+|*************************************************************************/
+
+
+
+sal_Bool SwPageFtnInfo::operator==( const SwPageFtnInfo& rCmp ) const
+{
+ return ( nMaxHeight == rCmp.GetHeight() &&
+ nLineWidth == rCmp.nLineWidth &&
+ eLineStyle == rCmp.eLineStyle &&
+ aLineColor == rCmp.aLineColor &&
+ aWidth == rCmp.GetWidth() &&
+ eAdj == rCmp.GetAdj() &&
+ nTopDist == rCmp.GetTopDist() &&
+ nBottomDist== rCmp.GetBottomDist() );
+}
+
+SwPageDescExt::SwPageDescExt(const SwPageDesc & rPageDesc, SwDoc * _pDoc)
+ : aPageDesc(rPageDesc), pDoc(_pDoc)
+{
+ SetPageDesc(rPageDesc);
+}
+
+SwPageDescExt::SwPageDescExt(const SwPageDescExt & rSrc)
+ : aPageDesc(rSrc.aPageDesc), pDoc(rSrc.pDoc)
+{
+ SetPageDesc(rSrc.aPageDesc);
+}
+
+SwPageDescExt::~SwPageDescExt()
+{
+}
+
+const String & SwPageDescExt::GetName() const
+{
+ return aPageDesc.GetName();
+}
+
+void SwPageDescExt::SetPageDesc(const SwPageDesc & _aPageDesc)
+{
+ aPageDesc = _aPageDesc;
+
+ if (aPageDesc.GetFollow())
+ sFollow = aPageDesc.GetFollow()->GetName();
+}
+
+SwPageDescExt & SwPageDescExt::operator = (const SwPageDesc & rSrc)
+{
+ SetPageDesc(rSrc);
+
+ return *this;
+}
+
+SwPageDescExt & SwPageDescExt::operator = (const SwPageDescExt & rSrc)
+{
+ SetPageDesc(rSrc.aPageDesc);
+
+ return *this;
+}
+
+SwPageDescExt::operator SwPageDesc() const
+{
+ SwPageDesc aResult(aPageDesc);
+
+ SwPageDesc * pPageDesc = pDoc->GetPageDesc(sFollow);
+
+ if ( 0 != pPageDesc )
+ aResult.SetFollow(pPageDesc);
+
+ return aResult;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/pagefrm.src b/sw/source/core/layout/pagefrm.src
new file mode 100644
index 000000000000..1c5cafc38c4d
--- /dev/null
+++ b/sw/source/core/layout/pagefrm.src
@@ -0,0 +1,7 @@
+#include "pagefrm.hrc"
+
+Bitmap BMP_PAGE_SHADOW_MASK
+{
+ File = "page-shadow-mask.png";
+};
+
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
new file mode 100644
index 000000000000..8744151ef0e2
--- /dev/null
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -0,0 +1,6701 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <hintids.hxx>
+#include <vcl/sound.hxx>
+#include <tools/poly.hxx>
+#include <svl/svstdarr.hxx>
+#include <svx/xoutbmp.hxx>
+#include <sfx2/progress.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/prntitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <svx/framelink.hxx>
+#include <vcl/graph.hxx>
+#include <svx/svdpagv.hxx>
+#include <tgrditem.hxx>
+#include <switerator.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtclds.hxx>
+#include <tools/shl.hxx>
+#include <comcore.hrc>
+#include <swmodule.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <cntfrm.hxx>
+#include <viewsh.hxx>
+#include <section.hxx>
+#include <sectfrm.hxx>
+#include <doc.hxx>
+#include <viewimp.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <viewopt.hxx>
+#include <dview.hxx>
+#include <dcontact.hxx>
+#include <txtfrm.hxx>
+#include <ftnfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <notxtfrm.hxx>
+#include <swregion.hxx>
+#include <layact.hxx>
+#include <pagedesc.hxx>
+#include <ptqueue.hxx>
+#include <noteurl.hxx>
+#include <virtoutp.hxx>
+#include <lineinfo.hxx>
+#include <dbg_lay.hxx>
+#include <accessibilityoptions.hxx>
+#include <docsh.hxx>
+#include <swtable.hxx>
+#include <svx/svdogrp.hxx>
+#include <sortedobjs.hxx>
+#include <EnhancedPDFExportHelper.hxx>
+#include <ndole.hxx>
+#include <svtools/chartprettypainter.hxx>
+#include <PostItMgr.hxx>
+#include <tools/color.hxx>
+#include <vcl/svapp.hxx>
+
+#define COL_NOTES_SIDEPANE RGB_COLORDATA(230,230,230)
+#define COL_NOTES_SIDEPANE_BORDER RGB_COLORDATA(200,200,200)
+#define COL_NOTES_SIDEPANE_SCROLLAREA RGB_COLORDATA(230,230,220)
+
+#include <svtools/borderhelper.hxx>
+
+#include "pagefrm.hrc"
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx>
+#include <svx/sdr/contact/objectcontacttools.hxx>
+#include <svx/unoapi.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+using namespace ::editeng;
+using namespace ::com::sun::star;
+
+#define GETOBJSHELL() ((SfxObjectShell*)rSh.GetDoc()->GetDocShell())
+
+//Tabellenhilfslinien an?
+#define IS_SUBS_TABLE \
+ (pGlobalShell->GetViewOptions()->IsTable() && \
+ !pGlobalShell->GetViewOptions()->IsPagePreview()&&\
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsTableBoundaries())
+//sonstige Hilfslinien an?
+#define IS_SUBS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly() && \
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsDocBoundaries())
+//Hilfslinien fuer Bereiche
+#define IS_SUBS_SECTION (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsSectionBoundaries())
+#define IS_SUBS_FLYS (!pGlobalShell->GetViewOptions()->IsPagePreview() && \
+ !pGlobalShell->GetViewOptions()->IsReadonly()&&\
+ !pGlobalShell->GetViewOptions()->IsFormView() &&\
+ SwViewOption::IsObjectBoundaries())
+
+#define SW_MAXBORDERCACHE 20
+
+//Klassendeklarationen. Hier weil sie eben nur in diesem File benoetigt
+//werden.
+
+#define SUBCOL_PAGE 0x01 //Helplines of the page
+#define SUBCOL_BREAK 0x02 //Helpline for a page or column break
+#define SUBCOL_TAB 0x08 //Helplines inside tables
+#define SUBCOL_FLY 0x10 //Helplines inside fly frames
+#define SUBCOL_SECT 0x20 //Helplines inside sections
+
+//----- Klassen zum Sammeln von Umrandungen und Hilfslinien ---
+class SwLineRect : public SwRect
+{
+ Color aColor;
+ SvxBorderStyle nStyle;
+ const SwTabFrm *pTab;
+ sal_uInt8 nSubColor; //Hilfslinien einfaerben
+ sal_Bool bPainted; //schon gepaintet?
+ sal_uInt8 nLock; //Um die Linien zum Hell-Layer abzugrenzen.
+public:
+ SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
+ const SwTabFrm *pT , const sal_uInt8 nSCol );
+
+ const Color *GetColor() const { return &aColor;}
+ SvxBorderStyle GetStyle() const { return nStyle; }
+ const SwTabFrm *GetTab() const { return pTab; }
+ void SetPainted() { bPainted = sal_True; }
+ void Lock( sal_Bool bLock ) { if ( bLock )
+ ++nLock;
+ else if ( nLock )
+ --nLock;
+ }
+ sal_Bool IsPainted() const { return bPainted; }
+ sal_Bool IsLocked() const { return nLock != 0; }
+ sal_uInt8 GetSubColor() const { return nSubColor;}
+
+ sal_Bool MakeUnion( const SwRect &rRect );
+};
+
+SV_DECL_VARARR( SwLRects, SwLineRect, 100, 100 )
+
+class SwLineRects : public SwLRects
+{
+ sal_uInt16 nLastCount; //unuetze Durchlaeufe im PaintLines verhindern.
+public:
+ SwLineRects() : nLastCount( 0 ) {}
+ void AddLineRect( const SwRect& rRect, const Color *pColor, const SvxBorderStyle nStyle,
+ const SwTabFrm *pTab, const sal_uInt8 nSCol );
+ void ConnectEdges( OutputDevice *pOut );
+ void PaintLines ( OutputDevice *pOut );
+ void LockLines( sal_Bool bLock );
+
+ /// OD 13.08.2002 - correct type of function
+ sal_uInt16 Free() const { return nFree; }
+};
+
+class SwSubsRects : public SwLineRects
+{
+ void RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects ); //;-)
+public:
+ void PaintSubsidiary( OutputDevice *pOut, const SwLineRects *pRects );
+
+ inline void Ins( const SwRect &rRect, const sal_uInt8 nSCol );
+};
+
+//----------------- End Klassen Umrandungen ----------------------
+
+static ViewShell *pGlobalShell = 0;
+
+//Wenn durchsichtige FlyInCnts im PaintBackground gepainted werden so soll der
+//Hintergrund nicht mehr retouchiert werden.
+//static sal_Bool bLockFlyBackground = sal_False;
+
+//Wenn vom Fly ein Metafile abgezogen wird, so soll nur der FlyInhalt und vor
+//nur hintergrund vom FlyInhalt gepaintet werden.
+static sal_Bool bFlyMetafile = sal_False;
+static OutputDevice *pFlyMetafileOut = 0;
+
+//Die Retouche fuer Durchsichtige Flys wird vom Hintergrund der Flys
+//erledigt. Dabei darf der Fly selbst natuerlich nicht ausgespart werden.
+//siehe PaintBackground und lcl_SubtractFlys()
+static SwFlyFrm *pRetoucheFly = 0;
+static SwFlyFrm *pRetoucheFly2 = 0;
+
+//Groesse eines Pixel und die Haelfte davon. Wird jeweils bei Eintritt in
+//SwRootFrm::Paint neu gesetzt.
+static long nPixelSzW = 0, nPixelSzH = 0;
+static long nHalfPixelSzW = 0, nHalfPixelSzH = 0;
+static long nMinDistPixelW = 0, nMinDistPixelH = 0;
+
+//Aktueller Zoomfaktor
+static double aScaleX = 1.0;
+static double aScaleY = 1.0;
+static double aMinDistScale = 0.73;
+static double aEdgeScale = 0.5;
+
+//In pLines werden Umrandungen waehrend des Paint gesammelt und soweit
+//moeglich zusammengefasst.
+//In pSubsLines werden Hilfslinien gesammelt und zusammengefasst. Diese
+//werden vor der Ausgabe mit pLines abgeglichen, so dass moeglichst keine
+//Umrandungen von den Hilfslinen verdeckt werden.
+//bTablines ist waerend des Paints einer Tabelle sal_True.
+static SwLineRects *pLines = 0;
+static SwSubsRects *pSubsLines = 0;
+// OD 18.11.2002 #99672# - global variable for sub-lines of body, header, footer,
+// section and footnote frames.
+static SwSubsRects *pSpecSubsLines = 0;
+
+static SfxProgress *pProgress = 0;
+
+static SwFlyFrm *pFlyOnlyDraw = 0;
+
+//Damit die Flys auch fuer den Hack richtig gepaintet werden koennen.
+static sal_Bool bTableHack = sal_False;
+
+//Um das teure Ermitteln der RetoucheColor zu optimieren
+Color aGlobalRetoucheColor;
+
+//Statics fuer Umrandungsalignment setzen.
+// OD 05.05.2003 #107169# - adjustment for 'small' twip-to-pixel relations:
+// For 'small' twip-to-pixel relations (less then 2:1)
+// values of <nHalfPixelSzW> and <nHalfPixelSzH> are set to ZERO.
+void SwCalcPixStatics( OutputDevice *pOut )
+{
+ // OD 30.04.2003 #107169# - determine 'small' twip-to-pixel relation
+ sal_Bool bSmallTwipToPxRelW = sal_False;
+ sal_Bool bSmallTwipToPxRelH = sal_False;
+ {
+ Size aCheckTwipToPxRelSz( pOut->PixelToLogic( Size( 100, 100 )) );
+ if ( (aCheckTwipToPxRelSz.Width()/100.0) < 2.0 )
+ {
+ bSmallTwipToPxRelW = sal_True;
+ }
+ if ( (aCheckTwipToPxRelSz.Height()/100.0) < 2.0 )
+ {
+ bSmallTwipToPxRelH = sal_True;
+ }
+ }
+
+ Size aSz( pOut->PixelToLogic( Size( 1,1 )) );
+
+ nPixelSzW = aSz.Width();
+ if( !nPixelSzW )
+ nPixelSzW = 1;
+ nPixelSzH = aSz.Height();
+ if( !nPixelSzH )
+ nPixelSzH = 1;
+
+ // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
+ if ( !bSmallTwipToPxRelW )
+ {
+ nHalfPixelSzW = nPixelSzW / 2 + 1;
+ }
+ else
+ {
+ nHalfPixelSzW = 0;
+ }
+ // OD 06.05.2003 #107169# - consider 'small' twip-to-pixel relations
+ if ( !bSmallTwipToPxRelH )
+ {
+ nHalfPixelSzH = nPixelSzH / 2 + 1;
+ }
+ else
+ {
+ nHalfPixelSzH = 0;
+ }
+
+ nMinDistPixelW = nPixelSzW * 2 + 1;
+ nMinDistPixelH = nPixelSzH * 2 + 1;
+
+ const MapMode &rMap = pOut->GetMapMode();
+ aScaleX = rMap.GetScaleX();
+ aScaleY = rMap.GetScaleY();
+}
+
+//Zum Sichern der statics, damit das Paint (quasi) reentrant wird.
+class SwSavePaintStatics
+{
+ sal_Bool bSFlyMetafile,
+ bSPageOnly;
+ ViewShell *pSGlobalShell;
+ OutputDevice *pSFlyMetafileOut;
+ SwFlyFrm *pSRetoucheFly,
+ *pSRetoucheFly2,
+ *pSFlyOnlyDraw;
+ SwLineRects *pSLines;
+ SwSubsRects *pSSubsLines;
+ // --> OD 2005-07-04 #123196#
+ SwSubsRects* pSSpecSubsLines;
+ // <--
+ SfxProgress *pSProgress;
+ long nSPixelSzW,
+ nSPixelSzH,
+ nSHalfPixelSzW,
+ nSHalfPixelSzH,
+ nSMinDistPixelW,
+ nSMinDistPixelH;
+ Color aSGlobalRetoucheColor;
+ double aSScaleX,
+ aSScaleY;
+public:
+ SwSavePaintStatics();
+ ~SwSavePaintStatics();
+};
+
+SwSavePaintStatics::SwSavePaintStatics() :
+ bSFlyMetafile ( bFlyMetafile ),
+ pSGlobalShell ( pGlobalShell ),
+ pSFlyMetafileOut ( pFlyMetafileOut ),
+ pSRetoucheFly ( pRetoucheFly ),
+ pSRetoucheFly2 ( pRetoucheFly2 ),
+ pSFlyOnlyDraw ( pFlyOnlyDraw ),
+ pSLines ( pLines ),
+ pSSubsLines ( pSubsLines ),
+ // --> OD 2005-07-04 #123196#
+ pSSpecSubsLines ( pSpecSubsLines ),
+ // <--
+ pSProgress ( pProgress ),
+ nSPixelSzW ( nPixelSzW ),
+ nSPixelSzH ( nPixelSzH ),
+ nSHalfPixelSzW ( nHalfPixelSzW ),
+ nSHalfPixelSzH ( nHalfPixelSzH ),
+ nSMinDistPixelW ( nMinDistPixelW ),
+ nSMinDistPixelH ( nMinDistPixelH ),
+ aSGlobalRetoucheColor( aGlobalRetoucheColor ),
+ aSScaleX ( aScaleX ),
+ aSScaleY ( aScaleY )
+{
+ bFlyMetafile = sal_False;
+ pFlyMetafileOut = 0;
+ pRetoucheFly = 0;
+ pRetoucheFly2 = 0;
+ nPixelSzW = nPixelSzH =
+ nHalfPixelSzW = nHalfPixelSzH =
+ nMinDistPixelW = nMinDistPixelH = 0;
+ aScaleX = aScaleY = 1.0;
+ aMinDistScale = 0.73;
+ aEdgeScale = 0.5;
+ pLines = 0;
+ pSubsLines = 0;
+ // --> OD 2005-07-04 #123196#
+ pSpecSubsLines = 0L;
+ // <--
+ pProgress = 0;
+}
+
+SwSavePaintStatics::~SwSavePaintStatics()
+{
+ pGlobalShell = pSGlobalShell;
+ bFlyMetafile = bSFlyMetafile;
+ pFlyMetafileOut = pSFlyMetafileOut;
+ pRetoucheFly = pSRetoucheFly;
+ pRetoucheFly2 = pSRetoucheFly2;
+ pFlyOnlyDraw = pSFlyOnlyDraw;
+ pLines = pSLines;
+ pSubsLines = pSSubsLines;
+ // --> OD 2005-07-04 #123196#
+ pSpecSubsLines = pSSpecSubsLines;
+ // <--
+ pProgress = pSProgress;
+ nPixelSzW = nSPixelSzW;
+ nPixelSzH = nSPixelSzH;
+ nHalfPixelSzW = nSHalfPixelSzW;
+ nHalfPixelSzH = nSHalfPixelSzH;
+ nMinDistPixelW = nSMinDistPixelW;
+ nMinDistPixelH = nSMinDistPixelH;
+ aGlobalRetoucheColor = aSGlobalRetoucheColor;
+ aScaleX = aSScaleX;
+ aScaleY = aSScaleY;
+}
+
+//----------------- Implementierungen fuer Tabellenumrandung --------------
+
+SV_IMPL_VARARR( SwLRects, SwLineRect );
+
+SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyl,
+ const SwTabFrm *pT, const sal_uInt8 nSCol ) :
+ SwRect( rRect ),
+ nStyle( nStyl ),
+ pTab( pT ),
+ nSubColor( nSCol ),
+ bPainted( sal_False ),
+ nLock( 0 )
+{
+ if ( pCol != NULL )
+ aColor = *pCol;
+}
+
+sal_Bool SwLineRect::MakeUnion( const SwRect &rRect )
+{
+ //Es wurde bereits ausserhalb geprueft, ob die Rechtecke die gleiche
+ //Ausrichtung (horizontal bzw. vertikal), Farbe usw. besitzen.
+ if ( Height() > Width() ) //Vertikale Linie
+ {
+ if ( Left() == rRect.Left() && Width() == rRect.Width() )
+ {
+ //Zusammenfassen wenn kein Luecke zwischen den Linien ist.
+ const long nAdd = nPixelSzW + nHalfPixelSzW;
+ if ( Bottom() + nAdd >= rRect.Top() &&
+ Top() - nAdd <= rRect.Bottom() )
+ {
+ Bottom( Max( Bottom(), rRect.Bottom() ) );
+ Top ( Min( Top(), rRect.Top() ) );
+ return sal_True;
+ }
+ }
+ }
+ else
+ {
+ if ( Top() == rRect.Top() && Height() == rRect.Height() )
+ {
+ //Zusammenfassen wenn kein Luecke zwischen den Linien ist.
+ const long nAdd = nPixelSzW + nHalfPixelSzW;
+ if ( Right() + nAdd >= rRect.Left() &&
+ Left() - nAdd <= rRect.Right() )
+ {
+ Right( Max( Right(), rRect.Right() ) );
+ Left ( Min( Left(), rRect.Left() ) );
+ return sal_True;
+ }
+ }
+ }
+ return sal_False;
+}
+
+void SwLineRects::AddLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderStyle nStyle,
+ const SwTabFrm *pTab, const sal_uInt8 nSCol )
+{
+ //Rueckwaerts durch, weil Linien die zusammengefasst werden koennen i.d.R.
+ //im gleichen Kontext gepaintet werden.
+ for ( sal_uInt16 i = Count(); i ; )
+ {
+ SwLineRect &rLRect = operator[](--i);
+ //Pruefen von Ausrichtung, Farbe, Tabelle.
+ if ( rLRect.GetTab() == pTab &&
+ !rLRect.IsPainted() && rLRect.GetSubColor() == nSCol &&
+ (rLRect.Height() > rLRect.Width()) == (rRect.Height() > rRect.Width()) &&
+ ((!rLRect.GetColor() && !pCol) ||
+ (rLRect.GetColor() && pCol && *rLRect.GetColor() == *pCol)) )
+ {
+ if ( rLRect.MakeUnion( rRect ) )
+ return;
+ }
+ }
+ Insert( SwLineRect( rRect, pCol, nStyle, pTab, nSCol ), Count() );
+}
+
+void SwLineRects::ConnectEdges( OutputDevice *pOut )
+{
+ if ( pOut->GetOutDevType() != OUTDEV_PRINTER )
+ {
+ //Fuer einen zu kleinen Zoom arbeite ich nicht.
+ if ( aScaleX < aEdgeScale || aScaleY < aEdgeScale )
+ return;
+ }
+
+ static const long nAdd = 20;
+
+ SvPtrarr aCheck( 64, 64 );
+
+ for ( int i = 0; i < (int)Count(); ++i )
+ {
+ SwLineRect &rL1 = operator[](sal_uInt16(i));
+ if ( !rL1.GetTab() || rL1.IsPainted() || rL1.IsLocked() )
+ continue;
+
+ aCheck.Remove( 0, aCheck.Count() );
+
+ const sal_Bool bVert = rL1.Height() > rL1.Width();
+ long nL1a, nL1b, nL1c, nL1d;
+
+ if ( bVert )
+ {
+ nL1a = rL1.Top(); nL1b = rL1.Left();
+ nL1c = rL1.Right(); nL1d = rL1.Bottom();
+ }
+ else
+ {
+ nL1a = rL1.Left(); nL1b = rL1.Top();
+ nL1c = rL1.Bottom(); nL1d = rL1.Right();
+ }
+
+ //Alle moeglicherweise mit i1 zu verbindenden Linien einsammeln.
+ for ( sal_uInt16 i2 = 0; i2 < Count(); ++i2 )
+ {
+ SwLineRect &rL2 = operator[](i2);
+ if ( rL2.GetTab() != rL1.GetTab() ||
+ rL2.IsPainted() ||
+ rL2.IsLocked() ||
+ (bVert == (rL2.Height() > rL2.Width())) )
+ continue;
+
+ long nL2a, nL2b, nL2c, nL2d;
+ if ( bVert )
+ {
+ nL2a = rL2.Top(); nL2b = rL2.Left();
+ nL2c = rL2.Right(); nL2d = rL2.Bottom();
+ }
+ else
+ {
+ nL2a = rL2.Left(); nL2b = rL2.Top();
+ nL2c = rL2.Bottom(); nL2d = rL2.Right();
+ }
+
+ if ( (nL1a - nAdd < nL2d && nL1d + nAdd > nL2a) &&
+ ((nL1b > nL2b && nL1c < nL2c) ||
+ (nL1c >= nL2c && nL1b - nAdd < nL2c) ||
+ (nL1b <= nL2b && nL1c + nAdd > nL2b)) )
+ {
+ SwLineRect *pMSC = &rL2;
+ aCheck.Insert( pMSC, aCheck.Count() );
+ }
+ }
+ if ( aCheck.Count() < 2 )
+ continue;
+
+ sal_Bool bRemove = sal_False;
+
+ //Fuer jede Linie jede alle folgenden checken.
+ for ( sal_uInt16 k = 0; !bRemove && k < aCheck.Count(); ++k )
+ {
+ SwLineRect &rR1 = (SwLineRect&)*(SwLineRect*)aCheck[k];
+
+ for ( sal_uInt16 k2 = k+1; !bRemove && k2 < aCheck.Count(); ++k2 )
+ {
+ SwLineRect &rR2 = (SwLineRect&)*(SwLineRect*)aCheck[k2];
+ if ( bVert )
+ {
+ SwLineRect *pLA = 0;
+ SwLineRect *pLB = 0;
+ if ( rR1.Top() < rR2.Top() )
+ {
+ pLA = &rR1; pLB = &rR2;
+ }
+ else if ( rR1.Top() > rR2.Top() )
+ {
+ pLA = &rR2; pLB = &rR1;
+ }
+ //beschreiben k1 und k2 eine Doppellinie?
+ if ( pLA && pLA->Bottom() + 60 > pLB->Top() )
+ {
+ if ( rL1.Top() < pLA->Top() )
+ {
+ if ( rL1.Bottom() == pLA->Bottom() )
+ continue; //kleiner Irrtum (woher?)
+
+ SwRect aIns( rL1 );
+ aIns.Bottom( pLA->Bottom() );
+ if ( !rL1.IsInside( aIns ) )
+ continue;
+ const sal_uInt16 nTmpFree = Free();
+ Insert( SwLineRect( aIns, rL1.GetColor(), SOLID,
+ rL1.GetTab(), SUBCOL_TAB ), Count() );
+ if ( !nTmpFree )
+ {
+ --i;
+ k = aCheck.Count();
+ break;
+ }
+ }
+
+ if ( rL1.Bottom() > pLB->Bottom() )
+ rL1.Top( pLB->Top() ); //i1 nach oben verlaengern
+ else
+ bRemove = sal_True; //abbrechen, i1 entfernen
+ }
+ }
+ else
+ {
+ SwLineRect *pLA = 0;
+ SwLineRect *pLB = 0;
+ if ( rR1.Left() < rR2.Left() )
+ {
+ pLA = &rR1; pLB = &rR2;
+ }
+ else if ( rR1.Left() > rR2.Left() )
+ {
+ pLA = &rR2; pLB = &rR1;
+ }
+ //Liegt eine 'doppellinie' vor?
+ if ( pLA && pLA->Right() + 60 > pLB->Left() )
+ {
+ if ( rL1.Left() < pLA->Left() )
+ {
+ if ( rL1.Right() == pLA->Right() )
+ continue; //kleiner irrtum
+
+ SwRect aIns( rL1 );
+ aIns.Right( pLA->Right() );
+ if ( !rL1.IsInside( aIns ) )
+ continue;
+ const sal_uInt16 nTmpFree = Free();
+ Insert( SwLineRect( aIns, rL1.GetColor(), SOLID,
+ rL1.GetTab(), SUBCOL_TAB ), Count() );
+ if ( !nTmpFree )
+ {
+ --i;
+ k = aCheck.Count();
+ break;
+ }
+ }
+ if ( rL1.Right() > pLB->Right() )
+ rL1.Left( pLB->Left() );
+ else
+ bRemove = sal_True;
+ }
+ }
+ }
+ }
+ if ( bRemove )
+ {
+ Remove( static_cast<sal_uInt16>(i), 1 );
+ --i; //keinen auslassen!
+ }
+ }
+}
+
+inline void SwSubsRects::Ins( const SwRect &rRect, const sal_uInt8 nSCol )
+{
+ //Linien die kuerzer als die breiteste Linienbreite sind werden
+ //nicht aufgenommen.
+ if ( rRect.Height() > DEF_LINE_WIDTH_4 || rRect.Width() > DEF_LINE_WIDTH_4 )
+ Insert( SwLineRect( rRect, 0, SOLID, 0, nSCol ), Count());
+}
+
+void SwSubsRects::RemoveSuperfluousSubsidiaryLines( const SwLineRects &rRects )
+{
+ //Alle Hilfslinien, die sich mit irgendwelchen Umrandungen decken werden
+ //entfernt bzw. zerstueckelt..
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ // OD 18.11.2002 #99672# - get a copy instead of a reference, because
+ // an <insert> may destroy the object due to a necessary array resize.
+ const SwLineRect aSubsLineRect = SwLineRect( operator[](i) );
+
+ // OD 19.12.2002 #106318# - add condition <aSubsLineRect.IsLocked()>
+ // in order to consider only border lines, which are *not* locked.
+ if ( aSubsLineRect.IsPainted() ||
+ aSubsLineRect.IsLocked() )
+ continue;
+
+ const bool bVerticalSubs = aSubsLineRect.Height() > aSubsLineRect.Width();
+ SwRect aSubsRect( aSubsLineRect );
+ if ( bVerticalSubs )
+ {
+ aSubsRect.Left ( aSubsRect.Left() - (nPixelSzW+nHalfPixelSzW) );
+ aSubsRect.Right ( aSubsRect.Right() + (nPixelSzW+nHalfPixelSzW) );
+ }
+ else
+ {
+ aSubsRect.Top ( aSubsRect.Top() - (nPixelSzH+nHalfPixelSzH) );
+ aSubsRect.Bottom( aSubsRect.Bottom() + (nPixelSzH+nHalfPixelSzH) );
+ }
+ for ( sal_uInt16 k = 0; k < rRects.Count(); ++k )
+ {
+ SwLineRect &rLine = rRects[k];
+
+ // OD 20.12.2002 #106318# - do *not* consider painted or locked
+ // border lines.
+ // OD 20.01.2003 #i1837# - locked border lines have to be considered.
+ if ( rLine.IsLocked () )
+ continue;
+
+ if ( !bVerticalSubs == ( rLine.Height() > rLine.Width() ) ) //same direction?
+ continue;
+
+ if ( aSubsRect.IsOver( rLine ) )
+ {
+ if ( bVerticalSubs ) // Vertical?
+ {
+ if ( aSubsRect.Left() <= rLine.Right() &&
+ aSubsRect.Right() >= rLine.Left() )
+ {
+ long nTmp = rLine.Top()-(nPixelSzH+1);
+ if ( aSubsLineRect.Top() < nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Bottom( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ nTmp = rLine.Bottom()+nPixelSzH+1;
+ if ( aSubsLineRect.Bottom() > nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Top( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ Remove( i, 1 );
+ --i;
+ break;
+ }
+ }
+ else //Horizontal
+ {
+ if ( aSubsRect.Top() <= rLine.Bottom() &&
+ aSubsRect.Bottom() >= rLine.Top() )
+ {
+ long nTmp = rLine.Left()-(nPixelSzW+1);
+ if ( aSubsLineRect.Left() < nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Right( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ nTmp = rLine.Right()+nPixelSzW+1;
+ if ( aSubsLineRect.Right() > nTmp )
+ {
+ SwRect aNewSubsRect( aSubsLineRect );
+ aNewSubsRect.Left( nTmp );
+ Insert( SwLineRect( aNewSubsRect, 0, aSubsLineRect.GetStyle(), 0,
+ aSubsLineRect.GetSubColor() ), Count());
+ }
+ Remove( i, 1 );
+ --i;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void SwLineRects::LockLines( sal_Bool bLock )
+{
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ operator[](i).Lock( bLock );
+}
+
+void lcl_DrawDashedRect( OutputDevice * pOut, SwLineRect & rLRect )
+{
+ double nHalfLWidth = rLRect.Height( );
+ if ( nHalfLWidth > 1 )
+ {
+ nHalfLWidth = nHalfLWidth / 2;
+ }
+ else
+ {
+ nHalfLWidth = 1;
+ }
+
+ long startX = rLRect.Left( );
+ long startY = rLRect.Top( ) + nHalfLWidth;
+ long endX = rLRect.Left( ) + rLRect.Width( );
+ long endY = rLRect.Top( ) + nHalfLWidth;
+
+ if ( rLRect.Height( ) > rLRect.Width( ) )
+ {
+ nHalfLWidth = rLRect.Width( );
+ if ( nHalfLWidth > 1 )
+ {
+ nHalfLWidth = nHalfLWidth / 2;
+ }
+ else
+ {
+ nHalfLWidth = 1;
+ }
+ startX = rLRect.Left( ) + nHalfLWidth;
+ startY = rLRect.Top( );
+ endX = rLRect.Left( ) + nHalfLWidth;
+ endY = rLRect.Top( ) + rLRect.Height( );
+ }
+
+ svtools::DrawLine( *pOut, Point( startX, startY ), Point( endX, endY ),
+ sal_uInt32( nHalfLWidth * 2 ), rLRect.GetStyle( ) );
+}
+
+void SwLineRects::PaintLines( OutputDevice *pOut )
+{
+ //Painten der Umrandungen. Leider muessen wir zweimal durch.
+ //Einmal fuer die innenliegenden und einmal fuer die Aussenkanten
+ //der Tabellen.
+ if ( Count() != nLastCount )
+ {
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetFillColor();
+ pOut->SetLineColor();
+ ConnectEdges( pOut );
+ const Color *pLast = 0;
+
+ sal_Bool bPaint2nd = sal_False;
+ sal_uInt16 nMinCount = Count();
+ sal_uInt16 i;
+
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+
+ if ( rLRect.IsPainted() )
+ continue;
+
+ if ( rLRect.IsLocked() )
+ {
+ nMinCount = Min( nMinCount, i );
+ continue;
+ }
+
+ //Jetzt malen oder erst in der zweiten Runde?
+ sal_Bool bPaint = sal_True;
+ if ( rLRect.GetTab() )
+ {
+ if ( rLRect.Height() > rLRect.Width() )
+ {
+ //Senkrechte Kante, ueberlappt sie mit der TabellenKante?
+ SwTwips nLLeft = rLRect.Left() - 30,
+ nLRight = rLRect.Right() + 30,
+ nTLeft = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Left(),
+ nTRight = rLRect.GetTab()->Frm().Left() + rLRect.GetTab()->Prt().Right();
+ if ( (nTLeft >= nLLeft && nTLeft <= nLRight) ||
+ (nTRight>= nLLeft && nTRight<= nLRight) )
+ bPaint = sal_False;
+ }
+ else
+ { //Waagerechte Kante, ueberlappt sie mit der Tabellenkante?
+ SwTwips nLTop = rLRect.Top() - 30,
+ nLBottom = rLRect.Bottom() + 30,
+ nTTop = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Top(),
+ nTBottom = rLRect.GetTab()->Frm().Top() + rLRect.GetTab()->Prt().Bottom();
+ if ( (nTTop >= nLTop && nTTop <= nLBottom) ||
+ (nTBottom >= nLTop && nTBottom <= nLBottom) )
+ bPaint = sal_False;
+ }
+ }
+ if ( bPaint )
+ {
+ if ( !pLast || *pLast != *rLRect.GetColor() )
+ {
+ pLast = rLRect.GetColor();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ pOut->SetDrawMode( 0 );
+
+ pOut->SetLineColor( *pLast );
+ pOut->SetFillColor( *pLast );
+ pOut->SetDrawMode( nOldDrawMode );
+ }
+
+ if( !rLRect.IsEmpty() )
+ lcl_DrawDashedRect( pOut, rLRect );
+ rLRect.SetPainted();
+ }
+ else
+ bPaint2nd = sal_True;
+ }
+ if ( bPaint2nd )
+ for ( i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+ if ( rLRect.IsPainted() )
+ continue;
+
+ if ( rLRect.IsLocked() )
+ {
+ nMinCount = Min( nMinCount, i );
+ continue;
+ }
+
+ if ( !pLast || *pLast != *rLRect.GetColor() )
+ {
+ pLast = rLRect.GetColor();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOut->SetDrawMode( 0 );
+ }
+
+ pOut->SetFillColor( *pLast );
+ pOut->SetDrawMode( nOldDrawMode );
+ }
+ if( !rLRect.IsEmpty() )
+ lcl_DrawDashedRect( pOut, rLRect );
+ rLRect.SetPainted();
+ }
+ nLastCount = nMinCount;
+ pOut->Pop();
+ }
+}
+
+void SwSubsRects::PaintSubsidiary( OutputDevice *pOut,
+ const SwLineRects *pRects )
+{
+ if ( Count() )
+ {
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ //Alle Hilfslinien, die sich fast decken entfernen (Tabellen)
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLi = operator[](i);
+ const bool bVerticalSubs = rLi.Height() > rLi.Width();
+
+ for ( sal_uInt16 k = i+1; k < Count(); ++k )
+ {
+ SwLineRect &rLk = operator[](k);
+ if ( rLi.SSize() == rLk.SSize() )
+ {
+ if ( bVerticalSubs == ( rLk.Height() > rLk.Width() ) )
+ {
+ if ( bVerticalSubs )
+ {
+ long nLi = rLi.Right();
+ long nLk = rLk.Right();
+ if ( rLi.Top() == rLk.Top() &&
+ ((nLi < rLk.Left() && nLi+21 > rLk.Left()) ||
+ (nLk < rLi.Left() && nLk+21 > rLi.Left())))
+ {
+ Remove( k, 1 );
+ //Nicht mit der inneren Schleife weiter, weil
+ //das Array schrumpfen koennte!
+ --i; k = Count();
+ }
+ }
+ else
+ {
+ long nLi = rLi.Bottom();
+ long nLk = rLk.Bottom();
+ if ( rLi.Left() == rLk.Left() &&
+ ((nLi < rLk.Top() && nLi+21 > rLk.Top()) ||
+ (nLk < rLi.Top() && nLk+21 > rLi.Top())))
+ {
+ Remove( k, 1 );
+ --i; k = Count();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( pRects && pRects->Count() )
+ RemoveSuperfluousSubsidiaryLines( *pRects );
+
+ if ( Count() )
+ {
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ // OD 14.01.2003 #106660# - reset draw mode in high contrast
+ // mode in order to get fill color set at output device.
+ // Recover draw mode after draw of lines.
+ // Necessary for the subsidiary lines painted by the fly frames.
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOut->SetDrawMode( 0 );
+ }
+
+ for ( sal_uInt16 i = 0; i < Count(); ++i )
+ {
+ SwLineRect &rLRect = operator[](i);
+ // OD 19.12.2002 #106318# - add condition <!rLRect.IsLocked()>
+ // to prevent paint of locked subsidiary lines.
+ if ( !rLRect.IsPainted() &&
+ !rLRect.IsLocked() )
+ {
+ const Color *pCol = 0;
+ switch ( rLRect.GetSubColor() )
+ {
+ case SUBCOL_PAGE: pCol = &SwViewOption::GetDocBoundariesColor(); break;
+ case SUBCOL_FLY: pCol = &SwViewOption::GetObjectBoundariesColor(); break;
+ case SUBCOL_TAB: pCol = &SwViewOption::GetTableBoundariesColor(); break;
+ case SUBCOL_SECT: pCol = &SwViewOption::GetSectionBoundColor(); break;
+ case SUBCOL_BREAK: pCol = &SwViewOption::GetPageBreakColor(); break;
+ }
+
+ if ( pOut->GetFillColor() != *pCol )
+ pOut->SetFillColor( *pCol );
+ pOut->DrawRect( rLRect.SVRect() );
+
+ rLRect.SetPainted();
+ }
+ }
+
+ // OD 14.01.2003 #106660# - recovering draw mode
+ pOut->SetDrawMode( nOldDrawMode );
+
+ pOut->Pop();
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+//Diverse Functions die in diesem File so verwendet werden.
+
+// OD 20.02.2003 - Note: function <SwAlignRect(..)> also used outside this file.
+// OD 29.04.2003 #107169# - correction: adjust rectangle on pixel level in order
+// to assure, that the border 'leaves its original pixel', if it has to.
+// No prior adjustments for odd relation between pixel and twip.
+void MA_FASTCALL SwAlignRect( SwRect &rRect, const ViewShell *pSh )
+{
+ if( !rRect.HasArea() )
+ return;
+
+ // OD 03.09.2002 #102450#
+ // Assure that view shell (parameter <pSh>) exists, if the output device
+ // is taken from this view shell --> no output device, no alignment.
+ // Output device taken from view shell <pSh>, if <bFlyMetafile> not set.
+ if ( !bFlyMetafile && !pSh )
+ {
+ return;
+ }
+
+ const OutputDevice *pOut = bFlyMetafile ?
+ pFlyMetafileOut : pSh->GetOut();
+
+ // OD 28.04.2003 #107169# - hold original rectangle in pixel
+ const Rectangle aOrgPxRect = pOut->LogicToPixel( rRect.SVRect() );
+ // OD 29.04.2003 #107169# - determine pixel-center rectangle in twip
+ const SwRect aPxCenterRect( pOut->PixelToLogic( aOrgPxRect ) );
+
+ // OD 06.05.2003 #107169# - perform adjustments on pixel level.
+ SwRect aAlignedPxRect( aOrgPxRect );
+ if ( rRect.Top() > aPxCenterRect.Top() )
+ {
+ // 'leave pixel overlapping on top'
+ aAlignedPxRect.Top( aAlignedPxRect.Top() + 1 );
+ }
+
+ if ( rRect.Bottom() < aPxCenterRect.Bottom() )
+ {
+ // 'leave pixel overlapping on bottom'
+ aAlignedPxRect.Bottom( aAlignedPxRect.Bottom() - 1 );
+ }
+
+ if ( rRect.Left() > aPxCenterRect.Left() )
+ {
+ // 'leave pixel overlapping on left'
+ aAlignedPxRect.Left( aAlignedPxRect.Left() + 1 );
+ }
+
+ if ( rRect.Right() < aPxCenterRect.Right() )
+ {
+ // 'leave pixel overlapping on right'
+ aAlignedPxRect.Right( aAlignedPxRect.Right() - 1 );
+ }
+
+ // OD 11.10.2002 #103636# - consider negative width/height
+ // check, if aligned SwRect has negative width/height.
+ // If Yes, adjust it to width/height = 0 twip.
+ // NOTE: A SwRect with negative width/height can occur, if the width/height
+ // of the given SwRect in twip was less than a pixel in twip and that
+ // the alignment calculates that the aligned SwRect should not contain
+ // the pixels the width/height is on.
+ if ( aAlignedPxRect.Width() < 0 )
+ {
+ aAlignedPxRect.Width(0);
+ }
+ if ( aAlignedPxRect.Height() < 0 )
+ {
+ aAlignedPxRect.Height(0);
+ }
+ // OD 30.04.2003 #107169# - consider zero width/height
+ // For converting a rectangle from pixel to logic it needs a width/height.
+ // Thus, set width/height to one, if it's zero and correct this on the twip
+ // level after the conversion.
+ sal_Bool bZeroWidth = sal_False;
+ if ( aAlignedPxRect.Width() == 0 )
+ {
+ aAlignedPxRect.Width(1);
+ bZeroWidth = sal_True;
+ }
+ sal_Bool bZeroHeight = sal_False;
+ if ( aAlignedPxRect.Height() == 0 )
+ {
+ aAlignedPxRect.Height(1);
+ bZeroHeight = sal_True;
+ }
+
+ rRect = pOut->PixelToLogic( aAlignedPxRect.SVRect() );
+
+ // OD 30.04.2003 #107169# - consider zero width/height and adjust calculated
+ // aligned twip rectangle.
+ // OD 19.05.2003 #109667# - reset width/height to zero; previous negative
+ // width/height haven't to be considered.
+ if ( bZeroWidth )
+ {
+ rRect.Width(0);
+ }
+ if ( bZeroHeight )
+ {
+ rRect.Height(0);
+ }
+}
+
+/** OD 19.05.2003 #109667# - helper method for twip adjustments on pixel base
+
+ method compares the x- or y-pixel position of two twip-point. If the x-/y-pixel
+ positions are the same, the x-/y-pixel position of the second twip point is
+ adjusted by a given amount of pixels.
+
+ @author OD
+*/
+void lcl_CompPxPosAndAdjustPos( const OutputDevice& _rOut,
+ const Point& _rRefPt,
+ Point& _rCompPt,
+ const sal_Bool _bChkXPos,
+ const sal_Int8 _nPxAdjustment )
+{
+ const Point aRefPxPt = _rOut.LogicToPixel( _rRefPt );
+ Point aCompPxPt = _rOut.LogicToPixel( _rCompPt );
+
+ if ( _bChkXPos )
+ {
+ if ( aCompPxPt.X() == aRefPxPt.X() )
+ {
+ aCompPxPt.X() += _nPxAdjustment ;
+ const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
+ _rCompPt.X() = aAdjustedCompPt.X();
+ }
+ }
+ else
+ {
+ if ( aCompPxPt.Y() == aRefPxPt.Y() )
+ {
+ aCompPxPt.Y() += _nPxAdjustment ;
+ const Point aAdjustedCompPt = _rOut.PixelToLogic( aCompPxPt );
+ _rCompPt.Y() = aAdjustedCompPt.Y();
+ }
+ }
+}
+
+/** OD 25.09.2002 #99739# - method to pixel-align rectangle for drawing graphic object
+
+ Because for drawing a graphic left-top-corner and size coordinations are
+ used, these coordinations have to be determined on pixel level.
+ Thus, convert rectangle to pixel and then convert left-top-corner and
+ size of pixel rectangle back to logic.
+ This calculation is necessary, because there exists a different between
+ the convert from logic to pixel of a normal rectangle with its left-top-
+ and right-bottom-corner and the same convert of the same rectangle
+ with left-top-corner and size.
+ Call this method before each <GraphicObject.Draw(...)>
+
+ @author OD
+*/
+void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut )
+{
+ Rectangle aPxRect = rOut.LogicToPixel( pGrfRect->SVRect() );
+ pGrfRect->Pos( rOut.PixelToLogic( aPxRect.TopLeft() ) );
+ pGrfRect->SSize( rOut.PixelToLogic( aPxRect.GetSize() ) );
+}
+
+long MA_FASTCALL lcl_AlignWidth( const long nWidth )
+{
+ if ( nWidth )
+ {
+ const long nW = nWidth % nPixelSzW;
+
+ if ( !nW || nW > nHalfPixelSzW )
+ return Max(1L, nWidth - nHalfPixelSzW);
+ }
+ return nWidth;
+}
+
+long MA_FASTCALL lcl_AlignHeight( const long nHeight )
+{
+ if ( nHeight )
+ {
+ const long nH = nHeight % nPixelSzH;
+
+ if ( !nH || nH > nHalfPixelSzH )
+ return Max(1L, nHeight - nHalfPixelSzH);
+ }
+ return nHeight;
+}
+
+long MA_FASTCALL lcl_MinHeightDist( const long nDist )
+{
+ if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
+ return nDist;
+ return ::lcl_AlignHeight( Max( nDist, nMinDistPixelH ));
+}
+
+long MA_FASTCALL lcl_MinWidthDist( const long nDist )
+{
+ if ( aScaleX < aMinDistScale || aScaleY < aMinDistScale )
+ return nDist;
+ return ::lcl_AlignWidth( Max( nDist, nMinDistPixelW ));
+}
+
+//Ermittelt PrtArea plus Umrandung plus Schatten.
+void MA_FASTCALL lcl_CalcBorderRect( SwRect &rRect, const SwFrm *pFrm,
+ const SwBorderAttrs &rAttrs,
+ const sal_Bool bShadow )
+{
+ // OD 23.01.2003 #106386# - special handling for cell frames.
+ // The printing area of a cell frame is completely enclosed in the frame area
+ // and a cell frame has no shadow. Thus, for cell frames the calculated
+ // area equals the frame area.
+ // Notes: Borders of cell frames in R2L text direction will switch its side
+ // - left border is painted on the right; right border on the left.
+ // See <lcl_PaintLeftLine> and <lcl_PaintRightLine>.
+ if( pFrm->IsSctFrm() )
+ {
+ rRect = pFrm->Prt();
+ rRect.Pos() += pFrm->Frm().Pos();
+ }
+ else if ( pFrm->IsCellFrm() )
+ rRect = pFrm->Frm();
+ else
+ {
+ rRect = pFrm->Prt();
+ rRect.Pos() += pFrm->Frm().Pos();
+
+ if ( rAttrs.IsLine() || rAttrs.IsBorderDist() ||
+ (bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE) )
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = pFrm->IsVertical() ? ( pFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ const SvxBoxItem &rBox = rAttrs.GetBox();
+ const sal_Bool bTop = 0 != (pFrm->*fnRect->fnGetTopMargin)();
+ if ( bTop )
+ {
+ SwTwips nDiff = rBox.GetTop() ?
+ rBox.CalcLineSpace( BOX_LINE_TOP ) :
+ ( rAttrs.IsBorderDist() ?
+ // OD 23.01.2003 #106386# - increase of distance by
+ // one twip is incorrect.
+ rBox.GetDistance( BOX_LINE_TOP ) : 0 );
+ if( nDiff )
+ (rRect.*fnRect->fnSubTop)( nDiff );
+ }
+
+ const sal_Bool bBottom = 0 != (pFrm->*fnRect->fnGetBottomMargin)();
+ if ( bBottom )
+ {
+ SwTwips nDiff = 0;
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pFrm->IsTabFrm() &&
+ ((SwTabFrm*)pFrm)->IsCollapsingBorders() )
+ {
+ // For collapsing borders, we have to add the height of
+ // the height of the last line
+ nDiff = ((SwTabFrm*)pFrm)->GetBottomLineSize();
+ }
+ // <-- collapsing
+ else
+ {
+ nDiff = rBox.GetBottom() ?
+ rBox.CalcLineSpace( BOX_LINE_BOTTOM ) :
+ ( rAttrs.IsBorderDist() ?
+ // OD 23.01.2003 #106386# - increase of distance by
+ // one twip is incorrect.
+ rBox.GetDistance( BOX_LINE_BOTTOM ) : 0 );
+ }
+ if( nDiff )
+ (rRect.*fnRect->fnAddBottom)( nDiff );
+ }
+
+ if ( rBox.GetLeft() )
+ (rRect.*fnRect->fnSubLeft)( rBox.CalcLineSpace( BOX_LINE_LEFT ) );
+ else if ( rAttrs.IsBorderDist() )
+ // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
+ (rRect.*fnRect->fnSubLeft)( rBox.GetDistance( BOX_LINE_LEFT ) );
+
+ if ( rBox.GetRight() )
+ (rRect.*fnRect->fnAddRight)( rBox.CalcLineSpace( BOX_LINE_RIGHT ) );
+ else if ( rAttrs.IsBorderDist() )
+ // OD 23.01.2003 #106386# - increase of distance by one twip is incorrect.
+ (rRect.*fnRect->fnAddRight)( rBox.GetDistance( BOX_LINE_RIGHT ) );
+
+ if ( bShadow && rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ if ( bTop )
+ (rRect.*fnRect->fnSubTop)(rShadow.CalcShadowSpace(SHADOW_TOP));
+ (rRect.*fnRect->fnSubLeft)(rShadow.CalcShadowSpace(SHADOW_LEFT));
+ if ( bBottom )
+ (rRect.*fnRect->fnAddBottom)
+ (rShadow.CalcShadowSpace( SHADOW_BOTTOM ));
+ (rRect.*fnRect->fnAddRight)(rShadow.CalcShadowSpace(SHADOW_RIGHT));
+ }
+ }
+ }
+
+ ::SwAlignRect( rRect, pGlobalShell );
+}
+
+void MA_FASTCALL lcl_ExtendLeftAndRight( SwRect& _rRect,
+ const SwFrm& _rFrm,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ // OD 21.05.2003 #108789# - extend left/right border/shadow rectangle to
+ // bottom of previous frame/to top of next frame, if border/shadow is joined
+ // with previous/next frame.
+ if ( _rAttrs.JoinedWithPrev( _rFrm ) )
+ {
+ const SwFrm* pPrevFrm = _rFrm.GetPrev();
+ (_rRect.*_rRectFn->fnSetTop)( (pPrevFrm->*_rRectFn->fnGetPrtBottom)() );
+ }
+ if ( _rAttrs.JoinedWithNext( _rFrm ) )
+ {
+ const SwFrm* pNextFrm = _rFrm.GetNext();
+ (_rRect.*_rRectFn->fnSetBottom)( (pNextFrm->*_rRectFn->fnGetPrtTop)() );
+ }
+}
+
+void MA_FASTCALL lcl_SubtractFlys( const SwFrm *pFrm, const SwPageFrm *pPage,
+ const SwRect &rRect, SwRegionRects &rRegion )
+{
+ const SwSortedObjs& rObjs = *pPage->GetSortedObjs();
+ const SwFlyFrm* pSelfFly = pFrm->IsInFly() ? pFrm->FindFlyFrm() : pRetoucheFly2;
+ if ( !pRetoucheFly )
+ pRetoucheFly = pRetoucheFly2;
+
+ for ( sal_uInt16 j = 0; (j < rObjs.Count()) && rRegion.Count(); ++j )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[j];
+ const SdrObject* pSdrObj = pAnchoredObj->GetDrawObj();
+
+ // OD 2004-01-15 #110582# - do not consider invisible objects
+ if ( !pPage->GetFmt()->GetDoc()->IsVisibleLayerId( pSdrObj->GetLayer() ) )
+ continue;
+
+ if ( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+
+ if ( pSelfFly == pFly || pRetoucheFly == pFly || !rRect.IsOver( pFly->Frm() ) )
+ continue;
+
+ if ( !pFly->GetFmt()->GetPrint().GetValue() &&
+ (OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() ||
+ pGlobalShell->IsPreView()))
+ continue;
+
+ const sal_Bool bLowerOfSelf = pSelfFly && pFly->IsLowerOf( pSelfFly ) ?
+ sal_True : sal_False;
+
+ //Bei zeichengebundenem Fly nur diejenigen betrachten, in denen er
+ //nicht selbst verankert ist.
+ //#33429# Warum nur bei zeichengebundenen? Es macht doch nie Sinn
+ //Rahmen abzuziehen in denen er selbst verankert ist oder?
+ if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
+ continue;
+
+ //#57194# Und warum gilt das nicht analog fuer den RetoucheFly?
+ if ( pRetoucheFly && pRetoucheFly->IsLowerOf( pFly ) )
+ continue;
+
+#if OSL_DEBUG_LEVEL > 1
+ //Flys, die innerhalb des eigenen verankert sind, muessen eine
+ //groessere OrdNum haben oder Zeichengebunden sein.
+ if ( pSelfFly && bLowerOfSelf )
+ {
+ OSL_ENSURE( pFly->IsFlyInCntFrm() ||
+ pSdrObj->GetOrdNumDirect() > pSelfFly->GetVirtDrawObj()->GetOrdNumDirect(),
+ "Fly with wrong z-Order" );
+ }
+#endif
+
+ sal_Bool bStopOnHell = sal_True;
+ if ( pSelfFly )
+ {
+ const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
+ if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ bStopOnHell = sal_False;
+ }
+ }
+ if ( pRetoucheFly )
+ {
+ const SdrObject *pTmp = pRetoucheFly->GetVirtDrawObj();
+ if ( pSdrObj->GetLayer() == pTmp->GetLayer() )
+ {
+ if ( pSdrObj->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
+ //Im gleichen Layer werden nur obenliegende beachtet.
+ continue;
+ }
+ else
+ {
+ if ( !pFly->IsLowerOf( pRetoucheFly ) && !pFly->GetFmt()->GetOpaque().GetValue() )
+ //Aus anderem Layer interessieren uns nur nicht transparente
+ //oder innenliegende
+ continue;
+ bStopOnHell = sal_False;
+ }
+ }
+
+ //Wenn der Inhalt des Fly Transparent ist, wird er nicht abgezogen, es sei denn
+ //er steht im Hell-Layer (#31941#)
+ const IDocumentDrawModelAccess* pIDDMA = pFly->GetFmt()->getIDocumentDrawModelAccess();
+ sal_Bool bHell = pSdrObj->GetLayer() == pIDDMA->GetHellId();
+ if ( (bStopOnHell && bHell) ||
+ /// OD 05.08.2002 - change internal order of condition
+ /// first check "!bHell", then "..->Lower()" and "..->IsNoTxtFrm()"
+ /// have not to be performed, if frame is in "Hell"
+ ( !bHell && pFly->Lower() && pFly->Lower()->IsNoTxtFrm() &&
+ ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
+ ((SwNoTxtFrm*)pFly->Lower())->HasAnimation() ||
+ pFly->GetFmt()->GetSurround().IsContour()
+ )
+ )
+ )
+ continue;
+
+ // OD 08.10.2002 #103898#
+ // Own if-statements for transparent background/shadow of fly frames
+ // (#99657#) in order to handle special conditions.
+ if ( pFly->IsBackgroundTransparent() )
+ {
+ // Background <pFly> is transparent drawn. Thus normally, its region
+ // have not to be substracted from given region.
+ // But, if method is called for a fly frame and
+ // <pFly> is a direct lower of this fly frame and
+ // <pFly> inherites its transparent background brush from its parent,
+ // then <pFly> frame area have to be subtracted from given region.
+ // NOTE: Because in Status Quo transparent backgrounds can only be
+ // assigned to fly frames, the handle of this special case
+ // avoids drawing of transparent areas more than once, if
+ // a fly frame inherites a transparent background from its
+ // parent fly frame.
+ if ( pFrm->IsFlyFrm() &&
+ (pFly->GetAnchorFrm()->FindFlyFrm() == pFrm) &&
+ static_cast<const SwFlyFrmFmt*>(pFly->GetFmt())->IsBackgroundBrushInherited()
+ )
+ {
+ SwRect aRect;
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
+ rRegion -= aRect;
+ continue;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if ( pFly->IsShadowTransparent() )
+ {
+ continue;
+ }
+
+ if ( bHell && pFly->GetAnchorFrm()->IsInFly() )
+ {
+ //Damit die Umrandung nicht vom Hintergrund des anderen Flys
+ //zerlegt wird.
+ SwRect aRect;
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( aRect, pFly, rAttrs, sal_True );
+ rRegion -= aRect;
+ }
+ else
+ {
+ SwRect aRect( pFly->Prt() );
+ aRect += pFly->Frm().Pos();
+ rRegion -= aRect;
+ }
+ }
+ if ( pRetoucheFly == pRetoucheFly2 )
+ pRetoucheFly = 0;
+}
+
+//---------------- Ausgabe fuer das BrushItem ----------------
+
+/** lcl_DrawGraphicBackgrd - local help method to draw a background for a graphic
+
+ OD 17.10.2002 #103876#
+ Under certain circumstances we have to draw a background for a graphic.
+ This method takes care of the conditions and draws the background with the
+ corresponding color.
+ Method introduced for bug fix #103876# in order to optimize drawing tiled
+ background graphics. Previously, this code was integrated in method
+ <lcl_DrawGraphic>.
+ Method implemented as a inline, checking the conditions and calling method
+ method <lcl_implDrawGraphicBackgrd(..)> for the intrinsic drawing.
+
+ @author OD
+
+ @param _rBackgrdBrush
+ background brush contain the color the background has to be drawn.
+
+ @param _pOut
+ output device the background has to be drawn in.
+
+ @param _rPaintRect
+ paint retangle in the output device, which has to be drawn with the background.
+ rectangle have to be aligned by method ::SwAlignRect
+
+ @param _rGraphicObj
+ graphic object, for which the background has to be drawn. Used for checking
+ the transparency of its bitmap, its type and if the graphic is drawn transparent
+
+ @param _bNumberingGraphic
+ boolean indicating that graphic is used as a numbering.
+
+ @param _bBackgrdAlreadyDrawn
+ boolean (optional; default: false) indicating, if the background is already drawn.
+*/
+void lcl_implDrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
+ OutputDevice* _pOut,
+ const SwRect& _rAlignedPaintRect,
+ const GraphicObject& _rGraphicObj )
+{
+ /// determine color of background
+ /// If color of background brush is not "no fill"/"auto fill" or
+ /// <bFlyMetafile> is set, use color of background brush, otherwise
+ /// use global retouche color.
+ const Color aColor( ( (_rBackgrdBrush.GetColor() != COL_TRANSPARENT) || bFlyMetafile )
+ ? _rBackgrdBrush.GetColor()
+ : aGlobalRetoucheColor );
+
+ /// determine, if background color have to be drawn transparent
+ /// and calculate transparency percent value
+ sal_Int8 nTransparencyPercent = 0;
+ bool bDrawTransparent = false;
+ if ( aColor.GetTransparency() != 0 )
+ /// background color is transparent --> draw transparent.
+ {
+ bDrawTransparent = true;
+ nTransparencyPercent = (aColor.GetTransparency()*100 + 0x7F)/0xFF;
+ }
+ else if ( (_rGraphicObj.GetAttr().GetTransparency() != 0) &&
+ (_rBackgrdBrush.GetColor() == COL_TRANSPARENT) )
+ /// graphic is drawn transparent and background color is
+ /// "no fill"/"auto fill" --> draw transparent
+ {
+ bDrawTransparent = true;
+ nTransparencyPercent = (_rGraphicObj.GetAttr().GetTransparency()*100 + 0x7F)/0xFF;
+ }
+
+ if ( bDrawTransparent )
+ {
+ /// draw background transparent
+ if( _pOut->GetFillColor() != aColor.GetRGBColor() )
+ _pOut->SetFillColor( aColor.GetRGBColor() );
+ PolyPolygon aPoly( _rAlignedPaintRect.SVRect() );
+ _pOut->DrawTransparent( aPoly, nTransparencyPercent );
+ }
+ else
+ {
+ /// draw background opaque
+ if ( _pOut->GetFillColor() != aColor )
+ _pOut->SetFillColor( aColor );
+ _pOut->DrawRect( _rAlignedPaintRect.SVRect() );
+ }
+}
+
+inline void lcl_DrawGraphicBackgrd( const SvxBrushItem& _rBackgrdBrush,
+ OutputDevice* _pOut,
+ const SwRect& _rAlignedPaintRect,
+ const GraphicObject& _rGraphicObj,
+ bool _bNumberingGraphic,
+ bool _bBackgrdAlreadyDrawn = false )
+{
+ /// draw background with background color, if
+ /// (1) graphic is not used as a numbering AND
+ /// (2) background is not already drawn AND
+ /// (3) intrinsic graphic is transparent OR intrinsic graphic doesn't exists
+ if ( !_bNumberingGraphic &&
+ !_bBackgrdAlreadyDrawn &&
+ ( _rGraphicObj.IsTransparent() || _rGraphicObj.GetType() == GRAPHIC_NONE )
+ )
+ {
+ lcl_implDrawGraphicBackgrd( _rBackgrdBrush, _pOut, _rAlignedPaintRect, _rGraphicObj );
+ }
+}
+
+/// OD 06.08.2002 #99657# - Note: the transparency of the background graphic
+/// is saved in SvxBrushItem.GetGraphicObject(<shell>).GetAttr().Set/GetTransparency()
+/// and is considered in the drawing of the graphic.
+/// Thus, to provide transparent background graphic for text frames nothing
+/// has to be coded.
+/// OD 25.09.2002 #99739# - use align rectangle for drawing graphic
+/// OD 25.09.2002 #99739# - pixel-align coordinations for drawing graphic.
+/// OD 17.10.2002 #103876# - outsource code for drawing background of the graphic
+/// with a background color in method <lcl_DrawGraphicBackgrd>
+/// Also, change type of <bGrfNum> and <bClip> from <sal_Bool> to <bool>.
+void lcl_DrawGraphic( const SvxBrushItem& rBrush, OutputDevice *pOut,
+ ViewShell &rSh, const SwRect &rGrf, const SwRect &rOut,
+ bool bClip, bool bGrfNum,
+ bool bBackgrdAlreadyDrawn = false )
+ /// OD 02.09.2002 #99657#
+ /// add parameter <bBackgrdAlreadyDrawn> to indicate
+ /// that the background is already drawn.
+{
+ /// OD 25.09.2002 #99739# - calculate align rectangle from parameter <rGrf>
+ /// and use aligned rectangle <aAlignedGrfRect> in the following code
+ SwRect aAlignedGrfRect = rGrf;
+ ::SwAlignRect( aAlignedGrfRect, &rSh );
+
+ /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>.
+ const bool bNotInside = bClip && !rOut.IsInside( aAlignedGrfRect );
+ if ( bNotInside )
+ {
+ pOut->Push( PUSH_CLIPREGION );
+ pOut->IntersectClipRegion( rOut.SVRect() );
+ }
+
+ //Hier kein Link, wir wollen die Grafik synchron laden!
+ ((SvxBrushItem&)rBrush).SetDoneLink( Link() );
+ GraphicObject *pGrf = (GraphicObject*)rBrush.GetGraphicObject();
+
+ /// OD 17.10.2002 #103876# - outsourcing drawing of background with a background color.
+ ::lcl_DrawGraphicBackgrd( rBrush, pOut, aAlignedGrfRect, *pGrf, bGrfNum, bBackgrdAlreadyDrawn );
+
+ /// OD 25.09.2002 #99739# -
+ /// Because for drawing a graphic left-top-corner and size coordinations are
+ /// used, these coordinations have to be determined on pixel level.
+ ::SwAlignGrfRect( &aAlignedGrfRect, *pOut );
+ pGrf->DrawWithPDFHandling( *pOut, aAlignedGrfRect.Pos(), aAlignedGrfRect.SSize() );
+
+ if ( bNotInside )
+ pOut->Pop();
+} // end of method <lcl_DrawGraphic>
+
+void MA_FASTCALL DrawGraphic( const SvxBrushItem *pBrush,
+ OutputDevice *pOutDev,
+ const SwRect &rOrg,
+ const SwRect &rOut,
+ const sal_uInt8 nGrfNum,
+ const sal_Bool bConsiderBackgroundTransparency )
+ /// OD 05.08.2002 #99657# - add 6th parameter to indicate that method should
+ /// consider background transparency, saved in the color of the brush item
+{
+ ViewShell &rSh = *pGlobalShell;
+ /// OD 17.10.2002 #103876# - change type from <sal_Bool> to <bool>
+ bool bReplaceGrfNum = GRFNUM_REPLACE == nGrfNum;
+ bool bGrfNum = GRFNUM_NO != nGrfNum;
+ Size aGrfSize;
+ SvxGraphicPosition ePos = GPOS_NONE;
+ if( pBrush && !bReplaceGrfNum )
+ {
+ if( rSh.GetViewOptions()->IsGraphic() )
+ {
+ //#125488#: load graphic directly in PDF import
+ // --> OD 2006-08-25 #i68953# - also during print load graphic directly.
+ if ( (rSh).GetViewOptions()->IsPDFExport() ||
+ rSh.GetOut()->GetOutDevType() == OUTDEV_PRINTER )
+ // <--
+ {
+ ((SvxBrushItem*)pBrush)->PurgeMedium();
+ ((SvxBrushItem*)pBrush)->SetDoneLink( Link() );
+ }
+ else
+ ((SvxBrushItem*)pBrush)->SetDoneLink( STATIC_LINK(
+ rSh.GetDoc(), SwDoc, BackgroundDone ) );
+ //SfxObjectShell &rObjSh = *GETOBJSHELL();
+ const Graphic* pGrf = pBrush->GetGraphic();
+ if( pGrf && GRAPHIC_NONE != pGrf->GetType() )
+ {
+ ePos = pBrush->GetGraphicPos();
+ if( pGrf->IsSupportedGraphic() )
+ // don't the use the specific output device! Bug 94802
+ aGrfSize = ::GetGraphicSizeTwip( *pGrf, 0 );
+ }
+ }
+ else
+ bReplaceGrfNum = bGrfNum;
+ }
+
+ SwRect aGrf;
+ aGrf.SSize( aGrfSize );
+ sal_Bool bDraw = sal_True;
+ sal_Bool bRetouche = sal_True;
+ switch ( ePos )
+ {
+ case GPOS_LT:
+ aGrf.Pos() = rOrg.Pos();
+ break;
+
+ case GPOS_MT:
+ aGrf.Pos().Y() = rOrg.Top();
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RT:
+ aGrf.Pos().Y() = rOrg.Top();
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_LM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Left();
+ break;
+
+ case GPOS_MM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RM:
+ aGrf.Pos().Y() = rOrg.Top() + rOrg.Height()/2 - aGrfSize.Height()/2;
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_LB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Left();
+ break;
+
+ case GPOS_MB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Left() + rOrg.Width()/2 - aGrfSize.Width()/2;
+ break;
+
+ case GPOS_RB:
+ aGrf.Pos().Y() = rOrg.Bottom() - aGrfSize.Height();
+ aGrf.Pos().X() = rOrg.Right() - aGrfSize.Width();
+ break;
+
+ case GPOS_AREA:
+ aGrf = rOrg;
+ /// OD 05.09.2002 #102912#
+ /// In spite the fact that the background graphic have to fill the complete
+ /// area, it has been checked, if the graphic will completely fill out
+ /// the region to be painted <rOut> and thus, nothing has to be retouched.
+ /// For example, this is the case for a fly frame without a background
+ /// brush positioned on the border of the page and inherited the
+ /// background brush from the page.
+ bRetouche = !rOut.IsInside( aGrf );
+ break;
+
+ case GPOS_TILED:
+ {
+ // OD 17.10.2002 #103876# - draw background of tiled graphic
+ // before drawing tiled graphic in loop
+ // determine graphic object
+ GraphicObject* pGraphicObj = const_cast< GraphicObject* >(pBrush->GetGraphicObject());
+ // calculate aligned paint rectangle
+ SwRect aAlignedPaintRect = rOut;
+ ::SwAlignRect( aAlignedPaintRect, &rSh );
+ // OD 25.10.2002 #103876# - draw background color for aligned paint rectangle
+ lcl_DrawGraphicBackgrd( *pBrush, pOutDev, aAlignedPaintRect, *pGraphicObj, bGrfNum );
+
+ // set left-top-corner of background graphic to left-top-corner of the
+ // area, from which the background brush is determined.
+ aGrf.Pos() = rOrg.Pos();
+ // setup clipping at output device
+ pOutDev->Push( PUSH_CLIPREGION );
+ pOutDev->IntersectClipRegion( rOut.SVRect() );
+ // OD 28.10.2002 #103876# - use new method <GraphicObject::DrawTiled(::)>
+ {
+ // calculate paint offset
+ Point aPaintOffset( aAlignedPaintRect.Pos() - aGrf.Pos() );
+ // draw background graphic tiled for aligned paint rectangle
+ // --> OD 2005-02-15 #i42643# - apply fix #104004# for Calc
+ // also for Writer - see /sc/source/view/printfun.cxx
+ // For PDF export, every draw operation for bitmaps takes a
+ // noticeable amount of place (~50 characters). Thus, optimize
+ // between tile bitmap size and number of drawing operations here.
+ //
+ // A_out
+ // n_chars = k1 * ---------- + k2 * A_bitmap
+ // A_bitmap
+ //
+ // minimum n_chars is obtained for (derive for A_bitmap,
+ // set to 0, take positive solution):
+ // k1
+ // A_bitmap = Sqrt( ---- A_out )
+ // k2
+ //
+ // where k1 is the number of chars per draw operation, and
+ // k2 is the number of chars per bitmap pixel.
+ // This is approximately 50 and 7 for current PDF writer, respectively.
+ //
+ const double k1( 50 );
+ const double k2( 7 );
+ const Size aSize( aAlignedPaintRect.SSize() );
+ const double Abitmap( k1/k2 * static_cast<double>(aSize.Width())*aSize.Height() );
+
+ pGraphicObj->DrawTiled( pOutDev,
+ aAlignedPaintRect.SVRect(),
+ aGrf.SSize(),
+ Size( aPaintOffset.X(), aPaintOffset.Y() ),
+ NULL, GRFMGR_DRAW_STANDARD,
+ ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
+ // <--
+ }
+ // reset clipping at output device
+ pOutDev->Pop();
+ // set <bDraw> and <bRetouche> to false, indicating that background
+ // graphic and background are already drawn.
+ bDraw = bRetouche = sal_False;
+ }
+ break;
+
+ case GPOS_NONE:
+ bDraw = sal_False;
+ break;
+
+ default: OSL_ENSURE( !pOutDev, "new Graphic position?" );
+ }
+
+ /// OD 02.09.2002 #99657#
+ /// init variable <bGrfBackgrdAlreadDrawn> to indicate, if background of
+ /// graphic is already drawn or not.
+ bool bGrfBackgrdAlreadyDrawn = false;
+ if ( bRetouche )
+ {
+ // OD 2004-04-23 #116347#
+ pOutDev->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOutDev->SetLineColor();
+
+ // OD 07.08.2002 #99657# #GetTransChg#
+ // check, if a existing background graphic (not filling the complete
+ // background) is transparent drawn and the background color is
+ // "no fill" respectively "auto fill", if background transparency
+ // has to be considered.
+ // If YES, memorise transparency of background graphic.
+ // check also, if background graphic bitmap is transparent.
+ bool bTransparentGrfWithNoFillBackgrd = false;
+ sal_Int32 nGrfTransparency = 0;
+ bool bGrfIsTransparent = false;
+ if ( (ePos != GPOS_NONE) &&
+ (ePos != GPOS_TILED) && (ePos != GPOS_AREA)
+ )
+ {
+ GraphicObject *pGrf = (GraphicObject*)pBrush->GetGraphicObject();
+ if ( bConsiderBackgroundTransparency )
+ {
+ GraphicAttr pGrfAttr = pGrf->GetAttr();
+ if ( (pGrfAttr.GetTransparency() != 0) &&
+ ( pBrush && (pBrush->GetColor() == COL_TRANSPARENT) )
+ )
+ {
+ bTransparentGrfWithNoFillBackgrd = true;
+ nGrfTransparency = pGrfAttr.GetTransparency();
+ }
+ }
+ if ( pGrf->IsTransparent() )
+ {
+ bGrfIsTransparent = true;
+ }
+ }
+
+ /// OD 06.08.2002 #99657# #GetTransChg# - to get color of brush,
+ /// check background color against COL_TRANSPARENT ("no fill"/"auto fill")
+ /// instead of checking, if transparency is not set.
+ const Color aColor( pBrush &&
+ ( !(pBrush->GetColor() == COL_TRANSPARENT) ||
+ bFlyMetafile )
+ ? pBrush->GetColor()
+ : aGlobalRetoucheColor );
+
+ /// OD 08.08.2002 #99657# - determine, if background region have to be
+ /// drawn transparent.
+ /// background region has to be drawn transparent, if
+ /// background transparency have to be considered
+ /// AND
+ /// ( background color is transparent OR
+ /// background graphic is transparent and background color is "no fill"
+ /// )
+ sal_Bool bDrawTransparent = bConsiderBackgroundTransparency &&
+ ( ( aColor.GetTransparency() != 0) ||
+ bTransparentGrfWithNoFillBackgrd );
+
+ // --> OD 2008-06-02 #i75614#
+ // reset draw mode in high contrast mode in order to get fill color set
+ const sal_uLong nOldDrawMode = pOutDev->GetDrawMode();
+ if ( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pOutDev->SetDrawMode( 0 );
+ }
+ // <--
+
+ /// OD 06.08.2002 #99657# - if background region have to be drawn
+ /// transparent, set only the RGB values of the background color as
+ /// the fill color for the output device.
+ if ( bDrawTransparent )
+ {
+ if( pOutDev->GetFillColor() != aColor.GetRGBColor() )
+ pOutDev->SetFillColor( aColor.GetRGBColor() );
+ }
+ else
+ {
+ if( pOutDev->GetFillColor() != aColor )
+ pOutDev->SetFillColor( aColor );
+ }
+
+ // --> OD 2008-06-02 #i75614#
+ // restore draw mode
+ pOutDev->SetDrawMode( nOldDrawMode );
+ // <--
+
+ /// OD 02.09.2002 #99657#
+ if ( bDrawTransparent )
+ {
+ /// background region have to be drawn transparent.
+ /// Thus, create a poly-polygon from the region and draw it with
+ /// the corresponding transparency precent.
+ PolyPolygon aDrawPoly( rOut.SVRect() );
+ if ( aGrf.HasArea() )
+ {
+ if ( !bGrfIsTransparent )
+ {
+ /// substract area of background graphic from draw area
+ /// OD 08.10.2002 #103898# - consider only that part of the
+ /// graphic area that is overlapping with draw area.
+ SwRect aTmpGrf = aGrf;
+ aTmpGrf.Intersection( rOut );
+ if ( aTmpGrf.HasArea() )
+ {
+ Polygon aGrfPoly( aTmpGrf.SVRect() );
+ aDrawPoly.Insert( aGrfPoly );
+ }
+ }
+ else
+ bGrfBackgrdAlreadyDrawn = true;
+ }
+ /// calculate transparency percent:
+ /// ( <transparency value[0x01..0xFF]>*100 + 0x7F ) / 0xFF
+ /// If there is a background graphic with a background color "no fill"/"auto fill",
+ /// the transparency value is taken from the background graphic,
+ /// otherwise take the transparency value from the color.
+ sal_Int8 nTransparencyPercent = static_cast<sal_Int8>(
+ (( bTransparentGrfWithNoFillBackgrd ? nGrfTransparency : aColor.GetTransparency()
+ )*100 + 0x7F)/0xFF);
+ /// draw poly-polygon transparent
+ pOutDev->DrawTransparent( aDrawPoly, nTransparencyPercent );
+ }
+ else
+ {
+ SwRegionRects aRegion( rOut, 4 );
+ if ( !bGrfIsTransparent )
+ aRegion -= aGrf;
+ else
+ bGrfBackgrdAlreadyDrawn = true;
+ /// loop rectangles of background region, which has to be drawn
+ for( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ pOutDev->DrawRect( aRegion[i].SVRect() );
+ }
+ }
+ pOutDev ->Pop();
+ }
+
+ if( bDraw && aGrf.IsOver( rOut ) )
+ /// OD 02.09.2002 #99657#
+ /// add parameter <bGrfBackgrdAlreadyDrawn>
+ lcl_DrawGraphic( *pBrush, pOutDev, rSh, aGrf, rOut, true, bGrfNum,
+ bGrfBackgrdAlreadyDrawn );
+
+ if( bReplaceGrfNum )
+ {
+ const BitmapEx& rBmp = ViewShell::GetReplacementBitmap( false );
+ Font aTmp( pOutDev->GetFont() );
+ Graphic::DrawEx( pOutDev, aEmptyStr, aTmp, rBmp, rOrg.Pos(), rOrg.SSize() );
+ }
+}
+
+//------------------------------------------------------------------------
+
+/** local help method for SwRootFrm::Paint(..) - Adjust given rectangle to pixel size
+
+ By OD at 27.09.2002 for #103636#
+ In order to avoid paint errors caused by multiple alignments - e.g. method
+ ::SwAlignRect(..) - and other changes to the rectangle to be painted,
+ this method is called for the rectangle to be painted in order to
+ adjust it to the pixel it is overlapping.
+
+ @author OD
+*/
+void lcl_AdjustRectToPixelSize( SwRect& io_aSwRect, const OutputDevice &aOut )
+{
+ /// local constant object of class <Size> to determine number of Twips
+ /// representing a pixel.
+ const Size aTwipToPxSize( aOut.PixelToLogic( Size( 1,1 )) );
+
+ /// local object of class <Rectangle> in Twip coordinates
+ /// calculated from given rectangle aligned to pixel centers.
+ const Rectangle aPxCenterRect = aOut.PixelToLogic(
+ aOut.LogicToPixel( io_aSwRect.SVRect() ) );
+
+ /// local constant object of class <Rectangle> representing given rectangle
+ /// in pixel.
+ const Rectangle aOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
+
+ /// calculate adjusted rectangle from pixel centered rectangle.
+ /// Due to rounding differences <aPxCenterRect> doesn't exactly represents
+ /// the Twip-centers. Thus, adjust borders by half of pixel width/height plus 1.
+ /// Afterwards, adjust calculated Twip-positions of the all borders.
+ Rectangle aSizedRect = aPxCenterRect;
+ aSizedRect.Left() -= (aTwipToPxSize.Width()/2 + 1);
+ aSizedRect.Right() += (aTwipToPxSize.Width()/2 + 1);
+ aSizedRect.Top() -= (aTwipToPxSize.Height()/2 + 1);
+ aSizedRect.Bottom() += (aTwipToPxSize.Height()/2 + 1);
+
+ /// adjust left()
+ while ( (aOut.LogicToPixel(aSizedRect)).Left() < aOrgPxRect.Left() )
+ {
+ ++aSizedRect.Left();
+ }
+ /// adjust right()
+ while ( (aOut.LogicToPixel(aSizedRect)).Right() > aOrgPxRect.Right() )
+ {
+ --aSizedRect.Right();
+ }
+ /// adjust top()
+ while ( (aOut.LogicToPixel(aSizedRect)).Top() < aOrgPxRect.Top() )
+ {
+ ++aSizedRect.Top();
+ }
+ /// adjust bottom()
+ while ( (aOut.LogicToPixel(aSizedRect)).Bottom() > aOrgPxRect.Bottom() )
+ {
+ --aSizedRect.Bottom();
+ }
+
+ io_aSwRect = SwRect( aSizedRect );
+
+#if OSL_DEBUG_LEVEL > 1
+ Rectangle aTestOrgPxRect = aOut.LogicToPixel( io_aSwRect.SVRect() );
+ Rectangle aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect == aTestNewPxRect,
+ "Error in lcl_AlignRectToPixelSize(..): Adjusted rectangle has incorrect position or size");
+ Rectangle aTestNewRect( aSizedRect );
+ /// check Left()
+ --aSizedRect.Left();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Left() >= (aTestNewPxRect.Left()+1),
+ "Error in lcl_AlignRectToPixelSize(..): Left() not correct adjusted");
+ ++aSizedRect.Left();
+ /// check Right()
+ ++aSizedRect.Right();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Right() <= (aTestNewPxRect.Right()-1),
+ "Error in lcl_AlignRectToPixelSize(..): Right() not correct adjusted");
+ --aSizedRect.Right();
+ /// check Top()
+ --aSizedRect.Top();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Top() >= (aTestNewPxRect.Top()+1),
+ "Error in lcl_AlignRectToPixelSize(..): Top() not correct adjusted");
+ ++aSizedRect.Top();
+ /// check Bottom()
+ ++aSizedRect.Bottom();
+ aTestNewPxRect = aOut.LogicToPixel( aSizedRect );
+ OSL_ENSURE( aTestOrgPxRect.Bottom() <= (aTestNewPxRect.Bottom()-1),
+ "Error in lcl_AlignRectToPixelSize(..): Bottom() not correct adjusted");
+ --aSizedRect.Bottom();
+#endif
+}
+
+//
+// FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES START
+//
+
+struct SwLineEntry
+{
+ SwTwips mnKey;
+ SwTwips mnStartPos;
+ SwTwips mnEndPos;
+
+ svx::frame::Style maAttribute;
+
+ enum OverlapType { NO_OVERLAP, OVERLAP1, OVERLAP2, OVERLAP3 };
+
+public:
+ SwLineEntry( SwTwips nKey,
+ SwTwips nStartPos,
+ SwTwips nEndPos,
+ const svx::frame::Style& rAttribute );
+
+ OverlapType Overlaps( const SwLineEntry& rComp ) const;
+};
+
+SwLineEntry::SwLineEntry( SwTwips nKey,
+ SwTwips nStartPos,
+ SwTwips nEndPos,
+ const svx::frame::Style& rAttribute )
+ : mnKey( nKey ),
+ mnStartPos( nStartPos ),
+ mnEndPos( nEndPos ),
+ maAttribute( rAttribute )
+{
+}
+
+/*
+
+ 1. ---------- rOld
+ ---------- rNew
+
+ 2. ---------- rOld
+ ------------- rNew
+
+ 3. ------- rOld
+ ------------- rNew
+
+ 4. ------------- rOld
+ ---------- rNew
+
+ 5. ---------- rOld
+ ---- rNew
+
+ 6. ---------- rOld
+ ---------- rNew
+
+ 7. ------------- rOld
+ ---------- rNew
+
+ 8. ---------- rOld
+ ------------- rNew
+
+ 9. ---------- rOld
+ ---------- rNew
+*/
+
+SwLineEntry::OverlapType SwLineEntry::Overlaps( const SwLineEntry& rNew ) const
+{
+ SwLineEntry::OverlapType eRet = OVERLAP3;
+
+ if ( mnStartPos >= rNew.mnEndPos || mnEndPos <= rNew.mnStartPos )
+ eRet = NO_OVERLAP;
+
+ // 1, 2, 3
+ else if ( mnEndPos < rNew.mnEndPos )
+ eRet = OVERLAP1;
+
+ // 4, 5, 6, 7
+ else if ( mnStartPos <= rNew.mnStartPos && mnEndPos >= rNew.mnEndPos )
+ eRet = OVERLAP2;
+
+ // 8, 9
+ return eRet;
+}
+
+struct lt_SwLineEntry
+{
+ bool operator()( const SwLineEntry& e1, const SwLineEntry& e2 ) const
+ {
+ return e1.mnStartPos < e2.mnStartPos;
+ }
+};
+
+typedef std::set< SwLineEntry, lt_SwLineEntry > SwLineEntrySet;
+typedef std::set< SwLineEntry, lt_SwLineEntry >::iterator SwLineEntrySetIter;
+typedef std::set< SwLineEntry, lt_SwLineEntry >::const_iterator SwLineEntrySetConstIter;
+typedef std::map< SwTwips, SwLineEntrySet > SwLineEntryMap;
+typedef std::map< SwTwips, SwLineEntrySet >::iterator SwLineEntryMapIter;
+typedef std::map< SwTwips, SwLineEntrySet >::const_iterator SwLineEntryMapConstIter;
+
+class SwTabFrmPainter
+{
+ SwLineEntryMap maVertLines;
+ SwLineEntryMap maHoriLines;
+ const SwTabFrm& mrTabFrm;
+
+ void Insert( SwLineEntry&, bool bHori );
+ void Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem );
+ void HandleFrame( const SwLayoutFrm& rFrm );
+ void FindStylesForLine( const Point&,
+ const Point&,
+ svx::frame::Style*,
+ bool bHori ) const;
+
+public:
+ SwTabFrmPainter( const SwTabFrm& rTabFrm );
+
+ void PaintLines( OutputDevice& rDev, const SwRect& rRect ) const;
+};
+
+SwTabFrmPainter::SwTabFrmPainter( const SwTabFrm& rTabFrm )
+ : mrTabFrm( rTabFrm )
+{
+ HandleFrame( rTabFrm );
+}
+
+void SwTabFrmPainter::HandleFrame( const SwLayoutFrm& rLayoutFrm )
+{
+ // Add border lines of cell frames. Skip covered cells. Skip cells
+ // in special row span row, which do not have a negative row span:
+ if ( rLayoutFrm.IsCellFrm() && !rLayoutFrm.IsCoveredCell() )
+ {
+ const SwCellFrm* pThisCell = static_cast<const SwCellFrm*>(&rLayoutFrm);
+ const SwRowFrm* pRowFrm = static_cast<const SwRowFrm*>(pThisCell->GetUpper());
+ const long nRowSpan = pThisCell->GetTabBox()->getRowSpan();
+ if ( !pRowFrm->IsRowSpanLine() || nRowSpan > 1 || nRowSpan < -1 )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), &rLayoutFrm );
+ const SwBorderAttrs& rAttrs = *aAccess.Get();
+ const SvxBoxItem& rBox = rAttrs.GetBox();
+ Insert( rLayoutFrm, rBox );
+ }
+ }
+
+ // Recurse into lower layout frames, but do not recurse into lower tabframes.
+ const SwFrm* pLower = rLayoutFrm.Lower();
+ while ( pLower )
+ {
+ const SwLayoutFrm* pLowerLayFrm = dynamic_cast<const SwLayoutFrm*>(pLower);
+ if ( pLowerLayFrm && !pLowerLayFrm->IsTabFrm() )
+ HandleFrame( *pLowerLayFrm );
+
+ pLower = pLower->GetNext();
+ }
+}
+
+void SwTabFrmPainter::PaintLines( OutputDevice& rDev, const SwRect& rRect ) const
+{
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, rDev );
+ // <--
+
+ const SwFrm* pTmpFrm = &mrTabFrm;
+ const bool bVert = pTmpFrm->IsVertical();
+
+ SwLineEntryMapConstIter aIter = maHoriLines.begin();
+ bool bHori = true;
+
+ // color for subsidiary lines:
+ const Color& rCol( SwViewOption::GetTableBoundariesColor() );
+
+ // high contrast mode:
+ // overrides the color of non-subsidiary lines.
+ const Color* pHCColor = 0;
+ sal_uLong nOldDrawMode = rDev.GetDrawMode();
+ if( pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pHCColor = &SwViewOption::GetFontColor();
+ rDev.SetDrawMode( 0 );
+ }
+
+ // set clip region:
+ rDev.Push( PUSH_CLIPREGION );
+ Size aSize( rRect.SSize() );
+ // Hack! Necessary, because the layout is not pixel aligned!
+ aSize.Width() += nPixelSzW; aSize.Height() += nPixelSzH;
+ rDev.SetClipRegion( Rectangle( rRect.Pos(), aSize ) );
+
+ // The following stuff if necessary to have the new table borders fit
+ // into a ::SwAlignRect adjusted world.
+ const SwTwips nTwipXCorr = bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 ); // 1 < 2 < 3 ;-)
+ const SwTwips nTwipYCorr = !bVert ? 0 : Max( 0L, nHalfPixelSzW - 2 ); // 1 < 2 < 3 ;-)
+ const SwFrm* pUpper = mrTabFrm.GetUpper();
+ SwRect aUpper( pUpper->Prt() );
+ aUpper.Pos() += pUpper->Frm().Pos();
+ SwRect aUpperAligned( aUpper );
+ ::SwAlignRect( aUpperAligned, pGlobalShell );
+
+ while ( true )
+ {
+ if ( bHori && aIter == maHoriLines.end() )
+ {
+ aIter = maVertLines.begin();
+ bHori = false;
+ }
+
+ if ( !bHori && aIter == maVertLines.end() )
+ break;
+
+ const SwLineEntrySet& rEntrySet = (*aIter).second;
+ SwLineEntrySetConstIter aSetIter = rEntrySet.begin();
+ while ( aSetIter != rEntrySet.end() )
+ {
+ const SwLineEntry& rEntry = *aSetIter;
+ const svx::frame::Style& rEntryStyle( (*aSetIter).maAttribute );
+
+ Point aStart, aEnd;
+ if ( bHori )
+ {
+ aStart.X() = rEntry.mnStartPos;
+ aStart.Y() = rEntry.mnKey;
+ aEnd.X() = rEntry.mnEndPos;
+ aEnd.Y() = rEntry.mnKey;
+ }
+ else
+ {
+ aStart.X() = rEntry.mnKey;
+ aStart.Y() = rEntry.mnStartPos;
+ aEnd.X() = rEntry.mnKey;
+ aEnd.Y() = rEntry.mnEndPos;
+ }
+
+ SwRect aRepaintRect( aStart, aEnd );
+
+ // the repaint rectangle has to be moved a bit for the centered lines:
+ SwTwips nRepaintRectSize = !rEntryStyle.GetWidth() ? 1 : rEntryStyle.GetWidth();
+ if ( bHori )
+ {
+ aRepaintRect.Height( 2 * nRepaintRectSize );
+ aRepaintRect.Pos().Y() -= nRepaintRectSize;
+ }
+ else
+ {
+ aRepaintRect.Width( 2 * nRepaintRectSize );
+ aRepaintRect.Pos().X() -= nRepaintRectSize;
+ }
+
+ if ( rRect.IsOver( aRepaintRect ) )
+ {
+ svx::frame::Style aStyles[ 7 ];
+ aStyles[ 0 ] = rEntryStyle;
+ FindStylesForLine( aStart, aEnd, aStyles, bHori );
+
+ // subsidiary lines
+ const Color* pTmpColor = 0;
+ if ( 0 == aStyles[ 0 ].GetWidth() )
+ {
+ if ( IS_SUBS_TABLE && pGlobalShell->GetWin() )
+ aStyles[ 0 ].Set( rCol, rCol, rCol, false, 1, 0, 0 );
+ }
+ else
+ pTmpColor = pHCColor;
+
+ // The line sizes stored in the line style have to be adjusted as well.
+ // This will guarantee that lines with the same twip size will have the
+ // same pixel size.
+ for ( int i = 0; i < 7; ++i )
+ {
+ sal_uInt16 nPrim = aStyles[ i ].Prim();
+ sal_uInt16 nDist = aStyles[ i ].Dist();
+ sal_uInt16 nSecn = aStyles[ i ].Secn();
+
+ if ( nPrim > 0 )
+ nPrim = (sal_uInt16)( Max( 1L, nPixelSzH * ( nPrim / nPixelSzH ) ) );
+ if ( nDist > 0 )
+ nDist = (sal_uInt16)( Max( 1L, nPixelSzH * ( nDist / nPixelSzH ) ) );
+ if ( nSecn > 0 )
+ nSecn = (sal_uInt16)( Max( 1L, nPixelSzH * ( nSecn / nPixelSzH ) ) );
+
+ aStyles[ i ].Set( nPrim, nDist, nSecn );
+ }
+
+ // The (twip) positions will be adjusted to meet these requirements:
+ // 1. The y coordinates are located in the middle of the pixel grid
+ // 2. The x coordinated are located at the beginning of the pixel grid
+ // This is done, because the horizontal lines are painted "at beginning",
+ // whereas the vertical lines are painted "centered". By making the line
+ // sizes a multiple of one pixel size, we can assure, that all lines having
+ // the same twip size have the same pixel size, independent of their position
+ // on the screen.
+ Point aPaintStart = rDev.PixelToLogic( rDev.LogicToPixel( aStart ) );
+ Point aPaintEnd = rDev.PixelToLogic( rDev.LogicToPixel( aEnd ) );
+
+ if( pGlobalShell->GetWin() )
+ {
+ // The table borders do not use SwAlignRect, but all the other frames do.
+ // Therefore we tweak the outer borders a bit to achieve that the outer
+ // borders match the subsidiary lines of the upper:
+ if ( aStart.X() == aUpper.Left() )
+ aPaintStart.X() = aUpperAligned.Left();
+ else if ( aStart.X() == aUpper._Right() )
+ aPaintStart.X() = aUpperAligned._Right();
+ if ( aStart.Y() == aUpper.Top() )
+ aPaintStart.Y() = aUpperAligned.Top();
+ else if ( aStart.Y() == aUpper._Bottom() )
+ aPaintStart.Y() = aUpperAligned._Bottom();
+
+ if ( aEnd.X() == aUpper.Left() )
+ aPaintEnd.X() = aUpperAligned.Left();
+ else if ( aEnd.X() == aUpper._Right() )
+ aPaintEnd.X() = aUpperAligned._Right();
+ if ( aEnd.Y() == aUpper.Top() )
+ aPaintEnd.Y() = aUpperAligned.Top();
+ else if ( aEnd.Y() == aUpper._Bottom() )
+ aPaintEnd.Y() = aUpperAligned._Bottom();
+ }
+
+ aPaintStart.X() -= nTwipXCorr; // nHalfPixelSzW - 2 to assure that we do not leave the pixel
+ aPaintEnd.X() -= nTwipXCorr;
+ aPaintStart.Y() -= nTwipYCorr;
+ aPaintEnd.Y() -= nTwipYCorr;
+
+ // Here comes the painting stuff: Thank you, DR, great job!!!
+ if ( bHori )
+ {
+ mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
+ aPaintStart,
+ aPaintEnd,
+ aStyles[ 0 ], // current style
+ aStyles[ 1 ], // aLFromT
+ aStyles[ 2 ], // aLFromL
+ aStyles[ 3 ], // aLFromB
+ aStyles[ 4 ], // aRFromT
+ aStyles[ 5 ], // aRFromR
+ aStyles[ 6 ], // aRFromB
+ pTmpColor
+ )
+ );
+ }
+ else
+ {
+ mrTabFrm.ProcessPrimitives( svx::frame::CreateBorderPrimitives(
+ aPaintEnd,
+ aPaintStart,
+ aStyles[ 0 ], // current style
+ aStyles[ 4 ], // aBFromL
+ aStyles[ 5 ], // aBFromB
+ aStyles[ 6 ], // aBFromR
+ aStyles[ 1 ], // aTFromL
+ aStyles[ 2 ], // aTFromT
+ aStyles[ 3 ], // aTFromR
+ pTmpColor
+ )
+ );
+ }
+ }
+
+ ++aSetIter;
+ }
+
+ ++aIter;
+ }
+
+ // restore output device:
+ rDev.Pop();
+ rDev.SetDrawMode( nOldDrawMode );
+}
+
+// Finds the lines that join the line defined by (StartPoint, EndPoint) in either
+// StartPoint or Endpoint. The styles of these lines are required for DR's magic
+// line painting functions.
+void SwTabFrmPainter::FindStylesForLine( const Point& rStartPoint,
+ const Point& rEndPoint,
+ svx::frame::Style* pStyles,
+ bool bHori ) const
+{
+ // pStyles[ 1 ] = bHori ? aLFromT : TFromL
+ // pStyles[ 2 ] = bHori ? aLFromL : TFromT,
+ // pStyles[ 3 ] = bHori ? aLFromB : TFromR,
+ // pStyles[ 4 ] = bHori ? aRFromT : BFromL,
+ // pStyles[ 5 ] = bHori ? aRFromR : BFromB,
+ // pStyles[ 6 ] = bHori ? aRFromB : BFromR,
+
+ SwLineEntryMapConstIter aMapIter = maVertLines.find( rStartPoint.X() );
+ OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rVertSet = (*aMapIter).second;
+ SwLineEntrySetConstIter aIter = rVertSet.begin();
+
+ while ( aIter != rVertSet.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( bHori )
+ {
+ if ( rStartPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 3 ] = rEntry.maAttribute;
+ else if ( rStartPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 1 ] = rEntry.maAttribute;
+ }
+ else
+ {
+ if ( rStartPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 2 ] = rEntry.maAttribute;
+ else if ( rEndPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 5 ] = rEntry.maAttribute;
+ }
+ ++aIter;
+ }
+
+ aMapIter = maHoriLines.find( rStartPoint.Y() );
+ OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rHoriSet = (*aMapIter).second;
+ aIter = rHoriSet.begin();
+
+ while ( aIter != rHoriSet.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( bHori )
+ {
+ if ( rStartPoint.X() == rEntry.mnEndPos )
+ pStyles[ 2 ] = rEntry.maAttribute;
+ else if ( rEndPoint.X() == rEntry.mnStartPos )
+ pStyles[ 5 ] = rEntry.maAttribute;
+ }
+ else
+ {
+ if ( rStartPoint.X() == rEntry.mnEndPos )
+ pStyles[ 1 ] = rEntry.maAttribute;
+ else if ( rStartPoint.X() == rEntry.mnStartPos )
+ pStyles[ 3 ] = rEntry.maAttribute;
+ }
+ ++aIter;
+ }
+
+ if ( bHori )
+ {
+ aMapIter = maVertLines.find( rEndPoint.X() );
+ OSL_ENSURE( aMapIter != maVertLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rVertSet2 = (*aMapIter).second;
+ aIter = rVertSet2.begin();
+
+ while ( aIter != rVertSet2.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( rEndPoint.Y() == rEntry.mnStartPos )
+ pStyles[ 6 ] = rEntry.maAttribute;
+ else if ( rEndPoint.Y() == rEntry.mnEndPos )
+ pStyles[ 4 ] = rEntry.maAttribute;
+ ++aIter;
+ }
+ }
+ else
+ {
+ aMapIter = maHoriLines.find( rEndPoint.Y() );
+ OSL_ENSURE( aMapIter != maHoriLines.end(), "FindStylesForLine: Error" );
+ const SwLineEntrySet& rHoriSet2 = (*aMapIter).second;
+ aIter = rHoriSet2.begin();
+
+ while ( aIter != rHoriSet2.end() )
+ {
+ const SwLineEntry& rEntry = *aIter;
+ if ( rEndPoint.X() == rEntry.mnEndPos )
+ pStyles[ 4 ] = rEntry.maAttribute;
+ else if ( rEndPoint.X() == rEntry.mnStartPos )
+ pStyles[ 6 ] = rEntry.maAttribute;
+ ++aIter;
+ }
+ }
+}
+
+void SwTabFrmPainter::Insert( const SwFrm& rFrm, const SvxBoxItem& rBoxItem )
+{
+ std::vector< const SwFrm* > aTestVec;
+ aTestVec.push_back( &rFrm );
+ aTestVec.push_back( &rFrm );
+ aTestVec.push_back( &rFrm );
+
+ // build 4 line entries for the 4 borders:
+ SwRect aBorderRect = rFrm.Frm();
+ if ( rFrm.IsTabFrm() )
+ {
+ aBorderRect = rFrm.Prt();
+ aBorderRect.Pos() += rFrm.Frm().Pos();
+ }
+
+ const SwTwips nLeft = aBorderRect._Left();
+ const SwTwips nRight = aBorderRect._Right();
+ const SwTwips nTop = aBorderRect._Top();
+ const SwTwips nBottom = aBorderRect._Bottom();
+
+ svx::frame::Style aL( rBoxItem.GetLeft() );
+ svx::frame::Style aR( rBoxItem.GetRight() );
+ svx::frame::Style aT( rBoxItem.GetTop() );
+ svx::frame::Style aB( rBoxItem.GetBottom() );
+
+ const SwTwips nHalfTopWidth = aT.GetWidth() / 2;
+
+ aR.MirrorSelf();
+ aB.MirrorSelf();
+
+ bool bVert = mrTabFrm.IsVertical();
+ bool bR2L = mrTabFrm.IsRightToLeft();
+
+ aL.SetRefMode( svx::frame::REFMODE_CENTERED );
+ aR.SetRefMode( svx::frame::REFMODE_CENTERED );
+ aT.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
+ aB.SetRefMode( !bVert ? svx::frame::REFMODE_BEGIN : svx::frame::REFMODE_END );
+
+ SwLineEntry aLeft ( nLeft, nTop + nHalfTopWidth, nBottom + nHalfTopWidth, bVert ? aB : ( bR2L ? aR : aL ) );
+ SwLineEntry aRight ( nRight, nTop + nHalfTopWidth, nBottom + nHalfTopWidth, bVert ? aT : ( bR2L ? aL : aR ) );
+ SwLineEntry aTop ( nTop + nHalfTopWidth, nLeft, nRight, bVert ? aL : aT );
+ SwLineEntry aBottom( nBottom + nHalfTopWidth, nLeft, nRight, bVert ? aR : aB );
+
+ Insert( aLeft, false );
+ Insert( aRight, false );
+ Insert( aTop, true );
+ Insert( aBottom, true );
+
+ const SwRowFrm* pThisRowFrm = dynamic_cast<const SwRowFrm*>(rFrm.GetUpper());
+
+ // special case: #i9860#
+ // first line in follow table without repeated headlines
+ if ( pThisRowFrm &&
+ pThisRowFrm->GetUpper() == &mrTabFrm &&
+ mrTabFrm.IsFollow() &&
+ !mrTabFrm.GetTable()->GetRowsToRepeat() &&
+ (!pThisRowFrm->GetPrev() || static_cast<const SwRowFrm*>(pThisRowFrm->GetPrev())->IsRowSpanLine()) &&
+ !rBoxItem.GetTop() &&
+ rBoxItem.GetBottom() )
+ {
+ SwLineEntry aFollowTop( !bVert ? nTop : nRight, !bVert ? nLeft : nTop, !bVert ? nRight : nBottom, aB );
+ Insert( aFollowTop, !bVert );
+ }
+}
+
+void SwTabFrmPainter::Insert( SwLineEntry& rNew, bool bHori )
+{
+ // get all lines from structure, that have key entry of pLE
+ SwLineEntryMap* pLine2 = bHori ? &maHoriLines : &maVertLines;
+ const SwTwips nKey = rNew.mnKey;
+ SwLineEntryMapIter aMapIter = pLine2->find( nKey );
+
+ SwLineEntrySet* pLineSet = aMapIter != pLine2->end() ? &((*aMapIter).second) : 0;
+ if ( !pLineSet )
+ {
+ SwLineEntrySet aNewSet;
+ (*pLine2)[ nKey ] = aNewSet;
+ pLineSet = &(*pLine2)[ nKey ];
+ }
+ SwLineEntrySetIter aIter = pLineSet->begin();
+
+ while ( pLineSet && aIter != pLineSet->end() && rNew.mnStartPos < rNew.mnEndPos )
+ {
+ const SwLineEntry& rOld = *aIter;
+ const SwLineEntry::OverlapType nOverlapType = rOld.Overlaps( rNew );
+
+ const svx::frame::Style& rOldAttr = rOld.maAttribute;
+ const svx::frame::Style& rNewAttr = rNew.maAttribute;
+ const svx::frame::Style& rCmpAttr = rNewAttr > rOldAttr ? rNewAttr : rOldAttr;
+
+ if ( SwLineEntry::OVERLAP1 == nOverlapType )
+ {
+ OSL_ENSURE( rNew.mnStartPos >= rOld.mnStartPos, "Overlap type 3? How this?" );
+
+ // new left segment
+ const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rOld.mnEndPos, rCmpAttr );
+
+ // new right segment
+ rNew.mnStartPos = rOld.mnEndPos;
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+
+ aIter = pLineSet->begin();
+
+ continue; // start over
+ }
+ else if ( SwLineEntry::OVERLAP2 == nOverlapType )
+ {
+ // new left segment
+ const SwLineEntry aLeft( nKey, rOld.mnStartPos, rNew.mnStartPos, rOldAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rNew.mnStartPos, rNew.mnEndPos, rCmpAttr );
+
+ // new right segment
+ const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+ if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
+
+ rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
+
+ break; // we are finished
+ }
+ else if ( SwLineEntry::OVERLAP3 == nOverlapType )
+ {
+ // new left segment
+ const SwLineEntry aLeft( nKey, rNew.mnStartPos, rOld.mnStartPos, rNewAttr );
+
+ // new middle segment
+ const SwLineEntry aMiddle( nKey, rOld.mnStartPos, rNew.mnEndPos, rCmpAttr );
+
+ // new right segment
+ const SwLineEntry aRight( nKey, rNew.mnEndPos, rOld.mnEndPos, rOldAttr );
+
+ // update current lines set
+ pLineSet->erase( aIter );
+ if ( aLeft.mnStartPos < aLeft.mnEndPos ) pLineSet->insert( aLeft );
+ if ( aMiddle.mnStartPos < aMiddle.mnEndPos ) pLineSet->insert( aMiddle );
+ if ( aRight.mnStartPos < aRight.mnEndPos ) pLineSet->insert( aRight );
+
+ rNew.mnStartPos = rNew.mnEndPos; // rNew should not be inserted!
+
+ break; // we are finished
+ }
+
+ ++aIter;
+ }
+
+ if ( rNew.mnStartPos < rNew.mnEndPos ) // insert rest
+ pLineSet->insert( rNew );
+}
+
+//
+// FUNCTIONS USED FOR COLLAPSING TABLE BORDER LINES END
+//
+
+/*************************************************************************
+|*
+|* SwRootFrm::Paint()
+|*
+|* Beschreibung
+|* Fuer jede sichtbare Seite, die von Rect ber?hrt wird einmal Painten.
+|* 1. Umrandungen und Hintergruende Painten.
+|* 2. Den Draw Layer (Ramen und Zeichenobjekte) der unter dem Dokument
+|* liegt painten (Hoelle).
+|* 3. Den Dokumentinhalt (Text) Painten.
+|* 4. Den Drawlayer der ueber dem Dokuemnt liegt painten.
+|*
+|*************************************************************************/
+
+void
+SwRootFrm::Paint(SwRect const& rRect, SwPrintData const*const pPrintData) const
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Lower der Root keine Seite." );
+
+ PROTOCOL( this, PROT_FILE_INIT, 0, 0)
+
+ sal_Bool bResetRootPaint = sal_False;
+ ViewShell *pSh = pCurrShell;
+
+ if ( pSh->GetWin() )
+ {
+ if ( pSh->GetOut() == pSh->GetWin() && !pSh->GetWin()->IsVisible() )
+ {
+ return;
+ }
+ if ( SwRootFrm::bInPaint )
+ {
+ SwPaintQueue::Add( pSh, rRect );
+ return;
+ }
+ }
+ else
+ SwRootFrm::bInPaint = bResetRootPaint = sal_True;
+
+ SwSavePaintStatics *pStatics = 0;
+ if ( pGlobalShell )
+ pStatics = new SwSavePaintStatics();
+ pGlobalShell = pSh;
+
+ if( !pSh->GetWin() )
+ pProgress = SfxProgress::GetActiveProgress( (SfxObjectShell*) pSh->GetDoc()->GetDocShell() );
+
+ ::SwCalcPixStatics( pSh->GetOut() );
+ aGlobalRetoucheColor = pSh->Imp()->GetRetoucheColor();
+
+ //Ggf. eine Action ausloesen um klare Verhaeltnisse zu schaffen.
+ //Durch diesen Kunstgriff kann in allen Paints davon ausgegangen werden,
+ //das alle Werte gueltigt sind - keine Probleme, keine Sonderbehandlung(en).
+ // --> OD 2008-10-07 #i92745#
+ // Extend check on certain states of the 'current' <ViewShell> instance to
+ // all existing <ViewShell> instances.
+ bool bPerformLayoutAction( true );
+ {
+ ViewShell* pTmpViewShell = pSh;
+ do {
+ if ( pTmpViewShell->IsInEndAction() ||
+ pTmpViewShell->IsPaintInProgress() ||
+ ( pTmpViewShell->Imp()->IsAction() &&
+ pTmpViewShell->Imp()->GetLayAction().IsActionInProgress() ) )
+ {
+ bPerformLayoutAction = false;
+ }
+
+ pTmpViewShell = static_cast<ViewShell*>(pTmpViewShell->GetNext());
+ } while ( bPerformLayoutAction && pTmpViewShell != pSh );
+ }
+ if ( bPerformLayoutAction )
+ // <--
+ {
+ ((SwRootFrm*)this)->ResetTurbo();
+ SwLayAction aAction( (SwRootFrm*)this, pSh->Imp() );
+ aAction.SetPaint( sal_False );
+ aAction.SetComplete( sal_False );
+ aAction.SetReschedule( pProgress ? sal_True : sal_False );
+ aAction.Action();
+ ((SwRootFrm*)this)->ResetTurboFlag();
+ if ( !pSh->ActionPend() )
+ pSh->Imp()->DelRegion();
+ }
+
+ SwRect aRect( rRect );
+ aRect.Intersection( pSh->VisArea() );
+
+ const sal_Bool bExtraData = ::IsExtraData( GetFmt()->GetDoc() );
+
+ pLines = new SwLineRects; //Sammler fuer Umrandungen.
+
+ // #104289#. During painting, something (OLE) can
+ // load the linguistic, which in turn can cause a reformat
+ // of the document. Dangerous! We better set this flag to
+ // avoid the reformat.
+ const sal_Bool bOldAction = IsCallbackActionEnabled();
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
+
+ const SwPageFrm *pPage = pSh->Imp()->GetFirstVisPage();
+
+ const bool bBookMode = pGlobalShell->GetViewOptions()->IsViewLayoutBookMode();
+ if ( bBookMode && pPage->GetPrev() && static_cast<const SwPageFrm*>(pPage->GetPrev())->IsEmptyPage() )
+ pPage = static_cast<const SwPageFrm*>(pPage->GetPrev());
+
+ // #i68597#
+ const bool bGridPainting(pSh->GetWin() && pSh->Imp()->HasDrawView() && pSh->Imp()->GetDrawView()->IsGridVisible());
+
+ // --> OD 2008-05-16 #i84659#
+// while ( pPage && !::IsShortCut( aRect, pPage->Frm() ) )
+ while ( pPage )
+ // <--
+ {
+ const bool bPaintRightShadow = pPage->IsRightShadowNeeded();
+ const bool bPaintLeftShadow = pPage->IsLeftShadowNeeded();
+ const bool bRightSidebar = pPage->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT;
+
+ if ( !pPage->IsEmptyPage() )
+ {
+ SwRect aPaintRect;
+ SwPageFrm::GetBorderAndShadowBoundRect( pPage->Frm(), pSh, aPaintRect,
+ bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+
+ if ( aRect.IsOver( aPaintRect ) )
+ // <--
+ {
+ if ( pSh->GetWin() )
+ {
+ pSubsLines = new SwSubsRects;
+ // OD 18.11.2002 #99672# - create array for special sub-lines
+ pSpecSubsLines = new SwSubsRects;
+ }
+
+ aPaintRect._Intersection( aRect );
+
+ if ( bExtraData &&
+ pSh->GetWin() && pSh->IsInEndAction() )
+ {
+ // enlarge paint rectangle to complete page width, subtract
+ // current paint area and invalidate the resulting region.
+ SWRECTFN( pPage )
+ SwRect aPageRectTemp( aPaintRect );
+ (aPageRectTemp.*fnRect->fnSetLeftAndWidth)(
+ (pPage->Frm().*fnRect->fnGetLeft)(),
+ (pPage->Frm().*fnRect->fnGetWidth)() );
+ aPageRectTemp._Intersection( pSh->VisArea() );
+ Region aPageRectRegion( aPageRectTemp.SVRect() );
+ aPageRectRegion.Exclude( aPaintRect.SVRect() );
+ pSh->GetWin()->Invalidate( aPageRectRegion, INVALIDATE_CHILDREN );
+ }
+ // <--
+
+ // --> OD 2007-08-20 #i80793#
+ // enlarge paint rectangle for objects overlapping the same pixel
+ // in all cases and before the DrawingLayer overlay is initialized.
+ lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
+ // <--
+
+ // #i68597#
+ // moved paint pre-process for DrawingLayer overlay here since the above
+ // code dependent from bExtraData may expand the PaintRect
+ {
+ // #i75172# if called from ViewShell::ImplEndAction it sould no longer
+ // really be used but handled by ViewShell::ImplEndAction already
+ const Region aDLRegion(aPaintRect.SVRect());
+ pSh->DLPrePaint2(aDLRegion);
+ }
+
+ if(OUTDEV_WINDOW == pGlobalShell->GetOut()->GetOutDevType())
+ {
+ /// OD 27.09.2002 #103636# - changed method SwLayVout::Enter(..)
+ /// 2nd parameter is no longer <const> and will be set to the
+ /// rectangle the virtual output device is calculated from <aPaintRect>,
+ /// if the virtual output is used.
+ pVout->Enter( pSh, aPaintRect, !bNoVirDev );
+
+ /// OD 27.09.2002 #103636# - adjust paint rectangle to pixel size
+ /// Thus, all objects overlapping on pixel level with the unadjusted
+ /// paint rectangle will be considered in the paint.
+ lcl_AdjustRectToPixelSize( aPaintRect, *(pSh->GetOut()) );
+ }
+
+ // maybe this can be put in the above scope. Since we are not sure, just leave it ATM
+ pVout->SetOrgRect( aPaintRect );
+
+ /// OD 29.08.2002 #102450#
+ /// determine background color of page for <PaintLayer> method
+ /// calls, paint <hell> or <heaven>
+ const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
+
+ pPage->PaintBaBo( aPaintRect, pPage, sal_True );
+
+ if ( pSh->Imp()->HasDrawView() )
+ {
+ pLines->LockLines( sal_True );
+ // OD 29.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+ pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), pPrintData, aPaintRect,
+ &aPageBackgrdColor, (pPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( pSh->GetOut() );
+ pLines->LockLines( sal_False );
+ }
+
+ if( pSh->GetWin() )
+ {
+ // OD 18.11.2002 #99672# - collect sub-lines
+ pPage->RefreshSubsidiary( aPaintRect );
+ // OD 18.11.2002 #99672# - paint special sub-lines
+ pSpecSubsLines->PaintSubsidiary( pSh->GetOut(), NULL );
+ }
+
+ pPage->Paint( aPaintRect );
+
+ // OD 20.12.2002 #94627# - no paint of page border and shadow, if
+ // writer is in place mode.
+ if( pSh->GetWin() && pSh->GetDoc()->GetDocShell() &&
+ !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
+ {
+ // OD 12.02.2003 #i9719#, #105645# - use new method
+ // <SwPageFrm::PaintBorderAndShadow(..)>.
+ SwPageFrm::PaintBorderAndShadow( pPage->Frm(), pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ SwPageFrm::PaintNotesSidebar( pPage->Frm(), pSh, pPage->GetPhyPageNum(), bRightSidebar);
+ }
+
+ pLines->PaintLines( pSh->GetOut() );
+
+ if ( pSh->Imp()->HasDrawView() )
+ {
+ /// OD 29.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ pSh->Imp()->PaintLayer( pSh->GetDoc()->GetHeavenId(), pPrintData, aPaintRect,
+ &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ }
+
+ if ( bExtraData )
+ pPage->RefreshExtraData( aPaintRect );
+
+ if ( pSh->GetWin() )
+ {
+ pSubsLines->PaintSubsidiary( pSh->GetOut(), pLines );
+ DELETEZ( pSubsLines );
+ DELETEZ( pSpecSubsLines );
+ }
+ pVout->Leave();
+
+ // #i68597#
+ // needed to move grid painting inside Begin/EndDrawLayer bounds and to change
+ // output rect for it accordingly
+ if(bGridPainting)
+ {
+ SdrPaintView* pPaintView = pSh->Imp()->GetDrawView();
+ SdrPageView* pPageView = pPaintView->GetSdrPageView();
+ pPageView->DrawPageViewGrid(*pSh->GetOut(), aPaintRect.SVRect(), SwViewOption::GetTextGridColor() );
+ }
+
+ // #i68597#
+ // moved paint post-process for DrawingLayer overlay here, see above
+ {
+ pSh->DLPostPaint2(true);
+ }
+ }
+ }
+ else if ( bBookMode && pSh->GetWin() && !pSh->GetDoc()->GetDocShell()->IsInPlaceActive() )
+ {
+ // paint empty page
+ SwRect aPaintRect;
+ SwRect aEmptyPageRect( pPage->Frm() );
+
+ // code from vprint.cxx
+ const SwPageFrm& rFormatPage = pPage->GetFormatPage();
+ aEmptyPageRect.SSize() = rFormatPage.Frm().SSize();
+
+ SwPageFrm::GetBorderAndShadowBoundRect( aEmptyPageRect, pSh, aPaintRect,
+ bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ aPaintRect._Intersection( aRect );
+
+ if ( aRect.IsOver( aEmptyPageRect ) )
+ {
+ // #i75172# if called from ViewShell::ImplEndAction it sould no longer
+ // really be used but handled by ViewShell::ImplEndAction already
+ {
+ const Region aDLRegion(aPaintRect.SVRect());
+ pSh->DLPrePaint2(aDLRegion);
+ }
+
+ if( pSh->GetOut()->GetFillColor() != aGlobalRetoucheColor )
+ pSh->GetOut()->SetFillColor( aGlobalRetoucheColor );
+
+ pSh->GetOut()->SetLineColor(); // OD 20.02.2003 #107369# - no line color
+ // OD 20.02.2003 #107369# - use aligned page rectangle
+ {
+ SwRect aTmpPageRect( aEmptyPageRect );
+ ::SwAlignRect( aTmpPageRect, pSh );
+ aEmptyPageRect = aTmpPageRect;
+ }
+
+ pSh->GetOut()->DrawRect( aEmptyPageRect.SVRect() );
+
+ // paint empty page text
+ const Font& rEmptyPageFont = SwPageFrm::GetEmptyPageFont();
+ const Font aOldFont( pSh->GetOut()->GetFont() );
+
+ pSh->GetOut()->SetFont( rEmptyPageFont );
+ pSh->GetOut()->DrawText( aEmptyPageRect.SVRect(), SW_RESSTR( STR_EMPTYPAGE ),
+ TEXT_DRAW_VCENTER |
+ TEXT_DRAW_CENTER |
+ TEXT_DRAW_CLIP );
+
+ pSh->GetOut()->SetFont( aOldFont );
+ // paint shadow and border for empty page
+ // OD 19.02.2003 #107369# - use new method to paint page border and
+ // shadow
+ SwPageFrm::PaintBorderAndShadow( aEmptyPageRect, pSh, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+ SwPageFrm::PaintNotesSidebar( aEmptyPageRect, pSh, pPage->GetPhyPageNum(), bRightSidebar);
+
+ {
+ pSh->DLPostPaint2(true);
+ }
+ }
+ }
+
+ OSL_ENSURE( !pPage->GetNext() || pPage->GetNext()->IsPageFrm(),
+ "Nachbar von Seite keine Seite." );
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ DELETEZ( pLines );
+
+ if ( bResetRootPaint )
+ SwRootFrm::bInPaint = sal_False;
+ if ( pStatics )
+ delete pStatics;
+ else
+ {
+ pProgress = 0;
+ pGlobalShell = 0;
+ }
+
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Paint()
+|*
+|*************************************************************************/
+
+void MA_FASTCALL lcl_EmergencyFormatFtnCont( SwFtnContFrm *pCont )
+{
+ //Es kann sein, dass der Cont vernichtet wird.
+ SwCntntFrm *pCnt = pCont->ContainsCntnt();
+ while ( pCnt && pCnt->IsInFtn() )
+ {
+ pCnt->Calc();
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+class SwShortCut
+{
+ SwRectDist fnCheck;
+ long nLimit;
+public:
+ SwShortCut( const SwFrm& rFrm, const SwRect& rRect );
+ sal_Bool Stop( const SwRect& rRect ) const
+ { return (rRect.*fnCheck)( nLimit ) > 0; }
+};
+
+SwShortCut::SwShortCut( const SwFrm& rFrm, const SwRect& rRect )
+{
+ sal_Bool bVert = rFrm.IsVertical();
+ sal_Bool bR2L = rFrm.IsRightToLeft();
+ if( rFrm.IsNeighbourFrm() && bVert == bR2L )
+ {
+ if( bVert )
+ {
+ fnCheck = &SwRect::GetBottomDistance;
+ nLimit = rRect.Top();
+ }
+ else
+ {
+ fnCheck = &SwRect::GetLeftDistance;
+ nLimit = rRect.Left() + rRect.Width();
+ }
+ }
+ else if( bVert == rFrm.IsNeighbourFrm() )
+ {
+ fnCheck = &SwRect::GetTopDistance;
+ nLimit = rRect.Top() + rRect.Height();
+ }
+ else
+ {
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( rFrm.IsVertLR() )
+ {
+ fnCheck = &SwRect::GetLeftDistance;
+ nLimit = rRect.Right();
+ }
+ else
+ {
+ fnCheck = &SwRect::GetRightDistance;
+ nLimit = rRect.Left();
+ }
+ }
+}
+
+void SwLayoutFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ Frm_Info aFrmInfo( *this );
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, &aFrmInfo, 0, *pSh->GetOut() );
+ // <--
+
+ const SwFrm *pFrm = Lower();
+ if ( !pFrm )
+ return;
+
+ SwShortCut aShortCut( *pFrm, rRect );
+ sal_Bool bCnt;
+ if ( sal_True == (bCnt = pFrm->IsCntntFrm()) )
+ pFrm->Calc();
+
+ if ( pFrm->IsFtnContFrm() )
+ {
+ ::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm );
+ pFrm = Lower();
+ }
+
+ const SwPageFrm *pPage = 0;
+ const sal_Bool bWin = pGlobalShell->GetWin() ? sal_True : sal_False;
+
+ while ( IsAnLower( pFrm ) )
+ {
+ SwRect aPaintRect( pFrm->PaintArea() );
+ if( aShortCut.Stop( aPaintRect ) )
+ break;
+ if ( bCnt && pProgress )
+ pProgress->Reschedule();
+
+ //Wenn ein Frm es explizit will muss retouchiert werden.
+ //Erst die Retouche, denn selbige koennte die aligned'en Raender
+ //plaetten.
+ if ( pFrm->IsRetouche() )
+ {
+ if ( pFrm->IsRetoucheFrm() && bWin && !pFrm->GetNext() )
+ { if ( !pPage )
+ pPage = FindPageFrm();
+ pFrm->Retouche( pPage, rRect );
+ }
+ pFrm->ResetRetouche();
+ }
+
+ if ( rRect.IsOver( aPaintRect ) )
+ {
+ if ( bCnt && pFrm->IsCompletePaint() &&
+ !rRect.IsInside( aPaintRect ) && GetpApp()->AnyInput( INPUT_KEYBOARD ) )
+ {
+ //fix(8104): Es kann vorkommen, dass die Verarbeitung nicht
+ //vollstaendig war, aber trotzdem Teile des Absatzes gepaintet
+ //werden. In der Folge werden dann evtl. wiederum andere Teile
+ //des Absatzes garnicht mehr gepaintet. Einziger Ausweg scheint
+ //hier ein Invalidieren der Windows zu sein.
+ //Um es nicht alzu Heftig werden zu lassen versuche ich hier
+ //das Rechteck zu begrenzen indem der gewuenschte Teil gepaintet
+ //und nur die uebrigen Absatzanteile invalidiert werden.
+ if ( aPaintRect.Left() == rRect.Left() &&
+ aPaintRect.Right() == rRect.Right() )
+ {
+ aPaintRect.Bottom( rRect.Top() - 1 );
+ if ( aPaintRect.Height() > 0 )
+ pGlobalShell->InvalidateWindows(aPaintRect);
+ aPaintRect.Top( rRect.Bottom() + 1 );
+ aPaintRect.Bottom( pFrm->Frm().Bottom() );
+ if ( aPaintRect.Height() > 0 )
+ pGlobalShell->InvalidateWindows(aPaintRect);
+ aPaintRect.Top( pFrm->Frm().Top() );
+ aPaintRect.Bottom( pFrm->Frm().Bottom() );
+ }
+ else
+ {
+ pGlobalShell->InvalidateWindows( aPaintRect );
+ pFrm = pFrm->GetNext();
+ if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
+ pFrm->Calc();
+ continue;
+ }
+ }
+ pFrm->ResetCompletePaint();
+ aPaintRect._Intersection( rRect );
+
+ pFrm->Paint( aPaintRect );
+
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ //Ggf. die Spaltentrennlinien malen. Fuer den Seitenbody ist
+ //nicht der Upper sondern die Seite Zustaendig.
+ const SwFrmFmt *pFmt = GetUpper() && GetUpper()->IsPageFrm()
+ ? GetUpper()->GetFmt()
+ : GetFmt();
+ const SwFmtCol &rCol = pFmt->GetCol();
+ if ( rCol.GetLineAdj() != COLADJ_NONE )
+ {
+ if ( !pPage )
+ pPage = pFrm->FindPageFrm();
+
+ PaintColLines( aPaintRect, rCol, pPage );
+ }
+ }
+ }
+ if ( !bCnt && pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm() )
+ ::lcl_EmergencyFormatFtnCont( (SwFtnContFrm*)pFrm->GetNext() );
+
+ pFrm = pFrm->GetNext();
+ if ( pFrm && (sal_True == (bCnt = pFrm->IsCntntFrm())) )
+ pFrm->Calc();
+ }
+}
+
+/** FlyFrm::IsBackgroundTransparent - for feature #99657#
+
+ OD 12.08.2002
+ determines, if background of fly frame has to be drawn transparent
+ declaration found in /core/inc/flyfrm.cxx
+ OD 08.10.2002 #103898# - If the background of the fly frame itself is not
+ transparent and the background is inherited from its parent/grandparent,
+ the background brush, used for drawing, has to be investigated for transparency.
+
+ @author OD
+
+ @return true, if background is transparent drawn.
+*/
+sal_Bool SwFlyFrm::IsBackgroundTransparent() const
+{
+ sal_Bool bBackgroundTransparent = GetFmt()->IsBackgroundTransparent();
+ if ( !bBackgroundTransparent &&
+ static_cast<const SwFlyFrmFmt*>(GetFmt())->IsBackgroundBrushInherited() )
+ {
+ const SvxBrushItem* pBackgrdBrush = 0;
+ const Color* pSectionTOXColor = 0;
+ SwRect aDummyRect;
+ if ( GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false) )
+ {
+ if ( pSectionTOXColor &&
+ (pSectionTOXColor->GetTransparency() != 0) &&
+ (pSectionTOXColor->GetColor() != COL_TRANSPARENT) )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ else if ( pBackgrdBrush )
+ {
+ if ( (pBackgrdBrush->GetColor().GetTransparency() != 0) &&
+ (pBackgrdBrush->GetColor() != COL_TRANSPARENT) )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ else
+ {
+ const GraphicObject *pTmpGrf =
+ static_cast<const GraphicObject*>(pBackgrdBrush->GetGraphicObject());
+ if ( (pTmpGrf) &&
+ (pTmpGrf->GetAttr().GetTransparency() != 0)
+ )
+ {
+ bBackgroundTransparent = sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ return bBackgroundTransparent;
+};
+
+/** FlyFrm::IsShadowTransparent - for feature #99657#
+
+ OD 13.08.2002
+ determine, if shadow color of fly frame has to be drawn transparent
+ declaration found in /core/inc/flyfrm.cxx
+
+ @author OD
+
+ @return true, if shadow color is transparent.
+*/
+sal_Bool SwFlyFrm::IsShadowTransparent() const
+{
+ return GetFmt()->IsShadowTransparent();
+};
+
+/*************************************************************************
+|*
+|* SwFlyFrm::IsPaint()
+|*
+|*************************************************************************/
+
+sal_Bool SwFlyFrm::IsPaint( SdrObject *pObj, const ViewShell *pSh )
+{
+ SdrObjUserCall *pUserCall;
+
+ if ( 0 == ( pUserCall = GetUserCall(pObj) ) )
+ return sal_True;
+
+ //Attributabhaengig nicht fuer Drucker oder PreView painten
+ sal_Bool bPaint = pFlyOnlyDraw ||
+ ((SwContact*)pUserCall)->GetFmt()->GetPrint().GetValue();
+ if ( !bPaint )
+ bPaint = pSh->GetWin() && !pSh->IsPreView();
+
+ if ( bPaint )
+ {
+ //Das Paint kann evtl. von von uebergeordneten Flys verhindert werden.
+ SwFrm *pAnch = 0;
+ if ( pObj->ISA(SwVirtFlyDrawObj) )
+ {
+ SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
+ if ( pFlyOnlyDraw && pFlyOnlyDraw == pFly )
+ return sal_True;
+
+ //Die Anzeige eines Zwischenstadiums vermeiden, Flys die nicht mit
+ //der Seite auf der sie verankert sind ueberlappen werden auch
+ //nicht gepaintet.
+ //HACK: Ausnahme: Drucken von Rahmen in Tabellen, diese koennen
+ //bei uebergrossen Tabellen (HTML) schon mal auserhalb der Seite
+ //stehen.
+ SwPageFrm *pPage = pFly->FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage->Frm().IsOver( pFly->Frm() ) )
+ pAnch = pFly->AnchorFrm();
+ else if ( bTableHack &&
+ pFly->Frm().Top() >= pFly->GetAnchorFrm()->Frm().Top() &&
+ pFly->Frm().Top() < pFly->GetAnchorFrm()->Frm().Bottom() &&
+ long(pSh->GetOut()) ==
+ long(pSh->getIDocumentDeviceAccess()->getPrinter( false ) ) )
+ {
+ pAnch = pFly->AnchorFrm();
+ }
+ }
+
+ }
+ else
+ {
+ // OD 13.10.2003 #i19919# - consider 'virtual' drawing objects
+ // OD 2004-03-29 #i26791#
+ pAnch = ((SwDrawContact*)pUserCall)->GetAnchorFrm( pObj );
+ if ( pAnch )
+ {
+ if ( !pAnch->GetValidPosFlag() )
+ pAnch = 0;
+ else if ( long(pSh->GetOut()) == long(pSh->getIDocumentDeviceAccess()->getPrinter( false )))
+ {
+ //HACK: fuer das Drucken muessen wir ein paar Objekte
+ //weglassen, da diese sonst doppelt gedruckt werden.
+ //Die Objekte sollen gedruckt werden, wenn der TableHack
+ //gerade greift. In der Folge duerfen sie nicht gedruckt werden
+ //wenn sie mit der Seite dran sind, ueber der sie von der
+ //Position her gerade schweben.
+ const SwPageFrm *pPage = pAnch->FindPageFrm();
+ if ( !bTableHack &&
+ !pPage->Frm().IsOver( pObj->GetCurrentBoundRect() ) )
+ pAnch = 0;
+ }
+ }
+ else
+ {
+ // OD 02.07.2003 #108784# - debug assert
+ if ( !pObj->ISA(SdrObjGroup) )
+ {
+ OSL_FAIL( "<SwFlyFrm::IsPaint(..)> - paint of drawing object without anchor frame!?" );
+ }
+ }
+ }
+ if ( pAnch )
+ {
+ if ( pAnch->IsInFly() )
+ bPaint = SwFlyFrm::IsPaint( pAnch->FindFlyFrm()->GetVirtDrawObj(),
+ pSh );
+ else if ( pFlyOnlyDraw )
+ bPaint = sal_False;
+ }
+ else
+ bPaint = sal_False;
+ }
+ return bPaint;
+}
+
+/*************************************************************************
+|* SwCellFrm::Paint( const SwRect& ) const
+|*************************************************************************/
+void SwCellFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( GetLayoutRowSpan() >= 1 )
+ SwLayoutFrm::Paint( rRect );
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::Paint()
+|*
+|*************************************************************************/
+
+//Weiter unten definiert
+void MA_FASTCALL lcl_PaintLowerBorders( const SwLayoutFrm *pLay,
+ const SwRect &rRect, const SwPageFrm *pPage );
+
+void SwFlyFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ //wegen der Ueberlappung von Rahmen und Zeichenobjekten muessen die
+ //Flys ihre Umrandung (und die der Innenliegenden) direkt ausgeben.
+ //z.B. #33066#
+ pLines->LockLines(sal_True);
+
+ SwRect aRect( rRect );
+ aRect._Intersection( Frm() );
+
+ OutputDevice* pOut = pGlobalShell->GetOut();
+ pOut->Push( PUSH_CLIPREGION );
+ pOut->SetClipRegion();
+ const SwPageFrm* pPage = FindPageFrm();
+
+ const SwNoTxtFrm *pNoTxt = Lower() && Lower()->IsNoTxtFrm()
+ ? (SwNoTxtFrm*)Lower() : 0;
+
+ bool bIsChart = false; //#i102950# don't paint additional borders for charts
+ //check whether we have a chart
+ if(pNoTxt)
+ {
+ const SwNoTxtNode* pNoTNd = dynamic_cast<const SwNoTxtNode*>(pNoTxt->GetNode());
+ if( pNoTNd )
+ {
+ SwOLENode* pOLENd = const_cast<SwOLENode*>(pNoTNd->GetOLENode());
+ if( pOLENd && ChartPrettyPainter::IsChart( pOLENd->GetOLEObj().GetObject() ) )
+ bIsChart = true;
+ }
+ }
+
+ {
+ bool bContour = GetFmt()->GetSurround().IsContour();
+ PolyPolygon aPoly;
+ if ( bContour )
+ {
+ // OD 16.04.2003 #i13147# - add 2nd parameter with value <sal_True>
+ // to indicate that method is called for paint in order to avoid
+ // load of the intrinsic graphic.
+ bContour = GetContour( aPoly, sal_True );
+ }
+
+ // --> OD 2005-06-08 #i47804# - distinguish complete background paint
+ // and margin paint.
+ // paint complete background for Writer text fly frames
+ bool bPaintCompleteBack( !pNoTxt );
+ // <--
+ // paint complete background for transparent graphic and contour,
+ // if own background color exists.
+ const bool bIsGraphicTransparent = pNoTxt ? pNoTxt->IsTransparent() : false;
+ if ( !bPaintCompleteBack &&
+ ( bIsGraphicTransparent|| bContour ) )
+ {
+ const SvxBrushItem &rBack = GetFmt()->GetBackground();
+ // OD 07.08.2002 #99657# #GetTransChg#
+ // to determine, if background has to be painted, by checking, if
+ // background color is not COL_TRANSPARENT ("no fill"/"auto fill")
+ // or a background graphic exists.
+ bPaintCompleteBack = !(rBack.GetColor() == COL_TRANSPARENT) ||
+ rBack.GetGraphicPos() != GPOS_NONE;
+ }
+ // paint of margin needed.
+ const bool bPaintMarginOnly( !bPaintCompleteBack &&
+ Prt().SSize() != Frm().SSize() );
+
+ // --> OD 2005-06-08 #i47804# - paint background of parent fly frame
+ // for transparent graphics in layer Hell, if parent fly frame isn't
+ // in layer Hell. It's only painted the intersection between the
+ // parent fly frame area and the paint area <aRect>
+ const IDocumentDrawModelAccess* pIDDMA = GetFmt()->getIDocumentDrawModelAccess();
+
+ if ( bIsGraphicTransparent &&
+ GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() &&
+ GetAnchorFrm()->FindFlyFrm() )
+ {
+ const SwFlyFrm* pParentFlyFrm = GetAnchorFrm()->FindFlyFrm();
+ if ( pParentFlyFrm->GetDrawObj()->GetLayer() !=
+ pIDDMA->GetHellId() )
+ {
+ SwFlyFrm* pOldRet = pRetoucheFly2;
+ pRetoucheFly2 = const_cast<SwFlyFrm*>(this);
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pParentFlyFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ SwRect aPaintRect( aRect );
+ aPaintRect._Intersection( pParentFlyFrm->Frm() );
+ pParentFlyFrm->PaintBackground( aPaintRect, pPage, rAttrs, sal_False, sal_False );
+
+ pRetoucheFly2 = pOldRet;
+ }
+ }
+
+ if ( bPaintCompleteBack || bPaintMarginOnly )
+ {
+ //#24926# JP 01.02.96, PaintBaBo in teilen hier, damit PaintBorder
+ //das orig. Rect bekommt, aber PaintBackground das begrenzte.
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ pPage = FindPageFrm();
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // paint background
+ {
+ SwRegionRects aRegion( aRect );
+ // --> OD 2007-12-13 #i80822#
+ // suppress painting of background in printing area for
+ // non-transparent graphics.
+ if ( bPaintMarginOnly ||
+ ( pNoTxt && !bIsGraphicTransparent ) )
+ // <--
+ {
+ //Was wir eigentlich Painten wollen ist der schmale Streifen
+ //zwischen PrtArea und aeusserer Umrandung.
+ SwRect aTmp( Prt() ); aTmp += Frm().Pos();
+ aRegion -= aTmp;
+ }
+ if ( bContour )
+ {
+ pOut->Push();
+ // --> OD 2007-12-13 #i80822#
+ // apply clip region under the same conditions, which are
+ // used in <SwNoTxtFrm::Paint(..)> to set the clip region
+ // for painting the graphic/OLE. Thus, the clip region is
+ // also applied for the PDF export.
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( !pOut->GetConnectMetaFile() || !pSh || !pSh->GetWin() )
+ // <--
+ {
+ pOut->SetClipRegion( aPoly );
+ }
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
+ pOut->Pop();
+ }
+ else
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ PaintBackground( aRegion[i], pPage, rAttrs, sal_False, sal_True );
+ }
+
+ // OD 06.08.2002 #99657# - paint border before painting background
+ // paint border
+ {
+ SwRect aTmp( rRect );
+ PaintBorder( aTmp, pPage, rAttrs );
+ }
+
+ pOut->Pop();
+ }
+ }
+
+ // OD 19.12.2002 #106318# - fly frame will paint it's subsidiary lines and
+ // the subsidiary lines of its lowers on its own, due to overlapping with
+ // other fly frames or other objects.
+ if( pGlobalShell->GetWin()
+ && !bIsChart ) //#i102950# don't paint additional borders for charts
+ {
+ bool bSubsLineRectsCreated;
+ if ( pSubsLines )
+ {
+ // Lock already existing subsidiary lines
+ pSubsLines->LockLines( sal_True );
+ bSubsLineRectsCreated = false;
+ }
+ else
+ {
+ // create new subsidiardy lines
+ pSubsLines = new SwSubsRects;
+ bSubsLineRectsCreated = true;
+ }
+
+ bool bSpecSubsLineRectsCreated;
+ if ( pSpecSubsLines )
+ {
+ // Lock already existing special subsidiary lines
+ pSpecSubsLines->LockLines( sal_True );
+ bSpecSubsLineRectsCreated = false;
+ }
+ else
+ {
+ // create new special subsidiardy lines
+ pSpecSubsLines = new SwSubsRects;
+ bSpecSubsLineRectsCreated = true;
+ }
+ // Add subsidiary lines of fly frame and its lowers
+ RefreshLaySubsidiary( pPage, aRect );
+ // paint subsidiary lines of fly frame and its lowers
+ pSpecSubsLines->PaintSubsidiary( pOut, NULL );
+ pSubsLines->PaintSubsidiary( pOut, pLines );
+ if ( !bSubsLineRectsCreated )
+ // unlock subsidiary lines
+ pSubsLines->LockLines( sal_False );
+ else
+ // delete created subsidiary lines container
+ DELETEZ( pSubsLines );
+
+ if ( !bSpecSubsLineRectsCreated )
+ // unlock special subsidiary lines
+ pSpecSubsLines->LockLines( sal_False );
+ else
+ {
+ // delete created special subsidiary lines container
+ DELETEZ( pSpecSubsLines );
+ }
+ }
+
+ SwLayoutFrm::Paint( aRect );
+
+ Validate();
+
+ // OD 19.12.2002 #106318# - first paint lines added by fly frame paint
+ // and then unlock other lines.
+ pLines->PaintLines( pOut );
+ pLines->LockLines( sal_False );
+
+ pOut->Pop();
+
+ if ( pProgress && pNoTxt )
+ pProgress->Reschedule();
+}
+/*************************************************************************
+|*
+|* SwTabFrm::Paint()
+|*
+|*************************************************************************/
+
+void SwTabFrm::Paint(SwRect const& rRect, SwPrintData const*const) const
+{
+ if ( pGlobalShell->GetViewOptions()->IsTable() )
+ {
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsCollapsingBorders() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // paint shadow
+ if ( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ SwRect aRect;
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
+ PaintShadow( rRect, aRect, rAttrs );
+ }
+
+ // paint lines
+ SwTabFrmPainter aHelper( *this );
+ aHelper.PaintLines( *pGlobalShell->GetOut(), rRect );
+ }
+ // <-- collapsing
+
+ SwLayoutFrm::Paint( rRect );
+ }
+ // OD 10.01.2003 #i6467# - no light grey rectangle for page preview
+ else if ( pGlobalShell->GetWin() && !pGlobalShell->IsPreView() )
+ {
+ // OD 10.01.2003 #i6467# - intersect output rectangle with table frame
+ SwRect aTabRect( Prt() );
+ aTabRect.Pos() += Frm().Pos();
+ SwRect aTabOutRect( rRect );
+ aTabOutRect.Intersection( aTabRect );
+ pGlobalShell->GetViewOptions()->
+ DrawRect( pGlobalShell->GetOut(), aTabOutRect, COL_LIGHTGRAY );
+ }
+ ((SwTabFrm*)this)->ResetComplete();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintShadow()
+|*
+|* Beschreibung Malt einen Schatten wenns das FrmFormat fordert.
+|* Der Schatten wird immer an den auesseren Rand des OutRect gemalt.
+|* Das OutRect wird ggf. so verkleinert, dass auf diesem das
+|* malen der Umrandung stattfinden kann.
+|*
+|*************************************************************************/
+/// OD 23.08.2002 #99657#
+/// draw full shadow rectangle for frames with transparent drawn backgrounds.
+void SwFrm::PaintShadow( const SwRect& rRect, SwRect& rOutRect,
+ const SwBorderAttrs &rAttrs ) const
+{
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ const long nWidth = ::lcl_AlignWidth ( rShadow.GetWidth() );
+ const long nHeight = ::lcl_AlignHeight( rShadow.GetWidth() );
+
+ SwRects aRegion( 2, 2 );
+ SwRect aOut( rOutRect );
+
+ const sal_Bool bCnt = IsCntntFrm();
+ const sal_Bool bTop = !bCnt || rAttrs.GetTopLine ( *(this) ) ? sal_True : sal_False;
+ const sal_Bool bBottom = !bCnt || rAttrs.GetBottomLine( *(this) ) ? sal_True : sal_False;
+
+ SvxShadowLocation eLoc = rShadow.GetLocation();
+
+ SWRECTFN( this )
+ if( IsVertical() )
+ {
+ switch( eLoc )
+ {
+ case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
+ case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
+ case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
+ case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_TOPLEFT; break;
+ default: break;
+ }
+ }
+
+ /// OD 23.08.2002 #99657# - determine, if full shadow rectangle have to
+ /// be drawn or only two shadow rectangles beside the frame.
+ /// draw full shadow rectangle, if frame background is drawn transparent.
+ /// Status Quo:
+ /// SwLayoutFrm can have transparent drawn backgrounds. Thus,
+ /// "asked" their frame format.
+ sal_Bool bDrawFullShadowRectangle =
+ ( IsLayoutFrm() &&
+ (static_cast<const SwLayoutFrm*>(this))->GetFmt()->IsBackgroundTransparent()
+ );
+ switch ( eLoc )
+ {
+ case SVX_SHADOW_BOTTOMRIGHT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Top( aOut.Top() + nHeight );
+ aOut.Left( aOut.Left() + nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Top ( aOut.Bottom() - nHeight );
+ aOut.Left( aOut.Left() + nWidth );
+ if ( bBottom )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Left( aOut.Right() - nWidth );
+ aOut.Top ( rOutRect.Top() + nHeight );
+ if ( bBottom )
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ if ( bCnt && (!bTop || !bBottom) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Right ( rOutRect.Right() - nWidth );
+ rOutRect.Bottom( rOutRect.Bottom()- nHeight );
+ }
+ break;
+ case SVX_SHADOW_TOPLEFT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Bottom( aOut.Top() + nHeight );
+ aOut.Right ( aOut.Right() - nWidth );
+ if ( bTop )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Right ( aOut.Left() + nWidth );
+ aOut.Bottom( rOutRect.Bottom() - nHeight );
+ if ( bTop )
+ aOut.Top( aOut.Top() + nHeight );
+ if ( bCnt && (!bBottom || !bTop) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Left( rOutRect.Left() + nWidth );
+ rOutRect.Top( rOutRect.Top() + nHeight );
+ }
+ break;
+ case SVX_SHADOW_TOPRIGHT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Bottom( aOut.Bottom() - nHeight);
+ aOut.Left( aOut.Left() + nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Bottom( aOut.Top() + nHeight );
+ aOut.Left ( aOut.Left()+ nWidth );
+ if ( bTop )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Left ( aOut.Right() - nWidth );
+ aOut.Bottom( rOutRect.Bottom() - nHeight );
+ if ( bTop )
+ aOut.Top( aOut.Top() + nHeight );
+ if ( bCnt && (!bBottom || bTop) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Right( rOutRect.Right() - nWidth );
+ rOutRect.Top( rOutRect.Top() + nHeight );
+ }
+ break;
+ case SVX_SHADOW_BOTTOMLEFT:
+ {
+ if ( bDrawFullShadowRectangle )
+ {
+ /// OD 06.08.2002 #99657# - draw full shadow rectangle
+ aOut.Top( aOut.Top() + nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+ else
+ {
+ aOut.Top ( aOut.Bottom()- nHeight );
+ aOut.Right( aOut.Right() - nWidth );
+ if ( bBottom )
+ aRegion.Insert( aOut, aRegion.Count() );
+ aOut.Right( aOut.Left() + nWidth );
+ aOut.Top( rOutRect.Top() + nHeight );
+ if ( bBottom )
+ aOut.Bottom( aOut.Bottom() - nHeight );
+ if ( bCnt && (!bTop || !bBottom) )
+ ::lcl_ExtendLeftAndRight( aOut, *(this), rAttrs, fnRect );
+ aRegion.Insert( aOut, aRegion.Count() );
+ }
+
+ rOutRect.Left( rOutRect.Left() + nWidth );
+ rOutRect.Bottom( rOutRect.Bottom() - nHeight );
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "new ShadowLocation() ?" );
+ break;
+ }
+
+ OutputDevice *pOut = pGlobalShell->GetOut();
+
+ sal_uLong nOldDrawMode = pOut->GetDrawMode();
+ Color aShadowColor( rShadow.GetColor() );
+ if( aRegion.Count() && pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ // Is heigh contrast mode, the output device has already set the
+ // DRAWMODE_SETTINGSFILL flag. This causes the SetFillColor function
+ // to ignore the setting of a new color. Therefore we have to reset
+ // the drawing mode
+ pOut->SetDrawMode( 0 );
+ aShadowColor = SwViewOption::GetFontColor();
+ }
+
+ if ( pOut->GetFillColor() != aShadowColor )
+ pOut->SetFillColor( aShadowColor );
+
+ pOut->SetDrawMode( nOldDrawMode );
+
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ SwRect &rOut = aRegion[i];
+ aOut = rOut;
+ // OD 30.09.2002 #103636# - no SwAlign of shadow rectangle
+ // no alignment necessary, because (1) <rRect> is already aligned
+ // and because (2) paint of border and background will occur later.
+ // Thus, (1) assures that no conflicts with neighbour object will occure
+ // and (2) assures that border and background is not affected by the
+ // shadow paint.
+ /*
+ ::SwAlignRect( aOut, pGlobalShell );
+ */
+ if ( rRect.IsOver( aOut ) && aOut.Height() > 0 && aOut.Width() > 0 )
+ {
+ aOut._Intersection( rRect );
+ pOut->DrawRect( aOut.SVRect() );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorderLine()
+|*
+|*************************************************************************/
+
+void SwFrm::PaintBorderLine( const SwRect& rRect,
+ const SwRect& rOutRect,
+ const SwPageFrm *pPage,
+ const Color *pColor,
+ const SvxBorderStyle nStyle ) const
+{
+ if ( !rOutRect.IsOver( rRect ) )
+ return;
+
+ SwRect aOut( rOutRect );
+ aOut._Intersection( rRect );
+
+ const SwTabFrm *pTab = IsCellFrm() ? FindTabFrm() : 0;
+ sal_uInt8 nSubCol = ( IsCellFrm() || IsRowFrm() ) ? SUBCOL_TAB :
+ ( IsInSct() ? SUBCOL_SECT :
+ ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
+ if( pColor && pGlobalShell->GetWin() &&
+ Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ pColor = &SwViewOption::GetFontColor();
+ }
+
+ if ( pPage->GetSortedObjs() )
+ {
+ SwRegionRects aRegion( aOut, 4, 1 );
+ ::lcl_SubtractFlys( this, pPage, aOut, aRegion );
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ pLines->AddLineRect( aRegion[i], pColor, nStyle, pTab, nSubCol );
+ }
+ else
+ pLines->AddLineRect( aOut, pColor, nStyle, pTab, nSubCol );
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorderLines()
+|*
+|* Beschreibung Nur alle Linien einfach oder alle Linien doppelt!!!!
+|*
+|*************************************************************************/
+
+// OD 29.04.2003 #107169# - method called for left and right border rectangles.
+// For a printer output device perform adjustment for non-overlapping top and
+// bottom border rectangles. Thus, add parameter <_bPrtOutputDev> to indicate
+// printer output device.
+// NOTE: For printer output device left/right border rectangle <_iorRect>
+// has to be already non-overlapping the outer top/bottom border rectangle.
+void MA_FASTCALL lcl_SubTopBottom( SwRect& _iorRect,
+ const SvxBoxItem& _rBox,
+ const SwBorderAttrs& _rAttrs,
+ const SwFrm& _rFrm,
+ const SwRectFn& _rRectFn,
+ const sal_Bool _bPrtOutputDev )
+{
+ const sal_Bool bCnt = _rFrm.IsCntntFrm();
+ if ( _rBox.GetTop() && _rBox.GetTop()->GetInWidth() &&
+ ( !bCnt || _rAttrs.GetTopLine( _rFrm ) )
+ )
+ {
+ // substract distance between outer and inner line.
+ SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetTop()->GetDistance() );
+ // OD 19.05.2003 #109667# - non-overlapping border rectangles:
+ // adjust x-/y-position, if inner top line is a hair line (width = 1)
+ sal_Bool bIsInnerTopLineHairline = sal_False;
+ if ( !_bPrtOutputDev )
+ {
+ // additionally substract width of top outer line
+ // --> left/right inner/outer line doesn't overlap top outer line.
+ nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetOutWidth() );
+ }
+ else
+ {
+ // OD 29.04.2003 #107169# - additionally substract width of top inner line
+ // --> left/right inner/outer line doesn't overlap top inner line.
+ nDist += ::lcl_AlignHeight( _rBox.GetTop()->GetInWidth() );
+ bIsInnerTopLineHairline = _rBox.GetTop()->GetInWidth() == 1;
+ }
+ (_iorRect.*_rRectFn->fnSubTop)( -nDist );
+ // OD 19.05.2003 #109667# - adjust calculated border top, if inner top line
+ // is a hair line
+ if ( bIsInnerTopLineHairline )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // right of border rectangle has to be checked and adjusted
+ Point aCompPt( _iorRect.Right(), 0 );
+ Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, -1 );
+ _iorRect.Right( aCompPt.X() );
+ }
+ else
+ {
+ // top of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, _iorRect.Top() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, +1 );
+ _iorRect.Top( aCompPt.Y() );
+ }
+ }
+ }
+
+ if ( _rBox.GetBottom() && _rBox.GetBottom()->GetInWidth() &&
+ ( !bCnt || _rAttrs.GetBottomLine( _rFrm ) )
+ )
+ {
+ // substract distance between outer and inner line.
+ SwTwips nDist = ::lcl_MinHeightDist( _rBox.GetBottom()->GetDistance() );
+ // OD 19.05.2003 #109667# - non-overlapping border rectangles:
+ // adjust x-/y-position, if inner bottom line is a hair line (width = 1)
+ sal_Bool bIsInnerBottomLineHairline = sal_False;
+ if ( !_bPrtOutputDev )
+ {
+ // additionally substract width of bottom outer line
+ // --> left/right inner/outer line doesn't overlap bottom outer line.
+ nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetOutWidth() );
+ }
+ else
+ {
+ // OD 29.04.2003 #107169# - additionally substract width of bottom inner line
+ // --> left/right inner/outer line doesn't overlap bottom inner line.
+ nDist += ::lcl_AlignHeight( _rBox.GetBottom()->GetInWidth() );
+ bIsInnerBottomLineHairline = _rBox.GetBottom()->GetInWidth() == 1;
+ }
+ (_iorRect.*_rRectFn->fnAddBottom)( -nDist );
+ // OD 19.05.2003 #109667# - adjust calculated border bottom, if inner
+ // bottom line is a hair line.
+ if ( bIsInnerBottomLineHairline )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // left of border rectangle has to be checked and adjusted
+ Point aCompPt( _iorRect.Left(), 0 );
+ Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, +1 );
+ _iorRect.Left( aCompPt.X() );
+ }
+ else
+ {
+ // bottom of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, _iorRect.Bottom() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, -1 );
+ _iorRect.Bottom( aCompPt.Y() );
+ }
+ }
+ }
+}
+
+// method called for top and bottom border rectangles.
+void MA_FASTCALL lcl_SubLeftRight( SwRect& rRect,
+ const SvxBoxItem& rBox,
+ const SwRectFn& rRectFn )
+{
+ if ( rBox.GetLeft() && rBox.GetLeft()->GetInWidth() )
+ {
+ const long nDist = ::lcl_MinWidthDist( rBox.GetLeft()->GetDistance() )
+ + ::lcl_AlignWidth( rBox.GetLeft()->GetOutWidth() );
+ (rRect.*rRectFn->fnSubLeft)( -nDist );
+ }
+
+ if ( rBox.GetRight() && rBox.GetRight()->GetInWidth() )
+ {
+ const long nDist = ::lcl_MinWidthDist( rBox.GetRight()->GetDistance() )
+ + ::lcl_AlignWidth( rBox.GetRight()->GetOutWidth() );
+ (rRect.*rRectFn->fnAddRight)( -nDist );
+ }
+}
+
+sal_uInt16 lcl_GetLineWidth( const SvxBorderLine* pLine )
+{
+ sal_uInt16 result = 0;
+
+ if ( pLine != NULL )
+ result = pLine->GetScaledWidth();
+
+ return result;
+}
+
+double lcl_GetExtent( const SvxBorderLine* pSideLine, const SvxBorderLine* pOppositeLine )
+{
+ double nExtent = 0.0;
+
+ if ( pSideLine && !pSideLine->isEmpty() )
+ nExtent = -lcl_GetLineWidth( pSideLine ) / 2.0;
+ else if ( pOppositeLine )
+ nExtent = lcl_GetLineWidth( pOppositeLine ) / 2.0;
+
+ return nExtent;
+}
+
+// OD 19.05.2003 #109667# - merge <lcl_PaintLeftLine> and <lcl_PaintRightLine>
+// into new method <lcl_PaintLeftRightLine(..)>
+void lcl_PaintLeftRightLine( const sal_Bool _bLeft,
+ const SwFrm& _rFrm,
+ const SwPageFrm& /*_rPage*/,
+ const SwRect& _rOutRect,
+ const SwRect& /*_rRect*/,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ const SvxBoxItem& rBox = _rAttrs.GetBox();
+ const sal_Bool bR2L = _rFrm.IsCellFrm() && _rFrm.IsRightToLeft();
+ const SvxBorderLine* pLeftRightBorder = 0;
+ const SvxBorderLine* pTopBorder = rBox.GetTop();
+ const SvxBorderLine* pBottomBorder = rBox.GetBottom();
+
+ if ( _bLeft )
+ {
+ pLeftRightBorder = bR2L ? rBox.GetRight() : rBox.GetLeft();
+ }
+ else
+ {
+ pLeftRightBorder = bR2L ? rBox.GetLeft() : rBox.GetRight();
+ }
+ // OD 06.05.2003 #107169# - init boolean indicating printer output device.
+ const sal_Bool bPrtOutputDev =
+ ( OUTDEV_PRINTER == pGlobalShell->GetOut()->GetOutDevType() );
+
+ if ( !pLeftRightBorder )
+ {
+ return;
+ }
+
+ SwRect aRect( _rOutRect );
+ if ( _bLeft )
+ {
+ (aRect.*_rRectFn->fnAddRight)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ) ) -
+ (aRect.*_rRectFn->fnGetWidth)() );
+ }
+ else
+ {
+ (aRect.*_rRectFn->fnSubLeft)( ::lcl_AlignWidth( lcl_GetLineWidth( pLeftRightBorder ) ) -
+ (aRect.*_rRectFn->fnGetWidth)() );
+ }
+
+ const sal_Bool bCnt = _rFrm.IsCntntFrm();
+
+ if ( bCnt )
+ {
+ ::lcl_ExtendLeftAndRight( aRect, _rFrm, _rAttrs, _rRectFn );
+
+ // No Top / bottom borders for joint borders
+ if ( _rAttrs.JoinedWithPrev( _rFrm ) ) pTopBorder = NULL;
+ if ( _rAttrs.JoinedWithNext( _rFrm ) ) pBottomBorder = NULL;
+ }
+
+ // OD 06.05.2003 #107169# - adjustments for printer output device
+ if ( bPrtOutputDev )
+ {
+ // substract width of outer top line.
+ if ( rBox.GetTop() && (!bCnt || _rAttrs.GetTopLine( _rFrm )) )
+ {
+ long nDist = ::lcl_AlignHeight( rBox.GetTop()->GetOutWidth() );
+ (aRect.*_rRectFn->fnSubTop)( -nDist );
+ // OD 19.05.2003 #109667# - If outer top line is hair line, calculated
+ // top has to be adjusted.
+ if ( nDist == 1 )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // right of border rectangle has to be checked and adjusted
+ Point aCompPt( aRect.Right(), 0 );
+ Point aRefPt( aCompPt.X() + 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, -1 );
+ aRect.Right( aCompPt.X() );
+ }
+ else
+ {
+ // top of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, aRect.Top() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() - 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, +1 );
+ aRect.Top( aCompPt.Y() );
+ }
+ }
+ }
+ // substract width of outer bottom line.
+ if ( rBox.GetBottom() && (!bCnt || _rAttrs.GetBottomLine( _rFrm )) )
+ {
+ long nDist = ::lcl_AlignHeight( rBox.GetBottom()->GetOutWidth());
+ (aRect.*_rRectFn->fnAddBottom)( -nDist );
+ // OD 19.05.2003 #109667# - If outer bottom line is hair line, calculated
+ // top has to be adjusted.
+ if ( nDist == 1 )
+ {
+ if ( _rFrm.IsVertical() )
+ {
+ // left of border rectangle has to be checked and adjusted
+ Point aCompPt( aRect.Left(), 0 );
+ Point aRefPt( aCompPt.X() - 1, aCompPt.Y() );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_True, +1 );
+ aRect.Left( aCompPt.X() );
+ }
+ else
+ {
+ // bottom of border rectangle has to be checked and adjusted
+ Point aCompPt( 0, aRect.Bottom() );
+ Point aRefPt( aCompPt.X(), aCompPt.Y() + 1 );
+ lcl_CompPxPosAndAdjustPos( *(pGlobalShell->GetOut()),
+ aRefPt, aCompPt,
+ sal_False, -1 );
+ aRect.Bottom( aCompPt.Y() );
+ }
+ }
+ }
+ }
+
+ if ( !pLeftRightBorder->GetInWidth() )
+ {
+ // OD 06.05.2003 #107169# - add 6th parameter
+ ::lcl_SubTopBottom( aRect, rBox, _rAttrs, _rFrm, _rRectFn, bPrtOutputDev );
+ }
+
+ // TODO Postpone the processing of the primitives
+ if ( lcl_GetLineWidth( pLeftRightBorder ) > 0 )
+ {
+ drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
+
+ double nExtentIS = lcl_GetExtent( pTopBorder, NULL );
+ double nExtentIE = lcl_GetExtent( pBottomBorder, NULL );
+ double nExtentOS = lcl_GetExtent( NULL, pTopBorder );
+ double nExtentOE = lcl_GetExtent( NULL, pBottomBorder );
+
+ if ( !_bLeft )
+ {
+ nExtentIS = lcl_GetExtent( NULL, pTopBorder );
+ nExtentIE = lcl_GetExtent( NULL, pBottomBorder );
+ nExtentOS = lcl_GetExtent( pTopBorder, NULL );
+ nExtentOE = lcl_GetExtent( pBottomBorder, NULL );
+ }
+
+ basegfx::B2DPoint aStart( aRect.Left() + aRect.Width() / 2.0, aRect.Top() + lcl_GetLineWidth( pTopBorder ) / 2.0 );
+ basegfx::B2DPoint aEnd( aRect.Left() + aRect.Width() / 2.0, aRect.Bottom() - lcl_GetLineWidth( pBottomBorder ) / 2.0 );
+
+ double nLeftWidth = !_bLeft ? pLeftRightBorder->GetOutWidth() : pLeftRightBorder->GetInWidth( );
+ double nRightWidth = !_bLeft ? pLeftRightBorder->GetInWidth() : pLeftRightBorder->GetOutWidth( );
+ Color aLeftColor = _bLeft ? pLeftRightBorder->GetColorOut( _bLeft ) : pLeftRightBorder->GetColorIn( _bLeft );
+ Color aRightColor = _bLeft ? pLeftRightBorder->GetColorIn( _bLeft ) : pLeftRightBorder->GetColorOut( _bLeft );
+
+ aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D(
+ aStart, aEnd, nLeftWidth, pLeftRightBorder->GetDistance(), nRightWidth,
+ nExtentIS, nExtentIE, nExtentOS, nExtentOE,
+ aLeftColor.getBColor(), aRightColor.getBColor(),
+ pLeftRightBorder->GetColorGap().getBColor(),
+ pLeftRightBorder->HasGapColor(), pLeftRightBorder->GetStyle( ) );
+
+ _rFrm.ProcessPrimitives( aSequence );
+ }
+}
+
+// OD 19.05.2003 #109667# - merge <lcl_PaintTopLine> and <lcl_PaintBottomLine>
+// into <lcl_PaintTopLine>
+void lcl_PaintTopBottomLine( const sal_Bool _bTop,
+ const SwFrm& _rFrm,
+ const SwPageFrm& /*_rPage*/,
+ const SwRect& _rOutRect,
+ const SwRect& /*_rRect*/,
+ const SwBorderAttrs& _rAttrs,
+ const SwRectFn& _rRectFn )
+{
+ const SvxBoxItem& rBox = _rAttrs.GetBox();
+ const SvxBorderLine* pTopBottomBorder = 0;
+ const SvxBorderLine* pLeftBorder = rBox.GetLeft();
+ const SvxBorderLine* pRightBorder = rBox.GetRight();
+ if ( _bTop )
+ {
+ pTopBottomBorder = rBox.GetTop();
+ }
+ else
+ {
+ pTopBottomBorder = rBox.GetBottom();
+ }
+
+ if ( !pTopBottomBorder )
+ {
+ return;
+ }
+
+ SwRect aRect( _rOutRect );
+ if ( _bTop )
+ {
+ (aRect.*_rRectFn->fnAddBottom)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ) ) -
+ (aRect.*_rRectFn->fnGetHeight)() );
+ }
+ else
+ {
+ (aRect.*_rRectFn->fnSubTop)( ::lcl_AlignHeight( lcl_GetLineWidth( pTopBottomBorder ) ) -
+ (aRect.*_rRectFn->fnGetHeight)() );
+ }
+
+ // TODO Postpone the processing of the primitives
+ if ( lcl_GetLineWidth( pTopBottomBorder ) > 0 )
+ {
+ drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
+
+ double nExtentIS = lcl_GetExtent( pRightBorder, NULL );
+ double nExtentIE = lcl_GetExtent( pLeftBorder, NULL );
+ double nExtentOS = lcl_GetExtent( NULL, pRightBorder );
+ double nExtentOE = lcl_GetExtent( NULL, pLeftBorder );
+
+ if ( !_bTop )
+ {
+ nExtentIS = lcl_GetExtent( NULL, pRightBorder );
+ nExtentIE = lcl_GetExtent( NULL, pLeftBorder );
+ nExtentOS = lcl_GetExtent( pRightBorder, NULL );
+ nExtentOE = lcl_GetExtent( pLeftBorder, NULL );
+ }
+
+ basegfx::B2DPoint aStart( aRect.Right() - lcl_GetLineWidth( pRightBorder ) / 2.0, aRect.Top() + aRect.Height() / 2.0 );
+ basegfx::B2DPoint aEnd( aRect.Left() + lcl_GetLineWidth( pLeftBorder ) / 2.0, aRect.Top() + aRect.Height() / 2.0 );
+
+ double nLeftWidth = !_bTop ? pTopBottomBorder->GetOutWidth() : pTopBottomBorder->GetInWidth( );
+ double nRightWidth = !_bTop ? pTopBottomBorder->GetInWidth() : pTopBottomBorder->GetOutWidth( );
+ Color aLeftColor = _bTop ? pTopBottomBorder->GetColorOut( _bTop ) : pTopBottomBorder->GetColorIn( _bTop );
+ Color aRightColor = _bTop ? pTopBottomBorder->GetColorIn( _bTop ) : pTopBottomBorder->GetColorOut( _bTop );
+
+ aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D(
+ aStart, aEnd, nLeftWidth, pTopBottomBorder->GetDistance(), nRightWidth,
+ nExtentIS, nExtentIE, nExtentOS, nExtentOE,
+ aLeftColor.getBColor(), aRightColor.getBColor(),
+ pTopBottomBorder->GetColorGap().getBColor(),
+ pTopBottomBorder->HasGapColor(), pTopBottomBorder->GetStyle( ) );
+
+ _rFrm.ProcessPrimitives( aSequence );
+ }
+}
+
+/*************************************************************************
+|*
+|* const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
+|*
+|* No comment. #i15844#
+|*
+|*************************************************************************/
+
+const SwFrm* lcl_HasNextCell( const SwFrm& rFrm )
+{
+ OSL_ENSURE( rFrm.IsCellFrm(),
+ "lcl_HasNextCell( const SwFrm& rFrm ) should be called with SwCellFrm" );
+
+ const SwFrm* pTmpFrm = &rFrm;
+ do
+ {
+ if ( pTmpFrm->GetNext() )
+ return pTmpFrm->GetNext();
+
+ pTmpFrm = pTmpFrm->GetUpper()->GetUpper();
+ }
+ while ( pTmpFrm->IsCellFrm() );
+
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBorder()
+|*
+|* Beschreibung Malt Schatten und Umrandung
+|*
+|*************************************************************************/
+
+/** local method to determine cell frame, from which the border attributes
+ for paint of top/bottom border has to be used.
+
+ OD 21.02.2003 #b4779636#, #107692#
+
+ @author OD
+
+ @param _pCellFrm
+ input parameter - constant pointer to cell frame for which the cell frame
+ for the border attributes has to be determined.
+
+ @param _rCellBorderAttrs
+ input parameter - constant reference to the border attributes of cell frame
+ <_pCellFrm>.
+
+ @param _bTop
+ input parameter - boolean, that controls, if cell frame for top border or
+ for bottom border has to be determined.
+
+ @return constant pointer to cell frame, for which the border attributes has
+ to be used
+*/
+const SwFrm* lcl_GetCellFrmForBorderAttrs( const SwFrm* _pCellFrm,
+ const SwBorderAttrs& _rCellBorderAttrs,
+ const bool _bTop )
+{
+ OSL_ENSURE( _pCellFrm, "No cell frame available, dying soon" );
+
+ // determine, if cell frame is at bottom/top border of a table frame and
+ // the table frame has/is a follow.
+ const SwFrm* pTmpFrm = _pCellFrm;
+ bool bCellAtBorder = true;
+ bool bCellAtLeftBorder = !_pCellFrm->GetPrev();
+ bool bCellAtRightBorder = !_pCellFrm->GetNext();
+ while( !pTmpFrm->IsRowFrm() || !pTmpFrm->GetUpper()->IsTabFrm() )
+ {
+ pTmpFrm = pTmpFrm->GetUpper();
+ if ( pTmpFrm->IsRowFrm() &&
+ (_bTop ? pTmpFrm->GetPrev() : pTmpFrm->GetNext())
+ )
+ {
+ bCellAtBorder = false;
+ }
+ if ( pTmpFrm->IsCellFrm() )
+ {
+ if ( pTmpFrm->GetPrev() )
+ {
+ bCellAtLeftBorder = false;
+ }
+ if ( pTmpFrm->GetNext() )
+ {
+ bCellAtRightBorder = false;
+ }
+ }
+ }
+ OSL_ENSURE( pTmpFrm && pTmpFrm->IsRowFrm(), "No RowFrm available" );
+
+ const SwLayoutFrm* pParentRowFrm = static_cast<const SwLayoutFrm*>(pTmpFrm);
+ const SwTabFrm* pParentTabFrm =
+ static_cast<const SwTabFrm*>(pParentRowFrm->GetUpper());
+
+ const bool bCellNeedsAttribute = bCellAtBorder &&
+ ( _bTop ?
+ // bCellInFirstRowWithMaster
+ ( !pParentRowFrm->GetPrev() &&
+ pParentTabFrm->IsFollow() &&
+ 0 == pParentTabFrm->GetTable()->GetRowsToRepeat() ) :
+ // bCellInLastRowWithFollow
+ ( !pParentRowFrm->GetNext() &&
+ pParentTabFrm->GetFollow() )
+ );
+
+ const SwFrm* pRet = _pCellFrm;
+ if ( bCellNeedsAttribute )
+ {
+ // determine, if cell frame has no borders inside the table.
+ const SwFrm* pNextCell = 0;
+ bool bNoBordersInside = false;
+
+ if ( bCellAtLeftBorder && ( 0 != ( pNextCell = lcl_HasNextCell( *_pCellFrm ) ) ) )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pNextCell );
+ const SwBorderAttrs &rBorderAttrs = *aAccess.Get();
+ const SvxBoxItem& rBorderBox = rBorderAttrs.GetBox();
+ bCellAtRightBorder = !lcl_HasNextCell( *pNextCell );
+ bNoBordersInside =
+ ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
+ !rBorderBox.GetLeft() &&
+ ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
+ ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
+ }
+ else
+ {
+ const SvxBoxItem& rBorderBox = _rCellBorderAttrs.GetBox();
+ bNoBordersInside =
+ ( !rBorderBox.GetTop() || !pParentRowFrm->GetPrev() ) &&
+ ( !rBorderBox.GetLeft() || bCellAtLeftBorder ) &&
+ ( !rBorderBox.GetRight() || bCellAtRightBorder ) &&
+ ( !rBorderBox.GetBottom() || !pParentRowFrm->GetNext() );
+ }
+
+ if ( bNoBordersInside )
+ {
+ if ( _bTop && !_rCellBorderAttrs.GetBox().GetTop() )
+ {
+ // #b4779636#-hack:
+ // Cell frame has no top border and no border inside the table, but
+ // it is at the top border of a table frame, which is a follow.
+ // Thus, use border attributes of cell frame in first row of complete table.
+ // First, determine first table frame of complete table.
+ SwTabFrm* pMasterTabFrm = pParentTabFrm->FindMaster( true );
+ // determine first row of complete table.
+ const SwFrm* pFirstRow = pMasterTabFrm->GetLower();
+ // return first cell in first row
+ SwFrm* pLowerCell = const_cast<SwFrm*>(pFirstRow->GetLower());
+ while ( !pLowerCell->IsCellFrm() ||
+ ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
+ )
+ {
+ pLowerCell = pLowerCell->GetLower();
+ }
+ OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
+ pRet = pLowerCell;
+ }
+ else if ( !_bTop && !_rCellBorderAttrs.GetBox().GetBottom() )
+ {
+ // #b4779636#-hack:
+ // Cell frame has no bottom border and no border inside the table,
+ // but it is at the bottom border of a table frame, which has a follow.
+ // Thus, use border attributes of cell frame in last row of complete table.
+ // First, determine last table frame of complete table.
+ SwTabFrm* pLastTabFrm = const_cast<SwTabFrm*>(pParentTabFrm->GetFollow());
+ while ( pLastTabFrm->GetFollow() )
+ {
+ pLastTabFrm = pLastTabFrm->GetFollow();
+ }
+ // determine last row of complete table.
+ SwFrm* pLastRow = pLastTabFrm->GetLastLower();
+ // return first bottom border cell in last row
+ SwFrm* pLowerCell = const_cast<SwFrm*>(pLastRow->GetLower());
+ while ( !pLowerCell->IsCellFrm() ||
+ ( pLowerCell->GetLower() && pLowerCell->GetLower()->IsRowFrm() )
+ )
+ {
+ if ( pLowerCell->IsRowFrm() )
+ {
+ while ( pLowerCell->GetNext() )
+ {
+ pLowerCell = pLowerCell->GetNext();
+ }
+ }
+ pLowerCell = pLowerCell->GetLower();
+ }
+ OSL_ENSURE( pLowerCell && pLowerCell->IsCellFrm(), "No CellFrm available" );
+ pRet = pLowerCell;
+ }
+ }
+ }
+
+ return pRet;
+}
+
+void SwFrm::ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DSequence& rSequence ) const
+{
+ basegfx::B2DRange aViewRange;
+
+ SdrPage *pDrawPage = getRootFrm()->GetCurrShell()->Imp()->GetPageView()->GetPage();
+ const drawinglayer::geometry::ViewInformation2D aNewViewInfos(
+ basegfx::B2DHomMatrix( ),
+ getRootFrm()->GetCurrShell()->GetOut()->GetViewTransformation(),
+ aViewRange,
+ GetXDrawPageForSdrPage( pDrawPage ),
+ 0.0,
+ uno::Sequence< beans::PropertyValue >() );
+
+ drawinglayer::processor2d::BaseProcessor2D * pProcessor2D =
+ sdr::contact::createBaseProcessor2DFromOutputDevice(
+ *getRootFrm()->GetCurrShell()->GetOut(),
+ aNewViewInfos );
+
+ if ( pProcessor2D )
+ {
+ pProcessor2D->process( rSequence );
+ delete pProcessor2D;
+ }
+}
+
+void SwFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs &rAttrs ) const
+{
+ //fuer (Row,Body,Ftn,Root,Column,NoTxt) gibt's hier nix zu tun
+ if ( (GetType() & 0x90C5) )
+ return;
+
+ if ( (GetType() & 0x2000) && //Cell
+ !pGlobalShell->GetViewOptions()->IsTable() )
+ return;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
+ {
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ return;
+
+ if ( pTabFrm->GetTable()->IsNewModel() && ( !IsCellFrm() || IsCoveredCell() ) )
+ return;
+ }
+ // <--
+
+ const bool bLine = rAttrs.IsLine() ? true : false;
+ const bool bShadow = rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE;
+
+ // OD 24.02.2003 #b4779636#, #107692# - flag to control,
+ // if #b4779636#-hack has to be used.
+ const bool bb4779636HackActive = true;
+ // OD 21.02.2003 #b4779636#, #107692#
+ const SwFrm* pCellFrmForBottomBorderAttrs = 0;
+ const SwFrm* pCellFrmForTopBorderAttrs = 0;
+ bool bFoundCellForTopOrBorderAttrs = false;
+ if ( bb4779636HackActive && IsCellFrm() )
+ {
+ pCellFrmForBottomBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, false );
+ if ( pCellFrmForBottomBorderAttrs != this )
+ bFoundCellForTopOrBorderAttrs = true;
+ pCellFrmForTopBorderAttrs = lcl_GetCellFrmForBorderAttrs( this, rAttrs, true );
+ if ( pCellFrmForTopBorderAttrs != this )
+ bFoundCellForTopOrBorderAttrs = true;
+ }
+
+ // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
+ // for #b4779636#-hack
+ if ( bLine || bShadow || bFoundCellForTopOrBorderAttrs )
+ {
+ //Wenn das Rechteck vollstandig innerhalb der PrtArea liegt,
+ //so braucht kein Rand gepainted werden.
+ //Fuer die PrtArea muss der Aligned'e Wert zugrunde gelegt werden,
+ //anderfalls wuerden u.U. Teile nicht verarbeitet.
+ SwRect aRect( Prt() );
+ aRect += Frm().Pos();
+ ::SwAlignRect( aRect, pGlobalShell );
+ // OD 27.09.2002 #103636# - new local boolean variable in order to
+ // suspend border paint under special cases - see below.
+ // NOTE: This is a fix for the implementation of feature #99657#.
+ bool bDrawOnlyShadowForTransparentFrame = false;
+ if ( aRect.IsInside( rRect ) )
+ {
+ // OD 27.09.2002 #103636# - paint shadow, if background is transparent.
+ // Because of introduced transparent background for fly frame #99657#,
+ // the shadow have to be drawn if the background is transparent,
+ // in spite the fact that the paint rectangle <rRect> lies fully
+ // in the printing area.
+ // NOTE to chosen solution:
+ // On transparent background, continue processing, but suspend
+ // drawing of border by setting <bDrawOnlyShadowForTransparentFrame>
+ // to true.
+ if ( IsLayoutFrm() &&
+ static_cast<const SwLayoutFrm*>(this)->GetFmt()->IsBackgroundTransparent() )
+ {
+ bDrawOnlyShadowForTransparentFrame = true;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ if ( !pPage )
+ pPage = FindPageFrm();
+
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_True );
+ rAttrs.SetGetCacheLine( sal_True );
+ if ( bShadow )
+ PaintShadow( rRect, aRect, rAttrs );
+ // OD 27.09.2002 #103636# - suspend drawing of border
+ // add condition < NOT bDrawOnlyShadowForTransparentFrame > - see above
+ // OD 24.02.2003 #b4779636#, #107692# - add condition <bFoundCellForTopOrBorderAttrs>
+ // for #b4779636#-hack.
+ if ( ( bLine || bFoundCellForTopOrBorderAttrs ) &&
+ !bDrawOnlyShadowForTransparentFrame )
+ {
+ const SwFrm* pDirRefFrm = IsCellFrm() ? FindTabFrm() : this;
+ SWRECTFN( pDirRefFrm )
+ ::lcl_PaintLeftRightLine ( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ ::lcl_PaintLeftRightLine ( sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ if ( !IsCntntFrm() || rAttrs.GetTopLine( *(this) ) )
+ {
+ // OD 21.02.2003 #b4779636#, #107692# -
+ // #b4779636#-hack: If another cell frame for top border
+ // paint is found, paint its top border.
+ if ( IsCellFrm() && pCellFrmForTopBorderAttrs != this )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(),
+ pCellFrmForTopBorderAttrs );
+ const SwBorderAttrs &rTopAttrs = *aAccess.Get();
+ ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rTopAttrs, fnRect );
+ }
+ else
+ {
+ ::lcl_PaintTopBottomLine( sal_True, *(this), *(pPage), aRect, rRect, rAttrs, fnRect );
+ }
+ }
+ if ( !IsCntntFrm() || rAttrs.GetBottomLine( *(this) ) )
+ {
+ // OD 21.02.2003 #b4779636#, #107692# -
+ // #b4779636#-hack: If another cell frame for bottom border
+ // paint is found, paint its bottom border.
+ if ( IsCellFrm() && pCellFrmForBottomBorderAttrs != this )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(),
+ pCellFrmForBottomBorderAttrs );
+ const SwBorderAttrs &rBottomAttrs = *aAccess.Get();
+ ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rBottomAttrs, fnRect);
+ }
+ else
+ {
+ ::lcl_PaintTopBottomLine(sal_False, *(this), *(pPage), aRect, rRect, rAttrs, fnRect);
+ }
+ }
+ }
+ rAttrs.SetGetCacheLine( sal_False );
+ }
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::PaintBorder()
+|*
+|* Beschreibung Spezialimplementierung wg. der Fussnotenlinie.
+|* Derzeit braucht nur der obere Rand beruecksichtigt werden.
+|* Auf andere Linien und Schatten wird verzichtet.
+|*
+|*************************************************************************/
+
+void SwFtnContFrm::PaintBorder( const SwRect& rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs & ) const
+{
+ //Wenn das Rechteck vollstandig innerhalb der PrtArea liegt, so gibt es
+ //keinen Rand zu painten.
+ SwRect aRect( Prt() );
+ aRect.Pos() += Frm().Pos();
+ if ( !aRect.IsInside( rRect ) )
+ PaintLine( rRect, pPage );
+}
+/*************************************************************************
+|*
+|* SwFtnContFrm::PaintLine()
+|*
+|* Beschreibung Fussnotenline malen.
+|*
+|*************************************************************************/
+
+void SwFtnContFrm::PaintLine( const SwRect& rRect,
+ const SwPageFrm *pPage ) const
+{
+ //Laenge der Linie ergibt sich aus der prozentualen Angabe am PageDesc.
+ //Die Position ist ebenfalls am PageDesc angegeben.
+ //Der Pen steht direkt im PageDesc.
+
+ if ( !pPage )
+ pPage = FindPageFrm();
+ const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
+
+ SWRECTFN( this )
+ SwTwips nPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ Fraction aFract( nPrtWidth, 1 );
+ const SwTwips nWidth = (long)(aFract *= rInf.GetWidth());
+
+ SwTwips nX = (this->*fnRect->fnGetPrtLeft)();
+ switch ( rInf.GetAdj() )
+ {
+ case FTNADJ_CENTER:
+ nX += nPrtWidth/2 - nWidth/2; break;
+ case FTNADJ_RIGHT:
+ nX += nPrtWidth - nWidth; break;
+ case FTNADJ_LEFT:
+ /* do nothing */; break;
+ default:
+ OSL_ENSURE( !this, "Neues Adjustment fuer Fussnotenlinie?" );
+ }
+ SwTwips nLineWidth = rInf.GetLineWidth();
+ const SwRect aLineRect = bVert ?
+ SwRect( Point(Frm().Left()+Frm().Width()-rInf.GetTopDist()-nLineWidth,
+ nX), Size( nLineWidth, nWidth ) )
+ : SwRect( Point( nX, Frm().Pos().Y() + rInf.GetTopDist() ),
+ Size( nWidth, rInf.GetLineWidth()));
+ if ( aLineRect.HasArea() )
+ PaintBorderLine( rRect, aLineRect , pPage, &rInf.GetLineColor(),
+ rInf.GetLineStyle() );
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::PaintColLines()
+|*
+|* Beschreibung Painted die Trennlinien fuer die innenliegenden
+|* Spalten.
+|*
+|*************************************************************************/
+
+void SwLayoutFrm::PaintColLines( const SwRect &rRect, const SwFmtCol &rFmtCol,
+ const SwPageFrm *pPage ) const
+{
+ const SwFrm *pCol = Lower();
+ if ( !pCol || !pCol->IsColumnFrm() )
+ return;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+ SwRect aLineRect = Prt();
+ aLineRect += Frm().Pos();
+
+ SwTwips nTop = ((aLineRect.*fnRect->fnGetHeight)()*rFmtCol.GetLineHeight())
+ / 100 - (aLineRect.*fnRect->fnGetHeight)();
+ SwTwips nBottom = 0;
+
+ switch ( rFmtCol.GetLineAdj() )
+ {
+ case COLADJ_CENTER:
+ nBottom = nTop / 2; nTop -= nBottom; break;
+ case COLADJ_TOP:
+ nBottom = nTop; nTop = 0; break;
+ case COLADJ_BOTTOM:
+ break;
+ default:
+ OSL_ENSURE( !this, "Neues Adjustment fuer Spaltenlinie?" );
+ }
+
+ if( nTop )
+ (aLineRect.*fnRect->fnSubTop)( nTop );
+ if( nBottom )
+ (aLineRect.*fnRect->fnAddBottom)( nBottom );
+
+ SwTwips nPenHalf = rFmtCol.GetLineWidth();
+ (aLineRect.*fnRect->fnSetWidth)( nPenHalf );
+ nPenHalf /= 2;
+
+ //Damit uns nichts verlorengeht muessen wir hier etwas grosszuegiger sein.
+ SwRect aRect( rRect );
+ (aRect.*fnRect->fnSubLeft)( nPenHalf + nPixelSzW );
+ (aRect.*fnRect->fnAddRight)( nPenHalf + nPixelSzW );
+ SwRectGet fnGetX = IsRightToLeft() ? fnRect->fnGetLeft : fnRect->fnGetRight;
+ while ( pCol->GetNext() )
+ {
+ (aLineRect.*fnRect->fnSetPosX)
+ ( (pCol->Frm().*fnGetX)() - nPenHalf );
+ if ( aRect.IsOver( aLineRect ) )
+ PaintBorderLine( aRect, aLineRect , pPage, &rFmtCol.GetLineColor(),
+ rFmtCol.GetLineStyle() );
+ pCol = pCol->GetNext();
+ }
+}
+
+void SwPageFrm::PaintGrid( OutputDevice* pOut, SwRect &rRect ) const
+{
+ if( !bHasGrid || pRetoucheFly || pRetoucheFly2 )
+ return;
+ GETGRID( this )
+ if( pGrid && ( OUTDEV_PRINTER != pOut->GetOutDevType() ?
+ pGrid->GetDisplayGrid() : pGrid->GetPrintGrid() ) )
+ {
+ const SwLayoutFrm* pBody = FindBodyCont();
+ if( pBody )
+ {
+ SwRect aGrid( pBody->Prt() );
+ aGrid += pBody->Frm().Pos();
+
+ SwRect aInter( aGrid );
+ aInter.Intersection( rRect );
+ if( aInter.HasArea() )
+ {
+ sal_Bool bGrid = pGrid->GetRubyTextBelow();
+ sal_Bool bCell = GRID_LINES_CHARS == pGrid->GetGridType();
+ long nGrid = pGrid->GetBaseHeight();
+ const SwDoc* pDoc = GetFmt()->GetDoc();
+ long nGridWidth = GETGRIDWIDTH(pGrid,pDoc); //for textgrid refactor
+ long nRuby = pGrid->GetRubyHeight();
+ long nSum = nGrid + nRuby;
+ const Color *pCol = &pGrid->GetColor();
+
+ SwTwips nRight = aInter.Left() + aInter.Width();
+ SwTwips nBottom = aInter.Top() + aInter.Height();
+ if( IsVertical() )
+ {
+ SwTwips nOrig = aGrid.Left() + aGrid.Width();
+ SwTwips nY = nOrig + nSum *
+ ( ( nOrig - aInter.Left() ) / nSum );
+ SwRect aTmp( Point( nY, aInter.Top() ),
+ Size( 1, aInter.Height() ) );
+ SwTwips nX = aGrid.Top() + nGrid *
+ ( ( aInter.Top() - aGrid.Top() )/ nGrid );
+ if( nX < aInter.Top() )
+ nX += nGrid;
+ SwTwips nGridBottom = aGrid.Top() + aGrid.Height();
+ sal_Bool bLeft = aGrid.Top() >= aInter.Top();
+ sal_Bool bRight = nGridBottom <= nBottom;
+ sal_Bool bBorder = bLeft || bRight;
+ while( nY > nRight )
+ {
+ aTmp.Pos().X() = nY;
+ if( bGrid )
+ {
+ nY -= nGrid;
+ SwTwips nPosY = Max( aInter.Left(), nY );
+ SwTwips nHeight = Min(nRight, aTmp.Pos().X())-nPosY;
+ if( nHeight > 0 )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nPosY, nX ),
+ Size( nHeight, 1 ) );
+ while( aVert.Top() <= nBottom )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().Y() += nGrid;
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point( nPosY, aGrid.Top() ),
+ Size( nHeight, 1 ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY -= nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max( aInter.Left(), nY );
+ SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
+ SwRect aVert( Point( nPos, aGrid.Top() ),
+ Size( nW, 1 ) );
+ if( nW > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ while( nY >= aInter.Left() )
+ {
+ aTmp.Pos().X() = nY;
+ PaintBorderLine( rRect, aTmp, this, pCol);
+ if( bGrid )
+ {
+ nY -= nGrid;
+ SwTwips nHeight = aTmp.Pos().X()
+ - Max(aInter.Left(), nY );
+ if( nHeight > 0 )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point(aTmp.Pos().X()-nHeight,
+ nX ), Size( nHeight, 1 ) );
+ while( aVert.Top() <= nBottom )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().Y() += nGrid;
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point(aTmp.Pos().X()-nHeight,
+ aGrid.Top() ), Size( nHeight, 1 ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY -= nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max( aInter.Left(), nY );
+ SwTwips nW = Min(nRight, aTmp.Pos().X()) - nPos;
+ SwRect aVert( Point( nPos, aGrid.Top() ),
+ Size( nW, 1 ) );
+ if( nW > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().Y() = nGridBottom;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ }
+ else
+ {
+ SwTwips nOrig = aGrid.Top();
+ SwTwips nY = nOrig + nSum *( (aInter.Top()-nOrig)/nSum );
+ SwRect aTmp( Point( aInter.Left(), nY ),
+ Size( aInter.Width(), 1 ) );
+ //for textgrid refactor
+ SwTwips nX = aGrid.Left() + nGridWidth *
+ ( ( aInter.Left() - aGrid.Left() )/ nGridWidth );
+ if( nX < aInter.Left() )
+ nX += nGridWidth;
+ SwTwips nGridRight = aGrid.Left() + aGrid.Width();
+ sal_Bool bLeft = aGrid.Left() >= aInter.Left();
+ sal_Bool bRight = nGridRight <= nRight;
+ sal_Bool bBorder = bLeft || bRight;
+ while( nY < aInter.Top() )
+ {
+ aTmp.Pos().Y() = nY;
+ if( bGrid )
+ {
+ nY += nGrid;
+ SwTwips nPosY = Max( aInter.Top(), aTmp.Pos().Y() );
+ SwTwips nHeight = Min(nBottom, nY ) - nPosY;
+ if( nHeight )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nX, nPosY ),
+ Size( 1, nHeight ) );
+ while( aVert.Left() <= nRight )
+ {
+ PaintBorderLine(rRect,aVert,this,pCol);
+ aVert.Pos().X() += nGridWidth; //for textgrid refactor
+ }
+ }
+ else if ( bBorder )
+ {
+ SwRect aVert( Point( aGrid.Left(), nPosY ),
+ Size( 1, nHeight ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY += nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
+ SwTwips nH = Min( nBottom, nY ) - nPos;
+ SwRect aVert( Point( aGrid.Left(), nPos ),
+ Size( 1, nH ) );
+ if( nH > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ while( nY <= nBottom )
+ {
+ aTmp.Pos().Y() = nY;
+ PaintBorderLine( rRect, aTmp, this, pCol);
+ if( bGrid )
+ {
+ nY += nGrid;
+ SwTwips nHeight = Min(nBottom, nY) - aTmp.Pos().Y();
+ if( nHeight )
+ {
+ if( bCell )
+ {
+ SwRect aVert( Point( nX, aTmp.Pos().Y() ),
+ Size( 1, nHeight ) );
+ while( aVert.Left() <= nRight )
+ {
+ PaintBorderLine( rRect, aVert, this, pCol);
+ aVert.Pos().X() += nGridWidth; //for textgrid refactor
+ }
+ }
+ else if( bBorder )
+ {
+ SwRect aVert( Point( aGrid.Left(),
+ aTmp.Pos().Y() ), Size( 1, nHeight ) );
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ else
+ {
+ nY += nRuby;
+ if( bBorder )
+ {
+ SwTwips nPos = Max(aInter.Top(),aTmp.Pos().Y());
+ SwTwips nH = Min( nBottom, nY ) - nPos;
+ SwRect aVert( Point( aGrid.Left(), nPos ),
+ Size( 1, nH ) );
+ if( nH > 0 )
+ {
+ if( bLeft )
+ PaintBorderLine(rRect,aVert,this,pCol);
+ if( bRight )
+ {
+ aVert.Pos().X() = nGridRight;
+ PaintBorderLine(rRect,aVert,this,pCol);
+ }
+ }
+ }
+ }
+ bGrid = !bGrid;
+ }
+ }
+ }
+ }
+ }
+}
+
+/** paint margin area of a page
+
+ OD 20.11.2002 for #104598#:
+ implement paint of margin area; margin area will be painted for a
+ view shell with a window and if the document is not in online layout.
+
+ @author OD
+
+ @param _rOutputRect
+ input parameter - constant instance reference of the rectangle, for
+ which an output has to be generated.
+
+ @param _pViewShell
+ input parameter - instance of the view shell, on which the output
+ has to be generated.
+*/
+void SwPageFrm::PaintMarginArea( const SwRect& _rOutputRect,
+ ViewShell* _pViewShell ) const
+{
+ if ( _pViewShell->GetWin() &&
+ !_pViewShell->GetViewOptions()->getBrowseMode() )
+ {
+ SwRect aPgPrtRect( Prt() );
+ aPgPrtRect.Pos() += Frm().Pos();
+ if ( !aPgPrtRect.IsInside( _rOutputRect ) )
+ {
+ SwRect aPgRect = Frm();
+ aPgRect._Intersection( _rOutputRect );
+ if(aPgRect.Height() < 0 || aPgRect.Width() <= 0) // No intersection
+ return;
+ SwRegionRects aPgRegion( aPgRect );
+ aPgRegion -= aPgPrtRect;
+ const SwPageFrm* pPage = static_cast<const SwPageFrm*>(this);
+ if ( pPage->GetSortedObjs() )
+ ::lcl_SubtractFlys( this, pPage, aPgRect, aPgRegion );
+ if ( aPgRegion.Count() )
+ {
+ OutputDevice *pOut = _pViewShell->GetOut();
+ if ( pOut->GetFillColor() != aGlobalRetoucheColor )
+ pOut->SetFillColor( aGlobalRetoucheColor );
+ for ( sal_uInt16 i = 0; i < aPgRegion.Count(); ++i )
+ {
+ if ( 1 < aPgRegion.Count() )
+ {
+ ::SwAlignRect( aPgRegion[i], pGlobalShell );
+ if( !aPgRegion[i].HasArea() )
+ continue;
+ }
+ pOut->DrawRect(aPgRegion[i].SVRect());
+ }
+ }
+ }
+ }
+}
+
+const sal_Int8 SwPageFrm::mnShadowPxWidth = 9;
+
+sal_Bool SwPageFrm::IsRightShadowNeeded() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
+
+ // We paint the right shadow if we're not in book mode
+ // or if we've no sibling or are the last page of the "row"
+ return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetNext()
+ || (this == Lower()) || (bIsLTR && OnRightPage())
+ || (!bIsLTR && !OnRightPage());
+
+}
+
+sal_Bool SwPageFrm::IsLeftShadowNeeded() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bIsLTR = getRootFrm()->IsLeftToRightViewLayout();
+
+ // We paint the left shadow if we're not in book mode
+ // or if we've no sibling or are the last page of the "row"
+ return !pSh || (!pSh->GetViewOptions()->IsViewLayoutBookMode()) || !GetPrev()
+ || (bIsLTR && !OnRightPage())
+ || (!bIsLTR && OnRightPage());
+}
+
+/** determine rectangle for bottom page shadow
+
+ OD 12.02.2003 for #i9719# and #105645#
+
+ @author OD
+*/
+/*static*/ void SwPageFrm::GetHorizontalShadowRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orHorizontalShadowRect,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar )
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+
+ long lShadowAdjustment = mnShadowPxWidth - 1; // TODO extract this
+
+ _orHorizontalShadowRect.Chg(
+ Point( aPagePxRect.Left() + (bPaintLeftShadow ? lShadowAdjustment : 0), 0 ),
+ Size( aPagePxRect.Width() - ( (bPaintLeftShadow ? lShadowAdjustment : 0) + (bPaintRightShadow ? lShadowAdjustment : 0) ),
+ mnShadowPxWidth ) );
+
+ if(pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ // Notes are displayed, we've to extend borders
+ SwTwips aSidebarTotalWidth = pMgr->GetSidebarWidth(true) + pMgr->GetSidebarBorderWidth(true);
+ if(bRightSidebar)
+ _orHorizontalShadowRect.Right( _orHorizontalShadowRect.Right() + aSidebarTotalWidth );
+ else
+ _orHorizontalShadowRect.Left( _orHorizontalShadowRect.Left() - aSidebarTotalWidth );
+ }
+}
+
+/** paint page border and shadow
+
+ OD 12.02.2003 for #i9719# and #105645#
+ implement paint of page border and shadow
+
+ @author OD
+*/
+/*static*/ void SwPageFrm::PaintBorderAndShadow( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ bool bPaintLeftShadow,
+ bool bPaintRightShadow,
+ bool bRightSidebar )
+{
+ // No shadow in prefs
+ if( !SwViewOption::IsShadow() ) return;
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *_pViewShell->GetOut() );
+ // <--
+
+ static drawinglayer::primitive2d::DiscreteShadow shadowMask( SW_RES( BMP_PAGE_SHADOW_MASK ) );
+ static BitmapEx aPageTopRightShadow;
+ static BitmapEx aPageBottomRightShadow;
+ static BitmapEx aPageBottomLeftShadow;
+ static BitmapEx aPageBottomShadowBase;
+ static BitmapEx aPageRightShadowBase;
+ static BitmapEx aPageTopShadowBase;
+ static BitmapEx aPageTopLeftShadow;
+ static BitmapEx aPageLeftShadowBase;
+ static Color aShadowColor( COL_AUTO );
+
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+
+
+ if(aShadowColor != SwViewOption::GetShadowColor() ) {
+ aShadowColor = SwViewOption::GetShadowColor();
+
+ AlphaMask aMask( shadowMask.getBottomRight().GetBitmap() );
+ Bitmap aFilledSquare( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomRightShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getBottomLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomLeftShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getBottom().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageBottomShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTop().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTopRight().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopRightShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getRight().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageRightShadowBase = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getTopLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageTopLeftShadow = BitmapEx( aFilledSquare, aMask );
+
+ aMask = AlphaMask( shadowMask.getLeft().GetBitmap() );
+ aFilledSquare = Bitmap( aMask.GetSizePixel(), 24 );
+ aFilledSquare.Erase( aShadowColor );
+ aPageLeftShadowBase = BitmapEx( aFilledSquare, aMask );
+ }
+
+ SwRect aPaintRect;
+ OutputDevice *pOut = _pViewShell->GetOut();
+
+ SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aPaintRect, bPaintLeftShadow, bPaintRightShadow, bRightSidebar );
+
+ // Right shadow & corners
+ if ( bPaintRightShadow )
+ {
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + 1, aPagePxRect.Bottom() + 1 - (aPageBottomRightShadow.GetSizePixel().Height() - mnShadowPxWidth) ) ),
+ aPageBottomRightShadow );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + 1, aPagePxRect.Top() - mnShadowPxWidth ) ),
+ aPageTopRightShadow );
+ BitmapEx aPageRightShadow = aPageRightShadowBase;
+ aPageRightShadow.Scale( 1, aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1) );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Right() + mnShadowPxWidth, aPagePxRect.Top() + mnShadowPxWidth - 1) ), aPageRightShadow );
+ }
+
+ // Left shadows and corners
+ if(bPaintLeftShadow)
+ {
+ const long lLeft = aPaintRect.Left() - aPageBottomLeftShadow.GetSizePixel().Width();
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft,
+ aPagePxRect.Bottom() + 1 + mnShadowPxWidth - aPageBottomLeftShadow.GetSizePixel().Height() ) ), aPageBottomLeftShadow );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopLeftShadow );
+ BitmapEx aPageLeftShadow = aPageLeftShadowBase;
+ aPageLeftShadow.Scale( 1, aPagePxRect.Height() - 2 * (mnShadowPxWidth - 1) );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( lLeft, aPagePxRect.Top() + mnShadowPxWidth - 1) ), aPageLeftShadow );
+ }
+
+ BitmapEx aPageBottomShadow = aPageBottomShadowBase;
+ aPageBottomShadow.Scale( aPaintRect.Width(), 1 );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Left(), aPagePxRect.Bottom() + 1 ) ), aPageBottomShadow);
+ BitmapEx aPageTopShadow = aPageTopShadowBase;
+ aPageTopShadow.Scale( aPaintRect.Width(), 1 );
+ pOut->DrawBitmapEx( pOut->PixelToLogic( Point( aPaintRect.Left(), aPagePxRect.Top() - mnShadowPxWidth ) ), aPageTopShadow );
+}
+
+//mod #i6193# paint sidebar for notes
+//IMPORTANT: if you change the rects here, also change SwPostItMgr::ScrollbarHit
+/*static*/void SwPageFrm::PaintNotesSidebar(const SwRect& _rPageRect, ViewShell* _pViewShell, sal_uInt16 nPageNum, bool bRight)
+{
+ //TOOD: cut out scrollbar area and arrows out of sidepane rect, otherwise it could flicker when pressing arrow buttons
+ if (!_pViewShell )
+ return;
+
+ SwRect aPageRect( _rPageRect );
+ SwAlignRect( aPageRect, _pViewShell );
+
+ const SwPostItMgr *pMgr = _pViewShell->GetPostItMgr();
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes()) // do not show anything in print preview
+ {
+ sal_Int32 nScrollerHeight = pMgr->GetSidebarScrollerHeight();
+ const Rectangle &aVisRect = _pViewShell->VisArea().SVRect();
+ //draw border and sidepane
+ _pViewShell->GetOut()->SetLineColor();
+ if (!bRight)
+ {
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
+ _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()))) ;
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ else
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
+ _pViewShell->GetOut()->DrawRect(Rectangle(Point(aPageRect.Left()-pMgr->GetSidebarWidth()-pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()))) ;
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_BORDER);
+ SwRect aSidebarBorder(aPageRect.TopRight(),Size(pMgr->GetSidebarBorderWidth(),aPageRect.Height()));
+ _pViewShell->GetOut()->DrawRect(aSidebarBorder.SVRect());
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ else
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE);
+ SwRect aSidebar(Point(aPageRect.Right()+pMgr->GetSidebarBorderWidth(),aPageRect.Top()),Size(pMgr->GetSidebarWidth(),aPageRect.Height()));
+ _pViewShell->GetOut()->DrawRect(aSidebar.SVRect());
+ }
+ if (pMgr->ShowScrollbar(nPageNum))
+ {
+ // draw scrollbar area and arrows
+ Point aPointBottom;
+ Point aPointTop;
+ aPointBottom = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() - pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height()) :
+ Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- _pViewShell->GetOut()->PixelToLogic(Size(0,2+pMgr->GetSidebarScrollerHeight())).Height());
+ aPointTop = !bRight ? Point(aPageRect.Left() - pMgr->GetSidebarWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height()) :
+ Point(aPageRect.Right() + pMgr->GetSidebarBorderWidth() + _pViewShell->GetOut()->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + _pViewShell->GetOut()->PixelToLogic(Size(0,2)).Height());
+ Size aSize(pMgr->GetSidebarWidth() - _pViewShell->GetOut()->PixelToLogic(Size(4,0)).Width(), _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()) ;
+ Rectangle aRectBottom(aPointBottom,aSize);
+ Rectangle aRectTop(aPointTop,aSize);
+
+ if (aRectBottom.IsOver(aVisRect))
+ {
+
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_WHITE);
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_BLACK);
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
+ }
+ _pViewShell->GetOut()->DrawRect(aRectBottom);
+ _pViewShell->GetOut()->DrawLine(aPointBottom + Point(pMgr->GetSidebarWidth()/3,0), aPointBottom + Point(pMgr->GetSidebarWidth()/3 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
+
+ _pViewShell->GetOut()->SetLineColor();
+ Point aMiddleFirst(aPointBottom + Point(pMgr->GetSidebarWidth()/6,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ Point aMiddleSecond(aPointBottom + Point(pMgr->GetSidebarWidth()/3*2,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell,pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
+ }
+ if (aRectTop.IsOver(aVisRect))
+ {
+ if (Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_WHITE);
+ _pViewShell->GetOut()->SetFillColor(COL_BLACK);
+ }
+ else
+ {
+ _pViewShell->GetOut()->SetLineColor(COL_BLACK);
+ _pViewShell->GetOut()->SetFillColor(COL_NOTES_SIDEPANE_SCROLLAREA);
+ }
+ _pViewShell->GetOut()->DrawRect(aRectTop);
+ _pViewShell->GetOut()->DrawLine(aPointTop + Point(pMgr->GetSidebarWidth()/3*2,0), aPointTop + Point(pMgr->GetSidebarWidth()/3*2 , _pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()));
+
+ _pViewShell->GetOut()->SetLineColor();
+ Point aMiddleFirst(aPointTop + Point(pMgr->GetSidebarWidth()/3,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ Point aMiddleSecond(aPointTop + Point(pMgr->GetSidebarWidth()/6*5,_pViewShell->GetOut()->PixelToLogic(Size(0,nScrollerHeight)).Height()/2));
+ PaintNotesSidebarArrows(aMiddleFirst,aMiddleSecond,_pViewShell, pMgr->GetArrowColor(KEY_PAGEUP,nPageNum), pMgr->GetArrowColor(KEY_PAGEDOWN,nPageNum));
+ }
+ }
+ }
+}
+
+/*static*/ void SwPageFrm::PaintNotesSidebarArrows(const Point &aMiddleFirst, const Point &aMiddleSecond, ViewShell* _pViewShell, const Color aColorUp, const Color aColorDown)
+{
+ Polygon aTriangleUp(3);
+ Polygon aTriangleDown(3);
+
+ aTriangleUp.SetPoint(aMiddleFirst + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
+ aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),1);
+ aTriangleUp.SetPoint(aMiddleFirst + Point(_pViewShell->GetOut()->PixelToLogic(Size(3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
+
+ aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(-3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),0);
+ aTriangleDown.SetPoint(aMiddleSecond + Point(_pViewShell->GetOut()->PixelToLogic(Size(+3,0)).Width(),_pViewShell->GetOut()->PixelToLogic(Size(0,-3)).Height()),1);
+ aTriangleDown.SetPoint(aMiddleSecond + Point(0,_pViewShell->GetOut()->PixelToLogic(Size(0,3)).Height()),2);
+
+ _pViewShell->GetOut()->SetFillColor(aColorUp);
+ _pViewShell->GetOut()->DrawPolygon(aTriangleUp);
+ _pViewShell->GetOut()->SetFillColor(aColorDown);
+ _pViewShell->GetOut()->DrawPolygon(aTriangleDown);
+}
+
+/** get bound rectangle of border and shadow for repaints
+
+ OD 12.02.2003 for #i9719# and #105645#
+
+ author OD
+*/
+/*static*/ void SwPageFrm::GetBorderAndShadowBoundRect( const SwRect& _rPageRect,
+ const ViewShell* _pViewShell,
+ SwRect& _orBorderAndShadowBoundRect,
+ bool bLeftShadow,
+ bool bRightShadow,
+ bool bRightSidebar
+ )
+{
+ SwRect aAlignedPageRect( _rPageRect );
+ ::SwAlignRect( aAlignedPageRect, _pViewShell );
+ SwRect aPagePxRect =
+ _pViewShell->GetOut()->LogicToPixel( aAlignedPageRect.SVRect() );
+ aPagePxRect.Bottom( aPagePxRect.Bottom() + mnShadowPxWidth + 1 );
+ aPagePxRect.Top( aPagePxRect.Top() - mnShadowPxWidth - 1 );
+
+ SwRect aTmpRect;
+
+ // Always ask for full shadow since we want a bounding rect
+ // including at least the page frame
+ SwPageFrm::GetHorizontalShadowRect( _rPageRect, _pViewShell, aTmpRect, false, false, bRightSidebar );
+
+ if(bLeftShadow) aPagePxRect.Left( aTmpRect.Left() - mnShadowPxWidth - 1);
+ if(bRightShadow) aPagePxRect.Right( aTmpRect.Right() + mnShadowPxWidth + 1);
+
+ _orBorderAndShadowBoundRect = _pViewShell->GetOut()->PixelToLogic( aPagePxRect.SVRect() );
+}
+
+SwRect SwPageFrm::GetBoundRect() const
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwRect aPageRect( Frm() );
+ SwRect aResult;
+
+ if(!pSh) {
+ return SwRect( Point(0, 0), Size(0, 0) );
+ }
+
+ SwPageFrm::GetBorderAndShadowBoundRect( aPageRect, pSh, aResult,
+ IsLeftShadowNeeded(), IsRightShadowNeeded(), SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT );
+ return aResult;
+}
+
+/*static*/ void SwPageFrm::AddSidebarBorders(SwRect &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ if (!bRightSidebar)
+ aRect.SetLeftAndWidth(aRect.Left() - pMgr->GetSidebarWidth(bPx) - pMgr->GetSidebarBorderWidth(bPx), aRect.Width() + pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ else
+ aRect.AddRight(pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ }
+}
+
+/*static*/ void SwPageFrm::AddSidebarBorders(Rectangle &aRect, ViewShell* _pViewShell, bool bRightSidebar, bool bPx)
+{
+ const SwPostItMgr *pMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ if (pMgr && pMgr->ShowNotes() && pMgr->HasNotes())
+ {
+ if (!bRightSidebar)
+ aRect.Left() -= (pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx));
+ else
+ aRect.Right() += pMgr->GetSidebarWidth(bPx) + pMgr->GetSidebarBorderWidth(bPx);
+ }
+}
+
+/*static*/ SwTwips SwPageFrm::GetSidebarBorderWidth( const ViewShell* _pViewShell )
+{
+ const SwPostItMgr* pPostItMgr = _pViewShell ? _pViewShell->GetPostItMgr() : 0;
+ const SwTwips nRet = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBaBo()
+|*
+|*************************************************************************/
+
+void SwFrm::PaintBaBo( const SwRect& rRect, const SwPageFrm *pPage,
+ const sal_Bool bLowerBorder ) const
+{
+ if ( !pPage )
+ pPage = FindPageFrm();
+
+ OutputDevice *pOut = pGlobalShell->GetOut();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pOut );
+ // <--
+
+ // OD 2004-04-23 #116347#
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor();
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+
+ // OD 20.11.2002 #104598# - take care of page margin area
+ // Note: code move from <SwFrm::PaintBackground(..)> to new method
+ // <SwPageFrm::Paintmargin(..)>.
+ if ( IsPageFrm() )
+ {
+ static_cast<const SwPageFrm*>(this)->PaintMarginArea( rRect, pGlobalShell );
+ }
+
+ // paint background
+ {
+ PaintBackground( rRect, pPage, rAttrs, sal_False, bLowerBorder );
+ }
+
+ // OD 06.08.2002 #99657# - paint border before painting background
+ // paint grid for page frame and paint border
+ {
+ SwRect aRect( rRect );
+ if( IsPageFrm() )
+ ((SwPageFrm*)this)->PaintGrid( pOut, aRect );
+ PaintBorder( aRect, pPage, rAttrs );
+ }
+
+ pOut->Pop();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintBackground()
+|*
+|*************************************************************************/
+/// OD 05.09.2002 #102912#
+/// Do not paint background for fly frames without a background brush by
+/// calling <PaintBaBo> at the page or at the fly frame its anchored
+void SwFrm::PaintBackground( const SwRect &rRect, const SwPageFrm *pPage,
+ const SwBorderAttrs & rAttrs,
+ const sal_Bool bLowerMode,
+ const sal_Bool bLowerBorder ) const
+{
+ // OD 20.01.2003 #i1837# - no paint of table background, if corresponding
+ // option is *not* set.
+ if( IsTabFrm() &&
+ !pGlobalShell->GetViewOptions()->IsTable() )
+ {
+ return;
+ }
+
+ // nothing to do for covered table cells:
+ if( IsCellFrm() && IsCoveredCell() )
+ return;
+
+ ViewShell *pSh = pGlobalShell;
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
+ // <--
+
+ const SvxBrushItem* pItem;
+ /// OD 05.09.2002 #102912#
+ /// temporary background brush for a fly frame without a background brush
+ SvxBrushItem* pTmpBackBrush = 0;
+ const Color* pCol;
+ SwRect aOrigBackRect;
+ const sal_Bool bPageFrm = IsPageFrm();
+ sal_Bool bLowMode = sal_True;
+
+ sal_Bool bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, bLowerMode );
+ //- Ausgabe wenn ein eigener Hintergrund mitgebracht wird.
+ bool bNoFlyBackground = !bFlyMetafile && !bBack && IsFlyFrm();
+ if ( bNoFlyBackground )
+ {
+ // OD 05.09.2002 #102912# - Fly frame has no background.
+ // Try to find background brush at parents, if previous call of
+ // <GetBackgroundBrush> disabled this option with the parameter <bLowerMode>
+ if ( bLowerMode )
+ {
+ bBack = GetBackgroundBrush( pItem, pCol, aOrigBackRect, false );
+ }
+ // If still no background found for the fly frame, initialize the
+ // background brush <pItem> with global retouche color and set <bBack>
+ // to sal_True, that fly frame will paint its background using this color.
+ if ( !bBack )
+ {
+ // OD 10.01.2003 #i6467# - on print output, pdf output and
+ // in embedded mode not editing color COL_WHITE is used instead of
+ // the global retouche color.
+ if ( pSh->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
+ pSh->GetViewOptions()->IsPDFExport() ||
+ ( pSh->GetDoc()->GetDocShell()->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED &&
+ !pSh->GetDoc()->GetDocShell()->IsInPlaceActive()
+ )
+ )
+ {
+ pTmpBackBrush = new SvxBrushItem( Color( COL_WHITE ), RES_BACKGROUND );
+ }
+ else
+ {
+ pTmpBackBrush = new SvxBrushItem( aGlobalRetoucheColor, RES_BACKGROUND);
+ }
+ pItem = pTmpBackBrush;
+ bBack = true;
+ }
+ }
+
+ SwRect aPaintRect( Frm() );
+ if( IsTxtFrm() || IsSctFrm() )
+ aPaintRect = UnionFrm( sal_True );
+
+ if ( aPaintRect.IsOver( rRect ) )
+ {
+ if ( bBack || bPageFrm || !bLowerMode )
+ {
+ const sal_Bool bBrowse = pSh->GetViewOptions()->getBrowseMode();
+ SwRect aRect;
+ if ( (bPageFrm && bBrowse) ||
+ (IsTxtFrm() && Prt().SSize() == Frm().SSize()) )
+ {
+ aRect = Frm();
+ ::SwAlignRect( aRect, pGlobalShell );
+ }
+ else
+ {
+ ::lcl_CalcBorderRect( aRect, this, rAttrs, sal_False );
+ if ( (IsTxtFrm() || IsTabFrm()) && GetPrev() )
+ {
+ if ( GetPrev()->GetAttrSet()->GetBackground() ==
+ GetAttrSet()->GetBackground() )
+ {
+ aRect.Top( Frm().Top() );
+ }
+ }
+ }
+ aRect.Intersection( rRect );
+
+ OutputDevice *pOut = pSh->GetOut();
+
+ if ( aRect.HasArea() )
+ {
+ SvxBrushItem* pNewItem = 0;
+ SwRegionRects aRegion( aRect );
+ if( pCol )
+ {
+ pNewItem = new SvxBrushItem( *pCol, RES_BACKGROUND );
+ pItem = pNewItem;
+ }
+ if ( pPage->GetSortedObjs() )
+ ::lcl_SubtractFlys( this, pPage, aRect, aRegion );
+
+ {
+ /// OD 06.08.2002 #99657# - determine, if background transparency
+ /// have to be considered for drawing.
+ /// --> Status Quo: background transparency have to be
+ /// considered for fly frames
+ const sal_Bool bConsiderBackgroundTransparency = IsFlyFrm();
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ if ( 1 < aRegion.Count() )
+ {
+ ::SwAlignRect( aRegion[i], pGlobalShell );
+ if( !aRegion[i].HasArea() )
+ continue;
+ }
+ /// OD 06.08.2002 #99657# - add 6th parameter to indicate, if
+ /// background transparency have to be considered
+ /// Set missing 5th parameter to the default value GRFNUM_NO
+ /// - see declaration in /core/inc/frmtool.hxx.
+ ::DrawGraphic( pItem, pOut, aOrigBackRect, aRegion[i], GRFNUM_NO,
+ bConsiderBackgroundTransparency );
+ }
+ }
+ if( pCol )
+ delete pNewItem;
+ }
+ }
+ else
+ bLowMode = bLowerMode ? sal_True : sal_False;
+ }
+
+ /// OD 05.09.2002 #102912#
+ /// delete temporary background brush.
+ delete pTmpBackBrush;
+
+ //Jetzt noch Lower und dessen Nachbarn.
+ //Wenn ein Frn dabei die Kette verlaesst also nicht mehr Lower von mir ist
+ //so hoert der Spass auf.
+ const SwFrm *pFrm = GetLower();
+ if ( pFrm )
+ {
+ SwRect aFrmRect;
+ SwRect aRect( PaintArea() );
+ aRect._Intersection( rRect );
+ SwRect aBorderRect( aRect );
+ SwShortCut aShortCut( *pFrm, aBorderRect );
+ do
+ { if ( pProgress )
+ pProgress->Reschedule();
+
+ aFrmRect = pFrm->PaintArea();
+ if ( aFrmRect.IsOver( aBorderRect ) )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), (SwFrm*)pFrm );
+ const SwBorderAttrs &rTmpAttrs = *aAccess.Get();
+ /// OD 06.08.2002 #99657# - paint border before painting background
+ if ( bLowerBorder )
+ pFrm->PaintBorder( aBorderRect, pPage, rTmpAttrs );
+ if ( ( pFrm->IsLayoutFrm() && bLowerBorder ) ||
+ aFrmRect.IsOver( aRect ) )
+ pFrm->PaintBackground( aRect, pPage, rTmpAttrs, bLowMode,
+ bLowerBorder );
+ }
+ pFrm = pFrm->GetNext();
+ } while ( pFrm && pFrm->GetUpper() == this &&
+ !aShortCut.Stop( aFrmRect ) );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RefreshSubsidiary()
+|*
+|* Beschreibung Erneuert alle Hilfslinien der Seite.
+|*
+|*************************************************************************/
+
+void SwPageFrm::RefreshSubsidiary( const SwRect &rRect ) const
+{
+ if ( IS_SUBS || IS_SUBS_TABLE || IS_SUBS_SECTION || IS_SUBS_FLYS )
+ {
+ SwRect aRect( rRect );
+ // OD 18.02.2003 #104989# - Not necessary and incorrect alignment of
+ // the output rectangle.
+ //::SwAlignRect( aRect, pGlobalShell );
+ if ( aRect.HasArea() )
+ {
+ //Beim Paint ueber die Root wird das Array von dort gesteuert.
+ //Anderfalls kuemmern wir uns selbst darum.
+ sal_Bool bDelSubs = sal_False;
+ if ( !pSubsLines )
+ {
+ pSubsLines = new SwSubsRects;
+ // OD 20.12.2002 #106318# - create container for special subsidiary lines
+ pSpecSubsLines = new SwSubsRects;
+ bDelSubs = sal_True;
+ }
+
+ RefreshLaySubsidiary( this, aRect );
+
+ if ( bDelSubs )
+ {
+ // OD 20.12.2002 #106318# - paint special subsidiary lines
+ // and delete its container
+ pSpecSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), NULL );
+ DELETEZ( pSpecSubsLines );
+
+ pSubsLines->PaintSubsidiary( pGlobalShell->GetOut(), pLines );
+ DELETEZ( pSubsLines );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::RefreshLaySubsidiary()
+|*
+|*************************************************************************/
+void SwLayoutFrm::RefreshLaySubsidiary( const SwPageFrm *pPage,
+ const SwRect &rRect ) const
+{
+ const sal_Bool bNoLowerColumn = !Lower() || !Lower()->IsColumnFrm();
+ const sal_Bool bSubsOpt = IS_SUBS;
+ const sal_Bool bSubsTable = ((GetType() & (FRM_ROW | FRM_CELL)) && IS_SUBS_TABLE);
+ const sal_Bool bSubsOther = (GetType() & (FRM_HEADER | FRM_FOOTER | FRM_FTN )) && bSubsOpt;
+ const sal_Bool bSubsSect = IsSctFrm() &&
+ bNoLowerColumn &&
+ IS_SUBS_SECTION;
+ const sal_Bool bSubsFly = IS_SUBS_FLYS &&
+ (GetType() & FRM_FLY) &&
+ bNoLowerColumn &&
+ (!Lower() || !Lower()->IsNoTxtFrm() ||
+ !((SwNoTxtFrm*)Lower())->HasAnimation());
+ sal_Bool bSubsBody = sal_False;
+ if ( GetType() & FRM_BODY )
+ {
+ if ( IsPageBodyFrm() )
+ bSubsBody = bSubsOpt && bNoLowerColumn; //nur ohne Spalten
+ else //Spaltenbody
+ {
+ if ( GetUpper()->GetUpper()->IsSctFrm() )
+ bSubsBody = IS_SUBS_SECTION;
+ else
+ bSubsBody = bSubsOpt;
+ }
+ }
+
+ if ( bSubsOther || bSubsSect || bSubsBody || bSubsTable || bSubsFly )
+ PaintSubsidiaryLines( pPage, rRect );
+
+ const SwFrm *pLow = Lower();
+ if( !pLow )
+ return;
+ SwShortCut aShortCut( *pLow, rRect );
+ while( pLow && !aShortCut.Stop( pLow->Frm() ) )
+ {
+ if ( pLow->Frm().IsOver( rRect ) && pLow->Frm().HasArea() )
+ {
+ if ( pLow->IsLayoutFrm() )
+ ((const SwLayoutFrm*)pLow)->RefreshLaySubsidiary( pPage, rRect);
+ else if ( pLow->GetDrawObjs() )
+ {
+ const SwSortedObjs& rObjs = *(pLow->GetDrawObjs());
+ for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
+ pAnchoredObj->GetDrawObj()->GetLayer() ) &&
+ pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly =
+ static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() && pFly->Frm().IsOver( rRect ) )
+ {
+ if ( !pFly->Lower() || !pFly->Lower()->IsNoTxtFrm() ||
+ !((SwNoTxtFrm*)pFly->Lower())->HasAnimation())
+ pFly->RefreshLaySubsidiary( pPage, rRect );
+ }
+ }
+ }
+ }
+ }
+ pLow = pLow->GetNext();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::PaintSubsidiaryLines()
+|*
+|* Beschreibung Hilfslinien um die PrtAreas malen
+|* Nur die LayoutFrm's die direkt Cntnt enthalten.
+|*
+|*************************************************************************/
+
+//Malt die angegebene Linie, achtet darauf, dass keine Flys uebermalt werden.
+
+typedef long Size::* SizePtr;
+typedef long Point::* PointPtr;
+
+PointPtr pX = &Point::nA;
+PointPtr pY = &Point::nB;
+SizePtr pWidth = &Size::nA;
+SizePtr pHeight = &Size::nB;
+
+// OD 18.11.2002 #99672# - new parameter <_pSubsLines>
+void MA_FASTCALL lcl_RefreshLine( const SwLayoutFrm *pLay,
+ const SwPageFrm *pPage,
+ const Point &rP1,
+ const Point &rP2,
+ const sal_uInt8 nSubColor,
+ SwLineRects* _pSubsLines )
+{
+ //In welche Richtung gehts? Kann nur Horizontal oder Vertikal sein.
+ OSL_ENSURE( ((rP1.X() == rP2.X()) || (rP1.Y() == rP2.Y())),
+ "Schraege Hilfslinien sind nicht erlaubt." );
+ const PointPtr pDirPt = rP1.X() == rP2.X() ? pY : pX;
+ const PointPtr pOthPt = pDirPt == pX ? pY : pX;
+ const SizePtr pDirSz = pDirPt == pX ? pWidth : pHeight;
+ const SizePtr pOthSz = pDirSz == pWidth ? pHeight : pWidth;
+ Point aP1( rP1 ),
+ aP2( rP2 );
+
+ while ( aP1.*pDirPt < aP2.*pDirPt )
+ { //Der Startpunkt wird jetzt, falls er in einem Fly sitzt, direkt
+ //hinter den Fly gesetzt.
+ //Wenn der Endpunkt in einem Fly sitzt oder zwischen Start und Endpunkt
+ //ein Fly sitzt, so wird der Endpunkt eben an den Start herangezogen.
+ //Auf diese art und weise wird eine Portion nach der anderen
+ //ausgegeben.
+
+ //Wenn ich selbst ein Fly bin, weiche ich nur denjenigen Flys aus,
+ //die 'ueber' mir sitzen; d.h. die in dem Array hinter mir stehen.
+ //Auch wenn ich in einem Fly sitze oder in einem Fly im Fly usw. weiche
+ //ich keinem dieser Flys aus.
+ SwOrderIter aIter( pPage );
+ const SwFlyFrm *pMyFly = pLay->FindFlyFrm();
+ if ( pMyFly )
+ {
+ aIter.Current( pMyFly->GetVirtDrawObj() );
+ while ( 0 != (pMyFly = pMyFly->GetAnchorFrm()->FindFlyFrm()) )
+ {
+ if ( aIter()->GetOrdNum() > pMyFly->GetVirtDrawObj()->GetOrdNum() )
+ aIter.Current( pMyFly->GetVirtDrawObj() );
+ }
+ }
+ else
+ aIter.Bottom();
+
+ while ( aIter() )
+ {
+ const SwVirtFlyDrawObj *pObj = (SwVirtFlyDrawObj*)aIter();
+ const SwFlyFrm *pFly = pObj ? pObj->GetFlyFrm() : 0;
+
+ //Mir selbst weiche ich natuerlich nicht aus. Auch wenn ich
+ //_in_ dem Fly sitze weiche ich nicht aus.
+ if ( !pFly || (pFly == pLay || pFly->IsAnLower( pLay )) )
+ {
+ aIter.Next();
+ continue;
+ }
+
+ // OD 19.12.2002 #106318# - do *not* consider fly frames with
+ // a transparent background.
+ // OD 2004-02-12 #110582#-2 - do *not* consider fly frame, which
+ // belongs to a invisible layer
+ if ( pFly->IsBackgroundTransparent() ||
+ !pFly->GetFmt()->GetDoc()->IsVisibleLayerId( pObj->GetLayer() ) )
+ {
+ aIter.Next();
+ continue;
+ }
+
+ //Sitzt das Obj auf der Linie
+ const Rectangle &rBound = pObj->GetCurrentBoundRect();
+ const Point aDrPt( rBound.TopLeft() );
+ const Size aDrSz( rBound.GetSize() );
+ if ( rP1.*pOthPt >= aDrPt.*pOthPt &&
+ rP1.*pOthPt <= (aDrPt.*pOthPt + aDrSz.*pOthSz) )
+ {
+ if ( aP1.*pDirPt >= aDrPt.*pDirPt &&
+ aP1.*pDirPt <= (aDrPt.*pDirPt + aDrSz.*pDirSz) )
+ aP1.*pDirPt = aDrPt.*pDirPt + aDrSz.*pDirSz;
+
+ if ( aP2.*pDirPt >= aDrPt.*pDirPt &&
+ aP1.*pDirPt < (aDrPt.*pDirPt - 1) )
+ aP2.*pDirPt = aDrPt.*pDirPt - 1;
+ }
+ aIter.Next();
+ }
+
+ if ( aP1.*pDirPt < aP2.*pDirPt )
+ {
+ SwRect aRect( aP1, aP2 );
+ // OD 18.11.2002 #99672# - use parameter <_pSubsLines> instead of
+ // global variable <pSubsLines>.
+ _pSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ aP1 = aP2;
+ aP1.*pDirPt += 1;
+ aP2 = rP2;
+ }
+}
+
+void SwLayoutFrm::PaintSubsidiaryLines( const SwPageFrm *pPage,
+ const SwRect &rRect ) const
+{
+ bool bNewTableModel = false;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsTabFrm() || IsCellFrm() || IsRowFrm() )
+ {
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ return;
+
+ bNewTableModel = pTabFrm->GetTable()->IsNewModel();
+ // in the new table model, we have an early return for all cell-related
+ // frames, except from non-covered table cells
+ if ( bNewTableModel )
+ if ( IsTabFrm() ||
+ IsRowFrm() ||
+ ( IsCellFrm() && IsCoveredCell() ) )
+ return;
+ }
+ // <-- collapsing
+
+ const bool bFlys = pPage->GetSortedObjs() ? true : false;
+
+ const bool bCell = IsCellFrm() ? true : false;
+ // use frame area for cells
+ // OD 13.02.2003 #i3662# - for section use also frame area
+ const bool bUseFrmArea = bCell || IsSctFrm();
+ SwRect aOriginal( bUseFrmArea ? Frm() : Prt() );
+ if ( !bUseFrmArea )
+ aOriginal.Pos() += Frm().Pos();
+
+ // OD 13.02.2003 #i3662# - enlarge top of column body frame's printing area
+ // in sections to top of section frame.
+ const bool bColBodyInSection = IsBodyFrm() &&
+ !IsPageBodyFrm() &&
+ GetUpper()->GetUpper()->IsSctFrm();
+ if ( bColBodyInSection )
+ {
+ if ( IsVertical() )
+ aOriginal.Right( GetUpper()->GetUpper()->Frm().Right() );
+ else
+ aOriginal.Top( GetUpper()->GetUpper()->Frm().Top() );
+ }
+
+ ::SwAlignRect( aOriginal, pGlobalShell );
+
+ if ( !aOriginal.IsOver( rRect ) )
+ return;
+
+ SwRect aOut( aOriginal );
+ aOut._Intersection( rRect );
+ // OD 13.02.2003 #i3662# - do not intersect *enlarged* column body frame's
+ // printing area with the paint area of the body frame. Otherwise enlargement
+ // will get lost.
+ if ( !bColBodyInSection )
+ {
+ aOut.Intersection( PaintArea() );
+ }
+
+ const SwTwips nRight = aOut.Right();
+ const SwTwips nBottom= aOut.Bottom();
+
+ const Point aRT( nRight, aOut.Top() );
+ const Point aRB( nRight, nBottom );
+ const Point aLB( aOut.Left(), nBottom );
+
+ sal_uInt8 nSubColor = ( bCell || IsRowFrm() ) ? SUBCOL_TAB :
+ ( IsInSct() ? SUBCOL_SECT :
+ ( IsInFly() ? SUBCOL_FLY : SUBCOL_PAGE ) );
+
+ // OD 05.11.2002 #102406# - body frames are responsible for page/column breaks.
+ sal_Bool bBreak = sal_False;
+ if ( IsBodyFrm() )
+ {
+ const SwCntntFrm *pCnt = ContainsCntnt();
+ if ( pCnt )
+ {
+ // OD 05.11.2002 #102406# - adjust setting of <bBreak>.
+ bBreak = pCnt->IsPageBreak( sal_True ) ||
+ ( IsColBodyFrm() && pCnt->IsColBreak( sal_True ) );
+ }
+ }
+
+ // OD 18.11.2002 #99672# - collect body, header, footer, footnote and section
+ // sub-lines in <pSpecSubsLine> array.
+ const bool bSpecialSublines = IsBodyFrm() || IsHeaderFrm() || IsFooterFrm() ||
+ IsFtnFrm() || IsSctFrm();
+ SwLineRects* pUsedSubsLines = bSpecialSublines ? pSpecSubsLines : pSubsLines;
+
+ // NOTE: for cell frames only left and right (horizontal layout) respectively
+ // top and bottom (vertical layout) lines painted.
+ // NOTE2: this does not hold for the new table model!!! We paint the top border
+ // of each non-covered table cell.
+ const bool bVert = IsVertical() ? true : false;
+ if ( bFlys )
+ {
+ // OD 14.11.2002 #104822# - add control for drawing left and right lines
+ if ( !bCell || bNewTableModel || !bVert )
+ {
+ if ( aOriginal.Left() == aOut.Left() )
+ ::lcl_RefreshLine( this, pPage, aOut.Pos(), aLB, nSubColor,
+ pUsedSubsLines );
+ // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
+ if ( aOriginal.Right() == nRight )
+ ::lcl_RefreshLine( this, pPage, aRT, aRB,
+ (bBreak && bVert) ? SUBCOL_BREAK : nSubColor,
+ pUsedSubsLines );
+ }
+ // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
+ if ( !bCell || bNewTableModel || bVert )
+ {
+ if ( aOriginal.Top() == aOut.Top() )
+ // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
+ ::lcl_RefreshLine( this, pPage, aOut.Pos(), aRT,
+ (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor,
+ pUsedSubsLines );
+ if ( aOriginal.Bottom() == nBottom )
+ ::lcl_RefreshLine( this, pPage, aLB, aRB, nSubColor,
+ pUsedSubsLines );
+ }
+ }
+ else
+ {
+ // OD 14.11.2002 #104822# - add control for drawing left and right lines
+ if ( !bCell || bNewTableModel || !bVert )
+ {
+ if ( aOriginal.Left() == aOut.Left() )
+ {
+ const SwRect aRect( aOut.Pos(), aLB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ // OD 14.11.2002 #104821# - in vertical layout set page/column break at right
+ if ( aOriginal.Right() == nRight )
+ {
+ const SwRect aRect( aRT, aRB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0,
+ (bBreak && bVert) ? SUBCOL_BREAK : nSubColor );
+ }
+ }
+ // OD 14.11.2002 #104822# - adjust control for drawing top and bottom lines
+ if ( !bCell || bNewTableModel || bVert )
+ {
+ if ( aOriginal.Top() == aOut.Top() )
+ {
+ // OD 14.11.2002 #104821# - in horizontal layout set page/column break at top
+ const SwRect aRect( aOut.Pos(), aRT );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0,
+ (bBreak && !bVert) ? SUBCOL_BREAK : nSubColor );
+ }
+ if ( aOriginal.Bottom() == nBottom )
+ {
+ const SwRect aRect( aLB, aRB );
+ pUsedSubsLines->AddLineRect( aRect, 0, SOLID, 0, nSubColor );
+ }
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::RefreshExtraData(), SwLayoutFrm::RefreshExtraData()
+|*
+|* Beschreibung Erneuert alle Extradaten (Zeilennummern usw) der Seite.
+|* Grundsaetzlich sind nur diejenigen Objekte beruecksichtig,
+|* die in die seitliche Ausdehnung des Rects ragen.
+|*
+|*************************************************************************/
+
+void SwPageFrm::RefreshExtraData( const SwRect &rRect ) const
+{
+ const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
+ sal_Bool bLineInFly = (rInfo.IsPaintLineNumbers() && rInfo.IsCountInFlys())
+ || (sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE;
+
+ SwRect aRect( rRect );
+ ::SwAlignRect( aRect, pGlobalShell );
+ if ( aRect.HasArea() )
+ {
+ SwLayoutFrm::RefreshExtraData( aRect );
+
+ if ( bLineInFly && GetSortedObjs() )
+ for ( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->Frm().Top() <= aRect.Bottom() &&
+ pFly->Frm().Bottom() >= aRect.Top() )
+ pFly->RefreshExtraData( aRect );
+ }
+ }
+ }
+}
+
+void SwLayoutFrm::RefreshExtraData( const SwRect &rRect ) const
+{
+
+ const SwLineNumberInfo &rInfo = GetFmt()->GetDoc()->GetLineNumberInfo();
+ sal_Bool bLineInBody = rInfo.IsPaintLineNumbers(),
+ bLineInFly = bLineInBody && rInfo.IsCountInFlys(),
+ bRedLine = (sal_Int16)SW_MOD()->GetRedlineMarkPos()!=text::HoriOrientation::NONE;
+
+ const SwCntntFrm *pCnt = ContainsCntnt();
+ while ( pCnt && IsAnLower( pCnt ) )
+ {
+ if ( pCnt->IsTxtFrm() && ( bRedLine ||
+ ( !pCnt->IsInTab() &&
+ ((bLineInBody && pCnt->IsInDocBody()) ||
+ (bLineInFly && pCnt->IsInFly())) ) ) &&
+ pCnt->Frm().Top() <= rRect.Bottom() &&
+ pCnt->Frm().Bottom() >= rRect.Top() )
+ {
+ ((SwTxtFrm*)pCnt)->PaintExtraData( rRect );
+ }
+ if ( bLineInFly && pCnt->GetDrawObjs() )
+ for ( sal_uInt32 i = 0; i < pCnt->GetDrawObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pCnt->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() &&
+ pFly->Frm().Top() <= rRect.Bottom() &&
+ pFly->Frm().Bottom() >= rRect.Top() )
+ pFly->RefreshExtraData( rRect );
+ }
+ }
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+/** SwPageFrm::GetDrawBackgrdColor - for #102450#
+
+ determine the color, that is respectively will be drawn as background
+ for the page frame.
+ Using existing method SwFrm::GetBackgroundBrush to determine the color
+ that is set at the page frame respectively is parent. If none is found
+ return the global retouche color
+
+ @author OD
+
+ @return Color
+*/
+const Color& SwPageFrm::GetDrawBackgrdColor() const
+{
+ const SvxBrushItem* pBrushItem;
+ const Color* pDummyColor;
+ SwRect aDummyRect;
+ if ( GetBackgroundBrush( pBrushItem, pDummyColor, aDummyRect, true) )
+ return pBrushItem->GetColor();
+ else
+ return aGlobalRetoucheColor;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetEmptyPageFont()
+|*
+|* create/return font used to paint the "empty page" string
+|*
+|*************************************************************************/
+
+const Font& SwPageFrm::GetEmptyPageFont()
+{
+ static Font* pEmptyPgFont = 0;
+ if ( 0 == pEmptyPgFont )
+ {
+ pEmptyPgFont = new Font;
+ pEmptyPgFont->SetSize( Size( 0, 80 * 20 )); // == 80 pt
+ pEmptyPgFont->SetWeight( WEIGHT_BOLD );
+ pEmptyPgFont->SetStyleName( aEmptyStr );
+ pEmptyPgFont->SetName( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "Helvetica" )) );
+ pEmptyPgFont->SetFamily( FAMILY_SWISS );
+ pEmptyPgFont->SetTransparent( sal_True );
+ pEmptyPgFont->SetColor( COL_GRAY );
+ }
+
+ return *pEmptyPgFont;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Retouche
+|*
+|* Beschreibung Retouche fuer einen Bereich.
+|* Retouche wird nur dann durchgefuehrt, wenn der Frm der letzte seiner
+|* Kette ist. Der Gesamte Bereich des Upper unterhalb des Frm wird
+|* per PaintBackground gecleared.
+|*
+|*************************************************************************/
+
+void SwFrm::Retouche( const SwPageFrm * pPage, const SwRect &rRect ) const
+{
+ if ( bFlyMetafile )
+ return;
+
+ OSL_ENSURE( GetUpper(), "Retoucheversuch ohne Upper." );
+ OSL_ENSURE( getRootFrm()->GetCurrShell() && pGlobalShell->GetWin(), "Retouche auf dem Drucker?" );
+
+ SwRect aRetouche( GetUpper()->PaintArea() );
+ aRetouche.Top( Frm().Top() + Frm().Height() );
+ aRetouche.Intersection( pGlobalShell->VisArea() );
+
+ if ( aRetouche.HasArea() )
+ {
+ //Uebergebenes Rect ausparen. Dafuer brauchen wir leider eine Region
+ //zum ausstanzen.
+ SwRegionRects aRegion( aRetouche );
+ aRegion -= rRect;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pSh->GetOut() );
+ // <--
+
+ for ( sal_uInt16 i = 0; i < aRegion.Count(); ++i )
+ {
+ SwRect &rRetouche = aRegion[i];
+
+ GetUpper()->PaintBaBo( rRetouche, pPage, sal_True );
+
+ //Hoelle und Himmel muessen auch refreshed werden.
+ //Um Rekursionen zu vermeiden muss mein Retouche Flag zuerst
+ //zurueckgesetzt werden!
+ ResetRetouche();
+ SwRect aRetouchePart( rRetouche );
+ if ( aRetouchePart.HasArea() )
+ {
+ // OD 30.08.2002 #102450#
+ // determine background color of page for <PaintLayer> method
+ // calls, painting <hell> or <heaven>
+ const Color aPageBackgrdColor = pPage->GetDrawBackgrdColor();
+ // OD 29.08.2002 #102450#
+ // add 3rd parameter to <PaintLayer> method calls
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+
+ pSh->Imp()->PaintLayer( pIDDMA->GetHellId(), 0,
+ aRetouchePart, &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ pSh->Imp()->PaintLayer( pIDDMA->GetHeavenId(), 0,
+ aRetouchePart, &aPageBackgrdColor,
+ (pPage->IsRightToLeft() ? true : false) );
+ }
+
+ SetRetouche();
+
+ //Da wir uns ausserhalb aller Paint-Bereiche begeben muessen hier
+ //leider die Hilfslinien erneuert werden.
+ pPage->RefreshSubsidiary( aRetouchePart );
+ }
+ }
+ if ( ViewShell::IsLstEndAction() )
+ ResetRetouche();
+}
+
+/** SwFrm::GetBackgroundBrush
+
+ @descr
+ determine the background brush for the frame:
+ the background brush is taken from it-self or from its parent (anchor/upper).
+ Normally, the background brush is taken, which has no transparent color or
+ which has a background graphic. But there are some special cases:
+ (1) No background brush is taken from a page frame, if view option "IsPageBack"
+ isn't set.
+ (2) Background brush from a index section is taken under special conditions.
+ In this case parameter <rpCol> is set to the index shading color.
+ (3) New (OD 20.08.2002) - Background brush is taken, if on background drawing
+ of the frame transparency is considered and its color is not "no fill"/"auto fill"
+ ---- old description in german:
+ Beschreibung Liefert die Backgroundbrush fuer den Bereich des
+ des Frm. Die Brush wird entweder von ihm selbst oder von einem
+ Upper vorgegeben, die erste Brush wird benutzt.
+ Ist fuer keinen Frm eine Brush angegeben, so wird sal_False zurueck-
+ geliefert.
+
+ @param rpBrush
+ output parameter - constant reference pointer the found background brush
+
+ @param rpCol
+ output parameter - constant reference pointer to the color of the index shading
+ set under special conditions, if background brush is taken from an index section.
+
+ @param rOrigRect
+ in-/output parameter - reference to the retangle the background brush is
+ considered for - adjusted to the frame, from which the background brush is
+ taken.
+
+ @parem bLowerMode
+ input parameter - boolean indicating, if background brush should *not* be
+ taken from parent.
+
+ @return true, if a background brush for the frame is found
+*/
+sal_Bool SwFrm::GetBackgroundBrush( const SvxBrushItem* & rpBrush,
+ const Color*& rpCol,
+ SwRect &rOrigRect,
+ sal_Bool bLowerMode ) const
+{
+ const SwFrm *pFrm = this;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const SwViewOption *pOpt = pSh->GetViewOptions();
+ rpBrush = 0;
+ rpCol = NULL;
+ do
+ { if ( pFrm->IsPageFrm() && !pOpt->IsPageBack() )
+ return sal_False;
+
+ const SvxBrushItem &rBack = pFrm->GetAttrSet()->GetBackground();
+ if( pFrm->IsSctFrm() )
+ {
+ const SwSection* pSection = ((SwSectionFrm*)pFrm)->GetSection();
+ /// OD 20.08.2002 #99657# #GetTransChg#
+ /// Note: If frame <pFrm> is a section of the index and
+ /// it its background color is "no fill"/"auto fill" and
+ /// it has no background graphic and
+ /// we are not in the page preview and
+ /// we are not in read-only mode and
+ /// option "index shadings" is set and
+ /// the output is not the printer
+ /// then set <rpCol> to the color of the index shading
+ if( pSection && ( TOX_HEADER_SECTION == pSection->GetType() ||
+ TOX_CONTENT_SECTION == pSection->GetType() ) &&
+ (rBack.GetColor() == COL_TRANSPARENT) &&
+ ///rBack.GetColor().GetTransparency() &&
+ rBack.GetGraphicPos() == GPOS_NONE &&
+ !pOpt->IsPagePreview() &&
+ !pOpt->IsReadonly() &&
+ // --> FME 2004-06-29 #114856# Formular view
+ !pOpt->IsFormView() &&
+ // <--
+ SwViewOption::IsIndexShadings() &&
+ !pOpt->IsPDFExport() &&
+ pSh->GetOut()->GetOutDevType() != OUTDEV_PRINTER )
+ {
+ rpCol = &SwViewOption::GetIndexShadingsColor();
+ }
+ }
+
+ /// OD 20.08.2002 #99657#
+ /// determine, if background draw of frame <pFrm> considers transparency
+ /// --> Status Quo: background transparency have to be
+ /// considered for fly frames
+ const sal_Bool bConsiderBackgroundTransparency = pFrm->IsFlyFrm();
+ /// OD 20.08.2002 #99657#
+ /// add condition:
+ /// If <bConsiderBackgroundTransparency> is set - see above -,
+ /// return brush of frame <pFrm>, if its color is *not* "no fill"/"auto fill"
+ if ( !rBack.GetColor().GetTransparency() ||
+ rBack.GetGraphicPos() != GPOS_NONE ||
+ rpCol ||
+ (bConsiderBackgroundTransparency && (rBack.GetColor() != COL_TRANSPARENT))
+ )
+ {
+ rpBrush = &rBack;
+ if ( pFrm->IsPageFrm() &&
+ pSh->GetViewOptions()->getBrowseMode() )
+ rOrigRect = pFrm->Frm();
+ else
+ {
+ if ( pFrm->Frm().SSize() != pFrm->Prt().SSize() )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ ::lcl_CalcBorderRect( rOrigRect, pFrm, rAttrs, sal_False );
+ }
+ else
+ {
+ rOrigRect = pFrm->Prt();
+ rOrigRect += pFrm->Frm().Pos();
+ }
+ }
+ return sal_True;
+ }
+
+ if ( bLowerMode )
+ /// Do not try to get background brush from parent (anchor/upper)
+ return sal_False;
+
+ /// get parent frame - anchor or upper - for next loop
+ if ( pFrm->IsFlyFrm() )
+ /// OD 20.08.2002 - use "static_cast" instead of "old C-cast"
+ pFrm = (static_cast<const SwFlyFrm*>(pFrm))->GetAnchorFrm();
+ ///pFrm = ((SwFlyFrm*)pFrm)->GetAnchor();
+ else
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm );
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrmFmt::GetGraphic()
+|*
+|*************************************************************************/
+
+void SetOutDevAndWin( ViewShell *pSh, OutputDevice *pO,
+ Window *pW, sal_uInt16 nZoom )
+{
+ pSh->pOut = pO;
+ pSh->pWin = pW;
+ pSh->pOpt->SetZoom( nZoom );
+}
+
+Graphic SwFrmFmt::MakeGraphic( ImageMap* )
+{
+ return Graphic();
+}
+
+Graphic SwFlyFrmFmt::MakeGraphic( ImageMap* pMap )
+{
+ Graphic aRet;
+ //irgendeinen Fly suchen!
+ SwIterator<SwFrm,SwFmt> aIter( *this );
+ SwFrm *pFirst = aIter.First();
+ ViewShell *pSh;
+ if ( pFirst && 0 != ( pSh = pFirst->getRootFrm()->GetCurrShell()) )
+ {
+ ViewShell *pOldGlobal = pGlobalShell;
+ pGlobalShell = pSh;
+
+ sal_Bool bNoteURL = pMap &&
+ SFX_ITEM_SET != GetAttrSet().GetItemState( RES_URL, sal_True );
+ if( bNoteURL )
+ {
+ OSL_ENSURE( !pNoteURL, "MakeGraphic: pNoteURL already used? " );
+ pNoteURL = new SwNoteURL;
+ }
+ SwFlyFrm *pFly = (SwFlyFrm*)pFirst;
+
+ OutputDevice *pOld = pSh->GetOut();
+ VirtualDevice aDev( *pOld );
+ aDev.EnableOutput( sal_False );
+
+ GDIMetaFile aMet;
+ MapMode aMap( pOld->GetMapMode().GetMapUnit() );
+ aDev.SetMapMode( aMap );
+ aMet.SetPrefMapMode( aMap );
+
+ ::SwCalcPixStatics( pSh->GetOut() );
+ aMet.SetPrefSize( pFly->Frm().SSize() );
+
+ aMet.Record( &aDev );
+ aDev.SetLineColor();
+ aDev.SetFillColor();
+ aDev.SetFont( pOld->GetFont() );
+
+ //Rechteck ggf. ausdehnen, damit die Umrandunge mit aufgezeichnet werden.
+ SwRect aOut( pFly->Frm() );
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFly );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ if ( rAttrs.CalcRightLine() )
+ aOut.SSize().Width() += 2*nPixelSzW;
+ if ( rAttrs.CalcBottomLine() )
+ aOut.SSize().Height()+= 2*nPixelSzH;
+
+ // #i92711# start Pre/PostPaint encapsulation before pOut is changed to the buffering VDev
+ const Region aRepaintRegion(aOut.SVRect());
+ pSh->DLPrePaint2(aRepaintRegion);
+
+ Window *pWin = pSh->GetWin();
+ sal_uInt16 nZoom = pSh->GetViewOptions()->GetZoom();
+ ::SetOutDevAndWin( pSh, &aDev, 0, 100 );
+ bFlyMetafile = sal_True;
+ pFlyMetafileOut = pWin;
+
+ SwViewImp *pImp = pSh->Imp();
+ pFlyOnlyDraw = pFly;
+ pLines = new SwLineRects;
+
+ // OD 09.12.2002 #103045# - determine page, fly frame is on
+ const SwPageFrm* pFlyPage = pFly->FindPageFrm();
+ // OD 30.08.2002 #102450#
+ // determine color of page, the fly frame is on, for <PaintLayer> method
+ // calls, painting <hell> or <heaven>
+ const Color aPageBackgrdColor = pFlyPage->GetDrawBackgrdColor();
+ // OD 30.08.2002 #102450# - add 3rd parameter
+ // OD 09.12.2002 #103045# - add 4th parameter for horizontal text direction.
+ const IDocumentDrawModelAccess* pIDDMA = pSh->getIDocumentDrawModelAccess();
+ pImp->PaintLayer( pIDDMA->GetHellId(), 0, aOut, &aPageBackgrdColor,
+ (pFlyPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( &aDev );
+ if ( pFly->IsFlyInCntFrm() )
+ pFly->Paint( aOut );
+ pLines->PaintLines( &aDev );
+ /// OD 30.08.2002 #102450# - add 3rd parameter
+ pImp->PaintLayer( pIDDMA->GetHeavenId(), 0, aOut, &aPageBackgrdColor,
+ (pFlyPage->IsRightToLeft() ? true : false) );
+ pLines->PaintLines( &aDev );
+ DELETEZ( pLines );
+ pFlyOnlyDraw = 0;
+
+ pFlyMetafileOut = 0;
+ bFlyMetafile = sal_False;
+ ::SetOutDevAndWin( pSh, pOld, pWin, nZoom );
+
+ // #i92711# end Pre/PostPaint encapsulation when pOut is back and content is painted
+ pSh->DLPostPaint2(true);
+
+ aMet.Stop();
+ aMet.Move( -pFly->Frm().Left(), -pFly->Frm().Top() );
+ aRet = Graphic( aMet );
+
+ if( bNoteURL )
+ {
+ OSL_ENSURE( pNoteURL, "MakeGraphic: Good Bye, NoteURL." );
+ pNoteURL->FillImageMap( pMap, pFly->Frm().Pos(), aMap );
+ delete pNoteURL;
+ pNoteURL = NULL;
+ }
+ pGlobalShell = pOldGlobal;
+ }
+ return aRet;
+}
+
+Graphic SwDrawFrmFmt::MakeGraphic( ImageMap* )
+{
+ Graphic aRet;
+ SdrModel *pMod = getIDocumentDrawModelAccess()->GetDrawModel();
+ if ( pMod )
+ {
+ SdrObject *pObj = FindSdrObject();
+ SdrView *pView = new SdrView( pMod );
+ SdrPageView *pPgView = pView->ShowSdrPage(pView->GetModel()->GetPage(0));
+ pView->MarkObj( pObj, pPgView );
+ aRet = pView->GetMarkedObjBitmap();
+ pView->HideSdrPage();
+ delete pView;
+ }
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sectfrm.cxx b/sw/source/core/layout/sectfrm.cxx
new file mode 100644
index 000000000000..d7f5364c38f7
--- /dev/null
+++ b/sw/source/core/layout/sectfrm.cxx
@@ -0,0 +1,2779 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/smplhint.hxx>
+#include <svl/itemiter.hxx>
+#include <hints.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtclbl.hxx>
+#include "sectfrm.hxx"
+#include "section.hxx" // SwSection
+#include "frmtool.hxx" // StackHack
+#include "doc.hxx" // SwDoc
+#include "cntfrm.hxx" // SwCntntFrm
+#include "rootfrm.hxx" // SwRootFrm
+#include "pagefrm.hxx" // SwPageFrm
+#include "fmtpdsc.hxx" // SwFmtPageDesc
+#include "fmtcntnt.hxx" // SwFmtCntnt
+#include "ndindex.hxx" // SwNodeIndex
+#include "ftnidx.hxx"
+#include "txtfrm.hxx" // SwTxtFrm
+#include "fmtclds.hxx" // SwFmtCol
+#include "colfrm.hxx" // SwColumnFrm
+#include "tabfrm.hxx" // SwTabFrm
+#include "flyfrm.hxx" // SwFlyFrm
+#include "ftnfrm.hxx" // SwFtnFrm
+#include "layouter.hxx" // SwLayouter
+#include "dbg_lay.hxx"
+#include "viewsh.hxx"
+#include "viewopt.hxx"
+#include "viewimp.hxx"
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <fmtftntx.hxx>
+// OD 2004-05-24 #i28701#
+#include <dflyobj.hxx>
+#include <flyfrms.hxx>
+#include <sortedobjs.hxx>
+
+SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr )
+
+/*************************************************************************
+|*
+|* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm()
+|*
+|*************************************************************************/
+SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) :
+ SwLayoutFrm( rSect.GetFmt(), pSib ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pSection( &rSect )
+{
+ nType = FRMC_SECTION;
+
+ CalcFtnAtEndFlag();
+ CalcEndAtEndFlag();
+}
+
+SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) :
+ SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pSection( rSect.GetSection() )
+{
+ bFtnAtEnd = rSect.IsFtnAtEnd();
+ bEndnAtEnd = rSect.IsEndnAtEnd();
+ bLockJoin = sal_False;
+ nType = FRMC_SECTION;
+
+ PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect )
+
+ if( bMaster )
+ {
+ if( rSect.IsFollow() )
+ {
+ SwSectionFrm* pMaster = rSect.FindMaster();
+ pMaster->SetFollow( this );
+ bIsFollow = sal_True;
+ }
+ else
+ rSect.bIsFollow = sal_True;
+ SetFollow( &rSect );
+ }
+ else
+ {
+ bIsFollow = sal_True;
+ SetFollow( rSect.GetFollow() );
+ rSect.SetFollow( this );
+ if( !GetFollow() )
+ rSect.SimpleFormat();
+ if( !rSect.IsColLocked() )
+ rSect.InvalidateSize();
+ }
+}
+
+// NOTE: call <SwSectionFrm::Init()> directly after creation of a new section
+// frame and its insert in the layout.
+void SwSectionFrm::Init()
+{
+ OSL_ENSURE( GetUpper(), "SwSectionFrm::Init before insertion?!" );
+ SWRECTFN( this )
+ long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ (Frm().*fnRect->fnSetWidth)( nWidth );
+ (Frm().*fnRect->fnSetHeight)( 0 );
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() );
+ (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
+ rLRSpace.GetRight() );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() )
+ {
+ const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol;
+ ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() );
+ if( pOld != &rCol )
+ delete pOld;
+ }
+}
+
+SwSectionFrm::~SwSectionFrm()
+{
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm )
+ pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225
+ if( IsFollow() )
+ {
+ SwSectionFrm *pMaster = FindMaster();
+ if( pMaster )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster )
+ pMaster->SetFollow( GetFollow() );
+ // Ein Master greift sich immer den Platz bis zur Unterkante seines
+ // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
+ // freigeben, deshalb wird die Size des Masters invalidiert.
+ if( !GetFollow() )
+ pMaster->InvalidateSize();
+ }
+ }
+ else if( HasFollow() )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() )
+ GetFollow()->bIsFollow = sal_False;
+ }
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwSectionFrm::DelEmpty()
+|*
+|*************************************************************************/
+void SwSectionFrm::DelEmpty( sal_Bool bRemove )
+{
+ if( IsColLocked() )
+ {
+ OSL_ENSURE( !bRemove, "Don't delete locked SectionFrms" );
+ return;
+ }
+ SwFrm* pUp = GetUpper();
+ if( pUp )
+ {
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
+ {
+ ViewShell* pViewShell( getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ _Cut( bRemove );
+ }
+ if( IsFollow() )
+ {
+ SwSectionFrm *pMaster = FindMaster();
+ pMaster->SetFollow( GetFollow() );
+ // Ein Master greift sich immer den Platz bis zur Unterkante seines
+ // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder
+ // freigeben, deshalb wird die Size des Masters invalidiert.
+ if( !GetFollow() && !pMaster->IsColLocked() )
+ pMaster->InvalidateSize();
+ bIsFollow = sal_False;
+ }
+ else if( HasFollow() )
+ GetFollow()->bIsFollow = sal_False;
+ pFollow = NULL;
+ if( pUp )
+ {
+ Frm().Height( 0 );
+ // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir
+ // uns gar nicht erst in die Liste eintragen
+ if( bRemove )
+ { // Wenn wir bereits halbtot waren vor diesem DelEmpty, so
+ // stehen wir vermutlich auch in der Liste und muessen uns
+ // dort austragen
+ if( !pSection && getRootFrm() )
+ getRootFrm()->RemoveFromList( this );
+ }
+ else if( getRootFrm() )
+ getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225
+ pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Cut()
+|*
+|*************************************************************************/
+void SwSectionFrm::Cut()
+{
+ _Cut( sal_True );
+}
+
+void SwSectionFrm::_Cut( sal_Bool bRemove )
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ PROTOCOL( this, PROT_CUT, 0, GetUpper() )
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetNext();
+ SwFrm* pPrepFrm = NULL;
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet der ist jetzt wo er der erste wird obsolete
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if ( pFrm && pFrm->IsCntntFrm() )
+ {
+ pFrm->InvalidatePage( pPage );
+ if( IsInFtn() && !GetIndPrev() )
+ pPrepFrm = pFrm;
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ }
+ }
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ if( bRemove )
+ {
+ Remove();
+ if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() &&
+ pUp->GetUpper() )
+ {
+ pUp->Cut();
+ delete pUp;
+ pUp = NULL;
+ }
+ }
+ if( pPrepFrm )
+ pPrepFrm->Prepare( PREP_FTN );
+ if ( pUp )
+ {
+ SWRECTFN( this );
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 )
+ {
+ if( !bRemove )
+ {
+ (Frm().*fnRect->fnSetHeight)( 0 );
+ (Prt().*fnRect->fnSetHeight)( 0 );
+ }
+ pUp->Shrink( nFrmHeight );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Paste()
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ PROTOCOL( this, PROT_PASTE, 0, GetUpper() )
+
+ //In den Baum einhaengen.
+ SwSectionFrm* pSect = pParent->FindSctFrm();
+ // --> OD 2008-06-23 #156927#
+ // Assure that parent is not inside a table frame, which is inside the found section frame.
+ if ( pSect )
+ {
+ SwTabFrm* pTableFrm = pParent->FindTabFrm();
+ if ( pTableFrm &&
+ pSect->IsAnLower( pTableFrm ) )
+ {
+ pSect = 0;
+ }
+ }
+ // <--
+
+ SWRECTFN( pParent )
+ if( pSect && HasToBreak( pSect ) )
+ {
+ if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich
+ {
+ // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling
+ // auf den ersten Frame der naechsten Spalte zeigen, damit
+ // der Inhalt der naechsten Spalte von InsertGroup richtig in den
+ // neu angelegten pSect umgehaengt wird.
+ SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper();
+ while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
+ pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower();
+ if( pSibling )
+ {
+ // Schlimmer noch: alle folgenden Spalteninhalte muessen
+ // an die pSibling-Kette angehaengt werden, damit sie
+ // mitgenommen werden.
+ SwFrm *pTmp = pSibling;
+ while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) )
+ {
+ while ( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ SwFrm* pSave = ::SaveCntnt( pCol );
+ ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true );
+ }
+ }
+ }
+ pParent = pSect;
+ pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent );
+ // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am
+ // neuen, zweiten Teil angebracht werden.
+ pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() );
+ ((SwSectionFrm*)pParent)->SetFollow( NULL );
+ if( pSect->GetFollow() )
+ pParent->_InvalidateSize();
+
+ InsertGroupBefore( pParent, pSibling, pSect );
+ pSect->Init();
+ (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True);
+ if( !((SwLayoutFrm*)pParent)->Lower() )
+ {
+ SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False );
+ pParent = this;
+ }
+ }
+ else
+ InsertGroupBefore( pParent, pSibling, NULL );
+
+ _InvalidateAll();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+
+ if ( pSibling )
+ {
+ pSibling->_InvalidatePos();
+ pSibling->_InvalidatePrt();
+ if ( pSibling->IsCntntFrm() )
+ pSibling->InvalidatePage( pPage );
+ }
+
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight )
+ pParent->Grow( nFrmHeight );
+
+ if ( GetPrev() )
+ {
+ if ( !IsFollow() )
+ {
+ GetPrev()->InvalidateSize();
+ if ( GetPrev()->IsCntntFrm() )
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwSectionFrm::HasToBreak()
+|*
+|* Hier wird entschieden, ob der this-SectionFrm den uebergebenen
+|* (Section)Frm aufbrechen soll oder nicht.
+|* Zunaechst werden uebergeordnete Bereiche immer aufgebrochen,
+|* spaeter koennte man es einstellbar machen.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const
+{
+ if( !pFrm->IsSctFrm() )
+ return sal_False;
+
+ SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt();
+// if( !pTmp->GetSect().GetValue() )
+// return sal_False;
+
+ const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt();
+ do
+ {
+ pTmp = pTmp->GetParent();
+ if( !pTmp )
+ return sal_False;
+ if( pTmp == pOtherFmt )
+ return sal_True;
+ } while( sal_True ); // ( pTmp->GetSect().GetValue() );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MergeNext()
+|*
+|* Verschmilzt zwei SectionFrms, falls es sich um den
+|* gleichen Bereich handelt.
+|* Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der
+|* einen anderen in zwei Teile zerlegt hatte.
+|*
+|*************************************************************************/
+
+void SwSectionFrm::MergeNext( SwSectionFrm* pNxt )
+{
+ if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() )
+ {
+ PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt )
+
+ SwFrm* pTmp = ::SaveCntnt( pNxt );
+ if( pTmp )
+ {
+ SwFrm* pLast = Lower();
+ SwLayoutFrm* pLay = this;
+ if( pLast )
+ {
+ while( pLast->GetNext() )
+ pLast = pLast->GetNext();
+ if( pLast->IsColumnFrm() )
+ { // Spalten jetzt mit BodyFrm
+ pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower();
+ pLast = pLay->Lower();
+ if( pLast )
+ while( pLast->GetNext() )
+ pLast = pLast->GetNext();
+ }
+ }
+ ::RestoreCntnt( pTmp, pLay, pLast, true );
+ }
+ SetFollow( pNxt->GetFollow() );
+ pNxt->SetFollow( NULL );
+ pNxt->bIsFollow = sal_False;
+ pNxt->Cut();
+ delete pNxt;
+ InvalidateSize();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::SplitSect()
+|*
+|* Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem
+|* uebergebenen Frame.
+|* Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb
+|* von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt
+|* haben kann.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres )
+{
+ OSL_ENSURE( pFrm, "SplitSect: Why?" );
+ SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev();
+ if( !pOther )
+ return sal_False;
+ SwSectionFrm* pSect = pOther->FindSctFrm();
+ if( pSect != this )
+ return sal_False;
+ // Den Inhalt zur Seite stellen
+ SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm );
+ OSL_ENSURE( pSav, "SplitSect: What's on?" );
+ if( pSav ) // Robust
+ { // Einen neuen SctFrm anlegen, nicht als Follow/Master
+ SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect );
+ pNew->InsertBehind( pSect->GetUpper(), pSect );
+ pNew->Init();
+ SWRECTFN( this )
+ (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True );
+ // OD 25.03.2003 #108339# - restore content:
+ // determine layout frame for restoring content after the initialization
+ // of the section frame. In the section initialization the columns are
+ // created.
+ {
+ SwLayoutFrm* pLay = pNew;
+ // Search for last layout frame, e.g. for columned sections.
+ while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
+ pLay = (SwLayoutFrm*)pLay->Lower();
+ ::RestoreCntnt( pSav, pLay, NULL, true );
+ }
+ _InvalidateSize();
+ if( HasFollow() )
+ {
+ pNew->SetFollow( GetFollow() );
+ SetFollow( NULL );
+ }
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MoveCntntAndDelete()
+|*
+|* MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder
+|* Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen.
+|* Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in
+|* den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm
+|* umgehaengt, dieser muss ggf. gemergt werden.
+|*
+|*************************************************************************/
+// Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms
+// invalidiert werden
+
+void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva )
+{
+ while ( pFrm )
+ {
+ pFrm->InvalidateInfFlags();
+ if( bInva )
+ {
+ pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ }
+ if( pFrm->IsLayoutFrm() )
+ lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False );
+ pFrm = pFrm->GetNext();
+ }
+}
+
+
+//
+// Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm
+//
+SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd )
+{
+ if ( bFwd )
+ {
+ if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() )
+ return (SwCntntFrm*)pLay->GetNext();
+ }
+ else
+ {
+ if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() )
+ return (SwCntntFrm*)pLay->GetPrev();
+ }
+
+ // #100926#
+ const SwFrm* pFrm = pLay;
+ SwCntntFrm *pCntntFrm = 0;
+ sal_Bool bGoingUp = sal_True;
+ do {
+ const SwFrm *p = 0;
+ sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False;
+
+ bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) );
+ if ( !bGoingDown )
+ {
+ bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ?
+ ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) :
+ ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) );
+ if ( !bGoingFwdOrBwd )
+ {
+ bGoingUp = (0 != (p = pFrm->GetUpper() ) );
+ if ( !bGoingUp )
+ return 0;
+ }
+ }
+
+ bGoingUp = !( bGoingFwdOrBwd || bGoingDown );
+
+ if( !bFwd && bGoingDown && p )
+ while ( p->GetNext() )
+ p = p->GetNext();
+
+ pFrm = p;
+ } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) ));
+
+ return pCntntFrm;
+}
+
+#define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\
+ ? pLayFrm->GetNextLayoutLeaf() \
+ : pLayFrm )
+
+void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave )
+{
+ sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm();
+ SwFrm* pPrv = pDel->GetPrev();
+ SwLayoutFrm* pUp = pDel->GetUpper();
+ // OD 27.03.2003 #i12711# - initialize local pointer variables.
+ SwSectionFrm* pPrvSct = NULL;
+ SwSectionFrm* pNxtSct = NULL;
+ SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent();
+ if( pDel->IsInTab() && pParent )
+ {
+ SwTabFrm *pTab = pDel->FindTabFrm();
+ // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche
+ // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa
+ // einen Bereich, der die gesamte Tabelle umfasst.
+ if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() )
+ pParent = NULL;
+ }
+ // Wenn unser Format einen Parent besitzt, so haben wir vermutlich
+ // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden,
+ // dazu besorgen wir uns zunaechst den vorhergehende und den nach-
+ // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen.
+ // OD 27.03.2003 #i12711# - check, if previous and next section belonging
+ // together and can be joined, *not* only if deleted section contains content.
+ if ( pParent )
+ {
+ SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false );
+ pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL;
+ SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true );
+ pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL;
+ }
+ else
+ {
+ pParent = NULL;
+ pPrvSct = pNxtSct = NULL;
+ }
+
+ // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert
+ SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL;
+ sal_Bool bOldFtn = sal_True;
+ if( pSave && pUp->IsFtnFrm() )
+ {
+ bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked();
+ ((SwFtnFrm*)pUp)->ColLock();
+ }
+ pDel->DelEmpty( sal_True );
+ delete pDel;
+ if( pParent )
+ { // Hier wird die geeignete Einfuegeposition gesucht
+ if( pNxtSct && pNxtSct->GetFmt() == pParent )
+ { // Hier koennen wir uns am Anfang einfuegen
+ pUp = FIRSTLEAF( pNxtSct );
+ pPrv = NULL;
+ if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) )
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ else if( pPrvSct && pPrvSct->GetFmt() == pParent )
+ { // Wunderbar, hier koennen wir uns am Ende einfuegen
+ pUp = pPrvSct;
+ if( pUp->Lower() && pUp->Lower()->IsColumnFrm() )
+ {
+ pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower());
+ // Der Body der letzten Spalte
+ pUp = static_cast<SwLayoutFrm*>(pUp->Lower());
+ }
+ // damit hinter dem letzten eingefuegt wird
+ pPrv = pUp->GetLastLower();
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ else
+ {
+ if( pSave )
+ { // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich
+ // ist entweder die Bereichsgrenze des umfassenden Bereichs oder
+ // es schliesst ein anderer (Geschwister-)Bereich direkt an, der
+ // vom gleichen Parent abgeleitet ist.
+ // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt
+ // aufnehmen kann,also bauen wir ihn uns.
+ pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp );
+ pPrvSct->InsertBehind( pUp, pPrv );
+ pPrvSct->Init();
+ SWRECTFN( pUp )
+ (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True );
+ pUp = FIRSTLEAF( pPrvSct );
+ pPrv = NULL;
+ }
+ pPrvSct = NULL; // damit nicht gemergt wird
+ }
+ }
+ // Der Inhalt wird eingefuegt..
+ if( pSave )
+ {
+ lcl_InvalidateInfFlags( pSave, bSize );
+ ::RestoreCntnt( pSave, pUp, pPrv, true );
+ pUp->FindPageFrm()->InvalidateCntnt();
+ if( !bOldFtn )
+ ((SwFtnFrm*)pUp)->ColUnlock();
+ }
+ // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen
+ if( pPrvSct && !pPrvSct->IsJoinLocked() )
+ {
+ OSL_ENSURE( pNxtSct, "MoveCntnt: No Merge" );
+ pPrvSct->MergeNext( pNxtSct );
+ }
+}
+
+void SwSectionFrm::MakeAll()
+{
+ if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
+ return;
+ if( !pSection ) // Durch DelEmpty
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
+#endif
+ if( !bValidPos )
+ {
+ if( GetUpper() )
+ {
+ SWRECTFN( GetUpper() )
+ (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
+ }
+ }
+ bValidSize = bValidPos = bValidPrtArea = sal_True;
+ return;
+ }
+ LockJoin(); //Ich lass mich nicht unterwegs vernichten.
+
+ while( GetNext() && GetNext() == GetFollow() )
+ {
+ const SwFrm* pFoll = GetFollow();
+ MergeNext( (SwSectionFrm*)GetNext() );
+ if( pFoll == GetFollow() )
+ break;
+ }
+
+ // OD 2004-03-15 #116561# - In online layout join the follows, if section
+ // can grow.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ ( Grow( LONG_MAX, true ) > 0 ) )
+ {
+ while( GetFollow() )
+ {
+ const SwFrm* pFoll = GetFollow();
+ MergeNext( GetFollow() );
+ if( pFoll == GetFollow() )
+ break;
+ }
+ }
+
+ // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers
+ // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen...
+ if( !bValidPos && ToMaximize( sal_False ) )
+ bValidSize = sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ const SwFmtCol &rCol = GetFmt()->GetCol();
+ (void)rCol;
+#endif
+ SwLayoutFrm::MakeAll();
+ UnlockJoin();
+ if( pSection && IsSuperfluous() )
+ DelEmpty( sal_False );
+}
+
+sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & )
+{
+ OSL_FAIL( "Hups, wo ist meine Tarnkappe?" );
+ return sal_False;
+}
+
+const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const
+{
+ const SwSectionFmt *pFmt = pSection->GetFmt();
+ while( !pFmt->GetEndAtTxtEnd().IsAtEnd() )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ return NULL;
+ }
+ return pFmt;
+}
+
+void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm,
+ SwFrm* pFrm, sal_Bool &rbChkFtn )
+{
+ if( pFrm )
+ {
+ while( pFrm->GetNext() )
+ pFrm = pFrm->GetNext();
+ while( !rpCntntFrm && pFrm )
+ {
+ if( pFrm->IsCntntFrm() )
+ rpCntntFrm = (SwCntntFrm*)pFrm;
+ else if( pFrm->IsLayoutFrm() )
+ {
+ if( pFrm->IsFtnFrm() )
+ {
+ if( rbChkFtn )
+ {
+ rpFtnFrm = (SwFtnFrm*)pFrm;
+ rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote();
+ }
+ }
+ else
+ lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm,
+ ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn );
+ }
+ pFrm = pFrm->GetPrev();
+ }
+ }
+}
+
+SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode )
+{
+ SwCntntFrm *pRet = NULL;
+ SwFtnFrm *pFtnFrm = NULL;
+ SwSectionFrm *pSect = this;
+ if( nMode )
+ {
+ const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() :
+ pSection->GetFmt();
+ do {
+ while( pSect->HasFollow() )
+ pSect = pSect->GetFollow();
+ SwFrm* pTmp = pSect->FindNext();
+ while( pTmp && pTmp->IsSctFrm() &&
+ !((SwSectionFrm*)pTmp)->GetSection() )
+ pTmp = pTmp->FindNext();
+ if( pTmp && pTmp->IsSctFrm() &&
+ ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) )
+ pSect = (SwSectionFrm*)pTmp;
+ else
+ break;
+ } while( sal_True );
+ }
+ sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE;
+ do
+ {
+ lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound );
+ if( pRet || !pSect->IsFollow() || !nMode ||
+ ( FINDMODE_MYLAST == nMode && this == pSect ) )
+ break;
+ pSect = pSect->FindMaster();
+ } while( pSect );
+ if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm )
+ pRet = pFtnFrm->ContainsCntnt();
+ return pRet;
+}
+
+sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const
+{
+ if( ToMaximize( sal_True ) )
+ {
+ SWRECTFN( this )
+ rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+ *
+ * SwSectionFrm::CollectEndnotes( )
+ *
+ * CollectEndnotes looks for endnotes in the sectionfrm and his follows,
+ * the endnotes will cut off the layout and put into the array.
+ * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm
+ * contains only endnotes and it is not necessary to collect them.
+ *
+ *************************************************************************/
+
+SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty,
+ SwLayouter *pLayouter )
+{
+ // if rEmpty is set, the rpSect is already searched
+ SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect;
+ while( pSect )
+ {
+ OSL_ENSURE( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(),
+ "InsertEndnotes: Where's my column?" );
+
+ // i73332: Columned section in endnote
+ SwColumnFrm* pCol = 0;
+ if(pSect->Lower() && pSect->Lower()->IsColumnFrm())
+ pCol = (SwColumnFrm*)pSect->Lower();
+
+ while( pCol ) // check all columns
+ {
+ SwFtnContFrm* pFtnCont = pCol->FindFtnCont();
+ if( pFtnCont )
+ {
+ SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower();
+ while( pRet ) // look for endnotes
+ {
+ if( pRet->GetAttr()->GetFtn().IsEndNote() )
+ {
+ if( pRet->GetMaster() )
+ {
+ if( pLayouter )
+ pLayouter->CollectEndnote( pRet );
+ else
+ return 0;
+ }
+ else
+ return pRet; // Found
+ }
+ pRet = (SwFtnFrm*)pRet->GetNext();
+ }
+ }
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ }
+ rpSect = pSect;
+ pSect = pLayouter ? pSect->GetFollow() : NULL;
+ rbEmpty = sal_True;
+ }
+ return NULL;
+}
+
+void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow )
+{
+ while( pSect )
+ {
+ sal_Bool bOldLock = pSect->IsColLocked();
+ pSect->ColLock();
+ if( pSect->Lower() && pSect->Lower()->IsColumnFrm() )
+ {
+ SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower();
+ do
+ { pCol->_InvalidateSize();
+ pCol->_InvalidatePos();
+ ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize();
+ pCol->Calc(); // calculation of column and
+ ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body
+ pCol = (SwColumnFrm*)pCol->GetNext();
+ } while ( pCol );
+ }
+ if( !bOldLock )
+ pSect->ColUnlock();
+ if( bFollow )
+ pSect = pSect->GetFollow();
+ else
+ pSect = NULL;
+ }
+}
+
+void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter )
+{
+ OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" );
+ // i73332: Section in footnode does not have columns!
+ OSL_ENSURE( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" );
+
+ SwSectionFrm* pSect = this;
+ SwFtnFrm* pFtn;
+ sal_Bool bEmpty = sal_False;
+ // pSect is the last sectionfrm without endnotes or the this-pointer
+ // the first sectionfrm with endnotes may be destroyed, when the endnotes
+ // is cutted
+ while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) )
+ pLayouter->CollectEndnote( pFtn );
+ if( pLayouter->HasEndnotes() )
+ lcl_ColumnRefresh( this, sal_True );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
+|*
+|* Beschreibung: Passt die Groesse an die Umgebung an.
+|* Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante
+|* des Uppers gehen (bMaximize).
+|* Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow)
+|* seinen Upper zu growen.
+|* Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert.
+|*
+|*************************************************************************/
+
+/// OD 18.09.2002 #100522#
+/// perform calculation of content, only if height has changed.
+void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize )
+{
+ SWRECTFN( this )
+ long nDiff;
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() ||
+ !FindFlyFrm()->IsLocked() ) )
+ {
+ nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
+ if( !bMaximize )
+ nDiff += Undersize();
+ if( nDiff > 0 )
+ {
+ long nAdd = GetUpper()->Grow( nDiff );
+ if( bVert && !bRev )
+ nDeadLine -= nAdd;
+ else
+ nDeadLine += nAdd;
+ }
+ }
+ nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine );
+ SetUndersized( !bMaximize && nDiff >= 0 );
+ const bool bCalc = ( IsUndersized() || bMaximize ) &&
+ ( nDiff ||
+ (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() );
+ // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate
+ // that a calculation has to be done beside the value of <bCalc>.
+ bool bExtraCalc = false;
+ if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() )
+ {
+ SwSectionFrm *pSect = this;
+ sal_Bool bEmpty = sal_False;
+ SwLayoutFrm* pFtn = IsEndnAtEnd() ?
+ lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL;
+ if( pFtn )
+ {
+ pFtn = pFtn->FindFtnBossFrm();
+ SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT );
+ // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
+ if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) )
+ bExtraCalc = true;
+ }
+ else if( GetFollow() && !GetFollow()->ContainsAny() )
+ bExtraCalc = true;
+ }
+ if ( bCalc || bExtraCalc )
+ {
+ nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() );
+ if( nDiff < 0 )
+ {
+ nDiff = 0;
+ nDeadLine = (Frm().*fnRect->fnGetTop)();
+ }
+ const Size aOldSz( Prt().SSize() );
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ (Frm().*fnRect->fnSetBottom)( nDeadLine );
+ nDiff = (Frm().*fnRect->fnGetHeight)();
+ if( nTop > nDiff )
+ nTop = nDiff;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+
+ // OD 18.09.2002 #100522#
+ // Determine, if height has changed.
+ // Note: In vertical layout the height equals the width value.
+ bool bHeightChanged = bVert ?
+ (aOldSz.Width() != Prt().Width()) :
+ (aOldSz.Height() != Prt().Height());
+ // Wir haben zu guter Letzt noch einmal die Hoehe geaendert,
+ // dann wird das innere Layout (Columns) kalkuliert und
+ // der Inhalt ebenfalls.
+ // OD 18.09.2002 #100522#
+ // calculate content, only if height has changed.
+ // OD 03.11.2003 #i19737# - restriction of content calculation too strong.
+ // If an endnote has an incorrect position or a follow section contains
+ // no content except footnotes/endnotes, the content has also been calculated.
+ if ( ( bHeightChanged || bExtraCalc ) && Lower() )
+ {
+ if( Lower()->IsColumnFrm() )
+ {
+ lcl_ColumnRefresh( this, sal_False );
+ ::CalcCntnt( this );
+ }
+ else
+ {
+ ChgLowersProp( aOldSz );
+ if( !bMaximize && !IsCntntLocked() )
+ ::CalcCntnt( this );
+ }
+ }
+ }
+}
+
+void SwSectionFrm::SimpleFormat()
+{
+ if ( IsJoinLocked() || IsColLocked() )
+ return;
+ // OSL_ENSURE( pFollow, "SimpleFormat: Follow required" );
+ LockJoin();
+ SWRECTFN( this )
+ if( GetPrev() || GetUpper() )
+ {
+ // --> OD 2009-09-28 #b6882166#
+ // assure notifications on position changes.
+ const SwLayNotify aNotify( this );
+ // <--
+ (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False );
+ bValidPos = sal_True;
+ }
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in
+ // order to get calculated lowers, not only if there space left in its upper.
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 )
+ {
+ (Frm().*fnRect->fnSetBottom)( nDeadLine );
+ long nHeight = (Frm().*fnRect->fnGetHeight)();
+ long nTop = CalcUpperSpace();
+ if( nTop > nHeight )
+ nTop = nHeight;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ }
+ lcl_ColumnRefresh( this, sal_False );
+ UnlockJoin();
+}
+
+// --> OD 2005-01-11 #i40147# - helper class to perform extra section format
+// to position anchored objects and to keep the position of whose objects locked.
+class ExtraFormatToPositionObjs
+{
+ private:
+ SwSectionFrm* mpSectFrm;
+ bool mbExtraFormatPerformed;
+
+ public:
+ ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm)
+ : mpSectFrm( &_rSectFrm ),
+ mbExtraFormatPerformed( false )
+ {}
+
+ ~ExtraFormatToPositionObjs()
+ {
+ if ( mbExtraFormatPerformed )
+ {
+ // release keep locked position of lower floating screen objects
+ SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetKeepPosLocked( false );
+ }
+ }
+ }
+ }
+ }
+
+ // --> OD 2008-06-20 #i81555#
+ void InitObjs( SwFrm& rFrm )
+ {
+ SwSortedObjs* pObjs = rFrm.GetDrawObjs();
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->SetClearedEnvironment( false );
+ }
+ }
+ SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm);
+ if ( pLayoutFrm != 0 )
+ {
+ SwFrm* pLowerFrm = pLayoutFrm->GetLower();
+ while ( pLowerFrm != 0 )
+ {
+ InitObjs( *pLowerFrm );
+
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+ }
+ }
+ // <--
+
+ void FormatSectionToPositionObjs()
+ {
+ // perform extra format for multi-columned section.
+ if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() &&
+ mpSectFrm->Lower()->GetNext() )
+ {
+ // grow section till bottom of printing area of upper frame
+ SWRECTFN( mpSectFrm );
+ SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)();
+ Size aOldSectPrtSize( mpSectFrm->Prt().SSize() );
+ SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)(
+ (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 );
+ // --> OD 2006-05-08 #i59789#
+ // suppress formatting, if printing area of section is too narrow
+ if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 )
+ {
+ return;
+ }
+ // <--
+ mpSectFrm->ChgLowersProp( aOldSectPrtSize );
+
+ // format column frames and its body and footnote container
+ SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower());
+ while ( pColFrm )
+ {
+ pColFrm->Calc();
+ pColFrm->Lower()->Calc();
+ if ( pColFrm->Lower()->GetNext() )
+ {
+ pColFrm->Lower()->GetNext()->Calc();
+ }
+
+ pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext());
+ }
+
+ // unlock position of lower floating screen objects for the extra format
+ // --> OD 2008-06-20 #i81555#
+ // Section frame can already have changed the page and its content
+ // can still be on the former page.
+ // Thus, initialize objects via lower-relationship
+ InitObjs( *mpSectFrm );
+ // <--
+
+ // format content - first with collecting its foot-/endnotes before content
+ // format, second without collecting its foot-/endnotes.
+ ::CalcCntnt( mpSectFrm );
+ ::CalcCntnt( mpSectFrm, true );
+
+ // keep locked position of lower floating screen objects
+ SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetKeepPosLocked( true );
+ }
+ }
+ }
+
+ mbExtraFormatPerformed = true;
+ }
+ }
+};
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Format( const SwBorderAttrs *pAttr )
+{
+ if( !pSection ) // Durch DelEmpty
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" );
+#endif
+ bValidSize = bValidPos = bValidPrtArea = sal_True;
+ return;
+ }
+ SWRECTFN( this )
+ if ( !bValidPrtArea )
+ {
+ PROTOCOL( this, PROT_PRTAREA, 0, 0 )
+ bValidPrtArea = sal_True;
+ SwTwips nUpper = CalcUpperSpace();
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() );
+
+ if( nUpper != (this->*fnRect->fnGetTopMargin)() )
+ {
+ bValidSize = sal_False;
+ SwFrm* pOwn = ContainsAny();
+ if( pOwn )
+ pOwn->_InvalidatePos();
+ }
+ (this->*fnRect->fnSetYMargins)( nUpper, 0 );
+ }
+
+ if ( !bValidSize )
+ {
+ PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 )
+ const long nOldHeight = (Frm().*fnRect->fnGetHeight)();
+ sal_Bool bOldLock = IsColLocked();
+ ColLock();
+
+ bValidSize = sal_True;
+
+ //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm
+ //keinen Follow hat. Anderfalls fuellt er immer den Upper bis
+ //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein
+ //Inhalt selbst verantwortlich.
+ sal_Bool bMaximize = ToMaximize( sal_False );
+
+ // OD 2004-05-17 #i28701# - If the wrapping style has to be considered
+ // on object positioning, an extra formatting has to be performed
+ // to determine the correct positions the floating screen objects.
+ // --> OD 2005-01-11 #i40147#
+ // use new helper class <ExtraFormatToPositionObjs>.
+ // This class additionally keep the locked position of the objects
+ // and releases this position lock keeping on destruction.
+ ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this );
+ if ( !bMaximize &&
+ GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
+ !GetFmt()->GetBalancedColumns().GetValue() )
+ {
+ aExtraFormatToPosObjs.FormatSectionToPositionObjs();
+ }
+ // <--
+
+ // Column widths have to be adjusted before calling _CheckClipping.
+ // _CheckClipping can cause the formatting of the lower frames
+ // which still have a width of 0.
+ const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm();
+ if ( bHasColumns && Lower()->GetNext() )
+ AdjustColumns( 0, sal_False );
+
+ if( GetUpper() )
+ {
+ long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ (aFrm.*fnRect->fnSetWidth)( nWidth );
+
+ // #109700# LRSpace for sections
+ const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace();
+ (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() -
+ rLRSpace.GetRight() );
+
+ // OD 15.10.2002 #103517# - allow grow in online layout
+ // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling
+ // method <_CheckClipping(..)>.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize );
+ bMaximize = ToMaximize( sal_False );
+ bValidSize = sal_True;
+ }
+
+ //Breite der Spalten pruefen und ggf. einstellen.
+ if ( bHasColumns && ! Lower()->GetNext() && bMaximize )
+ ((SwColumnFrm*)Lower())->Lower()->Calc();
+
+ if ( !bMaximize )
+ {
+ SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)();
+ SwFrm *pFrm = pLower;
+ if( pFrm )
+ {
+ if( pFrm->IsColumnFrm() && pFrm->GetNext() )
+ {
+ // --> OD 2006-05-08 #i61435#
+ // suppress formatting, if upper frame has height <= 0
+ if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 )
+ {
+ FormatWidthCols( *pAttr, nRemaining, MINLAY );
+ }
+ // <--
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ while( HasFollow() && !GetFollow()->ContainsCntnt() &&
+ !GetFollow()->ContainsAny( true ) )
+ // <--
+ {
+ SwFrm* pOld = GetFollow();
+ GetFollow()->DelEmpty( sal_False );
+ if( pOld == GetFollow() )
+ break;
+ }
+ bMaximize = ToMaximize( sal_False );
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ }
+ else
+ {
+ if( pFrm->IsColumnFrm() )
+ {
+ pFrm->Calc();
+ pFrm = ((SwColumnFrm*)pFrm)->Lower();
+ pFrm->Calc();
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ CalcFtnCntnt();
+ }
+ // Wenn wir in einem spaltigen Rahmen stehen und dieser
+ // gerade im FormatWidthCols ein CalcCntnt ruft, muss
+ // unser Inhalt ggf. kalkuliert werden.
+ if( pFrm && !pFrm->IsValid() && IsInFly() &&
+ FindFlyFrm()->IsColLocked() )
+ ::CalcCntnt( this );
+ nRemaining += InnerHeight();
+ bMaximize = HasFollow();
+ }
+ }
+
+ SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if( nDiff < 0)
+ {
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ {
+ long nBottom = (Frm().*fnRect->fnGetBottom)();
+ nBottom = (*fnRect->fnYInc)( nBottom, -nDiff );
+ long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
+ if( nTmpDiff > 0 )
+ {
+ nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True );
+ nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff );
+ nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine );
+ if( nTmpDiff > 0 )
+ nDiff += nTmpDiff;
+ if( nDiff > 0 )
+ nDiff = 0;
+ }
+ }
+ }
+ if( nDiff )
+ {
+ long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)();
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ (Frm().*fnRect->fnAddBottom)( nTmp );
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ InvalidateNextPos();
+ if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) )
+ {
+ // Wenn ein einspaltiger Bereich gerade den Platz geschaffen
+ // hat, den sich die "undersized" Absaetze gewuenscht haben,
+ // muessen diese invalidiert und kalkuliert werden, damit
+ // sie diesen ausfuellen.
+ pFrm = pLower;
+ if( pFrm->IsColumnFrm() )
+ {
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePos();
+ pFrm->Calc();
+ pFrm = ((SwColumnFrm*)pFrm)->Lower();
+ pFrm->Calc();
+ pFrm = ((SwLayoutFrm*)pFrm)->Lower();
+ CalcFtnCntnt();
+ }
+ sal_Bool bUnderSz = sal_False;
+ while( pFrm )
+ {
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ {
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ bUnderSz = sal_True;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if( bUnderSz && !IsCntntLocked() )
+ ::CalcCntnt( this );
+ }
+ }
+ }
+
+ //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit
+ //Follows die Unterkante auch nicht unterschreiten.
+ if ( GetUpper() )
+ _CheckClipping( sal_True, bMaximize );
+ if( !bOldLock )
+ ColUnlock();
+ long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)();
+ if( nDiff > 0 )
+ {
+ if( !GetNext() )
+ SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen
+ if( GetUpper() && !GetUpper()->IsFooterFrm() )
+ GetUpper()->Shrink( nDiff );
+ }
+ if( IsUndersized() )
+ bValidPrtArea = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetNextSctLeaf()
+|*
+|* Beschreibung Liefert das naechste Layoutblatt in das der Frame
+|* gemoved werden kann.
+|* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage )
+{
+ //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt.
+
+ PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() )
+
+ // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind.
+ // Koennen wir in die naechste Spalte des Bereichs rutschen?
+ if( IsColBodyFrm() && GetUpper()->GetNext() )
+ return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower();
+ if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() )
+ return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower();
+ // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
+ // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen
+ if( GetUpper()->IsInTab() || FindFooterOrHeader() )
+ return 0;
+
+//MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im
+//FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein
+//GetLeaf gerufen wird.
+// SwSectionFrm *pSect = GetUpper()->FindSctFrm();
+ SwSectionFrm *pSect = FindSctFrm();
+ sal_Bool bWrongPage = sal_False;
+ OSL_ENSURE( pSect, "GetNextSctLeaf: Missing SectionFrm" );
+
+ // Hier eine Abkuerzung fuer Bereiche mit Follows,
+ // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten)
+ // dazwischen liegen.
+ // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger
+ if( pSect->HasFollow() && pSect->IsInDocBody() )
+ {
+ if( pSect->GetFollow() == pSect->GetNext() )
+ {
+ SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm();
+ if( WrongPageDesc( pPg ) )
+ bWrongPage = sal_True;
+ else
+ return FIRSTLEAF( pSect->GetFollow() );
+ }
+ else
+ {
+ SwFrm* pTmp;
+ if( !pSect->GetUpper()->IsColBodyFrm() ||
+ 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) )
+ pTmp = pSect->FindPageFrm()->GetNext();
+ if( pTmp ) // ist jetzt die naechste Spalte oder Seite
+ {
+ SwFrm* pTmpX = pTmp;
+ if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() )
+ pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen
+ SwFrm *pUp = pSect->GetFollow()->GetUpper();
+ // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte
+ // liegt, ansonsten die Seite:
+ if( !pUp->IsColBodyFrm() ||
+ !( pUp = pUp->GetUpper() )->GetPrev() )
+ pUp = pUp->FindPageFrm();
+ // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein,
+ // sonst liegen Seiten oder Spalten zwischen Master und Follow.
+ if( pUp == pTmp || pUp->GetNext() == pTmpX )
+ {
+ SwPageFrm* pNxtPg = pUp->IsPageFrm() ?
+ (SwPageFrm*)pUp : pUp->FindPageFrm();
+ if( WrongPageDesc( pNxtPg ) )
+ bWrongPage = sal_True;
+ else
+ return FIRSTLEAF( pSect->GetFollow() );
+ }
+ }
+ }
+ }
+
+ // Immer im gleichen Bereich landen: Body wieder in Body etc.
+ const sal_Bool bBody = IsInDocBody();
+ const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage();
+
+ SwLayoutFrm *pLayLeaf;
+ // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden
+ if( bWrongPage )
+ pLayLeaf = 0;
+ else if( IsTabFrm() )
+ {
+ SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt();
+ pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0;
+ }
+ else
+ {
+ pLayLeaf = GetNextLayoutLeaf();
+ if( IsColumnFrm() )
+ {
+ while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) )
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ }
+ }
+
+ SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
+ //nicht wieder vom Anfang gesucht
+ //wird.
+
+ while( sal_True )
+ {
+ if( pLayLeaf )
+ {
+ // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann,
+ // ob hier ein weiterer SectionFrm eingefuegt werden kann
+ // oder ob wir weitersuchen muessen.
+ SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm();
+ if ( !bFtnPage && pNxtPg->IsFtnPage() )
+ { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
+ pLayLeaf = 0;
+ continue;
+ }
+ // Einmal InBody, immer InBody, nicht in Tabellen hinein
+ // und nicht in fremde Bereiche hinein
+ if ( (bBody && !pLayLeaf->IsInDocBody()) ||
+ (IsInFtn() != pLayLeaf->IsInFtn() ) ||
+ pLayLeaf->IsInTab() ||
+ ( pLayLeaf->IsInSct() && ( !pSect->HasFollow()
+ || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) )
+ {
+ //Er will mich nicht; neuer Versuch, neues Glueck
+ pOldLayLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ continue;
+ }
+ if( WrongPageDesc( pNxtPg ) )
+ {
+ if( bWrongPage )
+ break; // there's a column between me and my right page
+ pLayLeaf = 0;
+ bWrongPage = sal_True;
+ pOldLayLeaf = 0;
+ continue;
+ }
+ }
+ //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
+ //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens
+ //neue Seiten nichts.
+ else if( !pSect->IsInFly() &&
+ ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
+ {
+ InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
+ sal_False );
+ //und nochmal das ganze
+ pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
+ continue;
+ }
+ break;
+ }
+
+ if( pLayLeaf )
+ {
+ // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen
+ // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt,
+ // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen
+ SwSectionFrm* pNew;
+
+ //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde
+ SwFrm* pFirst = pLayLeaf->Lower();
+ // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden
+ while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() )
+ pFirst = pFirst->GetNext();
+ if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst )
+ pNew = pSect->GetFollow();
+ else if( MAKEPAGE_NOSECTION == eMakePage )
+ return pLayLeaf;
+ else
+ {
+ pNew = new SwSectionFrm( *pSect, sal_False );
+ pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() );
+ pNew->Init();
+ SWRECTFN( pNew )
+ (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True );
+
+ // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
+ // umgehaengt werden hinter den neuen Follow der Bereichsframes.
+ SwFrm* pTmp = pSect->GetNext();
+ if( pTmp && pTmp != pSect->GetFollow() )
+ {
+ SwFlowFrm* pNxt;
+ SwCntntFrm* pNxtCntnt = NULL;
+ if( pTmp->IsCntntFrm() )
+ {
+ pNxt = (SwCntntFrm*)pTmp;
+ pNxtCntnt = (SwCntntFrm*)pTmp;
+ }
+ else
+ {
+ pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
+ if( pTmp->IsSctFrm() )
+ pNxt = (SwSectionFrm*)pTmp;
+ else
+ {
+ OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
+ pNxt = (SwTabFrm*)pTmp;
+ }
+ while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) )
+ {
+ if( pTmp->IsCntntFrm() )
+ pNxtCntnt = (SwCntntFrm*)pTmp;
+ else
+ pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt();
+ }
+ }
+ if( pNxtCntnt )
+ {
+ SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True );
+ if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) )
+ {
+ SwSaveFtnHeight aHeight( pOldBoss,
+ pOldBoss->Frm().Top() + pOldBoss->Frm().Height() );
+ pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss,
+ pLayLeaf->FindFtnBossFrm( sal_True ), sal_False );
+ }
+ }
+ ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() );
+ }
+ if( pNew->GetFollow() )
+ pNew->SimpleFormat();
+ }
+ // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms:
+ pLayLeaf = FIRSTLEAF( pNew );
+ }
+ return pLayLeaf;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPrevSctLeaf()
+|*
+|* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
+|* Frame gemoved werden kann.
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType )
+{
+ PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() )
+
+ SwLayoutFrm* pCol;
+ // ColumnFrm beinhalten jetzt stets einen BodyFrm
+ if( IsColBodyFrm() )
+ pCol = GetUpper();
+ else if( GetUpper()->IsColBodyFrm() )
+ pCol = GetUpper()->GetUpper();
+ else
+ pCol = NULL;
+ sal_Bool bJump = sal_False;
+ if( pCol )
+ {
+ if( pCol->GetPrev() )
+ {
+ do
+ {
+ pCol = (SwLayoutFrm*)pCol->GetPrev();
+ // Gibt es dort Inhalt?
+ if( ((SwLayoutFrm*)pCol->Lower())->Lower() )
+ {
+ if( bJump ) // Haben wir eine leere Spalte uebersprungen?
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ return (SwLayoutFrm*)pCol->Lower(); // Der Spaltenbody
+ }
+ bJump = sal_True;
+ } while( pCol->GetPrev() );
+
+ // Hier landen wir, wenn alle Spalten leer sind,
+ // pCol ist jetzt die erste Spalte, wir brauchen aber den Body:
+ pCol = (SwLayoutFrm*)pCol->Lower();
+ }
+ else
+ pCol = NULL;
+ }
+
+ if( bJump ) // Haben wir eine leere Spalte uebersprungen?
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+
+ // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann
+ // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette
+ // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat.
+ // Jetzt ziehen wir sogar eine leere Spalte in Betracht...
+ OSL_ENSURE( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" );
+ if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() )
+ return pCol;
+
+ // === IMPORTANT ===
+ // Precondition, which needs to be hold, is that the <this> frame can be
+ // inside a table, but then the found section frame <pSect> is also inside
+ // this table.
+ SwSectionFrm *pSect = FindSctFrm();
+
+ // --> OD 2009-01-16 #i95698#
+ // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..)
+ // Thus, a table inside a section, which is inside another table can only
+ // flow backward in the columns of its section.
+ // Note: The table cell, which contains the section, can not have a master table cell.
+ if ( IsTabFrm() && pSect->IsInTab() )
+ {
+ return pCol;
+ }
+ // <--
+
+ {
+ SwFrm *pPrv;
+ if( 0 != ( pPrv = pSect->GetIndPrev() ) )
+ {
+ // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren
+ while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() )
+ pPrv = pPrv->GetPrev();
+ if( pPrv )
+ return pCol;
+ }
+ }
+
+ const sal_Bool bBody = IsInDocBody();
+ const sal_Bool bFly = IsInFly();
+
+ SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
+ SwLayoutFrm *pPrevLeaf = 0;
+
+ while ( pLayLeaf )
+ {
+ //In Tabellen oder Bereiche geht's niemals hinein.
+ if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() )
+ {
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ else if ( bBody && pLayLeaf->IsInDocBody() )
+ {
+ // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for.
+ // Exception: pLayLeaf->Lower() is a zombie section frame
+ const SwFrm* pTmp = pLayLeaf->Lower();
+ // OD 11.04.2003 #108824# - consider, that the zombie section frame
+ // can have frame below it in the found layout leaf.
+ // Thus, skipping zombie section frame, if possible.
+ while ( pTmp && pTmp->IsSctFrm() &&
+ !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) &&
+ pTmp->GetNext()
+ )
+ {
+ pTmp = pTmp->GetNext();
+ }
+ if ( pTmp &&
+ ( !pTmp->IsSctFrm() ||
+ ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() )
+ )
+ )
+ {
+ break;
+ }
+ pPrevLeaf = pLayLeaf;
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ if ( pLayLeaf )
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ else if ( bFly )
+ break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum?
+ else
+ pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
+ }
+ if( !pLayLeaf )
+ {
+ if( !pPrevLeaf )
+ return pCol;
+ pLayLeaf = pPrevLeaf;
+ }
+
+ SwSectionFrm* pNew = NULL;
+ // Zunaechst einmal an das Ende des Layoutblatts gehen
+ SwFrm *pTmp = pLayLeaf->Lower();
+ if( pTmp )
+ {
+ while( pTmp->GetNext() )
+ pTmp = pTmp->GetNext();
+ if( pTmp->IsSctFrm() )
+ {
+ // Halbtote stoeren hier nur...
+ while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() &&
+ pTmp->GetPrev()->IsSctFrm() )
+ pTmp = pTmp->GetPrev();
+ if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect )
+ pNew = (SwSectionFrm*)pTmp;
+ }
+ }
+ if( !pNew )
+ {
+ pNew = new SwSectionFrm( *pSect, sal_True );
+ pNew->InsertBefore( pLayLeaf, NULL );
+ pNew->Init();
+ SWRECTFN( pNew )
+ (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True );
+
+ pLayLeaf = FIRSTLEAF( pNew );
+ if( !pNew->Lower() ) // einspaltige Bereiche formatieren
+ {
+ pNew->MakePos();
+ pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt
+ }
+ else
+ pNew->SimpleFormat();
+ }
+ else
+ {
+ pLayLeaf = FIRSTLEAF( pNew );
+ if( pLayLeaf->IsColBodyFrm() )
+ {
+ // In existent section columns we're looking for the last not empty
+ // column.
+ SwLayoutFrm *pTmpLay = pLayLeaf;
+ while( pLayLeaf->GetUpper()->GetNext() )
+ {
+ pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower();
+ if( pLayLeaf->Lower() )
+ pTmpLay = pLayLeaf;
+ }
+ // If we skipped an empty column, we've to set the jump-flag
+ if( pLayLeaf != pTmpLay )
+ {
+ pLayLeaf = pTmpLay;
+ SwFlowFrm::SetMoveBwdJump( sal_True );
+ }
+ }
+ }
+ return pLayLeaf;
+}
+
+SwTwips lcl_DeadLine( const SwFrm* pFrm )
+{
+ const SwLayoutFrm* pUp = pFrm->GetUpper();
+ while( pUp && pUp->IsInSct() )
+ {
+ if( pUp->IsSctFrm() )
+ pUp = pUp->GetUpper();
+ // Spalten jetzt mit BodyFrm
+ else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() )
+ pUp = pUp->GetUpper()->GetUpper();
+ else
+ break;
+ }
+ SWRECTFN( pFrm )
+ return pUp ? (pUp->*fnRect->fnGetPrtBottom)() :
+ (pFrm->Frm().*fnRect->fnGetBottom)();
+}
+
+// SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann,
+// ggf. muss die Umgebung gefragt werden
+
+sal_Bool SwSectionFrm::Growable() const
+{
+ SWRECTFN( this )
+ if( (*fnRect->fnYDiff)( lcl_DeadLine( this ),
+ (Frm().*fnRect->fnGetBottom)() ) > 0 )
+ return sal_True;
+
+ return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) );
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::_Grow(), _Shrink()
+|*
+|*************************************************************************/
+
+SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst )
+{
+ if ( !IsColLocked() && !HasFixSize() )
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ if ( nDist <= 0L )
+ return 0L;
+
+ sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked();
+ // OD 2004-03-15 #116561# - allow grow in online layout
+ sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() ||
+ GetSection()->GetFmt()->GetBalancedColumns().GetValue();
+ if( !bGrow )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ bGrow = pSh && pSh->GetViewOptions()->getBrowseMode();
+ }
+ if( bGrow )
+ {
+ SwTwips nGrow;
+ if( IsInFtn() )
+ nGrow = 0;
+ else
+ {
+ nGrow = lcl_DeadLine( this );
+ nGrow = (*fnRect->fnYDiff)( nGrow,
+ (Frm().*fnRect->fnGetBottom)() );
+ }
+ SwTwips nSpace = nGrow;
+ if( !bInCalcCntnt && nGrow < nDist && GetUpper() )
+ nGrow += GetUpper()->Grow( LONG_MAX, sal_True );
+
+ if( nGrow > nDist )
+ nGrow = nDist;
+ if( nGrow <= 0 )
+ {
+ nGrow = 0;
+ if( nDist && !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else
+ InvalidateSize();
+ }
+ }
+ else if( !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else if( nSpace < nGrow && nDist != nSpace + GetUpper()->
+ Grow( nGrow - nSpace, sal_False ) )
+ InvalidateSize();
+ else
+ {
+ const SvxGraphicPosition ePos =
+ GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_RT < ePos && GPOS_TILED != ePos )
+ {
+ SetCompletePaint();
+ InvalidatePage();
+ }
+ if( GetUpper() && GetUpper()->IsHeaderFrm() )
+ GetUpper()->InvalidateSize();
+ }
+ (Frm().*fnRect->fnAddBottom)( nGrow );
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow;
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight );
+
+ if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ SwFrm* pTmp = Lower();
+ do
+ {
+ pTmp->_InvalidateSize();
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ _InvalidateSize();
+ }
+ if( GetNext() )
+ {
+ SwFrm *pFrm = GetNext();
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ {
+ if( bInCalcCntnt )
+ pFrm->_InvalidatePos();
+ else
+ pFrm->InvalidatePos();
+ }
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning
+ // the frame on the next page/column can flow backward (e.g. it
+ // was moved forward due to the positioning of its objects ).
+ // Thus, invalivate this next frame, if document compatibility
+ // option 'Consider wrapping style influence on object positioning' is ON.
+ else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ }
+ return nGrow;
+ }
+ if ( !bTst )
+ {
+ if( bInCalcCntnt )
+ _InvalidateSize();
+ else
+ InvalidateSize();
+ }
+ }
+ return 0L;
+}
+
+SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst )
+{
+ if ( Lower() && !IsColLocked() && !HasFixSize() )
+ {
+ if( ToMaximize( sal_False ) )
+ {
+ if( !bTst )
+ InvalidateSize();
+ }
+ else
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nFrmHeight )
+ nDist = nFrmHeight;
+
+ if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd
+ !GetSection()->GetFmt()->GetBalancedColumns().GetValue() )
+ { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber
+ //das Wachstum (wg. des Ausgleichs).
+ if ( !bTst )
+ InvalidateSize();
+ return nDist;
+ }
+ else if( !bTst )
+ {
+ const SvxGraphicPosition ePos =
+ GetAttrSet()->GetBackground().GetGraphicPos();
+ if ( GPOS_RT < ePos && GPOS_TILED != ePos )
+ {
+ SetCompletePaint();
+ InvalidatePage();
+ }
+ (Frm().*fnRect->fnAddBottom)( -nDist );
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist;
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight );
+
+ // We do not allow a section frame to shrink the its upper
+ // footer frame. This is because in the calculation of a
+ // footer frame, the content of the section frame is _not_
+ // calculated. If there is a fly frame overlapping with the
+ // footer frame, the section frame is not affected by this
+ // during the calculation of the footer frame size.
+ // The footer frame does not grow in its FormatSize function
+ // but during the calculation of the content of the section
+ // frame. The section frame grows until some of its text is
+ // located on top of the fly frame. The next call of CalcCntnt
+ // tries to shrink the section and here it would also shrink
+ // the footer. This may not happen, because shrinking the footer
+ // would cause the top of the section frame to overlap with the
+ // fly frame again, this would result in a perfect loop.
+ if( GetUpper() && !GetUpper()->IsFooterFrm() )
+ GetUpper()->Shrink( nDist, bTst );
+
+ if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ SwFrm* pTmp = Lower();
+ do
+ {
+ pTmp->_InvalidateSize();
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ }
+ if( GetNext() )
+ {
+ SwFrm* pFrm = GetNext();
+ while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() )
+ pFrm = pFrm->GetNext();
+ if( pFrm )
+ pFrm->InvalidatePos();
+ else
+ SetRetouche();
+ }
+ else
+ SetRetouche();
+ return nDist;
+ }
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::MoveAllowed()
+|*
+|* Wann sind Frms innerhalb eines SectionFrms moveable?
+|* Wenn sie noch nicht in der letzten Spalte des SectionFrms sind,
+|* wenn es einen Follow gibt,
+|* wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter,
+|* dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt
+|* finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout
+|* geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody
+|* und auch im Fussnoten dagegen immer.
+|*
+|* Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein
+|* (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss.
+|*
+|*************************************************************************/
+
+sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const
+{
+ // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte?
+ if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() &&
+ pFrm->GetUpper()->GetUpper()->GetNext() ) )
+ return sal_True;
+ if( pFrm->IsInFtn() )
+ {
+ if( IsInFtn() )
+ {
+ if( GetUpper()->IsInSct() )
+ {
+ if( Growable() )
+ return sal_False;
+ return GetUpper()->FindSctFrm()->MoveAllowed( this );
+ }
+ else
+ return sal_True;
+ }
+ // The content of footnote inside a columned sectionfrm is moveable
+ // except in the last column
+ const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper();
+ if( pLay->IsColumnFrm() && pLay->GetNext() )
+ {
+ // The first paragraph in the first footnote in the first column
+ // in the sectionfrm at the top of the page is not moveable,
+ // if the columnbody is empty.
+ sal_Bool bRet = sal_False;
+ if( pLay->GetIndPrev() || pFrm->GetIndPrev() ||
+ pFrm->FindFtnFrm()->GetPrev() )
+ bRet = sal_True;
+ else
+ {
+ SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont();
+ if( pBody && pBody->Lower() )
+ bRet = sal_True;
+ }
+ if( bRet && ( IsFtnAtEnd() || !Growable() ) )
+ return sal_True;
+ }
+ }
+ // Oder kann der Bereich noch wachsen?
+ if( !IsColLocked() && Growable() )
+ return sal_False;
+ // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem
+ // ein Bereichsfollow erzeugt werden kann.
+ if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) )
+ return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht
+ if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen
+ return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE );
+ return sal_True;
+}
+
+/** Called for a frame inside a section with no direct previous frame (or only
+ previous empty section frames) the previous frame of the outer section is
+ returned, if the frame is the first flowing content of this section.
+
+ Note: For a frame inside a table frame, which is inside a section frame,
+ NULL is returned.
+*/
+SwFrm* SwFrm::_GetIndPrev() const
+{
+ SwFrm *pRet = NULL;
+ // --> OD 2007-09-04 #i79774#, #b659654#
+ // Do not assert, if the frame has a direct previous frame, because it
+ // could be an empty section frame. The caller has to assure, that the
+ // frame has no direct previous frame or only empty section frames as
+ // previous frames.
+ OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" );
+ // <--
+ const SwFrm* pSct = GetUpper();
+ if( !pSct )
+ return NULL;
+ if( pSct->IsSctFrm() )
+ pRet = pSct->GetIndPrev();
+ else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ {
+ // Do not return the previous frame of the outer section, if in one
+ // of the previous columns is content.
+ const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev();
+ while( pCol )
+ {
+ OSL_ENSURE( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" );
+ OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
+ "GetIndPrev(): Where's the body?");
+ if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
+ return NULL;
+ pCol = pCol->GetPrev();
+ }
+ pRet = pSct->GetIndPrev();
+ }
+
+ // skip empty section frames
+ while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() )
+ pRet = pRet->GetIndPrev();
+ return pRet;
+}
+
+SwFrm* SwFrm::_GetIndNext()
+{
+ OSL_ENSURE( !pNext && IsInSct(), "Why?" );
+ SwFrm* pSct = GetUpper();
+ if( !pSct )
+ return NULL;
+ if( pSct->IsSctFrm() )
+ return pSct->GetIndNext();
+ if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ { // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern,
+ // wenn in keiner folgenden Spalte mehr Inhalt ist
+ SwFrm* pCol = GetUpper()->GetUpper()->GetNext();
+ while( pCol )
+ {
+ OSL_ENSURE( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" );
+ OSL_ENSURE( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(),
+ "GetIndNext(): Where's the body?");
+ if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() )
+ return NULL;
+ pCol = pCol->GetNext();
+ }
+ return pSct->GetIndNext();
+ }
+ return NULL;
+}
+
+sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const
+{
+ if( !pSection || !pFmt )
+ return sal_False;
+ const SwSectionFmt *pMyFmt = pSection->GetFmt();
+ while( pFmt != pMyFmt )
+ {
+ if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn();
+ else
+ return sal_False;
+ }
+ return sal_True;
+}
+
+void SwSectionFrm::CalcFtnAtEndFlag()
+{
+ SwSectionFmt *pFmt = GetSection()->GetFmt();
+ sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
+ bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal;
+ bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
+ while( !bFtnAtEnd && !bOwnFtnNum )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ break;
+ nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue();
+ if( FTNEND_ATPGORDOCEND != nVal )
+ {
+ bFtnAtEnd = sal_True;
+ bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal ||
+ FTNEND_ATTXTEND_OWNNUMANDFMT == nVal;
+ }
+ }
+}
+
+sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const
+{
+ return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+}
+
+void SwSectionFrm::CalcEndAtEndFlag()
+{
+ SwSectionFmt *pFmt = GetSection()->GetFmt();
+ bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+ while( !bEndnAtEnd )
+ {
+ if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) )
+ pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn();
+ else
+ break;
+ bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwSectionFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ if ( nInvFlags & 0x01 )
+ InvalidateSize();
+ if ( nInvFlags & 0x10 )
+ SetCompletePaint();
+ }
+}
+
+void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
+{
+ const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+ if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() )
+ {
+ SwSectionFrm::MoveCntntAndDelete( this, sal_True );
+ }
+}
+
+void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ { // Mehrspaltigkeit in Fussnoten unterdruecken...
+ case RES_FMT_CHG:
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ if( !IsInFtn() )
+ {
+ //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns
+ //nicht auf das alte Spaltenattribut verlassen. Da diese
+ //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen,
+ //bleibt uns nur einen temporaeres Attribut zu basteln.
+ SwFmtCol aCol;
+ if ( Lower() && Lower()->IsColumnFrm() )
+ {
+ sal_uInt16 nCol = 0;
+ SwFrm *pTmp = Lower();
+ do
+ { ++nCol;
+ pTmp = pTmp->GetNext();
+ } while ( pTmp );
+ aCol.Init( nCol, 0, 1000 );
+ }
+ sal_Bool bChgFtn = IsFtnAtEnd();
+ sal_Bool bChgEndn = IsEndnAtEnd();
+ sal_Bool bChgMyEndn = IsEndnoteAtMyEnd();
+ CalcFtnAtEndFlag();
+ CalcEndAtEndFlag();
+ bChgFtn = ( bChgFtn != IsFtnAtEnd() ) ||
+ ( bChgEndn != IsEndnAtEnd() ) ||
+ ( bChgMyEndn != IsEndnoteAtMyEnd() );
+ ChgColumns( aCol, rNewCol, bChgFtn );
+ rInvFlags |= 0x10;
+ }
+ rInvFlags |= 0x01;
+ bClear = sal_False;
+ }
+ break;
+
+ case RES_COL:
+ if( !IsInFtn() )
+ {
+ ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
+ rInvFlags |= 0x11;
+ }
+ break;
+
+ case RES_FTN_AT_TXTEND:
+ if( !IsInFtn() )
+ {
+ sal_Bool bOld = IsFtnAtEnd();
+ CalcFtnAtEndFlag();
+ if( bOld != IsFtnAtEnd() )
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ ChgColumns( rNewCol, rNewCol, sal_True );
+ rInvFlags |= 0x01;
+ }
+ }
+ break;
+
+ case RES_END_AT_TXTEND:
+ if( !IsInFtn() )
+ {
+ sal_Bool bOld = IsEndnAtEnd();
+ sal_Bool bMyOld = IsEndnoteAtMyEnd();
+ CalcEndAtEndFlag();
+ if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd())
+ {
+ const SwFmtCol& rNewCol = GetFmt()->GetCol();
+ ChgColumns( rNewCol, rNewCol, sal_True );
+ rInvFlags |= 0x01;
+ }
+ }
+ break;
+ case RES_COLUMNBALANCE:
+ rInvFlags |= 0x01;
+ break;
+
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+
+ case RES_PROTECT:
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+ break;
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*--------------------------------------------------
+ * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the
+ * page causes a maximal Size of the sectionframe.
+ * --------------------------------------------------*/
+
+sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const
+{
+ if( HasFollow() )
+ {
+ if( !bCheckFollow ) // Don't check superfluous follows
+ return sal_True;
+ const SwSectionFrm* pFoll = GetFollow();
+ while( pFoll && pFoll->IsSuperfluous() )
+ pFoll = pFoll->GetFollow();
+ if( pFoll )
+ return sal_True;
+ }
+ if( IsFtnAtEnd() )
+ return sal_False;
+ const SwFtnContFrm* pCont = ContainsFtnCont();
+ if( !IsEndnAtEnd() )
+ return 0 != pCont;
+ sal_Bool bRet = sal_False;
+ while( pCont && !bRet )
+ {
+ if( pCont->FindFootNote() )
+ bRet = sal_True;
+ else
+ pCont = ContainsFtnCont( pCont );
+ }
+ return bRet;
+}
+
+/*--------------------------------------------------
+ * sal_Bool SwSectionFrm::ContainsFtnCont()
+ * checks every Column for FtnContFrms.
+ * --------------------------------------------------*/
+
+SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const
+{
+ SwFtnContFrm* pRet = NULL;
+ const SwLayoutFrm* pLay;
+ if( pCont )
+ {
+ pLay = pCont->FindFtnBossFrm( 0 );
+ OSL_ENSURE( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" );
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ }
+ else if( Lower() && Lower()->IsColumnFrm() )
+ pLay = (SwLayoutFrm*)Lower();
+ else
+ pLay = NULL;
+ while ( !pRet && pLay )
+ {
+ if( pLay->Lower() && pLay->Lower()->GetNext() )
+ {
+ OSL_ENSURE( pLay->Lower()->GetNext()->IsFtnContFrm(),
+ "ToMaximize: Unexspected Frame" );
+ pRet = (SwFtnContFrm*)pLay->Lower()->GetNext();
+ }
+ OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(),
+ "ToMaximize: ColFrm exspected" );
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ }
+ return pRet;
+}
+
+void SwSectionFrm::InvalidateFtnPos()
+{
+ SwFtnContFrm* pCont = ContainsFtnCont( NULL );
+ if( pCont )
+ {
+ SwFrm *pTmp = pCont->ContainsCntnt();
+ if( pTmp )
+ pTmp->_InvalidatePos();
+ }
+}
+
+/*--------------------------------------------------
+ * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern
+ * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null.
+ * Das Undersized-Flag wird ggf. korrigiert.
+ * --------------------------------------------------*/
+
+long SwSectionFrm::Undersize( sal_Bool bOverSize )
+{
+ bUndersized = sal_False;
+ SWRECTFN( this )
+ long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)();
+ if( nRet > 0 )
+ bUndersized = sal_True;
+ else if( !bOverSize )
+ nRet = 0;
+ return nRet;
+}
+
+/// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting
+/// before format of current one, because current one can move backward.
+/// After moving backward to a previous page method <FindNext()> will return
+/// the text frame presenting the first page footnote, if it exists. Thus, the
+/// rest of the footnote/endnote container would not be formatted.
+void SwSectionFrm::CalcFtnCntnt()
+{
+ SwFtnContFrm* pCont = ContainsFtnCont();
+ if( pCont )
+ {
+ SwFrm* pFrm = pCont->ContainsAny();
+ if( pFrm )
+ pCont->Calc();
+ while( pFrm && IsAnLower( pFrm ) )
+ {
+ SwFtnFrm* pFtn = pFrm->FindFtnFrm();
+ if( pFtn )
+ pFtn->Calc();
+ // OD 01.04.2003 #108446# - determine next frame before format current frame.
+ SwFrm* pNextFrm = 0;
+ {
+ if( pFrm->IsSctFrm() )
+ {
+ pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny();
+ }
+ if( !pNextFrm )
+ {
+ pNextFrm = pFrm->FindNext();
+ }
+ }
+ pFrm->Calc();
+ pFrm = pNextFrm;
+ }
+ }
+}
+
+/* --------------------------------------------------
+ * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt,
+ * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer
+ * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter
+ * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und
+ * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms
+ * muessen vom Layout/beim Formatieren ignoriert werden.
+ *
+ * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf,
+ * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor),
+ * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert
+ * --------------------------------------------------*/
+
+void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel )
+{
+ if( !pDestroy )
+ pDestroy = new SwDestroyList;
+ sal_uInt16 nPos;
+ if( !pDestroy->Seek_Entry( pDel, &nPos ) )
+ pDestroy->Insert( pDel );
+}
+
+void SwRootFrm::_DeleteEmptySct()
+{
+ OSL_ENSURE( pDestroy, "Keine Liste, keine Kekse" );
+ while( pDestroy->Count() )
+ {
+ SwSectionFrm* pSect = (*pDestroy)[0];
+ pDestroy->Remove( sal_uInt16(0) );
+ OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),
+ "DeleteEmptySct: Locked SectionFrm" );
+ if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() )
+ {
+ SwLayoutFrm* pUp = pSect->GetUpper();
+ pSect->Remove();
+ delete pSect;
+ if( pUp && !pUp->Lower() )
+ {
+ if( pUp->IsPageBodyFrm() )
+ pUp->getRootFrm()->SetSuperfluous();
+ else if( pUp->IsFtnFrm() && !pUp->IsColLocked() &&
+ pUp->GetUpper() )
+ {
+ pUp->Cut();
+ delete pUp;
+ }
+ }
+ }
+ else {
+ OSL_ENSURE( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" );
+ }
+ }
+}
+
+void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct )
+{
+ OSL_ENSURE( pDestroy, "Where's my list?" );
+ sal_uInt16 nPos;
+ if( pDestroy->Seek_Entry( pSct, &nPos ) )
+ pDestroy->Remove( nPos );
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const
+{
+ sal_uInt16 nPos;
+ return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) );
+}
+
+#endif
+
+bool SwSectionFrm::IsBalancedSection() const
+{
+ bool bRet = false;
+ if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() )
+ {
+ bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue();
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/softpagebreak.cxx b/sw/source/core/layout/softpagebreak.cxx
new file mode 100644
index 000000000000..c27bd3753637
--- /dev/null
+++ b/sw/source/core/layout/softpagebreak.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "ndtxt.hxx"
+#include "txtfrm.hxx"
+#include "pagefrm.hxx"
+#include "swtable.hxx"
+#include "frmfmt.hxx"
+#include "rowfrm.hxx"
+#include "tabfrm.hxx"
+#include "switerator.hxx"
+
+void SwTxtNode::fillSoftPageBreakList( SwSoftPageBreakList& rBreak ) const
+{
+ SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
+ for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // No soft page break in header or footer
+ if( pFrm->FindFooterOrHeader() || pFrm->IsInFly() )
+ return;
+ // No soft page break if I'm not the first frame in my layout frame
+ if( pFrm->GetIndPrev() )
+ continue;
+ const SwPageFrm* pPage = pFrm->FindPageFrm();
+ // No soft page break at the first page
+ if( pPage && pPage->GetPrev() )
+ {
+ const SwCntntFrm* pFirst2 = pPage->FindFirstBodyCntnt();
+ // Special handling for content frame in table frames
+ if( pFrm->IsInTab() )
+ {
+ // No soft page break if I'm in a table but the first content frame
+ // at my page is not in a table
+ if( !pFirst2->IsInTab() )
+ continue;
+ const SwLayoutFrm *pRow = pFrm->GetUpper();
+ // Looking for the "most upper" row frame,
+ // skipping sub tables and/or table in table
+ while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ||
+ pRow->GetUpper()->GetUpper()->IsInTab() )
+ pRow = pRow->GetUpper();
+ const SwTabFrm *pTab = pRow->FindTabFrm();
+ // For master tables the soft page break will exported at the table row,
+ // not at the content frame.
+ // If the first content is outside my table frame, no soft page break.
+ if( !pTab->IsFollow() || !pTab->IsAnLower( pFirst2 ) )
+ continue;
+ // Only content of non-heading-rows can get a soft page break
+ const SwFrm* pFirstRow = pTab->GetFirstNonHeadlineRow();
+ // If there's no follow flow line, the soft page break will be
+ // exported at the row, not at the content.
+ if( pRow == pFirstRow &&
+ pTab->FindMaster( false )->HasFollowFlowLine() )
+ {
+ // Now we have the row which causes a new page,
+ // this row is a follow flow line and therefor cannot get
+ // the soft page break itself.
+ // Every first content frame of every cell frane in this row
+ // will get the soft page break
+ const SwFrm* pCell = pRow->Lower();
+ while( pCell )
+ {
+ pFirst2 = static_cast<const SwLayoutFrm*>(pCell)->ContainsCntnt();
+ if( pFirst2 == pFrm )
+ { // Here we are: a first content inside a cell
+ // inside the splitted row => soft page break
+ rBreak.insert( pFrm->GetOfst() );
+ break;
+ }
+ pCell = pCell->GetNext();
+ }
+ }
+ }
+ else // No soft page break if there's a "hard" page break attribute
+ if( pFirst2 == pFrm && !pFrm->IsPageBreak( sal_True ) )
+ rBreak.insert( pFrm->GetOfst() );
+ }
+ }
+}
+
+bool SwTableLine::hasSoftPageBreak() const
+{
+ // No soft page break for sub tables
+ if( GetUpper() || !GetFrmFmt() )
+ return false;
+ SwIterator<SwRowFrm,SwFmt> aIter( *GetFrmFmt() );
+ for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pLast->GetTabLine() == this )
+ {
+ const SwTabFrm* pTab = pLast->FindTabFrm();
+ // No soft page break for
+ // tables with prevs, i.e. if the frame is not the first in its layout frame
+ // tables in footer or header
+ // tables in flies
+ // inner tables of nested tables
+ // master table frames with "hard" page break attribute
+ if( pTab->GetIndPrev() || pTab->FindFooterOrHeader()
+ || pTab->IsInFly() || pTab->GetUpper()->IsInTab() ||
+ ( !pTab->IsFollow() && pTab->IsPageBreak( sal_True ) ) )
+ return false;
+ const SwPageFrm* pPage = pTab->FindPageFrm();
+ // No soft page break at the first page of the document
+ if( pPage && !pPage->GetPrev() )
+ return false;
+ const SwCntntFrm* pFirst = pPage->FindFirstBodyCntnt();
+ // No soft page break for
+ // tables which does not contain the first body content of the page
+ if( !pFirst || !pTab->IsAnLower( pFirst->FindTabFrm() ) )
+ return false;
+ // The row which could get a soft page break must be either the first
+ // row of a master table frame or the first "non-headline-row" of a
+ // follow table frame...
+ const SwFrm* pRow = pTab->IsFollow() ?
+ pTab->GetFirstNonHeadlineRow() : pTab->Lower();
+ if( pRow == pLast )
+ {
+ // The last check: no soft page break for "follow" table lines
+ if( pTab->IsFollow() && pTab->FindMaster( false )->HasFollowFlowLine() )
+ return false;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sortedobjs.cxx b/sw/source/core/layout/sortedobjs.cxx
new file mode 100644
index 000000000000..e984d278f4e7
--- /dev/null
+++ b/sw/source/core/layout/sortedobjs.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <sortedobjs.hxx>
+#include <sortedobjsimpl.hxx>
+
+SwSortedObjs::SwSortedObjs()
+ : mpImpl( new SwSortedObjsImpl )
+{
+}
+
+SwSortedObjs::~SwSortedObjs()
+{
+ delete mpImpl;
+}
+
+sal_uInt32 SwSortedObjs::Count() const
+{
+ return mpImpl->Count();
+}
+
+SwAnchoredObject* SwSortedObjs::operator[]( sal_uInt32 _nIndex ) const
+{
+ return (*mpImpl)[ _nIndex ];
+}
+
+bool SwSortedObjs::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Insert( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Remove( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Remove( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Contains( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ return mpImpl->Contains( _rAnchoredObj );
+}
+
+bool SwSortedObjs::Update( SwAnchoredObject& _rAnchoredObj )
+{
+ return mpImpl->Update( _rAnchoredObj );
+}
+
+sal_uInt32 SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ return mpImpl->ListPosOf( _rAnchoredObj );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/sortedobjsimpl.cxx b/sw/source/core/layout/sortedobjsimpl.cxx
new file mode 100644
index 000000000000..dc81c71f0355
--- /dev/null
+++ b/sw/source/core/layout/sortedobjsimpl.cxx
@@ -0,0 +1,312 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <sortedobjsimpl.hxx>
+
+#include <algorithm>
+#include <anchoredobject.hxx>
+#include <frmfmt.hxx>
+#include <svx/svdobj.hxx>
+#include <pam.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
+#include <IDocumentDrawModelAccess.hxx>
+
+
+using namespace ::com::sun::star;
+
+typedef std::vector< SwAnchoredObject* >::iterator tIter;
+typedef std::vector< SwAnchoredObject* >::const_iterator tConstIter;
+
+
+SwSortedObjsImpl::SwSortedObjsImpl()
+{
+}
+
+SwSortedObjsImpl::~SwSortedObjsImpl()
+{
+}
+
+sal_uInt32 SwSortedObjsImpl::Count() const
+{
+ return maSortedObjLst.size();
+}
+
+SwAnchoredObject* SwSortedObjsImpl::operator[]( sal_uInt32 _nIndex )
+{
+ SwAnchoredObject* pAnchoredObj = 0L;
+
+ if ( _nIndex >= Count() )
+ {
+ OSL_FAIL( "<SwSortedObjsImpl::operator[]> - index out of range" );
+ }
+ else
+ {
+ pAnchoredObj = maSortedObjLst[ _nIndex ];
+ }
+
+ return pAnchoredObj;
+}
+
+struct ObjAnchorOrder
+{
+ bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
+ const SwAnchoredObject* _pNewAnchoredObj )
+ {
+ // get attributes of listed object
+ const SwFrmFmt& rFmtListed = _pListedAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor* pAnchorListed = &(rFmtListed.GetAnchor());
+
+ // get attributes of new object
+ const SwFrmFmt& rFmtNew = _pNewAnchoredObj->GetFrmFmt();
+ const SwFmtAnchor* pAnchorNew = &(rFmtNew.GetAnchor());
+
+ // check for to-page anchored objects
+ if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_PAGE))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() != FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_PAGE))
+ {
+ return false;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_PAGE) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_PAGE))
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // Both objects aren't anchored to page.
+ // Thus, check for to-fly anchored objects
+ if ((pAnchorListed->GetAnchorId() == FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_FLY))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() != FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_FLY))
+ {
+ return false;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_FLY) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_FLY))
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // Both objects aren't anchor to page or to fly
+ // Thus, compare content anchor nodes, if existing.
+ const SwPosition* pCntntAnchorListed = pAnchorListed->GetCntntAnchor();
+ const SwPosition* pCntntAnchorNew = pAnchorNew->GetCntntAnchor();
+ if ( pCntntAnchorListed && pCntntAnchorNew &&
+ pCntntAnchorListed->nNode != pCntntAnchorNew->nNode )
+ {
+ return pCntntAnchorListed->nNode < pCntntAnchorNew->nNode;
+ }
+
+ // objects anchored at the same content.
+ // --> OD 2006-11-29 #???# - objects have to be ordered by anchor node position
+ // Thus, compare content anchor node positions and anchor type,
+ // if not anchored at-paragraph
+ if ((pAnchorListed->GetAnchorId() != FLY_AT_PARA) &&
+ (pAnchorNew ->GetAnchorId() != FLY_AT_PARA) &&
+ pCntntAnchorListed && pCntntAnchorNew )
+ {
+ if ( pCntntAnchorListed->nContent != pCntntAnchorNew->nContent )
+ {
+ return pCntntAnchorListed->nContent < pCntntAnchorNew->nContent;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AT_CHAR) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AS_CHAR))
+ {
+ return true;
+ }
+ else if ((pAnchorListed->GetAnchorId() == FLY_AS_CHAR) &&
+ (pAnchorNew ->GetAnchorId() == FLY_AT_CHAR))
+ {
+ return false;
+ }
+ }
+ // <--
+
+ // objects anchored at the same content and at the same content anchor
+ // node position with the same anchor type
+ // Thus, compare its wrapping style including its layer
+ const IDocumentDrawModelAccess* pIDDMA = rFmtListed.getIDocumentDrawModelAccess();
+ const SdrLayerID nHellId = pIDDMA->GetHellId();
+ const SdrLayerID nInvisibleHellId = pIDDMA->GetInvisibleHellId();
+ const bool bWrapThroughOrHellListed =
+ rFmtListed.GetSurround().GetSurround() == SURROUND_THROUGHT ||
+ _pListedAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
+ _pListedAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
+ const bool bWrapThroughOrHellNew =
+ rFmtNew.GetSurround().GetSurround() == SURROUND_THROUGHT ||
+ _pNewAnchoredObj->GetDrawObj()->GetLayer() == nHellId ||
+ _pNewAnchoredObj->GetDrawObj()->GetLayer() == nInvisibleHellId;
+ if ( bWrapThroughOrHellListed != bWrapThroughOrHellNew )
+ {
+ if ( bWrapThroughOrHellListed )
+ return false;
+ else
+ return true;
+ }
+ else if ( bWrapThroughOrHellListed && bWrapThroughOrHellNew )
+ {
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+
+ // objects anchored at the same content with a set text wrapping
+ // Thus, compare wrap influences on object position
+ const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosListed =
+ &(rFmtListed.GetWrapInfluenceOnObjPos());
+ const SwFmtWrapInfluenceOnObjPos* pWrapInfluenceOnObjPosNew =
+ &(rFmtNew.GetWrapInfluenceOnObjPos());
+ // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
+ if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true ) !=
+ pWrapInfluenceOnObjPosNew->GetWrapInfluenceOnObjPos( true ) )
+ // <--
+ {
+ // --> OD 2004-10-18 #i35017# - constant name has changed
+ if ( pWrapInfluenceOnObjPosListed->GetWrapInfluenceOnObjPos( true )
+ == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE )
+ // <--
+ return true;
+ else
+ return false;
+ }
+
+ // objects anchored at the same content position/page/fly with same
+ // wrap influence.
+ // Thus, compare anchor order number
+ return pAnchorListed->GetOrder() < pAnchorNew->GetOrder();
+ }
+};
+
+bool SwSortedObjsImpl::Insert( SwAnchoredObject& _rAnchoredObj )
+{
+ // --> OD 2005-08-18 #i51941#
+ if ( Contains( _rAnchoredObj ) )
+ {
+ // list already contains object
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwSortedObjsImpl::Insert()> - already contains object" );
+#endif
+ return true;
+ }
+
+ // find insert position
+ tIter aInsPosIter = std::lower_bound( maSortedObjLst.begin(),
+ maSortedObjLst.end(),
+ &_rAnchoredObj, ObjAnchorOrder() );
+
+ // insert object into list
+ maSortedObjLst.insert( aInsPosIter, &_rAnchoredObj );
+
+ return Contains( _rAnchoredObj );
+}
+
+bool SwSortedObjsImpl::Remove( SwAnchoredObject& _rAnchoredObj )
+{
+ bool bRet = true;
+
+ tIter aDelPosIter = std::find( maSortedObjLst.begin(),
+ maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ if ( aDelPosIter == maSortedObjLst.end() )
+ {
+ // object not found.
+ bRet = false;
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "<SwSortedObjsImpl::Remove()> - object not found" );
+#endif
+ }
+ else
+ {
+ maSortedObjLst.erase( aDelPosIter );
+ }
+
+ return bRet;
+}
+
+bool SwSortedObjsImpl::Contains( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ return aIter != maSortedObjLst.end();
+}
+
+bool SwSortedObjsImpl::Update( SwAnchoredObject& _rAnchoredObj )
+{
+ if ( !Contains( _rAnchoredObj ) )
+ {
+ // given anchored object not found in list
+ OSL_FAIL( "<SwSortedObjsImpl::Update(..) - sorted list doesn't contain given anchored object" );
+ return false;
+ }
+
+ if ( Count() == 1 )
+ {
+ // given anchored object is the only one in the list.
+ return true;
+ }
+
+ Remove( _rAnchoredObj );
+ Insert( _rAnchoredObj );
+
+ return Contains( _rAnchoredObj );
+}
+
+sal_uInt32 SwSortedObjsImpl::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
+{
+ sal_uInt32 nRetLstPos = Count();
+
+ tConstIter aIter = std::find( maSortedObjLst.begin(), maSortedObjLst.end(),
+ &_rAnchoredObj );
+
+ if ( aIter != maSortedObjLst.end() )
+ {
+ // --> OD 2005-08-18 #i51941#
+// nRetLstPos = aIter - maSortedObjLst.begin();
+ std::vector< SwAnchoredObject* >::difference_type nPos =
+ aIter - maSortedObjLst.begin();
+ nRetLstPos = sal_uInt32( nPos );
+ // <--
+ }
+
+ return nRetLstPos;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
new file mode 100644
index 000000000000..1bfaa40c7ae8
--- /dev/null
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -0,0 +1,814 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <ftnfrm.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <doc.hxx>
+#include <node.hxx>
+#include <dview.hxx>
+#include <dcontact.hxx>
+#include <dflyobj.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx> // ClearPara()
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <fmtfsize.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <ndtxt.hxx>
+#include <ndindex.hxx>
+#include <frmtool.hxx>
+#include <pagedesc.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <fmtclds.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include <sortedobjs.hxx>
+#include <hints.hxx>
+#include <switerator.hxx>
+
+ // No inline cause we need the function pointers
+long SwFrm::GetTopMargin() const
+ { return Prt().Top(); }
+long SwFrm::GetBottomMargin() const
+ { return Frm().Height() -Prt().Height() -Prt().Top(); }
+long SwFrm::GetLeftMargin() const
+ { return Prt().Left(); }
+long SwFrm::GetRightMargin() const
+ { return Frm().Width() - Prt().Width() - Prt().Left(); }
+long SwFrm::GetPrtLeft() const
+ { return Frm().Left() + Prt().Left(); }
+long SwFrm::GetPrtBottom() const
+ { return Frm().Top() + Prt().Height() + Prt().Top(); }
+long SwFrm::GetPrtRight() const
+ { return Frm().Left() + Prt().Width() + Prt().Left(); }
+long SwFrm::GetPrtTop() const
+ { return Frm().Top() + Prt().Top(); }
+
+sal_Bool SwFrm::SetMinLeft( long nDeadline )
+{
+ SwTwips nDiff = nDeadline - Frm().Left();
+ if( nDiff > 0 )
+ {
+ Frm().Left( nDeadline );
+ Prt().Width( Prt().Width() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMaxBottom( long nDeadline )
+{
+ SwTwips nDiff = Frm().Top() + Frm().Height() - nDeadline;
+ if( nDiff > 0 )
+ {
+ Frm().Height( Frm().Height() - nDiff );
+ Prt().Height( Prt().Height() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMinTop( long nDeadline )
+{
+ SwTwips nDiff = nDeadline - Frm().Top();
+ if( nDiff > 0 )
+ {
+ Frm().Top( nDeadline );
+ Prt().Height( Prt().Height() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwFrm::SetMaxRight( long nDeadline )
+{
+ SwTwips nDiff = Frm().Left() + Frm().Width() - nDeadline;
+ if( nDiff > 0 )
+ {
+ Frm().Width( Frm().Width() - nDiff );
+ Prt().Width( Prt().Width() - nDiff );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SwFrm::MakeBelowPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().Y() += pPrv->Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ }
+ if( bNotify )
+ aFrm.Pos().Y() += 1;
+}
+
+void SwFrm::MakeUpperPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().Y() -= Frm().Height();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ aFrm.Pos().Y() += pUp->Prt().Height() - aFrm.Height();
+ }
+ if( bNotify )
+ aFrm.Pos().Y() -= 1;
+}
+
+void SwFrm::MakeLeftPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().X() -= Frm().Width();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ aFrm.Pos().X() += pUp->Prt().Width() - aFrm.Width();
+ }
+ if( bNotify )
+ aFrm.Pos().X() -= 1;
+}
+
+void SwFrm::MakeRightPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
+{
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->Frm().Pos() );
+ aFrm.Pos().X() += pPrv->Frm().Width();
+ }
+ else
+ {
+ aFrm.Pos( pUp->Frm().Pos() );
+ aFrm.Pos() += pUp->Prt().Pos();
+ }
+ if( bNotify )
+ aFrm.Pos().X() += 1;
+}
+
+void SwFrm::SetTopBottomMargins( long nTop, long nBot )
+{
+ Prt().Top( nTop );
+ Prt().Height( Frm().Height() - nTop - nBot );
+}
+
+void SwFrm::SetBottomTopMargins( long nBot, long nTop )
+{
+ Prt().Top( nTop );
+ Prt().Height( Frm().Height() - nTop - nBot );
+}
+
+void SwFrm::SetLeftRightMargins( long nLeft, long nRight)
+{
+ Prt().Left( nLeft );
+ Prt().Width( Frm().Width() - nLeft - nRight );
+}
+
+void SwFrm::SetRightLeftMargins( long nRight, long nLeft)
+{
+ Prt().Left( nLeft );
+ Prt().Width( Frm().Width() - nLeft - nRight );
+}
+
+const sal_uInt16 nMinVertCellHeight = 1135;
+
+/*--------------------------------------------------
+ * SwFrm::CheckDirChange(..)
+ * checks the layout direction and
+ * invalidates the lower frames rekursivly, if necessary.
+ * --------------------------------------------------*/
+
+void SwFrm::CheckDirChange()
+{
+ sal_Bool bOldVert = GetVerticalFlag();
+ sal_Bool bOldRev = IsReverse();
+ sal_Bool bOldR2L = GetRightToLeftFlag();
+ SetInvalidVert( sal_True );
+ SetInvalidR2L( sal_True );
+ sal_Bool bChg = bOldR2L != IsRightToLeft();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ sal_Bool bOldVertL2R = IsVertLR();
+ if( ( IsVertical() != bOldVert ) || bChg || IsReverse() != bOldRev || bOldVertL2R != IsVertLR() )
+ {
+ InvalidateAll();
+ if( IsLayoutFrm() )
+ {
+ // set minimum row height for vertical cells in horizontal table:
+ if ( IsCellFrm() && GetUpper() )
+ {
+ if ( IsVertical() != GetUpper()->IsVertical() &&
+ ((SwCellFrm*)this)->GetTabBox()->getRowSpan() == 1 )
+ {
+ SwTableLine* pLine = (SwTableLine*)((SwCellFrm*)this)->GetTabBox()->GetUpper();
+ SwFrmFmt* pFrmFmt = pLine->GetFrmFmt();
+ SwFmtFrmSize aNew( pFrmFmt->GetFrmSize() );
+ if ( ATT_FIX_SIZE != aNew.GetHeightSizeType() )
+ aNew.SetHeightSizeType( ATT_MIN_SIZE );
+ if ( aNew.GetHeight() < nMinVertCellHeight )
+ aNew.SetHeight( nMinVertCellHeight );
+ SwDoc* pDoc = pFrmFmt->GetDoc();
+ pDoc->SetAttr( aNew, *pLine->ClaimFrmFmt() );
+ }
+ }
+
+ SwFrm* pFrm = ((SwLayoutFrm*)this)->Lower();
+ const SwFmtCol* pCol = NULL;
+ SwLayoutFrm* pBody = 0;
+ if( pFrm )
+ {
+ if( IsPageFrm() )
+ {
+ // If we're a page frame and we change our layout direction,
+ // we have to look for columns and rearrange them.
+ pBody = ((SwPageFrm*)this)->FindBodyCont();
+ if(pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm())
+ pCol = &((SwPageFrm*)this)->GetFmt()->GetCol();
+ }
+ else if( pFrm->IsColumnFrm() )
+ {
+ pBody = ((SwLayoutFrm*)this);
+ const SwFrmFmt *pFmt = pBody->GetFmt();
+ if( pFmt )
+ pCol = &pFmt->GetCol();
+ }
+ }
+ while( pFrm )
+ {
+ pFrm->CheckDirChange();
+ pFrm = pFrm->GetNext();
+ }
+ if( pCol )
+ pBody->AdjustColumns( pCol, sal_True );
+ }
+ else if( IsTxtFrm() )
+ ((SwTxtFrm*)this)->Prepare( PREP_CLEAR );
+
+ // --> OD 2004-07-27 #i31698# - notify anchored objects also for page frames.
+ // Remove code above for special handling of page frames
+ if ( GetDrawObjs() )
+ {
+ const SwSortedObjs *pObjs = GetDrawObjs();
+ sal_uInt32 nCnt = pObjs->Count();
+ for ( sal_uInt32 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if( pAnchoredObj->ISA(SwFlyFrm) )
+ static_cast<SwFlyFrm*>(pAnchoredObj)->CheckDirChange();
+ else
+ {
+ // OD 2004-04-06 #i26791# - direct object
+ // positioning no longer needed. Instead
+ // invalidate
+ pAnchoredObj->InvalidateObjPos();
+ }
+ // --> OD 2004-07-27 #i31698# - update layout direction of
+ // anchored object
+ {
+ ::setContextWritingMode( pAnchoredObj->DrawObj(), pAnchoredObj->GetAnchorFrmContainingAnchPos() );
+ pAnchoredObj->UpdateLayoutDir();
+ }
+ // <--
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------
+ * SwFrm::GetFrmAnchorPos(..)
+ * returns the position for anchors based on frame direction
+ * --------------------------------------------------*/
+// OD 2004-03-10 #i11860# - consider lower space and line spacing of
+// previous frame according to new option 'Use former object positioning'
+Point SwFrm::GetFrmAnchorPos( sal_Bool bIgnoreFlysAnchoredAtThisFrame ) const
+{
+ Point aAnchor = Frm().Pos();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if ( ( IsVertical() && !IsVertLR() ) || IsRightToLeft() )
+ aAnchor.X() += Frm().Width();
+
+ if ( IsTxtFrm() )
+ {
+ SwTwips nBaseOfstForFly =
+ ((SwTxtFrm*)this)->GetBaseOfstForFly( bIgnoreFlysAnchoredAtThisFrame );
+ if ( IsVertical() )
+ aAnchor.Y() += nBaseOfstForFly;
+ else
+ aAnchor.X() += nBaseOfstForFly;
+
+ // OD 2004-03-10 #i11860# - if option 'Use former object positioning'
+ // is OFF, consider the lower space and the line spacing of the
+ // previous frame and the spacing considered for the page grid
+ const SwTxtFrm* pThisTxtFrm = static_cast<const SwTxtFrm*>(this);
+ const SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
+ pThisTxtFrm->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
+ if ( IsVertical() )
+ {
+ aAnchor.X() -= nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+ }
+ else
+ {
+ aAnchor.Y() += nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
+ }
+ }
+
+ return aAnchor;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::~SwFrm()
+|*
+|*************************************************************************/
+
+SwFrm::~SwFrm()
+{
+ // accessible objects for fly and cell frames have been already disposed
+ // by the destructors of the derived classes.
+ if( IsAccessibleFrm() && !(IsFlyFrm() || IsCellFrm()) && GetDep() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell *pVSh = pRootFrm->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ OSL_ENSURE( !GetLower(), "Lowers should be dispose already!" );
+ pVSh->Imp()->DisposeAccessibleFrm( this );
+ }
+ }
+ }
+
+ if( pDrawObjs )
+ {
+ for ( sal_uInt32 i = pDrawObjs->Count(); i; )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pDrawObjs)[--i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ }
+ if ( pDrawObjs )
+ delete pDrawObjs;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ // JP 15.10.2001: for detection of access to deleted frames
+ pDrawObjs = (SwSortedObjs*)0x33333333;
+#endif
+}
+
+/*************************************************************************/
+
+const SwFrmFmt * SwLayoutFrm::GetFmt() const
+{
+ return static_cast< const SwFlyFrmFmt * >( GetDep() );
+}
+
+SwFrmFmt * SwLayoutFrm::GetFmt()
+{
+ return static_cast< SwFlyFrmFmt * >( GetDep() );
+}
+
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::SetFrmFmt()
+|*
+|*************************************************************************/
+
+
+void SwLayoutFrm::SetFrmFmt( SwFrmFmt *pNew )
+{
+ if ( pNew != GetFmt() )
+ {
+ SwFmtChg aOldFmt( GetFmt() );
+ pNew->Add( this );
+ SwFmtChg aNewFmt( pNew );
+ ModifyNotification( &aOldFmt, &aNewFmt );
+ }
+}
+
+/*************************************************************************
+|* SwCntntFrm::SwCntntFrm()
+|*************************************************************************/
+SwCntntFrm::SwCntntFrm( SwCntntNode * const pCntnt, SwFrm* pSib ) :
+ SwFrm( pCntnt, pSib ),
+ SwFlowFrm( (SwFrm&)*this )
+{
+}
+
+/*************************************************************************
+|* SwCntntFrm::~SwCntntFrm()
+|*************************************************************************/
+SwCntntFrm::~SwCntntFrm()
+{
+ SwCntntNode* pCNd;
+ if( 0 != ( pCNd = PTR_CAST( SwCntntNode, GetRegisteredIn() )) &&
+ !pCNd->GetDoc()->IsInDtor() )
+ {
+ //Bei der Root abmelden wenn ich dort noch im Turbo stehe.
+ SwRootFrm *pRoot = getRootFrm();
+ if( pRoot && pRoot->GetTurbo() == this )
+ {
+ pRoot->DisallowTurbo();
+ pRoot->ResetTurbo();
+ }
+ if( IsTxtFrm() && ((SwTxtFrm*)this)->HasFtn() )
+ {
+ SwTxtNode *pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
+ const SwFtnIdxs &rFtnIdxs = pCNd->GetDoc()->GetFtnIdxs();
+ sal_uInt16 nPos;
+ sal_uLong nIndex = pCNd->GetIndex();
+ rFtnIdxs.SeekEntry( *pTxtNd, &nPos );
+ SwTxtFtn* pTxtFtn;
+ if( nPos < rFtnIdxs.Count() )
+ {
+ while( nPos && pTxtNd == &(rFtnIdxs[ nPos ]->GetTxtNode()) )
+ --nPos;
+ if( nPos || pTxtNd != &(rFtnIdxs[ nPos ]->GetTxtNode()) )
+ ++nPos;
+ }
+ while( nPos < rFtnIdxs.Count() )
+ {
+ pTxtFtn = rFtnIdxs[ nPos ];
+ if( pTxtFtn->GetTxtNode().GetIndex() > nIndex )
+ break;
+ pTxtFtn->DelFrms( this );
+ ++nPos;
+ }
+ }
+ }
+}
+
+void SwCntntFrm::RegisterToNode( SwCntntNode& rNode )
+{
+ rNode.Add( this );
+}
+
+void SwCntntFrm::DelFrms( const SwCntntNode& rNode )
+{
+ SwIterator<SwCntntFrm,SwCntntNode> aIter( rNode );
+ for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
+ {
+ // --> OD 2005-12-01 #i27138#
+ // notify accessibility paragraphs objects about changed
+ // CONTENT_FLOWS_FROM/_TO relation.
+ // Relation CONTENT_FLOWS_FROM for current next paragraph will change
+ // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
+ if ( pFrm->IsTxtFrm() )
+ {
+ ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
+ if ( pViewShell && pViewShell->GetLayout() &&
+ pViewShell->GetLayout()->IsAnyShellAccessible() )
+ {
+ pViewShell->InvalidateAccessibleParaFlowRelation(
+ dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
+ dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
+ }
+ }
+ // <--
+ if( pFrm->HasFollow() )
+ pFrm->GetFollow()->_SetIsFollow( pFrm->IsFollow() );
+ if( pFrm->IsFollow() )
+ {
+ SwCntntFrm* pMaster = (SwTxtFrm*)pFrm->FindMaster();
+ pMaster->SetFollow( pFrm->GetFollow() );
+ pFrm->_SetIsFollow( sal_False );
+ }
+ pFrm->SetFollow( 0 );//Damit er nicht auf dumme Gedanken kommt.
+ //Andernfalls kann es sein, dass ein Follow
+ //vor seinem Master zerstoert wird, der Master
+ //greift dann ueber den ungueltigen
+ //Follow-Pointer auf fremdes Memory zu.
+ //Die Kette darf hier zerknauscht werden, weil
+ //sowieso alle zerstoert werden.
+ if( pFrm->GetUpper() && pFrm->IsInFtn() && !pFrm->GetIndNext() &&
+ !pFrm->GetIndPrev() )
+ {
+ SwFtnFrm *pFtn = pFrm->FindFtnFrm();
+ OSL_ENSURE( pFtn, "You promised a FtnFrm?" );
+ SwCntntFrm* pCFrm;
+ if( !pFtn->GetFollow() && !pFtn->GetMaster() &&
+ 0 != ( pCFrm = pFtn->GetRefFromAttr()) && pCFrm->IsFollow() )
+ {
+ OSL_ENSURE( pCFrm->IsTxtFrm(), "NoTxtFrm has Footnote?" );
+ ((SwTxtFrm*)pCFrm->FindMaster())->Prepare( PREP_FTN_GONE );
+ }
+ }
+ pFrm->Cut();
+ delete pFrm;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::~SwLayoutFrm
+|*
+|*************************************************************************/
+
+
+SwLayoutFrm::~SwLayoutFrm()
+{
+ SwFrm *pFrm = pLower;
+
+ if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
+ {
+ while ( pFrm )
+ {
+ //Erst die Objs des Frm vernichten, denn diese koennen sich sonst nach
+ //dem Remove nicht mehr bei der Seite abmelden.
+ //Falls sich einer nicht abmeldet wollen wir nicht gleich
+ //endlos schleifen.
+
+ sal_uInt32 nCnt;
+ while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
+ {
+ nCnt = pFrm->GetDrawObjs()->Count();
+ // --> OD 2004-06-30 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ if ( pFrm->GetDrawObjs() &&
+ nCnt == pFrm->GetDrawObjs()->Count() )
+ {
+ pFrm->GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ // <--
+ }
+ pFrm->Remove();
+ delete pFrm;
+ pFrm = pLower;
+ }
+ //Fly's vernichten. Der letzte loescht gleich das Array.
+ sal_uInt32 nCnt;
+ while ( GetDrawObjs() && GetDrawObjs()->Count() )
+ {
+ nCnt = GetDrawObjs()->Count();
+
+ // --> OD 2004-06-30 #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[0];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ delete pAnchoredObj;
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrm::~SwFrm> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ if ( GetDrawObjs() && nCnt == GetDrawObjs()->Count() )
+ {
+ GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ // <--
+ }
+ }
+ else
+ {
+ while( pFrm )
+ {
+ SwFrm *pNxt = pFrm->GetNext();
+ delete pFrm;
+ pFrm = pNxt;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::PaintArea()
+|*
+|* The paintarea is the area, in which the content of a frame is allowed
+|* to be displayed. This region could be larger than the printarea (Prt())
+|* of the upper, it includes e.g. often the margin of the page.
+|*
+|*************************************************************************/
+
+const SwRect SwFrm::PaintArea() const
+{
+ // NEW TABLES
+ // Cell frames may not leave their upper:
+ SwRect aRect = IsRowFrm() ? GetUpper()->Frm() : Frm();
+ const sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ long nRight = (aRect.*fnRect->fnGetRight)();
+ long nLeft = (aRect.*fnRect->fnGetLeft)();
+ const SwFrm* pTmp = this;
+ sal_Bool bLeft = sal_True;
+ sal_Bool bRight = sal_True;
+ long nRowSpan = 0;
+ while( pTmp )
+ {
+ if( pTmp->IsCellFrm() && pTmp->GetUpper() &&
+ pTmp->GetUpper()->IsVertical() != pTmp->IsVertical() )
+ nRowSpan = ((SwCellFrm*)pTmp)->GetTabBox()->getRowSpan();
+ long nTmpRight = (pTmp->Frm().*fnRect->fnGetRight)();
+ long nTmpLeft = (pTmp->Frm().*fnRect->fnGetLeft)();
+ if( pTmp->IsRowFrm() && nRowSpan > 1 )
+ {
+ const SwFrm* pNxt = pTmp;
+ while( --nRowSpan > 0 && pNxt->GetNext() )
+ pNxt = pNxt->GetNext();
+ if( pTmp->IsVertical() )
+ nTmpLeft = (pNxt->Frm().*fnRect->fnGetLeft)();
+ else
+ nTmpRight = (pNxt->Frm().*fnRect->fnGetRight)();
+ }
+ OSL_ENSURE( pTmp, "PaintArea lost in time and space" );
+ if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() ||
+ pTmp->IsCellFrm() || pTmp->IsRowFrm() || //nobody leaves a table!
+ pTmp->IsRootFrm() )
+ {
+ if( bLeft || nLeft < nTmpLeft )
+ nLeft = nTmpLeft;
+ if( bRight || nTmpRight < nRight )
+ nRight = nTmpRight;
+ if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() || pTmp->IsRootFrm() )
+ break;
+ bLeft = sal_False;
+ bRight = sal_False;
+ }
+ else if( pTmp->IsColumnFrm() ) // nobody enters neightbour columns
+ {
+ sal_Bool bR2L = pTmp->IsRightToLeft();
+ // the first column has _no_ influence to the left range
+ if( bR2L ? pTmp->GetNext() : pTmp->GetPrev() )
+ {
+ if( bLeft || nLeft < nTmpLeft )
+ nLeft = nTmpLeft;
+ bLeft = sal_False;
+ }
+ // the last column has _no_ influence to the right range
+ if( bR2L ? pTmp->GetPrev() : pTmp->GetNext() )
+ {
+ if( bRight || nTmpRight < nRight )
+ nRight = nTmpRight;
+ bRight = sal_False;
+ }
+ }
+ else if( bVert && pTmp->IsBodyFrm() )
+ {
+ // Header and footer frames have always horizontal direction and
+ // limit the body frame.
+ // A previous frame of a body frame must be a header,
+ // the next frame of a body frame may be a footnotecontainer or
+ // a footer. The footnotecontainer has the same direction like
+ // the body frame.
+ if( pTmp->GetPrev() && ( bLeft || nLeft < nTmpLeft ) )
+ {
+ nLeft = nTmpLeft;
+ bLeft = sal_False;
+ }
+ if( pTmp->GetNext() &&
+ ( pTmp->GetNext()->IsFooterFrm() || pTmp->GetNext()->GetNext() )
+ && ( bRight || nTmpRight < nRight ) )
+ {
+ nRight = nTmpRight;
+ bRight = sal_False;
+ }
+ }
+ pTmp = pTmp->GetUpper();
+ }
+ (aRect.*fnRect->fnSetLeft)( nLeft );
+ (aRect.*fnRect->fnSetRight)( nRight );
+ return aRect;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::UnionFrm()
+|*
+|* The unionframe is the framearea (Frm()) of a frame expanded by the
+|* printarea, if there's a negative margin at the left or right side.
+|*
+|*************************************************************************/
+
+const SwRect SwFrm::UnionFrm( sal_Bool bBorder ) const
+{
+ sal_Bool bVert = IsVertical();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ long nLeft = (Frm().*fnRect->fnGetLeft)();
+ long nWidth = (Frm().*fnRect->fnGetWidth)();
+ long nPrtLeft = (Prt().*fnRect->fnGetLeft)();
+ long nPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ if( nPrtLeft + nPrtWidth > nWidth )
+ nWidth = nPrtLeft + nPrtWidth;
+ if( nPrtLeft < 0 )
+ {
+ nLeft += nPrtLeft;
+ nWidth -= nPrtLeft;
+ }
+ SwTwips nRight = nLeft + nWidth;
+ long nAdd = 0;
+ if( bBorder )
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ const SvxBoxItem &rBox = rAttrs.GetBox();
+ if ( rBox.GetLeft() )
+ nLeft -= rBox.CalcLineSpace( BOX_LINE_LEFT );
+ else if ( rAttrs.IsBorderDist() )
+ nLeft -= rBox.GetDistance( BOX_LINE_LEFT ) + 1;
+ if ( rBox.GetRight() )
+ nAdd += rBox.CalcLineSpace( BOX_LINE_RIGHT );
+ else if ( rAttrs.IsBorderDist() )
+ nAdd += rBox.GetDistance( BOX_LINE_RIGHT ) + 1;
+ if( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
+ {
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ nLeft -= rShadow.CalcShadowSpace( SHADOW_LEFT );
+ nAdd += rShadow.CalcShadowSpace( SHADOW_RIGHT );
+ }
+ }
+ if( IsTxtFrm() && ((SwTxtFrm*)this)->HasPara() )
+ {
+ long nTmp = ((SwTxtFrm*)this)->HangingMargin();
+ if( nTmp > nAdd )
+ nAdd = nTmp;
+ }
+ nWidth = nRight + nAdd - nLeft;
+ SwRect aRet( Frm() );
+ (aRet.*fnRect->fnSetPosX)( nLeft );
+ (aRet.*fnRect->fnSetWidth)( nWidth );
+ return aRet;
+}
+
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/swselectionlist.cxx b/sw/source/core/layout/swselectionlist.cxx
new file mode 100644
index 000000000000..e2997db0a6bc
--- /dev/null
+++ b/sw/source/core/layout/swselectionlist.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <swselectionlist.hxx>
+#include <layfrm.hxx>
+#include <flyfrm.hxx>
+#include <ftnfrm.hxx>
+
+/** This class is used as parameter for functions to create a rectangular text selection
+*/
+
+namespace {
+
+ /** Find the context of a given frame
+
+ A context is the environment where text is allowed to flow.
+ The context is represented by
+ - the SwRootFrm if the frame is part of a page body
+ - the SwHeaderFrm if the frame is part of a page header
+ - the SwFooterFrm if the frame is part of a page footer
+ - the (master) SwFtnFrm if the frame is part of footnote
+ - the (first) SwFlyFrm if the frame is part of a (linked) fly frame
+
+ @param pFrm
+ the given frame
+
+ @return the context of the frame, represented by a SwFrm*
+ */
+ const SwFrm* getContext( const SwFrm* pFrm )
+ {
+ while( pFrm )
+ {
+ if( pFrm->IsRootFrm() || pFrm->IsHeaderFrm() || pFrm->IsFooterFrm() )
+ break;
+ if( pFrm->IsFlyFrm() )
+ {
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>( pFrm );
+ while( pFly->GetPrevLink() )
+ pFly = pFly->GetPrevLink();
+ break;
+ }
+ if( pFrm->IsFtnFrm() )
+ {
+ const SwFtnFrm* pFtn = static_cast<const SwFtnFrm*>( pFrm );
+ while( pFtn->GetMaster() )
+ pFtn = pFtn->GetMaster();
+ break;
+ }
+ pFrm = pFrm->GetUpper();
+ }
+ return pFrm;
+ }
+}
+
+SwSelectionList::SwSelectionList( const SwFrm* pInitCxt ) :
+ pContext( getContext( pInitCxt ) )
+{
+}
+
+bool SwSelectionList::checkContext( const SwFrm* pCheck )
+{
+ pCheck = getContext( pCheck );
+ if( !pContext )
+ pContext = pCheck;
+ return pContext == pCheck;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
new file mode 100644
index 000000000000..08f756d65b87
--- /dev/null
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -0,0 +1,5798 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "pagefrm.hxx"
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "viewsh.hxx"
+#include "doc.hxx"
+#include "docsh.hxx"
+#include "viewimp.hxx"
+#include "swtable.hxx"
+#include "dflyobj.hxx"
+#include "flyfrm.hxx"
+#include "frmtool.hxx"
+#include "frmfmt.hxx"
+#include "dcontact.hxx"
+#include <anchoreddrawobject.hxx>
+#include <fmtanchr.hxx>
+#include "viewopt.hxx"
+#include "hints.hxx"
+#include "dbg_lay.hxx"
+#include <ftnidx.hxx>
+#include <svl/itemiter.hxx>
+#include <docary.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtfsize.hxx>
+#include <swtblfmt.hxx>
+#include <ndtxt.hxx>
+#include "tabfrm.hxx"
+#include "rowfrm.hxx"
+#include "cellfrm.hxx"
+#include "flyfrms.hxx"
+#include "txtfrm.hxx" //HasFtn()
+#include "htmltbl.hxx"
+#include "sectfrm.hxx" //SwSectionFrm
+#include <fmtfollowtextflow.hxx>
+#include <sortedobjs.hxx>
+#include <objectformatter.hxx>
+#include <layouter.hxx>
+#include <switerator.hxx>
+
+extern void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
+ SwFrm *pFrm, SwPageFrm *pPage );
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwTabFrm::SwTabFrm(), ~SwTabFrm()
+|*
+|*************************************************************************/
+SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ):
+ SwLayoutFrm( rTab.GetFrmFmt(), pSib ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pTable( &rTab )
+{
+ bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove =
+ bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
+ bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
+ // --> OD 2004-10-04 #i26945#
+ bConsiderObjsForMinCellHeight = sal_True;
+ bObjsDoesFit = sal_True;
+ // <--
+ bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen.
+ nType = FRMC_TAB;
+
+ //Gleich die Zeilen erzeugen und einfuegen.
+ const SwTableLines &rLines = rTab.GetTabLines();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ SwRowFrm *pNew = new SwRowFrm( *rLines[i], this );
+ if( pNew->Lower() )
+ {
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+ else
+ delete pNew;
+ }
+ OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
+}
+
+SwTabFrm::SwTabFrm( SwTabFrm &rTab ) :
+ SwLayoutFrm( rTab.GetFmt(), &rTab ),
+ SwFlowFrm( (SwFrm&)*this ),
+ pTable( rTab.GetTable() )
+{
+ bIsFollow = sal_True;
+ bLockJoin = bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove =
+ bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
+ bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
+ // --> OD 2004-10-04 #i26945#
+ bConsiderObjsForMinCellHeight = sal_True;
+ bObjsDoesFit = sal_True;
+ // <--
+ bFixSize = sal_False; //Nicht nochmal auf die Importfilter hereinfallen.
+ nType = FRMC_TAB;
+
+ SetFollow( rTab.GetFollow() );
+ rTab.SetFollow( this );
+}
+
+extern const SwTable *pColumnCacheLastTable;
+extern const SwTabFrm *pColumnCacheLastTabFrm;
+extern const SwFrm *pColumnCacheLastCellFrm;
+extern const SwTable *pRowCacheLastTable;
+extern const SwTabFrm *pRowCacheLastTabFrm;
+extern const SwFrm *pRowCacheLastCellFrm;
+
+SwTabFrm::~SwTabFrm()
+{
+ // There is some terrible code in fetab.cxx, that
+ // makes use of these global pointers. Obviously
+ // this code did not consider that a TabFrm can be
+ // deleted.
+ if ( this == pColumnCacheLastTabFrm )
+ {
+ pColumnCacheLastTable = NULL;
+ pColumnCacheLastTabFrm = NULL;
+ pColumnCacheLastCellFrm= NULL;
+ pRowCacheLastTable = NULL;
+ pRowCacheLastTabFrm = NULL;
+ pRowCacheLastCellFrm= NULL;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::JoinAndDelFollows()
+|*
+|*************************************************************************/
+void SwTabFrm::JoinAndDelFollows()
+{
+ SwTabFrm *pFoll = GetFollow();
+ if ( pFoll->HasFollow() )
+ pFoll->JoinAndDelFollows();
+ pFoll->Cut();
+ SetFollow( pFoll->GetFollow() );
+ delete pFoll;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwTabFrm::RegistFlys()
+{
+ OSL_ENSURE( Lower() && Lower()->IsRowFrm(), "Keine Zeilen." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ SwRowFrm *pRow = (SwRowFrm*)Lower();
+ do
+ {
+ pRow->RegistFlys( pPage );
+ pRow = (SwRowFrm*)pRow->GetNext();
+ } while ( pRow );
+ }
+}
+
+/*************************************************************************
+|* Some prototypes
+|*************************************************************************/
+void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom );
+void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom );
+sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva );
+// --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
+// that only row and cell frames are formatted.
+sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
+ long nBottom,
+ bool _bOnlyRowsAndCells = false );
+// <--
+// OD 2004-02-18 #106629# - correct type of 1st parameter
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
+// control, if floating screen objects have to be considered for the minimal
+// cell height.
+SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm *pRow,
+ const sal_Bool _bConsiderObjs );
+// <--
+SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& );
+
+/*************************************************************************
+|* START: local helper functions for repeated headlines
+|*************************************************************************/
+
+SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount )
+{
+ if ( !nCount || !pStart)
+ return 0;
+
+ SwTwips nRet = 0;
+ SWRECTFN( pStart )
+ while ( pStart && nCount > 0 )
+ {
+ nRet += (pStart->Frm().*fnRect->fnGetHeight)();
+ pStart = pStart->GetNext();
+ --nCount;
+ }
+
+ return nRet;
+}
+
+/*************************************************************************
+|* END: local helper functions for repeated headlines
+|*************************************************************************/
+
+/*************************************************************************
+|* START: local helper functions for splitting row frames
+|*************************************************************************/
+
+//
+// Local helper function to insert a new follow flow line
+//
+SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine )
+{
+ OSL_ENSURE( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" );
+ const SwRowFrm& rRow = (SwRowFrm&)rTmpRow;
+
+ rTab.SetFollowFlowLine( sal_True );
+ SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false );
+ pFollowFlowLine->SetRowSpanLine( bRowSpanLine );
+ SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow();
+ pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow );
+ return pFollowFlowLine;
+}
+
+// --> OD 2004-11-05 #i26945# - local helper function to invalidate all lower
+// objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
+// additionally the objects are moved 'out of range'.
+void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm,
+ const bool _bMoveObjsOutOfRange = false,
+ SwPageFrm* _pPageFrm = 0L )
+{
+ // determine page frame, if needed
+ if ( !_pPageFrm )
+ {
+ _pPageFrm = _rLayoutFrm.FindPageFrm();
+ OSL_ENSURE( _pPageFrm,
+ "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
+ if ( !_pPageFrm )
+ {
+ return;
+ }
+ }
+
+ // loop on lower frames
+ SwFrm* pLowerFrm = _rLayoutFrm.Lower();
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsLayoutFrm() )
+ {
+ ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)),
+ _bMoveObjsOutOfRange, _pPageFrm );
+ }
+ if ( pLowerFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pLowerFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i];
+
+ // invalidate position of anchored object
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ pAnchoredObj->SetConsiderForTextWrap( false );
+ pAnchoredObj->UnlockPosition();
+ pAnchoredObj->InvalidateObjPos();
+
+ // move anchored object 'out of range'
+ if ( _bMoveObjsOutOfRange )
+ {
+ // indicate, that positioning is progress to avoid
+ // modification of the anchored object resp. its attributes
+ // due to the movement
+ SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
+ pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() );
+ // --> OD 2004-11-24 #115759# - reset character rectangle,
+ // top of line and relative position in order to assure,
+ // that anchored object is correctly positioned.
+ pAnchoredObj->ClearCharRectAndTopOfLine();
+ pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
+ if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR )
+ {
+ pAnchoredObj->AnchorFrm()
+ ->Prepare( PREP_FLY_ATTR_CHG,
+ &(pAnchoredObj->GetFrmFmt()) );
+ }
+ // <--
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ pFly->GetVirtDrawObj()->SetRectsDirty();
+ pFly->GetVirtDrawObj()->SetChanged();
+ }
+ }
+
+ // If anchored object is a fly frame, invalidate its lower objects
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm );
+ }
+ }
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+}
+// <--
+//
+// Local helper function to shrink all lowers of rRow to 0 height
+//
+void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow )
+{
+ SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower());
+ SWRECTFN( pCurrMasterCell )
+
+ while ( pCurrMasterCell )
+ {
+ // NEW TABLES
+ SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ?
+ const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) :
+ *pCurrMasterCell;
+
+ // --> OD 2004-10-04 #i26945#
+ // all lowers should have the correct position
+ lcl_ArrangeLowers( &rToAdjust,
+ (rToAdjust.*fnRect->fnGetPrtTop)(),
+ sal_False );
+ // <--
+ // TODO: Optimize number of frames which are set to 0 height
+ // we have to start with the last lower frame, otherwise
+ // the shrink will not shrink the current cell
+ SwFrm* pTmp = rToAdjust.GetLastLower();
+
+ if ( pTmp && pTmp->IsRowFrm() )
+ {
+ SwRowFrm* pTmpRow = (SwRowFrm*)pTmp;
+ lcl_ShrinkCellsAndAllContent( *pTmpRow );
+ }
+ else
+ {
+ // TODO: Optimize number of frames which are set to 0 height
+ while ( pTmp )
+ {
+ // the frames have to be shrunk
+ if ( pTmp && pTmp->IsTabFrm() )
+ {
+ SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower();
+ while ( pTmpRow )
+ {
+ lcl_ShrinkCellsAndAllContent( *pTmpRow );
+ pTmpRow = (SwRowFrm*)pTmpRow->GetNext();
+ }
+ }
+ else
+ {
+ pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() );
+ (pTmp->Prt().*fnRect->fnSetTop)( 0 );
+ (pTmp->Prt().*fnRect->fnSetHeight)( 0 );
+ }
+
+ pTmp = pTmp->GetPrev();
+ }
+
+ // all lowers should have the correct position
+ lcl_ArrangeLowers( &rToAdjust,
+ (rToAdjust.*fnRect->fnGetPrtTop)(),
+ sal_False );
+ }
+
+ pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext());
+ }
+}
+
+//
+// Local helper function to move the content from rSourceLine to rDestLine
+// The content is inserted behind the last content in the corresponding
+// cell in rDestLine.
+//
+void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine )
+{
+ SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower();
+ SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
+
+ // Move content of follow cells into master cells
+ while ( pCurrSourceCell )
+ {
+ if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() )
+ {
+ SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ while ( pTmpSourceRow )
+ {
+ // --> FME 2006-01-10 #125926# Achtung! It is possible,
+ // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
+ // cannot be found. In this case, we have to move the complete
+ // row.
+ SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower();
+ // <--
+
+ if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow )
+ {
+ // move content from follow flow row to pTmpDestRow:
+ while ( pTmpDestRow->GetNext() )
+ pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext();
+
+ OSL_ENSURE( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Knoten in der Tabelle" );
+
+ lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow );
+ pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() );
+ pTmpSourceRow->Remove();
+ delete pTmpSourceRow;
+ }
+ else
+ {
+ // move complete row:
+ pTmpSourceRow->Remove();
+ pTmpSourceRow->InsertBefore( pCurrDestCell, 0 );
+ }
+
+ pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ }
+ }
+ else
+ {
+ SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell );
+ if ( pTmp )
+ {
+ // NEW TABLES
+ SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell);
+ if ( pDestCell->GetTabBox()->getRowSpan() < 1 )
+ pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true ));
+
+ // Find last content
+ SwFrm* pFrm = pDestCell->GetLastLower();
+ ::RestoreCntnt( pTmp, pDestCell, pFrm, true );
+ }
+ }
+ pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext();
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ }
+}
+
+//
+// Local helper function to move all footnotes in rRowFrm from
+// the footnote boss of rSource to the footnote boss of rDest.
+//
+void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm )
+{
+ if ( 0 != rSource.GetFmt()->GetDoc()->GetFtnIdxs().Count() )
+ {
+ SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( sal_True );
+ SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( sal_True );
+ rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, sal_True );
+ }
+}
+
+//
+// Local helper function to handle nested table cells before the split process
+//
+void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine,
+ SwRowFrm& rFollowFlowLine, SwTwips nRemain )
+{
+ SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower();
+ SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower();
+
+ SWRECTFN( pCurrLastLineCell )
+
+ //
+ // Move content of follow cells into master cells
+ //
+ while ( pCurrLastLineCell )
+ {
+ if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() )
+ {
+ SwTwips nTmpCut = nRemain;
+ SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower();
+
+ // --> OD 2004-10-04 #i26945#
+ SwTwips nCurrentHeight =
+ lcl_CalcMinRowHeight( pTmpLastLineRow,
+ rTab.IsConsiderObjsForMinCellHeight() );
+ // <--
+ while ( pTmpLastLineRow && pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight )
+ {
+ nTmpCut -= nCurrentHeight;
+ pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ // --> OD 2004-10-04 #i26945#
+ nCurrentHeight =
+ lcl_CalcMinRowHeight( pTmpLastLineRow,
+ rTab.IsConsiderObjsForMinCellHeight() );
+ // <--
+ }
+
+ //
+ // pTmpLastLineRow does not fit to the line or it is the last line
+ //
+ if ( pTmpLastLineRow )
+ {
+ //
+ // Check if we can move pTmpLastLineRow to the follow table,
+ // or if we have to split the line:
+ //
+ SwFrm* pCell = pTmpLastLineRow->Lower();
+ bool bTableLayoutToComplex = false;
+ long nMinHeight = 0;
+
+ //
+ // We have to take into account:
+ // 1. The fixed height of the row
+ // 2. The borders of the cells inside the row
+ // 3. The minimum height of the row
+ //
+ if ( pTmpLastLineRow->HasFixSize() )
+ nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)();
+ else
+ {
+ while ( pCell )
+ {
+ if ( ((SwCellFrm*)pCell)->Lower() &&
+ ((SwCellFrm*)pCell)->Lower()->IsRowFrm() )
+ {
+ bTableLayoutToComplex = true;
+ break;
+ }
+
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nMinHeight = Max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) );
+ pCell = pCell->GetNext();
+ }
+
+ const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize();
+ if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
+ nMinHeight = Max( nMinHeight, rSz.GetHeight() );
+ }
+
+ //
+ // 1. Case:
+ // The line completely fits into the master table.
+ // Nevertheless, we build a follow (otherwise painting problems
+ // with empty cell).
+ //
+ // 2. Case:
+ // The line has to be split, the minimum height still fits into
+ // the master table, and the table structure is not to complex.
+ //
+ if ( nTmpCut > nCurrentHeight ||
+ ( pTmpLastLineRow->IsRowSplitAllowed() &&
+ !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
+ {
+ // The line has to be split:
+ SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false );
+ pNewRow->SetFollowFlowRow( true );
+ pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() );
+ pTmpLastLineRow->SetFollowRow( pNewRow );
+ pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 );
+ pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ }
+
+ //
+ // The following lines have to be moved:
+ //
+ while ( pTmpLastLineRow )
+ {
+ SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext();
+ lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow );
+ pTmpLastLineRow->Remove();
+ pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 );
+ pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
+ pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
+ pTmpLastLineRow = pTmp;
+ }
+ }
+ }
+
+ pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext();
+ pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext();
+ }
+}
+
+//
+// Local helper function to handle nested table cells after the split process
+//
+void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine )
+{
+ SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
+ while ( pCurrMasterCell )
+ {
+ if ( pCurrMasterCell->Lower() &&
+ pCurrMasterCell->Lower()->IsRowFrm() )
+ {
+ SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower());
+
+ if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() )
+ {
+ OSL_ENSURE( pRowFrm->GetFollowRow(), "Deleting row frame without follow" );
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm );
+ pRowFrm->Cut();
+ SwRowFrm* pFollowRow = pRowFrm->GetFollowRow();
+ pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow );
+ pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() );
+ lcl_MoveRowContent( *pFollowRow, *pRowFrm );
+ pFollowRow->Cut();
+ delete pFollowRow;
+ ::SwInvalidateAll( pCurrMasterCell, LONG_MAX );
+ }
+ }
+
+ pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
+ }
+}
+
+//
+// Local helper function to re-calculate the split line.
+//
+inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); }
+inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); }
+
+bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine,
+ SwTwips nRemainingSpaceForLastRow )
+{
+ bool bRet = true;
+
+ SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper();
+
+ //
+ // If there are nested cells in rLastLine, the recalculation of the last
+ // line needs some preprocessing.
+ //
+ lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow );
+
+ //
+ // Here the recalculation process starts:
+ //
+ rTab.SetRebuildLastLine( sal_True );
+ // --> OD 2004-10-15 #i26945#
+ rTab.SetDoesObjsFit( sal_True );
+ // <--
+ SWRECTFN( rTab.GetUpper() )
+
+ // --> OD 2004-11-05 #i26945# - invalidate and move floating screen
+ // objects 'out of range'
+ ::lcl_InvalidateLowerObjs( rLastLine, true );
+ // <--
+ //
+ // manipulate row and cell sizes
+ //
+ // --> OD 2004-10-04 #i26945# - Do *not* consider floating screen objects
+ // for the minimal cell height.
+ rTab.SetConsiderObjsForMinCellHeight( sal_False );
+ ::lcl_ShrinkCellsAndAllContent( rLastLine );
+ rTab.SetConsiderObjsForMinCellHeight( sal_True );
+ // <--
+
+ //
+ // invalidate last line
+ //
+ ::SwInvalidateAll( &rLastLine, LONG_MAX );
+
+ //
+ // Lock this tab frame and its follow
+ //
+ bool bUnlockMaster = false;
+ bool bUnlockFollow = false;
+ SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0;
+ if ( pMaster && !pMaster->IsJoinLocked() )
+ {
+ bUnlockMaster = true;
+ ::TableSplitRecalcLock( pMaster );
+ }
+ if ( !rTab.GetFollow()->IsJoinLocked() )
+ {
+ bUnlockFollow = true;
+ ::TableSplitRecalcLock( rTab.GetFollow() );
+ }
+
+ //
+ // Do the recalculation
+ //
+ lcl_RecalcRow( rLastLine, LONG_MAX );
+ // --> OD 2004-11-23 #115759# - force a format of the last line in order to
+ // get the correct height.
+ rLastLine.InvalidateSize();
+ rLastLine.Calc();
+ // <--
+
+ //
+ // Unlock this tab frame and its follow
+ //
+ if ( bUnlockFollow )
+ ::TableSplitRecalcUnlock( rTab.GetFollow() );
+ if ( bUnlockMaster )
+ ::TableSplitRecalcUnlock( pMaster );
+
+ //
+ // If there are nested cells in rLastLine, the recalculation of the last
+ // line needs some postprocessing.
+ //
+ lcl_PostprocessRowsInCells( rTab, rLastLine );
+
+ //
+ // Do a couple of checks on the current situation.
+ //
+ // If we are not happy with the current situation we return false.
+ // This will start a new try to split the table, this time we do not
+ // try to split the table rows.
+ //
+
+ //
+ // 1. Check if table fits to its upper.
+ // --> OD 2004-10-15 #i26945# - include check, if objects fit
+ //
+ const SwTwips nDistanceToUpperPrtBottom =
+ (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
+ if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() )
+ bRet = false;
+ // <--
+
+ //
+ // 2. Check if each cell in the last line has at least one content frame.
+ //
+ // Note: a FollowFlowRow may contains empty cells!
+ //
+ if ( bRet )
+ {
+ if ( !rLastLine.IsInFollowFlowRow() )
+ {
+ SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
+ while ( pCurrMasterCell )
+ {
+ if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 )
+ {
+ bRet = false;
+ break;
+ }
+ pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
+ }
+ }
+ }
+
+ //
+ // 3. Check if last line does not contain any content:
+ //
+ if ( bRet )
+ {
+ if ( !rLastLine.ContainsCntnt() )
+ {
+ bRet = false;
+ }
+ }
+
+
+ //
+ // 4. Check if follow flow line does not contain content:
+ //
+ if ( bRet )
+ {
+ if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() )
+ {
+ bRet = false;
+ }
+ }
+
+ if ( bRet )
+ {
+ //
+ // Everything looks fine. Splitting seems to be successful. We invalidate
+ // rFollowLine to force a new formatting.
+ //
+ ::SwInvalidateAll( &rFollowLine, LONG_MAX );
+ }
+ else
+ {
+ //
+ // Splitting the table row gave us an unexpected result.
+ // Everything has to be prepared for a second try to split
+ // the table, this time without splitting the row.
+ //
+ ::SwInvalidateAll( &rLastLine, LONG_MAX );
+ }
+
+ rTab.SetRebuildLastLine( sal_False );
+ // --> OD 2004-10-15 #i26945#
+ rTab.SetDoesObjsFit( sal_True );
+ // <--
+
+ return bRet;
+}
+
+//
+// Sets the correct height for all spanned cells
+//
+void lcl_AdjustRowSpanCells( SwRowFrm* pRow )
+{
+ SWRECTFN( pRow )
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower());
+ while ( pCellFrm )
+ {
+ const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan();
+ if ( nLayoutRowSpan > 1 )
+ {
+ // calculate height of cell:
+ const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan );
+ const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ }
+
+ pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
+ }
+}
+
+//
+// Returns the maximum layout row span of the row
+// Looking for the next row that contains no covered cells:
+long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow )
+{
+ long nRet = 1;
+
+ const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext());
+ bool bNextRow = false;
+
+ while ( pCurrentRowFrm )
+ {
+ // if there is any covered cell, we proceed to the next row frame
+ const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower());
+ while ( pLower )
+ {
+ if ( pLower->GetTabBox()->getRowSpan() < 0 )
+ {
+ ++nRet;
+ bNextRow = true;
+ break;
+ }
+ pLower = static_cast<const SwCellFrm*>(pLower->GetNext());
+ }
+ pCurrentRowFrm = bNextRow ?
+ static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) :
+ 0;
+ }
+
+ return nRet;
+}
+
+/*************************************************************************
+|* END: local helper functions for splitting row frames
+|*************************************************************************/
+
+//
+// Function to remove the FollowFlowLine of rTab.
+// The content of the FollowFlowLine is moved to the associated line in the
+// master table.
+//
+bool SwTabFrm::RemoveFollowFlowLine()
+{
+ // find FollowFlowLine
+ SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow());
+
+ // find last row in master
+ SwFrm* pLastLine = GetLastLower();
+
+ OSL_ENSURE( HasFollowFlowLine() &&
+ pFollowFlowLine &&
+ pLastLine, "There should be a flowline in the follow" );
+
+ // We have to reset the flag here, because lcl_MoveRowContent
+ // calls a GrowFrm(), which has a different bahavior if
+ // this flag is set.
+ SetFollowFlowLine( sal_False );
+
+ // --> FME 2007-07-19 #140081# Make code robust.
+ if ( !pFollowFlowLine || !pLastLine )
+ return true;
+
+ // Move content
+ lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine );
+
+ // NEW TABLES
+ // If a row span follow flow line is removed, we want to move the whole span
+ // to the master:
+ long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine );
+
+ if ( nRowsToMove > 1 )
+ {
+ SWRECTFN( this )
+ SwFrm* pRow = pFollowFlowLine->GetNext();
+ SwFrm* pInsertBehind = GetLastLower();
+ SwTwips nGrow = 0;
+
+ while ( pRow && nRowsToMove-- > 1 )
+ {
+ SwFrm* pNxt = pRow->GetNext();
+ nGrow += (pRow->Frm().*fnRect->fnGetHeight)();
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow );
+
+ pRow->Remove();
+ pRow->InsertBehind( this, pInsertBehind );
+ pRow->_InvalidateAll();
+ pRow->CheckDirChange();
+ pInsertBehind = pRow;
+ pRow = pNxt;
+ }
+
+ SwFrm* pFirstRow = Lower();
+ while ( pFirstRow )
+ {
+ lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) );
+ pFirstRow = pFirstRow->GetNext();
+ }
+
+ Grow( nGrow );
+ GetFollow()->Shrink( nGrow );
+ }
+
+ bool bJoin = !pFollowFlowLine->GetNext();
+ pFollowFlowLine->Cut();
+ delete pFollowFlowLine;
+
+ return bJoin;
+}
+
+// --> OD 2004-10-04 #i26945# - Floating screen objects are no longer searched.
+bool lcl_FindSectionsInRow( const SwRowFrm& rRow )
+{
+ bool bRet = false;
+ SwCellFrm* pLower = (SwCellFrm*)rRow.Lower();
+ while ( pLower )
+ {
+ if ( pLower->IsVertical() != rRow.IsVertical() )
+ return true;
+
+ SwFrm* pTmpFrm = pLower->Lower();
+ while ( pTmpFrm )
+ {
+ if ( pTmpFrm->IsRowFrm() )
+ {
+ bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm );
+ }
+ else
+ {
+ // --> OD 2004-10-04 #i26945# - search only for sections
+ bRet = pTmpFrm->IsSctFrm();
+ // <--
+ }
+
+ if ( bRet )
+ return true;
+ pTmpFrm = pTmpFrm->GetNext();
+ }
+
+ pLower = (SwCellFrm*)pLower->GetNext();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Split(), Join()
+|*
+|*************************************************************************/
+bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep )
+{
+ bool bRet = true;
+
+ SWRECTFN( this )
+
+ // --> OD 2004-10-14 #i26745# - format row and cell frames of table
+ {
+ this->Lower()->_InvalidatePos();
+ // --> OD 2005-03-30 #i43913# - correction:
+ // call method <lcl_InnerCalcLayout> with first lower.
+ lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
+ // <--
+ }
+ // <--
+
+ //Um die Positionen der Zellen mit der CutPos zu vergleichen muessen sie
+ //ausgehend von der Tabelle nacheinander berechnet werden. Sie koennen
+ //wg. Positionsaenderungen der Tabelle durchaus ungueltig sein.
+ SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower());
+ if( !pRow )
+ return bRet;
+
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ sal_uInt16 nRowCount = 0; // pRow currently points to the first row
+
+ SwTwips nRemainingSpaceForLastRow =
+ (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() );
+ nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)();
+
+ //
+ // Make pRow point to the line that does not fit anymore:
+ //
+ while( pRow->GetNext() &&
+ nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() +
+ (IsCollapsingBorders() ?
+ pRow->GetBottomLineSize() :
+ 0 ) ) )
+ {
+ if( bTryToSplit || !pRow->IsRowSpanLine() ||
+ 0 != (pRow->Frm().*fnRect->fnGetHeight)() )
+ ++nRowCount;
+ nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)();
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ }
+
+ //
+ // bSplitRowAllowed: Row may be split according to its attributes.
+ // bTryToSplit: Row will never be split if bTryToSplit = false.
+ // This can either be passed as a parameter, indicating
+ // that we are currently doing the second try to split the
+ // table, or it will be set to falseunder certain
+ // conditions that are not suitable for splitting
+ // the row.
+ //
+ bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
+
+ // --> FME 2004-06-03 #i29438#
+ // --> OD 2004-10-04 #i26945# - Floating screen objects no longer forbid
+ // a splitting of the table row.
+ // Special DoNotSplit case 1:
+ // Search for sections inside pRow:
+ //
+ if ( lcl_FindSectionsInRow( *pRow ) )
+ {
+ bTryToSplit = false;
+ }
+ // <--
+
+ // --> FME 2004-06-07 #i29771#
+ // To avoid loops, we do some checks before actually trying to split
+ // the row. Maybe we should keep the next row in this table.
+ // Note: This is only done if we are at the beginning of our upper
+ bool bKeepNextRow = false;
+ if ( nRowCount < nRepeat )
+ {
+ //
+ // First case: One of the repeated headline does not fit to the page anymore.
+ // At least one more non-heading row has to stay in this table in
+ // order to avoid loops:
+ //
+ OSL_ENSURE( !GetIndPrev(), "Table is supposed to be at beginning" );
+ bKeepNextRow = true;
+ }
+ else if ( !GetIndPrev() && nRepeat == nRowCount )
+ {
+ //
+ // Second case: The first non-headline row does not fit to the page.
+ // If it is not allowed to be split, or it contains a sub-row that
+ // is not allowed to be split, we keep the row in this table:
+ //
+ if ( bTryToSplit && bSplitRowAllowed )
+ {
+ // Check if there are (first) rows inside this row,
+ // which are not allowed to be split.
+ SwCellFrm* pLowerCell = pRow ? (SwCellFrm*)pRow->Lower() : 0;
+ while ( pLowerCell )
+ {
+ if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() )
+ {
+ const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower();
+ if ( !pLowerRow->IsRowSplitAllowed() &&
+ (pLowerRow->Frm().*fnRect->fnGetHeight)() >
+ nRemainingSpaceForLastRow )
+ {
+ bKeepNextRow = true;
+ break;
+ }
+ }
+ pLowerCell = (SwCellFrm*)pLowerCell->GetNext();
+ }
+ }
+ else
+ bKeepNextRow = true;
+ }
+
+ //
+ // Better keep the next row in this table:
+ //
+ if ( bKeepNextRow )
+ {
+ pRow = GetFirstNonHeadlineRow();
+ if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() )
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ if ( pRow )
+ {
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+ ++nRowCount;
+ }
+ }
+
+ //
+ // No more row to split or to move to follow table:
+ //
+ if ( !pRow )
+ return bRet;
+
+ //
+ // We try to split the row if
+ // - the attributes of the row are set accordingly and
+ // - we are allowed to do so
+ // - the it should not keep with the next row
+ //
+ bSplitRowAllowed = bSplitRowAllowed && bTryToSplit &&
+ ( !bTableRowKeep ||
+ !pRow->ShouldRowKeepWithNext() );
+
+ // Adjust pRow according to the keep-with-next attribute:
+ if ( !bSplitRowAllowed && bTableRowKeep )
+ {
+ SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev());
+ SwRowFrm* pOldRow = pRow;
+ while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
+ nRowCount > nRepeat )
+ {
+ pRow = pTmpRow;
+ --nRowCount;
+ pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev());
+ }
+
+ // loop prevention
+ if ( nRowCount == nRepeat && !GetIndPrev())
+ {
+ pRow = pOldRow;
+ }
+ }
+
+ //
+ // If we do not indent to split pRow, we check if we are
+ // allowed to move pRow to a follow. Otherwise we return
+ // false, indicating an error
+ //
+ if ( !bSplitRowAllowed )
+ {
+ SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
+ if ( pRow == pFirstNonHeadlineRow )
+ return false;
+
+ // --> OD 2008-10-21 #i91764#
+ // Ignore row span lines
+ SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
+ while ( pTmpRow && pTmpRow->IsRowSpanLine() )
+ {
+ pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext());
+ }
+ if ( !pTmpRow || pRow == pTmpRow )
+ {
+ return false;
+ }
+ // <--
+ }
+
+ //
+ // Build follow table if not already done:
+ //
+ sal_Bool bNewFollow;
+ SwTabFrm *pFoll;
+ if ( GetFollow() )
+ {
+ pFoll = GetFollow();
+ bNewFollow = sal_False;
+ }
+ else
+ {
+ bNewFollow = sal_True;
+ pFoll = new SwTabFrm( *this );
+
+ //
+ // We give the follow table an initial width.
+ //
+ (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() );
+ (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() );
+ (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() );
+
+ //
+ // Insert the new follow table
+ //
+ pFoll->InsertBehind( GetUpper(), this );
+
+ //
+ // Repeat the headlines.
+ //
+ for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount )
+ {
+ // Insert new headlines:
+ bDontCreateObjects = sal_True; //frmtool
+ SwRowFrm* pHeadline = new SwRowFrm(
+ *GetTable()->GetTabLines()[ nRowCount ], this );
+ pHeadline->SetRepeatedHeadline( true );
+ bDontCreateObjects = sal_False;
+ pHeadline->InsertBefore( pFoll, 0 );
+
+ SwPageFrm *pPage = pHeadline->FindPageFrm();
+ const SwSpzFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts();
+ if( pTbl->Count() )
+ {
+ sal_uLong nIndex;
+ SwCntntFrm* pFrm = pHeadline->ContainsCntnt();
+ while( pFrm )
+ {
+ nIndex = pFrm->GetNode()->GetIndex();
+ AppendObjs( pTbl, nIndex, pFrm, pPage );
+ pFrm = pFrm->GetNextCntntFrm();
+ if( !pHeadline->IsAnLower( pFrm ) )
+ break;
+ }
+ }
+ }
+ }
+
+ SwRowFrm* pLastRow = 0; // will point to the last remaining line in master
+ SwRowFrm* pFollowRow = 0; // points to either the follow flow line of the
+ // first regular line in the follow
+
+ if ( bSplitRowAllowed )
+ {
+ // If the row that does not fit anymore is allowed
+ // to be split, the next row has to be moved to the follow table.
+ pLastRow = pRow;
+ pRow = static_cast<SwRowFrm*>(pRow->GetNext());
+
+ // new follow flow line for last row of master table
+ pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false );
+ }
+ else
+ {
+ pFollowRow = pRow;
+
+ // NEW TABLES
+ // check if we will break a row span by moving pFollowRow to the follow:
+ // In this case we want to reformat the last line.
+ const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower());
+ while ( pCellFrm )
+ {
+ if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
+ {
+ pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev());
+ break;
+ }
+
+ pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext());
+ }
+
+ // new follow flow line for last row of master table
+ if ( pLastRow )
+ pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
+ }
+
+ SwTwips nRet = 0;
+
+ //Optimierung beim neuen Follow braucht's kein Paste und dann kann
+ //das Optimierte Insert verwendet werden (nur dann treten gluecklicher weise
+ //auch groessere Mengen von Rows auf).
+ if ( bNewFollow )
+ {
+ SwFrm* pNxt = 0;
+ SwFrm* pInsertBehind = pFoll->GetLastLower();
+
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nRet += (pRow->Frm().*fnRect->fnGetHeight)();
+ // The footnotes do not have to be moved, this is done in the
+ // MoveFwd of the follow table!!!
+ pRow->Remove();
+ pRow->InsertBehind( pFoll, pInsertBehind );
+ pRow->_InvalidateAll();
+ pInsertBehind = pRow;
+ pRow = static_cast<SwRowFrm*>(pNxt);
+ }
+ }
+ else
+ {
+ SwFrm* pNxt = 0;
+ SwFrm* pPasteBefore = HasFollowFlowLine() ?
+ pFollowRow->GetNext() :
+ pFoll->GetFirstNonHeadlineRow();
+
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nRet += (pRow->Frm().*fnRect->fnGetHeight)();
+
+ // The footnotes have to be moved:
+ lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
+
+ pRow->Remove();
+ pRow->Paste( pFoll, pPasteBefore );
+
+ pRow->CheckDirChange();
+ pRow = static_cast<SwRowFrm*>(pNxt);
+ }
+ }
+
+ Shrink( nRet );
+
+ // we rebuild the last line to assure that it will be fully formatted
+ if ( pLastRow )
+ {
+ // recalculate the split line
+ bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow );
+
+ // NEW TABLES
+ // check if each cell in the row span line has a good height
+ if ( bRet && pFollowRow->IsRowSpanLine() )
+ lcl_AdjustRowSpanCells( pFollowRow );
+
+ // We The RowSplitLine stuff did not work. In this case we conceal the split error:
+ if ( !bRet && !bSplitRowAllowed )
+ {
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+bool SwTabFrm::Join()
+{
+ OSL_ENSURE( !HasFollowFlowLine(), "Joining follow flow line" );
+
+ SwTabFrm *pFoll = GetFollow();
+
+ if ( !pFoll->IsJoinLocked() )
+ {
+ SWRECTFN( this )
+ pFoll->Cut(); //Erst ausschneiden um unuetze Benachrichtigungen zu
+ //minimieren.
+
+ SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(),
+ *pNxt;
+
+ SwFrm* pPrv = GetLastLower();
+
+ SwTwips nHeight = 0; //Gesamthoehe der eingefuegten Zeilen als Return.
+ while ( pRow )
+ {
+ pNxt = pRow->GetNext();
+ nHeight += (pRow->Frm().*fnRect->fnGetHeight)();
+ pRow->Remove();
+ pRow->_InvalidateAll();
+ pRow->InsertBehind( this, pPrv );
+ pRow->CheckDirChange();
+ pPrv = pRow;
+ pRow = pNxt;
+ }
+
+ SetFollow( pFoll->GetFollow() );
+ SetFollowFlowLine( pFoll->HasFollowFlowLine() );
+ delete pFoll;
+
+ Grow( nHeight );
+ }
+
+ return true;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::MakeAll()
+|*
+|*************************************************************************/
+void MA_FASTCALL SwInvalidatePositions( SwFrm *pFrm, long nBottom )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ SWRECTFN( pFrm )
+ do
+ { pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ if( pFrm->IsLayoutFrm() )
+ {
+ if ( ((SwLayoutFrm*)pFrm)->Lower() )
+ {
+ ::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom);
+ // --> OD 2004-11-05 #i26945#
+ ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) );
+ // <--
+ }
+ }
+ else
+ pFrm->Prepare( PREP_ADJUST_FRM );
+ pFrm = pFrm->GetNext();
+ } while ( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
+}
+
+void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ SWRECTFN( pFrm )
+ do
+ {
+ pFrm->_InvalidatePos();
+ pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ if( pFrm->IsLayoutFrm() )
+ {
+ // NEW TABLES
+ SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm);
+ SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
+ if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
+ {
+ pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
+ pToInvalidate->_InvalidatePos();
+ pToInvalidate->_InvalidateSize();
+ pToInvalidate->_InvalidatePrt();
+ }
+
+ if ( pToInvalidate->Lower() )
+ ::SwInvalidateAll( pToInvalidate->Lower(), nBottom);
+ }
+ else
+ pFrm->Prepare( PREP_CLEAR );
+
+ pFrm = pFrm->GetNext();
+ } while ( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm )
+{
+ pLayFrm->_InvalidatePrt();
+ pLayFrm->_InvalidateSize();
+ pLayFrm->SetCompletePaint();
+
+ SwFrm* pFrm = pLayFrm->Lower();
+
+ while ( pFrm )
+ {
+ if ( pFrm->IsLayoutFrm() )
+ lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm );
+ else
+ {
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidateSize();
+ pFrm->SetCompletePaint();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+}
+// <-- collapsing
+
+bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave,
+ long nBottom, bool bSkipRowSpanCells )
+{
+ if ( !pLay )
+ return sal_True;
+
+ // LONG_MAX == nBottom means we have to calculate all
+ bool bAll = LONG_MAX == nBottom;
+ bool bRet = sal_False;
+ SwCntntFrm *pCnt = pLay->ContainsCntnt();
+ SWRECTFN( pLay )
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+ const SwModify* pLoopControlCond = 0;
+
+ while ( pCnt && pDontLeave->IsAnLower( pCnt ) )
+ {
+ // --> OD 2004-11-23 #115759# - check, if a format of content frame is
+ // possible. Thus, 'copy' conditions, found at the beginning of
+ // <SwCntntFrm::MakeAll(..)>, and check these.
+ const bool bFormatPossible = !pCnt->IsJoinLocked() &&
+ ( !pCnt->IsTxtFrm() ||
+ !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) &&
+ ( pCnt->IsFollow() || !StackHack::IsLocked() );
+
+ // NEW TABLES
+ bool bSkipContent = false;
+ if ( bSkipRowSpanCells && pCnt->IsInTab() )
+ {
+ const SwFrm* pCell = pCnt->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() )
+ bSkipContent = true;
+ }
+
+ if ( bFormatPossible && !bSkipContent )
+ {
+ bRet |= !pCnt->IsValid();
+ // --> OD 2004-10-06 #i26945# - no extra invalidation of floating
+ // screen objects needed.
+ // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
+ // <--
+ pCnt->Calc();
+ // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
+ // to format the floating screen objects
+ // --> OD 2005-05-03 #i46941# - frame has to be valid
+ // Note: frame could be invalid after calling its format, if it's locked.
+ OSL_ENSURE( !pCnt->IsTxtFrm() ||
+ pCnt->IsValid() ||
+ static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(),
+ "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." );
+ if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
+ {
+ // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame to
+ // the object formatter
+ if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
+ *(pCnt->FindPageFrm()) ) )
+ // <--
+ {
+ if ( pCnt->GetRegisteredIn() == pLoopControlCond )
+ ++nLoopControlRuns;
+ else
+ {
+ nLoopControlRuns = 0;
+ pLoopControlCond = pCnt->GetRegisteredIn();
+ }
+
+ if ( nLoopControlRuns < nLoopControlMax )
+ {
+ // restart format with first content
+ pCnt = pLay->ContainsCntnt();
+ continue;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_FAIL( "LoopControl in SwCntntFrm::CalcLowers" )
+#endif
+ }
+ }
+ pCnt->GetUpper()->Calc();
+ }
+ // <--
+ if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 )
+ break;
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ return bRet;
+}
+
+// --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
+// that only row and cell frames are formatted.
+sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
+ long nBottom,
+ bool _bOnlyRowsAndCells )
+{
+ // LONG_MAX == nBottom means we have to calculate all
+ sal_Bool bAll = LONG_MAX == nBottom;
+ sal_Bool bRet = sal_False;
+ const SwFrm* pOldUp = pFrm->GetUpper();
+ SWRECTFN( pFrm )
+ do
+ {
+ // --> OD 2004-10-15 #i26945# - parameter <_bOnlyRowsAndCells> controls,
+ // if only row and cell frames are formatted.
+ if ( pFrm->IsLayoutFrm() &&
+ ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) )
+ // <--
+ {
+ // --> FME 2006-02-23 #130744# An invalid locked table frame will
+ // not be calculated => It will not become valid =>
+ // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
+ bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() );
+ // <--
+ pFrm->Calc();
+ if( static_cast<SwLayoutFrm*>(pFrm)->Lower() )
+ bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom);
+
+ // NEW TABLES
+ SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
+ if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
+ {
+ SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
+ bRet |= !rToCalc.IsValid();
+ rToCalc.Calc();
+ if ( rToCalc.Lower() )
+ bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom);
+ }
+ }
+ pFrm = pFrm->GetNext();
+ } while( pFrm &&
+ ( bAll ||
+ (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 )
+ && pFrm->GetUpper() == pOldUp );
+ return bRet;
+}
+
+void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom )
+{
+ // --> OD 2004-10-05 #i26945# - For correct appliance of the 'straightforward
+ // object positioning process, it's needed to notify that the page frame,
+ // on which the given layout frame is in, is in its layout process.
+ SwPageFrm* pPageFrm = rRow.FindPageFrm();
+ if ( pPageFrm && !pPageFrm->IsLayoutInProgress() )
+ pPageFrm->SetLayoutInProgress( true );
+ else
+ pPageFrm = 0L;
+ // <--
+
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_1 = 0;
+ sal_uInt16 nLoopControlStage_1 = 0;
+ const sal_uInt16 nLoopControlMax = 10;
+
+ bool bCheck = true;
+ do
+ {
+ // FME 2007-08-30 #i81146# new loop control
+ sal_uInt16 nLoopControlRuns_2 = 0;
+ sal_uInt16 nLoopControlStage_2 = 0;
+
+ while( lcl_InnerCalcLayout( &rRow, nBottom ) )
+ {
+ if ( ++nLoopControlRuns_2 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
+ OSL_ENSURE( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
+ OSL_ENSURE( 2 > nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
+#endif
+ rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ );
+ nLoopControlRuns_2 = 0;
+ if( nLoopControlStage_2 > 2 )
+ break;
+ }
+
+ bCheck = true;
+ }
+
+ if( bCheck )
+ {
+ // --> OD 2004-11-23 #115759# - force another format of the
+ // lowers, if at least one of it was invalid.
+ bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true );
+ // <--
+
+ // NEW TABLES
+ // First we calculate the cells with row span of < 1, afterwards
+ // all cells with row span of > 1:
+ for ( int i = 0; i < 2; ++i )
+ {
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower());
+ while ( pCellFrm )
+ {
+ const bool bCalc = 0 == i ?
+ pCellFrm->GetLayoutRowSpan() < 1 :
+ pCellFrm->GetLayoutRowSpan() > 1;
+
+ if ( bCalc )
+ {
+ SwCellFrm& rToRecalc = 0 == i ?
+ const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) :
+ *pCellFrm;
+ bCheck |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false );
+ }
+
+ pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
+ }
+ }
+
+ if ( bCheck )
+ {
+ if ( ++nLoopControlRuns_1 > nLoopControlMax )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
+ OSL_ENSURE( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
+ OSL_ENSURE( 2 > nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
+#endif
+ rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ );
+ nLoopControlRuns_1 = 0;
+ if( nLoopControlStage_1 > 2 )
+ break;
+ }
+
+ continue;
+ }
+ }
+ break;
+ } while( true );
+
+ // --> OD 2004-10-05 #i26945#
+ if ( pPageFrm )
+ pPageFrm->SetLayoutInProgress( false );
+ // <--
+}
+
+void MA_FASTCALL lcl_RecalcTable( SwTabFrm& rTab,
+ SwLayoutFrm *pFirstRow,
+ SwLayNotify &rNotify )
+{
+ if ( rTab.Lower() )
+ {
+ if ( !pFirstRow )
+ {
+ pFirstRow = (SwLayoutFrm*)rTab.Lower();
+ rNotify.SetLowersComplete( sal_True );
+ }
+ ::SwInvalidatePositions( pFirstRow, LONG_MAX );
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX );
+ }
+}
+
+// This is a new function to check the first condition whether
+// a tab frame may move backward. It replaces the formerly used
+// GetIndPrev(), which did not work correctly for #i5947#
+bool lcl_NoPrev( const SwFrm& rFrm )
+{
+ // --> OD 2007-09-04 #i79774#, #b6596954#
+ // skip empty sections on investigation of direct previous frame.
+ // use information, that at least one empty section is skipped in the following code.
+ bool bSkippedDirectPrevEmptySection( false );
+ if ( rFrm.GetPrev() )
+ {
+ const SwFrm* pPrev( rFrm.GetPrev() );
+ while ( pPrev &&
+ pPrev->IsSctFrm() &&
+ !dynamic_cast<const SwSectionFrm*>(pPrev)->GetSection() )
+ {
+ pPrev = pPrev->GetPrev();
+ bSkippedDirectPrevEmptySection = true;
+ }
+ if ( pPrev )
+ {
+ return false;
+ }
+ }
+
+ if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) ||
+ ( bSkippedDirectPrevEmptySection &&
+ ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) )
+ {
+ return true;
+ }
+ // <--
+
+ // I do not have a direct prev, but I have an indirect prev.
+ // In section frames I have to check if I'm located inside
+ // the first column:
+ if ( rFrm.IsInSct() )
+ {
+ const SwFrm* pSct = rFrm.GetUpper();
+ if ( pSct && pSct->IsColBodyFrm() &&
+ (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
+ {
+ const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev();
+ if ( pPrevCol )
+ // I'm not inside the first column and do not have a direct
+ // prev. I can try to go backward.
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#define KEEPTAB ( !GetFollow() && !IsFollow() )
+
+// --> OD 2005-09-28 #b6329202# - helper method to find next content frame of
+// a table frame and format it to assure keep attribute.
+// method return true, if a next content frame is formatted.
+// Precondition: The given table frame hasn't a follow and isn't a follow.
+SwFrm* lcl_FormatNextCntntForKeep( SwTabFrm* pTabFrm )
+{
+ // find next content, table or section
+ SwFrm* pNxt = pTabFrm->FindNext();
+
+ // skip empty sections
+ while ( pNxt && pNxt->IsSctFrm() &&
+ !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
+ {
+ pNxt = pNxt->FindNext();
+ }
+
+ // if found next frame is a section, get its first content.
+ if ( pNxt && pNxt->IsSctFrm() )
+ {
+ pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny();
+ }
+
+ // format found next frame.
+ // if table frame is inside another table, method <SwFrm::MakeAll()> is
+ // called to avoid that the superior table frame is formatted.
+ if ( pNxt )
+ {
+ if ( pTabFrm->GetUpper()->IsInTab() )
+ pNxt->MakeAll();
+ else
+ pNxt->Calc();
+ }
+
+ return pNxt;
+}
+
+void SwTabFrm::MakeAll()
+{
+ if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
+ return;
+
+ if ( HasFollow() )
+ {
+ SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
+ OSL_ENSURE( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
+ "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" );
+ if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
+ return;
+ }
+
+ PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
+
+ LockJoin(); //Ich lass mich nicht unterwegs vernichten.
+ SwLayNotify aNotify( this ); //uebernimmt im DTor die Benachrichtigung
+ // If pos is invalid, we have to call a SetInvaKeep at aNotify.
+ // Otherwise the keep atribute would not work in front of a table.
+ const sal_Bool bOldValidPos = GetValidPosFlag();
+
+ //Wenn mein direkter Nachbar gleichzeitig mein Follow ist
+ //verleibe ich mir das Teil ein.
+ // OD 09.04.2003 #108698# - join all follows, which are placed on the
+ // same page/column.
+ // OD 29.04.2003 #109213# - join follow, only if join for the follow
+ // is not locked. Otherwise, join will not be performed and this loop
+ // will be endless.
+ while ( GetNext() && GetNext() == GetFollow() &&
+ !GetFollow()->IsJoinLocked()
+ )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+
+ // The bRemoveFollowFlowLinePending is set if the split attribute of the
+ // last line is set:
+ if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
+ {
+ if ( RemoveFollowFlowLine() )
+ Join();
+ SetRemoveFollowFlowLinePending( sal_False );
+ }
+
+ if ( bResizeHTMLTable ) //Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes
+ {
+ bResizeHTMLTable = sal_False;
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if ( pLayout )
+ bCalcLowers = pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ }
+
+
+ sal_Bool bMakePage = sal_True; //solange sal_True kann eine neue Seite
+ //angelegt werden (genau einmal)
+ sal_Bool bMovedBwd = sal_False; //Wird sal_True wenn der Frame zurueckfliesst
+ sal_Bool bMovedFwd = sal_False; //solange sal_False kann der Frm zurueck-
+ //fliessen (solange, bis er einmal
+ //vorwaerts ge'moved wurde).
+ sal_Bool bSplit = sal_False; //Wird sal_True wenn der Frm gesplittet wurde.
+ const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count();
+ sal_Bool bMoveable;
+ const sal_Bool bFly = IsInFly();
+
+ SwBorderAttrAccess *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ const SwBorderAttrs *pAttrs = pAccess->Get();
+
+ // The beloved keep attribute
+ const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
+
+ // All rows should keep together
+ // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
+ const bool bDontSplit = !IsFollow() &&
+ ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
+
+ // The number of repeated headlines
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+
+ // This flag indicates that we are allowed to try to split the
+ // table rows.
+ bool bTryToSplit = true;
+
+ // --> FME 2006-02-16 #131283#
+ // Indicates that two individual rows may keep together, based on the keep
+ // attribute set at the first paragraph in the first cell.
+ const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP);
+
+ // The Magic Move: Used for the table row keep feature.
+ // If only the last row of the table wants to keep (implicitely by setting
+ // keep for the first paragraph in the first cell), and this table does
+ // not have a next, the last line will be cut. Loop prevention: Only
+ // one try.
+ bool bLastRowHasToMoveToFollow = false;
+ bool bLastRowMoveNoMoreTries = false;
+
+ // Join follow table, if this table is not allowed to split:
+ if ( bDontSplit )
+ {
+ while ( GetFollow() && !GetFollow()->IsJoinLocked() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ // Join follow table, if this does not have enough (repeated) lines:
+ if ( nRepeat )
+ {
+ if( GetFollow() && !GetFollow()->IsJoinLocked() &&
+ 0 == GetFirstNonHeadlineRow() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ // Join follow table, if last row of this table should keep:
+ if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
+ {
+ const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
+ if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ Join();
+ }
+ }
+
+ //Einen Frischling moven wir gleich schon einmal vorwaerts...
+ if ( !Frm().Top() && IsFollow() )
+ {
+ SwFrm *pPre = GetPrev();
+ if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
+ {
+ if ( !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+ bMovedFwd = sal_True;
+ }
+ }
+
+ int nUnSplitted = 5; // Just another loop control :-(
+ SWRECTFN( this )
+ while ( !bValidPos || !bValidSize || !bValidPrtArea )
+ {
+ if ( sal_True == (bMoveable = IsMoveable()) )
+ if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
+ {
+ bMovedFwd = sal_True;
+ bCalcLowers = sal_True;
+ // --> OD 2009-08-12 #i99267#
+ // reset <bSplit> after forward move to assure that follows
+ // can be joined, if further space is available.
+ bSplit = sal_False;
+ // <--
+ }
+
+ Point aOldPos( (Frm().*fnRect->fnGetPos)() );
+ MakePos();
+
+ if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
+ {
+ if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
+ {
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if( pLayout )
+ {
+ delete pAccess;
+ bCalcLowers |= pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+
+ bValidPrtArea = sal_False;
+ aNotify.SetLowersComplete( sal_False );
+ }
+ SwFrm *pPre;
+ if ( bKeep || (0 != (pPre = FindPrev()) &&
+ pPre->GetAttrSet()->GetKeep().GetValue()) )
+ {
+ bCalcLowers = sal_True;
+ // --> OD 2009-03-06 #i99267#
+ // reset <bSplit> after forward move to assure that follows
+ // can be joined, if further space is available.
+ bSplit = sal_False;
+ // <--
+ }
+ }
+
+ //Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese
+ //kleiner wird muss ggf. der Master angestossen werden um noetigenfalls
+ //die Zeile aufzunehmen.
+ long n1StLineHeight = 0;
+ if ( IsFollow() )
+ {
+ SwFrm* pFrm = GetFirstNonHeadlineRow();
+ if ( pFrm )
+ n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
+ }
+
+ if ( !bValidSize || !bValidPrtArea )
+ {
+ const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
+ const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
+ const Point aOldPrtPos = (Prt().*fnRect->fnGetPos)();
+ Format( pAttrs );
+
+ SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
+ if ( pLayout &&
+ ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
+ (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
+ {
+ delete pAccess;
+ bCalcLowers |= pLayout->Resize(
+ pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+ if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
+ aNotify.SetLowersComplete( sal_False );
+ }
+
+ //Wenn ich der erste einer Kette bin koennte ich mal sehen ob
+ //ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
+ //Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
+ //geflosssen sein.
+ if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
+ {
+ //Bei Follows muss der Master benachrichtigt
+ //werden. Der Follow muss nur dann Moven, wenn er leere Blaetter
+ //ueberspringen muss.
+ if ( IsFollow() )
+ {
+ //Nur wenn die Hoehe der ersten Zeile kleiner geworder ist.
+ SwFrm *pFrm = GetFirstNonHeadlineRow();
+ if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
+ {
+ SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
+ sal_Bool bDummy;
+ if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) )
+ pMaster->InvalidatePos();
+ }
+ }
+ SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0;
+ sal_Bool bReformat;
+ if ( MoveBwd( bReformat ) )
+ {
+ SWREFRESHFN( this )
+ bMovedBwd = sal_True;
+ aNotify.SetLowersComplete( sal_False );
+ if ( bFtnsInDoc )
+ MoveLowerFtns( 0, pOldBoss, 0, sal_True );
+ if ( bReformat || bKeep )
+ {
+ long nOldTop = (Frm().*fnRect->fnGetTop)();
+ MakePos();
+ if( nOldTop != (Frm().*fnRect->fnGetTop)() )
+ {
+ SwHTMLTableLayout *pHTMLLayout =
+ GetTable()->GetHTMLTableLayout();
+ if( pHTMLLayout )
+ {
+ delete pAccess;
+ bCalcLowers |= pHTMLLayout->Resize(
+ pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
+ sal_False );
+
+ pAccess= new SwBorderAttrAccess(
+ SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+ }
+
+ bValidPrtArea = sal_False;
+ Format( pAttrs );
+ }
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ if ( bKeep && KEEPTAB )
+ {
+ // --> OD 2005-09-28 #b6329202#
+ // Consider case that table is inside another table,
+ // because it has to be avoided, that superior table
+ // is formatted.
+ // Thus, find next content, table or section
+ // and, if a section is found, get its first
+ // content.
+ if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() )
+ {
+ bValidPos = sal_False;
+ }
+ // <--
+ }
+ }
+ }
+ }
+
+ //Wieder ein Wert ungueltig? - dann nochmal das ganze...
+ if ( !bValidPos || !bValidSize || !bValidPrtArea )
+ continue;
+
+ // check, if calculation of table frame is ready.
+
+ /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom>
+ /// Introduce local variable and init it with the distance from the
+ /// table frame bottom to the bottom of the upper printing area.
+ /// Note: negative values denotes the situation that table frame doesn't
+ /// fit in its upper.
+
+ SwTwips nDistanceToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+
+ /// OD 23.10.2002 #103517# - In online layout try to grow upper of table
+ /// frame, if table frame doesn't fit in its upper.
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
+ {
+ if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
+ {
+ // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
+ nDistanceToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+ }
+ }
+
+ // If there is still some space left in the upper, we check if we
+ // can join some rows of the follow.
+ // Setting bLastRowHasToMoveToFollow to true means we want to force
+ // the table to be split! Only skip this if condition once.
+ if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
+ {
+ // OD 23.10.2002 - translate german commentary
+ // If there is space left in the upper printing area, join as for trial
+ // at least one further row of an existing follow.
+ if ( !bSplit && GetFollow() )
+ {
+ sal_Bool bDummy;
+ if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) )
+ {
+ SwFrm *pTmp = GetUpper();
+ SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
+ if ( bBrowseMode )
+ nDeadLine += pTmp->Grow( LONG_MAX, sal_True );
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
+ {
+ //
+ // First, we remove an existing follow flow line.
+ //
+ if ( HasFollowFlowLine() )
+ {
+ SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
+ RemoveFollowFlowLine();
+ // invalidate and rebuild last row
+ if ( pLastLine )
+ {
+ ::SwInvalidateAll( pLastLine, LONG_MAX );
+ SetRebuildLastLine( sal_True );
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
+ SetRebuildLastLine( sal_False );
+ }
+
+ SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
+
+ if ( !pRow || !pRow->GetNext() )
+ //Der Follow wird leer und damit ueberfluessig.
+ Join();
+
+ continue;
+ }
+
+ //
+ // If there is no follow flow line, we move the first
+ // row in the follow table to the master table.
+ //
+ SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
+
+ //Der Follow wird leer und damit ueberfluessig.
+ if ( !pRow )
+ {
+ Join();
+ continue;
+ }
+
+ const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
+ long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
+ SwFrm* pRowToMove = pRow;
+
+ while ( pRowToMove && nRowsToMove-- > 0 )
+ {
+ const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
+
+ SwFtnBossFrm *pOldBoss = 0;
+ if ( bMoveFtns )
+ pOldBoss = pRowToMove->FindFtnBossFrm( sal_True );
+
+ SwFrm* pNextRow = pRowToMove->GetNext();
+
+ if ( !pNextRow )
+ //Der Follow wird leer und damit ueberfluessig.
+ Join();
+ else
+ {
+ pRowToMove->Cut();
+ pRowToMove->Paste( this );
+ }
+
+ //Die Fussnoten verschieben!
+ if ( bMoveFtns )
+ if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns(
+ 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) )
+ GetUpper()->Calc();
+
+ pRowToMove = pNextRow;
+ }
+
+ if ( nOld != (Frm().*fnRect->fnGetHeight)() )
+ lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
+
+ continue;
+ }
+ }
+ }
+ else if ( KEEPTAB )
+ {
+ bool bFormat = false;
+ if ( bKeep )
+ bFormat = true;
+ else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
+ {
+ // We only want to give the last row one chance to move
+ // to the follow table. Set the flag as early as possible:
+ bLastRowMoveNoMoreTries = true;
+
+ // The last line of the table has to be cut off if:
+ // 1. The table does not want to keep with its next
+ // 2. The compatibility option is set and the table is allowed to split
+ // 3. We did not already cut off the last row
+ // 4. There is not break after attribute set at the table
+ // 5. There is no break before attribute set behind the table
+ // 6. There is no section change behind the table (see IsKeep)
+ // 7. The last table row wants to keep with its next.
+ const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
+ if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
+ pLastRow->ShouldRowKeepWithNext() )
+ bFormat = true;
+ }
+
+ if ( bFormat )
+ {
+ delete pAccess;
+
+ // --> OD 2005-09-28 #b6329202#
+ // Consider case that table is inside another table, because
+ // it has to be avoided, that superior table is formatted.
+ // Thus, find next content, table or section and, if a section
+ // is found, get its first content.
+ const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this );
+ // <--
+
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+
+ // The last row wants to keep with the frame behind the table.
+ // Check if the next frame is on a different page and valid.
+ // In this case we do a magic trick:
+ if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
+ {
+ bValidPos = sal_False;
+ bLastRowHasToMoveToFollow = true;
+ }
+ }
+ }
+
+ if ( IsValid() )
+ {
+ if ( bCalcLowers )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+ else if ( bONECalcLowers )
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bONECalcLowers = sal_False;
+ }
+ }
+ continue;
+ }
+
+ //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
+ //an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
+
+ //Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
+ //ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
+ //mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
+ //zwar mit aller Kraft.
+ if ( !bMoveable )
+ {
+ if ( bCalcLowers && IsValid() )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+ else if ( bONECalcLowers )
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bONECalcLowers = sal_False;
+ }
+
+ // It does not make sense to cut off the last line if we are
+ // not moveable:
+ bLastRowHasToMoveToFollow = false;
+
+ continue;
+ }
+
+ if ( bCalcLowers && IsValid() )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ if( !IsValid() )
+ continue;
+ }
+
+ //
+ // First try to split the table. Condition:
+ // 1. We have at least one non headline row
+ // 2. If this row wants to keep, we need an additional row
+ // 3. The table is allowed to split or we do not have an pIndPrev:
+ //
+ SwFrm* pIndPrev = GetIndPrev();
+ const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
+
+ if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
+ ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() ) &&
+ ( !bDontSplit || !pIndPrev ) )
+ {
+ // --> FME 2004-06-03 #i29438#
+ // Special DoNotSplit case:
+ // We better avoid splitting of a row frame if we are inside a columned
+ // section which has a height of 0, because this is not growable and thus
+ // all kinds of unexpected things could happen.
+ if ( IsInSct() &&
+ (FindSctFrm())->Lower()->IsColumnFrm() &&
+ 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)() )
+ {
+ bTryToSplit = false;
+ }
+ // <--
+
+ // 1. Try: bTryToSplit = true => Try to split the row.
+ // 2. Try: bTryToSplit = false => Split the table between the rows.
+ if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
+ {
+ SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
+ nDeadLine = (*fnRect->fnYInc)( nDeadLine,
+ GetUpper()->Grow( LONG_MAX, sal_True ) );
+
+ ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
+ bLowersFormatted = sal_True;
+ aNotify.SetLowersComplete( sal_True );
+
+ // One more check if its really necessary to split the table.
+ // 1. The table either has to exceed the deadline or
+ // 2. We explicitly want to cut off the last row.
+ if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
+ {
+ continue;
+ }
+
+ // Set to false again as early as possible.
+ bLastRowHasToMoveToFollow = false;
+
+ // --> FME 2005-08-03 #i52781#
+ // YaSC - Yet another special case:
+ // If our upper is inside a table cell which is not allowed
+ // to split, we do not try to split:
+ if ( GetUpper()->IsInTab() )
+ {
+ const SwFrm* pTmpRow = GetUpper();
+ while ( pTmpRow && !pTmpRow->IsRowFrm() )
+ pTmpRow = pTmpRow->GetUpper();
+ if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
+ continue;
+ }
+ // <--
+
+ sal_uInt16 nMinNumOfLines = nRepeat;
+
+ if ( bTableRowKeep )
+ {
+ const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
+ while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
+ {
+ ++nMinNumOfLines;
+ pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
+ }
+ // Check if all lines want to keep together and we
+ // have a pIndPrev. In this case we set nDeadLine
+ // to 0, forcing the table to move forward.
+ if ( !pTmpRow && pIndPrev )
+ nDeadLine = 0;
+ }
+
+ if ( !bTryToSplit )
+ ++nMinNumOfLines;
+
+ const SwTwips nBreakLine = (*fnRect->fnYInc)(
+ (Frm().*fnRect->fnGetTop)(),
+ (this->*fnRect->fnGetTopMargin)() +
+ lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
+
+ // Some more checks if we want to call the split algorithm or not:
+ // The repeating lines / keeping lines still fit into the upper or
+ // if we do not have an (in)direkt Prev, we split anyway.
+ if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
+ {
+ aNotify.SetLowersComplete( sal_False );
+ bSplit = sal_True;
+
+ //
+ // An existing follow flow line has to be removed.
+ //
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+
+ const bool bSplitError = !Split( nDeadLine, bTryToSplit, bTableRowKeep );
+ if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
+ --nUnSplitted;
+
+ // --> FME 2004-06-09 #i29771# Two tries to split the table:
+ // If an error occurred during splitting. We start a second
+ // try, this time without splitting of table rows.
+ if ( bSplitError )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ }
+
+ // --> FME 2005-02-10 #119477#
+ // If splitting the table was successfull or not,
+ // we do not want to have 'empty' follow tables.
+ if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
+ Join();
+ // <--
+
+
+ // We want to restore the situation before the failed
+ // split operation as good as possible. Therefore we
+ // do some more calculations. Note: Restricting this
+ // to nDeadLine may not be enough.
+ if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
+ {
+ lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
+ bValidPos = sal_False;
+ bTryToSplit = false;
+ continue;
+ }
+ // <--
+
+ bTryToSplit = !bSplitError;
+
+ //Damit es nicht zu Oszillationen kommt, muss der
+ //Follow gleich gueltig gemacht werden.
+ if ( GetFollow() )
+ {
+ // --> OD 2007-11-30 #i80924#
+ // After a successful split assure that the first row
+ // is invalid. When graphics are present, this isn't hold.
+ // Note: defect i80924 could also be fixed, if it is
+ // assured, that <SwLayNotify::bLowersComplete> is only
+ // set, if all lower are valid *and* are correct laid out.
+ if ( !bSplitError && GetFollow()->GetLower() )
+ {
+ GetFollow()->GetLower()->InvalidatePos();
+ }
+ // <--
+ SWRECTFNX( GetFollow() )
+
+ static sal_uInt8 nStack = 0;
+ if ( !StackHack::IsLocked() && nStack < 4 )
+ {
+ ++nStack;
+ StackHack aHack;
+ delete pAccess;
+
+ GetFollow()->MakeAll();
+
+ pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
+ pAttrs = pAccess->Get();
+
+ ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False);
+ // --> OD 2005-03-30 #i43913# - lock follow table
+ // to avoid its formatting during the format of
+ // its content.
+ const bool bOldJoinLock = GetFollow()->IsJoinLocked();
+ GetFollow()->LockJoin();
+ // <--
+ ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
+ (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
+ // --> OD 2005-03-30 #i43913#
+ // --> FME 2006-04-05 #i63632# Do not unlock the
+ // follow if it wasn't locked before.
+ if ( !bOldJoinLock )
+ GetFollow()->UnlockJoin();
+ // <--
+
+ if ( !GetFollow()->GetFollow() )
+ {
+ SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
+ if ( pNxt )
+ {
+ // OD 26.08.2003 #i18103# - no formatting
+ // of found next frame, if its a follow
+ // section of the 'ColLocked' section,
+ // the follow table is in.
+ bool bCalcNxt = true;
+ if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
+ {
+ SwSectionFrm* pSct = GetFollow()->FindSctFrm();
+ if ( pSct->IsColLocked() &&
+ pSct->GetFollow() == pNxt )
+ {
+ bCalcNxt = false;
+ }
+ }
+ if ( bCalcNxt )
+ {
+ pNxt->Calc();
+ }
+ }
+ }
+ --nStack;
+ }
+ else if ( GetFollow() == GetNext() )
+ ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False );
+ }
+ continue;
+ }
+ }
+ }
+
+ // Set to false again as early as possible.
+ bLastRowHasToMoveToFollow = false;
+
+ if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
+ GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
+ ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
+ ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
+ bMovedFwd = sal_False;
+
+ // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper
+ const SwFrm* pOldUpper = GetUpper();
+ // <--
+
+ //Mal sehen ob ich irgenwo Platz finde...
+ if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
+ bMakePage = sal_False;
+
+ // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper
+ if ( GetUpper() != pOldUpper )
+ {
+ bTryToSplit = true;
+ nUnSplitted = 5;
+ }
+ // <--
+
+ SWREFRESHFN( this )
+ bMovedFwd = bCalcLowers = sal_True;
+ aNotify.SetLowersComplete( sal_False );
+ if ( IsFollow() )
+ { //Um Oszillationen zu vermeiden sollte kein ungueltiger Master
+ //zurueckbleiben.
+ SwTabFrm *pTab = FindMaster();
+ if ( pTab->GetUpper() )
+ pTab->GetUpper()->Calc();
+ pTab->Calc();
+ pTab->SetLowersFormatted( sal_False );
+ }
+
+ //Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist
+ //verleibe ich mir das Teil ein.
+ if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
+ {
+ if ( HasFollowFlowLine() )
+ RemoveFollowFlowLine();
+ if ( GetFollow() )
+ Join();
+ }
+
+ if ( bMovedBwd && GetUpper() )
+ //Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig
+ //zu Painten, dass koennen wir uns jetzt nach dem hin und her
+ //fliessen sparen.
+ GetUpper()->ResetCompletePaint();
+
+ if ( bCalcLowers && IsValid() )
+ {
+ // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary
+ // and can cause layout loops, if table doesn't fit and isn't
+ // allowed to split.
+ SwTwips nDistToUpperPrtBottom =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
+ if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
+ {
+ lcl_RecalcTable( *this, 0, aNotify );
+ bLowersFormatted = sal_True;
+ bCalcLowers = sal_False;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ OSL_FAIL( "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
+ }
+#endif
+ // <--
+ }
+
+ } //while ( !bValidPos || !bValidSize || !bValidPrtArea )
+
+ //Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich
+ //bei der nachstbesten Gelegenheit vernichten.
+ if ( IsFollow() )
+ {
+ SwFrm *pPre = GetPrev();
+ if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
+ pPre->InvalidatePos();
+ }
+
+ bCalcLowers = bONECalcLowers = sal_False;
+ delete pAccess;
+ UnlockJoin();
+ if ( bMovedFwd || bMovedBwd || !bOldValidPos )
+ aNotify.SetInvaKeep();
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::CalcFlyOffsets()
+|*
+|* Beschreibung: Berechnet die Offsets, die durch FlyFrames
+|* entstehen.
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
+ long& rLeftOffset,
+ long& rRightOffset ) const
+{
+ sal_Bool bInvalidatePrtArea = sal_False;
+ const SwPageFrm *pPage = FindPageFrm();
+ const SwFlyFrm* pMyFly = FindFlyFrm();
+
+ // --> #108724# Page header/footer content doesn't have to wrap around
+ // floating screen objects
+
+ const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
+ const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
+ ( !IsInFtn() && 0 == FindFooterOrHeader() );
+ // <--
+
+ if ( pPage->GetSortedObjs() && bWrapAllowed )
+ {
+ SWRECTFN( this )
+ const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
+ long nPrtPos = (Frm().*fnRect->fnGetTop)();
+ nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
+ SwRect aRect( Frm() );
+ long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
+ if( nYDiff > 0 )
+ (aRect.*fnRect->fnAddBottom)( -nYDiff );
+ for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
+ // --> OD 2004-10-07 #i26945# - correction of conditions,
+ // if Writer fly frame has to be considered:
+ // - no need to check, if top of Writer fly frame differs
+ // from WEIT_WECH, because its also check, if the Writer
+ // fly frame rectangle overlaps with <aRect>
+ // - no check, if bottom of anchor frame is prior the top of
+ // the table, because Writer fly frames can be negative positioned.
+ // - correct check, if the Writer fly frame is an lower of the
+ // table, because table lines/rows can split and a at-character
+ // anchored Writer fly frame could be positioned in the follow
+ // flow line.
+ // - add condition, that an existing anchor character text frame
+ // has to be on the same page as the table.
+ // E.g., it could happen, that the fly frame is still registered
+ // at the page frame, the table is on, but it's anchor character
+ // text frame has already changed its page.
+ const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
+ bool bConsiderFly =
+ // --> OD 2005-04-06 #i46807# - do not consider invalid
+ // Writer fly frames.
+ pFly->IsValid() &&
+ // <--
+ // fly anchored at character
+ pFly->IsFlyAtCntFrm() &&
+ // fly overlaps with corresponding table rectangle
+ aFlyRect.IsOver( aRect ) &&
+ // fly isn't lower of table and
+ // anchor character frame of fly isn't lower of table
+ ( !IsAnLower( pFly ) &&
+ ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
+ // table isn't lower of fly
+ !pFly->IsAnLower( this ) &&
+ // fly is lower of fly, the table is in
+ // --> OD 2005-05-31 #123274# - correction:
+ // assure that fly isn't a lower of a fly, the table isn't in.
+ // E.g., a table in the body doesn't wrap around a graphic,
+ // which is inside a frame.
+ ( ( !pMyFly ||
+ pMyFly->IsAnLower( pFly ) ) &&
+ pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
+ // <--
+ // anchor frame not on following page
+ pPage->GetPhyPageNum() >=
+ pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
+ // anchor character text frame on same page
+ ( !pAnchorCharFrm ||
+ pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
+ pPage->GetPhyPageNum() );
+
+ if ( bConsiderFly )
+ {
+ const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
+ const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
+
+ if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
+ // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set,
+ // we want to consider the fly if it is located in the header and
+ // the table is located in the body:
+ ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
+ bConsiderFly = false;
+ // <--
+ }
+
+ if ( bConsiderFly )
+ // <--
+ {
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
+ if ( SURROUND_NONE == rSur.GetSurround() )
+ {
+ long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
+ if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
+ nPrtPos = nBottom;
+ bInvalidatePrtArea = sal_True;
+ }
+ if ( (SURROUND_RIGHT == rSur.GetSurround() ||
+ SURROUND_PARALLEL == rSur.GetSurround())&&
+ text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
+ {
+ const long nWidth = (*fnRect->fnXDiff)(
+ (aFlyRect.*fnRect->fnGetRight)(),
+ (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
+ rLeftOffset = Max( rLeftOffset, nWidth );
+ bInvalidatePrtArea = sal_True;
+ }
+ if ( (SURROUND_LEFT == rSur.GetSurround() ||
+ SURROUND_PARALLEL == rSur.GetSurround())&&
+ text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
+ {
+ const long nWidth = (*fnRect->fnXDiff)(
+ (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
+ (aFlyRect.*fnRect->fnGetLeft)() );
+ rRightOffset = Max( rRightOffset, nWidth );
+ bInvalidatePrtArea = sal_True;
+ }
+ }
+ }
+ }
+ rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
+ }
+
+ return bInvalidatePrtArea;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "TabFrm::Format, pAttrs ist 0." );
+
+ SWRECTFN( this )
+ if ( !bValidSize )
+ {
+ long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
+ (Frm().*fnRect->fnGetWidth)();
+ if( nDiff )
+ (aFrm.*fnRect->fnAddRight)( nDiff );
+ }
+
+ //VarSize ist immer die Hoehe.
+ //Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer
+ //cntfrms (sie MakePrtArea() von diesen).
+
+ SwTwips nUpper = CalcUpperSpace( pAttrs );
+
+ //Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten:
+ //1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen
+ //2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind
+ // rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die
+ // Raender vor.
+ long nTmpRight = -1000000,
+ nLeftOffset = 0;
+ if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
+ bValidPrtArea = sal_False;
+ long nRightOffset = Max( 0L, nTmpRight );
+
+ SwTwips nLower = pAttrs->CalcBottomLine();
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( IsCollapsingBorders() )
+ nLower += GetBottomLineSize();
+ // <-- collapsing
+
+ if ( !bValidPrtArea )
+ { bValidPrtArea = sal_True;
+
+ //Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender
+ //sind entsprechend einzustellen.
+ //Mindestraender werden von Umrandung und Schatten vorgegeben.
+ //Die Rander werden so eingestellt, dass die PrtArea nach dem
+ //angegebenen Adjustment im Frm ausgerichtet wird.
+ //Wenn das Adjustment 0 ist, so werden die Rander anhand des
+ //Randattributes eingestellt.
+
+ const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
+ const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)();
+
+ // OD 14.03.2003 #i9040# - adjust variable names.
+ const SwTwips nLeftLine = pAttrs->CalcLeftLine();
+ const SwTwips nRightLine = pAttrs->CalcRightLine();
+
+ //Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo
+ //'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so
+ //bezieht sie sich in der BrowseView auf die Bildschirmbreite.
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ // OD 14.03.2003 #i9040# - adjust variable name.
+ const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True );
+
+ sal_Bool bCheckBrowseWidth = sal_False;
+
+ // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
+ SwTwips nLeftSpacing = 0;
+ SwTwips nRightSpacing = 0;
+ switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
+ {
+ case text::HoriOrientation::LEFT:
+ {
+ // left indent:
+ nLeftSpacing = nLeftLine + nLeftOffset;
+ // OD 06.03.2003 #i9040# - correct calculation of right indent:
+ // - Consider right indent given by right line attributes.
+ // - Consider negative right indent.
+ // wished right indent determined by wished table width and
+ // left offset given by surround fly frames on the left:
+ const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
+ if ( nRightOffset > 0 )
+ {
+ // surrounding fly frames on the right
+ // -> right indent is maximun of given right offset
+ // and wished right offset.
+ nRightSpacing = nRightLine + Max( nRightOffset, nWishRight );
+ }
+ else
+ {
+ // no surrounding fly frames on the right
+ // If intrinsic right indent (intrinsic means not considering
+ // determined left indent) is negative,
+ // then hold this intrinsic indent,
+ // otherwise non negative wished right indent is hold.
+ nRightSpacing = nRightLine +
+ ( ( (nWishRight+nLeftOffset) < 0 ) ?
+ (nWishRight+nLeftOffset) :
+ Max( 0L, nWishRight ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::RIGHT:
+ {
+ // right indent:
+ nRightSpacing = nRightLine + nRightOffset;
+ // OD 06.03.2003 #i9040# - correct calculation of left indent:
+ // - Consider left indent given by left line attributes.
+ // - Consider negative left indent.
+ // wished left indent determined by wished table width and
+ // right offset given by surrounding fyl frames on the right:
+ const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
+ if ( nLeftOffset > 0 )
+ {
+ // surrounding fly frames on the left
+ // -> right indent is maximun of given left offset
+ // and wished left offset.
+ nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft );
+ }
+ else
+ {
+ // no surrounding fly frames on the left
+ // If intrinsic left indent (intrinsic = not considering
+ // determined right indent) is negative,
+ // then hold this intrinsic indent,
+ // otherwise non negative wished left indent is hold.
+ nLeftSpacing = nLeftLine +
+ ( ( (nWishLeft+nRightOffset) < 0 ) ?
+ (nWishLeft+nRightOffset) :
+ Max( 0L, nWishLeft ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::CENTER:
+ {
+ // OD 07.03.2003 #i9040# - consider left/right line attribute.
+ // OD 10.03.2003 #i9040# -
+ const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
+ nLeftSpacing = nLeftLine +
+ ( (nLeftOffset > 0) ?
+ Max( nCenterSpacing, nLeftOffset ) :
+ nCenterSpacing );
+ nRightSpacing = nRightLine +
+ ( (nRightOffset > 0) ?
+ Max( nCenterSpacing, nRightOffset ) :
+ nCenterSpacing );
+ }
+ break;
+ case text::HoriOrientation::FULL:
+ //Das Teil dehnt sich ueber die gesamte Breite aus.
+ //Nur die fuer die Umrandung benoetigten Freiraeume
+ //werden beruecksichtigt.
+ //Die Attributwerte von LRSpace werden bewusst missachtet!
+ bCheckBrowseWidth = sal_True;
+ nLeftSpacing = nLeftLine + nLeftOffset;
+ nRightSpacing = nRightLine + nRightOffset;
+ break;
+ case text::HoriOrientation::NONE:
+ {
+ //Die Raender werden vom Randattribut bestimmt.
+ nLeftSpacing = pAttrs->CalcLeft( this );
+ if( nLeftOffset )
+ {
+ // OD 07.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of left spacing and left offset.
+ // OD 10.03.2003 #i9040# - consider left line attribute.
+ nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
+ }
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nRightSpacing = pAttrs->CalcRight( this );
+ if( nRightOffset )
+ {
+ // OD 07.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of right spacing and right offset.
+ // OD 10.03.2003 #i9040# - consider right line attribute.
+ nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) );
+ }
+ }
+ break;
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ {
+ //Linker Rand und die Breite zaehlen (Word-Spezialitaet)
+ // OD 10.03.2003 #i9040# - no width alignment in online mode.
+ //bCheckBrowseWidth = sal_True;
+ nLeftSpacing = pAttrs->CalcLeft( this );
+ if( nLeftOffset )
+ {
+ // OD 10.03.2003 #i9040# - surround fly frames only, if
+ // they overlap with the table.
+ // Thus, take maximun of right spacing and right offset.
+ // OD 10.03.2003 #i9040# - consider left line attribute.
+ nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
+ }
+ // OD 10.03.2003 #i9040# - consider right and left line attribute.
+ const SwTwips nWishRight =
+ nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
+ nRightSpacing = nRightLine +
+ ( (nRightOffset > 0) ?
+ Max( nWishRight, nRightOffset ) :
+ nWishRight );
+ }
+ break;
+ default:
+ OSL_FAIL( "Ungueltige orientation fuer Table." );
+ }
+
+ // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table
+ // is last content inside a table cell.
+ if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
+ GetUpper()->IsInTab() && !GetIndNext() )
+ {
+ nLower += pAttrs->GetULSpace().GetLower();
+ }
+ // <--
+ (this->*fnRect->fnSetYMargins)( nUpper, nLower );
+ if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
+ (this->*fnRect->fnSetXMargins)( 0, 0 );
+ else
+ (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
+
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if ( bCheckBrowseWidth &&
+ pSh && pSh->GetViewOptions()->getBrowseMode() &&
+ GetUpper()->IsPageBodyFrm() && // nur PageBodyFrms, nicht etwa ColBodyFrms
+ pSh->VisArea().Width() )
+ {
+ //Nicht ueber die Kante des sichbaren Bereiches hinausragen.
+ //Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
+ //geben kann (RootFrm::ImplCalcBrowseWidth())
+ long nWidth = pSh->GetBrowseWidth();
+ nWidth -= Prt().Left();
+ nWidth -= pAttrs->CalcRightLine();
+ Prt().Width( Min( nWidth, Prt().Width() ) );
+ }
+
+ if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
+ bValidSize = sal_False;
+ }
+
+ if ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+ //Die Groesse wird durch den Inhalt plus den Raendern bestimmt.
+ SwTwips nRemaining = 0, nDiff;
+ SwFrm *pFrm = pLower;
+ while ( pFrm )
+ {
+ nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ //Jetzt noch die Raender addieren
+ nRemaining += nUpper + nLower;
+
+ nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff > 0 )
+ Shrink( nDiff );
+ else if ( nDiff < 0 )
+ Grow( -nDiff );
+ }
+}
+/*************************************************************************
+|*
+|* SwTabFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
+ if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
+ nDist = LONG_MAX - nHeight;
+
+ if ( bTst && !IsRestrictTableGrowth() )
+ return nDist;
+
+ if ( GetUpper() )
+ {
+ SwRect aOldFrm( Frm() );
+
+ //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal
+ //die bereits zur Verfuegung stehende Strecke bereitgestellt.
+ SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pFrm = GetUpper()->Lower();
+ while ( pFrm && GetFollow() != pFrm )
+ {
+ nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+
+ if ( nReal < nDist )
+ {
+ long nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
+
+ if ( IsRestrictTableGrowth() )
+ {
+ nTmp = Min( nDist, nReal + nTmp );
+ nDist = nTmp < 0 ? 0 : nTmp;
+ }
+ }
+
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnAddBottom)( nDist );
+
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ }
+
+ if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved
+ // forward due to the positioning of its objects ). Thus, invalivate this
+ // next frame, if document compatibility option 'Consider wrapping style
+ // influence on object positioning' is ON.
+ else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ SetComplete();
+
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+
+ return nDist;
+}
+/*************************************************************************
+|*
+|* SwTabFrm::Modify()
+|*
+|*************************************************************************/
+void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+
+ if( bAttrSetChg )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwLayoutFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x02 )
+ _InvalidatePrt();
+ if ( nInvFlags & 0x40 )
+ _InvalidatePos();
+ SwFrm *pTmp;
+ if ( 0 != (pTmp = GetIndNext()) )
+ {
+ if ( nInvFlags & 0x04 )
+ {
+ pTmp->_InvalidatePrt();
+ if ( pTmp->IsCntntFrm() )
+ pTmp->InvalidatePage( pPage );
+ }
+ if ( nInvFlags & 0x10 )
+ pTmp->SetCompletePaint();
+ }
+ if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
+ {
+ pTmp->_InvalidatePrt();
+ if ( pTmp->IsCntntFrm() )
+ pTmp->InvalidatePage( pPage );
+ }
+ if ( nInvFlags & 0x20 )
+ {
+ if ( pPage && pPage->GetUpper() && !IsFollow() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+ }
+ if ( nInvFlags & 0x80 )
+ InvalidateNextPos();
+ }
+}
+
+void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_TBLHEADLINECHG:
+ if ( IsFollow() )
+ {
+ // Delete remaining headlines:
+ SwRowFrm* pLowerRow = 0;
+ while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
+ {
+ pLowerRow->Cut();
+ delete pLowerRow;
+ }
+
+ // insert new headlines
+ const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
+ for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
+ {
+ bDontCreateObjects = sal_True; //frmtool
+ SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
+ pHeadline->SetRepeatedHeadline( true );
+ bDontCreateObjects = sal_False;
+ pHeadline->Paste( this, pLowerRow );
+ }
+ }
+ rInvFlags |= 0x02;
+ break;
+
+ case RES_FRM_SIZE:
+ case RES_HORI_ORIENT:
+ rInvFlags |= 0x22;
+ break;
+
+ case RES_PAGEDESC: //Attributaenderung (an/aus)
+ if ( IsInDocBody() )
+ {
+ rInvFlags |= 0x40;
+ SwPageFrm *pPage = FindPageFrm();
+ if ( !GetPrev() )
+ CheckPageDescs( pPage );
+ if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() )
+ ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+ break;
+
+ case RES_BREAK:
+ rInvFlags |= 0xC0;
+ break;
+
+ case RES_LAYOUT_SPLIT:
+ if ( !IsFollow() )
+ rInvFlags |= 0x40;
+ break;
+ case RES_FRAMEDIR :
+ SetDerivedR2L( sal_False );
+ CheckDirChange();
+ break;
+ case RES_COLLAPSING_BORDERS :
+ rInvFlags |= 0x02;
+ lcl_InvalidateAllLowersPrt( this );
+ break;
+ case RES_UL_SPACE:
+ rInvFlags |= 0x1C;
+ /* kein Break hier */
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwLayoutFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::GetInfo()
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
+{
+ if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
+ {
+ SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( pPage )
+ {
+ if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
+ {
+ //Das sollte er sein (kann allenfalls temporaer anders sein,
+ // sollte uns das beunruhigen?)
+ rInfo.SetInfo( pPage, this );
+ return sal_False;
+ }
+ if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
+ (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
+ {
+ //Das koennte er sein.
+ rInfo.SetInfo( pPage, this );
+ }
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::FindLastCntnt()
+|*
+|*************************************************************************/
+SwCntntFrm *SwTabFrm::FindLastCntnt()
+{
+ SwFrm *pRet = pLower;
+
+ while ( pRet && !pRet->IsCntntFrm() )
+ {
+ SwFrm *pOld = pRet;
+
+ SwFrm *pTmp = pRet; // To skip empty section frames
+ while ( pRet->GetNext() )
+ {
+ pRet = pRet->GetNext();
+ if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
+ pTmp = pRet;
+ }
+ pRet = pTmp;
+
+ if ( pRet->GetLower() )
+ pRet = pRet->GetLower();
+ if ( pRet == pOld )
+ {
+ // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht,
+ // der eine leere letzte Spalte hat, muessen wir noch die anderen
+ // Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt
+ if( pRet->IsColBodyFrm() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ SwSectionFrm* pSect = pRet->FindSctFrm();
+ OSL_ENSURE( pSect, "Wo kommt denn die Spalte her?");
+ OSL_ENSURE( IsAnLower( pSect ), "Gespaltene Zelle?" );
+#endif
+ return pRet->FindSctFrm()->FindLastCntnt();
+ }
+
+ //
+ // pRet may be a cell frame without a lower (cell has been split).
+ // We have to find the last content the hard way:
+ //
+ OSL_ENSURE( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" );
+ const SwFrm* pRow = pRet->GetUpper();
+ while ( pRow && !pRow->GetUpper()->IsTabFrm() )
+ pRow = pRow->GetUpper();
+ SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt();
+ pRet = 0;
+
+ while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
+ {
+ pRet = pCntntFrm;
+ pCntntFrm = pCntntFrm->GetNextCntntFrm();
+ }
+ }
+ }
+
+ // #112929# There actually is a situation, which results in pRet = 0:
+ // Insert frame, insert table via text <-> table. This gives you a frame
+ // containing a table without any other content frames. Split the table
+ // and undo the splitting. This operation gives us a table frame without
+ // a lower.
+ if ( pRet )
+ {
+ while ( pRet->GetNext() )
+ pRet = pRet->GetNext();
+
+ if( pRet->IsSctFrm() )
+ pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
+ }
+
+ return (SwCntntFrm*)pRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::GetLeaf()
+|*
+|*************************************************************************/
+SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
+{
+ SwLayoutFrm *pRet;
+ if ( bFwd )
+ {
+ pRet = GetNextLeaf( eMakePage );
+ while ( IsAnLower( pRet ) )
+ pRet = pRet->GetNextLeaf( eMakePage );
+ }
+ else
+ pRet = GetPrevLeaf();
+ if ( pRet )
+ pRet->Calc();
+ return pRet;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::ShouldBwdMoved()
+|*
+|* Beschreibung Returnwert sagt ob der Frm verschoben werden sollte
+|*
+|*************************************************************************/
+sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat )
+{
+ rReformat = sal_False;
+ if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
+ {
+ //Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
+ //Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
+ //moechte die FixSize die gleiche ist, die der Frm selbst hat.
+ //In diesem Fall kann einfach geprueft werden, ob der Frm genug
+ //Platz fuer seine VarSize findet, ist dies nicht der Fall kann
+ //gleich auf das Verschieben verzichtet werden.
+ //Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
+ //durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
+ //aufspalten kann.
+ //Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
+ //(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
+ //der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
+ //etwas Platz zur Verfuegung steht).
+
+ //Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer
+ //Die Breite.
+
+ SwPageFrm *pOldPage = FindPageFrm(),
+ *pNewPage = pNewUpper->FindPageFrm();
+ sal_Bool bMoveAnyway = sal_False;
+ SwTwips nSpace = 0;
+
+ SWRECTFN( this )
+ if ( !SwFlowFrm::IsMoveBwdJump() )
+ {
+
+ long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ SWRECTFNX( pNewUpper );
+ long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
+ if( Abs( nNewWidth - nOldWidth ) < 2 )
+ {
+ if( sal_False ==
+ ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) )
+ {
+ SwRect aRect( pNewUpper->Prt() );
+ aRect.Pos() += pNewUpper->Frm().Pos();
+ const SwFrm *pPrevFrm = pNewUpper->Lower();
+ while ( pPrevFrm && pPrevFrm != this )
+ {
+ (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
+ fnGetBottom)() );
+ pPrevFrm = pPrevFrm->GetNext();
+ }
+ bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
+
+ // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake,
+ // the tabfrm may not have a correct position. Therefore
+ // it is possible that pNewUpper->Prt().Height == 0. In this
+ // case the above calculation of nSpace might give wrong
+ // results and we really do not want to MoveBackwrd into a
+ // 0 height frame. If nTmpSpace is already <= 0, we take this
+ // value:
+ const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
+ if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
+ nSpace = nTmpSpace;
+ // <--
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetViewOptions()->getBrowseMode() )
+ nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
+ }
+ }
+ else if( !bLockBackMove )
+ bMoveAnyway = sal_True;
+ }
+ else if( !bLockBackMove )
+ bMoveAnyway = sal_True;
+
+ if ( bMoveAnyway )
+ return rReformat = sal_True;
+ else if ( !bLockBackMove && nSpace > 0 )
+ {
+ // --> OD 2004-10-05 #i26945# - check, if follow flow line
+ // contains frame, which are moved forward due to its object
+ // positioning.
+ SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
+ if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
+ SwLayouter::DoesRowContainMovedFwdFrm(
+ *(pFirstRow->GetFmt()->GetDoc()),
+ *(pFirstRow) ) )
+ {
+ return sal_False;
+ }
+ // <--
+ SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
+
+ // --> FME 2005-01-17 #118840#
+ // For some mysterious reason, I changed the good old
+ // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
+ // This obviously results in problems with table frames in
+ // sections. Remember: Every twip is sacred.
+ return nTmpHeight <= nSpace;
+ // <--
+ }
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Cut()
+|*
+|*************************************************************************/
+void SwTabFrm::Cut()
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetNext();
+ if( pFrm )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet der ist jetzt wo er der erste wird obsolete
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ pFrm->_InvalidatePos();
+ if ( pFrm->IsCntntFrm() )
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ }
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ SWRECTFN( this )
+ Remove();
+ if ( pUp )
+ {
+ OSL_ENSURE( !pUp->IsFtnFrm(), "Tabelle in Fussnote." );
+ SwSectionFrm *pSct = 0;
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ if ( !pUp->Lower() && pUp->IsInSct() &&
+ !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) )
+ // <--
+ {
+ if ( pUp->GetUpper() )
+ {
+ pSct->DelEmpty( sal_False );
+ pSct->_InvalidateSize();
+ }
+ }
+ else if( (Frm().*fnRect->fnGetHeight)() )
+ {
+ // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
+ // undo changes of fix for #104992#
+ pUp->Shrink( Frm().Height() );
+ }
+ }
+
+ if ( pPage && !IsFollow() && pPage->GetUpper() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Paste()
+|*
+|*************************************************************************/
+void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ _InvalidateAll();
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ GetNext()->_InvalidatePrt();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+
+ SWRECTFN( this )
+ if( (Frm().*fnRect->fnGetHeight)() )
+ pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
+
+ if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
+ Prepare( PREP_FIXSIZE_CHG );
+ if ( GetPrev() )
+ {
+ if ( !IsFollow() )
+ {
+ GetPrev()->InvalidateSize();
+ if ( GetPrev()->IsCntntFrm() )
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+ else if ( GetNext() )
+ //Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger
+ //zu beachten. Faelle (beide treten immer gleichzeitig auf):
+ //a) Der Cntnt wird der erste einer Kette
+ //b) Der neue Nachfolger war vorher der erste einer Kette
+ GetNext()->_InvalidatePrt();
+
+ if ( pPage && !IsFollow() )
+ {
+ if ( pPage->GetUpper() )
+ ((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
+
+ if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig.
+ {
+ const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
+ if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
+ (!pDesc && pPage->GetPageDesc() !=
+ &(const_cast<const SwDoc *>(GetFmt()->GetDoc())
+ ->GetPageDesc(0))) )
+ CheckPageDescs( pPage, sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwTabFrm::Prepare()
+|*
+|*************************************************************************/
+void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool )
+{
+ if( PREP_BOSS_CHGD == eHint )
+ CheckDirChange();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::SwRowFrm(), ~SwRowFrm()
+|*
+|*************************************************************************/
+SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
+ SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
+ pTabLine( &rLine ),
+ pFollowRow( 0 ),
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ mnTopMarginForLowers( 0 ),
+ mnBottomMarginForLowers( 0 ),
+ mnBottomLineSize( 0 ),
+ // <-- collapsing
+ // --> split table rows
+ bIsFollowFlowRow( false ),
+ // <-- split table rows
+ bIsRepeatedHeadline( false ),
+ mbIsRowSpanLine( false )
+{
+ nType = FRMC_ROW;
+
+ //Gleich die Boxen erzeugen und einfuegen.
+ const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
+ {
+ SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+}
+
+SwRowFrm::~SwRowFrm()
+{
+ SwModify* pMod = GetFmt();
+ if( pMod )
+ {
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::RegistFlys()
+|*
+|*************************************************************************/
+void SwRowFrm::RegistFlys( SwPageFrm *pPage )
+{
+ ::RegistFlys( pPage ? pPage : FindPageFrm(), this );
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Modify()
+|*
+|*************************************************************************/
+void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+ const SfxPoolItem *pItem = 0;
+
+ if( bAttrSetChg )
+ {
+ const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
+ pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem);
+ if ( !pItem )
+ pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem);
+ }
+ else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() )
+ pItem = pNew;
+
+ if ( pItem )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab )
+ {
+ const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
+ this == pTab->GetFirstNonHeadlineRow();
+ // --> FME 2004-10-27 #i35063#
+ // Invalidation required is pRow is last row
+ if ( bInFirstNonHeadlineRow || !GetNext() )
+ // <--
+ {
+ if ( bInFirstNonHeadlineRow )
+ pTab = pTab->FindMaster();
+ pTab->InvalidatePos();
+ }
+ }
+ }
+
+ SwLayoutFrm::Modify( pOld, pNew );
+}
+
+
+
+/*************************************************************************
+|*
+|* SwRowFrm::MakeAll()
+|*
+|*************************************************************************/
+void SwRowFrm::MakeAll()
+{
+ if ( !GetNext() )
+ bValidSize = sal_False;
+ SwLayoutFrm::MakeAll();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Format()
+|*
+|*************************************************************************/
+long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm )
+{
+ SWRECTFN( pFrm )
+ long nHeight = 0;
+ const SwFrm* pTmp = pFrm->IsSctFrm() ?
+ ((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
+ while( pTmp )
+ {
+ // --> OD 2004-10-08 #i26945# - consider follow text frames
+ const SwSortedObjs* pObjs( 0L );
+ bool bIsFollow( false );
+ if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
+ {
+ const SwFrm* pMaster;
+ // --> FME 2005-04-01 #i46450# Master does not necessarily have
+ // to exist if this function is called from JoinFrm() ->
+ // Cut() -> Shrink()
+ const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
+ if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
+ static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
+ static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
+ pMaster = 0;
+ else
+ pMaster = pTmpFrm->FindMaster();
+
+ if ( pMaster )
+ {
+ pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
+ bIsFollow = true;
+ }
+ }
+ else
+ {
+ pObjs = pTmp->GetDrawObjs();
+ }
+ if ( pObjs )
+ // <--
+ {
+ for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the
+ // anchor character frame has to be <pTmp>.
+ if ( bIsFollow &&
+ const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2004-10-04 #i26945# - consider also drawing objects
+ {
+ // OD 30.09.2003 #i18732# - only objects, which follow
+ // the text flow have to be considered.
+ const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
+ const bool bConsiderObj =
+ (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
+ pAnchoredObj->GetObjRect().Top() != WEIT_WECH &&
+ rFrmFmt.GetFollowTextFlow().GetValue() &&
+ pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
+ if ( bConsiderObj )
+ {
+ const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
+ if( !rSz.GetHeightPercent() )
+ {
+ const SwTwips nDistOfFlyBottomToAnchorTop =
+ (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
+ ( bVert ?
+ pAnchoredObj->GetCurrRelPos().X() :
+ pAnchoredObj->GetCurrRelPos().Y() );
+
+ const SwTwips nFrmDiff =
+ (*fnRect->fnYDiff)(
+ (pTmp->Frm().*fnRect->fnGetTop)(),
+ (pFrm->Frm().*fnRect->fnGetTop)() );
+
+ nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
+ (pFrm->Frm().*fnRect->fnGetHeight)() );
+
+ // --> FME 2006-01-24 #i56115# The first height calculation
+ // gives wrong results if pFrm->Prt().Y() > 0. We do
+ // a second calculation based on the actual rectangles of
+ // pFrm and pAnchoredObj, and use the maximum of the results.
+ // I do not want to remove the first calculation because
+ // if clipping has been applied, using the GetCurrRelPos
+ // might be the better option to calculate nHeight.
+ const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
+ (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
+ (pFrm->Frm().*fnRect->fnGetBottom)() );
+
+ nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 );
+ // <--
+ }
+ }
+ }
+ // <--
+ }
+ }
+ if( !pFrm->IsSctFrm() )
+ break;
+ pTmp = pTmp->FindNextCnt();
+ if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
+ break;
+ }
+ return nHeight;
+}
+
+SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
+{
+ const SwTabFrm* pTab = rCell.FindTabFrm();
+ SwTwips nTopSpace = 0;
+ SwTwips nBottomSpace = 0;
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
+ {
+ nTopSpace = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
+ nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
+ }
+ // <-- collapsing
+ else
+ {
+ if ( pTab->IsVertical() != rCell.IsVertical() )
+ {
+ nTopSpace = rAttrs.CalcLeft( &rCell );
+ nBottomSpace = rAttrs.CalcRight( &rCell );
+ }
+ else
+ {
+ nTopSpace = rAttrs.CalcTop();
+ nBottomSpace = rAttrs.CalcBottom();
+ }
+ }
+
+ return nTopSpace + nBottomSpace;
+}
+
+
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
+// control, if floating screen objects have to be considered for the minimal
+// cell height.
+SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
+ const sal_Bool _bConsiderObjs,
+ const SwBorderAttrs *pAttrs = 0 )
+{
+ SWRECTFN( _pCell )
+ SwTwips nHeight = 0;
+ const SwFrm* pLow = _pCell->Lower();
+ if ( pLow )
+ {
+ long nFlyAdd = 0;
+ while ( pLow )
+ {
+ // OD 2004-02-18 #106629# - change condition and switch then-body
+ // and else-body
+ if ( pLow->IsRowFrm() )
+ {
+ // --> OD 2004-10-04 #i26945#
+ nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
+ _bConsiderObjs );
+ // <--
+ }
+ else
+ {
+ long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
+ nHeight += nLowHeight;
+ // --> OD 2004-10-04 #i26945#
+ if ( _bConsiderObjs )
+ {
+ nFlyAdd = Max( 0L, nFlyAdd - nLowHeight );
+ nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
+ }
+ // <--
+ }
+
+ pLow = pLow->GetNext();
+ }
+ if ( nFlyAdd )
+ nHeight += nFlyAdd;
+ }
+ //Der Border will natuerlich auch mitspielen, er kann leider nicht
+ //aus PrtArea und Frm errechnet werden, da diese in beliebiger
+ //Kombination ungueltig sein koennen.
+ if ( _pCell->Lower() )
+ {
+ if ( pAttrs )
+ nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
+ else
+ {
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
+ }
+ }
+ return nHeight;
+}
+
+// OD 2004-02-18 #106629# - correct type of 1st parameter
+// --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control,
+// if floating screen objects have to be considered for the minimal cell height
+SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
+ const sal_Bool _bConsiderObjs )
+{
+ SWRECTFN( _pRow )
+
+ const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
+
+ if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
+ {
+ OSL_ENSURE( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" );
+ return rSz.GetHeight();
+ }
+
+ SwTwips nHeight = 0;
+ const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
+ while ( pLow )
+ {
+ SwTwips nTmp = 0;
+ const long nRowSpan = pLow->GetLayoutRowSpan();
+ // --> NEW TABLES
+ // Consider height of
+ // 1. current cell if RowSpan == 1
+ // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
+ // 3. master cell if RowSpan == -1
+ if ( 1 == nRowSpan )
+ {
+ nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
+ }
+ else if ( -1 == nRowSpan )
+ {
+ // Height of the last cell of a row span is height of master cell
+ // minus the height of the other rows which are covered by the master
+ // cell:
+ const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
+ nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
+ const SwFrm* pMasterRow = rMaster.GetUpper();
+ while ( pMasterRow && pMasterRow != _pRow )
+ {
+ nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
+ pMasterRow = pMasterRow->GetNext();
+ }
+ }
+ // <-- NEW TABLES
+
+ // Do not consider rotated cells:
+ if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight )
+ nHeight = nTmp;
+
+ pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
+ }
+ if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
+ nHeight = Max( nHeight, rSz.GetHeight() );
+ return nHeight;
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+
+// Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
+sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
+{
+ sal_uInt16 nTopSpace = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpTopSpace = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True );
+ }
+ nTopSpace = Max( nTopSpace, nTmpTopSpace );
+ }
+ return nTopSpace;
+}
+
+// Calculate the maximum of TopLineDist over all lowers:
+sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
+{
+ sal_uInt16 nTopLineDist = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpTopLineDist = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
+ }
+ nTopLineDist = Max( nTopLineDist, nTmpTopLineDist );
+ }
+ return nTopLineDist;
+}
+
+// Calculate the maximum of BottomLineSize over all lowers:
+sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
+{
+ sal_uInt16 nBottomLineSize = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpBottomLineSize = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ {
+ const SwFrm* pRow = pCurrLower->GetLastLower();
+ nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
+ }
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) -
+ rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ }
+ nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize );
+ }
+ return nBottomLineSize;
+}
+
+// Calculate the maximum of BottomLineDist over all lowers:
+sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
+{
+ sal_uInt16 nBottomLineDist = 0;
+ for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
+ pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
+ {
+ sal_uInt16 nTmpBottomLineDist = 0;
+ if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
+ {
+ const SwFrm* pRow = pCurrLower->GetLastLower();
+ nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
+ }
+ else
+ {
+ const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
+ const SvxBoxItem& rBoxItem = rSet.GetBox();
+ nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
+ }
+ nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist );
+ }
+ return nBottomLineDist;
+}
+
+// <-- collapsing
+
+void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ SWRECTFN( this )
+ OSL_ENSURE( pAttrs, "SwRowFrm::Format ohne Attrs." );
+
+ const sal_Bool bFix = bFixSize;
+
+ if ( !bValidPrtArea )
+ {
+ //RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer
+ //dem Frm.
+ bValidPrtArea = sal_True;
+ aPrt.Left( 0 );
+ aPrt.Top( 0 );
+ aPrt.Width ( aFrm.Width() );
+ aPrt.Height( aFrm.Height() );
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ // Here we calculate the top-printing area for the lower cell frames
+ SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->IsCollapsingBorders() )
+ {
+ const sal_uInt16 nTopSpace = lcl_GetTopSpace( *this );
+ const sal_uInt16 nTopLineDist = lcl_GetTopLineDist( *this );
+ const sal_uInt16 nBottomLineSize = lcl_GetBottomLineSize( *this );
+ const sal_uInt16 nBottomLineDist = lcl_GetBottomLineDist( *this );
+
+
+ const SwRowFrm* pPreviousRow = 0;
+
+ // --> FME 2004-09-14 #i32456#
+ // In order to calculate the top printing area for the lower cell
+ // frames, we have to find the 'previous' row frame and compare
+ // the bottom values of the 'previous' row with the 'top' values
+ // of this row. The best way to find the 'previous' row is to
+ // use the table structure:
+ const SwTable* pTable = pTabFrm->GetTable();
+ const SwTableLine* pPrevTabLine = 0;
+ const SwRowFrm* pTmpRow = this;
+
+ while ( pTmpRow && !pPrevTabLine )
+ {
+ sal_uInt16 nIdx = 0;
+ const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
+ pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
+ pTable->GetTabLines();
+
+ while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
+ ++nIdx;
+
+ if ( nIdx > 0 )
+ {
+ // pTmpRow has a 'previous' row in the table structure:
+ pPrevTabLine = rLines[ nIdx - 1 ];
+ }
+ else
+ {
+ // pTmpRow is a first row in the table structue.
+ // We go up in the table structure:
+ pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
+ pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
+ static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
+ 0;
+ }
+ }
+
+ // If we found a 'previous' row, we look for the appropriate row frame:
+ if ( pPrevTabLine )
+ {
+ SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
+ for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
+ {
+ // --> OD 2004-11-23 #115759# - do *not* take repeated
+ // headlines, because during split of table it can be
+ // invalid and thus can't provide correct border values.
+ if ( pRow->GetTabLine() == pPrevTabLine &&
+ !pRow->IsRepeatedHeadline() )
+ // <--
+ {
+ pPreviousRow = pRow;
+ break;
+ }
+ }
+ }
+ // <--
+
+ sal_uInt16 nTopPrtMargin = nTopSpace;
+ if ( pPreviousRow )
+ {
+ const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
+ if ( nTmpPrtMargin > nTopPrtMargin )
+ nTopPrtMargin = nTmpPrtMargin;
+ }
+
+ // table has to be notified if it has to change its lower
+ // margin due to changes of nBottomLineSize:
+ if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
+ pTabFrm->_InvalidatePrt();
+
+ // If there are rows nested inside this row, the nested rows
+ // may not have been calculated yet. Therefore the
+ // ::lcl_CalcMinRowHeight( this ) operation later in this
+ // function cannot consider the correct border values. We
+ // have to trigger the invalidation of the outer row frame
+ // manually:
+ // Note: If any further invalidations should be necessary, we
+ // should consider moving the invalidation stuff to the
+ // appropriate SwNotify object.
+ if ( GetUpper()->GetUpper()->IsRowFrm() &&
+ ( nBottomLineDist != GetBottomMarginForLowers() ||
+ nTopPrtMargin != GetTopMarginForLowers() ) )
+ GetUpper()->GetUpper()->_InvalidateSize();
+
+ SetBottomMarginForLowers( nBottomLineDist ); // 3.
+ SetBottomLineSize( nBottomLineSize ); // 4.
+ SetTopMarginForLowers( nTopPrtMargin ); // 5.
+
+ }
+// <-- collapsing
+ }
+
+ while ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+#if OSL_DEBUG_LEVEL > 1
+ if ( HasFixSize() )
+ {
+ const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
+ OSL_ENSURE( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
+ }
+#endif
+ const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
+ ( HasFixSize() && !IsRowSpanLine()
+ ? pAttrs->GetSize().Height()
+ // --> OD 2004-10-04 #i26945#
+ : ::lcl_CalcMinRowHeight( this,
+ FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
+ // <--
+ if ( nDiff )
+ {
+ bFixSize = sal_False;
+ if ( nDiff > 0 )
+ Shrink( nDiff, sal_False, sal_True );
+ else if ( nDiff < 0 )
+ Grow( -nDiff );
+ bFixSize = bFix;
+ }
+ }
+
+ // last row will fill the space in its upper.
+ if ( !GetNext() )
+ {
+ //Der letzte fuellt den verbleibenden Raum im Upper aus.
+ SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pSibling = GetUpper()->Lower();
+ do
+ { nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
+ pSibling = pSibling->GetNext();
+ } while ( pSibling );
+ if ( nDiff > 0 )
+ {
+ bFixSize = sal_False;
+ Grow( nDiff );
+ bFixSize = bFix;
+ bValidSize = sal_True;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::AdjustCells()
+|*
+|*************************************************************************/
+void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight )
+{
+ SwFrm *pFrm = Lower();
+ if ( bHeight )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ SWRECTFN( this )
+ SwRect aOldFrm;
+
+ while ( pFrm )
+ {
+ SwFrm* pNotify = 0;
+
+ SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
+
+ // NEW TABLES
+ // Which cells need to be adjusted if the current row changes
+ // its height?
+
+ // Current frame is a covered frame:
+ // Set new height for covered cell and adjust master cell:
+ if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
+ {
+ // Set height of current (covered) cell to new line height.
+ const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ {
+ (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
+ pCellFrm->_InvalidatePrt();
+ }
+ }
+
+ SwCellFrm* pToAdjust = 0;
+ SwFrm* pToAdjustRow = 0;
+
+ // If current frame is covered frame, we still want to adjust the
+ // height of the cell starting the row span
+ if ( pCellFrm->GetLayoutRowSpan() < 1 )
+ {
+ pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
+ pToAdjustRow = pToAdjust->GetUpper();
+ }
+ else
+ {
+ pToAdjust = pCellFrm;
+ pToAdjustRow = this;
+ }
+
+ // Set height of master cell to height of all lines spanned by this line.
+ long nRowSpan = pToAdjust->GetLayoutRowSpan();
+ SwTwips nSumRowHeight = 0;
+ while ( pToAdjustRow )
+ {
+ // Use new height for the current row:
+ nSumRowHeight += pToAdjustRow == this ?
+ nHeight :
+ (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
+
+ if ( nRowSpan-- == 1 )
+ break;
+
+ pToAdjustRow = pToAdjustRow->GetNext();
+ }
+
+ if ( pToAdjustRow && pToAdjustRow != this )
+ pToAdjustRow->_InvalidateSize();
+
+ const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
+ if ( nDiff )
+ {
+ aOldFrm = pToAdjust->Frm();
+ (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
+ pNotify = pToAdjust;
+ }
+
+ if ( pNotify )
+ {
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
+
+ pNotify->_InvalidatePrt();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+ }
+ else
+ { while ( pFrm )
+ {
+ pFrm->_InvalidateAll();
+ pFrm = pFrm->GetNext();
+ }
+ }
+ InvalidatePage();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::Cut()
+|*
+|*************************************************************************/
+void SwRowFrm::Cut()
+{
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
+ {
+ pTab->FindMaster()->InvalidatePos();
+ }
+
+ // --> OD 2010-02-17 #i103961#
+ // notification for accessibility
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell* pVSh = pRootFrm->GetCurrShell();
+ if ( pVSh && pVSh->Imp() )
+ {
+ SwFrm* pCellFrm( GetLower() );
+ while ( pCellFrm )
+ {
+ OSL_ENSURE( pCellFrm->IsCellFrm(),
+ "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
+ pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
+
+ pCellFrm = pCellFrm->GetNext();
+ }
+ }
+ }
+ }
+ // <--
+
+ SwLayoutFrm::Cut();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::GrowFrm()
+|*
+|*************************************************************************/
+
+
+SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SwTwips nReal = 0;
+
+ SwTabFrm* pTab = FindTabFrm();
+ SWRECTFN( pTab )
+
+ bool bRestrictTableGrowth;
+ bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
+
+ if ( GetUpper()->IsTabFrm() )
+ {
+ const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
+ bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
+ }
+ else
+ {
+ OSL_ENSURE( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" );
+ bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
+ OSL_ENSURE( !bRestrictTableGrowth || !GetNext(),
+ "GetFollowRow for row frame that has a Next" );
+
+ //
+ // There may still be some space left in my direct upper:
+ //
+ const SwTwips nAdditionalSpace =
+ (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
+ if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
+ {
+ nReal = Min( nAdditionalSpace, nDist );
+ nDist -= nReal;
+ if ( !bTst )
+ (Frm().*fnRect->fnAddBottom)( nReal );
+ }
+ }
+
+ if ( bRestrictTableGrowth )
+ pTab->SetRestrictTableGrowth( sal_True );
+ else
+ {
+ // Ok, this looks like a hack, indeed, it is a hack.
+ // If the current row frame is inside another cell frame,
+ // and the current row frame has no follow, it should not
+ // be allowed to grow. In fact, setting bRestrictTableGrowth
+ // to 'false' does not work, because the surrounding RowFrm
+ // would set this to 'true'.
+ pTab->SetFollowFlowLine( sal_False );
+ }
+
+ nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
+
+ pTab->SetRestrictTableGrowth( sal_False );
+ pTab->SetFollowFlowLine( bHasFollowFlowLine );
+
+ //Hoehe der Zellen auf den neuesten Stand bringen.
+ if ( !bTst )
+ {
+ SWRECTFNX( this )
+ AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True );
+ if ( nReal )
+ SetCompletePaint();
+ }
+
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ if( HasFixSize() )
+ {
+ AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True );
+ return 0L;
+ }
+
+ //bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann
+ //entsprechend reagiert werden
+ const sal_Bool bShrinkAnyway = bInfo;
+
+ //Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst.
+ SwTwips nRealDist = nDist;
+ {
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
+ rSz.GetHeight() :
+ 0;
+
+ // Only necessary to calculate minimal row height if height
+ // of pRow is at least nMinHeight. Otherwise nMinHeight is the
+ // minimum height.
+ if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
+ {
+ // --> OD 2004-10-04 #i26945#
+ OSL_ENSURE( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
+ const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
+ // <--
+ nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
+ }
+
+ if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
+ nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
+ }
+ if ( nRealDist < 0 )
+ nRealDist = 0;
+
+ SwTwips nReal = nRealDist;
+ if ( nReal )
+ {
+ if ( !bTst )
+ {
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !bRev )
+ Frm().Pos().X() += nReal;
+ }
+
+ SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
+ if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
+ {
+ //Der letzte bekommt den Rest im Upper und nimmt deshalb
+ //ggf. Ruecksichten (sonst: Endlosschleife)
+ if ( !bTst )
+ {
+ nReal -= nTmp;
+ SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !bRev )
+ Frm().Pos().X() -= nReal;
+ }
+ nReal = nTmp;
+ }
+ }
+
+ //Geeignet invalidieren und die Hoehe der Zellen auf den neuesten
+ //Stand bringen.
+ if ( !bTst )
+ {
+ if ( nReal )
+ {
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+ _InvalidateAll();
+ SetCompletePaint();
+
+ SwTabFrm *pTab = FindTabFrm();
+ if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() &&
+ this == pTab->GetFirstNonHeadlineRow() )
+ {
+ SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
+ pMasterTab->InvalidatePos();
+ }
+ }
+ AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True );
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::IsRowSplitAllowed()
+|*
+|*************************************************************************/
+bool SwRowFrm::IsRowSplitAllowed() const
+{
+ // Fixed size rows are never allowed to split:
+ if ( HasFixSize() )
+ {
+ OSL_ENSURE( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" );
+ return false;
+ }
+
+ // Repeated headlines are never allowed to split:
+ const SwTabFrm* pTabFrm = FindTabFrm();
+ if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
+ pTabFrm->IsInHeadline( *this ) )
+ return false;
+
+ const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
+ const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
+ return 0 != rLP.GetValue();
+}
+
+/*************************************************************************
+|*
+|* SwRowFrm::ShouldRowKeepWithNext()
+|*
+|*************************************************************************/
+bool SwRowFrm::ShouldRowKeepWithNext() const
+{
+ bool bRet = false;
+
+ const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
+ const SwFrm* pTxt = pCell->Lower();
+
+ if ( pTxt && pTxt->IsTxtFrm() )
+ {
+ bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::SwCellFrm(), ~SwCellFrm()
+|*
+|*************************************************************************/
+SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
+ SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
+ pTabBox( &rBox )
+{
+ nType = FRMC_CELL;
+
+ if ( !bInsertContent )
+ return;
+
+ //Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle
+ //angelegt, andernfalls muessen Rows vorhanden sein und diese werden
+ //angelegt.
+ if ( rBox.GetSttIdx() )
+ {
+ sal_uLong nIndex = rBox.GetSttIdx();
+ ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
+ }
+ else
+ {
+ const SwTableLines &rLines = rBox.GetTabLines();
+ SwFrm *pTmpPrev = 0;
+ for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
+ {
+ SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
+ pNew->InsertBehind( this, pTmpPrev );
+ pTmpPrev = pNew;
+ }
+ }
+}
+
+SwCellFrm::~SwCellFrm()
+{
+ SwModify* pMod = GetFmt();
+ if( pMod )
+ {
+ // At this stage the lower frames aren't destroyed already,
+ // therfor we have to do a recursive dispose.
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True );
+ }
+
+ pMod->Remove( this ); // austragen,
+ if( !pMod->GetDepends() )
+ delete pMod; // und loeschen
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::Format()
+|*
+|*************************************************************************/
+sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva )
+{
+ sal_Bool bRet = sal_False;
+ SwFrm *pFrm = pLay->Lower();
+ SWRECTFN( pLay )
+ while ( pFrm )
+ {
+ long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
+ if( nFrmTop != lYStart )
+ {
+ bRet = sal_True;
+ const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
+ const long lDiffX = lYStart - nFrmTop;
+ (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
+ (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
+ pFrm->SetCompletePaint();
+ if ( !pFrm->GetNext() )
+ pFrm->SetRetouche();
+ if( bInva )
+ pFrm->Prepare( PREP_POS_CHGD );
+ if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
+ lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
+ (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
+ + lDiffX, bInva );
+ if ( pFrm->GetDrawObjs() )
+ {
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ // --> OD 2004-10-08 #i26945# - check, if anchored object
+ // is lower of layout frame by checking, if the anchor
+ // frame, which contains the anchor position, is a lower
+ // of the layout frame.
+ if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
+ {
+ continue;
+ }
+ // <--
+ // --> OD 2005-08-08 #i52904# - distinguish between anchored
+ // objects, whose vertical position depends on its anchor
+ // frame and whose vertical position is independent
+ // from its anchor frame.
+ bool bVertPosDepOnAnchor( true );
+ {
+ SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
+ switch ( aVert.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ bVertPosDepOnAnchor = false;
+ break;
+ default: break;
+ }
+ }
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+
+ // OD 2004-05-18 #i28701# - no direct move of objects,
+ // which are anchored to-paragraph/to-character, if
+ // the wrapping style influence has to be considered
+ // on the object positioning.
+ // --> OD 2005-08-08 #i52904# - no direct move of objects,
+ // whose vertical position doesn't depend on anchor frame.
+ const bool bDirectMove =
+ WEIT_WECH != pFly->Frm().Top() &&
+ bVertPosDepOnAnchor &&
+ !pFly->ConsiderObjWrapInfluenceOnObjPos();
+ // <--
+ if ( bDirectMove )
+ {
+ (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
+ (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
+ pFly->GetVirtDrawObj()->SetRectsDirty();
+ // --> OD 2004-08-17 - also notify view of <SdrObject>
+ // instance, which represents the Writer fly frame in
+ // the drawing layer
+ pFly->GetVirtDrawObj()->SetChanged();
+ // <--
+ // --> OD 2006-10-13 #i58280#
+ pFly->InvalidateObjRectWithSpaces();
+ // <--
+ }
+
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
+ // --> OD 2004-12-02 #115759# - reset current relative
+ // position to get re-positioned, if not directly moved.
+ if ( !bDirectMove )
+ {
+ pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
+ }
+ // <--
+ }
+ else if( pFly->IsAutoPos() )
+ {
+ pFly->AddLastCharY( lDiff );
+ // OD 2004-05-18 #i28701# - follow-up of #i22341#
+ // <mnLastTopOfLine> has also been adjusted.
+ pFly->AddLastTopOfLineY( lDiff );
+ }
+ // --> OD 2004-11-05 #i26945# - re-registration at
+ // page frame of anchor frame, if table frame isn't
+ // a follow table and table frame isn't in its
+ // rebuild of last line.
+ const SwTabFrm* pTabFrm = pLay->FindTabFrm();
+ // --> OD 2004-11-23 #115759#
+ // - save: check, if table frame is found.
+ if ( pTabFrm &&
+ !( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
+ pFly->IsFlyFreeFrm() )
+ // <--
+ {
+ SwPageFrm* pPageFrm = pFly->GetPageFrm();
+ SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
+ if ( pPageFrm != pPageOfAnchor )
+ {
+ pFly->InvalidatePos();
+ if ( pPageFrm )
+ pPageFrm->MoveFly( pFly, pPageOfAnchor );
+ else
+ pPageOfAnchor->AppendFlyToPage( pFly );
+ }
+ }
+ // <--
+ // OD 2004-05-11 #i28701# - Because of the introduction
+ // of new positionings and alignments (e.g. aligned at
+ // page area, but anchored at-character), the position
+ // of the Writer fly frame has to be invalidated.
+ pFly->InvalidatePos();
+
+ // --> OD 2004-11-04 #i26945# - follow-up of #i3317#
+ // No arrangement of lowers, if Writer fly frame isn't
+ // moved
+ if ( bDirectMove &&
+ ::lcl_ArrangeLowers( pFly,
+ (pFly->*fnRect->fnGetPrtTop)(),
+ bInva ) )
+ // <--
+ {
+ pFly->SetCompletePaint();
+ }
+ }
+ else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
+ {
+ // --> OD 2004-11-05 #i26945#
+ const SwTabFrm* pTabFrm = pLay->FindTabFrm();
+ if ( pTabFrm &&
+ !( pTabFrm->IsFollow() &&
+ pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
+ !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
+ == FLY_AS_CHAR )
+ {
+ SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
+ SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
+ if ( pPageFrm != pPageOfAnchor )
+ {
+ pAnchoredObj->InvalidateObjPos();
+ if ( pPageFrm )
+ {
+ pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
+ }
+ pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
+ }
+ }
+ // --> OD 2004-07-01 #i28701# - adjust last character
+ // rectangle and last top of line.
+ pAnchoredObj->AddLastCharY( lDiff );
+ pAnchoredObj->AddLastTopOfLineY( lDiff );
+ // --> OD 2005-08-08 #i52904# - re-introduce direct move
+ // of drawing objects
+ const bool bDirectMove =
+ static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
+ bVertPosDepOnAnchor &&
+ !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
+ if ( bDirectMove )
+ {
+ SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
+ if ( bVert )
+ {
+ pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
+ }
+ else
+ {
+ pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
+ }
+ // --> OD 2006-10-13 #i58280#
+ pAnchoredObj->InvalidateObjRectWithSpaces();
+ // <--
+ }
+ // <--
+ pAnchoredObj->InvalidateObjPos();
+ }
+ else
+ {
+ OSL_FAIL( "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
+ }
+ }
+ }
+ }
+ // Columns and cells are ordered horizontal, not vertical
+ if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
+ lYStart = (*fnRect->fnYInc)( lYStart,
+ (pFrm->Frm().*fnRect->fnGetHeight)() );
+
+ // Nowadays, the content inside a cell can flow into the follow table.
+ // Thus, the cell may only grow up to the end of the environment.
+ // So the content may have grown, but the cell could not grow.
+ // Therefore we have to trigger a formatting for the frames, which do
+ // not fit into the cell anymore:
+ SwTwips nDistanceToUpperPrtBottom =
+ (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
+ // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945#
+ // do *not* consider content inside fly frames, if it's an undersized paragraph.
+ // --> OD 2004-10-08 #i26945# - consider content inside fly frames
+ if ( nDistanceToUpperPrtBottom < 0 &&
+ ( ( pFrm->IsInFly() &&
+ ( !pFrm->IsTxtFrm() ||
+ !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
+ pFrm->IsInSplitTableRow() ) )
+ // <--
+ {
+ pFrm->InvalidatePos();
+ }
+
+ pFrm = pFrm->GetNext();
+ }
+ return bRet;
+}
+
+void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "CellFrm::Format, pAttrs ist 0." );
+ const SwTabFrm* pTab = FindTabFrm();
+ SWRECTFN( pTab )
+
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+
+ //Position einstellen.
+ if ( Lower() )
+ {
+ SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm() )
+ {
+ const SvxBoxItem& rBoxItem = pAttrs->GetBox();
+ nLeftSpace = rBoxItem.GetDistance( BOX_LINE_LEFT );
+ nRightSpace = rBoxItem.GetDistance( BOX_LINE_RIGHT );
+ nTopSpace = ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
+ nBottomSpace = ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
+ }
+ else
+ {
+ // <-- collapsing
+ // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
+ nLeftSpace = pAttrs->CalcLeft( this );
+ nRightSpace = pAttrs->CalcRight( this );
+ nTopSpace = pAttrs->CalcTop();
+ nBottomSpace = pAttrs->CalcBottom();
+ }
+ (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
+ (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
+ }
+ }
+ // --> OD 2004-10-04 #i26945#
+ long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
+ ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
+ 0;
+ // <--
+ if ( !bValidSize )
+ {
+ bValidSize = sal_True;
+
+ //Die VarSize der CellFrms ist immer die Breite.
+ //Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das
+ //Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum
+ //nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf
+ //Basis des Attributes errechnet, der Wert im Attribut passt zu dem
+ //gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen
+ //wurden werden hier Proportional beruecksichtigt.
+ //Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht
+ //die Attribute, sonder greift sich einfach den Rest des
+ //Uppers
+ SwTwips nWidth;
+ if ( GetNext() )
+ {
+ const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
+ nWidth = pAttrs->GetSize().Width();
+
+ OSL_ENSURE( nWish, "Tabelle ohne Breite?" );
+ OSL_ENSURE( nWidth <= nWish, "Zelle breiter als Tabelle." );
+ OSL_ENSURE( nWidth > 0, "Box without width" );
+
+ const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
+ if ( nWish != nPrtWidth )
+ {
+ // Avoid rounding problems, at least for the new table model
+ if ( pTab->GetTable()->IsNewModel() )
+ {
+ // 1. sum of widths of cells up to this cell (in model)
+ const SwTableLine* pTabLine = GetTabBox()->GetUpper();
+ const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
+ const SwTableBox* pTmpBox = 0;
+
+ SwTwips nSumWidth = 0;
+ sal_uInt16 i = 0;
+ do
+ {
+ pTmpBox = rBoxes[ i++ ];
+ nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ }
+ while ( pTmpBox != GetTabBox() );
+
+ // 2. calculate actual width of cells up to this one
+ double nTmpWidth = nSumWidth;
+ nTmpWidth *= nPrtWidth;
+ nTmpWidth /= nWish;
+ nWidth = (SwTwips)nTmpWidth;
+
+ // 3. calculate frame widths of cells up to this one:
+ const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
+ SwTwips nSumFrameWidths = 0;
+ while ( pTmpCell != this )
+ {
+ nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
+ pTmpCell = pTmpCell->GetNext();
+ }
+
+ nWidth = nWidth - nSumFrameWidths;
+ }
+ else
+ {
+ // #i12092# use double instead of long,
+ // otherwise this could lead to overflows
+ double nTmpWidth = nWidth;
+ nTmpWidth *= nPrtWidth;
+ nTmpWidth /= nWish;
+ nWidth = (SwTwips)nTmpWidth;
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( pAttrs->GetSize().Width() > 0, "Box without width" );
+ nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
+ SwFrm *pPre = GetUpper()->Lower();
+ while ( pPre != this )
+ {
+ nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
+ pPre = pPre->GetNext();
+ }
+ }
+ const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
+ if( IsNeighbourFrm() && IsRightToLeft() )
+ (Frm().*fnRect->fnSubLeft)( nDiff );
+ else
+ (Frm().*fnRect->fnAddRight)( nDiff );
+ (Prt().*fnRect->fnAddRight)( nDiff );
+
+ //Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern
+ //bestimmt.
+ const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
+ if ( nDiffHeight )
+ {
+ if ( nDiffHeight > 0 )
+ {
+ //Wieder validieren wenn kein Wachstum stattgefunden hat.
+ //Invalidiert wird durch AdjustCells von der Row.
+ if ( !Grow( nDiffHeight ) )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ else
+ {
+ //Nur dann invalidiert lassen, wenn tatsaechlich
+ //geshrinkt wurde; das kann abgelehnt werden, weil alle
+ //nebeneinanderliegenden Zellen gleichgross sein muessen.
+ if ( !Shrink( -nDiffHeight ) )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ }
+ }
+ const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
+
+ if ( !Lower() )
+ return;
+
+ // From now on, all operations are related to the table cell.
+ SWREFRESHFN( this )
+
+ SwPageFrm* pPg = 0;
+ if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
+ // --> OD 2008-07-16 #158225# no vertical alignment of covered cells
+ !IsCoveredCell() &&
+ // <--
+ // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode
+ !(pPg = FindPageFrm())->HasGrid() )
+ // <--
+ {
+ if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
+ {
+ // OSL_ENSURE(fuer HTML-Import!
+ OSL_ENSURE( !this, "VAlign an Zelle ohne Inhalt" );
+ return;
+ }
+ sal_Bool bVertDir = sal_True;
+ // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping
+ // style influence is considered on object positioning and
+ // an object is anchored inside the cell.
+ const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
+ // <--
+ //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen.
+ if ( pPg->GetSortedObjs() )
+ {
+ SwRect aRect( Prt() ); aRect += Frm().Pos();
+ for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
+ SwRect aTmp( pAnchoredObj->GetObjRect() );
+ if ( aTmp.IsOver( aRect ) )
+ {
+ const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
+ const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
+
+ if ( SURROUND_THROUGHT != rSur.GetSurround() )
+ {
+ // frames, which the cell is a lower of, aren't relevant
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ const SwFlyFrm *pFly =
+ static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsAnLower( this ) )
+ continue;
+ }
+
+ const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
+ // --> OD 2005-03-30 #i43913#
+ // --> OD 2005-08-08 #i52904# - no vertical alignment,
+ // if object, anchored inside cell, has temporarly
+ // consider its wrapping style on object positioning.
+ // --> FME 2006-02-01 #i58806# - no vertical alignment
+ // if object does not follow the text flow.
+ if ( bConsiderWrapOnObjPos ||
+ !IsAnLower( pAnch ) ||
+ pAnchoredObj->IsTmpConsiderWrapInfluence() ||
+ !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
+ // <--
+ {
+ bVertDir = sal_False;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
+ (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
+ {
+ long nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
+ if ( nDiff >= 0 )
+ {
+ long lTopOfst = 0;
+ if ( bVertDir )
+ {
+ switch ( rOri.GetVertOrient() )
+ {
+ case text::VertOrientation::CENTER: lTopOfst = nDiff / 2; break;
+ case text::VertOrientation::BOTTOM: lTopOfst = nDiff; break;
+ default: break;
+ };
+ }
+ long nTmp = (*fnRect->fnYInc)(
+ (this->*fnRect->fnGetPrtTop)(), lTopOfst );
+ if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
+ SetCompletePaint();
+ }
+ }
+ }
+ else
+ {
+ //Ist noch eine alte Ausrichtung beruecksichtigt worden?
+ if ( Lower()->IsCntntFrm() )
+ {
+ const long lYStart = (this->*fnRect->fnGetPrtTop)();
+ lcl_ArrangeLowers( this, lYStart, sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::Modify()
+|*
+|*************************************************************************/
+
+void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
+ const SfxPoolItem *pItem = 0;
+
+ if( bAttrSetChg )
+ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem);
+ else if ( RES_VERT_ORIENT == pNew->Which() )
+ pItem = pNew;
+
+ if ( pItem )
+ {
+ sal_Bool bInva = sal_True;
+ if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
+ // OD 04.11.2003 #112910#
+ Lower() && Lower()->IsCntntFrm() )
+ {
+ SWRECTFN( this )
+ const long lYStart = (this->*fnRect->fnGetPrtTop)();
+ bInva = lcl_ArrangeLowers( this, lYStart, sal_False );
+ }
+ if ( bInva )
+ {
+ SetCompletePaint();
+ InvalidatePrt();
+ }
+ }
+
+ if ( ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) ||
+ RES_PROTECT == pNew->Which() )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
+ pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
+ }
+
+ if ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) )
+ {
+ SetDerivedVert( sal_False );
+ CheckDirChange();
+ }
+
+ // --> collapsing borders FME 2005-05-27 #i29550#
+ if ( bAttrSetChg &&
+ SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) )
+ {
+ SwFrm* pTmpUpper = GetUpper();
+ while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
+ pTmpUpper = pTmpUpper->GetUpper();
+
+ SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
+ if ( pTabFrm->IsCollapsingBorders() )
+ {
+ // Invalidate lowers of this and next row:
+ lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
+ pTmpUpper = pTmpUpper->GetNext();
+ if ( pTmpUpper )
+ lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
+ else
+ pTabFrm->InvalidatePrt();
+ }
+ }
+ // <-- collapsing
+
+ SwLayoutFrm::Modify( pOld, pNew );
+}
+
+/*************************************************************************
+|* SwCellFrm::GetLayoutRowSpan() const
+|*************************************************************************/
+
+long SwCellFrm::GetLayoutRowSpan() const
+{
+ long nRet = GetTabBox()->getRowSpan();
+ if ( nRet < 1 )
+ {
+ const SwFrm* pRow = GetUpper();
+ const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
+
+ if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
+ nRet = -nRet;
+ }
+ return nRet;
+}
+
+// --> OD 2010-02-17 #i103961#
+void SwCellFrm::Cut()
+{
+ // notification for accessibility
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
+ {
+ ViewShell* pVSh = pRootFrm->GetCurrShell();
+ if ( pVSh && pVSh->Imp() )
+ {
+ pVSh->Imp()->DisposeAccessibleFrm( this );
+ }
+ }
+ }
+
+ SwLayoutFrm::Cut();
+}
+// <--
+
+//
+// Helper functions for repeated headlines:
+//
+
+/*
+ * SwTabFrm::IsInHeadline( const SwFrm& rFrm )
+ */
+bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
+{
+ OSL_ENSURE( IsAnLower( &rFrm ) && rFrm.IsInTab(),
+ "SwTabFrm::IsInHeadline called for frame not lower of table" );
+
+ const SwFrm* pTmp = &rFrm;
+ while ( !pTmp->GetUpper()->IsTabFrm() )
+ pTmp = pTmp->GetUpper();
+
+ return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
+}
+
+/*
+ * SwTabFrm::GetFirstNonHeadlineRow()
+ *
+ * If this is a master table, we can may assume, that there are at least
+ * nRepeat lines in the table.
+ * If this is a follow table, there are intermediate states for the table
+ * layout, e.g., during deletion of rows, which makes it necessary to find
+ * the first non-headline row by evaluating the headline flag at the row frame.
+ */
+SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
+{
+ SwRowFrm* pRet = (SwRowFrm*)Lower();
+ if ( pRet )
+ {
+ if ( IsFollow() )
+ {
+ while ( pRet && pRet->IsRepeatedHeadline() )
+ pRet = (SwRowFrm*)pRet->GetNext();
+ }
+ else
+ {
+ sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ while ( pRet && nRepeat > 0 )
+ {
+ pRet = (SwRowFrm*)pRet->GetNext();
+ --nRepeat;
+ }
+ }
+ }
+
+ return (SwRowFrm*)pRet;
+}
+
+/*
+ * SwTable::IsHeadline()
+ */
+bool SwTable::IsHeadline( const SwTableLine& rLine ) const
+{
+ for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
+ if ( GetTabLines()[ i ] == &rLine )
+ return true;
+
+ return false;
+}
+
+bool SwTabFrm::IsLayoutSplitAllowed() const
+{
+ return GetFmt()->GetLayoutSplit().GetValue();
+}
+
+// --> collapsing borders FME 2005-05-27 #i29550#
+
+sal_uInt16 SwTabFrm::GetBottomLineSize() const
+{
+ OSL_ENSURE( IsCollapsingBorders(),
+ "BottomLineSize only required for collapsing borders" );
+
+ OSL_ENSURE( Lower(), "Warning! Trying to prevent a crash, please inform FME" );
+
+ const SwFrm* pTmp = GetLastLower();
+
+ // --> FME 2005-12-07 #124755# Try to make code robust:
+ if ( !pTmp ) return 0;
+ // <--
+
+ return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
+}
+
+bool SwTabFrm::IsCollapsingBorders() const
+{
+ return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
+}
+
+// <-- collapsing
+
+
+//
+// Local helper function to calculate height of first text row
+//
+SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
+{
+ // Find corresponding split line in master table
+ const SwTabFrm* pTab = rSourceLine.FindTabFrm();
+ SWRECTFN( pTab )
+ const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
+
+ //
+ // 1. Case: rSourceLine is a follow flow line.
+ // In this case we have to return the minimum of the heights
+ // of the first lines in rSourceLine.
+ //
+ // 2. Case: rSourceLine is not a follow flow line.
+ // In this case we have to return the maximum of the heights
+ // of the first lines in rSourceLine.
+ //
+ bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
+ SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
+
+ while ( pCurrSourceCell )
+ {
+ // NEW TABLES
+ // Skip cells which are not responsible for the height of
+ // the follow flow line:
+ if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
+ {
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ continue;
+ }
+
+ const SwFrm *pTmp = pCurrSourceCell->Lower();
+ if ( pTmp )
+ {
+ SwTwips nTmpHeight = USHRT_MAX;
+ // --> FME 2004-09-14 #i32456# Consider lower row frames
+ if ( pTmp->IsRowFrm() )
+ {
+ const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
+ nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
+ }
+ // <--
+ if ( pTmp->IsTabFrm() )
+ {
+ nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
+ }
+ else if ( pTmp->IsTxtFrm() )
+ {
+ SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
+ pTxtFrm->GetFormatted();
+ nTmpHeight = pTxtFrm->FirstLineHeight();
+ }
+
+ if ( USHRT_MAX != nTmpHeight )
+ {
+ const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
+ if ( pPrevCell )
+ {
+ // If we are in a split row, there may be some space
+ // left in the cell frame of the master row.
+ // We look for the minimum of all first line heights;
+ SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
+ const SwFrm* pFrm = pPrevCell->Lower();
+ const SwFrm* pLast = pFrm;
+ while ( pFrm )
+ {
+ nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pLast = pFrm;
+ pFrm = pFrm->GetNext();
+ }
+
+ // --> FME, OD 2004-07-15 #i26831#, #i26520#
+ // The additional lower space of the current last.
+ // --> OD 2004-11-25 #115759# - do *not* consider the
+ // additional lower space for 'master' text frames
+ if ( pLast && pLast->IsFlowFrm() &&
+ ( !pLast->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
+ // <--
+ {
+ nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
+ }
+ // Don't forget the upper space and lower space,
+ // --> OD 2004-11-25 #115759# - do *not* consider the upper
+ // and the lower space for follow text frames.
+ if ( pTmp->IsFlowFrm() &&
+ ( !pTmp->IsTxtFrm() ||
+ !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
+ }
+ // <--
+ // --> OD 2004-11-25 #115759# - consider additional lower
+ // space of <pTmp>, if contains only one line.
+ // In this case it would be the new last text frame, which
+ // would have no follow and thus would add this space.
+ if ( pTmp->IsTxtFrm() &&
+ const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
+ ->GetLineCount( STRING_LEN ) == 1 )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
+ ->CalcAddLowerSpaceAsLastInTableCell();
+ }
+ // <--
+ if ( nReal > 0 )
+ nTmpHeight -= nReal;
+ }
+ else
+ {
+ // pFirstRow is not a FollowFlowRow. In this case,
+ // we look for the maximum of all first line heights:
+ SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
+ // --> OD 2004-07-16 #i26250#
+ // Don't forget the upper space and lower space,
+ if ( pTmp->IsFlowFrm() )
+ {
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
+ nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
+ }
+ // <--
+ }
+ }
+
+ if ( bIsInFollowFlowLine )
+ {
+ // minimum
+ if ( nTmpHeight < nHeight )
+ nHeight = nTmpHeight;
+ }
+ else
+ {
+ // maximum
+ if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
+ nHeight = nTmpHeight;
+ }
+ }
+
+ pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
+ }
+
+ return ( LONG_MAX == nHeight ) ? 0 : nHeight;
+}
+
+//
+// Function to calculate height of first text row
+//
+SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
+{
+ SWRECTFN( this )
+
+ const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
+
+ if ( bDontSplit )
+ {
+ // Table is not allowed to split: Take the whole height, that's all
+ return (Frm().*fnRect->fnGetHeight)();
+ }
+
+ SwRowFrm* pFirstRow = 0;
+ SwTwips nTmpHeight = 0;
+
+ pFirstRow = GetFirstNonHeadlineRow();
+ OSL_ENSURE( !IsFollow() || pFirstRow, "FollowTable without Lower" );
+
+ // NEW TABLES
+ if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
+ pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
+
+ // Calculate the height of the headlines:
+ const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
+ SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
+
+ // Calculate the height of the keeping lines
+ // (headlines + following keeping lines):
+ SwTwips nKeepHeight = nRepeatHeight;
+ if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
+ {
+ sal_uInt16 nKeepRows = nRepeat;
+
+ // Check how many rows want to keep together
+ while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
+ {
+ ++nKeepRows;
+ pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
+ }
+
+ if ( nKeepRows > nRepeat )
+ nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
+ }
+
+ // For master tables, the height of the headlines + the heigth of the
+ // keeping lines (if any) has to be considered. For follow tables, we
+ // only consider the height of the keeping rows without the repeated lines:
+ if ( !IsFollow() )
+ {
+ nTmpHeight = nKeepHeight;
+ }
+ else
+ {
+ nTmpHeight = nKeepHeight - nRepeatHeight;
+ }
+
+ // pFirstRow row is the first non-heading row.
+ // nTmpHeight is the height of the heading row if we are a follow.
+ if ( pFirstRow )
+ {
+ const bool bSplittable = pFirstRow->IsRowSplitAllowed();
+ const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
+
+ if ( !bSplittable )
+ {
+ // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
+ // actually is determined by a lower cell with rowspan = -1. In this case we should not
+ // just return the height of the first line. Basically we need to get the height of the
+ // line as it would be on the last page. Since this is quite complicated to calculate,
+ // we olny calculate the height of the first line.
+ if ( pFirstRow->GetPrev() &&
+ static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
+ {
+ // Calculate maximum height of all cells with rowspan = 1:
+ SwTwips nMaxHeight = 0;
+ const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
+ while ( pLower2 )
+ {
+ if ( 1 == pLower2->GetTabBox()->getRowSpan() )
+ {
+ const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True );
+ nMaxHeight = Max( nCellHeight, nMaxHeight );
+ }
+ pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
+ }
+ nTmpHeight += nMaxHeight;
+ }
+ else
+ {
+ nTmpHeight += nFirstLineHeight;
+ }
+ }
+
+ // --> FME 2004-11-18 #118411#
+ // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
+ // a formatting of the row frame (via the GetFormatted()). We don't
+ // want this formatting if the row does not have a height.
+ else if ( 0 != nFirstLineHeight )
+ // <--
+ {
+ const bool bOldJoinLock = IsJoinLocked();
+ ((SwTabFrm*)this)->LockJoin();
+ const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
+
+ // Consider minimum row height:
+ const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
+ const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
+ rSz.GetHeight() : 0;
+
+ nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight );
+
+ if ( !bOldJoinLock )
+ ((SwTabFrm*)this)->UnlockJoin();
+ }
+ }
+
+ return nTmpHeight;
+}
+
+//
+// Some more functions for covered/covering cells. This way inclusion of
+// SwCellFrm can be avoided
+//
+
+bool SwFrm::IsLeaveUpperAllowed() const
+{
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
+}
+
+bool SwFrm::IsCoveredCell() const
+{
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
+}
+
+bool SwFrm::IsInCoveredCell() const
+{
+ bool bRet = false;
+
+ const SwFrm* pThis = this;
+ while ( pThis && !pThis->IsCellFrm() )
+ pThis = pThis->GetUpper();
+
+ if ( pThis )
+ bRet = pThis->IsCoveredCell();
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx
new file mode 100644
index 000000000000..2673082d5468
--- /dev/null
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -0,0 +1,2611 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <tools/bigint.hxx>
+#include <editeng/protitem.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/outdev.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtsrnd.hxx>
+#include <pagedesc.hxx>
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <ftnfrm.hxx>
+#include <flyfrm.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <txtfrm.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <doc.hxx>
+#include <viscrs.hxx>
+#include <frmfmt.hxx>
+#include <swtable.hxx>
+#include <dflyobj.hxx>
+#include <crstate.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+// FLT_MAX
+#include <cfloat>
+#include <swselectionlist.hxx>
+
+//Fuer SwFlyFrm::GetCrsrOfst
+class SwCrsrOszControl
+{
+public:
+ // damit schon der Compiler die Klasse initialisieren kann, keinen
+ // DTOR und member als publics:
+ const SwFlyFrm *pEntry;
+ const SwFlyFrm *pStk1;
+ const SwFlyFrm *pStk2;
+
+//public:
+// SwCrsrOszControl() : pStk1( 0 ), pStk2( 0 ) {}; // ; <- ????
+
+ sal_Bool ChkOsz( const SwFlyFrm *pFly )
+ {
+ sal_Bool bRet = sal_True;
+ if ( pFly != pStk1 && pFly != pStk2 )
+ {
+ pStk1 = pStk2;
+ pStk2 = pFly;
+ bRet = sal_False;
+ }
+ return bRet;
+ }
+ void Entry( const SwFlyFrm *pFly )
+ {
+ if ( !pEntry )
+ pEntry = pStk1 = pFly;
+ }
+ void Exit( const SwFlyFrm *pFly )
+ {
+ if ( pFly == pEntry )
+ pEntry = pStk1 = pStk2 = 0;
+ }
+};
+
+static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Sucht denjenigen CntntFrm, innerhalb dessen
+|* PrtArea der Point liegt.
+|*
+|*************************************************************************/
+sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bRet = sal_False;
+ const SwFrm *pFrm = Lower();
+ while ( !bRet && pFrm )
+ {
+ pFrm->Calc();
+
+ // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
+ const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
+ const SwRect aPaintRect( bCntntCheck ?
+ pFrm->UnionFrm() :
+ pFrm->PaintArea() );
+ // <--
+
+ if ( aPaintRect.IsInside( rPoint ) &&
+ ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
+ bRet = sal_True;
+ else
+ pFrm = pFrm->GetNext();
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Sucht die Seite, innerhalb der der gesuchte Point
+|* liegt.
+|*
+|*************************************************************************/
+
+sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bRet = sal_False;
+ Point aPoint( rPoint );
+
+ // check, if we have to adjust the point
+ if ( !Frm().IsInside( aPoint ) )
+ {
+ aPoint.X() = Max( aPoint.X(), Frm().Left() );
+ aPoint.X() = Min( aPoint.X(), Frm().Right() );
+ aPoint.Y() = Max( aPoint.Y(), Frm().Top() );
+ aPoint.Y() = Min( aPoint.Y(), Frm().Bottom() );
+ }
+
+ //Wenn kein Cntnt unterhalb der Seite 'antwortet', so korrigieren
+ //wir den StartPoint und fangen nochmal eine Seite vor der
+ //aktuellen an. Mit Flys ist es dann allerdings vorbei.
+ if ( SwLayoutFrm::GetCrsrOfst( pPos, aPoint, pCMS ) )
+ bRet = sal_True;
+ else
+ {
+ if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return sal_False;
+ }
+ const SwCntntFrm *pCnt = GetCntntPos( aPoint, sal_False, sal_False, sal_False, pCMS, sal_False );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+
+ OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
+ if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
+ bRet = pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ else
+ bRet = pCnt->GetCrsrOfst( pPos, aPoint, pCMS );
+
+ if ( !bRet )
+ {
+ // Set point to pCnt, delete mark
+ // this may happen, if pCnt is hidden
+ *pPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
+ bRet = sal_True;
+ }
+ }
+
+ if ( !bRet )
+ {
+ //Koennte ein Freifliegender gemeint sein?
+ //Wenn sein Inhalt geschuetzt werden soll, so ist nix mit Crsr
+ //hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
+ if ( GetSortedObjs() )
+ {
+ SwOrderIter aIter( this );
+ aIter.Top();
+ while ( aIter() )
+ {
+ const SwVirtFlyDrawObj* pObj =
+ static_cast<const SwVirtFlyDrawObj*>(aIter());
+ const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
+ if ( pFly &&
+ ( ( pCMS ? pCMS->bSetInReadOnly : sal_False ) ||
+ !pFly->IsProtected() ) &&
+ pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
+ {
+ bRet = sal_True;
+ break;
+ }
+
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ aIter.Prev();
+ }
+ }
+ }
+
+ if ( bRet )
+ rPoint = aPoint;
+
+ return bRet;
+}
+
+bool SwLayoutFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
+{
+ bool bRet = false;
+ if( rRect.IsOver(PaintArea()) )
+ {
+ const SwFrm* pFrm = Lower();
+ while( pFrm )
+ {
+ pFrm->FillSelection( rList, rRect );
+ pFrm = pFrm->GetNext();
+ }
+ }
+ return bRet;
+}
+
+bool SwPageFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
+{
+ bool bRet = false;
+ if( rRect.IsOver(PaintArea()) )
+ {
+ bRet = SwLayoutFrm::FillSelection( rList, rRect );
+ if( GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ if( pFly->FillSelection( rList, rRect ) )
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
+{
+ const SwFrm *pPage = Lower();
+ const long nBottom = rRect.Bottom();
+ while( pPage )
+ {
+ if( pPage->Frm().Top() < nBottom )
+ {
+ if( pPage->Frm().Bottom() > rRect.Top() )
+ pPage->FillSelection( aSelList, rRect );
+ pPage = pPage->GetNext();
+ }
+ else
+ pPage = 0;
+ }
+ return !aSelList.isEmpty();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetCrsrOfst()
+|*
+|* Beschreibung: Reicht Primaer den Aufruf an die erste Seite weiter.
+|* Wenn der 'reingereichte Point veraendert wird,
+|* so wird sal_False zurueckgegeben.
+|*
+|*************************************************************************/
+sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ sal_Bool bOldAction = IsCallbackActionEnabled();
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
+ OSL_ENSURE( (Lower() && Lower()->IsPageFrm()), "Keinen PageFrm gefunden." );
+ if( pCMS && pCMS->pFill )
+ ((SwCrsrMoveState*)pCMS)->bFillRet = sal_False;
+ Point aOldPoint = rPoint;
+
+ // PAGES01
+ // search for page containing rPoint. The borders around the pages are considerd
+ const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
+
+ // --> OD 2008-12-23 #i95626#
+ // special handling for <rPoint> beyond root frames area
+ if ( !pPage &&
+ rPoint.X() > Frm().Right() &&
+ rPoint.Y() > Frm().Bottom() )
+ {
+ pPage = dynamic_cast<const SwPageFrm*>(Lower());
+ while ( pPage && pPage->GetNext() )
+ {
+ pPage = dynamic_cast<const SwPageFrm*>(pPage->GetNext());
+ }
+ }
+ // <--
+ if ( pPage )
+ {
+ pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS );
+ }
+
+ ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
+ if( pCMS )
+ {
+ if( pCMS->bStop )
+ return sal_False;
+ if( pCMS->pFill )
+ return pCMS->bFillRet;
+ }
+ return aOldPoint == rPoint;
+}
+
+/*************************************************************************
+|*
+|* SwCellFrm::GetCrsrOfst()
+|*
+|* Beschreibung Wenn es sich um eine Cntnt-tragende Cell handelt wird
+|* der Crsr notfalls mit Gewalt in einen der CntntFrms
+|* gesetzt.
+|* In geschuetzte Zellen gibt es hier keinen Eingang.
+|*
+|*************************************************************************/
+sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ // cell frame does not necessarily have a lower (split table cell)
+ if ( !Lower() )
+ return sal_False;
+
+ if ( !(pCMS?pCMS->bSetInReadOnly:sal_False) &&
+ GetFmt()->GetProtect().IsCntntProtected() )
+ return sal_False;
+
+ if ( pCMS && pCMS->eState == MV_TBLSEL )
+ {
+ const SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return sal_False;
+ }
+ }
+
+ if ( Lower() )
+ {
+ if ( Lower()->IsLayoutFrm() )
+ return SwLayoutFrm::GetCrsrOfst( pPos, rPoint, pCMS );
+ else
+ {
+ Calc();
+ sal_Bool bRet = sal_False;
+
+ const SwFrm *pFrm = Lower();
+ while ( pFrm && !bRet )
+ {
+ pFrm->Calc();
+ if ( pFrm->Frm().IsInside( rPoint ) )
+ {
+ bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if ( !bRet )
+ {
+ Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
+ const SwCntntFrm *pCnt = GetCntntPos( rPoint, sal_True );
+ if( pPoint && pCnt->IsTxtFrm() )
+ {
+ pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
+ rPoint = *pPoint;
+ }
+ else
+ pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ delete pPoint;
+ }
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFlyFrm::GetCrsrOfst()
+|*
+|*************************************************************************/
+//Problem: Wenn zwei Flys genau gleich gross sind und auf derselben
+//Position stehen, so liegt jeder innerhalb des anderen.
+//Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines
+//anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet
+//und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer
+//endlosen Rekursion fuehren.
+//Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das
+//GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der
+//am weitesten oben liegt.
+
+sal_Bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
+ SwCrsrMoveState* pCMS ) const
+{
+ aOszCtrl.Entry( this );
+
+ //Wenn der Point innerhalb des Fly sitzt wollen wir energisch
+ //versuchen den Crsr hineinzusetzen.
+ //Wenn der Point allerdings in einem Flys sitzt, der sich vollstaendig
+ //innerhalb des aktuellen befindet, so wird fuer diesen das
+ //GetCrsrOfst gerufen.
+ Calc();
+ sal_Bool bInside = Frm().IsInside( rPoint ) && Lower(),
+ bRet = sal_False;
+
+ //Wenn der Frm eine Grafik enthaelt, aber nur Text gewuenscht ist, so
+ //nimmt er den Crsr grundsaetzlich nicht an.
+ if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
+ (!Lower() || Lower()->IsNoTxtFrm()) )
+ bInside = sal_False;
+
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( bInside && pPage && pPage->GetSortedObjs() )
+ {
+ SwOrderIter aIter( pPage );
+ aIter.Top();
+ while ( aIter() && !bRet )
+ {
+ const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
+ const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
+ if ( pFly && pFly->Frm().IsInside( rPoint ) &&
+ Frm().IsInside( pFly->Frm() ) )
+ {
+ if ( aOszCtrl.ChkOsz( pFly ) ||
+ sal_True == (bRet = pFly->GetCrsrOfst( pPos, rPoint, pCMS )))
+ break;
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ aIter.Next();
+ }
+ }
+
+ while ( bInside && !bRet )
+ {
+ const SwFrm *pFrm = Lower();
+ while ( pFrm && !bRet )
+ {
+ pFrm->Calc();
+ if ( pFrm->Frm().IsInside( rPoint ) )
+ {
+ bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ }
+ pFrm = pFrm->GetNext();
+ }
+ if ( !bRet )
+ {
+ Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
+ const SwCntntFrm *pCnt = GetCntntPos(
+ rPoint, sal_True, sal_False, sal_False, pCMS );
+ if ( pCMS && pCMS->bStop )
+ return sal_False;
+ if( pPoint && pCnt->IsTxtFrm() )
+ {
+ pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
+ rPoint = *pPoint;
+ }
+ else
+ pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
+ delete pPoint;
+ bRet = sal_True;
+ }
+ }
+ aOszCtrl.Exit( this );
+ return bRet;
+}
+
+/*************************************************************************
+|*
+|* Beschreibung Layoutabhaengiges Cursortravelling
+|*
+|*************************************************************************/
+sal_Bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
+{
+ if( pPam->GetNode() != (SwCntntNode*)GetNode() )
+ return sal_False;
+ ((SwCntntNode*)GetNode())->
+ MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
+ return sal_True;
+}
+
+sal_Bool SwCntntFrm::RightMargin(SwPaM *pPam, sal_Bool) const
+{
+ if( pPam->GetNode() != (SwCntntNode*)GetNode() )
+ return sal_False;
+ ((SwCntntNode*)GetNode())->
+ MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
+ return sal_True;
+}
+
+const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
+{
+ return pCnt->GetNextCntntFrm();
+}
+
+const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
+{
+ return pCnt->GetPrevCntntFrm();
+}
+
+typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
+
+//Frame in wiederholter Headline?
+sal_Bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
+ const SwTabFrm** ppTFrm = 0 )
+{
+ const SwTabFrm *pTab = pFrm->FindTabFrm();
+ if( ppTFrm )
+ *ppTFrm = pTab;
+ return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
+}
+
+
+//Ueberspringen geschuetzter Tabellenzellen. Optional auch
+//Ueberspringen von wiederholten Headlines.
+//MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen.
+// FME: Skip follow flow cells
+const SwCntntFrm * MA_FASTCALL lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
+ GetNxtPrvCnt fnNxtPrv,
+ sal_Bool bMissHeadline,
+ sal_Bool bInReadOnly,
+ sal_Bool bMissFollowFlowLine )
+{
+ if ( pCnt && pCnt->IsInTab() )
+ {
+ sal_Bool bProtect = sal_True;
+ while ( pCnt && bProtect )
+ {
+ const SwLayoutFrm *pCell = pCnt->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ if ( !pCell ||
+ (( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
+ ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
+ ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
+ !pCell->IsCoveredCell()) ) )
+ bProtect = sal_False;
+ else
+ pCnt = (*fnNxtPrv)( pCnt );
+ }
+ }
+ else if ( !bInReadOnly )
+ while ( pCnt && pCnt->IsProtected() )
+ pCnt = (*fnNxtPrv)( pCnt );
+
+ return pCnt;
+}
+
+sal_Bool MA_FASTCALL lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
+ GetNxtPrvCnt fnNxtPrv, sal_Bool bInReadOnly )
+{
+ OSL_ENSURE( pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
+ "lcl_UpDown arbeitet nicht fuer andere." );
+
+ const SwCntntFrm *pCnt = 0;
+
+ //Wenn gerade eine Tabellenselection laeuft muss ein bischen getricktst
+ //werden: Beim hochlaufen an den Anfang der Zelle gehen, beim runterlaufen
+ //an das Ende der Zelle gehen.
+ sal_Bool bTblSel = false;
+ if ( pStart->IsInTab() &&
+ pPam->GetNode( sal_True )->StartOfSectionNode() !=
+ pPam->GetNode( sal_False )->StartOfSectionNode() )
+ {
+ bTblSel = true;
+ const SwLayoutFrm *pCell = pStart->GetUpper();
+ while ( !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+
+ //
+ // Check, if cell has a Prev/Follow cell:
+ //
+ const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
+ const SwLayoutFrm* pTmpCell = bFwd ?
+ ((SwCellFrm*)pCell)->GetFollowCell() :
+ ((SwCellFrm*)pCell)->GetPreviousCell();
+
+ const SwCntntFrm* pTmpStart = pStart;
+ while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
+ {
+ pCell = pTmpCell;
+ pTmpCell = bFwd ?
+ ((SwCellFrm*)pCell)->GetFollowCell() :
+ ((SwCellFrm*)pCell)->GetPreviousCell();
+ }
+ const SwCntntFrm *pNxt = pCnt = pTmpStart;
+
+ while ( pCell->IsAnLower( pNxt ) )
+ {
+ pCnt = pNxt;
+ pNxt = (*fnNxtPrv)( pNxt );
+ }
+ }
+
+ pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+
+
+ const SwTabFrm *pStTab = pStart->FindTabFrm();
+ const SwTabFrm *pTable = 0;
+ const sal_Bool bTab = pStTab || (pCnt && pCnt->IsInTab()) ? sal_True : sal_False;
+ sal_Bool bEnd = bTab ? sal_False : sal_True;
+
+ const SwFrm* pVertRefFrm = pStart;
+ if ( bTblSel && pStTab )
+ pVertRefFrm = pStTab;
+ SWRECTFN( pVertRefFrm )
+
+ SwTwips nX = 0;
+ if ( bTab )
+ {
+ //
+ // pStart or pCnt is inside a table. nX will be used for travelling:
+ //
+ SwRect aRect( pStart->Frm() );
+ pStart->GetCharRect( aRect, *pPam->GetPoint() );
+ Point aCenter = aRect.Center();
+ nX = bVert ? aCenter.Y() : aCenter.X();
+
+ pTable = pCnt ? pCnt->FindTabFrm() : 0;
+ if ( !pTable )
+ pTable = pStTab;
+
+ if ( pStTab &&
+ !pStTab->GetUpper()->IsInTab() &&
+ !pTable->GetUpper()->IsInTab() )
+ {
+ const SwFrm *pCell = pStart->GetUpper();
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell, "Zelle nicht gefunden." );
+ nX = (pCell->Frm().*fnRect->fnGetLeft)() +
+ (pCell->Frm().*fnRect->fnGetWidth)() / 2;
+
+ //Der Fluss fuehrt von einer Tabelle in die nachste. Der X-Wert
+ //muss ausgehend von der Mitte der Startzelle um die Verschiebung
+ //der Tabellen korrigiert werden.
+ if ( pStTab != pTable )
+ {
+ nX += (pTable->Frm().*fnRect->fnGetLeft)() -
+ (pStTab->Frm().*fnRect->fnGetLeft)();
+ }
+ }
+
+ //
+ // Restrict nX to the left and right borders of pTab:
+ // (is this really necessary?)
+ //
+ if ( !pTable->GetUpper()->IsInTab() )
+ {
+ const sal_Bool bRTL = pTable->IsRightToLeft();
+ const long nPrtLeft = bRTL ?
+ (pTable->*fnRect->fnGetPrtRight)() :
+ (pTable->*fnRect->fnGetPrtLeft)();
+ if ( bRTL != (nX < nPrtLeft) )
+ nX = nPrtLeft;
+ else
+ {
+ const long nPrtRight = bRTL ?
+ (pTable->*fnRect->fnGetPrtLeft)() :
+ (pTable->*fnRect->fnGetPrtRight)();
+ if ( bRTL != (nX > nPrtRight) )
+ nX = nPrtRight;
+ }
+ }
+ }
+
+ do
+ {
+ //Wenn ich im DokumentBody bin, so will ich da auch bleiben
+ if ( pStart->IsInDocBody() )
+ {
+ while ( pCnt && (!pCnt->IsInDocBody() ||
+ (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //Wenn ich im Fussnotenbereich bin, so versuche ich notfalls den naechsten
+ //Fussnotenbereich zu erreichen.
+ else if ( pStart->IsInFtn() )
+ {
+ while ( pCnt && (!pCnt->IsInFtn() ||
+ (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //In Flys kann es Blind weitergehen solange ein Cntnt
+ //gefunden wird.
+ else if ( pStart->IsInFly() )
+ {
+ if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ //Andernfalls weigere ich mich einfach den derzeitigen Bereich zu
+ //verlassen.
+ else if ( pCnt )
+ {
+ const SwFrm *pUp = pStart->GetUpper(); //Head/Foot
+ while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
+ pUp = pUp->GetUpper();
+ sal_Bool bSame = sal_False;
+ const SwFrm *pCntUp = pCnt->GetUpper();
+ while ( pCntUp && !bSame )
+ { if ( pUp == pCntUp )
+ bSame = sal_True;
+ else
+ pCntUp = pCntUp->GetUpper();
+ }
+ if ( !bSame )
+ pCnt = 0;
+ else if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ if ( bTab )
+ {
+ if ( !pCnt )
+ bEnd = sal_True;
+ else
+ { const SwTabFrm *pTab = pCnt->FindTabFrm();
+ if( !pTab )
+ bEnd = sal_True;
+ else
+ {
+ if ( pTab != pTable )
+ {
+ //Der Fluss fuehrt von einer Tabelle in die nachste. Der
+ //X-Wert muss um die Verschiebung der Tabellen korrigiert
+ //werden.
+ if ( pTable &&
+ !pTab->GetUpper()->IsInTab() &&
+ !pTable->GetUpper()->IsInTab() )
+ nX += pTab->Frm().Left() - pTable->Frm().Left();
+ pTable = pTab;
+ }
+ const SwLayoutFrm *pCell = pTable ? pCnt->GetUpper() : 0;
+ while ( pCell && !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+
+ Point aInsideCell;
+ Point aInsideCnt;
+ if ( pCell )
+ {
+ long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
+ if ( bVert )
+ {
+ if ( nTmpTop )
+ --nTmpTop;
+
+ aInsideCell = Point( nTmpTop, nX );
+ }
+ else
+ aInsideCell = Point( nX, nTmpTop );
+ }
+
+ long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
+ if ( bVert )
+ {
+ if ( nTmpTop )
+ --nTmpTop;
+
+ aInsideCnt = Point( nTmpTop, nX );
+ }
+ else
+ aInsideCnt = Point( nX, nTmpTop );
+
+ if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
+ {
+ bEnd = sal_True;
+ //Jetzt noch schnell den richtigen Cntnt in der Zelle
+ //greifen.
+ if ( !pCnt->Frm().IsInside( aInsideCnt ) )
+ {
+ pCnt = pCell->ContainsCntnt();
+ if ( fnNxtPrv == lcl_GetPrvCnt )
+ while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+ }
+ else if ( pCnt->Frm().IsInside( aInsideCnt ) )
+ bEnd = sal_True;
+ }
+ }
+ if ( !bEnd )
+ {
+ pCnt = (*fnNxtPrv)( pCnt );
+ pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
+ }
+ }
+
+ } while ( !bEnd ||
+ (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
+
+ if( pCnt )
+ { // setze den Point auf den Content-Node
+ SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
+ pPam->GetPoint()->nNode = *pCNd;
+ if ( fnNxtPrv == lcl_GetPrvCnt )
+ pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
+ else
+ pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
+{
+ return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
+}
+
+sal_Bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
+{
+ return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetCurrPage()
+|*
+|* Beschreibung: Liefert die Nummer der aktuellen Seite.
+|* Wenn die Methode einen PaM bekommt, so ist die aktuelle Seite
+|* diejenige in der der PaM sitzt. Anderfalls ist die aktuelle
+|* Seite die erste Seite innerhalb der VisibleArea.
+|* Es wird nur auf den vorhandenen Seiten gearbeitet!
+|*
+|*************************************************************************/
+sal_uInt16 SwRootFrm::GetCurrPage( const SwPaM *pActualCrsr ) const
+{
+ OSL_ENSURE( pActualCrsr, "Welche Seite soll's denn sein?" );
+ SwFrm const*const pActFrm = pActualCrsr->GetPoint()->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, 0,
+ pActualCrsr->GetPoint(),
+ sal_False );
+ return pActFrm->FindPageFrm()->GetPhyPageNum();
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::SetCurrPage()
+|*
+|* Beschreibung: Liefert einen PaM der am Anfang der gewuenschten
+|* Seite sitzt.
+|* Formatiert wird soweit notwendig
+|* Liefert Null, wenn die Operation nicht moeglich ist.
+|* Der PaM sitzt in der letzten Seite, wenn die Seitenzahl zu gross
+|* gewaehlt wurde.
+|*
+|*************************************************************************/
+sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
+
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ sal_Bool bEnd =sal_False;
+ while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
+ { if ( pPage->GetNext() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ { //Ersten CntntFrm Suchen, und solange Formatieren bis
+ //eine neue Seite angefangen wird oder bis die CntntFrm's alle
+ //sind.
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ while ( pCntnt && pPage->IsAnLower( pCntnt ) )
+ {
+ pCntnt->Calc();
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ //Jetzt ist entweder eine neue Seite da, oder die letzte Seite
+ //ist gefunden.
+ if ( pPage->GetNext() )
+ pPage = (SwPageFrm*)pPage->GetNext();
+ else
+ bEnd = sal_True;
+ }
+ }
+ //pPage zeigt jetzt auf die 'gewuenschte' Seite. Jetzt muss noch der
+ //PaM auf den Anfang des ersten CntntFrm im Body-Text erzeugt werden.
+ //Wenn es sich um eine Fussnotenseite handelt, wird der PaM in die erste
+ //Fussnote gesetzt.
+ const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
+ if ( pPage->IsFtnPage() )
+ while ( pCntnt && !pCntnt->IsInFtn() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ else
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( pCntnt )
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
+ pToSet->GetPoint()->nNode = *pCNd;
+ pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
+ pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
+
+ SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
+ if( pSCrsr )
+ {
+ Point &rPt = pSCrsr->GetPtPos();
+ rPt = pCntnt->Frm().Pos();
+ rPt += pCntnt->Prt().Pos();
+ }
+ return pPage->GetPhyPageNum();
+ }
+ return 0;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::StartxxPage(), EndxxPage()
+|*
+|* Beschreibung Cursor an Anfang/Ende der aktuellen/vorherigen/
+|* naechsten Seite. Alle sechs Methoden rufen GetFrmInPage() mit der
+|* entsprechenden Parametrisierung.
+|* Zwei Parameter steuern die Richtung: einer bestimmt die Seite, der
+|* andere Anfang/Ende.
+|* Fuer die Bestimmung der Seite und des Cntnt (Anfang/Ende) werden
+|* die im folgenden definierten Funktionen benutzt.
+|*
+|*************************************************************************/
+SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
+{
+ return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
+}
+
+SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
+{
+ return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
+}
+
+SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
+{
+ SwLayoutFrm *pNext =
+ (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pFrm->GetNext() : 0;
+ // #i39402# in case of an empty page
+ if(pNext && !pNext->ContainsCntnt())
+ pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pNext->GetNext() : 0;
+ return pNext;
+}
+
+SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
+{
+ return (SwLayoutFrm*)pFrm;
+}
+
+SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
+{
+ SwLayoutFrm *pPrev =
+ (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pFrm->GetPrev() : 0;
+ // #i39402# in case of an empty page
+ if(pPrev && !pPrev->ContainsCntnt())
+ pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
+ (SwLayoutFrm*)pPrev->GetPrev() : 0;
+ return pPrev;
+}
+
+//Jetzt koennen auch die Funktionspointer initalisiert werden;
+//sie sind in cshtyp.hxx declariert.
+SwPosPage fnPageStart = GetFirstSub;
+SwPosPage fnPageEnd = GetLastSub;
+SwWhichPage fnPagePrev = GetPrevFrm;
+SwWhichPage fnPageCurr = GetThisFrm;
+SwWhichPage fnPageNext = GetNextFrm;
+
+//Liefert den ersten/den letzten Contentframe (gesteuert ueber
+//den Parameter fnPosPage) in der
+//aktuellen/vorhergehenden/folgenden Seite (gesteuert durch den
+//Parameter fnWhichPage).
+sal_Bool GetFrmInPage( const SwCntntFrm *pCnt, SwWhichPage fnWhichPage,
+ SwPosPage fnPosPage, SwPaM *pPam )
+{
+ //Erstmal die gewuenschte Seite besorgen, anfangs die aktuelle, dann
+ //die die per fnWichPage gewuenscht wurde
+ const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
+ if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
+ return sal_False;
+
+ //Jetzt den gewuenschen CntntFrm unterhalb der Seite
+ if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
+ return sal_False;
+ else
+ {
+ // repeated headlines in tables
+ if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
+ {
+ const SwTabFrm* pTab = pCnt->FindTabFrm();
+ if ( pTab->IsFollow() )
+ {
+ if ( pTab->IsInHeadline( *pCnt ) )
+ {
+ SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
+ if ( pRow )
+ {
+ // We are in the first line of a follow table
+ // with repeated headings.
+ // To actually make a "real" move we take the first content
+ // of the next row
+ pCnt = pRow->ContainsCntnt();
+ if ( ! pCnt )
+ return sal_False;
+ }
+ }
+ }
+ }
+
+ SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
+ pPam->GetPoint()->nNode = *pCNd;
+ xub_StrLen nIdx;
+ if( fnPosPage == GetFirstSub )
+ nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
+ else
+ nIdx = pCnt->GetFollow() ?
+ ((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
+ pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
+ return sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GetCntntPos()
+|*
+|* Beschreibung Es wird der nachstliegende Cntnt zum uebergebenen
+|* gesucht. Betrachtet werden die vorhergehende, die
+|* aktuelle und die folgende Seite.
+|* Wenn kein Inhalt gefunden wird, so wird der Bereich
+ * erweitert bis einer gefunden wird.
+|* Zurueckgegeben wird die 'Semantisch richtige' Position
+|* innerhalb der PrtArea des gefundenen CntntFrm
+|*
+|*************************************************************************/
+sal_uLong CalcDiff( const Point &rPt1, const Point &rPt2 )
+{
+ //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
+ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
+ sal_uInt32 dX = Max( rPt1.X(), rPt2.X() ) -
+ Min( rPt1.X(), rPt2.X() ),
+ dY = Max( rPt1.Y(), rPt2.Y() ) -
+ Min( rPt1.Y(), rPt2.Y() );
+ BigInt dX1( dX ), dY1( dY );
+ dX1 *= dX1; dY1 *= dY1;
+ return ::SqRt( dX1 + dY1 );
+}
+
+// lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem
+// auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang
+// Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer.
+// Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt,
+// eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn
+// dessen Abstand zum Punkt geringer ist.
+
+const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
+{
+ const SwLayoutFrm* pUp = pCnt->GetUpper();
+ while( pUp )
+ {
+ if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
+ {
+ if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
+ return pUp;
+ return NULL;
+ }
+ if( pUp->IsFtnContFrm() )
+ return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
+ pUp = pUp->GetUpper();
+ }
+ return NULL;
+}
+
+const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint,
+ const sal_Bool bDontLeave,
+ const sal_Bool bBodyOnly,
+ const sal_Bool bCalc,
+ const SwCrsrMoveState *pCMS,
+ const sal_Bool bDefaultExpand ) const
+{
+ //Ersten CntntFrm ermitteln.
+ const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
+ (SwLayoutFrm*)GetPrev() : this;
+ const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
+
+ if ( !pCntnt && (GetPrev() && !bDontLeave) )
+ pCntnt = ContainsCntnt();
+
+ if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+
+ const SwCntntFrm *pActual= pCntnt;
+ const SwLayoutFrm *pInside = NULL;
+ sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
+ Point aPoint = rPoint;
+ sal_uLong nDistance = ULONG_MAX;
+
+ while ( sal_True ) //Sicherheitsschleifchen, damit immer einer gefunden wird.
+ {
+ while ( pCntnt &&
+ ((!bDontLeave || IsAnLower( pCntnt )) &&
+ (pCntnt->GetPhyPageNum() <= nMaxPage)) )
+ {
+ if ( ( bCalc || pCntnt->Frm().Width() ) &&
+ ( !bBodyOnly || pCntnt->IsInDocBody() ) )
+ {
+ //Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section)
+ //liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht.
+ const SwCntntFrm *pComp = pCntnt;
+ pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, sal_False,
+ pCMS ? pCMS->bSetInReadOnly : sal_False, sal_False );
+ if ( pComp != pCntnt )
+ continue;
+
+ if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
+ {
+ if ( bCalc )
+ pCntnt->Calc();
+
+ SwRect aCntFrm( pCntnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPoint ) )
+ {
+ pActual = pCntnt;
+ aPoint = rPoint;
+ break;
+ }
+ //Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird
+ //jetzt berechnet.
+ Point aCntntPoint( rPoint );
+
+ //Erst die Vertikale Position einstellen
+ if ( aCntFrm.Top() > aCntntPoint.Y() )
+ aCntntPoint.Y() = aCntFrm.Top();
+ else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
+ aCntntPoint.Y() = aCntFrm.Bottom();
+
+ //Jetzt die Horizontale Position
+ if ( aCntFrm.Left() > aCntntPoint.X() )
+ aCntntPoint.X() = aCntFrm.Left();
+ else if ( aCntFrm.Right() < aCntntPoint.X() )
+ aCntntPoint.X() = aCntFrm.Right();
+
+ // pInside ist ein Seitenbereich, in dem der Punkt liegt,
+ // sobald pInside!=0 ist, werden nur noch Frames akzeptiert,
+ // die innerhalb liegen.
+ if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
+ ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
+ {
+ const sal_uLong nDiff = ::CalcDiff( aCntntPoint, rPoint );
+ sal_Bool bBetter = nDiff < nDistance; // Dichter dran
+ if( !pInside )
+ {
+ pInside = lcl_Inside( pCntnt, rPoint );
+ if( pInside ) // Im "richtigen" Seitenteil
+ bBetter = sal_True;
+ }
+ if( bBetter )
+ {
+ aPoint = aCntntPoint;
+ nDistance = nDiff;
+ pActual = pCntnt;
+ }
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( bBodyOnly )
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+ if ( !pActual )
+ { //Wenn noch keiner gefunden wurde muss der Suchbereich erweitert
+ //werden, irgenwann muessen wir einen Finden!
+ //MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im
+ //Body suchen, koennen wir den Suchbereich gleich in einem
+ //Schritt hinreichend erweitern.
+ if ( bBodyOnly )
+ {
+ while ( !pCntnt && pStart->GetPrev() )
+ {
+ ++nMaxPage;
+ if( !pStart->GetPrev()->IsLayoutFrm() )
+ return 0;
+ pStart = (SwLayoutFrm*)pStart->GetPrev();
+ pCntnt = pStart->IsInDocBody()
+ ? pStart->ContainsCntnt()
+ : pStart->FindPageFrm()->FindFirstBodyCntnt();
+ }
+ if ( !pCntnt ) //irgendwann muessen wir mit irgendeinem Anfangen!
+ {
+ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ if ( !pCntnt )
+ return 0; //Es gibt noch keine Dokumentinhalt!
+ }
+ }
+ else
+ {
+ ++nMaxPage;
+ if ( pStart->GetPrev() )
+ {
+ if( !pStart->GetPrev()->IsLayoutFrm() )
+ return 0;
+ pStart = (SwLayoutFrm*)pStart->GetPrev();
+ pCntnt = pStart->ContainsCntnt();
+ }
+ else //irgendwann muessen wir mit irgendeinem Anfangen!
+ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
+ }
+ pActual = pCntnt;
+ }
+ else
+ break;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pActual, "Keinen Cntnt gefunden." );
+ if ( bBodyOnly )
+ OSL_ENSURE( pActual->IsInDocBody(), "Cnt nicht im Body." );
+#endif
+
+ //Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte
+ //TblHedlines.
+ if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL )
+ {
+ const SwTabFrm *pTab = pActual->FindTabFrm();
+ if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
+ {
+ ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
+ return 0;
+ }
+ }
+
+ //Jetzt noch eine kleine Korrektur beim ersten/letzten
+ Size aActualSize( pActual->Prt().SSize() );
+ if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
+ aActualSize.Height() = pActual->GetUpper()->Prt().Height();
+
+ SWRECTFN( pActual )
+ if ( !pActual->GetPrev() &&
+ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
+ bVert ? rPoint.X() : rPoint.Y() ) > 0 )
+ {
+ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
+ aPoint.X() = pActual->Frm().Left() +
+ ( pActual->IsRightToLeft() || bVert ?
+ pActual->Prt().Right() :
+ pActual->Prt().Left() );
+ }
+ else if ( !pActual->GetNext() &&
+ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
+ bVert ? rPoint.X() : rPoint.Y() ) < 0 )
+ {
+ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
+ aPoint.X() = pActual->Frm().Left() +
+ ( pActual->IsRightToLeft() || bVert ?
+ pActual->Prt().Left() :
+ pActual->Prt().Right() );
+ }
+
+ //Und den Point in die PrtArea bringen
+ if ( bCalc )
+ pActual->Calc();
+ const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
+ aActualSize );
+ if ( aPoint.Y() < aRect.Top() )
+ aPoint.Y() = aRect.Top();
+ else if ( aPoint.Y() > aRect.Bottom() )
+ aPoint.Y() = aRect.Bottom();
+ if ( aPoint.X() < aRect.Left() )
+ aPoint.X() = aRect.Left();
+ else if ( aPoint.X() > aRect.Right() )
+ aPoint.X() = aRect.Right();
+ rPoint = aPoint;
+ return pActual;
+}
+
+/*************************************************************************
+|*
+|* SwPageFrm::GetCntntPosition()
+|*
+|* Beschreibung Analog zu SwLayoutFrm::GetCntntPos().
+|* Spezialisiert fuer Felder in Rahmen.
+|*
+|*************************************************************************/
+void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
+{
+ //Ersten CntntFrm ermitteln.
+ const SwCntntFrm *pCntnt = ContainsCntnt();
+ if ( pCntnt )
+ {
+ //Einen weiter zurueck schauen (falls moeglich).
+ const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
+ while ( pTmp && !pTmp->IsInDocBody() )
+ pTmp = pTmp->GetPrevCntntFrm();
+ if ( pTmp )
+ pCntnt = pTmp;
+ }
+ else
+ pCntnt = GetUpper()->ContainsCntnt();
+
+ const SwCntntFrm *pAct = pCntnt;
+ Point aAct = rPt;
+ sal_uLong nDist = ULONG_MAX;
+
+ while ( pCntnt )
+ {
+ SwRect aCntFrm( pCntnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPt ) )
+ {
+ //dichter gehts nimmer.
+ pAct = pCntnt;
+ break;
+ }
+
+ //Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen.
+ Point aPoint( rPt );
+
+ //Erst die vertikale Position einstellen
+ if ( aCntFrm.Top() > rPt.Y() )
+ aPoint.Y() = aCntFrm.Top();
+ else if ( aCntFrm.Bottom() < rPt.Y() )
+ aPoint.Y() = aCntFrm.Bottom();
+
+ //Jetzt die horizontale Position
+ if ( aCntFrm.Left() > rPt.X() )
+ aPoint.X() = aCntFrm.Left();
+ else if ( aCntFrm.Right() < rPt.X() )
+ aPoint.X() = aCntFrm.Right();
+
+ const sal_uLong nDiff = ::CalcDiff( aPoint, rPt );
+ if ( nDiff < nDist )
+ {
+ aAct = aPoint;
+ nDist = nDiff;
+ pAct = pCntnt;
+ }
+ else if ( aCntFrm.Top() > Frm().Bottom() )
+ //Dichter wirds im Sinne der Felder nicht mehr!
+ break;
+
+ pCntnt = pCntnt->GetNextCntntFrm();
+ while ( pCntnt && !pCntnt->IsInDocBody() )
+ pCntnt = pCntnt->GetNextCntntFrm();
+ }
+
+ //Und den Point in die PrtArea bringen
+ const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() );
+ if ( aAct.Y() < aRect.Top() )
+ aAct.Y() = aRect.Top();
+ else if ( aAct.Y() > aRect.Bottom() )
+ aAct.Y() = aRect.Bottom();
+ if ( aAct.X() < aRect.Left() )
+ aAct.X() = aRect.Left();
+ else if ( aAct.X() > aRect.Right() )
+ aAct.X() = aRect.Right();
+
+ if( !pAct->IsValid() )
+ {
+ // CntntFrm nicht formatiert -> immer auf Node-Anfang
+ SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
+ OSL_ENSURE( pCNd, "Wo ist mein CntntNode?" );
+ rPos.nNode = *pCNd;
+ rPos.nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
+ pAct->GetCrsrOfst( &rPos, aAct, &aTmpState );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetNextPrevCntntPos()
+|*
+|* Beschreibung Es wird der naechstliegende Cntnt zum uebergebenen
+|* Point gesucht. Es wird nur im BodyText gesucht.
+|*
+|*************************************************************************/
+
+// --> OD 2005-05-25 #123110# - helper class to disable creation of an action
+// by a callback event - e.g., change event from a drawing object
+class DisableCallbackAction
+{
+ private:
+ SwRootFrm& mrRootFrm;
+ sal_Bool mbOldCallbackActionState;
+
+ public:
+ DisableCallbackAction( const SwRootFrm& _rRootFrm ) :
+ mrRootFrm( const_cast<SwRootFrm&>(_rRootFrm) ),
+ mbOldCallbackActionState( _rRootFrm.IsCallbackActionEnabled() )
+ {
+ mrRootFrm.SetCallbackActionEnabled( sal_False );
+ }
+
+ ~DisableCallbackAction()
+ {
+ mrRootFrm.SetCallbackActionEnabled( mbOldCallbackActionState );
+ }
+};
+// <--
+
+//!!!!! Es wird nur der vertikal naechstliegende gesucht.
+//JP 11.10.2001: only in tables we try to find the right column - Bug 72294
+Point SwRootFrm::GetNextPrevCntntPos( const Point& rPoint, sal_Bool bNext ) const
+{
+ // --> OD 2005-05-25 #123110# - disable creation of an action by a callback
+ // event during processing of this method. Needed because formatting is
+ // triggered by this method.
+ DisableCallbackAction aDisableCallbackAction( *this );
+ // <--
+ //Ersten CntntFrm und seinen Nachfolger im Body-Bereich suchen
+ //Damit wir uns nicht tot suchen (und vor allem nicht zuviel formatieren)
+ //gehen wir schon mal von der richtigen Seite aus.
+ SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
+ if( pPage )
+ while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
+ pPage = (SwLayoutFrm*)pPage->GetNext();
+
+ const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
+ while ( pCnt && !pCnt->IsInDocBody() )
+ pCnt = pCnt->GetNextCntntFrm();
+
+ if ( !pCnt )
+ return Point( 0, 0 );
+
+ pCnt->Calc();
+ if( !bNext )
+ {
+ // Solange der Point vor dem ersten CntntFrm liegt und es noch
+ // vorhergehende Seiten gibt gehe ich jeweils eine Seite nach vorn.
+ while ( rPoint.Y() < pCnt->Frm().Top() && pPage->GetPrev() )
+ {
+ pPage = (SwLayoutFrm*)pPage->GetPrev();
+ pCnt = pPage->ContainsCntnt();
+ while ( !pCnt )
+ {
+ pPage = (SwLayoutFrm*)pPage->GetPrev();
+ if ( pPage )
+ pCnt = pPage->ContainsCntnt();
+ else
+ return ContainsCntnt()->UnionFrm().Pos();
+ }
+ pCnt->Calc();
+ }
+ }
+
+ //Liegt der Point ueber dem ersten CntntFrm?
+ if ( rPoint.Y() < pCnt->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
+ return pCnt->UnionFrm().Pos();
+
+ while ( pCnt )
+ {
+ //Liegt der Point im aktuellen CntntFrm?
+ SwRect aCntFrm( pCnt->UnionFrm() );
+ if ( aCntFrm.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
+ return rPoint;
+
+ //Ist der aktuelle der letzte CntntFrm? ||
+ //Wenn der naechste CntntFrm hinter dem Point liegt, ist der
+ //aktuelle der gesuchte.
+ const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
+ while ( pNxt && !pNxt->IsInDocBody() )
+ pNxt = pNxt->GetNextCntntFrm();
+
+ //Liegt der Point hinter dem letzten CntntFrm?
+ if ( !pNxt )
+ return Point( aCntFrm.Right(), aCntFrm.Bottom() );
+
+ //Wenn der naechste CntntFrm hinter dem Point liegt ist er der
+ //gesuchte.
+ const SwTabFrm* pTFrm;
+ pNxt->Calc();
+ if( pNxt->Frm().Top() > rPoint.Y() &&
+ !lcl_IsInRepeatedHeadline( pCnt, &pTFrm ) &&
+ ( !pTFrm || pNxt->Frm().Left() > rPoint.X() ))
+ {
+ if( bNext )
+ return pNxt->Frm().Pos();
+ return Point( aCntFrm.Right(), aCntFrm.Bottom() );
+ }
+ pCnt = pNxt;
+ }
+ return Point( 0, 0 );
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::GetPagePos()
+|*
+|* Beschreibung: Liefert die absolute Dokumentpositon der gewuenschten
+|* Seite.
+|* Formatiert wird nur soweit notwendig und nur dann wenn bFormat=sal_True
+|* Liefert Null, wenn die Operation nicht moeglich ist.
+|* Die Pos ist die der letzten Seite, wenn die Seitenzahl zu gross
+|* gewaehlt wurde.
+|*
+|*************************************************************************/
+Point SwRootFrm::GetPagePos( sal_uInt16 nPageNum ) const
+{
+ OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
+
+ const SwPageFrm *pPage = (const SwPageFrm*)Lower();
+ while ( sal_True )
+ {
+ if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
+ break;
+ pPage = (const SwPageFrm*)pPage->GetNext();
+ }
+ return pPage->Frm().Pos();
+}
+
+/** get page frame by phyiscal page number
+
+ OD 14.01.2003 #103492#
+
+ @return pointer to the page frame with the given physical page number
+*/
+SwPageFrm* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum ) const
+{
+ const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>( Lower() );
+ while ( pPageFrm && pPageFrm->GetPhyPageNum() < _nPageNum )
+ {
+ pPageFrm = static_cast<const SwPageFrm*>( pPageFrm->GetNext() );
+ }
+
+ if ( pPageFrm && pPageFrm->GetPhyPageNum() == _nPageNum )
+ {
+ return const_cast<SwPageFrm*>( pPageFrm );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::IsDummyPage(sal_uInt16)
+|*
+|* Description: Returns sal_True, when the given physical pagenumber does't exist
+|* or this page is an empty page.
+|*************************************************************************/
+sal_Bool SwRootFrm::IsDummyPage( sal_uInt16 nPageNum ) const
+{
+ if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
+ return sal_True;
+
+ const SwPageFrm *pPage = (const SwPageFrm*)Lower();
+ while( pPage && nPageNum < pPage->GetPhyPageNum() )
+ pPage = (const SwPageFrm*)pPage->GetNext();
+ return pPage ? pPage->IsEmptyPage() : sal_True;
+}
+
+
+/*************************************************************************
+|*
+|* SwFrm::IsProtected()
+|*
+|* Beschreibung Ist der Frm bzw. die Section in der er steht
+|* geschuetzt?
+|* Auch Fly in Fly in ... und Fussnoten
+|*
+|*
+|*************************************************************************/
+sal_Bool SwFrm::IsProtected() const
+{
+ if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
+ {
+ const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
+ bool isFormProtected=pDoc->get(IDocumentSettingAccess::PROTECT_FORM );
+ if (isFormProtected)
+ {
+ return sal_False; // TODO a hack for now, well deal with it laster, I we return true here we have a "double" locking
+ }
+ }
+ //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein.
+ //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker.
+ const SwFrm *pFrm = this;
+ do
+ {
+ if ( pFrm->IsCntntFrm() )
+ {
+ if ( ((SwCntntFrm*)pFrm)->GetNode() &&
+ ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
+ return sal_True;
+ }
+ else
+ {
+ if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
+ ((SwLayoutFrm*)pFrm)->GetFmt()->
+ GetProtect().IsCntntProtected() )
+ return sal_True;
+ if ( pFrm->IsCoveredCell() )
+ return sal_True;
+ }
+ if ( pFrm->IsFlyFrm() )
+ {
+ //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette
+ //vorgegeben werden.
+ if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
+ {
+ SwFlyFrm *pMaster = (SwFlyFrm*)pFrm;
+ do
+ { pMaster = pMaster->GetPrevLink();
+ } while ( pMaster->GetPrevLink() );
+ if ( pMaster->IsProtected() )
+ return sal_True;
+ }
+ pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
+ }
+ else if ( pFrm->IsFtnFrm() )
+ pFrm = ((SwFtnFrm*)pFrm)->GetRef();
+ else
+ pFrm = pFrm->GetUpper();
+
+ } while ( pFrm );
+
+ return sal_False;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetPhyPageNum()
+|* Beschreibung: Liefert die physikalische Seitennummer
+|*
+|*
+|*************************************************************************/
+sal_uInt16 SwFrm::GetPhyPageNum() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ return pPage ? pPage->GetPhyPageNum() : 0;
+}
+
+/*--------------------------------------------------
+ * SwFrm::WannaRightPage()
+ * decides if the page want to be a rightpage or not.
+ * If the first content of the page has a page descriptor,
+ * we take the follow of the page descriptor of the last not empty page.
+ * If this descriptor allows only right(left) pages and the page
+ * isn't an empty page then it wanna be such right(left) page.
+ * If the descriptor allows right and left pages, we look for a number offset
+ * in the first content. If there is one, odd number results right pages,
+ * even number results left pages.
+ * If there is no number offset, we take the physical page number instead,
+ * but a previous empty page don't count.
+ * --------------------------------------------------*/
+
+sal_Bool SwFrm::WannaRightPage() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( !pPage || !pPage->GetUpper() )
+ return sal_True;
+
+ const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
+ SwPageDesc *pDesc = 0;
+ sal_uInt16 nPgNum = 0;
+ if ( pFlow )
+ {
+ if ( pFlow->IsInTab() )
+ pFlow = pFlow->FindTabFrm();
+ const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
+ if ( !pTmp->IsFollow() )
+ {
+ const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
+ pDesc = (SwPageDesc*)rPgDesc.GetPageDesc();
+ nPgNum = rPgDesc.GetNumOffset();
+ }
+ }
+ if ( !pDesc )
+ {
+ SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
+ if( pPrv && pPrv->IsEmptyPage() )
+ pPrv = (SwPageFrm*)pPrv->GetPrev();
+ if( pPrv )
+ pDesc = pPrv->GetPageDesc()->GetFollow();
+ else
+ {
+ const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
+ pDesc = (SwPageDesc*)&pDoc->GetPageDesc( 0 );
+ }
+ }
+ OSL_ENSURE( pDesc, "No pagedescriptor" );
+ sal_Bool bOdd;
+ if( nPgNum )
+ bOdd = nPgNum % 2 ? sal_True : sal_False;
+ else
+ {
+ bOdd = pPage->OnRightPage();
+ if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
+ bOdd = !bOdd;
+ }
+ if( !pPage->IsEmptyPage() )
+ {
+ if( !pDesc->GetRightFmt() )
+ bOdd = sal_False;
+ else if( !pDesc->GetLeftFmt() )
+ bOdd = sal_True;
+ }
+ return bOdd;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::GetVirtPageNum()
+|* Beschreibung: Liefert die virtuelle Seitennummer mit Offset
+|*
+|*************************************************************************/
+sal_uInt16 SwFrm::GetVirtPageNum() const
+{
+ const SwPageFrm *pPage = FindPageFrm();
+ if ( !pPage || !pPage->GetUpper() )
+ return 0;
+
+ sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
+ if ( !((SwRootFrm*)pPage->GetUpper())->IsVirtPageNum() )
+ return nPhyPage;
+
+ //Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen.
+ //Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen
+ //wir jetzt gezielt ueber die Abhaengigkeiten.
+ //von den PageDescs bekommen wir die Attribute, von den Attributen
+ //wiederum bekommen wir die Absaetze.
+ const SwPageFrm *pVirtPage = 0;
+ const SwFrm *pFrm = 0;
+ const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
+ for( sal_uInt32 n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
+ continue;
+
+ const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
+ if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
+ {
+ const SwModify *pMod = pDesc->GetDefinedIn();
+ SwVirtPageNumInfo aInfo( pPage );
+ pMod->GetInfo( aInfo );
+ if ( aInfo.GetPage() )
+ {
+ if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
+ GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
+ {
+ pVirtPage = aInfo.GetPage();
+ pFrm = aInfo.GetFrm();
+ }
+ }
+ }
+ }
+ if ( pFrm )
+ return nPhyPage - pFrm->GetPhyPageNum() +
+ pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
+ return nPhyPage;
+}
+
+/*************************************************************************
+|*
+|* SwRootFrm::MakeTblCrsrs()
+|*
+|*************************************************************************/
+//Ermitteln und einstellen derjenigen Zellen die von der Selektion
+//eingeschlossen sind.
+
+bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
+{
+ //Union-Rects und Tabellen (Follows) der Selektion besorgen.
+ OSL_ENSURE( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( sal_False ),
+ "Tabselection nicht auf Cnt." );
+
+ bool bRet = false;
+
+ // For new table models there's no need to ask the layout..
+ if( rTblCrsr.NewTableSelection() )
+ return true;
+
+ Point aPtPt, aMkPt;
+ {
+ SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
+
+ if( pShCrsr )
+ {
+ aPtPt = pShCrsr->GetPtPos();
+ aMkPt = pShCrsr->GetMkPos();
+ }
+ }
+
+ // --> FME 2008-01-14 #151012# Made code robust here:
+ const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
+ const SwCntntNode* pTmpEndNode = rTblCrsr.GetCntntNode(sal_False);
+
+ const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, sal_False ) : 0;
+ const SwFrm* pTmpEndFrm = pTmpEndNode ? pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, sal_False ) : 0;
+
+ const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
+ const SwLayoutFrm* pEnd = pTmpEndFrm ? pTmpEndFrm->GetUpper() : 0;
+
+ OSL_ENSURE( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" );
+ // <--
+
+ /* #109590# Only change table boxes if the frames are
+ valid. Needed because otherwise the table cursor after moving
+ table cells by dnd resulted in an empty tables cursor. */
+ if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
+ {
+ SwSelUnions aUnions;
+ ::MakeSelUnions( aUnions, pStart, pEnd );
+
+ SwSelBoxes aNew;
+
+ const sal_Bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
+
+ for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
+ {
+ SwSelUnion *pUnion = aUnions[i];
+ const SwTabFrm *pTable = pUnion->GetTable();
+
+ // Skip any repeated headlines in the follow:
+ SwLayoutFrm* pRow = pTable->IsFollow() ?
+ pTable->GetFirstNonHeadlineRow() :
+ (SwLayoutFrm*)pTable->Lower();
+
+ while ( pRow )
+ {
+ if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
+ {
+ const SwLayoutFrm *pCell = pRow->FirstCell();
+
+ while ( pCell && pRow->IsAnLower( pCell ) )
+ {
+ OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
+ if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
+ (bReadOnlyAvailable ||
+ !pCell->GetFmt()->GetProtect().IsCntntProtected()))
+ {
+ SwTableBox* pInsBox = (SwTableBox*)
+ ((SwCellFrm*)pCell)->GetTabBox();
+ aNew.Insert( pInsBox );
+ }
+ if ( pCell->GetNext() )
+ {
+ pCell = (const SwLayoutFrm*)pCell->GetNext();
+ if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
+ pCell = pCell->FirstCell();
+ }
+ else
+ {
+ const SwLayoutFrm* pLastCell = pCell;
+ do
+ {
+ pCell = pCell->GetNextLayoutLeaf();
+ } while ( pCell && pLastCell->IsAnLower( pCell ) );
+ // Fuer (spaltige) Bereiche...
+ if( pCell && pCell->IsInTab() )
+ {
+ while( !pCell->IsCellFrm() )
+ {
+ pCell = pCell->GetUpper();
+ OSL_ENSURE( pCell, "Where's my cell?" );
+ }
+ }
+ }
+ }
+ }
+ pRow = (SwLayoutFrm*)pRow->GetNext();
+ }
+ }
+
+ rTblCrsr.ActualizeSelection( aNew );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::CalcFrmRects
+|*
+|*************************************************************************/
+
+/*
+ * nun koennen folgende Situationen auftreten:
+ * 1. Start und Ende liegen in einer Bildschirm - Zeile und im
+ * gleichen Node
+ * -> aus Start und End ein Rectangle, dann Ok
+ * 2. Start und Ende liegen in einem Frame (dadurch im gleichen Node!)
+ * -> Start nach rechts, End nach links erweitern,
+ * und bei mehr als 2 Bildschirm - Zeilen, das dazwischen
+ * liegende berechnen
+ * 3. Start und Ende liegen in verschiedenen Frames
+ * -> Start nach rechts erweitern, bis Frame-Ende Rect berechnen
+ * Ende nach links erweitern, bis Frame-Start Rect berechnen
+ * und bei mehr als 2 Frames von allen dazwischen liegenden
+ * Frames die PrtArea dazu.
+ * 4. Wenn es sich um eine Tabellenselektion handelt wird fuer jeden
+ * PaM im Ring der CellFrm besorgt, dessen PrtArea wird zu den
+ * Rechtecken addiert.
+ *
+ * Grosser Umbau wg. der FlyFrm; denn diese muessen ausgespart werden.
+ * Ausnahmen: - Der Fly in dem die Selektion stattfindet (wenn sie in einem Fly
+ * stattfindet).
+ * - Die Flys, die vom Text unterlaufen werden.
+ * Arbeitsweise: Zuerst wird eine SwRegion mit der Root initialisiert.
+ * Aus der Region werden die zu invertierenden Bereiche
+ * ausgestantzt. Die Region wird Komprimiert und letztlich
+ * invertiert. Damit liegen dann die zu invertierenden
+ * Rechtecke vor.
+ * Am Ende werden die Flys aus der Region ausgestanzt.
+ */
+
+inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
+{
+ if( rRect.Width() > 1 && rRect.Height() > 1 &&
+ rRect.IsOver( rRegion.GetOrigin() ))
+ rRegion -= rRect;
+}
+
+void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode )
+{
+ SwPosition *pStartPos = rCrsr.Start(),
+ *pEndPos = rCrsr.GetPoint() == pStartPos ?
+ rCrsr.GetMark() : rCrsr.GetPoint();
+
+ ViewShell *pSh = GetCurrShell();
+
+// --> FME 2004-06-08 #i12836# enhanced pdf
+ SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
+ pSh->VisArea() :
+ Frm() );
+// <--
+ if( !pStartPos->nNode.GetNode().IsCntntNode() ||
+ !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
+ ( pStartPos->nNode != pEndPos->nNode &&
+ ( !pEndPos->nNode.GetNode().IsCntntNode() ||
+ !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
+ {
+ return;
+ }
+
+ //Erstmal die CntntFrms zum Start und End besorgen, die brauch ich auf
+ //jedenfall.
+ SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
+
+ SwCntntFrm const* pEndFrm = pEndPos->nNode.GetNode().
+ GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
+
+ OSL_ENSURE( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
+
+ //Damit die FlyFrms, in denen selektierte Frames stecken, nicht
+ //abgezogen werden
+ SwSortedObjs aSortObjs;
+ if ( pStartFrm->IsInFly() )
+ {
+ const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
+ OSL_ENSURE( pObj, "No Start Object." );
+ if (pObj) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
+ const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
+ OSL_ENSURE( pObj2, "No Start Object." );
+ if (pObj2) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
+ }
+
+ //Fall 4: Tabellenselection
+ if( bIsTblMode )
+ {
+ const SwFrm *pCell = pStartFrm->GetUpper();
+ while ( !pCell->IsCellFrm() )
+ pCell = pCell->GetUpper();
+ SwRect aTmp( pCell->Prt() );
+ aTmp.Pos() += pCell->Frm().Pos();
+ aRegion.ChangeOrigin( aTmp );
+ aRegion.Remove( 0, aRegion.Count() );
+ aRegion.Insert( aTmp, 0 );
+ }
+ else
+ {
+ // falls eine nicht erlaubte Selection besteht, dann korrigiere das
+ // nicht erlaubt ist Header/Footer/TableHeadline ueber 2 Seiten
+ do { // middle check loop
+ const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
+ const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
+ while( pSttLFrm &&
+ ! (cHdFtTblHd & pSttLFrm->GetType() ))
+ pSttLFrm = pSttLFrm->GetUpper();
+ if( !pSttLFrm )
+ break;
+ const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
+ while( pEndLFrm &&
+ ! (cHdFtTblHd & pEndLFrm->GetType() ))
+ pEndLFrm = pEndLFrm->GetUpper();
+ if( !pEndLFrm )
+ break;
+
+ OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(),
+ "Selection ueber unterschiedliche Inhalte" );
+ switch( pSttLFrm->GetType() )
+ {
+ case FRM_HEADER:
+ case FRM_FOOTER:
+ // auf unterschiedlichen Seiten ??
+ // dann immer auf die Start-Seite
+ if( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
+ {
+ // End- auf den Start-CntntFrame setzen
+ if( pStartPos == rCrsr.GetPoint() )
+ pEndFrm = pStartFrm;
+ else
+ pStartFrm = pEndFrm;
+ }
+ break;
+ case FRM_TAB:
+ // auf unterschiedlichen Seiten ??
+ // existiert
+ // dann teste auf Tabelle-Headline
+ {
+ const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm;
+ if( ( pTabFrm->GetFollow() ||
+ ((SwTabFrm*)pEndLFrm)->GetFollow() ) &&
+ pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
+ pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() &&
+ ( lcl_IsInRepeatedHeadline( pStartFrm ) ||
+ lcl_IsInRepeatedHeadline( pEndFrm ) ) )
+ {
+ // End- auf den Start-CntntFrame setzen
+ if( pStartPos == rCrsr.GetPoint() )
+ pEndFrm = pStartFrm;
+ else
+ pStartFrm = pEndFrm;
+ }
+ }
+ break;
+ }
+ } while( sal_False );
+
+ SwCrsrMoveState aTmpState( MV_NONE );
+ aTmpState.b2Lines = sal_True;
+ aTmpState.bNoScroll = sal_True;
+ aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
+
+ //CntntRects zu Start- und EndFrms.
+ SwRect aStRect, aEndRect;
+ pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
+ Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
+ aTmpState.p2Lines = NULL;
+ aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
+
+ pEndFrm->GetCharRect ( aEndRect, *pEndPos, &aTmpState );
+ Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
+
+ SwRect aStFrm ( pStartFrm->UnionFrm( sal_True ) );
+ aStFrm.Intersection( pStartFrm->PaintArea() );
+ SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm :
+ pEndFrm->UnionFrm( sal_True ) );
+ if( pStartFrm != pEndFrm )
+ aEndFrm.Intersection( pEndFrm->PaintArea() );
+ SWRECTFN( pStartFrm )
+ const sal_Bool bR2L = pStartFrm->IsRightToLeft();
+ const sal_Bool bEndR2L = pEndFrm->IsRightToLeft();
+
+ // If there's no doubleline portion involved or start and end are both
+ // in the same doubleline portion, all works fine, but otherwise
+ // we need the following...
+ if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
+ pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
+ {
+ // If we have a start(end) position inside a doubleline portion
+ // the surrounded part of the doubleline portion is subtracted
+ // from the region and the aStRect(aEndRect) is set to the
+ // end(start) of the doubleline portion.
+ if( pSt2Pos )
+ {
+ SwRect aTmp( aStRect );
+
+ // BiDi-Portions are swimming against the current.
+ const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
+ ! bR2L :
+ bR2L;
+
+ if( MT_BIDI == pSt2Pos->nMultiType &&
+ (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
+ {
+ // nested bidi portion
+ long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
+
+ (aTmp.*fnRect->fnSetRight)( nRightAbs );
+
+ if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
+ {
+ SwRect aTmp2( pSt2Pos->aPortion );
+ (aTmp2.*fnRect->fnSetRight)( nLeftAbs );
+ aTmp2.Intersection( aEndFrm );
+ Sub( aRegion, aTmp2 );
+ }
+ }
+ else
+ {
+ if( bPorR2L )
+ (aTmp.*fnRect->fnSetLeft)(
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
+ else
+ (aTmp.*fnRect->fnSetRight)(
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ }
+
+ if( MT_ROT_90 == pSt2Pos->nMultiType ||
+ (pSt2Pos->aPortion.*fnRect->fnGetTop)() ==
+ (aTmp.*fnRect->fnGetTop)() )
+ {
+ (aTmp.*fnRect->fnSetTop)(
+ (pSt2Pos->aLine.*fnRect->fnGetTop)() );
+ }
+
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+
+ SwTwips nTmp = (pSt2Pos->aLine.*fnRect->fnGetBottom)();
+ if( MT_ROT_90 != pSt2Pos->nMultiType &&
+ (aStRect.*fnRect->fnBottomDist)( nTmp ) > 0 )
+ {
+ (aTmp.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetBottom)() );
+ (aTmp.*fnRect->fnSetBottom)( nTmp );
+ if( (aStRect.*fnRect->fnBottomDist)(
+ (pSt2Pos->aPortion.*fnRect->fnGetBottom)() ) > 0 )
+ {
+ if( bPorR2L )
+ (aTmp.*fnRect->fnSetRight)(
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ else
+ (aTmp.*fnRect->fnSetLeft)(
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
+ }
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+ }
+
+ aStRect = pSt2Pos->aLine;
+ (aStRect.*fnRect->fnSetLeft)( bR2L ?
+ (pSt2Pos->aPortion.*fnRect->fnGetLeft)() :
+ (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
+ (aStRect.*fnRect->fnSetWidth)( 1 );
+ }
+
+ if( pEnd2Pos )
+ {
+ SWRECTFNX( pEndFrm )
+ SwRect aTmp( aEndRect );
+
+ // BiDi-Portions are swimming against the current.
+ const sal_Bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
+ ! bEndR2L :
+ bEndR2L;
+
+ if( MT_BIDI == pEnd2Pos->nMultiType &&
+ (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
+ {
+ // nested bidi portion
+ long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
+ nRightAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
+
+ (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
+
+ if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
+ {
+ SwRect aTmp2( pEnd2Pos->aPortion );
+ (aTmp2.*fnRectX->fnSetLeft)( nRightAbs );
+ aTmp2.Intersection( aEndFrm );
+ Sub( aRegion, aTmp2 );
+ }
+ }
+ else
+ {
+ if ( bPorR2L )
+ (aTmp.*fnRectX->fnSetRight)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
+ else
+ (aTmp.*fnRectX->fnSetLeft)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ }
+
+ if( MT_ROT_90 == pEnd2Pos->nMultiType ||
+ (pEnd2Pos->aPortion.*fnRectX->fnGetBottom)() ==
+ (aEndRect.*fnRectX->fnGetBottom)() )
+ {
+ (aTmp.*fnRectX->fnSetBottom)(
+ (pEnd2Pos->aLine.*fnRectX->fnGetBottom)() );
+ }
+
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+
+ // The next statement means neither ruby nor rotate(90):
+ if( !( MT_RUBY & pEnd2Pos->nMultiType ) )
+ {
+ SwTwips nTmp = (pEnd2Pos->aLine.*fnRectX->fnGetTop)();
+ if( (aEndRect.*fnRectX->fnGetTop)() != nTmp )
+ {
+ (aTmp.*fnRectX->fnSetBottom)(
+ (aTmp.*fnRectX->fnGetTop)() );
+ (aTmp.*fnRectX->fnSetTop)( nTmp );
+ if( (aEndRect.*fnRectX->fnGetTop)() !=
+ (pEnd2Pos->aPortion.*fnRectX->fnGetTop)() )
+ {
+ if( bPorR2L )
+ (aTmp.*fnRectX->fnSetLeft)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ else
+ (aTmp.*fnRectX->fnSetRight)(
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
+ }
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+ }
+ }
+
+ aEndRect = pEnd2Pos->aLine;
+ (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ?
+ (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() :
+ (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
+ (aEndRect.*fnRectX->fnSetWidth)( 1 );
+ }
+ }
+ else if( pSt2Pos && pEnd2Pos &&
+ MT_BIDI == pSt2Pos->nMultiType &&
+ MT_BIDI == pEnd2Pos->nMultiType &&
+ pSt2Pos->aPortion == pEnd2Pos->aPortion &&
+ pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
+ {
+ // This is the ugly special case, where the selection starts and
+ // ends in the same bidi portion but one start or end is inside a
+ // nested bidi portion.
+
+ if ( (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
+ {
+ SwRect aTmp( aStRect );
+ long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
+
+ (aTmp.*fnRect->fnSetRight)( nRightAbs );
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+
+ aStRect = pSt2Pos->aLine;
+ (aStRect.*fnRect->fnSetLeft)( bR2L ? nRightAbs : nLeftAbs );
+ (aStRect.*fnRect->fnSetWidth)( 1 );
+ }
+
+ SWRECTFNX( pEndFrm )
+ if ( (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
+ {
+ SwRect aTmp( aEndRect );
+ long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
+ nRightAbs -= (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
+ long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
+
+ (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
+ aTmp.Intersection( aEndFrm );
+ Sub( aRegion, aTmp );
+
+ aEndRect = pEnd2Pos->aLine;
+ (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ? nLeftAbs : nRightAbs );
+ (aEndRect.*fnRectX->fnSetWidth)( 1 );
+ }
+ }
+
+ // The charrect may be outside the paintarea (for cursortravelling)
+ // but the selection has to be restricted to the paintarea
+ if( aStRect.Left() < aStFrm.Left() )
+ aStRect.Left( aStFrm.Left() );
+ else if( aStRect.Left() > aStFrm.Right() )
+ aStRect.Left( aStFrm.Right() );
+ SwTwips nTmp = aStRect.Right();
+ if( nTmp < aStFrm.Left() )
+ aStRect.Right( aStFrm.Left() );
+ else if( nTmp > aStFrm.Right() )
+ aStRect.Right( aStFrm.Right() );
+ if( aEndRect.Left() < aEndFrm.Left() )
+ aEndRect.Left( aEndFrm.Left() );
+ else if( aEndRect.Left() > aEndFrm.Right() )
+ aEndRect.Left( aEndFrm.Right() );
+ nTmp = aEndRect.Right();
+ if( nTmp < aEndFrm.Left() )
+ aEndRect.Right( aEndFrm.Left() );
+ else if( nTmp > aEndFrm.Right() )
+ aEndRect.Right( aEndFrm.Right() );
+
+ if( pStartFrm == pEndFrm )
+ {
+ sal_Bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
+ ( MT_BIDI & pSt2Pos->nMultiType ) &&
+ pSt2Pos->aPortion == pEnd2Pos->aPortion;
+ //case 1: (Same frame and same row)
+ if( bSameRotatedOrBidi ||
+ (aStRect.*fnRect->fnGetTop)() == (aEndRect.*fnRect->fnGetTop)() )
+ {
+ Point aTmpSt( aStRect.Pos() );
+ Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
+ if( bSameRotatedOrBidi || bR2L )
+ {
+ if( aTmpSt.Y() > aTmpEnd.Y() )
+ {
+ long nTmpY = aTmpEnd.Y();
+ aTmpEnd.Y() = aTmpSt.Y();
+ aTmpSt.Y() = nTmpY;
+ }
+ if( aTmpSt.X() > aTmpEnd.X() )
+ {
+ long nTmpX = aTmpEnd.X();
+ aTmpEnd.X() = aTmpSt.X();
+ aTmpSt.X() = nTmpX;
+ }
+ }
+
+ SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
+ // Bug 34888: falls Inhalt selektiert ist, der keinen Platz
+ // einnimmt (z.B. PostIts,RefMarks, TOXMarks),
+ // dann mindestens die Breite des Crsr setzen.
+ if( 1 == (aTmp.*fnRect->fnGetWidth)() &&
+ pStartPos->nContent.GetIndex() !=
+ pEndPos->nContent.GetIndex() )
+ {
+ OutputDevice* pOut = pSh->GetOut();
+ long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
+ GetCursorSize();
+ (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic(
+ Size( nCrsrWidth, 0 ) ).Width() );
+ }
+ aTmp.Intersection( aStFrm );
+ Sub( aRegion, aTmp );
+ }
+ //case 2: (Same frame, but not the same line)
+ else
+ {
+ SwTwips lLeft, lRight;
+ if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
+ {
+ lLeft = (pSt2Pos->aPortion.*fnRect->fnGetLeft)();
+ lRight = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
+ }
+ else
+ {
+ lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
+ (pStartFrm->Prt().*fnRect->fnGetLeft)();
+ lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
+ (pStartFrm->Prt().*fnRect->fnGetRight)();
+ }
+ if( lLeft < (aStFrm.*fnRect->fnGetLeft)() )
+ lLeft = (aStFrm.*fnRect->fnGetLeft)();
+ if( lRight > (aStFrm.*fnRect->fnGetRight)() )
+ lRight = (aStFrm.*fnRect->fnGetRight)();
+ SwRect aSubRect( aStRect );
+ //First line
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ else
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ Sub( aRegion, aSubRect );
+
+ //If there's at least a twips between start- and endline,
+ //so the whole area between will be added.
+ SwTwips aTmpBottom = (aStRect.*fnRect->fnGetBottom)();
+ SwTwips aTmpTop = (aEndRect.*fnRect->fnGetTop)();
+ if( aTmpBottom != aTmpTop )
+ {
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ (aSubRect.*fnRect->fnSetTop)( aTmpBottom );
+ (aSubRect.*fnRect->fnSetBottom)( aTmpTop );
+ Sub( aRegion, aSubRect );
+ }
+ //and the last line
+ aSubRect = aEndRect;
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetRight)( lRight );
+ else
+ (aSubRect.*fnRect->fnSetLeft)( lLeft );
+ Sub( aRegion, aSubRect );
+ }
+ }
+ //case 3: (Different frames, maybe with ohther frames between
+ else
+ {
+ //The startframe first...
+ SwRect aSubRect( aStRect );
+ if( bR2L )
+ (aSubRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)());
+ else
+ (aSubRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)());
+ Sub( aRegion, aSubRect );
+ SwTwips nTmpTwips = (aStRect.*fnRect->fnGetBottom)();
+ if( (aStFrm.*fnRect->fnGetBottom)() != nTmpTwips )
+ {
+ aSubRect = aStFrm;
+ (aSubRect.*fnRect->fnSetTop)( nTmpTwips );
+ Sub( aRegion, aSubRect );
+ }
+
+ //Now the frames between, if there are any
+ sal_Bool bBody = pStartFrm->IsInDocBody();
+ const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
+ ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
+ const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
+ SwRect aPrvRect;
+
+ // --> OD 2006-01-24 #123908# - introduce robust code:
+ // The stacktrace issue reveals that <pCntnt> could be NULL.
+ // One root cause found by AMA - see #130650#
+ OSL_ENSURE( pCntnt,
+ "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
+ while ( pCntnt && pCntnt != pEndFrm )
+ // <--
+ {
+ if ( pCntnt->IsInFly() )
+ {
+ const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
+ aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
+ }
+
+ // Consider only frames which have the same IsInDocBody value like pStartFrm
+ // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
+ // same cell frame (or its follow cell)
+ const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
+ ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
+ if ( bBody == pCntnt->IsInDocBody() &&
+ ( !pCellBox || pCellBox == pTmpCellBox ) )
+ {
+ SwRect aCRect( pCntnt->UnionFrm( sal_True ) );
+ aCRect.Intersection( pCntnt->PaintArea() );
+ if( aCRect.IsOver( aRegion.GetOrigin() ))
+ {
+ SwRect aTmp( aPrvRect );
+ aTmp.Union( aCRect );
+ if ( (aPrvRect.Height() * aPrvRect.Width() +
+ aCRect.Height() * aCRect.Width()) ==
+ (aTmp.Height() * aTmp.Width()) )
+ {
+ aPrvRect.Union( aCRect );
+ }
+ else
+ {
+ if ( aPrvRect.HasArea() )
+ Sub( aRegion, aPrvRect );
+ aPrvRect = aCRect;
+ }
+ }
+ }
+ pCntnt = pCntnt->GetNextCntntFrm();
+ // --> OD 2006-01-24 #123908#
+ OSL_ENSURE( pCntnt,
+ "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
+ // <--
+ }
+ if ( aPrvRect.HasArea() )
+ Sub( aRegion, aPrvRect );
+
+ //At least the endframe...
+ bVert = pEndFrm->IsVertical();
+ bRev = pEndFrm->IsReverse();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
+ ( bRev ? fnRectB2T : fnRectHori );
+ nTmpTwips = (aEndRect.*fnRect->fnGetTop)();
+ if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips )
+ {
+ aSubRect = aEndFrm;
+ (aSubRect.*fnRect->fnSetBottom)( nTmpTwips );
+ Sub( aRegion, aSubRect );
+ }
+ aSubRect = aEndRect;
+ if( bEndR2L )
+ (aSubRect.*fnRect->fnSetRight)((aEndFrm.*fnRect->fnGetRight)());
+ else
+ (aSubRect.*fnRect->fnSetLeft)( (aEndFrm.*fnRect->fnGetLeft)() );
+ Sub( aRegion, aSubRect );
+ }
+
+// aRegion.Compress( sal_False );
+ aRegion.Invert();
+ delete pSt2Pos;
+ delete pEnd2Pos;
+ }
+
+ //Flys mit Durchlauf ausstanzen. Nicht ausgestanzt werden Flys:
+ //- die Lower des StartFrm/EndFrm sind (FlyInCnt und alle Flys die wiederum
+ // darin sitzen)
+ //- in der Z-Order ueber denjenigen Flys stehen in denen sich der StartFrm
+ // befindet.
+ const SwPageFrm *pPage = pStartFrm->FindPageFrm();
+ const SwPageFrm *pEndPage = pEndFrm->FindPageFrm();
+
+ while ( pPage )
+ {
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( !pAnchoredObj->ISA(SwFlyFrm) )
+ continue;
+ const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
+ const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
+ const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
+ if ( !pFly->IsAnLower( pStartFrm ) &&
+ (rSur.GetSurround() != SURROUND_THROUGHT &&
+ !rSur.IsContour()) )
+ {
+ if ( aSortObjs.Contains( *pAnchoredObj ) )
+ continue;
+
+ sal_Bool bSub = sal_True;
+ const sal_uInt32 nPos = pObj->GetOrdNum();
+ for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k )
+ {
+ OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm),
+ "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
+ const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
+ do
+ { if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
+ bSub = sal_False;
+ else
+ pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
+ } while ( bSub && pTmp );
+ }
+ if ( bSub )
+ Sub( aRegion, pFly->Frm() );
+ }
+ }
+ }
+ if ( pPage == pEndPage )
+ break;
+ else
+ pPage = (SwPageFrm*)pPage->GetNext();
+ }
+
+ //Weil's besser aussieht noch die DropCaps ausschliessen.
+ SwRect aDropRect;
+ if ( pStartFrm->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
+ Sub( aRegion, aDropRect );
+ }
+ if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
+ {
+ if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
+ Sub( aRegion, aDropRect );
+ }
+
+ rCrsr.Remove( 0, rCrsr.Count() );
+ rCrsr.Insert( &aRegion, 0 );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/unusedf.cxx b/sw/source/core/layout/unusedf.cxx
new file mode 100644
index 000000000000..7c38aaa4430e
--- /dev/null
+++ b/sw/source/core/layout/unusedf.cxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "rootfrm.hxx"
+#include "cntfrm.hxx"
+#include "flyfrm.hxx"
+
+
+void SwFrm::Format( const SwBorderAttrs * )
+{
+ OSL_FAIL( "Format() der Basisklasse gerufen." );
+}
+
+void SwFrm::Paint(SwRect const&, SwPrintData const*const) const
+{
+ OSL_FAIL( "Paint() der Basisklasse gerufen." );
+}
+
+sal_Bool SwCntntFrm::WouldFit( SwTwips &, sal_Bool&, sal_Bool )
+{
+ OSL_FAIL( "WouldFit des CntntFrm gerufen." );
+ return sal_False;
+}
+
+bool SwFrm::FillSelection( SwSelectionList& , const SwRect& ) const
+{
+ OSL_FAIL( "Don't call this function at the base class!" );
+ return false;
+}
+
+sal_Bool SwFrm::GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* ) const
+{
+ OSL_FAIL( "GetCrsrOfst der Basisklasse, hi!" );
+ return sal_False;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+void SwRootFrm::Cut()
+{
+ OSL_FAIL( "Cut() des RootFrm gerufen." );
+}
+
+void SwRootFrm::Paste( SwFrm *, SwFrm * )
+{
+ OSL_FAIL( "Paste() des RootFrm gerufen." );
+}
+
+void SwFlyFrm::Paste( SwFrm *, SwFrm * )
+{
+ OSL_FAIL( "Paste() des FlyFrm gerufen." );
+}
+
+#endif
+
+sal_Bool SwFrm::GetCharRect( SwRect&, const SwPosition&,
+ SwCrsrMoveState* ) const
+{
+ OSL_FAIL( "GetCharRect() der Basis gerufen." );
+ return sal_False;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/virtoutp.cxx b/sw/source/core/layout/virtoutp.cxx
new file mode 100644
index 000000000000..d769f3c4987a
--- /dev/null
+++ b/sw/source/core/layout/virtoutp.cxx
@@ -0,0 +1,258 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <vcl/window.hxx>
+
+#include "hintids.hxx"
+#include "viewsh.hxx"
+#include "virtoutp.hxx"
+#include "viewopt.hxx"
+#include "rootfrm.hxx"
+// OD 12.11.2002 #96272# - include declaration for <SetMappingForVirtDev>
+#include "setmapvirtdev.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+/*************************************************************************
+ * class DbgRect
+ *************************************************************************/
+
+class DbgRect
+{
+ OutputDevice *pOut;
+public:
+ DbgRect( OutputDevice *pOut, const Rectangle &rRect,
+ const ColorData eColor = COL_LIGHTBLUE );
+};
+
+inline DbgRect::DbgRect( OutputDevice *pOutDev, const Rectangle &rRect,
+ const ColorData eColor )
+ :pOut( pOutDev )
+{
+ if( pOut )
+ {
+ pOut->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
+ pOut->SetLineColor( eColor );
+ pOut->SetFillColor();
+ pOut->DrawRect( rRect );
+ pOut->Pop();
+ }
+}
+
+#endif
+
+/* class SwLayVout verwaltet das virtuelle Outputdevice
+ * Es gibt von dieser Klasse einen statischen Member am RootFrm,
+ * dieser wird in _FrmInit angelegt und in _FrmFinit zerstoert.
+ * */
+
+sal_Bool SwRootFrm::FlushVout()
+{
+ if( SwRootFrm::pVout->IsFlushable() )
+ {
+ SwRootFrm::pVout->_Flush();
+ return sal_True;
+ }
+ return sal_False;
+}
+
+sal_Bool SwRootFrm::HasSameRect( const SwRect& rRect )
+{
+ if( SwRootFrm::pVout->IsFlushable() )
+ return ( rRect == SwRootFrm::pVout->GetOrgRect() );
+ return sal_False;
+}
+
+/** method to set mapping/pixel offset for virtual output device
+
+ OD 12.11.2002 #96272# - method implements two solutions for the mapping of
+ the virtual output device:
+ The old solution set the origin of the mapping mode, which will be used in
+ the virtual output device. This causes several paint errors, because of the
+ different roundings in the virtual output device and the original output device.
+ The new solution avoids the rounding differences between virtual and original
+ output device by setting a pixel offset at the virtual output device.
+ A define controls, which solution is used, in order to switch in escalation
+ back to old solution.
+
+ @author OD
+
+ @param _pOrgOutDev
+ input parameter - constant instance of the original output device, for which
+ the virtual output device is created.
+
+ @param _pVirDev
+ input/output parameter - instance of the virtual output device.
+
+ @param _pMapMode
+ input/output parameter - instance of the mapping mode, which will be set
+ at the virtual output device.
+
+ @param _rNewOrigin
+ input parameter - constant instance of the origin, which will be used in
+ the virtual output device
+*/
+// define to control, if old or new solution for setting the mapping for
+// an virtual output device is used.
+void SetMappingForVirtDev( const Point& _rNewOrigin,
+ MapMode* ,
+ const OutputDevice* _pOrgOutDev,
+ VirtualDevice* _pVirDev )
+{
+ // new solution: set pixel offset at virtual output device
+ Point aPixelOffset = _pOrgOutDev->LogicToPixel( _rNewOrigin );
+ _pVirDev->SetPixelOffset( Size( -aPixelOffset.X(), -aPixelOffset.Y() ) );
+}
+
+
+/*************************************************************************
+ * SwVOut::DoesFit()
+ *************************************************************************/
+
+// rSize muss in Pixel-Koordinaten vorliegen!
+sal_Bool SwLayVout::DoesFit( const Size &rNew )
+{
+ if( rNew.Height() > VIRTUALHEIGHT )
+ return sal_False;
+ if( rNew.Width() <= 0 || rNew.Height() <= 0 )
+ return sal_False;
+ if( rNew.Width() <= aSize.Width() )
+ return sal_True;
+ if( !pVirDev )
+ {
+ pVirDev = new VirtualDevice();
+ pVirDev->SetLineColor();
+ if( pOut )
+ {
+ if( pVirDev->GetFillColor() != pOut->GetFillColor() )
+ pVirDev->SetFillColor( pOut->GetFillColor() );
+ }
+ }
+
+ if( rNew.Width() > aSize.Width() )
+ {
+ aSize.Width() = rNew.Width();
+ if( !pVirDev->SetOutputSizePixel( aSize ) )
+ {
+ delete pVirDev;
+ pVirDev = NULL;
+ aSize.Width() = 0;
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+/*************************************************************************
+ * SwLayVout::Enter
+ *************************************************************************/
+/// OD 27.09.2002 #103636# - change 2nd parameter <rRect> - no longer <const>
+/// in order to return value of class member variable <aRect>, if virtual
+/// output is used.
+/// <aRect> contains the rectangle that represents the area the virtual
+/// output device is used for and that is flushed at the end.
+void SwLayVout::Enter( ViewShell *pShell, SwRect &rRect, sal_Bool bOn )
+{
+ Flush();
+
+#if OSL_DEBUG_LEVEL > 1
+ if( pShell->GetViewOptions()->IsTest3() )
+ {
+ ++nCount;
+ return;
+ }
+#endif
+
+ bOn = bOn && !nCount && rRect.HasArea() && pShell->GetWin();
+ ++nCount;
+ if( bOn )
+ {
+ pSh = pShell;
+ pOut = NULL;
+ OutputDevice *pO = pSh->GetOut();
+// Auf dem Drucker oder einem virt. Outputdevice wird nicht getrickst...
+ if( OUTDEV_WINDOW != pO->GetOutDevType() )
+ return;
+
+ pOut = pO;
+ Size aPixSz( pOut->PixelToLogic( Size( 1,1 )) );
+ SwRect aTmp( rRect );
+ aTmp.SSize().Width() += aPixSz.Width()/2 + 1;
+ aTmp.SSize().Height()+= aPixSz.Height()/2 + 1;
+ Rectangle aTmpRect( pO->LogicToPixel( aTmp.SVRect() ) );
+
+ OSL_ENSURE( !pSh->GetWin()->IsReallyVisible() ||
+ aTmpRect.GetWidth() <= pSh->GetWin()->GetOutputSizePixel().Width() + 2,
+ "Paintwidth bigger than visarea?" );
+ // Passt das Rechteck in unseren Buffer ?
+ if( !DoesFit( aTmpRect.GetSize() ) )
+ {
+ pOut = NULL;
+ return;
+ }
+
+ aRect = SwRect( pO->PixelToLogic( aTmpRect ) );
+
+ SetOutDev( pSh, pVirDev );
+
+ if( pVirDev->GetFillColor() != pOut->GetFillColor() )
+ pVirDev->SetFillColor( pOut->GetFillColor() );
+
+ MapMode aMapMode( pOut->GetMapMode() );
+ // OD 12.11.2002 #96272# - use method to set mapping
+ //aMapMode.SetOrigin( Point(0,0) - aRect.Pos() );
+ ::SetMappingForVirtDev( aRect.Pos(), &aMapMode, pOut, pVirDev );
+
+ if( aMapMode != pVirDev->GetMapMode() )
+ pVirDev->SetMapMode( aMapMode );
+
+ /// OD 27.09.2002 #103636# - set value of parameter <rRect>
+ rRect = aRect;
+ }
+}
+
+/*************************************************************************
+ * SwLayVout::Flush()
+ *************************************************************************/
+
+void SwLayVout::_Flush()
+{
+ OSL_ENSURE( pVirDev, "SwLayVout::DrawOut: nothing left Toulouse" );
+ Rectangle aTmp( aRect.SVRect() );
+ pOut->DrawOutDev( aRect.Pos(), aRect.SSize(),
+ aRect.Pos(), aRect.SSize(), *pVirDev );
+ SetOutDev( pSh, pOut );
+ pOut = NULL;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/virtoutp.hxx b/sw/source/core/layout/virtoutp.hxx
new file mode 100644
index 000000000000..f3f27a184150
--- /dev/null
+++ b/sw/source/core/layout/virtoutp.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _VIRTOUTP_HXX
+#define _VIRTOUTP_HXX
+
+#include <vcl/virdev.hxx>
+
+#include "swtypes.hxx" // UCHAR
+#include "swrect.hxx" // SwRect
+
+class ViewShell;
+#define VIRTUALHEIGHT 64
+
+/*************************************************************************
+ * class SwTxtVout
+ *************************************************************************/
+
+class SwLayVout
+{
+ friend void _FrmFinit(); //loescht das Vout
+private:
+ ViewShell* pSh;
+ OutputDevice* pOut;
+ VirtualDevice* pVirDev;
+ SwRect aRect;
+ SwRect aOrgRect;
+ Size aSize;
+ sal_uInt16 nCount;
+
+ sal_Bool DoesFit( const Size &rOut );
+
+public:
+ SwLayVout() : pSh(0), pOut(0), pVirDev(0), aSize(0, VIRTUALHEIGHT), nCount(0) {}
+ ~SwLayVout() { delete pVirDev; }
+
+ /// OD 27.09.2002 #103636# - change 2nd parameter <rRect> - no longer <const>
+ void Enter( ViewShell *pShell, SwRect &rRect, sal_Bool bOn );
+ void Leave() { --nCount; Flush(); }
+
+ void SetOrgRect( SwRect &rRect ) { aOrgRect = rRect; }
+ const SwRect& GetOrgRect() const { return aOrgRect; }
+
+ sal_Bool IsFlushable() { return 0 != pOut; }
+ void _Flush();
+ void Flush() { if( pOut ) _Flush(); }
+};
+
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
new file mode 100644
index 000000000000..0d9f04e62d9c
--- /dev/null
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -0,0 +1,3967 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <tools/pstm.hxx>
+#include <vcl/outdev.hxx>
+#include <svl/itemiter.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtornt.hxx>
+#include <pagefrm.hxx>
+#include <section.hxx>
+#include <rootfrm.hxx>
+#include <cntfrm.hxx>
+#include <dcontact.hxx>
+#include <anchoreddrawobject.hxx>
+#include <fmtanchr.hxx>
+#include <viewsh.hxx>
+#include <viewimp.hxx>
+#include "viewopt.hxx"
+#include <doc.hxx>
+#include <fesh.hxx>
+#include <docsh.hxx>
+#include <flyfrm.hxx>
+#include <frmtool.hxx>
+#include <ftninfo.hxx>
+#include <dflyobj.hxx>
+#include <fmtclbl.hxx>
+#include <fmtfordr.hxx>
+#include <fmtfsize.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtsrnd.hxx>
+#include <ftnfrm.hxx>
+#include <tabfrm.hxx>
+#include <htmltbl.hxx>
+#include <flyfrms.hxx>
+#include <sectfrm.hxx>
+#include <fmtclds.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <bodyfrm.hxx>
+#include <cellfrm.hxx>
+#include <dbg_lay.hxx>
+#include <editeng/frmdiritem.hxx>
+// OD 2004-05-24 #i28701#
+#include <sortedobjs.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+/*************************************************************************
+|*
+|* SwFrm::SwFrm()
+|*
+|*************************************************************************/
+
+SwFrm::SwFrm( SwModify *pMod, SwFrm* pSib ) :
+ SwClient( pMod ),
+ // --> OD 2006-05-10 #i65250#
+ mnFrmId( SwFrm::mnLastFrmId++ ),
+ // <--
+ mpRoot( pSib ? pSib->getRootFrm() : 0 ),
+ pUpper( 0 ),
+ pNext( 0 ),
+ pPrev( 0 ),
+ pDrawObjs( 0 )
+ , bInfBody( sal_False )
+ , bInfTab ( sal_False )
+ , bInfFly ( sal_False )
+ , bInfFtn ( sal_False )
+ , bInfSct ( sal_False )
+{
+#if OSL_DEBUG_LEVEL > 1
+ bFlag01 = bFlag02 = bFlag03 = bFlag04 = bFlag05 = 0;
+#endif
+
+ OSL_ENSURE( pMod, "Kein Frameformat uebergeben." );
+ bInvalidR2L = bInvalidVert = 1;
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ bDerivedR2L = bDerivedVert = bRightToLeft = bVertical = bReverse = bVertLR = 0;
+
+ bValidPos = bValidPrtArea = bValidSize = bValidLineNum = bRetouche =
+ bFixSize = bColLocked = sal_False;
+ bCompletePaint = bInfInvalid = sal_True;
+}
+
+const IDocumentDrawModelAccess* SwFrm::getIDocumentDrawModelAccess()
+{
+ return GetUpper()->GetFmt()->getIDocumentDrawModelAccess();
+}
+
+bool SwFrm::KnowsFormat( const SwFmt& rFmt ) const
+{
+ return GetRegisteredIn() == &rFmt;
+}
+
+void SwFrm::RegisterToFormat( SwFmt& rFmt )
+{
+ rFmt.Add( this );
+}
+
+void SwFrm::CheckDir( sal_uInt16 nDir, sal_Bool bVert, sal_Bool bOnlyBiDi, sal_Bool bBrowse )
+{
+ if( FRMDIR_ENVIRONMENT == nDir || ( bVert && bOnlyBiDi ) )
+ {
+ bDerivedVert = 1;
+ if( FRMDIR_ENVIRONMENT == nDir )
+ bDerivedR2L = 1;
+ SetDirFlags( bVert );
+ }
+ else if( bVert )
+ {
+ bInvalidVert = 0;
+ if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir
+ || bBrowse )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ {
+ bVertical = 0;
+ bVertLR = 0;
+ }
+ else
+ {
+ bVertical = 1;
+ if(FRMDIR_VERT_TOP_RIGHT == nDir)
+ bVertLR = 0;
+ else if(FRMDIR_VERT_TOP_LEFT==nDir)
+ bVertLR = 1;
+ }
+ }
+ else
+ {
+ bInvalidR2L = 0;
+ if( FRMDIR_HORI_RIGHT_TOP == nDir )
+ bRightToLeft = 1;
+ else
+ bRightToLeft = 0;
+ }
+}
+
+void SwFrm::CheckDirection( sal_Bool bVert )
+{
+ if( bVert )
+ {
+ if( !IsHeaderFrm() && !IsFooterFrm() )
+ {
+ bDerivedVert = 1;
+ SetDirFlags( bVert );
+ }
+ }
+ else
+ {
+ bDerivedR2L = 1;
+ SetDirFlags( bVert );
+ }
+}
+
+void SwSectionFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_True, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwFlyFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_False, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwTabFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ if( pFmt )
+ {
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
+ bVert, sal_True, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwCellFrm::CheckDirection( sal_Bool bVert )
+{
+ const SwFrmFmt* pFmt = GetFmt();
+ const SfxPoolItem* pItem;
+ // --> FME 2006-03-30 #b6402837# Check if the item is set, before actually
+ // using it. Otherwise the dynamic pool default is used, which may be set
+ // to LTR in case of OOo 1.0 documents.
+ // <--
+ if( pFmt && SFX_ITEM_SET == pFmt->GetItemState( RES_FRAMEDIR, sal_True, &pItem ) )
+ {
+ const SvxFrameDirectionItem* pFrmDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir( pFrmDirItem->GetValue(), bVert, sal_False, bBrowseMode );
+ }
+ else
+ SwFrm::CheckDirection( bVert );
+}
+
+void SwTxtFrm::CheckDirection( sal_Bool bVert )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ CheckDir( GetTxtNode()->GetSwAttrSet().GetFrmDir().GetValue(), bVert,
+ sal_True, bBrowseMode );
+}
+
+/*************************************************************************/
+void SwFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ while( sal_True )
+ {
+ _UpdateAttrFrm( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ }
+ else
+ _UpdateAttrFrm( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x01 )
+ {
+ _InvalidatePrt();
+ if( !GetPrev() && IsTabFrm() && IsInSct() )
+ FindSctFrm()->_InvalidatePrt();
+ }
+ if ( nInvFlags & 0x02 )
+ _InvalidateSize();
+ if ( nInvFlags & 0x04 )
+ _InvalidatePos();
+ if ( nInvFlags & 0x08 )
+ SetCompletePaint();
+ SwFrm *pNxt;
+ if ( nInvFlags & 0x30 && 0 != (pNxt = GetNext()) )
+ {
+ pNxt->InvalidatePage( pPage );
+ if ( nInvFlags & 0x10 )
+ pNxt->_InvalidatePos();
+ if ( nInvFlags & 0x20 )
+ pNxt->SetCompletePaint();
+ }
+ }
+}
+
+void SwFrm::_UpdateAttrFrm( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
+ sal_uInt8 &rInvFlags )
+{
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch( nWhich )
+ {
+ case RES_BOX:
+ case RES_SHADOW:
+ Prepare( PREP_FIXSIZE_CHG );
+ // hier kein break !
+ case RES_LR_SPACE:
+ case RES_UL_SPACE:
+ rInvFlags |= 0x0B;
+ break;
+
+ case RES_HEADER_FOOTER_EAT_SPACING:
+ rInvFlags |= 0x03;
+ break;
+
+ case RES_BACKGROUND:
+ rInvFlags |= 0x28;
+ break;
+
+ case RES_KEEP:
+ rInvFlags |= 0x04;
+ break;
+
+ case RES_FRM_SIZE:
+ ReinitializeFrmSizeAttrFlags();
+ rInvFlags |= 0x13;
+ break;
+
+ case RES_FMT_CHG:
+ rInvFlags |= 0x0F;
+ break;
+
+ case RES_ROW_SPLIT:
+ {
+ if ( IsRowFrm() )
+ {
+ sal_Bool bInFollowFlowRow = 0 != IsInFollowFlowRow();
+ if ( bInFollowFlowRow || 0 != IsInSplitTableRow() )
+ {
+ SwTabFrm* pTab = FindTabFrm();
+ if ( bInFollowFlowRow )
+ pTab = pTab->FindMaster();
+ pTab->SetRemoveFollowFlowLinePending( sal_True );
+ }
+ }
+ break;
+ }
+ case RES_COL:
+ OSL_FAIL( "Spalten fuer neuen FrmTyp?" );
+ break;
+
+ default:
+ /* do Nothing */;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Prepare()
+|*
+|*************************************************************************/
+void SwFrm::Prepare( const PrepareHint, const void *, sal_Bool )
+{
+ /* Do nothing */
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InvalidatePage()
+|* Beschreibung: Invalidiert die Seite, in der der Frm gerade steht.
+|* Je nachdem ob es ein Layout, Cntnt oder FlyFrm ist wird die Seite
+|* entsprechend Invalidiert.
+|*
+|*************************************************************************/
+void SwFrm::InvalidatePage( const SwPageFrm *pPage ) const
+{
+ if ( !pPage )
+ {
+ pPage = FindPageFrm();
+ // --> OD 2004-07-02 #i28701# - for at-character and as-character
+ // anchored Writer fly frames additionally invalidate also page frame
+ // its 'anchor character' is on.
+ if ( pPage && pPage->GetUpper() && IsFlyFrm() )
+ {
+ const SwFlyFrm* pFlyFrm = static_cast<const SwFlyFrm*>(this);
+ if ( pFlyFrm->IsAutoPos() || pFlyFrm->IsFlyInCntFrm() )
+ {
+ // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
+ // is replaced by method <FindPageFrmOfAnchor()>. It's return value
+ // have to be checked.
+ SwPageFrm* pPageFrmOfAnchor =
+ const_cast<SwFlyFrm*>(pFlyFrm)->FindPageFrmOfAnchor();
+ if ( pPageFrmOfAnchor && pPageFrmOfAnchor != pPage )
+ // <--
+ {
+ InvalidatePage( pPageFrmOfAnchor );
+ }
+ }
+ }
+ // <--
+ }
+
+ if ( pPage && pPage->GetUpper() )
+ {
+ if ( pPage->GetFmt()->GetDoc()->IsInDtor() )
+ return;
+
+ SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
+ const SwFlyFrm *pFly = FindFlyFrm();
+ if ( IsCntntFrm() )
+ {
+ if ( pRoot->IsTurboAllowed() )
+ {
+ // JP 21.09.95: wenn sich der ContentFrame 2 mal eintragen
+ // will, kann es doch eine TurboAction bleiben.
+ // ODER????
+ if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
+ pRoot->SetTurbo( (const SwCntntFrm*)this );
+ else
+ {
+ pRoot->DisallowTurbo();
+ //Die Seite des Turbo koennte eine andere als die meinige
+ //sein, deshalb muss sie invalidiert werden.
+ const SwFrm *pTmp = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pTmp->InvalidatePage();
+ }
+ }
+ if ( !pRoot->GetTurbo() )
+ {
+ if ( pFly )
+ { if( !pFly->IsLocked() )
+ {
+ if ( pFly->IsFlyInCntFrm() )
+ { pPage->InvalidateFlyInCnt();
+ ((SwFlyInCntFrm*)pFly)->InvalidateCntnt();
+ pFly->GetAnchorFrm()->InvalidatePage();
+ }
+ else
+ pPage->InvalidateFlyCntnt();
+ }
+ }
+ else
+ pPage->InvalidateCntnt();
+ }
+ }
+ else
+ {
+ pRoot->DisallowTurbo();
+ if ( pFly )
+ {
+ if ( !pFly->IsLocked() )
+ {
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ pPage->InvalidateFlyInCnt();
+ ((SwFlyInCntFrm*)pFly)->InvalidateLayout();
+ pFly->GetAnchorFrm()->InvalidatePage();
+ }
+ else
+ pPage->InvalidateFlyLayout();
+ }
+ }
+ else
+ pPage->InvalidateLayout();
+
+ if ( pRoot->GetTurbo() )
+ { const SwFrm *pTmp = pRoot->GetTurbo();
+ pRoot->ResetTurbo();
+ pTmp->InvalidatePage();
+ }
+ }
+ pRoot->SetIdleFlags();
+
+ const SwTxtFrm *pTxtFrm = dynamic_cast< const SwTxtFrm * >(this);
+ if (pTxtFrm)
+ {
+ const SwTxtNode *pTxtNode = pTxtFrm->GetTxtNode();
+ if (pTxtNode && pTxtNode->IsGrammarCheckDirty())
+ pRoot->SetNeedGrammarCheck( sal_True );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ChgSize()
+|*
+|*************************************************************************/
+Size SwFrm::ChgSize( const Size& aNewSize )
+{
+ bFixSize = sal_True;
+ const Size aOldSize( Frm().SSize() );
+ if ( aNewSize == aOldSize )
+ return aOldSize;
+
+ if ( GetUpper() )
+ {
+ SWRECTFN2( this )
+ SwRect aNew( Point(0,0), aNewSize );
+ (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
+ long nNew = (aNew.*fnRect->fnGetHeight)();
+ long nDiff = nNew - (aFrm.*fnRect->fnGetHeight)();
+ if( nDiff )
+ {
+ if ( GetUpper()->IsFtnBossFrm() && HasFixSize() &&
+ NA_GROW_SHRINK !=
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this ) )
+ {
+ (aFrm.*fnRect->fnSetHeight)( nNew );
+ SwTwips nReal = ((SwLayoutFrm*)this)->AdjustNeighbourhood(nDiff);
+ if ( nReal != nDiff )
+ (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
+ }
+ else
+ {
+ // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
+ // NOTE: neighbour frames are cell and column frames.
+ if ( !bNeighb )
+ {
+ if ( nDiff > 0 )
+ Grow( nDiff );
+ else
+ Shrink( -nDiff );
+
+ if ( GetUpper() && (aFrm.*fnRect->fnGetHeight)() != nNew )
+ GetUpper()->_InvalidateSize();
+ }
+
+ // Auch wenn das Grow/Shrink noch nicht die gewuenschte Breite eingestellt hat,
+ // wie z.B. beim Aufruf durch ChgColumns, um die Spaltenbreiten einzustellen,
+ // wird die Breite jetzt gesetzt.
+ (aFrm.*fnRect->fnSetHeight)( nNew );
+ }
+ }
+ }
+ else
+ aFrm.SSize( aNewSize );
+
+ if ( Frm().SSize() != aOldSize )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ GetNext()->InvalidatePage( pPage );
+ }
+ if( IsLayoutFrm() )
+ {
+ if( IsRightToLeft() )
+ _InvalidatePos();
+ if( ((SwLayoutFrm*)this)->Lower() )
+ ((SwLayoutFrm*)this)->Lower()->_InvalidateSize();
+ }
+ _InvalidatePrt();
+ _InvalidateSize();
+ InvalidatePage( pPage );
+ }
+
+ return aFrm.SSize();
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertBefore()
+|*
+|* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
+|* Eingefuegt wird unterhalb des Parent und entweder
+|* vor pBehind oder am Ende der Kette wenn pBehind
+|* leer ist.
+|*
+|*************************************************************************/
+void SwFrm::InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBehind || (pBehind && pParent == pBehind->GetUpper())),
+ "Framebaum inkonsistent." );
+
+ pUpper = pParent;
+ pNext = pBehind;
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( 0 != (pPrev = pBehind->pPrev) )
+ pPrev->pNext = this;
+ else
+ pUpper->pLower = this;
+ pBehind->pPrev = this;
+ }
+ else
+ { //Einfuegen am Ende, oder als ersten Node im Unterbaum
+ pPrev = pUpper->Lower();
+ if ( pPrev )
+ {
+ while( pPrev->pNext )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = this;
+ }
+ else
+ pUpper->pLower = this;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertBehind()
+|*
+|* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
+|* Eingefuegt wird unterhalb des Parent und entweder
+|* hinter pBefore oder am Anfang der Kette wenn pBefore
+|* leer ist.
+|*
+|*************************************************************************/
+void SwFrm::InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBefore || (pBefore && pParent == pBefore->GetUpper())),
+ "Framebaum inkonsistent." );
+
+ pUpper = pParent;
+ pPrev = pBefore;
+ if ( pBefore )
+ {
+ //Einfuegen hinter pBefore
+ if ( 0 != (pNext = pBefore->pNext) )
+ pNext->pPrev = this;
+ pBefore->pNext = this;
+ }
+ else
+ {
+ //Einfuegen am Anfang der Kette
+ pNext = pParent->Lower();
+ if ( pParent->Lower() )
+ pParent->Lower()->pPrev = this;
+ pParent->pLower = this;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::InsertGroup()
+|*
+|* Beschreibung Eine Kette von SwFrms wird in eine bestehende Struktur
+|* eingefuegt
+|*
+|* Bisher wird dies genutzt, um einen SectionFrame, der ggf. schon Geschwister
+|* mit sich bringt, in eine bestehende Struktur einzufuegen.
+|*
+|* Wenn man den dritten Parameter als NULL uebergibt, entspricht
+|* diese Methode dem SwFrm::InsertBefore(..), nur eben mit Geschwistern.
+|*
+|* Wenn man einen dritten Parameter uebergibt, passiert folgendes:
+|* this wird pNext von pParent,
+|* pSct wird pNext vom Letzten der this-Kette,
+|* pBehind wird vom pParent an den pSct umgehaengt.
+|* Dies dient dazu: ein SectionFrm (this) wird nicht als
+|* Kind an einen anderen SectionFrm (pParent) gehaengt, sondern pParent
+|* wird in zwei Geschwister aufgespalten (pParent+pSct) und this dazwischen
+|* eingebaut.
+|*
+|*************************************************************************/
+void SwFrm::InsertGroupBefore( SwFrm* pParent, SwFrm* pBehind, SwFrm* pSct )
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Insert." );
+ OSL_ENSURE( (!pBehind || ( (pBehind && (pParent == pBehind->GetUpper()))
+ || ((pParent->IsSctFrm() && pBehind->GetUpper()->IsColBodyFrm())) ) ),
+ "Framebaum inkonsistent." );
+ if( pSct )
+ {
+ pUpper = pParent->GetUpper();
+ SwFrm *pLast = this;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ if( pBehind )
+ {
+ pLast->pNext = pSct;
+ pSct->pPrev = pLast;
+ pSct->pNext = pParent->GetNext();
+ }
+ else
+ {
+ pLast->pNext = pParent->GetNext();
+ if( pLast->GetNext() )
+ pLast->GetNext()->pPrev = pLast;
+ }
+ pParent->pNext = this;
+ pPrev = pParent;
+ if( pSct->GetNext() )
+ pSct->GetNext()->pPrev = pSct;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( pBehind->GetPrev() )
+ pBehind->GetPrev()->pNext = NULL;
+ else
+ pBehind->GetUpper()->pLower = NULL;
+ pBehind->pPrev = NULL;
+ SwLayoutFrm* pTmp = (SwLayoutFrm*)pSct;
+ if( pTmp->Lower() )
+ {
+ OSL_ENSURE( pTmp->Lower()->IsColumnFrm(), "InsertGrp: Used SectionFrm" );
+ pTmp = (SwLayoutFrm*)((SwLayoutFrm*)pTmp->Lower())->Lower();
+ OSL_ENSURE( pTmp, "InsertGrp: Missing ColBody" );
+ }
+ pBehind->pUpper = pTmp;
+ pBehind->GetUpper()->pLower = pBehind;
+ pLast = pBehind->GetNext();
+ while ( pLast )
+ {
+ pLast->pUpper = pBehind->GetUpper();
+ pLast = pLast->GetNext();
+ };
+ }
+ else
+ {
+ OSL_ENSURE( pSct->IsSctFrm(), "InsertGroup: For SectionFrms only" );
+ delete ((SwSectionFrm*)pSct);
+ }
+ }
+ else
+ {
+ pUpper = (SwLayoutFrm*)pParent;
+ SwFrm *pLast = this;
+ while( pLast->GetNext() )
+ {
+ pLast = pLast->GetNext();
+ pLast->pUpper = GetUpper();
+ }
+ pLast->pNext = pBehind;
+ if( pBehind )
+ { //Einfuegen vor pBehind.
+ if( 0 != (pPrev = pBehind->pPrev) )
+ pPrev->pNext = this;
+ else
+ pUpper->pLower = this;
+ pBehind->pPrev = pLast;
+ }
+ else
+ { //Einfuegen am Ende, oder des ersten Nodes im Unterbaum
+ pPrev = pUpper->Lower();
+ if ( pPrev )
+ {
+ while( pPrev->pNext )
+ pPrev = pPrev->pNext;
+ pPrev->pNext = this;
+ }
+ else
+ pUpper->pLower = this;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Remove()
+|*
+|*************************************************************************/
+void SwFrm::Remove()
+{
+ OSL_ENSURE( pUpper, "Removen ohne Upper?" );
+
+ if( pPrev )
+ // einer aus der Mitte wird removed
+ pPrev->pNext = pNext;
+ else
+ { // der erste in einer Folge wird removed
+ OSL_ENSURE( pUpper->pLower == this, "Layout inkonsistent." );
+ pUpper->pLower = pNext;
+ }
+ if( pNext )
+ pNext->pPrev = pPrev;
+
+ // Verbindung kappen.
+ pNext = pPrev = 0;
+ pUpper = 0;
+}
+/*************************************************************************
+|*
+|* SwCntntFrm::Paste()
+|*
+|*************************************************************************/
+void SwCntntFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+ OSL_ENSURE( !pSibling || pSibling->IsFlowFrm(),
+ "<SwCntntFrm::Paste(..)> - sibling not of expected type." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ SwPageFrm *pPage = FindPageFrm();
+ _InvalidateAll();
+ InvalidatePage( pPage );
+
+ if( pPage )
+ {
+ pPage->InvalidateSpelling();
+ pPage->InvalidateSmartTags(); // SMARTTAGS
+ pPage->InvalidateAutoCompleteWords();
+ pPage->InvalidateWordCount();
+ }
+
+ if ( GetNext() )
+ {
+ SwFrm* pNxt = GetNext();
+ pNxt->_InvalidatePrt();
+ pNxt->_InvalidatePos();
+ pNxt->InvalidatePage( pPage );
+ if( pNxt->IsSctFrm() )
+ pNxt = ((SwSectionFrm*)pNxt)->ContainsCntnt();
+ if( pNxt && pNxt->IsTxtFrm() && pNxt->IsInFtn() )
+ pNxt->Prepare( PREP_FTN, 0, sal_False );
+ }
+
+ if ( Frm().Height() )
+ pParent->Grow( Frm().Height() );
+
+ if ( Frm().Width() != pParent->Prt().Width() )
+ Prepare( PREP_FIXSIZE_CHG );
+
+ if ( GetPrev() )
+ {
+ if ( IsFollow() )
+ //Ich bin jetzt direkter Nachfolger meines Masters geworden
+ ((SwCntntFrm*)GetPrev())->Prepare( PREP_FOLLOW_FOLLOWS );
+ else
+ {
+ if ( GetPrev()->Frm().Height() !=
+ GetPrev()->Prt().Height() + GetPrev()->Prt().Top() )
+ //Umrandung zu beruecksichtigen?
+ GetPrev()->_InvalidatePrt();
+ // OD 18.02.2003 #104989# - force complete paint of previous frame,
+ // if frame is inserted at the end of a section frame, in order to
+ // get subsidiary lines repainted for the section.
+ if ( pParent->IsSctFrm() && !GetNext() )
+ {
+ // force complete paint of previous frame, if new inserted frame
+ // in the section is the last one.
+ GetPrev()->SetCompletePaint();
+ }
+ GetPrev()->InvalidatePage( pPage );
+ }
+ }
+ if ( IsInFtn() )
+ {
+ SwFrm* pFrm = GetIndPrev();
+ if( pFrm && pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ if( !GetNext() )
+ {
+ pFrm = FindFtnFrm()->GetNext();
+ if( pFrm && 0 != (pFrm=((SwLayoutFrm*)pFrm)->ContainsAny()) )
+ pFrm->_InvalidatePrt();
+ }
+ }
+
+ _InvalidateLineNum();
+ SwFrm *pNxt = FindNextCnt();
+ if ( pNxt )
+ {
+ while ( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if ( pNxt )
+ {
+ pNxt->_InvalidateLineNum();
+ if ( pNxt != GetNext() )
+ pNxt->InvalidatePage();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::Cut()
+|*
+|*************************************************************************/
+void SwCntntFrm::Cut()
+{
+ OSL_ENSURE( GetUpper(), "Cut ohne Upper()." );
+
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm = GetIndPrev();
+ if( pFrm )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if ( pFrm && pFrm->IsCntntFrm() )
+ {
+ pFrm->_InvalidatePrt();
+ if( IsInFtn() )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ // --> OD 2004-07-15 #i26250# - invalidate printing area of previous
+ // table frame.
+ else if ( pFrm && pFrm->IsTabFrm() )
+ {
+ pFrm->InvalidatePrt();
+ }
+ // <--
+ }
+
+ SwFrm *pNxt = FindNextCnt();
+ if ( pNxt )
+ {
+ while ( pNxt && pNxt->IsInTab() )
+ {
+ if( 0 != (pNxt = pNxt->FindTabFrm()) )
+ pNxt = pNxt->FindNextCnt();
+ }
+ if ( pNxt )
+ {
+ pNxt->_InvalidateLineNum();
+ if ( pNxt != GetNext() )
+ pNxt->InvalidatePage();
+ }
+ }
+
+ if( 0 != (pFrm = GetIndNext()) )
+ { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
+ //berechnet, der ist jetzt, wo er der erste wird obsolet bzw. anders.
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ if( pFrm->IsSctFrm() )
+ {
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ {
+ pFrm->_InvalidatePrt();
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ }
+ }
+ if( pFrm && IsInFtn() )
+ pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ }
+ else
+ {
+ InvalidateNextPos();
+ //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
+ if ( 0 != (pFrm = GetPrev()) )
+ { pFrm->SetRetouche();
+ pFrm->Prepare( PREP_WIDOWS_ORPHANS );
+ pFrm->_InvalidatePos();
+ pFrm->InvalidatePage( pPage );
+ }
+ //Wenn ich der einzige CntntFrm in meinem Upper bin (war), so muss
+ //er die Retouche uebernehmen.
+ //Ausserdem kann eine Leerseite entstanden sein.
+ else
+ { SwRootFrm *pRoot = getRootFrm();
+ if ( pRoot )
+ {
+ pRoot->SetSuperfluous();
+ GetUpper()->SetCompletePaint();
+ GetUpper()->InvalidatePage( pPage );
+ }
+ if( IsInSct() )
+ {
+ SwSectionFrm* pSct = FindSctFrm();
+ if( !pSct->IsFollow() )
+ {
+ pSct->_InvalidatePrt();
+ pSct->InvalidatePage( pPage );
+ }
+ }
+ // --> FME 2005-08-03 #i52253# The master table should take care
+ // of removing the follow flow line.
+ if ( IsInTab() )
+ {
+ SwTabFrm* pThisTab = FindTabFrm();
+ SwTabFrm* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : 0;
+ if ( pMasterTab )
+ {
+ pMasterTab->_InvalidatePos();
+ pMasterTab->SetRemoveFollowFlowLinePending( sal_True );
+ }
+ }
+ // <--
+ }
+ }
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+ Remove();
+ if ( pUp )
+ {
+ SwSectionFrm *pSct = 0;
+ if ( !pUp->Lower() &&
+ ( ( pUp->IsFtnFrm() && !pUp->IsColLocked() ) ||
+ ( pUp->IsInSct() &&
+ // --> FME 2004-06-03 #i29438#
+ // We have to consider the case that the section may be "empty"
+ // except from a temporary empty table frame.
+ // This can happen due to the new cell split feature.
+ !pUp->IsCellFrm() &&
+ // <--
+ // --> OD 2006-01-04 #126020# - adjust check for empty section
+ // --> OD 2006-02-01 #130797# - correct fix #126020#
+ !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
+ !pSct->ContainsAny( true ) ) ) )
+ // <--
+ {
+ if ( pUp->GetUpper() )
+ {
+ // --> OD 2006-09-25 #b6448963#
+ // prevent delete of <ColLocked> footnote frame
+ if ( pUp->IsFtnFrm() && !pUp->IsColLocked())
+ // <--
+ {
+ if( pUp->GetNext() && !pUp->GetPrev() )
+ {
+ SwFrm* pTmp = ((SwLayoutFrm*)pUp->GetNext())->ContainsAny();
+ if( pTmp )
+ pTmp->_InvalidatePrt();
+ }
+ pUp->Cut();
+ delete pUp;
+ }
+ else
+ {
+ // --> OD 2006-09-25 #b6448963#
+ if ( pSct->IsColLocked() || !pSct->IsInFtn() ||
+ ( pUp->IsFtnFrm() && pUp->IsColLocked() ) )
+ // <--
+ {
+ pSct->DelEmpty( sal_False );
+ // Wenn ein gelockter Bereich nicht geloescht werden darf,
+ // so ist zumindest seine Groesse durch das Entfernen seines
+ // letzten Contents ungueltig geworden.
+ pSct->_InvalidateSize();
+ }
+ else
+ {
+ pSct->DelEmpty( sal_True );
+ delete pSct;
+ }
+ }
+ }
+ }
+ else
+ {
+ SWRECTFN( this )
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight )
+ pUp->Shrink( nFrmHeight );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Paste()
+|*
+|*************************************************************************/
+void SwLayoutFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
+{
+ OSL_ENSURE( pParent, "Kein Parent fuer Paste." );
+ OSL_ENSURE( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
+ OSL_ENSURE( pParent != this, "Bin selbst der Parent." );
+ OSL_ENSURE( pSibling != this, "Bin mein eigener Nachbar." );
+ OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
+ "Bin noch irgendwo angemeldet." );
+
+ //In den Baum einhaengen.
+ InsertBefore( (SwLayoutFrm*)pParent, pSibling );
+
+ // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
+ // <fnRect> is used for the following:
+ // (1) To invalidate the frame's size, if its size, which has to be the
+ // same as its upper/parent, differs from its upper's/parent's.
+ // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
+ // size, which is not determined by its upper/parent.
+ // Which size is which depends on the frame type and the layout direction
+ // (vertical or horizontal).
+ // There are the following cases:
+ // (A) Header and footer frames both in vertical and in horizontal layout
+ // have to size the width to the upper/parent. A dimension in the height
+ // has to cause a adjustment/grow of the upper/parent.
+ // --> <fnRect> = fnRectHori
+ // (B) Cell and column frames in vertical layout, the width has to be the
+ // same as upper/parent and a dimension in height causes adjustment/grow
+ // of the upper/parent.
+ // --> <fnRect> = fnRectHori
+ // in horizontal layout the other way around
+ // --> <fnRect> = fnRectVert
+ // (C) Other frames in vertical layout, the height has to be the
+ // same as upper/parent and a dimension in width causes adjustment/grow
+ // of the upper/parent.
+ // --> <fnRect> = fnRectVert
+ // in horizontal layout the other way around
+ // --> <fnRect> = fnRectHori
+ //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
+ SwRectFn fnRect;
+ if ( IsHeaderFrm() || IsFooterFrm() )
+ fnRect = fnRectHori;
+ else if ( IsCellFrm() || IsColumnFrm() )
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert );
+ else
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+
+
+ if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)())
+ _InvalidateSize();
+ _InvalidatePos();
+ const SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ SwFrm *pFrm;
+ if( !IsColumnFrm() )
+ {
+ if( 0 != ( pFrm = GetIndNext() ) )
+ {
+ pFrm->_InvalidatePos();
+ if( IsInFtn() )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
+ }
+ }
+ if ( IsInFtn() && 0 != ( pFrm = GetIndPrev() ) )
+ {
+ if( pFrm->IsSctFrm() )
+ pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
+ if( pFrm )
+ pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
+ }
+ }
+
+ if( (Frm().*fnRect->fnGetHeight)() )
+ {
+ // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
+ // die sich nicht in Rahmen befinden
+ sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+ SwTwips nGrow = (Frm().*fnRect->fnGetHeight)();
+ if( NA_ONLY_ADJUST == nAdjust )
+ AdjustNeighbourhood( nGrow );
+ else
+ {
+ SwTwips nReal = 0;
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal = AdjustNeighbourhood( nGrow );
+ if( nReal < nGrow )
+ nReal += pParent->Grow( nGrow - nReal );
+ if( NA_GROW_ADJUST == nAdjust && nReal < nGrow )
+ AdjustNeighbourhood( nGrow - nReal );
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Cut()
+|*
+|*************************************************************************/
+void SwLayoutFrm::Cut()
+{
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+
+ SWRECTFN( this )
+ SwTwips nShrink = (Frm().*fnRect->fnGetHeight)();
+
+ //Erst removen, dann Upper Shrinken.
+ SwLayoutFrm *pUp = GetUpper();
+
+ // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
+ // die sich nicht in Rahmen befinden
+
+ // Remove must not be called before a AdjustNeighbourhood, but it has to
+ // be called before the upper-shrink-call, if the upper-shrink takes care
+ // of his content
+ if ( pUp && nShrink )
+ {
+ if( pUp->IsFtnBossFrm() )
+ {
+ sal_uInt8 nAdjust= ((SwFtnBossFrm*)pUp)->NeighbourhoodAdjustment( this );
+ if( NA_ONLY_ADJUST == nAdjust )
+ AdjustNeighbourhood( -nShrink );
+ else
+ {
+ SwTwips nReal = 0;
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal = -AdjustNeighbourhood( -nShrink );
+ if( nReal < nShrink )
+ {
+ SwTwips nOldHeight = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( 0 );
+ nReal += pUp->Shrink( nShrink - nReal );
+ (Frm().*fnRect->fnSetHeight)( nOldHeight );
+ }
+ if( NA_GROW_ADJUST == nAdjust && nReal < nShrink )
+ AdjustNeighbourhood( nReal - nShrink );
+ }
+ Remove();
+ }
+ else
+ {
+ Remove();
+ pUp->Shrink( nShrink );
+ }
+ }
+ else
+ Remove();
+
+ if( pUp && !pUp->Lower() )
+ {
+ pUp->SetCompletePaint();
+ pUp->InvalidatePage();
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Grow()
+|*
+|*************************************************************************/
+SwTwips SwFrm::Grow( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ OSL_ENSURE( nDist >= 0, "Negatives Wachstum?" );
+
+ PROTOCOL_ENTER( this, bTst ? PROT_GROW_TST : PROT_GROW, 0, &nDist )
+
+ if ( nDist )
+ {
+ SWRECTFN( this )
+
+ SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
+ nDist = LONG_MAX - nPrtHeight;
+
+ if ( IsFlyFrm() )
+ return ((SwFlyFrm*)this)->_Grow( nDist, bTst );
+ else if( IsSctFrm() )
+ return ((SwSectionFrm*)this)->_Grow( nDist, bTst );
+ else
+ {
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell )
+ {
+ const SwTabFrm* pTab = FindTabFrm();
+
+ // NEW TABLES
+ if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
+ pThisCell->GetLayoutRowSpan() < 1 )
+ return 0;
+ }
+
+ const SwTwips nReal = GrowFrm( nDist, bTst, bInfo );
+ if( !bTst )
+ {
+ nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight +
+ ( IsCntntFrm() ? nDist : nReal ) );
+ }
+ return nReal;
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::Shrink()
+|*
+|*************************************************************************/
+SwTwips SwFrm::Shrink( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ OSL_ENSURE( nDist >= 0, "Negative Verkleinerung?" );
+
+ PROTOCOL_ENTER( this, bTst ? PROT_SHRINK_TST : PROT_SHRINK, 0, &nDist )
+
+ if ( nDist )
+ {
+ if ( IsFlyFrm() )
+ return ((SwFlyFrm*)this)->_Shrink( nDist, bTst );
+ else if( IsSctFrm() )
+ return ((SwSectionFrm*)this)->_Shrink( nDist, bTst );
+ else
+ {
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell )
+ {
+ const SwTabFrm* pTab = FindTabFrm();
+
+ // NEW TABLES
+ if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
+ pThisCell->GetLayoutRowSpan() < 1 )
+ return 0;
+ }
+
+ SWRECTFN( this )
+ SwTwips nReal = (Frm().*fnRect->fnGetHeight)();
+ ShrinkFrm( nDist, bTst, bInfo );
+ nReal -= (Frm().*fnRect->fnGetHeight)();
+ if( !bTst )
+ {
+ const SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ (Prt().*fnRect->fnSetHeight)( nPrtHeight -
+ ( IsCntntFrm() ? nDist : nReal ) );
+ }
+ return nReal;
+ }
+ }
+ return 0L;
+}
+
+/*************************************************************************
+|*
+|* SwFrm::AdjustNeighbourhood()
+|*
+|* Beschreibung Wenn sich die Groesse eines Frm's direkt unterhalb
+|* eines Fussnotenbosses (Seite/Spalte) veraendert hat, so muss dieser
+|* "Normalisiert" werden.
+|* Es gibt dort immer einen Frame, der den "maximal moeglichen" Raum
+|* einnimmt (der Frame, der den Body.Text enhaelt) und keinen oder
+|* mehrere Frames die den Platz einnehmen den sie halt brauchen
+|* (Kopf-/Fussbereich, Fussnoten).
+|* Hat sich einer der Frames veraendert, so muss der Body-Text-Frame
+|* entsprechen wachsen oder schrumpfen; unabhaegig davon, dass er fix ist.
+|* !! Ist es moeglich dies allgemeiner zu loesen, also nicht auf die
+|* Seite beschraenkt und nicht auf einen Speziellen Frame, der den
+|* maximalen Platz einnimmt (gesteuert ueber Attribut FrmSize)? Probleme:
+|* Was ist wenn mehrere Frames nebeneinander stehen, die den maximalen
+|* Platz einnehmen?
+|* Wie wird der Maximale Platz berechnet?
+|* Wie klein duerfen diese Frames werden?
+|*
+|* Es wird auf jeden Fall nur so viel Platz genehmigt, dass ein
+|* Minimalwert fuer die Hoehe des Bodys nicht unterschritten wird.
+|*
+|* Parameter: nDiff ist der Betrag, um den Platz geschaffen werden muss
+|*
+|*************************************************************************/
+SwTwips SwFrm::AdjustNeighbourhood( SwTwips nDiff, sal_Bool bTst )
+{
+ PROTOCOL_ENTER( this, PROT_ADJUSTN, 0, &nDiff );
+
+ if ( !nDiff || !GetUpper()->IsFtnBossFrm() ) // nur innerhalb von Seiten/Spalten
+ return 0L;
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+
+ //Der (Page)Body veraendert sich nur im BrowseMode, aber nicht wenn er
+ //Spalten enthaelt.
+ if ( IsPageBodyFrm() && (!bBrowse ||
+ (((SwLayoutFrm*)this)->Lower() &&
+ ((SwLayoutFrm*)this)->Lower()->IsColumnFrm())) )
+ return 0L;
+
+ //In der BrowseView kann der PageFrm selbst ersteinmal einiges von den
+ //Wuenschen abfangen.
+ long nBrowseAdd = 0;
+ if ( bBrowse && GetUpper()->IsPageFrm() ) // nur (Page)BodyFrms
+ {
+ ViewShell *pViewShell = getRootFrm()->GetCurrShell();
+ SwLayoutFrm *pUp = GetUpper();
+ long nChg;
+ const long nUpPrtBottom = pUp->Frm().Height() -
+ pUp->Prt().Height() - pUp->Prt().Top();
+ SwRect aInva( pUp->Frm() );
+ if ( pViewShell )
+ {
+ aInva.Pos().X() = pViewShell->VisArea().Left();
+ aInva.Width( pViewShell->VisArea().Width() );
+ }
+ if ( nDiff > 0 )
+ {
+ nChg = BROWSE_HEIGHT - pUp->Frm().Height();
+ nChg = Min( nDiff, nChg );
+
+ if ( !IsBodyFrm() )
+ {
+ SetCompletePaint();
+ if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->Frm().Height() )
+ {
+ //Ersteinmal den Body verkleinern. Der waechst dann schon
+ //wieder.
+ SwFrm *pBody = ((SwFtnBossFrm*)pUp)->FindBodyCont();
+ const long nTmp = nChg - pBody->Prt().Height();
+ if ( !bTst )
+ {
+ pBody->Frm().Height(Max( 0L, pBody->Frm().Height() - nChg ));
+ pBody->_InvalidatePrt();
+ pBody->_InvalidateSize();
+ if ( pBody->GetNext() )
+ pBody->GetNext()->_InvalidatePos();
+ if ( !IsHeaderFrm() )
+ pBody->SetCompletePaint();
+ }
+ nChg = nTmp <= 0 ? 0 : nTmp;
+ }
+ }
+
+ const long nTmp = nUpPrtBottom + 20;
+ aInva.Top( aInva.Bottom() - nTmp );
+ aInva.Height( nChg + nTmp );
+ }
+ else
+ {
+ //Die Seite kann bis auf 0 schrumpfen. Die erste Seite bleibt
+ //mindestens so gross wie die VisArea.
+ nChg = nDiff;
+ long nInvaAdd = 0;
+ if ( pViewShell && !pUp->GetPrev() &&
+ pUp->Frm().Height() + nDiff < pViewShell->VisArea().Height() )
+ {
+ //Das heisst aber wiederum trotzdem, das wir geeignet invalidieren
+ //muessen.
+ nChg = pViewShell->VisArea().Height() - pUp->Frm().Height();
+ nInvaAdd = -(nDiff - nChg);
+ }
+
+ //Invalidieren inklusive unterem Rand.
+ long nBorder = nUpPrtBottom + 20;
+ nBorder -= nChg;
+ aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
+ if ( !IsBodyFrm() )
+ {
+ SetCompletePaint();
+ if ( !IsHeaderFrm() )
+ ((SwFtnBossFrm*)pUp)->FindBodyCont()->SetCompletePaint();
+ }
+ //Wegen der Rahmen die Seite invalidieren. Dadurch wird die Seite
+ //wieder entsprechend gross wenn ein Rahmen nicht passt. Das
+ //funktioniert anderfalls nur zufaellig fuer absatzgebundene Rahmen
+ //(NotifyFlys).
+ pUp->InvalidateSize();
+ }
+ if ( !bTst )
+ {
+ //Unabhaengig von nChg
+ if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
+ pViewShell->InvalidateWindows( aInva );
+ }
+ if ( !bTst && nChg )
+ {
+ const SwRect aOldRect( pUp->Frm() );
+ pUp->Frm().SSize().Height() += nChg;
+ pUp->Prt().SSize().Height() += nChg;
+ if ( pViewShell )
+ pViewShell->Imp()->SetFirstVisPageInvalid();
+
+ if ( GetNext() )
+ GetNext()->_InvalidatePos();
+
+ //Ggf. noch ein Repaint ausloesen.
+ const SvxGraphicPosition ePos = pUp->GetFmt()->GetBackground().GetGraphicPos();
+ if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
+ pViewShell->InvalidateWindows( pUp->Frm() );
+
+ if ( pUp->GetUpper() )
+ {
+ if ( pUp->GetNext() )
+ pUp->GetNext()->InvalidatePos();
+
+ //Mies aber wahr: im Notify am ViewImp wird evtl. ein Calc
+ //auf die Seite und deren Lower gerufen. Die Werte sollten
+ //unverandert bleiben, weil der Aufrufer bereits fuer die
+ //Anpassung von Frm und Prt sorgen wird.
+ const long nOldFrmHeight = Frm().Height();
+ const long nOldPrtHeight = Prt().Height();
+ const sal_Bool bOldComplete = IsCompletePaint();
+ if ( IsBodyFrm() )
+ Prt().SSize().Height() = nOldFrmHeight;
+
+ // PAGES01
+ if ( pUp->GetUpper() )
+ static_cast<SwRootFrm*>(pUp->GetUpper())->CheckViewLayout( 0, 0 );
+ //((SwPageFrm*)pUp)->AdjustRootSize( CHG_CHGPAGE, &aOldRect );
+
+ Frm().SSize().Height() = nOldFrmHeight;
+ Prt().SSize().Height() = nOldPrtHeight;
+ bCompletePaint = bOldComplete;
+ }
+ if ( !IsBodyFrm() )
+ pUp->_InvalidateSize();
+ InvalidatePage( (SwPageFrm*)pUp );
+ }
+ nDiff -= nChg;
+ if ( !nDiff )
+ return nChg;
+ else
+ nBrowseAdd = nChg;
+ }
+
+ const SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
+
+ SwTwips nReal = 0,
+ nAdd = 0;
+ SwFrm *pFrm = 0;
+ SWRECTFN( this )
+
+ if( IsBodyFrm() )
+ {
+ if( IsInSct() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
+ GetNext()->IsFtnContFrm() )
+ {
+ SwFtnContFrm* pCont = (SwFtnContFrm*)GetNext();
+ SwTwips nMinH = 0;
+ SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
+ sal_Bool bFtn = sal_False;
+ while( pFtn )
+ {
+ if( !pFtn->GetAttr()->GetFtn().IsEndNote() )
+ {
+ nMinH += (pFtn->Frm().*fnRect->fnGetHeight)();
+ bFtn = sal_True;
+ }
+ pFtn = (SwFtnFrm*)pFtn->GetNext();
+ }
+ if( bFtn )
+ nMinH += (pCont->Prt().*fnRect->fnGetTop)();
+ nReal = (pCont->Frm().*fnRect->fnGetHeight)() - nMinH;
+ if( nReal > nDiff )
+ nReal = nDiff;
+ if( nReal > 0 )
+ pFrm = GetNext();
+ else
+ nReal = 0;
+ }
+ if( !bTst && !pSect->IsColLocked() )
+ pSect->InvalidateSize();
+ }
+ if( !pFrm )
+ return nBrowseAdd;
+ }
+ else
+ {
+ const sal_Bool bFtnPage = pBoss->IsPageFrm() && ((SwPageFrm*)pBoss)->IsFtnPage();
+ if ( bFtnPage && !IsFtnContFrm() )
+ pFrm = (SwFrm*)pBoss->FindFtnCont();
+ if ( !pFrm )
+ pFrm = (SwFrm*)pBoss->FindBodyCont();
+
+ if ( !pFrm )
+ return 0;
+
+ //Wenn ich keinen finde eruebrigt sich alles weitere.
+ nReal = (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( nReal > nDiff )
+ nReal = nDiff;
+ if( !bFtnPage )
+ {
+ //Minimalgrenze beachten!
+ if( nReal )
+ {
+ const SwTwips nMax = pBoss->GetVarSpace();
+ if ( nReal > nMax )
+ nReal = nMax;
+ }
+ if( !IsFtnContFrm() && nDiff > nReal &&
+ pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm()
+ && ( pFrm->GetNext()->IsVertical() == IsVertical() )
+ )
+ {
+ //Wenn der Body nicht genuegend her gibt, kann ich noch mal
+ //schauen ob es eine Fussnote gibt, falls ja kann dieser
+ //entsprechend viel gemopst werden.
+ const SwTwips nAddMax = (pFrm->GetNext()->Frm().*fnRect->
+ fnGetHeight)();
+ nAdd = nDiff - nReal;
+ if ( nAdd > nAddMax )
+ nAdd = nAddMax;
+ if ( !bTst )
+ {
+ (pFrm->GetNext()->Frm().*fnRect->fnSetHeight)(nAddMax-nAdd);
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bVert && !bVertL2R && !bRev )
+ pFrm->GetNext()->Frm().Pos().X() += nAdd;
+ pFrm->GetNext()->InvalidatePrt();
+ if ( pFrm->GetNext()->GetNext() )
+ pFrm->GetNext()->GetNext()->_InvalidatePos();
+ }
+ }
+ }
+ }
+
+ if ( !bTst && nReal )
+ {
+ SwTwips nTmp = (pFrm->Frm().*fnRect->fnGetHeight)();
+ (pFrm->Frm().*fnRect->fnSetHeight)( nTmp - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bVert && !bVertL2R && !bRev )
+ pFrm->Frm().Pos().X() += nReal;
+ pFrm->InvalidatePrt();
+ if ( pFrm->GetNext() )
+ pFrm->GetNext()->_InvalidatePos();
+ if( nReal < 0 && pFrm->IsInSct() )
+ {
+ SwLayoutFrm* pUp = pFrm->GetUpper();
+ if( pUp && 0 != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrm() &&
+ !pUp->IsColLocked() )
+ pUp->InvalidateSize();
+ }
+ if( ( IsHeaderFrm() || IsFooterFrm() ) && pBoss->GetDrawObjs() )
+ {
+ const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
+ OSL_ENSURE( pBoss->IsPageFrm(), "Header/Footer out of page?" );
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ OSL_ENSURE( !pFly->IsFlyInCntFrm(), "FlyInCnt at Page?" );
+ const SwFmtVertOrient &rVert =
+ pFly->GetFmt()->GetVertOrient();
+ // Wann muss invalidiert werden?
+ // Wenn ein Rahmen am SeitenTextBereich ausgerichtet ist,
+ // muss bei Aenderung des Headers ein TOP, MIDDLE oder NONE,
+ // bei Aenderung des Footers ein BOTTOM oder MIDDLE
+ // ausgerichteter Rahmen seine Position neu berechnen.
+ if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
+ rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
+ ((IsHeaderFrm() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
+ (IsFooterFrm() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
+ rVert.GetVertOrient() != text::VertOrientation::TOP)) )
+ {
+ pFly->_InvalidatePos();
+ pFly->_Invalidate();
+ }
+ }
+ }
+ }
+ }
+ return (nBrowseAdd + nReal + nAdd);
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ImplInvalidateSize(), ImplInvalidatePrt(), ImplInvalidatePos(),
+|* ImplInvalidateLineNum()
+|*
+|*************************************************************************/
+/** method to perform additional actions on an invalidation
+
+ OD 2004-05-19 #i28701#
+
+ @author OD
+*/
+void SwFrm::_ActionOnInvalidation( const InvalidationType )
+{
+ // default behaviour is to perform no additional action
+}
+
+/** method to determine, if an invalidation is allowed.
+
+ OD 2004-05-19 #i28701#
+
+ @author OD
+*/
+bool SwFrm::_InvalidationAllowed( const InvalidationType ) const
+{
+ // default behaviour is to allow invalidation
+ return true;
+}
+
+void SwFrm::ImplInvalidateSize()
+{
+ if ( _InvalidationAllowed( INVALID_SIZE ) )
+ {
+ bValidSize = sal_False;
+ if ( IsFlyFrm() )
+ ((SwFlyFrm*)this)->_Invalidate();
+ else
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_SIZE );
+ }
+}
+
+void SwFrm::ImplInvalidatePrt()
+{
+ if ( _InvalidationAllowed( INVALID_PRTAREA ) )
+ {
+ bValidPrtArea = sal_False;
+ if ( IsFlyFrm() )
+ ((SwFlyFrm*)this)->_Invalidate();
+ else
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_PRTAREA );
+ }
+}
+
+void SwFrm::ImplInvalidatePos()
+{
+ if ( _InvalidationAllowed( INVALID_POS ) )
+ {
+ bValidPos = sal_False;
+ if ( IsFlyFrm() )
+ {
+ ((SwFlyFrm*)this)->_Invalidate();
+ }
+ else
+ {
+ InvalidatePage();
+ }
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_POS );
+ }
+}
+
+void SwFrm::ImplInvalidateLineNum()
+{
+ if ( _InvalidationAllowed( INVALID_LINENUM ) )
+ {
+ bValidLineNum = sal_False;
+ OSL_ENSURE( IsTxtFrm(), "line numbers are implemented for text only" );
+ InvalidatePage();
+
+ // OD 2004-05-19 #i28701#
+ _ActionOnInvalidation( INVALID_LINENUM );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwFrm::ReinitializeFrmSizeAttrFlags
+|*
+|*************************************************************************/
+void SwFrm::ReinitializeFrmSizeAttrFlags()
+{
+ const SwFmtFrmSize &rFmtSize = GetAttrSet()->GetFrmSize();
+ if ( ATT_VAR_SIZE == rFmtSize.GetHeightSizeType() ||
+ ATT_MIN_SIZE == rFmtSize.GetHeightSizeType())
+ {
+ bFixSize = sal_False;
+ if ( GetType() & (FRM_HEADER | FRM_FOOTER | FRM_ROW) )
+ {
+ SwFrm *pFrm = ((SwLayoutFrm*)this)->Lower();
+ while ( pFrm )
+ { pFrm->_InvalidateSize();
+ pFrm->_InvalidatePrt();
+ pFrm = pFrm->GetNext();
+ }
+ SwCntntFrm *pCnt = ((SwLayoutFrm*)this)->ContainsCntnt();
+ // --> OD 2004-12-20 #i36991# - be save.
+ // E.g., a row can contain *no* content.
+ if ( pCnt )
+ {
+ pCnt->InvalidatePage();
+ do
+ {
+ pCnt->Prepare( PREP_ADJUST_FRM );
+ pCnt->_InvalidateSize();
+ pCnt = pCnt->GetNextCntntFrm();
+ } while ( ((SwLayoutFrm*)this)->IsAnLower( pCnt ) );
+ }
+ // <--
+ }
+ }
+ else if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ {
+ if( IsVertical() )
+ ChgSize( Size( rFmtSize.GetWidth(), Frm().Height()));
+ else
+ ChgSize( Size( Frm().Width(), rFmtSize.GetHeight()));
+ }
+}
+
+/*************************************************************************
+|* SwFrm::ValidateThisAndAllLowers()
+ *
+ * FME 2007-08-30 #i81146# new loop control
+|*************************************************************************/
+void SwFrm::ValidateThisAndAllLowers( const sal_uInt16 nStage )
+{
+ // Stage 0: Only validate frames. Do not process any objects.
+ // Stage 1: Only validate fly frames and all of their contents.
+ // Stage 2: Validate all.
+
+ const bool bOnlyObject = 1 == nStage;
+ const bool bIncludeObjects = 1 <= nStage;
+
+ if ( !bOnlyObject || ISA(SwFlyFrm) )
+ {
+ bValidSize = sal_True;
+ bValidPrtArea = sal_True;
+ bValidPos = sal_True;
+ }
+
+ if ( bIncludeObjects )
+ {
+ const SwSortedObjs* pObjs = GetDrawObjs();
+ if ( pObjs )
+ {
+ const sal_uInt32 nCnt = pObjs->Count();
+ for ( sal_uInt32 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchObj = (*pObjs)[i];
+ if ( pAnchObj->ISA(SwFlyFrm) )
+ static_cast<SwFlyFrm*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
+ else if ( pAnchObj->ISA(SwAnchoredDrawObject) )
+ static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
+ }
+ }
+ }
+
+ if ( IsLayoutFrm() )
+ {
+ SwFrm* pLower = static_cast<SwLayoutFrm*>(this)->Lower();
+ while ( pLower )
+ {
+ pLower->ValidateThisAndAllLowers( nStage );
+ pLower = pLower->GetNext();
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwCntntFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if( nFrmHeight > 0 &&
+ nDist > (LONG_MAX - nFrmHeight ) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
+ {
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ if ( GetNext() )
+ {
+ GetNext()->InvalidatePos();
+ }
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved forward
+ // due to the positioning of its objects ). Thus, invalivate this next frame,
+ // if document compatibility option 'Consider wrapping style influence on
+ // object positioning' is ON.
+ else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ // <--
+ }
+ return 0;
+ }
+
+ SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
+ SwFrm *pFrm = GetUpper()->Lower();
+ while( pFrm && nReal > 0 )
+ { nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+
+ if ( !bTst )
+ {
+ //Cntnts werden immer auf den gewuenschten Wert gebracht.
+ long nOld = (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnSetHeight)( nOld + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical()&& !IsVertLR() && !IsReverse() )
+ Frm().Pos().X() -= nDist;
+ if ( nOld && IsInTab() )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->GetTable()->GetHTMLTableLayout() &&
+ !pTab->IsJoinLocked() &&
+ !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
+ {
+ pTab->InvalidatePos();
+ pTab->SetResizeHTMLTable();
+ }
+ }
+ }
+
+ //Upper nur growen wenn notwendig.
+ if ( nReal < nDist )
+ {
+ if( GetUpper() )
+ {
+ if( bTst || !GetUpper()->IsFooterFrm() )
+ nReal = GetUpper()->Grow( nDist - (nReal > 0 ? nReal : 0),
+ bTst, bInfo );
+ else
+ {
+ nReal = 0;
+ GetUpper()->InvalidateSize();
+ }
+ }
+ else
+ nReal = 0;
+ }
+ else
+ nReal = nDist;
+
+ // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
+ // frame on the next page/column can flow backward (e.g. it was moved forward
+ // due to the positioning of its objects ). Thus, invalivate this next frame,
+ // if document compatibility option 'Consider wrapping style influence on
+ // object positioning' is ON.
+ if ( !bTst )
+ {
+ if ( GetNext() )
+ {
+ GetNext()->InvalidatePos();
+ }
+ else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
+ {
+ InvalidateNextPos();
+ }
+ }
+ // <--
+
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwCntntFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ SWRECTFN( this )
+ OSL_ENSURE( nDist >= 0, "nDist < 0" );
+ OSL_ENSURE( nDist <= (Frm().*fnRect->fnGetHeight)(),
+ "nDist > als aktuelle Grosse." );
+
+ if ( !bTst )
+ {
+ SwTwips nRstHeight;
+ if( GetUpper() )
+ nRstHeight = (Frm().*fnRect->fnBottomDist)
+ ( (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ else
+ nRstHeight = 0;
+ if( nRstHeight < 0 )
+ {
+ SwTwips nNextHeight = 0;
+ if( GetUpper()->IsSctFrm() && nDist > LONG_MAX/2 )
+ {
+ SwFrm *pNxt = GetNext();
+ while( pNxt )
+ {
+ nNextHeight += (pNxt->Frm().*fnRect->fnGetHeight)();
+ pNxt = pNxt->GetNext();
+ }
+ }
+ nRstHeight = nDist + nRstHeight - nNextHeight;
+ }
+ else
+ nRstHeight = nDist;
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() - nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( IsVertical() && !IsVertLR() )
+ Frm().Pos().X() += nDist;
+ nDist = nRstHeight;
+ if ( IsInTab() )
+ {
+ SwTabFrm *pTab = FindTabFrm();
+ if ( pTab->GetTable()->GetHTMLTableLayout() &&
+ !pTab->IsJoinLocked() &&
+ !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
+ {
+ pTab->InvalidatePos();
+ pTab->SetResizeHTMLTable();
+ }
+ }
+ }
+
+ SwTwips nReal;
+ if( GetUpper() && nDist > 0 )
+ {
+ if( bTst || !GetUpper()->IsFooterFrm() )
+ nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
+ else
+ {
+ nReal = 0;
+
+ // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
+ // if there are any objects anchored inside your content, which
+ // overlap with the shrinking frame.
+ // This may lead to a footer frame that is too big, but this is better
+ // than looping.
+ // #109722# : The fix for #108745# was too strict.
+
+ bool bInvalidate = true;
+ const SwRect aRect( Frm() );
+ const SwPageFrm* pPage = FindPageFrm();
+ const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : 0;
+ if( pSorted )
+ {
+ for ( sal_uInt16 i = 0; i < pSorted->Count(); ++i )
+ {
+ const SwAnchoredObject* pAnchoredObj = (*pSorted)[i];
+ const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
+
+ if( aBound.Left() > aRect.Right() )
+ continue;
+
+ if( aBound.IsOver( aRect ) )
+ {
+ const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
+ if( SURROUND_THROUGHT != rFmt.GetSurround().GetSurround() )
+ {
+ const SwFrm* pAnchor = pAnchoredObj->GetAnchorFrm();
+ if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
+ {
+ bInvalidate = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ( bInvalidate )
+ GetUpper()->InvalidateSize();
+ }
+ }
+ else
+ nReal = 0;
+
+ if ( !bTst )
+ {
+ //Die Position des naechsten Frm's veraendert sich auf jeden Fall.
+ InvalidateNextPos();
+
+ //Wenn ich keinen Nachfolger habe, so muss ich mich eben selbst um
+ //die Retusche kuemmern.
+ if ( !GetNext() )
+ SetRetouche();
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwCntntFrm::Modify()
+|*
+|*************************************************************************/
+void SwCntntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
+{
+ sal_uInt8 nInvFlags = 0;
+
+ if( pNew && RES_ATTRSET_CHG == pNew->Which() )
+ {
+ SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
+ SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
+ SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
+ SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
+ while( sal_True )
+ {
+ _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
+ (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
+ &aOldSet, &aNewSet );
+ if( aNIter.IsAtEnd() )
+ break;
+ aNIter.NextItem();
+ aOIter.NextItem();
+ }
+ if ( aOldSet.Count() || aNewSet.Count() )
+ SwFrm::Modify( &aOldSet, &aNewSet );
+ }
+ else
+ _UpdateAttr( pOld, pNew, nInvFlags );
+
+ if ( nInvFlags != 0 )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ InvalidatePage( pPage );
+ if ( nInvFlags & 0x01 )
+ SetCompletePaint();
+ if ( nInvFlags & 0x02 )
+ _InvalidatePos();
+ if ( nInvFlags & 0x04 )
+ _InvalidateSize();
+ if ( nInvFlags & 0x88 )
+ {
+ if( IsInSct() && !GetPrev() )
+ {
+ SwSectionFrm *pSect = FindSctFrm();
+ if( pSect->ContainsAny() == this )
+ {
+ pSect->_InvalidatePrt();
+ pSect->InvalidatePage( pPage );
+ }
+ }
+ _InvalidatePrt();
+ }
+ SwFrm* pNextFrm = GetIndNext();
+ if ( pNextFrm && nInvFlags & 0x10)
+ {
+ pNextFrm->_InvalidatePrt();
+ pNextFrm->InvalidatePage( pPage );
+ }
+ if ( pNextFrm && nInvFlags & 0x80 )
+ {
+ pNextFrm->SetCompletePaint();
+ }
+ if ( nInvFlags & 0x20 )
+ {
+ SwFrm* pPrevFrm = GetPrev();
+ if ( pPrevFrm )
+ {
+ pPrevFrm->_InvalidatePrt();
+ pPrevFrm->InvalidatePage( pPage );
+ }
+ }
+ if ( nInvFlags & 0x40 )
+ InvalidateNextPos();
+ }
+}
+
+void SwCntntFrm::_UpdateAttr( const SfxPoolItem* pOld, const SfxPoolItem* pNew,
+ sal_uInt8 &rInvFlags,
+ SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
+{
+ sal_Bool bClear = sal_True;
+ sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
+ switch ( nWhich )
+ {
+ case RES_FMT_CHG:
+ rInvFlags = 0xFF;
+ /* kein break hier */
+
+ case RES_PAGEDESC: //Attributaenderung (an/aus)
+ if ( IsInDocBody() && !IsInTab() )
+ {
+ rInvFlags |= 0x02;
+ SwPageFrm *pPage = FindPageFrm();
+ if ( !GetPrev() )
+ CheckPageDescs( pPage );
+ if ( pPage && GetAttrSet()->GetPageDesc().GetNumOffset() )
+ ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
+ SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
+ pPage->GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
+ }
+ break;
+
+ case RES_UL_SPACE:
+ {
+ // OD 2004-02-18 #106629# - correction
+ // Invalidation of the printing area of next frame, not only
+ // for footnote content.
+ if ( !GetIndNext() )
+ {
+ SwFrm* pNxt = FindNext();
+ if ( pNxt )
+ {
+ SwPageFrm* pPg = pNxt->FindPageFrm();
+ pNxt->InvalidatePage( pPg );
+ pNxt->_InvalidatePrt();
+ if( pNxt->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->_InvalidatePrt();
+ pCnt->InvalidatePage( pPg );
+ }
+ }
+ pNxt->SetCompletePaint();
+ }
+ }
+ // OD 2004-03-17 #i11860#
+ if ( GetIndNext() &&
+ !GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
+ {
+ // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
+ GetIndNext()->InvalidateObjs( true );
+ }
+ Prepare( PREP_UL_SPACE ); //TxtFrm muss Zeilenabst. korrigieren.
+ rInvFlags |= 0x80;
+ /* kein Break hier */
+ }
+ case RES_LR_SPACE:
+ case RES_BOX:
+ case RES_SHADOW:
+ Prepare( PREP_FIXSIZE_CHG );
+ SwFrm::Modify( pOld, pNew );
+ rInvFlags |= 0x30;
+ break;
+
+ case RES_BREAK:
+ {
+ rInvFlags |= 0x42;
+ const IDocumentSettingAccess* pIDSA = GetUpper()->GetFmt()->getIDocumentSettingAccess();
+ if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
+ pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) )
+ {
+ rInvFlags |= 0x1;
+ SwFrm* pNxt = FindNext();
+ if( pNxt )
+ {
+ SwPageFrm* pPg = pNxt->FindPageFrm();
+ pNxt->InvalidatePage( pPg );
+ pNxt->_InvalidatePrt();
+ if( pNxt->IsSctFrm() )
+ {
+ SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
+ if( pCnt )
+ {
+ pCnt->_InvalidatePrt();
+ pCnt->InvalidatePage( pPg );
+ }
+ }
+ pNxt->SetCompletePaint();
+ }
+ }
+ }
+ break;
+
+ // OD 2004-02-26 #i25029#
+ case RES_PARATR_CONNECT_BORDER:
+ {
+ rInvFlags |= 0x01;
+ if ( IsTxtFrm() )
+ {
+ InvalidateNextPrtArea();
+ }
+ if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
+ {
+ FindTabFrm()->InvalidateSize();
+ }
+ }
+ break;
+
+ case RES_PARATR_TABSTOP:
+ case RES_CHRATR_PROPORTIONALFONTSIZE:
+ case RES_CHRATR_SHADOWED:
+ case RES_CHRATR_AUTOKERN:
+ case RES_CHRATR_UNDERLINE:
+ case RES_CHRATR_OVERLINE:
+ case RES_CHRATR_KERNING:
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_ESCAPEMENT:
+ case RES_CHRATR_CONTOUR:
+ case RES_PARATR_NUMRULE:
+ rInvFlags |= 0x01;
+ break;
+
+
+ case RES_FRM_SIZE:
+ rInvFlags |= 0x01;
+ /* no break here */
+
+ default:
+ bClear = sal_False;
+ }
+ if ( bClear )
+ {
+ if ( pOldSet || pNewSet )
+ {
+ if ( pOldSet )
+ pOldSet->ClearItem( nWhich );
+ if ( pNewSet )
+ pNewSet->ClearItem( nWhich );
+ }
+ else
+ SwFrm::Modify( pOld, pNew );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::SwLayoutFrm()
+|*
+|*************************************************************************/
+SwLayoutFrm::SwLayoutFrm( SwFrmFmt* pFmt, SwFrm* pSib ):
+ SwFrm( pFmt, pSib ),
+ pLower( 0 )
+{
+ const SwFmtFrmSize &rFmtSize = pFmt->GetFrmSize();
+ if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
+ bFixSize = sal_True;
+}
+
+// --> OD 2004-06-29 #i28701#
+TYPEINIT1(SwLayoutFrm,SwFrm);
+// <--
+/*--------------------------------------------------
+ * SwLayoutFrm::InnerHeight()
+ * --------------------------------------------------*/
+
+SwTwips SwLayoutFrm::InnerHeight() const
+{
+ if( !Lower() )
+ return 0;
+ SwTwips nRet = 0;
+ const SwFrm* pCnt = Lower();
+ SWRECTFN( this )
+ if( pCnt->IsColumnFrm() || pCnt->IsCellFrm() )
+ {
+ do
+ {
+ SwTwips nTmp = ((SwLayoutFrm*)pCnt)->InnerHeight();
+ if( pCnt->GetValidPrtAreaFlag() )
+ nTmp += (pCnt->Frm().*fnRect->fnGetHeight)() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ if( nRet < nTmp )
+ nRet = nTmp;
+ pCnt = pCnt->GetNext();
+ } while ( pCnt );
+ }
+ else
+ {
+ do
+ {
+ nRet += (pCnt->Frm().*fnRect->fnGetHeight)();
+ if( pCnt->IsCntntFrm() && ((SwTxtFrm*)pCnt)->IsUndersized() )
+ nRet += ((SwTxtFrm*)pCnt)->GetParHeight() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ if( pCnt->IsLayoutFrm() && !pCnt->IsTabFrm() )
+ nRet += ((SwLayoutFrm*)pCnt)->InnerHeight() -
+ (pCnt->Prt().*fnRect->fnGetHeight)();
+ pCnt = pCnt->GetNext();
+ } while( pCnt );
+
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::GrowFrm()
+|*
+|*************************************************************************/
+SwTwips SwLayoutFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetType() & nTmpType) && HasFixSize() )
+ return 0;
+
+ SWRECTFN( this )
+ const SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ const SwTwips nFrmPos = Frm().Pos().X();
+
+ if ( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
+ nDist = LONG_MAX - nFrmHeight;
+
+ SwTwips nMin = 0;
+ if ( GetUpper() && !IsCellFrm() )
+ {
+ SwFrm *pFrm = GetUpper()->Lower();
+ while( pFrm )
+ { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ nMin = (GetUpper()->Prt().*fnRect->fnGetHeight)() - nMin;
+ if ( nMin < 0 )
+ nMin = 0;
+ }
+
+ SwRect aOldFrm( Frm() );
+ sal_Bool bMoveAccFrm = sal_False;
+
+ sal_Bool bChgPos = IsVertical() && !IsReverse();
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() -= nDist;
+ bMoveAccFrm = sal_True;
+ }
+
+ SwTwips nReal = nDist - nMin;
+ if ( nReal > 0 )
+ {
+ if ( GetUpper() )
+ { // AdjustNeighbourhood jetzt auch in Spalten (aber nicht in Rahmen)
+ sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+ if( NA_ONLY_ADJUST == nAdjust )
+ nReal = AdjustNeighbourhood( nReal, bTst );
+ else
+ {
+ if( NA_ADJUST_GROW == nAdjust )
+ nReal += AdjustNeighbourhood( nReal, bTst );
+
+ SwTwips nGrow = 0;
+ if( 0 < nReal )
+ {
+ SwFrm* pToGrow = GetUpper();
+ // NEW TABLES
+ // A cell with a row span of > 1 is allowed to grow the
+ // line containing the end of the row span if it is
+ // located in the same table frame:
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
+ {
+ SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
+ if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
+ pToGrow = rEndCell.GetUpper();
+ else
+ pToGrow = 0;
+ }
+
+ nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
+ }
+
+ if( NA_GROW_ADJUST == nAdjust && nGrow < nReal )
+ nReal += AdjustNeighbourhood( nReal - nGrow, bTst );
+
+ if ( IsFtnFrm() && (nGrow != nReal) && GetNext() )
+ {
+ //Fussnoten koennen ihre Nachfolger verdraengen.
+ SwTwips nSpace = bTst ? 0 : -nDist;
+ const SwFrm *pFrm = GetUpper()->Lower();
+ do
+ { nSpace += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ } while ( pFrm != GetNext() );
+ nSpace = (GetUpper()->Prt().*fnRect->fnGetHeight)() -nSpace;
+ if ( nSpace < 0 )
+ nSpace = 0;
+ nSpace += nGrow;
+ if ( nReal > nSpace )
+ nReal = nSpace;
+ if ( nReal && !bTst )
+ ((SwFtnFrm*)this)->InvalidateNxtFtnCnts( FindPageFrm() );
+ }
+ else
+ nReal = nGrow;
+ }
+ }
+ else
+ nReal = 0;
+
+ nReal += nMin;
+ }
+ else
+ nReal = nDist;
+
+ if ( !bTst )
+ {
+ if( nReal != nDist &&
+ // NEW TABLES
+ ( !IsCellFrm() || static_cast<SwCellFrm*>(this)->GetLayoutRowSpan() > 1 ) )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight + nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() = nFrmPos - nReal;
+ bMoveAccFrm = sal_True;
+ }
+
+ if ( nReal )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ }
+ if ( !IsPageBodyFrm() )
+ {
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ }
+ if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ NotifyLowerObjs();
+
+ if( IsCellFrm() )
+ InvaPercentLowers( nReal );
+
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+ }
+
+ if( bMoveAccFrm && IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ return nReal;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::ShrinkFrm()
+|*
+|*************************************************************************/
+SwTwips SwLayoutFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
+{
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
+ const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
+ if( !(GetType() & nTmpType) && HasFixSize() )
+ return 0;
+
+ OSL_ENSURE( nDist >= 0, "nDist < 0" );
+ SWRECTFN( this )
+ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nDist > nFrmHeight )
+ nDist = nFrmHeight;
+
+ SwTwips nMin = 0;
+ sal_Bool bChgPos = IsVertical() && !IsReverse();
+ if ( Lower() )
+ {
+ if( !Lower()->IsNeighbourFrm() )
+ { const SwFrm *pFrm = Lower();
+ const long nTmp = (Prt().*fnRect->fnGetHeight)();
+ while( pFrm && nMin < nTmp )
+ { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
+ pFrm = pFrm->GetNext();
+ }
+ }
+ }
+ SwTwips nReal = nDist;
+ SwTwips nMinDiff = (Prt().*fnRect->fnGetHeight)() - nMin;
+ if( nReal > nMinDiff )
+ nReal = nMinDiff;
+ if( nReal <= 0 )
+ return nDist;
+
+ SwRect aOldFrm( Frm() );
+ sal_Bool bMoveAccFrm = sal_False;
+
+ SwTwips nRealDist = nReal;
+ if ( !bTst )
+ {
+ (Frm().*fnRect->fnSetHeight)( nFrmHeight - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nReal;
+ bMoveAccFrm = sal_True;
+ }
+
+ sal_uInt8 nAdjust = GetUpper() && GetUpper()->IsFtnBossFrm() ?
+ ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
+ : NA_GROW_SHRINK;
+
+ // AdjustNeighbourhood auch in Spalten (aber nicht in Rahmen)
+ if( NA_ONLY_ADJUST == nAdjust )
+ {
+ if ( IsPageBodyFrm() && !bBrowse )
+ nReal = nDist;
+ else
+ { nReal = AdjustNeighbourhood( -nReal, bTst );
+ nReal *= -1;
+ if ( !bTst && IsBodyFrm() && nReal < nRealDist )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
+ + nRealDist - nReal );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nRealDist - nReal;
+ OSL_ENSURE( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
+ }
+ }
+ }
+ else if( IsColumnFrm() || IsColBodyFrm() )
+ {
+ SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
+ if ( nTmp != nReal )
+ {
+ (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
+ + nReal - nTmp );
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ if( bChgPos && !IsVertLR() )
+ Frm().Pos().X() += nTmp - nReal;
+ OSL_ENSURE( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
+ nReal = nTmp;
+ }
+ }
+ else
+ {
+ SwTwips nShrink = nReal;
+ SwFrm* pToShrink = GetUpper();
+ const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
+ // NEW TABLES
+ if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
+ {
+ SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
+ pToShrink = rEndCell.GetUpper();
+ }
+
+ nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
+ if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
+ && nReal < nShrink )
+ AdjustNeighbourhood( nReal - nShrink );
+ }
+
+ if( bMoveAccFrm && IsAccessibleFrm() )
+ {
+ SwRootFrm *pRootFrm = getRootFrm();
+ if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
+ pRootFrm->GetCurrShell() )
+ {
+ pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
+ }
+ }
+ if ( !bTst && (IsCellFrm() || IsColumnFrm() ? nReal : nRealDist) )
+ {
+ SwPageFrm *pPage = FindPageFrm();
+ if ( GetNext() )
+ {
+ GetNext()->_InvalidatePos();
+ if ( GetNext()->IsCntntFrm() )
+ GetNext()->InvalidatePage( pPage );
+ if ( IsTabFrm() )
+ ((SwTabFrm*)this)->SetComplete();
+ }
+ else
+ { if ( IsRetoucheFrm() )
+ SetRetouche();
+ if ( IsTabFrm() )
+ {
+ if( IsTabFrm() )
+ ((SwTabFrm*)this)->SetComplete();
+ if ( Lower() ) //Kann auch im Join stehen und leer sein!
+ InvalidateNextPos();
+ }
+ }
+ if ( !IsBodyFrm() )
+ {
+ _InvalidateAll();
+ InvalidatePage( pPage );
+ const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
+ if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
+ SetCompletePaint();
+ }
+
+ if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
+ NotifyLowerObjs();
+
+ if( IsCellFrm() )
+ InvaPercentLowers( nReal );
+
+ SwCntntFrm *pCnt;
+ if( IsFtnFrm() && !((SwFtnFrm*)this)->GetAttr()->GetFtn().IsEndNote() &&
+ ( GetFmt()->GetDoc()->GetFtnInfo().ePos != FTNPOS_CHAPTER ||
+ ( IsInSct() && FindSctFrm()->IsFtnAtEnd() ) ) &&
+ 0 != (pCnt = ((SwFtnFrm*)this)->GetRefFromAttr() ) )
+ {
+ if ( pCnt->IsFollow() )
+ { // Wenn wir sowieso schon in einer anderen Spalte/Seite sitzen
+ // als der Frame mit der Referenz, dann brauchen wir nicht
+ // auch noch seinen Master zu invalidieren.
+ SwFrm *pTmp = pCnt->FindFtnBossFrm(sal_True) == FindFtnBossFrm(sal_True)
+ ? pCnt->FindMaster()->GetFrm() : pCnt;
+ pTmp->Prepare( PREP_ADJUST_FRM );
+ pTmp->InvalidateSize();
+ }
+ else
+ pCnt->InvalidatePos();
+ }
+ }
+ return nReal;
+}
+/*************************************************************************
+|*
+|* SwLayoutFrm::ChgLowersProp()
+|*
+|* Beschreibung Aendert die Grosse der direkt untergeordneten Frm's
+|* die eine Fixe Groesse haben, proportional zur Groessenaenderung der
+|* PrtArea des Frm's.
+|* Die Variablen Frm's werden auch proportional angepasst; sie werden
+|* sich schon wieder zurechtwachsen/-schrumpfen.
+|*
+|*************************************************************************/
+void SwLayoutFrm::ChgLowersProp( const Size& rOldSize )
+{
+ // no change of lower properties for root frame or if no lower exists.
+ if ( IsRootFrm() || !Lower() )
+ return;
+
+ // declare and init <SwFrm* pLowerFrm> with first lower
+ SwFrm *pLowerFrm = Lower();
+
+ // declare and init const booleans <bHeightChgd> and <bWidthChg>
+ const bool bHeightChgd = rOldSize.Height() != Prt().Height();
+ const bool bWidthChgd = rOldSize.Width() != Prt().Width();
+
+ // declare and init variables <bVert>, <bRev> and <fnRect>
+ SWRECTFN( this )
+
+ // This shortcut basically tries to handle only lower frames that
+ // are affected by the size change. Otherwise much more lower frames
+ // are invalidated.
+ if ( !( bVert ? bHeightChgd : bWidthChgd ) &&
+ ! Lower()->IsColumnFrm() &&
+ ( ( IsBodyFrm() && IsInDocBody() && ( !IsInSct() || !FindSctFrm()->IsColLocked() ) ) ||
+ // --> FME 2004-07-21 #i10826# Section frames without columns should not
+ // invalidate all lowers!
+ IsSctFrm() ) )
+ // <--
+ {
+ // Determine page frame the body frame resp. the section frame belongs to.
+ SwPageFrm *pPage = FindPageFrm();
+ // Determine last lower by traveling through them using <GetNext()>.
+ // During travel check each section frame, if it will be sized to
+ // maximum. If Yes, invalidate size of section frame and set
+ // corresponding flags at the page.
+ do
+ {
+ if( pLowerFrm->IsSctFrm() &&((SwSectionFrm*)pLowerFrm)->_ToMaximize() )
+ {
+ pLowerFrm->_InvalidateSize();
+ pLowerFrm->InvalidatePage( pPage );
+ }
+ if( pLowerFrm->GetNext() )
+ pLowerFrm = pLowerFrm->GetNext();
+ else
+ break;
+ } while( sal_True );
+ // If found last lower is a section frame containing no section
+ // (section frame isn't valid and will be deleted in the future),
+ // travel backwards.
+ while( pLowerFrm->IsSctFrm() && !((SwSectionFrm*)pLowerFrm)->GetSection() &&
+ pLowerFrm->GetPrev() )
+ pLowerFrm = pLowerFrm->GetPrev();
+ // If found last lower is a section frame, set <pLowerFrm> to its last
+ // content, if the section frame is valid and is not sized to maximum.
+ // Otherwise set <pLowerFrm> to NULL - In this case body frame only
+ // contains invalid section frames.
+ if( pLowerFrm->IsSctFrm() )
+ pLowerFrm = ((SwSectionFrm*)pLowerFrm)->GetSection() &&
+ !((SwSectionFrm*)pLowerFrm)->ToMaximize( sal_False ) ?
+ ((SwSectionFrm*)pLowerFrm)->FindLastCntnt() : NULL;
+
+ // continue with found last lower, probably the last content of a section
+ if ( pLowerFrm )
+ {
+ // If <pLowerFrm> is in a table frame, set <pLowerFrm> to this table
+ // frame and continue.
+ if ( pLowerFrm->IsInTab() )
+ {
+ // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrm> to
+ // its table frame - check, if the table frame is also a lower
+ // of the body frame, in order to assure that <pLowerFrm> is not
+ // set to a frame, which is an *upper* of the body frame.
+ SwFrm* pTableFrm = pLowerFrm->FindTabFrm();
+ if ( IsAnLower( pTableFrm ) )
+ {
+ pLowerFrm = pTableFrm;
+ }
+ }
+ // Check, if variable size of body frame resp. section frame has grown
+ // OD 28.10.2002 #97265# - correct check, if variable size has grown.
+ SwTwips nOldHeight = bVert ? rOldSize.Width() : rOldSize.Height();
+ if( nOldHeight < (Prt().*fnRect->fnGetHeight)() )
+ {
+ // If variable size of body|section frame has grown, only found
+ // last lower and the position of the its next have to be invalidated.
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ if( !pLowerFrm->IsFlowFrm() ||
+ !SwFlowFrm::CastFlowFrm( pLowerFrm )->HasFollow() )
+ pLowerFrm->InvalidateNextPos( sal_True );
+ if ( pLowerFrm->IsTxtFrm() )
+ ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ else
+ {
+ // variable size of body|section frame has shrinked. Thus,
+ // invalidate all lowers not matching the new body|section size
+ // and the dedicated new last lower.
+ if( bVert )
+ {
+ SwTwips nBot = Frm().Left() + Prt().Left();
+ while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Left() < nBot )
+ {
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ pLowerFrm = pLowerFrm->GetPrev();
+ }
+ }
+ else
+ {
+ SwTwips nBot = Frm().Top() + Prt().Bottom();
+ while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Top() > nBot )
+ {
+ pLowerFrm->_InvalidateAll();
+ pLowerFrm->InvalidatePage( pPage );
+ pLowerFrm = pLowerFrm->GetPrev();
+ }
+ }
+ if ( pLowerFrm )
+ {
+ pLowerFrm->_InvalidateSize();
+ pLowerFrm->InvalidatePage( pPage );
+ if ( pLowerFrm->IsTxtFrm() )
+ ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ }
+ // --> OD 2005-01-31 #i41694# - improvement by removing duplicates
+ if ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsInSct() )
+ {
+ // --> OD 2005-01-31 #i41694# - follow-up of issue #i10826#:
+ // No invalidation of section frame, if it's the this.
+ SwFrm* pSectFrm = pLowerFrm->FindSctFrm();
+ if( pSectFrm != this && IsAnLower( pSectFrm ) )
+ {
+ pSectFrm->_InvalidateSize();
+ pSectFrm->InvalidatePage( pPage );
+ }
+ // <--
+ }
+ }
+ // <--
+ }
+ return;
+ } // end of { special case }
+
+
+ // Invalidate page for content only once.
+ bool bInvaPageForCntnt = true;
+
+ // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
+ // adjustment, if fixed/variable size has changed.
+ bool bFixChgd, bVarChgd;
+ if( bVert == pLowerFrm->IsNeighbourFrm() )
+ {
+ bFixChgd = bWidthChgd;
+ bVarChgd = bHeightChgd;
+ }
+ else
+ {
+ bFixChgd = bHeightChgd;
+ bVarChgd = bWidthChgd;
+ }
+
+ // Declare const unsigned short <nFixWidth> and init it this frame types
+ // which has fixed width in vertical respectively horizontal layout.
+ // In vertical layout these are neighbour frames (cell and column frames),
+ // header frames and footer frames.
+ // In horizontal layout these are all frames, which aren't neighbour frames.
+ const sal_uInt16 nFixWidth = bVert ? (FRM_NEIGHBOUR | FRM_HEADFOOT)
+ : ~FRM_NEIGHBOUR;
+
+ // Declare const unsigned short <nFixHeight> and init it this frame types
+ // which has fixed height in vertical respectively horizontal layout.
+ // In vertical layout these are all frames, which aren't neighbour frames,
+ // header frames, footer frames, body frames or foot note container frames.
+ // In horizontal layout these are neighbour frames.
+ const sal_uInt16 nFixHeight= bVert ? ~(FRM_NEIGHBOUR | FRM_HEADFOOT | FRM_BODYFTNC)
+ : FRM_NEIGHBOUR;
+
+ // Travel through all lowers using <GetNext()>
+ while ( pLowerFrm )
+ {
+ if ( pLowerFrm->IsTxtFrm() )
+ {
+ // Text frames will only be invalidated - prepare invalidation
+ if ( bFixChgd )
+ static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_FIXSIZE_CHG );
+ if ( bVarChgd )
+ static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_ADJUST_FRM );
+ }
+ else
+ {
+ // If lower isn't a table, row, cell or section frame, adjust its
+ // frame size.
+ const sal_uInt16 nLowerType = pLowerFrm->GetType();
+ if ( !(nLowerType & (FRM_TAB|FRM_ROW|FRM_CELL|FRM_SECTION)) )
+ {
+ if ( bWidthChgd )
+ {
+ if( nLowerType & nFixWidth )
+ {
+ // Considering previous conditions:
+ // In vertical layout set width of column, header and
+ // footer frames to its upper width.
+ // In horizontal layout set width of header, footer,
+ // foot note container, foot note, body and no-text
+ // frames to its upper width.
+ pLowerFrm->Frm().Width( Prt().Width() );
+ }
+ else if( rOldSize.Width() && !pLowerFrm->IsFtnFrm() )
+ {
+ // Adjust frame width proportional, if lower isn't a
+ // foot note frame and condition <nLowerType & nFixWidth>
+ // isn't true.
+ // Considering previous conditions:
+ // In vertical layout these are foot note container,
+ // body and no-text frames.
+ // In horizontal layout these are column and no-text frames.
+ // OD 24.10.2002 #97265# - <double> calculation
+ // Perform <double> calculation of new width, if
+ // one of the coefficients is greater than 50000
+ SwTwips nNewWidth;
+ if ( (pLowerFrm->Frm().Width() > 50000) ||
+ (Prt().Width() > 50000) )
+ {
+ double nNewWidthTmp =
+ ( double(pLowerFrm->Frm().Width())
+ * double(Prt().Width()) )
+ / double(rOldSize.Width());
+ nNewWidth = SwTwips(nNewWidthTmp);
+ }
+ else
+ {
+ nNewWidth =
+ (pLowerFrm->Frm().Width() * Prt().Width()) / rOldSize.Width();
+ }
+ pLowerFrm->Frm().Width( nNewWidth );
+ }
+ }
+ if ( bHeightChgd )
+ {
+ if( nLowerType & nFixHeight )
+ {
+ // Considering previous conditions:
+ // In vertical layout set height of foot note and
+ // no-text frames to its upper height.
+ // In horizontal layout set height of column frames
+ // to its upper height.
+ pLowerFrm->Frm().Height( Prt().Height() );
+ }
+ // OD 01.10.2002 #102211#
+ // add conditions <!pLowerFrm->IsHeaderFrm()> and
+ // <!pLowerFrm->IsFooterFrm()> in order to avoid that
+ // the <Grow> of header or footer are overwritten.
+ // NOTE: Height of header/footer frame is determined by contents.
+ else if ( rOldSize.Height() &&
+ !pLowerFrm->IsFtnFrm() &&
+ !pLowerFrm->IsHeaderFrm() &&
+ !pLowerFrm->IsFooterFrm()
+ )
+ {
+ // Adjust frame height proportional, if lower isn't a
+ // foot note, a header or a footer frame and
+ // condition <nLowerType & nFixHeight> isn't true.
+ // Considering previous conditions:
+ // In vertical layout these are column, foot note container,
+ // body and no-text frames.
+ // In horizontal layout these are column, foot note
+ // container, body and no-text frames.
+
+ // OD 29.10.2002 #97265# - special case for page lowers
+ // The page lowers that have to be adjusted on page height
+ // change are the body frame and the foot note container
+ // frame.
+ // In vertical layout the height of both is directly
+ // adjusted to the page height change.
+ // In horizontal layout the height of the body frame is
+ // directly adjsuted to the page height change and the
+ // foot note frame height isn't touched, because its
+ // determined by its content.
+ // OD 31.03.2003 #108446# - apply special case for page
+ // lowers - see description above - also for section columns.
+ if ( IsPageFrm() ||
+ ( IsColumnFrm() && IsInSct() )
+ )
+ {
+ OSL_ENSURE( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm(),
+ "ChgLowersProp - only for body or foot note container" );
+ if ( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm() )
+ {
+ if ( IsVertical() || pLowerFrm->IsBodyFrm() )
+ {
+ SwTwips nNewHeight =
+ pLowerFrm->Frm().Height() +
+ ( Prt().Height() - rOldSize.Height() );
+ if ( nNewHeight < 0)
+ {
+ // OD 01.04.2003 #108446# - adjust assertion condition and text
+ OSL_ENSURE( !( IsPageFrm() &&
+ (pLowerFrm->Frm().Height()>0) &&
+ (pLowerFrm->IsValid()) ),
+ "ChgLowersProg - negative height for lower.");
+ nNewHeight = 0;
+ }
+ pLowerFrm->Frm().Height( nNewHeight );
+ }
+ }
+ }
+ else
+ {
+ SwTwips nNewHeight;
+ // OD 24.10.2002 #97265# - <double> calculation
+ // Perform <double> calculation of new height, if
+ // one of the coefficients is greater than 50000
+ if ( (pLowerFrm->Frm().Height() > 50000) ||
+ (Prt().Height() > 50000) )
+ {
+ double nNewHeightTmp =
+ ( double(pLowerFrm->Frm().Height())
+ * double(Prt().Height()) )
+ / double(rOldSize.Height());
+ nNewHeight = SwTwips(nNewHeightTmp);
+ }
+ else
+ {
+ nNewHeight = ( pLowerFrm->Frm().Height()
+ * Prt().Height() ) / rOldSize.Height();
+ }
+ if( !pLowerFrm->GetNext() )
+ {
+ SwTwips nSum = Prt().Height();
+ SwFrm* pTmp = Lower();
+ while( pTmp->GetNext() )
+ {
+ if( !pTmp->IsFtnContFrm() || !pTmp->IsVertical() )
+ nSum -= pTmp->Frm().Height();
+ pTmp = pTmp->GetNext();
+ }
+ if( nSum - nNewHeight == 1 &&
+ nSum == pLowerFrm->Frm().Height() )
+ nNewHeight = nSum;
+ }
+ pLowerFrm->Frm().Height( nNewHeight );
+ }
+ }
+ }
+ }
+ } // end of else { NOT text frame }
+
+ pLowerFrm->_InvalidateAll();
+ if ( bInvaPageForCntnt && pLowerFrm->IsCntntFrm() )
+ {
+ pLowerFrm->InvalidatePage();
+ bInvaPageForCntnt = false;
+ }
+
+ if ( !pLowerFrm->GetNext() && pLowerFrm->IsRetoucheFrm() )
+ {
+ //Wenn ein Wachstum stattgefunden hat, und die untergeordneten
+ //zur Retouche faehig sind (derzeit Tab, Section und Cntnt), so
+ //trigger ich sie an.
+ if ( rOldSize.Height() < Prt().SSize().Height() ||
+ rOldSize.Width() < Prt().SSize().Width() )
+ pLowerFrm->SetRetouche();
+ }
+ pLowerFrm = pLowerFrm->GetNext();
+ }
+
+ // Finally adjust the columns if width is set to auto
+ // Possible optimisation: execute this code earlier in this function and
+ // return???
+ if ( ( (bVert && bHeightChgd) || (! bVert && bWidthChgd) ) &&
+ Lower()->IsColumnFrm() )
+ {
+ // get column attribute
+ const SwFmtCol* pColAttr = NULL;
+ if ( IsPageBodyFrm() )
+ {
+ OSL_ENSURE( GetUpper()->IsPageFrm(), "Upper is not page frame" );
+ pColAttr = &GetUpper()->GetFmt()->GetCol();
+ }
+ else
+ {
+ OSL_ENSURE( IsFlyFrm() || IsSctFrm(), "Columns not in fly or section" );
+ pColAttr = &GetFmt()->GetCol();
+ }
+
+ if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
+ AdjustColumns( pColAttr, sal_False );
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::Format()
+|*
+|* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
+|* Die Fixsize wird hier nicht eingestellt.
+|*
+|*************************************************************************/
+void SwLayoutFrm::Format( const SwBorderAttrs *pAttrs )
+{
+ OSL_ENSURE( pAttrs, "LayoutFrm::Format, pAttrs ist 0." );
+
+ if ( bValidPrtArea && bValidSize )
+ return;
+
+ const sal_uInt16 nLeft = (sal_uInt16)pAttrs->CalcLeft( this );
+ const sal_uInt16 nUpper = pAttrs->CalcTop();
+
+ const sal_uInt16 nRight = (sal_uInt16)((SwBorderAttrs*)pAttrs)->CalcRight( this );
+ const sal_uInt16 nLower = pAttrs->CalcBottom();
+ sal_Bool bVert = IsVertical() && !IsPageFrm();
+ //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
+ if ( !bValidPrtArea )
+ {
+ bValidPrtArea = sal_True;
+ (this->*fnRect->fnSetXMargins)( nLeft, nRight );
+ (this->*fnRect->fnSetYMargins)( nUpper, nLower );
+ }
+
+ if ( !bValidSize )
+ {
+ if ( !HasFixSize() )
+ {
+ const SwTwips nBorder = nUpper + nLower;
+ const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
+ SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? rSz.GetHeight() : 0;
+ do
+ { bValidSize = sal_True;
+
+ //Die Groesse in der VarSize wird durch den Inhalt plus den
+ //Raendern bestimmt.
+ SwTwips nRemaining = 0;
+ SwFrm *pFrm = Lower();
+ while ( pFrm )
+ { nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
+ if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
+ // Dieser TxtFrm waere gern ein bisschen groesser
+ nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
+ - (pFrm->Prt().*fnRect->fnGetHeight)();
+ else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
+ nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
+ pFrm = pFrm->GetNext();
+ }
+ nRemaining += nBorder;
+ nRemaining = Max( nRemaining, nMinHeight );
+ const SwTwips nDiff = nRemaining-(Frm().*fnRect->fnGetHeight)();
+ const long nOldLeft = (Frm().*fnRect->fnGetLeft)();
+ const long nOldTop = (Frm().*fnRect->fnGetTop)();
+ if ( nDiff )
+ {
+ if ( nDiff > 0 )
+ Grow( nDiff );
+ else
+ Shrink( -nDiff );
+ //Schnell auf dem kurzen Dienstweg die Position updaten.
+ MakePos();
+ }
+ //Unterkante des Uppers nicht ueberschreiten.
+ if ( GetUpper() && (Frm().*fnRect->fnGetHeight)() )
+ {
+ const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
+ if( (this->*fnRect->fnSetLimit)( nLimit ) &&
+ nOldLeft == (Frm().*fnRect->fnGetLeft)() &&
+ nOldTop == (Frm().*fnRect->fnGetTop)() )
+ bValidSize = bValidPrtArea = sal_True;
+ }
+ } while ( !bValidSize );
+ }
+ else if ( GetType() & 0x0018 )
+ {
+ do
+ { if ( Frm().Height() != pAttrs->GetSize().Height() )
+ ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
+ bValidSize = sal_True;
+ MakePos();
+ } while ( !bValidSize );
+ }
+ else
+ bValidSize = sal_True;
+ }
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::InvalidatePercentLowers()
+|*
+|*************************************************************************/
+static void InvaPercentFlys( SwFrm *pFrm, SwTwips nDiff )
+{
+ OSL_ENSURE( pFrm->GetDrawObjs(), "Can't find any Objects" );
+ for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ const SwFmtFrmSize &rSz = pFly->GetFmt()->GetFrmSize();
+ if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
+ {
+ sal_Bool bNotify = sal_True;
+ // If we've a fly with more than 90% relative height...
+ if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrm() &&
+ rSz.GetHeightPercent() != 0xFF && nDiff )
+ {
+ const SwFrm *pRel = pFly->IsFlyLayFrm() ? pFly->GetAnchorFrm():
+ pFly->GetAnchorFrm()->GetUpper();
+ // ... and we have already more than 90% height and we
+ // not allow the text to go through...
+ // then a notifycation could cause an endless loop, e.g.
+ // 100% height and no text wrap inside a cell of a table.
+ if( pFly->Frm().Height()*10 >
+ ( nDiff + pRel->Prt().Height() )*9 &&
+ pFly->GetFmt()->GetSurround().GetSurround() !=
+ SURROUND_THROUGHT )
+ bNotify = sal_False;
+ }
+ if( bNotify )
+ pFly->InvalidateSize();
+ }
+ }
+ }
+}
+
+void SwLayoutFrm::InvaPercentLowers( SwTwips nDiff )
+{
+ if ( GetDrawObjs() )
+ ::InvaPercentFlys( this, nDiff );
+
+ SwFrm *pFrm = ContainsCntnt();
+ if ( pFrm )
+ do
+ {
+ if ( pFrm->IsInTab() && !IsTabFrm() )
+ {
+ SwFrm *pTmp = pFrm->FindTabFrm();
+ OSL_ENSURE( pTmp, "Where's my TabFrm?" );
+ if( IsAnLower( pTmp ) )
+ pFrm = pTmp;
+ }
+
+ if ( pFrm->IsTabFrm() )
+ {
+ const SwFmtFrmSize &rSz = ((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize();
+ if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
+ pFrm->InvalidatePrt();
+ }
+ else if ( pFrm->GetDrawObjs() )
+ ::InvaPercentFlys( pFrm, nDiff );
+ pFrm = pFrm->FindNextCnt();
+ } while ( pFrm && IsAnLower( pFrm ) ) ;
+}
+
+/*************************************************************************
+|*
+|* SwLayoutFrm::CalcRel()
+|*
+|*************************************************************************/
+long SwLayoutFrm::CalcRel( const SwFmtFrmSize &rSz, sal_Bool ) const
+{
+ long nRet = rSz.GetWidth(),
+ nPercent = rSz.GetWidthPercent();
+
+ if ( nPercent )
+ {
+ const SwFrm *pRel = GetUpper();
+ long nRel = LONG_MAX;
+ const ViewShell *pSh = getRootFrm()->GetCurrShell();
+ const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
+ if( pRel->IsPageBodyFrm() && pSh && bBrowseMode && pSh->VisArea().Width() )
+ {
+ nRel = pSh->GetBrowseWidth();
+ long nDiff = nRel - pRel->Prt().Width();
+ if ( nDiff > 0 )
+ nRel -= nDiff;
+ }
+ nRel = Min( nRel, pRel->Prt().Width() );
+ nRet = nRel * nPercent / 100;
+ }
+ return nRet;
+}
+
+/*************************************************************************
+|* Local helpers for SwLayoutFrm::FormatWidthCols()
+|*************************************************************************/
+long MA_FASTCALL lcl_CalcMinColDiff( SwLayoutFrm *pLayFrm )
+{
+ long nDiff = 0, nFirstDiff = 0;
+ SwLayoutFrm *pCol = (SwLayoutFrm*)pLayFrm->Lower();
+ OSL_ENSURE( pCol, "Where's the columnframe?" );
+ SwFrm *pFrm = pCol->Lower();
+ do
+ {
+ if( pFrm && pFrm->IsBodyFrm() )
+ pFrm = ((SwBodyFrm*)pFrm)->Lower();
+ if ( pFrm && pFrm->IsTxtFrm() )
+ {
+ const long nTmp = ((SwTxtFrm*)pFrm)->FirstLineHeight();
+ if ( nTmp != USHRT_MAX )
+ {
+ if ( pCol == pLayFrm->Lower() )
+ nFirstDiff = nTmp;
+ else
+ nDiff = nDiff ? Min( nDiff, nTmp ) : nTmp;
+ }
+ }
+ //Leere Spalten ueberspringen!
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ while ( pCol && 0 == (pFrm = pCol->Lower()) )
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+
+ } while ( pFrm && pCol );
+
+ return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
+}
+
+sal_Bool lcl_IsFlyHeightClipped( SwLayoutFrm *pLay )
+{
+ SwFrm *pFrm = pLay->ContainsCntnt();
+ while ( pFrm )
+ {
+ if ( pFrm->IsInTab() )
+ pFrm = pFrm->FindTabFrm();
+
+ if ( pFrm->GetDrawObjs() )
+ {
+ sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
+ for ( sal_uInt16 i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsHeightClipped() &&
+ ( !pFly->IsFlyFreeFrm() || pFly->GetPageFrm() ) )
+ return sal_True;
+ }
+ }
+ }
+ pFrm = pFrm->FindNextCnt();
+ }
+ return sal_False;
+}
+
+/*************************************************************************
+|* SwLayoutFrm::FormatWidthCols()
+|*************************************************************************/
+void SwLayoutFrm::FormatWidthCols( const SwBorderAttrs &rAttrs,
+ const SwTwips nBorder, const SwTwips nMinHeight )
+{
+ //Wenn Spalten im Spiel sind, so wird die Groesse an der
+ //letzten Spalte ausgerichtet.
+ //1. Inhalt formatieren.
+ //2. Hoehe der letzten Spalte ermitteln, wenn diese zu
+ // zu gross ist muss der Fly wachsen.
+ // Der Betrag um den der Fly waechst ist aber nicht etwa
+ // der Betrag des Ueberhangs, denn wir muessen davon
+ // ausgehen, dass etwas Masse zurueckfliesst und so
+ // zusaetzlicher Platz geschaffen wird.
+ // Im Ersten Ansatz ist der Betrag um den gewachsen wird
+ // der Ueberhang geteilt durch die Spaltenanzahl oder
+ // der Ueberhang selbst wenn er kleiner als die Spalten-
+ // anzahl ist.
+ //3. Weiter mit 1. bis zur Stabilitaet.
+
+ const SwFmtCol &rCol = rAttrs.GetAttrSet().GetCol();
+ const sal_uInt16 nNumCols = rCol.GetNumCols();
+
+ sal_Bool bEnd = sal_False;
+ sal_Bool bBackLock = sal_False;
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ SwViewImp *pImp = pSh ? pSh->Imp() : 0;
+ {
+ // Zugrunde liegender Algorithmus
+ // Es wird versucht, eine optimale Hoehe fuer die Spalten zu finden.
+ // nMinimum beginnt mit der uebergebenen Mindesthoehe und wird dann als
+ // Maximum der Hoehen gepflegt, bei denen noch Spalteninhalt aus einer
+ // Spalte herausragt.
+ // nMaximum beginnt bei LONG_MAX und wird als Minimum der Hoehen gepflegt,
+ // bei denen der Inhalt gepasst hat.
+ // Bei spaltigen Bereichen beginnt nMaximum bei dem maximalen Wert, den
+ // die Umgebung vorgibt, dies kann natuerlich ein Wert sein, bei dem noch
+ // Inhalt heraushaengt.
+ // Es werden die Spalten formatiert, wenn Inhalt heraushaengt, wird nMinimum
+ // ggf. angepasst, dann wird gewachsen, mindestens um nMinDiff, aber nicht ueber
+ // ein groesseres nMaximum hinaus. Wenn kein Inhalt heraushaengt, sondern
+ // noch Luft in einer Spalte ist, schrumpfen wir entsprechend, mindestens um
+ // nMinDiff, aber nicht unter das nMinimum.
+ // Abgebrochen wird, wenn kein Inhalt mehr heraushaengt und das Minimum sich auf
+ // weniger als ein MinDiff dem Maximum angenaehert hat oder das von der
+ // Umgebung vorgegebene Maximum erreicht ist und trotzdem Inhalt heraus-
+ // haengt.
+
+ // Kritik an der Implementation
+ // 1. Es kann theoretisch Situationen geben, in denen der Inhalt in einer geringeren
+ // Hoehe passt und in einer groesseren Hoehe nicht passt. Damit der Code robust
+ // gegen solche Verhaeltnisse ist, sind ein paar Abfragen bezgl. Minimum und Maximum
+ // drin, die wahrscheinlich niemals zuschlagen koennen.
+ // 2. Es wird fuer das Schrumpfen das gleiche nMinDiff benutzt wie fuer das Wachstum,
+ // das nMinDiff ist allerdings mehr oder weniger die kleinste erste Zeilenhoehe und
+ // als Mindestwert fuer das Schrumpfen nicht unbedingt optimal.
+
+ long nMinimum = nMinHeight;
+ long nMaximum;
+ sal_Bool bNoBalance = sal_False;
+ SWRECTFN( this )
+ if( IsSctFrm() )
+ {
+ nMaximum = (Frm().*fnRect->fnGetHeight)() - nBorder +
+ (Frm().*fnRect->fnBottomDist)(
+ (GetUpper()->*fnRect->fnGetPrtBottom)() );
+ nMaximum += GetUpper()->Grow( LONG_MAX, sal_True );
+ if( nMaximum < nMinimum )
+ {
+ if( nMaximum < 0 )
+ nMinimum = nMaximum = 0;
+ else
+ nMinimum = nMaximum;
+ }
+ if( nMaximum > BROWSE_HEIGHT )
+ nMaximum = BROWSE_HEIGHT;
+
+ bNoBalance = ((SwSectionFrm*)this)->GetSection()->GetFmt()->
+ GetBalancedColumns().GetValue();
+ SwFrm* pAny = ContainsAny();
+ if( bNoBalance ||
+ ( !(Frm().*fnRect->fnGetHeight)() && pAny ) )
+ {
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ // --> OD 2004-11-01 #i23129# - correction: enlarge section
+ // to the calculated maximum height.
+ (Frm().*fnRect->fnAddBottom)( nMaximum -
+ (Frm().*fnRect->fnGetHeight)() );
+ // <--
+ if( nTop > nMaximum )
+ nTop = nMaximum;
+ (this->*fnRect->fnSetYMargins)( nTop, 0 );
+ }
+ if( !pAny && !((SwSectionFrm*)this)->IsFtnLock() )
+ {
+ SwFtnContFrm* pFtnCont = ((SwSectionFrm*)this)->ContainsFtnCont();
+ if( pFtnCont )
+ {
+ SwFrm* pFtnAny = pFtnCont->ContainsAny();
+ if( pFtnAny && pFtnAny->IsValid() )
+ {
+ bBackLock = sal_True;
+ ((SwSectionFrm*)this)->SetFtnLock( sal_True );
+ }
+ }
+ }
+ }
+ else
+ nMaximum = LONG_MAX;
+
+ // --> OD 2004-08-25 #i3317# - reset temporarly consideration
+ // of wrapping style influence
+ SwPageFrm* pPageFrm = FindPageFrm();
+ SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
+ if ( pObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+
+ if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ }
+ }
+ }
+ // <--
+ do
+ {
+ //Kann eine Weile dauern, deshalb hier auf Waitcrsr pruefen.
+ if ( pImp )
+ pImp->CheckWaitCrsr();
+
+ bValidSize = sal_True;
+ //Erstmal die Spalten formatieren, das entlastet den
+ //Stack ein wenig.
+ //Bei der Gelegenheit stellen wir auch gleich mal die
+ //Breiten und Hoehen der Spalten ein (so sie denn falsch sind).
+ SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
+
+ // --> FME 2004-07-19 #i27399#
+ // Simply setting the column width based on the values returned by
+ // CalcColWidth does not work for automatic column width.
+ AdjustColumns( &rCol, sal_False );
+ // <--
+
+ for ( sal_uInt16 i = 0; i < nNumCols; ++i )
+ {
+ pCol->Calc();
+ // ColumnFrms besitzen jetzt einen BodyFrm, der auch kalkuliert werden will
+ pCol->Lower()->Calc();
+ if( pCol->Lower()->GetNext() )
+ pCol->Lower()->GetNext()->Calc(); // SwFtnCont
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+
+ ::CalcCntnt( this );
+
+ pCol = (SwLayoutFrm*)Lower();
+ OSL_ENSURE( pCol && pCol->GetNext(), ":-( Spalten auf Urlaub?");
+ // bMinDiff wird gesetzt, wenn es keine leere Spalte gibt
+ sal_Bool bMinDiff = sal_True;
+ // OD 28.03.2003 #108446# - check for all column content and all columns
+ while ( bMinDiff && pCol )
+ {
+ bMinDiff = 0 != pCol->ContainsCntnt();
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+ pCol = (SwLayoutFrm*)Lower();
+ // OD 28.03.2003 #108446# - initialize local variable
+ SwFrm *pLow = NULL;
+ SwTwips nDiff = 0;
+ SwTwips nMaxFree = 0;
+ SwTwips nAllFree = LONG_MAX;
+ // bFoundLower wird gesetzt, wenn es mind. eine nichtleere Spalte gibt
+ sal_Bool bFoundLower = sal_False;
+ while( pCol )
+ {
+ SwLayoutFrm* pLay = (SwLayoutFrm*)pCol->Lower();
+ SwTwips nInnerHeight = (pLay->Frm().*fnRect->fnGetHeight)() -
+ (pLay->Prt().*fnRect->fnGetHeight)();
+ if( pLay->Lower() )
+ {
+ bFoundLower = sal_True;
+ nInnerHeight += pLay->InnerHeight();
+ }
+ else if( nInnerHeight < 0 )
+ nInnerHeight = 0;
+
+ if( pLay->GetNext() )
+ {
+ bFoundLower = sal_True;
+ pLay = (SwLayoutFrm*)pLay->GetNext();
+ OSL_ENSURE( pLay->IsFtnContFrm(),"FtnContainer exspected" );
+ nInnerHeight += pLay->InnerHeight();
+ nInnerHeight += (pLay->Frm().*fnRect->fnGetHeight)() -
+ (pLay->Prt().*fnRect->fnGetHeight)();
+ }
+ nInnerHeight -= (pCol->Prt().*fnRect->fnGetHeight)();
+ if( nInnerHeight > nDiff )
+ {
+ nDiff = nInnerHeight;
+ nAllFree = 0;
+ }
+ else
+ {
+ if( nMaxFree < -nInnerHeight )
+ nMaxFree = -nInnerHeight;
+ if( nAllFree > -nInnerHeight )
+ nAllFree = -nInnerHeight;
+ }
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+
+ if ( bFoundLower || ( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() ) )
+ {
+ SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
+ // Hier wird entschieden, ob wir wachsen muessen, naemlich wenn
+ // ein Spalteninhalt (nDiff) oder ein Fly herausragt.
+ // Bei spaltigen Bereichen wird beruecksichtigt, dass mit dem
+ // Besitz eines nichtleeren Follows die Groesse festgelegt ist.
+ if ( nDiff || ::lcl_IsFlyHeightClipped( this ) ||
+ ( IsSctFrm() && ((SwSectionFrm*)this)->CalcMinDiff( nMinDiff ) ) )
+ {
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ // Das Minimum darf nicht kleiner sein als unsere PrtHeight,
+ // solange noch etwas herausragt.
+ if( nMinimum < nPrtHeight )
+ nMinimum = nPrtHeight;
+ // Es muss sichergestellt sein, dass das Maximum nicht kleiner
+ // als die PrtHeight ist, wenn noch etwas herausragt
+ if( nMaximum < nPrtHeight )
+ nMaximum = nPrtHeight; // Robust, aber kann das ueberhaupt eintreten?
+ if( !nDiff ) // wenn nur Flys herausragen, wachsen wir um nMinDiff
+ nDiff = nMinDiff;
+ // Wenn wir um mehr als nMinDiff wachsen wollen, wird dies auf die
+ // Spalten verteilt
+ if ( Abs(nDiff - nMinDiff) > nNumCols && nDiff > (long)nNumCols )
+ nDiff /= nNumCols;
+
+ if ( bMinDiff )
+ { // Wenn es keinen leeren Spalten gibt, wollen wir mind. um nMinDiff
+ // wachsen. Sonderfall: Wenn wir kleiner als die minimale Frmhoehe
+ // sind und die PrtHeight kleiner als nMinDiff ist, wachsen wir so,
+ // dass die PrtHeight hinterher genau nMinDiff ist.
+ long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
+ if ( nFrmHeight > nMinHeight || nPrtHeight >= nMinDiff )
+ nDiff = Max( nDiff, nMinDiff );
+ else if( nDiff < nMinDiff )
+ nDiff = nMinDiff - nPrtHeight + 1;
+ }
+ // nMaximum ist eine Groesse, in der der Inhalt gepasst hat,
+ // oder der von der Umgebung vorgegebene Wert, deshalb
+ // brauchen wir nicht ueber diesen Wrt hinauswachsen.
+ if( nDiff + nPrtHeight > nMaximum )
+ nDiff = nMaximum - nPrtHeight;
+ }
+ else if( nMaximum > nMinimum ) // Wir passen, haben wir auch noch Spielraum?
+ {
+ long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
+ if ( nMaximum < nPrtHeight )
+ nDiff = nMaximum - nPrtHeight; // wir sind ueber eine funktionierende
+ // Hoehe hinausgewachsen und schrumpfen wieder auf diese zurueck,
+ // aber kann das ueberhaupt eintreten?
+ else
+ { // Wir haben ein neues Maximum, eine Groesse, fuer die der Inhalt passt.
+ nMaximum = nPrtHeight;
+ // Wenn der Freiraum in den Spalten groesser ist als nMinDiff und wir
+ // nicht dadurch wieder unter das Minimum rutschen, wollen wir ein wenig
+ // Luft herauslassen.
+ if ( !bNoBalance &&
+ // --> OD 2004-11-04 #i23129# - <nMinDiff> can be
+ // big, because of an object at the beginning of
+ // a column. Thus, decrease optimization here.
+ //nMaxFree >= nMinDiff &&
+ nMaxFree > 0 &&
+ // <--
+ ( !nAllFree ||
+ nMinimum < nPrtHeight - nMinDiff ) )
+ {
+ nMaxFree /= nNumCols; // auf die Spalten verteilen
+ nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // mind. nMinDiff
+ if( nPrtHeight + nDiff <= nMinimum ) // Unter das Minimum?
+ nDiff = ( nMinimum - nMaximum ) / 2; // dann lieber die Mitte
+ }
+ else if( nAllFree )
+ {
+ nDiff = -nAllFree;
+ if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
+ nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
+ }
+ }
+ }
+ if( nDiff ) // jetzt wird geschrumpft oder gewachsen..
+ {
+ Size aOldSz( Prt().SSize() );
+ long nTop = (this->*fnRect->fnGetTopMargin)();
+ nDiff = (Prt().*fnRect->fnGetHeight)() + nDiff + nBorder -
+ (Frm().*fnRect->fnGetHeight)();
+ (Frm().*fnRect->fnAddBottom)( nDiff );
+ // --> OD 2006-08-16 #i68520#
+ if ( dynamic_cast<SwFlyFrm*>(this) )
+ {
+ dynamic_cast<SwFlyFrm*>(this)->InvalidateObjRectWithSpaces();
+ }
+ // <--
+ (this->*fnRect->fnSetYMargins)( nTop, nBorder - nTop );
+ ChgLowersProp( aOldSz );
+ NotifyLowerObjs();
+
+ // --> OD 2004-08-25 #i3317# - reset temporarly consideration
+ // of wrapping style influence
+ SwPageFrm* pTmpPageFrm = FindPageFrm();
+ SwSortedObjs* pTmpObjs = pTmpPageFrm ? pTmpPageFrm->GetSortedObjs() : 0L;
+ if ( pTmpObjs )
+ {
+ sal_uInt32 i = 0;
+ for ( i = 0; i < pTmpObjs->Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pTmpObjs)[i];
+
+ if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
+ {
+ pAnchoredObj->SetTmpConsiderWrapInfluence( false );
+ }
+ }
+ }
+ // <--
+ //Es muss geeignet invalidiert werden, damit
+ //sich die Frms huebsch ausbalancieren
+ //- Der jeweils erste ab der zweiten Spalte bekommt
+ // ein InvalidatePos();
+ pCol = (SwLayoutFrm*)Lower()->GetNext();
+ while ( pCol )
+ {
+ pLow = pCol->Lower();
+ if ( pLow )
+ pLow->_InvalidatePos();
+ pCol = (SwLayoutFrm*)pCol->GetNext();
+ }
+ if( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() )
+ {
+ // Wenn wir einen Follow erzeugt haben, muessen wir
+ // seinem Inhalt die Chance geben, im CalcCntnt
+ // zurueckzufliessen
+ SwCntntFrm* pTmpCntnt =
+ ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
+ if( pTmpCntnt )
+ pTmpCntnt->_InvalidatePos();
+ }
+ }
+ else
+ bEnd = sal_True;
+ }
+ else
+ bEnd = sal_True;
+
+ } while ( !bEnd || !bValidSize );
+ }
+ // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
+ // 2nd parameter to <true>.
+ ::CalcCntnt( this, true );
+ if( IsSctFrm() )
+ {
+ // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
+ ::CalcCntnt( this, true );
+ if( bBackLock )
+ ((SwSectionFrm*)this)->SetFtnLock( sal_False );
+ }
+}
+
+
+/*************************************************************************
+|*
+|* SwRootFrm::InvalidateAllCntnt()
+|*
+|*************************************************************************/
+
+SwCntntFrm* lcl_InvalidateSection( SwFrm *pCnt, sal_uInt8 nInv )
+{
+ SwSectionFrm* pSect = pCnt->FindSctFrm();
+ // Wenn unser CntntFrm in einer Tabelle oder Fussnote steht, sind nur
+ // Bereiche gemeint, die ebenfalls innerhalb liegen.
+ // Ausnahme: Wenn direkt eine Tabelle uebergeben wird.
+ if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
+ ( pCnt->IsInFtn() && !pSect->IsInFtn() ) ) && !pCnt->IsTabFrm() )
+ return NULL;
+ if( nInv & INV_SIZE )
+ pSect->_InvalidateSize();
+ if( nInv & INV_POS )
+ pSect->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pSect->_InvalidatePrt();
+ SwFlowFrm *pFoll = pSect->GetFollow();
+ // Temporary separation from follow
+ pSect->SetFollow( NULL );
+ SwCntntFrm* pRet = pSect->FindLastCntnt();
+ pSect->SetFollow( pFoll );
+ return pRet;
+}
+
+SwCntntFrm* lcl_InvalidateTable( SwTabFrm *pTable, sal_uInt8 nInv )
+{
+ if( ( nInv & INV_SECTION ) && pTable->IsInSct() )
+ lcl_InvalidateSection( pTable, nInv );
+ if( nInv & INV_SIZE )
+ pTable->_InvalidateSize();
+ if( nInv & INV_POS )
+ pTable->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pTable->_InvalidatePrt();
+ return pTable->FindLastCntnt();
+}
+
+void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv );
+
+void lcl_InvalidateCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
+{
+ SwCntntFrm *pLastTabCnt = NULL;
+ SwCntntFrm *pLastSctCnt = NULL;
+ while ( pCnt )
+ {
+ if( nInv & INV_SECTION )
+ {
+ if( pCnt->IsInSct() )
+ {
+ // Siehe oben bei Tabellen
+ if( !pLastSctCnt )
+ pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
+ if( pLastSctCnt == pCnt )
+ pLastSctCnt = NULL;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !pLastSctCnt, "Where's the last SctCntnt?" );
+#endif
+ }
+ if( nInv & INV_TABLE )
+ {
+ if( pCnt->IsInTab() )
+ {
+ // Um nicht fuer jeden CntntFrm einer Tabelle das FindTabFrm() zu rufen
+ // und wieder die gleiche Tabelle zu invalidieren, merken wir uns den letzten
+ // CntntFrm der Tabelle und reagieren erst wieder auf IsInTab(), wenn wir
+ // an diesem vorbei sind.
+ // Beim Eintritt in die Tabelle wird der LastSctCnt auf Null gesetzt,
+ // damit Bereiche im Innern der Tabelle richtig invalidiert werden.
+ // Sollte die Tabelle selbst in einem Bereich stehen, so wird an
+ // diesem die Invalidierung bis zu dreimal durchgefuehrt, das ist vertretbar.
+ if( !pLastTabCnt )
+ {
+ pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrm(), nInv );
+ pLastSctCnt = NULL;
+ }
+ if( pLastTabCnt == pCnt )
+ {
+ pLastTabCnt = NULL;
+ pLastSctCnt = NULL;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !pLastTabCnt, "Where's the last TabCntnt?" );
+#endif
+ }
+
+ if( nInv & INV_SIZE )
+ pCnt->Prepare( PREP_CLEAR, 0, sal_False );
+ if( nInv & INV_POS )
+ pCnt->_InvalidatePos();
+ if( nInv & INV_PRTAREA )
+ pCnt->_InvalidatePrt();
+ if ( nInv & INV_LINENUM )
+ pCnt->InvalidateLineNum();
+ if ( pCnt->GetDrawObjs() )
+ lcl_InvalidateAllCntnt( pCnt, nInv );
+ pCnt = pCnt->GetNextCntntFrm();
+ }
+}
+
+void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
+{
+ SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ if ( pFly->IsFlyInCntFrm() )
+ {
+ ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
+ if( nInv & INV_DIRECTION )
+ pFly->CheckDirChange();
+ }
+ }
+ }
+}
+
+void SwRootFrm::InvalidateAllCntnt( sal_uInt8 nInv )
+{
+ // Erst werden alle Seitengebundenen FlyFrms abgearbeitet.
+ SwPageFrm *pPage = (SwPageFrm*)Lower();
+ while( pPage )
+ {
+ pPage->InvalidateFlyLayout();
+ pPage->InvalidateFlyCntnt();
+ pPage->InvalidateFlyInCnt();
+ pPage->InvalidateLayout();
+ pPage->InvalidateCntnt();
+ pPage->InvalidatePage( pPage ); //Damit ggf. auch der Turbo verschwindet
+
+ if ( pPage->GetSortedObjs() )
+ {
+ const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
+ for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ if ( pAnchoredObj->ISA(SwFlyFrm) )
+ {
+ SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
+ ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
+ if ( nInv & INV_DIRECTION )
+ pFly->CheckDirChange();
+ }
+ }
+ }
+ if( nInv & INV_DIRECTION )
+ pPage->CheckDirChange();
+ pPage = (SwPageFrm*)(pPage->GetNext());
+ }
+
+ //Hier den gesamten Dokumentinhalt und die zeichengebundenen Flys.
+ ::lcl_InvalidateCntnt( ContainsCntnt(), nInv );
+
+ if( nInv & INV_PRTAREA )
+ {
+ ViewShell *pSh = getRootFrm()->GetCurrShell();
+ if( pSh )
+ pSh->InvalidateWindows( Frm() );
+ }
+}
+
+/** method to invalidate/re-calculate the position of all floating
+ screen objects (Writer fly frames and drawing objects), which are
+ anchored to paragraph or to character.
+
+ OD 2004-03-16 #i11860#
+
+ @author OD
+*/
+void SwRootFrm::InvalidateAllObjPos()
+{
+ const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>(Lower());
+ while( pPageFrm )
+ {
+ pPageFrm->InvalidateFlyLayout();
+
+ if ( pPageFrm->GetSortedObjs() )
+ {
+ const SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
+ for ( sal_uInt8 i = 0; i < rObjs.Count(); ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = rObjs[i];
+ const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
+ if ((rAnch.GetAnchorId() != FLY_AT_PARA) &&
+ (rAnch.GetAnchorId() != FLY_AT_CHAR))
+ {
+ // only to paragraph and to character anchored objects are considered.
+ continue;
+ }
+ // --> OD 2004-07-07 #i28701# - special invalidation for anchored
+ // objects, whose wrapping style influence has to be considered.
+ if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
+ pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
+ else
+ pAnchoredObj->InvalidateObjPos();
+ // <--
+ }
+ }
+
+ pPageFrm = static_cast<const SwPageFrm*>(pPageFrm->GetNext());
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */