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 );