diff options
Diffstat (limited to 'binfilter/bf_sw/source/core/layout/sw_flycnt.cxx')
-rw-r--r-- | binfilter/bf_sw/source/core/layout/sw_flycnt.cxx | 2194 |
1 files changed, 2194 insertions, 0 deletions
diff --git a/binfilter/bf_sw/source/core/layout/sw_flycnt.cxx b/binfilter/bf_sw/source/core/layout/sw_flycnt.cxx new file mode 100644 index 000000000000..e91750ea3dde --- /dev/null +++ b/binfilter/bf_sw/source/core/layout/sw_flycnt.cxx @@ -0,0 +1,2194 @@ +/* -*- 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. + * + ************************************************************************/ + + +#ifdef _MSC_VER +#pragma hdrstop +#endif + + +#include <tools/bigint.hxx> +#include "pagefrm.hxx" +#include "rootfrm.hxx" + +#include <horiornt.hxx> + +#include "txtfrm.hxx" +#include "doc.hxx" +#include "pam.hxx" +#include "frmfmt.hxx" +#include "frmtool.hxx" +#include "dflyobj.hxx" +#include "hints.hxx" +#include "ndtxt.hxx" + +#include <bf_svx/ulspitem.hxx> +#include <bf_svx/lrspitem.hxx> + +#include <fmtanchr.hxx> +#include <fmtornt.hxx> +#include <fmtfsize.hxx> +#include <fmtsrnd.hxx> +#include "tabfrm.hxx" +#include "flyfrms.hxx" +#include "sectfrm.hxx" +namespace binfilter { + +/************************************************************************* +|* +|* SwFlyAtCntFrm::SwFlyAtCntFrm() +|* +|* Ersterstellung MA 11. Nov. 92 +|* Letzte Aenderung MA 09. Apr. 99 +|* +|*************************************************************************/ + +/*N*/ SwFlyAtCntFrm::SwFlyAtCntFrm( SwFlyFrmFmt *pFmt, SwFrm *pAnch ) : +/*N*/ SwFlyFreeFrm( pFmt, pAnch ) +/*N*/ { +/*N*/ bAtCnt = TRUE; +/*N*/ bAutoPosition = FLY_AUTO_CNTNT == pFmt->GetAnchor().GetAnchorId(); +/*N*/ } + +/************************************************************************* +|* +|* SwFlyAtCntFrm::CheckCharRect() +|* +|*************************************************************************/ + + +/************************************************************************* +|* +|* SwFlyAtCntFrm::Modify() +|* +|* Ersterstellung MA 08. Feb. 93 +|* Letzte Aenderung MA 23. Nov. 94 +|* +|*************************************************************************/ + +/*N*/ void SwFlyAtCntFrm::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew ) +/*N*/ { +/*N*/ USHORT nWhich = pNew ? pNew->Which() : 0; +/*N*/ const SwFmtAnchor *pAnch = 0; +/*N*/ if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET == +/*N*/ ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, FALSE, +/*N*/ (const SfxPoolItem**)&pAnch )) +/*N*/ ; // Beim GetItemState wird der AnkerPointer gesetzt ! +/*N*/ +/*N*/ else if( RES_ANCHOR == nWhich ) +/*N*/ { +/*N*/ //Ankerwechsel, ich haenge mich selbst um. +/*N*/ //Es darf sich nicht um einen Wechsel des Ankertyps handeln, +/*N*/ //dies ist nur ueber die SwFEShell moeglich. +/*?*/ pAnch = (const SwFmtAnchor*)pNew; +/*N*/ } +/*N*/ +/*N*/ if( pAnch ) +/*N*/ { +/*N*/ ASSERT( pAnch->GetAnchorId() == GetFmt()->GetAnchor().GetAnchorId(), +/*N*/ "Unzulaessiger Wechsel des Ankertyps." ); +/*N*/ +/*N*/ //Abmelden, neuen Anker besorgen und 'dranhaengen. +/*N*/ SwRect aOld( AddSpacesToFrm() ); +/*N*/ SwPageFrm *pOldPage = FindPageFrm(); +/*N*/ const SwFrm *pOldAnchor = GetAnchor(); +/*N*/ SwCntntFrm *pCntnt = (SwCntntFrm*)GetAnchor(); +/*N*/ GetAnchor()->RemoveFly( this ); +/*N*/ +/*N*/ const BOOL bBodyFtn = (pCntnt->IsInDocBody() || pCntnt->IsInFtn()); +/*N*/ +/*N*/ //Den neuen Anker anhand des NodeIdx suchen, am alten und +/*N*/ //neuen NodeIdx kann auch erkannt werden, in welche Richtung +/*N*/ //gesucht werden muss. +/*N*/ const SwNodeIndex aNewIdx( pAnch->GetCntntAnchor()->nNode ); +/*N*/ SwNodeIndex aOldIdx( *pCntnt->GetNode() ); +/*N*/ +/*N*/ //fix: Umstellung, ehemals wurde in der do-while-Schleife nach vorn bzw. +/*N*/ //nach hinten gesucht; je nachdem wie welcher Index kleiner war. +/*N*/ //Das kann aber u.U. zu einer Endlosschleife fuehren. Damit +/*N*/ //wenigstens die Schleife unterbunden wird suchen wir nur in eine +/*N*/ //Richtung. Wenn der neue Anker nicht gefunden wird koennen wir uns +/*N*/ //immer noch vom Node einen Frame besorgen. Die Change, dass dies dann +/*N*/ //der richtige ist, ist gut. +/*N*/ const FASTBOOL bNext = aOldIdx < aNewIdx; +/*N*/ while ( pCntnt && aOldIdx != aNewIdx ) +/*N*/ { +/*N*/ do +/*N*/ { if ( bNext ) +/*?*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ else +/*N*/ pCntnt = pCntnt->GetPrevCntntFrm(); +/*N*/ } while ( pCntnt && +/*N*/ !(bBodyFtn == (pCntnt->IsInDocBody() || +/*N*/ pCntnt->IsInFtn())) ); +/*N*/ if (pCntnt) +/*N*/ aOldIdx = *pCntnt->GetNode(); +/*N*/ } +/*N*/ if ( !pCntnt ) +/*N*/ { +/*?*/ SwCntntNode *pNode = aNewIdx.GetNode().GetCntntNode(); +/*?*/ pCntnt = pNode->GetFrm( &pOldAnchor->Frm().Pos(), 0, FALSE ); +/*?*/ ASSERT( pCntnt, "Neuen Anker nicht gefunden" ); +/*N*/ } +/*N*/ //Flys haengen niemals an einem Follow sondern immer am +/*N*/ //Master, den suchen wir uns jetzt. +/*N*/ const SwFlowFrm *pFlow = pCntnt; +/*N*/ while ( pFlow->IsFollow() ) +/*?*/ pFlow = pFlow->FindMaster(); +/*N*/ pCntnt = (SwCntntFrm*)pFlow->GetFrm(); +/*N*/ +/*N*/ //und schwupp angehaengt das teil... +/*N*/ pCntnt->AppendFly( this ); +/*N*/ if ( pOldPage && pOldPage != FindPageFrm() ) +/*N*/ NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE ); +/*N*/ +/*N*/ //Fix(3495) +/*N*/ _InvalidatePos(); +/*N*/ InvalidatePage(); +/*N*/ SetNotifyBack(); +/*N*/ } +/*N*/ else +/*N*/ SwFlyFrm::Modify( pOld, pNew ); +/*N*/ } + +/************************************************************************* +|* +|* 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. +|* +|* Ersterstellung MA 12. Nov. 92 +|* Letzte Aenderung MA 20. Sep. 96 +|* +|*************************************************************************/ +//Wir brauchen ein Paar Hilfsklassen zur Kontrolle der Ozillation und ein paar +//Funktionen um die Uebersicht zu gewaehrleisten. + +/*N*/ class SwOszControl +/*N*/ { +/*N*/ static const SwFlyFrm *pStk1; +/*N*/ static const SwFlyFrm *pStk2; +/*N*/ static const SwFlyFrm *pStk3; +/*N*/ static const SwFlyFrm *pStk4; +/*N*/ static const SwFlyFrm *pStk5; +/*N*/ +/*N*/ const SwFlyFrm *pFly; +/*N*/ Point aStk1, aStk2, aStk3, aStk4, aStk5; +/*N*/ +/*N*/ public: +/*N*/ SwOszControl( const SwFlyFrm *pFrm ); +/*N*/ ~SwOszControl(); +/*N*/ FASTBOOL ChkOsz(); +/*N*/ static FASTBOOL IsInProgress( const SwFlyFrm *pFly ); +/*N*/ }; +/*N*/ const SwFlyFrm *SwOszControl::pStk1 = 0; +/*N*/ const SwFlyFrm *SwOszControl::pStk2 = 0; +/*N*/ const SwFlyFrm *SwOszControl::pStk3 = 0; +/*N*/ const SwFlyFrm *SwOszControl::pStk4 = 0; +/*N*/ const SwFlyFrm *SwOszControl::pStk5 = 0; + +/*N*/ SwOszControl::SwOszControl( const SwFlyFrm *pFrm ) : +/*N*/ pFly( pFrm ) +/*N*/ { +/*N*/ if ( !SwOszControl::pStk1 ) +/*N*/ SwOszControl::pStk1 = pFly; +/*N*/ 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; +/*N*/ } + +/*N*/ SwOszControl::~SwOszControl() +/*N*/ { +/*N*/ if ( SwOszControl::pStk1 == pFly ) +/*N*/ SwOszControl::pStk1 = 0; +/*N*/ 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; +/*N*/ } + +/*N*/ FASTBOOL IsInProgress( const SwFlyFrm *pFly ) +/*N*/ { + DBG_BF_ASSERT(0, "STRIP"); return FALSE;//STRIP001 //STRIP001 return SwOszControl::IsInProgress( pFly ); +/*N*/ } + +/*N*/ FASTBOOL SwOszControl::IsInProgress( const SwFlyFrm *pFly ) +/*N*/ { +/*N*/ if ( SwOszControl::pStk1 && !pFly->IsLowerOf( SwOszControl::pStk1 ) ) +/*N*/ return TRUE; +/*N*/ if ( SwOszControl::pStk2 && !pFly->IsLowerOf( SwOszControl::pStk2 ) ) +/*?*/ return TRUE; +/*N*/ if ( SwOszControl::pStk3 && !pFly->IsLowerOf( SwOszControl::pStk3 ) ) +/*?*/ return TRUE; +/*N*/ if ( SwOszControl::pStk4 && !pFly->IsLowerOf( SwOszControl::pStk4 ) ) +/*?*/ return TRUE; +/*N*/ if ( SwOszControl::pStk5 && !pFly->IsLowerOf( SwOszControl::pStk5 ) ) +/*?*/ return TRUE; +/*N*/ return FALSE; +/*N*/ } + +/*N*/ FASTBOOL SwOszControl::ChkOsz() +/*N*/ { +/*N*/ FASTBOOL bRet = TRUE; +/*N*/ Point aTmp = pFly->Frm().Pos(); +/*N*/ if( aTmp == Point() ) +/*N*/ aTmp.X() = 1; +/*N*/ //Ist der Stack am Ende? +/*N*/ if ( aStk1 != Point() ) +/*?*/ return TRUE; +/*N*/ if ( aTmp != aStk1 && aTmp != aStk2 && aTmp != aStk3 && +/*N*/ aTmp != aStk4 && aTmp != aStk5 ) +/*N*/ { +/*N*/ aStk1 = aStk2; +/*N*/ aStk2 = aStk3; +/*N*/ aStk3 = aStk4; +/*N*/ aStk4 = aStk5; +/*N*/ aStk5 = aTmp; +/*N*/ bRet = FALSE; +/*N*/ } +/*N*/ return bRet; +/*N*/ } + +/*M*/ void SwFlyAtCntFrm::MakeAll() +/*M*/ { +/*M*/ if ( !SwOszControl::IsInProgress( this ) && !IsLocked() && !IsColLocked() ) +/*M*/ { +/*M*/ if( !GetPage() && GetAnchor() && GetAnchor()->IsInFly() ) +/*M*/ { +/*M*/ SwFlyFrm* pFly = GetAnchor()->FindFlyFrm(); +/*M*/ SwPageFrm *pPage = pFly ? pFly->FindPageFrm() : NULL; +/*M*/ if( pPage ) +/*M*/ pPage->SwPageFrm::AppendFly( this ); +/*M*/ } +/*M*/ if( GetPage() ) +/*M*/ { +/*M*/ //Den Anker muessen wir zwischendurch natuerlich Formatieren, damit +/*M*/ //Repaints usw. stimmen sollte er natuerlich trotzdem Invalid bleiben. +/*M*/ //Jetzt Stufe 2: Damit Repaints stimmen muessen alle Frms wieder Invalidiert +/*M*/ //werden, die unterwegs formatiert werden. +/*M*/ //Dazu werden sie ein ein PrtArr eingetragen; die Frms mit CompletePaint +/*M*/ //zu flaggen scheint mir hier das Mittel der Wahl. +/*M*/ //(Vielleicht sollte es einmal die Moeglichkeit geben sie einfach mit +/*M*/ //Paint zu flaggen; kein Formatieren, aber ein Paint-Aufruf, vor allem +/*M*/ //wohl fuer TxtFrms geeignet. +/*M*/ //Jetzt Stufe 3: einfach ein globales Flag und schon flaggen sie sich +/*M*/ //selbst. +/*M*/ bSetCompletePaintOnInvalidate = TRUE; +/*M*/ sal_Bool bLockedAnchor = +/*M*/ static_cast<const SwTxtFrm*>( GetAnchor() )->IsAnyJoinLocked(); +/*M*/ { +/*M*/ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); +/*M*/ const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize(); +/*M*/ if( rFrmSz.GetHeightPercent() != 0xFF && +/*M*/ rFrmSz.GetHeightPercent() >= 100 ) +/*M*/ { +/*M*/ pFmt->LockModify(); +/*M*/ SwFmtSurround aMain( pFmt->GetSurround() ); +/*M*/ if ( aMain.GetSurround() == SURROUND_NONE ) +/*M*/ { +/*M*/ aMain.SetSurround( SURROUND_THROUGHT ); +/*M*/ pFmt->SetAttr( aMain ); +/*M*/ } +/*M*/ pFmt->UnlockModify(); +/*M*/ } +/*M*/ } +/*M*/ SwOszControl aOszCntrl( this ); +/*M*/ +/*M*/ if( !bLockedAnchor ) +/*M*/ { +/*M*/ if( GetAnchor()->IsInSct() ) +/*M*/ { +/*M*/ SwSectionFrm *pSct = GetAnchor()->FindSctFrm(); +/*M*/ pSct->Calc(); +/*M*/ } +/*M*/ +/*M*/ GetAnchor()->Calc(); +/*M*/ } +/*M*/ +/*M*/ SwFrm* pFooter = GetAnchor()->FindFooterOrHeader(); +/*M*/ if( pFooter && !pFooter->IsFooterFrm() ) +/*M*/ pFooter = NULL; +/*M*/ FASTBOOL bOsz = FALSE; +/*M*/ FASTBOOL bExtra = Lower() && Lower()->IsColumnFrm(); +/*M*/ +/*M*/ do { +/*M*/ SWRECTFN( this ) +/*M*/ Point aOldPos( (Frm().*fnRect->fnGetPos)() ); +/*M*/ SwFlyFreeFrm::MakeAll(); +/*M*/ BOOL bPosChg = aOldPos != (Frm().*fnRect->fnGetPos)(); +/*M*/ if( !bLockedAnchor ) +/*M*/ { +/*M*/ if( GetAnchor()->IsInSct() ) +/*M*/ { +/*M*/ SwSectionFrm *pSct = GetAnchor()->FindSctFrm(); +/*M*/ pSct->Calc(); +/*M*/ } +/*M*/ +/*M*/ GetAnchor()->Calc(); +/*M*/ } +/*M*/ +/*M*/ if( aOldPos != (Frm().*fnRect->fnGetPos)() || +/*M*/ ( !GetValidPosFlag() &&( pFooter || bPosChg ) ) ) +/*M*/ bOsz = aOszCntrl.ChkOsz(); +/*M*/ if( bExtra && Lower() && !Lower()->GetValidPosFlag() ) +/*M*/ { // Wenn ein mehrspaltiger Rahmen wg. Positionswechsel ungueltige +/*M*/ // Spalten hinterlaesst, so drehen wir lieber hier eine weitere +/*M*/ // Runde und formatieren unseren Inhalt via FormatWidthCols nochmal. +/*M*/ _InvalidateSize(); +/*M*/ bExtra = FALSE; // Sicherhaltshalber gibt es nur eine Ehrenrunde. +/*M*/ } +/*M*/ } while ( !IsValid() && !bOsz ); +/*M*/ +/*M*/ if ( bOsz ) +/*M*/ { +/*M*/ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); +/*M*/ pFmt->LockModify(); +/*M*/ SwFmtSurround aMain( pFmt->GetSurround() ); +/*M*/ // Im Notfall setzen wir automatisch positionierte Rahmen mit +/*M*/ // Rekursion auf Durchlauf, das duerfte beruhigend wirken. +/*M*/ if( IsAutoPos() && aMain.GetSurround() != SURROUND_THROUGHT ) +/*M*/ { +/*M*/ aMain.SetSurround( SURROUND_THROUGHT ); +/*M*/ pFmt->SetAttr( aMain ); +/*M*/ } +/*M*/ else +/*M*/ { +/*M*/ SwFmtVertOrient aOrient( pFmt->GetVertOrient() ); +/*M*/ aOrient.SetVertOrient( VERT_TOP ); +/*M*/ pFmt->SetAttr( aOrient ); +/*M*/ //Wenn der Rahmen auf "Kein Umlauf" steht, versuchen wir es mal +/*M*/ //mit Seitenumlauf. +/*M*/ if ( aMain.GetSurround() == SURROUND_NONE ) +/*M*/ { +/*M*/ aMain.SetSurround( SURROUND_PARALLEL ); +/*M*/ pFmt->SetAttr( aMain ); +/*M*/ } +/*M*/ } +/*M*/ pFmt->UnlockModify(); +/*M*/ +/*M*/ _InvalidatePos(); +/*M*/ SwFlyFreeFrm::MakeAll(); +/*M*/ if( !bLockedAnchor ) +/*M*/ GetAnchor()->Calc(); +/*M*/ if ( !GetValidPosFlag() ) +/*M*/ { +/*M*/ SwFlyFreeFrm::MakeAll(); +/*M*/ if( !bLockedAnchor ) +/*M*/ GetAnchor()->Calc(); +/*M*/ } +/*M*/ //Osz auf jeden fall zum Stehen bringen. +/*M*/ bValidPos = bValidSize = bValidPrtArea = TRUE; +/*M*/ } +/*M*/ bSetCompletePaintOnInvalidate = FALSE; +/*M*/ } +/*M*/ } +/*M*/ } + +/************************************************************************* +|* +|* FindAnchor() und Hilfsfunktionen. +|* +|* Beschreibung: Sucht ausgehend von pOldAnch einen Anker fuer +|* Absatzgebundene Objekte. +|* Wird beim Draggen von Absatzgebundenen Objekten zur Ankeranzeige sowie +|* fuer Ankerwechsel benoetigt. +|* Ersterstellung MA 22. Jun. 93 +|* Letzte Aenderung MA 30. Jan. 95 +|* +|*************************************************************************/ + +/*N*/ class SwDistance +/*N*/ { +/*N*/ public: +/*N*/ SwTwips nMain, nSub; +/*N*/ SwDistance() { nMain = nSub = 0; } +/*N*/ SwDistance& operator=( const SwDistance &rTwo ) +/*N*/ { nMain = rTwo.nMain; nSub = rTwo.nSub; return *this; } +/*N*/ BOOL operator<( const SwDistance& rTwo ) +/*N*/ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && nSub && +/*N*/ rTwo.nSub && nSub < rTwo.nSub ); } +/*N*/ BOOL operator<=( const SwDistance& rTwo ) +/*N*/ { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && ( !nSub || +/*N*/ !rTwo.nSub || nSub <= rTwo.nSub ) ); } +/*N*/ }; + +/*N*/ const SwFrm * MA_FASTCALL lcl_CalcDownDist( SwDistance &rRet, +/*N*/ const Point &rPt, +/*N*/ const SwCntntFrm *pCnt ) +/*N*/ { +/*N*/ rRet.nSub = 0; +/*N*/ //Wenn der Point direkt innerhalb des Cnt steht ist die Sache klar und +/*N*/ //der Cntnt hat automatisch eine Entfernung von 0 +/*N*/ if ( pCnt->Frm().IsInside( rPt ) ) +/*N*/ { +/*N*/ rRet.nMain = 0; +/*N*/ return pCnt; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ const SwLayoutFrm *pUp = pCnt->IsInTab() ? pCnt->FindTabFrm()->GetUpper() : pCnt->GetUpper(); +/*N*/ // einspaltige Bereiche muessen zu ihrem Upper durchschalten +/*N*/ while( pUp->IsSctFrm() ) +/*N*/ pUp = pUp->GetUpper(); +/*N*/ SWRECTFN( pUp ) +/*N*/ //Dem Textflus folgen. +/*N*/ if ( pUp->Frm().IsInside( rPt ) ) +/*N*/ { +/*N*/ if( bVert ) +/*N*/ rRet.nMain = pCnt->Frm().Left() + pCnt->Frm().Width() -rPt.X(); +/*N*/ else +/*N*/ rRet.nMain = rPt.Y() - pCnt->Frm().Top(); +/*N*/ return pCnt; +/*N*/ } +/*N*/ else if ( rPt.Y() <= pUp->Frm().Top() ) +/*N*/ { +/*N*/ rRet.nMain = LONG_MAX; +/*N*/ } +/*N*/ else if( rPt.X() < pUp->Frm().Left() && +/*N*/ rPt.Y() <= ( bVert ? pUp->Frm().Top() : pUp->Frm().Bottom() ) ) +/*N*/ { +/*?*/ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, FALSE, pCnt ); +/*?*/ if( !pLay || +/*?*/ (bVert && (pLay->Frm().Top() + pLay->Prt().Bottom()) <rPt.Y())|| +/*?*/ (!bVert && (pLay->Frm().Left() + pLay->Prt().Right())<rPt.X()) ) +/*?*/ { +/*?*/ if( bVert ) +/*?*/ rRet.nMain = pCnt->Frm().Left() + pCnt->Frm().Width() +/*?*/ - rPt.X(); +/*?*/ else +/*?*/ rRet.nMain = rPt.Y() - pCnt->Frm().Top(); +/*?*/ return pCnt; +/*?*/ } +/*?*/ else +/*?*/ rRet.nMain = LONG_MAX; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ rRet.nMain = bVert ? pCnt->Frm().Left() + pCnt->Frm().Width() - +/*N*/ (pUp->Frm().Left() + pUp->Prt().Left()) +/*N*/ : (pUp->Frm().Top() + pUp->Prt().Bottom()) - pCnt->Frm().Top(); +/*N*/ +/*N*/ const SwFrm *pPre = pCnt; +/*N*/ const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, TRUE, pCnt ); +/*N*/ SwTwips nFrmTop, nPrtHeight; +/*N*/ BOOL bSct; +/*N*/ const SwSectionFrm *pSect = pUp->FindSctFrm(); +/*N*/ if( pSect ) +/*N*/ { +/*N*/ rRet.nSub = rRet.nMain; +/*N*/ rRet.nMain = 0; +/*N*/ } +/*N*/ if( pSect && !pSect->IsAnLower( pLay ) ) +/*N*/ { +/*?*/ bSct = FALSE; +/*?*/ const SwSectionFrm* pNxtSect = pLay ? pLay->FindSctFrm() : 0; +/*?*/ if( pSect->IsAnFollow( pNxtSect ) ) +/*?*/ { +/*?*/ if( pLay->IsVertical() ) +/*?*/ { +/*?*/ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); +/*?*/ nPrtHeight = pLay->Prt().Width(); +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ nFrmTop = pLay->Frm().Top(); +/*?*/ nPrtHeight = pLay->Prt().Height(); +/*?*/ } +/*?*/ pSect = pNxtSect; +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ pLay = pSect->GetUpper(); +/*?*/ if( pLay->IsVertical() ) +/*?*/ { +/*?*/ nFrmTop = pSect->Frm().Left(); +/*?*/ nPrtHeight = pSect->Frm().Left() - pLay->Frm().Left() +/*?*/ - pLay->Prt().Left(); +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ nFrmTop = pSect->Frm().Bottom(); +/*?*/ nPrtHeight = pLay->Frm().Top() + pLay->Prt().Top() +/*?*/ + pLay->Prt().Height() - pSect->Frm().Top() +/*?*/ - pSect->Frm().Height(); +/*?*/ } +/*?*/ pSect = 0; +/*?*/ } +/*?*/ } +/*N*/ else if( pLay ) +/*N*/ { +/*N*/ if( pLay->IsVertical() ) +/*N*/ { +/*N*/ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); +/*N*/ nPrtHeight = pLay->Prt().Width(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ nFrmTop = pLay->Frm().Top(); +/*N*/ nPrtHeight = pLay->Prt().Height(); +/*N*/ } +/*N*/ bSct = 0 != pSect; +/*N*/ } +/*N*/ while ( pLay && !pLay->Frm().IsInside( rPt ) && +/*N*/ ( pLay->Frm().Top() <= rPt.Y() || pLay->IsInFly() || +/*N*/ ( pLay->IsInSct() && +/*N*/ pLay->FindSctFrm()->GetUpper()->Frm().Top() <= rPt.Y())) ) +/*N*/ { +/*N*/ if ( pLay->IsFtnContFrm() ) +/*N*/ { +/*N*/ if ( !((SwLayoutFrm*)pLay)->Lower() ) +/*N*/ { +/*N*/ SwFrm *pDel = (SwFrm*)pLay; +/*N*/ pDel->Cut(); +/*N*/ delete pDel; +/*N*/ return pPre; +/*N*/ } +/*N*/ return 0; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ if( bSct || pSect ) +/*N*/ rRet.nSub += nPrtHeight; +/*N*/ else +/*N*/ rRet.nMain += nPrtHeight; +/*N*/ pPre = pLay; +/*N*/ pLay = pLay->GetLeaf( MAKEPAGE_NONE, TRUE, pCnt ); +/*N*/ if( pSect && !pSect->IsAnLower( pLay ) ) +/*N*/ { // If we're leaving a SwSectionFrm, the next Leaf-Frm +/*?*/ // is the part of the upper below the SectionFrm. +/*?*/ const SwSectionFrm* pNxtSect = pLay ? +/*?*/ pLay->FindSctFrm() : NULL; +/*?*/ bSct = FALSE; +/*?*/ if( pSect->IsAnFollow( pNxtSect ) ) +/*?*/ { +/*?*/ pSect = pNxtSect; +/*?*/ if( pLay->IsVertical() ) +/*?*/ { +/*?*/ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); +/*?*/ nPrtHeight = pLay->Prt().Width(); +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ nFrmTop = pLay->Frm().Top(); +/*?*/ nPrtHeight = pLay->Prt().Height(); +/*?*/ } +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ pLay = pSect->GetUpper(); +/*?*/ if( pLay->IsVertical() ) +/*?*/ { +/*?*/ nFrmTop = pSect->Frm().Left(); +/*?*/ nPrtHeight = pSect->Frm().Left() - +/*?*/ pLay->Frm().Left() - pLay->Prt().Left(); +/*?*/ } +/*?*/ else +/*?*/ { +/*?*/ nFrmTop = pSect->Frm().Bottom(); +/*?*/ nPrtHeight = pLay->Frm().Top()+pLay->Prt().Top() +/*?*/ + pLay->Prt().Height() - pSect->Frm().Top() +/*?*/ - pSect->Frm().Height(); +/*?*/ } +/*?*/ pSect = 0; +/*?*/ } +/*N*/ } +/*N*/ else if( pLay ) +/*N*/ { +/*N*/ if( pLay->IsVertical() ) +/*N*/ { +/*N*/ nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); +/*N*/ nPrtHeight = pLay->Prt().Width(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ nFrmTop = pLay->Frm().Top(); +/*N*/ nPrtHeight = pLay->Prt().Height(); +/*N*/ } +/*N*/ bSct = 0 != pSect; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if ( pLay ) +/*N*/ { +/*?*/ if ( pLay->Frm().IsInside( rPt ) ) +/*?*/ { +/*?*/ SwTwips nDiff = pLay->IsVertical() ? ( nFrmTop - rPt.X() ) +/*?*/ : ( rPt.Y() - nFrmTop ); +/*?*/ if( bSct || pSect ) +/*?*/ rRet.nSub += nDiff; +/*?*/ else +/*?*/ rRet.nMain += nDiff; +/*?*/ } +/*?*/ if ( pLay->IsFtnContFrm() && !((SwLayoutFrm*)pLay)->Lower() ) +/*?*/ { +/*?*/ SwFrm *pDel = (SwFrm*)pLay; +/*?*/ pDel->Cut(); +/*?*/ delete pDel; +/*?*/ return 0; +/*?*/ } +/*?*/ return pLay; +/*N*/ } +/*N*/ else +/*N*/ rRet.nMain = LONG_MAX; +/*N*/ } +/*N*/ } +/*N*/ return 0; +/*N*/ } + +//Bug 3985, optimierungsproblem, vergleiche auch trvlfrm.cxx lcl_FindCntnt() + +/*N*/ ULONG MA_FASTCALL lcl_FindCntDiff( const Point &rPt, const SwLayoutFrm *pLay, +/*N*/ const SwCntntFrm *& rpCnt, +/*N*/ const BOOL bBody, const BOOL bFtn ) +/*N*/ { +/*N*/ //Sucht unterhalb von pLay den dichtesten Cnt zum Point. Der Bezugspunkt +/*N*/ //der Cntnts ist immer die linke obere Ecke. +/*N*/ //Der Cnt soll moeglichst ueber dem Point liegen. +/*N*/ +/*N*/ #if OSL_DEBUG_LEVEL > 1 +/*N*/ Point arPoint( rPt ); +/*N*/ #endif +/*N*/ +/*N*/ rpCnt = 0; +/*N*/ ULONG nDistance = ULONG_MAX; +/*N*/ ULONG nNearest = ULONG_MAX; +/*N*/ const SwCntntFrm *pCnt = pLay->ContainsCntnt(); +/*N*/ +/*N*/ while ( pCnt && (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn())) +/*N*/ { +/*N*/ pCnt = pCnt->GetNextCntntFrm(); +/*N*/ if ( !pLay->IsAnLower( pCnt ) ) +/*N*/ pCnt = 0; +/*N*/ } +/*N*/ const SwCntntFrm *pNearest = pCnt; +/*N*/ if ( pCnt ) +/*N*/ { +/*N*/ do +/*N*/ { +/*N*/ //Jetzt die Entfernung zwischen den beiden Punkten berechnen. +/*N*/ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2 +/*N*/ sal_uInt32 dX = Max( pCnt->Frm().Left(), rPt.X() ) - +/*N*/ Min( pCnt->Frm().Left(), rPt.X() ), +/*N*/ dY = Max( pCnt->Frm().Top(), rPt.Y() ) - +/*N*/ Min( pCnt->Frm().Top(), rPt.Y() ); +/*N*/ BigInt dX1( dX ), dY1( dY ); +/*N*/ dX1 *= dX1; dY1 *= dY1; +/*N*/ const ULONG nDiff = ::binfilter::SqRt( dX1 + dY1 ); +/*N*/ if ( pCnt->Frm().Top() <= rPt.Y() ) +/*N*/ { +/*N*/ if ( nDiff < nDistance ) +/*N*/ { //Der ist dichter dran +/*N*/ nDistance = nNearest = nDiff; +/*N*/ rpCnt = pNearest = pCnt; +/*N*/ } +/*N*/ } +/*N*/ else if ( nDiff < nNearest ) +/*N*/ { +/*N*/ nNearest = nDiff; +/*N*/ pNearest = pCnt; +/*N*/ } +/*N*/ pCnt = pCnt->GetNextCntntFrm(); +/*N*/ while ( pCnt && +/*N*/ (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn())) +/*N*/ pCnt = pCnt->GetNextCntntFrm(); +/*N*/ +/*N*/ } while ( pCnt && pLay->IsAnLower( pCnt ) ); +/*N*/ } +/*N*/ if ( nDistance == ULONG_MAX ) +/*N*/ { rpCnt = pNearest; +/*N*/ return nNearest; +/*N*/ } +/*N*/ return nDistance; +/*N*/ } + +/*N*/ #ifdef _MSC_VER +/*N*/ #pragma optimize("e",on) +/*N*/ #endif + +/*N*/ const SwCntntFrm * MA_FASTCALL lcl_FindCnt( const Point &rPt, const SwCntntFrm *pCnt, +/*N*/ const BOOL bBody, const BOOL bFtn ) +/*N*/ { +/*N*/ //Sucht ausgehen von pCnt denjenigen CntntFrm, dessen linke obere +/*N*/ //Ecke am dichtesten am Point liegt. +/*N*/ //Liefert _immer_ einen CntntFrm zurueck. +/*N*/ +/*N*/ //Zunaechst wird versucht den dichtesten Cntnt innerhalt derjenigen +/*N*/ //Seite zu suchen innerhalb derer der Cntnt steht. +/*N*/ //Ausgehend von der Seite muessen die Seiten in beide +/*N*/ //Richtungen beruecksichtigt werden. +/*N*/ //Falls moeglich wird ein Cntnt geliefert, dessen Y-Position ueber der +/*N*/ //des Point sitzt. +/*N*/ const SwCntntFrm *pRet, *pNew; +/*N*/ const SwLayoutFrm *pLay = pCnt->FindPageFrm(); +/*N*/ ULONG nDist; +/*N*/ +/*N*/ nDist = ::binfilter::lcl_FindCntDiff( rPt, pLay, pNew, bBody, bFtn ); +/*N*/ if ( pNew ) +/*N*/ pRet = pNew; +/*N*/ else +/*N*/ { pRet = pCnt; +/*N*/ nDist = ULONG_MAX; +/*N*/ } +/*N*/ const SwCntntFrm *pNearest = pRet; +/*N*/ ULONG nNearest = nDist; +/*N*/ +/*N*/ if ( pLay ) +/*N*/ { +/*N*/ const SwLayoutFrm *pPge = pLay; +/*N*/ ULONG nOldNew = ULONG_MAX; +/*N*/ for ( USHORT i = 0; pPge->GetPrev() && (i < 3); ++i ) +/*N*/ { +/*N*/ pPge = (SwLayoutFrm*)pPge->GetPrev(); +/*N*/ const ULONG nNew = ::binfilter::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn ); +/*N*/ if ( nNew < nDist ) +/*N*/ { +/*N*/ if ( pNew->Frm().Top() <= rPt.Y() ) +/*N*/ { +/*N*/ pRet = pNearest = pNew; +/*N*/ nDist = nNearest = nNew; +/*N*/ } +/*N*/ else if ( nNew < nNearest ) +/*N*/ { +/*N*/ pNearest = pNew; +/*N*/ nNearest = nNew; +/*N*/ } +/*N*/ } +/*N*/ else if ( nOldNew != ULONG_MAX && nNew > nOldNew ) +/*N*/ break; +/*N*/ else +/*N*/ nOldNew = nNew; +/*N*/ +/*N*/ } +/*N*/ pPge = pLay; +/*N*/ nOldNew = ULONG_MAX; +/*N*/ for ( USHORT j = 0; pPge->GetNext() && (j < 3); ++j ) +/*N*/ { +/*N*/ pPge = (SwLayoutFrm*)pPge->GetNext(); +/*N*/ const ULONG nNew = ::binfilter::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn ); +/*N*/ if ( nNew < nDist ) +/*N*/ { +/*N*/ if ( pNew->Frm().Top() <= rPt.Y() ) +/*N*/ { +/*N*/ pRet = pNearest = pNew; +/*N*/ nDist = nNearest = nNew; +/*N*/ } +/*N*/ else if ( nNew < nNearest ) +/*N*/ { +/*N*/ pNearest = pNew; +/*N*/ nNearest = nNew; +/*N*/ } +/*N*/ } +/*N*/ else if ( nOldNew != ULONG_MAX && nNew > nOldNew ) +/*N*/ break; +/*N*/ else +/*N*/ nOldNew = nNew; +/*N*/ } +/*N*/ } +/*N*/ if ( (pRet->Frm().Top() > rPt.Y()) ) +/*N*/ return pNearest; +/*N*/ else +/*N*/ return pRet; +/*N*/ } + +/*N*/ void lcl_PointToPrt( Point &rPoint, const SwFrm *pFrm ) +/*N*/ { +/*N*/ SwRect aTmp( pFrm->Prt() ); +/*N*/ aTmp += pFrm->Frm().Pos(); +/*N*/ if ( rPoint.X() < aTmp.Left() ) +/*N*/ rPoint.X() = aTmp.Left(); +/*N*/ else if ( rPoint.X() > aTmp.Right() ) +/*N*/ rPoint.X() = aTmp.Right(); +/*N*/ if ( rPoint.Y() < aTmp.Top() ) +/*N*/ rPoint.Y() = aTmp.Top(); +/*N*/ else if ( rPoint.Y() > aTmp.Bottom() ) +/*N*/ rPoint.Y() = aTmp.Bottom(); +/*N*/ +/*N*/ } + +/*N*/ const SwCntntFrm *FindAnchor( const SwFrm *pOldAnch, const Point &rNew, +/*N*/ const BOOL bBodyOnly ) +/*N*/ { +/*N*/ //Zu der angegebenen DokumentPosition wird der dichteste Cnt im +/*N*/ //Textfluss gesucht. AusgangsFrm ist der uebergebene Anker. +/*N*/ const SwCntntFrm *pCnt; +/*N*/ if ( pOldAnch->IsCntntFrm() ) +/*N*/ pCnt = (const SwCntntFrm*)pOldAnch; +/*N*/ else +/*N*/ { Point aTmp( rNew ); +/*N*/ SwLayoutFrm *pTmpLay = (SwLayoutFrm*)pOldAnch; +/*N*/ if( pTmpLay->IsRootFrm() ) +/*N*/ { +/*N*/ SwRect aTmpRect( aTmp, Size(0,0) ); +/*N*/ pTmpLay = (SwLayoutFrm*)::binfilter::FindPage( aTmpRect, pTmpLay->Lower() ); +/*N*/ } +/*N*/ pCnt = pTmpLay->GetCntntPos( aTmp, FALSE, bBodyOnly ); +/*N*/ } +/*N*/ +/*N*/ //Beim Suchen darauf achten, dass die Bereiche sinnvoll erhalten +/*N*/ //bleiben. D.h. in diesem Fall nicht in Header/Footer hinein und +/*N*/ //nicht aus Header/Footer hinaus. +/*N*/ const BOOL bBody = pCnt->IsInDocBody() || bBodyOnly; +/*N*/ const BOOL bFtn = !bBodyOnly && pCnt->IsInFtn(); +/*N*/ +/*N*/ Point aNew( rNew ); +/*N*/ if ( bBody ) +/*N*/ { +/*N*/ //#38848 Vom Seitenrand in den Body ziehen. +/*N*/ const SwFrm *pPage = pCnt->FindPageFrm(); +/*N*/ ::binfilter::lcl_PointToPrt( aNew, pPage->GetUpper() ); +/*N*/ SwRect aTmp( aNew, Size( 0, 0 ) ); +/*N*/ pPage = ::binfilter::FindPage( aTmp, pPage ); +/*N*/ ::binfilter::lcl_PointToPrt( aNew, pPage ); +/*N*/ } +/*N*/ +/*N*/ if ( pCnt->IsInDocBody() == bBody && pCnt->Frm().IsInside( aNew ) ) +/*N*/ return pCnt; +/*N*/ else if ( pOldAnch->IsInDocBody() || pOldAnch->IsPageFrm() ) +/*N*/ { +/*N*/ //Vielleicht befindet sich der gewuenschte Anker ja auf derselben +/*N*/ //Seite wie der aktuelle Anker. +/*N*/ //So gibt es kein Problem mit Spalten. +/*N*/ Point aTmp( aNew ); +/*N*/ const SwCntntFrm *pTmp = pCnt->FindPageFrm()-> +/*N*/ GetCntntPos( aTmp, FALSE, TRUE, FALSE ); +/*N*/ if ( pTmp && pTmp->Frm().IsInside( aNew ) ) +/*N*/ return pTmp; +/*N*/ } +/*N*/ +/*N*/ //Ausgehend vom Anker suche ich jetzt in beide Richtungen bis ich +/*N*/ //den jeweils dichtesten gefunden habe. +/*N*/ //Nicht die direkte Entfernung ist relevant sondern die Strecke die +/*N*/ //im Textfluss zurueckgelegt werden muss. +/*N*/ const SwCntntFrm *pUpLst; +/*N*/ const SwCntntFrm *pUpFrm = pCnt; +/*N*/ SwDistance nUp, nUpLst; +/*N*/ ::binfilter::lcl_CalcDownDist( nUp, aNew, pUpFrm ); +/*N*/ SwDistance nDown = nUp; +/*N*/ BOOL bNegAllowed = TRUE;//Einmal aus dem negativen Bereich heraus lassen. +/*N*/ do +/*N*/ { +/*N*/ pUpLst = pUpFrm; nUpLst = nUp; +/*N*/ pUpFrm = pUpLst->GetPrevCntntFrm(); +/*N*/ while ( pUpFrm && +/*N*/ (bBody != pUpFrm->IsInDocBody() || bFtn != pUpFrm->IsInFtn())) +/*N*/ pUpFrm = pUpFrm->GetPrevCntntFrm(); +/*N*/ if ( pUpFrm ) +/*N*/ { +/*N*/ ::binfilter::lcl_CalcDownDist( nUp, aNew, pUpFrm ); +/*N*/ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es +/*N*/ //sich weiter zu suchen. +/*N*/ if ( pUpLst->IsInTab() && pUpFrm->IsInTab() ) +/*N*/ { +/*N*/ while ( pUpFrm && ((nUpLst < nUp && pUpFrm->IsInTab()) || +/*N*/ bBody != pUpFrm->IsInDocBody()) ) +/*N*/ { +/*N*/ pUpFrm = pUpFrm->GetPrevCntntFrm(); +/*N*/ if ( pUpFrm ) +/*N*/ ::binfilter::lcl_CalcDownDist( nUp, aNew, pUpFrm ); +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if ( !pUpFrm ) +/*N*/ nUp.nMain = LONG_MAX; +/*N*/ if ( nUp.nMain >= 0 && LONG_MAX != nUp.nMain ) +/*N*/ { +/*N*/ bNegAllowed = FALSE; +/*N*/ if ( nUpLst.nMain < 0 ) //nicht den falschen erwischen, wenn der Wert +/*N*/ //gerade von negativ auf positiv gekippt ist. +/*N*/ { pUpLst = pUpFrm; +/*N*/ nUpLst = nUp; +/*N*/ } +/*N*/ } +/*N*/ } while ( pUpFrm && ( ( bNegAllowed && nUp.nMain < 0 ) || ( nUp <= nUpLst ) ) ); +/*N*/ +/*N*/ const SwCntntFrm *pDownLst; +/*N*/ const SwCntntFrm *pDownFrm = pCnt; +/*N*/ SwDistance nDownLst; +/*N*/ if ( nDown.nMain < 0 ) +/*N*/ nDown.nMain = LONG_MAX; +/*N*/ do +/*N*/ { +/*N*/ pDownLst = pDownFrm; nDownLst = nDown; +/*N*/ pDownFrm = pDownLst->GetNextCntntFrm(); +/*N*/ while ( pDownFrm && +/*N*/ (bBody != pDownFrm->IsInDocBody() || bFtn != pDownFrm->IsInFtn())) +/*N*/ pDownFrm = pDownFrm->GetNextCntntFrm(); +/*N*/ if ( pDownFrm ) +/*N*/ { +/*N*/ ::binfilter::lcl_CalcDownDist( nDown, aNew, pDownFrm ); +/*N*/ if ( nDown.nMain < 0 ) +/*N*/ nDown.nMain = LONG_MAX; +/*N*/ //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es +/*N*/ //sich weiter zu suchen. +/*N*/ if ( pDownLst->IsInTab() && pDownFrm->IsInTab() ) +/*N*/ { +/*N*/ while ( pDownFrm && ( ( nDown.nMain != LONG_MAX && nDownLst < nDownLst +/*N*/ && pDownFrm->IsInTab()) || bBody != pDownFrm->IsInDocBody() ) ) +/*N*/ { +/*N*/ pDownFrm = pDownFrm->GetNextCntntFrm(); +/*N*/ if ( pDownFrm ) +/*N*/ ::binfilter::lcl_CalcDownDist( nDown, aNew, pDownFrm ); +/*N*/ if ( nDown.nMain < 0 ) +/*N*/ nDown.nMain = LONG_MAX; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if ( !pDownFrm ) +/*N*/ nDown.nMain = LONG_MAX; +/*N*/ +/*N*/ } while ( pDownFrm && nDown <= nDownLst && +/*N*/ nDown.nMain != LONG_MAX && nDownLst.nMain != LONG_MAX ); +/*N*/ +/*N*/ //Wenn ich in beide Richtungen keinen gefunden habe, so suche ich mir +/*N*/ //denjenigen Cntnt dessen linke obere Ecke dem Point am naechsten liegt. +/*N*/ //Eine derartige Situation tritt z.b. auf, wenn der Point nicht im Text- +/*N*/ //fluss sondern in irgendwelchen Raendern steht. +/*N*/ if ( nDownLst.nMain == LONG_MAX && nUpLst.nMain == LONG_MAX ) +/*N*/ { +/*N*/ // #102861# If an OLE objects, which is contained in a fly frame +/*N*/ // is resized in inplace mode and the new Position is outside the +/*N*/ // fly frame, we do not want to leave our fly frame. +/*N*/ if ( pCnt->IsInFly() ) +/*N*/ return pCnt; +/*N*/ +/*N*/ return ::binfilter::lcl_FindCnt( aNew, pCnt, bBody, bFtn ); +/*N*/ } +/*N*/ else +/*N*/ return nDownLst < nUpLst ? pDownLst : pUpLst; +/*N*/ } + +/************************************************************************* +|* +|* SwFlyAtCntFrm::SetAbsPos() +|* +|* Ersterstellung MA 22. Jun. 93 +|* Letzte Aenderung MA 11. Sep. 98 +|* +|*************************************************************************/ + + +/************************************************************************* +|* +|* SwFlyAtCntFrm::MakeFlyPos() +|* +|* Beschreibung: +|* +|* virtueller Anker: Der virtuelle Anker eines Flys ist der Anker selbst +|* oder einer seiner Follows. Es ist genau derjenige +|* Cntnt, der dem Fly aktuell am naechsten liegt, +|* genauer der aktuellen relativen Position des Fly +|* (siehe auch VertPos, Fix). Es wird nur die +|* vertikale Entfernung gemessen. +|* Der virtuelle Anker fuer die Horizontale Ausrichtung +|* muss nicht ein CntntFrm sein, denn wenn der Fly +|* z.B. ueber einer leeren Spalte steht, so muss eben +|* der LayoutFrm als virtueller Anker dienen, der im +|* Textfluss des Ankers liegt. +|* +|* HoriPos: +|* - Automatisch: Die automatische Ausrichtung orientiert sich +|* an einem SwFrm der folgendermassen ermittelt wird: Abhaengig +|* vom Attriut und ausgehend vom virtuellen Anker wird der +|* Bezugsframe gesucht (CntntFrm, LayoutFrm). +|* - Fix: Der Wert der relativen Entfernung aus dem Attribut ist +|* die relative Entfernung vom virtuellen Anker. +|* VertPos: +|* - Automatisch: Die automatische Ausrichtung orientiert sich immer +|* am virtuellen Anker. +|* - Fix: Der Fly muss nicht in der Umgebung untergebracht sein, in +|* der sein Anker steht; er folgt aber stets dem Textfluss dem +|* der Anker folgt. Geclippt (Drawing) wird der Fly am Rootfrm. +|* Damit die erstgenannte Bedingung erreicht wird, wird der +|* Fly ggf. entsprechend verschoben. Dabei bleibt die relative +|* Position des Attributes erhalten, die tatsaechliche relative +|* Position verhaelt sich zu der des Attributes etwa wie ein +|* Teleskoparm. Der Betrag der relativen Position ist die +|* Entfernung zur AbsPos des Ankers im Textfluss. +|* +|* Es wird immer zuerst die vertikale Position bestimmt, denn erst dann +|* steht der virtuelle Anker fest. +|* Die tatsaechliche relative Position (Member aRelPos) ist immer die +|* die Entfernung zum Anker - sie muss also nicht mit den im Attribut +|* angegebenen Werten uebereinstimmen, denn diese geben die Entfernung +|* 'im Textfluss' an. +|* +|* Ersterstellung MA 19. Nov. 92 +|* Letzte Aenderung MA 14. Nov. 96 +|* +|*************************************************************************/ + +/*N*/ inline void ValidateSz( SwFrm *pFrm ) +/*N*/ { +/*N*/ if ( pFrm ) +/*N*/ pFrm->bValidSize = TRUE; +/*N*/ } + +/*M*/ void DeepCalc( const SwFrm *pFrm ) +/*M*/ { +/*M*/ if( pFrm->IsSctFrm() || +/*M*/ ( pFrm->IsFlyFrm() && ((SwFlyFrm*)pFrm)->IsFlyInCntFrm() ) ) +/*M*/ return; +/*M*/ const SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm ); +/*M*/ if( pFlow && pFlow->IsAnyJoinLocked() ) +/*M*/ return; +/*M*/ +/*M*/ USHORT nCnt = 0; +/*M*/ +/*M*/ FASTBOOL bContinue = FALSE; +/*M*/ do +/*M*/ { if ( ++nCnt == 10 ) +/*M*/ { +/*M*/ ASSERT( !nCnt, "DeepCalc: Loop detected1?" ); +/*M*/ break; +/*M*/ } +/*M*/ +/*M*/ const FASTBOOL bSetComplete = !pFrm->IsValid(); +/*M*/ const SwRect aOldFrm( pFrm->Frm() ); +/*M*/ const SwRect aOldPrt( pFrm->Prt() ); +/*M*/ +/*M*/ const SwFrm *pUp = pFrm->GetUpper(); +/*M*/ if ( pUp ) +/*M*/ { +/*M*/ //Nicht weiter wenn der Up ein Fly mit Spalten ist. +/*M*/ if( ( !pUp->IsFlyFrm() || !((SwLayoutFrm*)pUp)->Lower() || +/*M*/ !((SwLayoutFrm*)pUp)->Lower()->IsColumnFrm() ) && +/*M*/ !pUp->IsSctFrm() ) +/*M*/ { +/*M*/ SWRECTFN( pUp ) +/*M*/ const Point aPt( (pUp->Frm().*fnRect->fnGetPos)() ); +/*M*/ ::binfilter::DeepCalc( pUp ); +/*M*/ bContinue = aPt != (pUp->Frm().*fnRect->fnGetPos)(); +/*M*/ } +/*M*/ } +/*M*/ else +/*M*/ pUp = pFrm; +/*M*/ +/*M*/ pFrm->Calc(); +/*M*/ if ( bSetComplete && (aOldFrm != pFrm->Frm() || aOldPrt != pFrm->Prt())) +/*M*/ pFrm->SetCompletePaint(); +/*M*/ +/*M*/ // bContinue = !pUp->IsValid(); +/*M*/ if ( pUp->IsFlyFrm() ) +/*M*/ { +/*M*/ if ( ((SwFlyFrm*)pUp)->IsLocked() || +/*M*/ (((SwFlyFrm*)pUp)->IsFlyAtCntFrm() && +/*M*/ SwOszControl::IsInProgress( (const SwFlyFrm*)pUp )) ) +/*M*/ { +/*M*/ bContinue = FALSE; +/*M*/ } +/*M*/ } +/*M*/ } while ( bContinue ); +/*M*/ } + +//Ermittlung des virtuellen Ankers fuer die Positionierung. +//Dieser ist entweder der Anker selbst oder einer seiner Follows. + +/*N*/ const SwCntntFrm *GetVirtualAnchor( const SwFlyAtCntFrm *pFly, xub_StrLen nOfs ) +/*N*/ { +/*N*/ const SwTxtFrm *pAct = (const SwTxtFrm*)pFly->GetAnchor(); +/*N*/ const SwTxtFrm* pTmp; +/*N*/ do +/*N*/ { +/*N*/ pTmp = pAct; +/*N*/ pAct = pTmp->GetFollow(); +/*N*/ } +/*N*/ while( pAct && nOfs >= pAct->GetOfst() ); +/*N*/ return pTmp; +/*N*/ } + +//Ermittlung des virtuellen Ankers, an dem sich die horizontale Ausrichtung +//orientieren muss. +//pAssumed enthaelt entweder bereits den Anker (Es ist dann der Anker des +//Flys oder einer seiner Follows) oder die Umgebung die der Orientierung, +//mangels einer besseren Moeglichkeit, dienen muss. + +/*N*/ const SwFrm *GetVirtualHoriAnchor( const SwFrm *pAssumed, const SwFlyFrm *pFly ) +/*N*/ { +/*N*/ const SwFrm *pRet = pAssumed; +/*N*/ +/*N*/ if ( !pRet->IsCntntFrm() ) +/*N*/ { //Wenn es Lower gibt, die selbst der Anker des Fly oder ein Follow +/*N*/ //desselben sind, so wird derjenige ausgewaehlt, der der aktuellen +/*N*/ //absoluten vertikalen Position des Fly am naechsten steht. +/*N*/ //Gibt es keinen, so bleib es bei pAssumed +/*N*/ const SwFrm *pFlow = ((SwLayoutFrm*)pRet)->Lower(); +/*N*/ SwTwips nCntDiff = LONG_MAX; +/*N*/ while ( pFlow ) +/*N*/ { +/*N*/ if ( pFlow->IsCntntFrm() && +/*N*/ ((SwCntntFrm*)pFly->GetAnchor())->IsAnFollow( (SwCntntFrm*)pFlow ) ) +/*N*/ { +/*N*/ SWRECTFN( pFlow ) +/*N*/ SwTwips nDiff = (pFly->Frm().*fnRect->fnGetTop)() - +/*N*/ (pFlow->Frm().*fnRect->fnGetTop)(); +/*N*/ if ( (nDiff = Abs(nDiff)) < nCntDiff ) +/*N*/ { +/*N*/ pRet = pFlow; //Der ist dichter dran +/*N*/ nCntDiff = nDiff; +/*N*/ } +/*N*/ } +/*N*/ pFlow = pFlow->GetNext(); +/*N*/ } +/*N*/ } +/*N*/ return pRet; +/*N*/ +/*N*/ } + +/*N*/ void SwFlyAtCntFrm::AssertPage() +/*N*/ { +/*N*/ //Prueft ob der Fly an der Seite haengt, auf der er steht, falls nicht +/*N*/ //wird er umgehaengt. Zur Pruefung wird nur die vertikale Ausrichtung +/*N*/ //herangezogen. +/*N*/ +/*N*/ SwPageFrm *pNewPage = FindPageFrm(); +/*N*/ SwPageFrm *pMyPage = pNewPage; +/*N*/ BOOL bSuperfluous = FALSE; +/*N*/ +/*N*/ //#45516# Ausnahmebehandlung. Eine Tabelle ist zu gross und haengt aus der +/*N*/ //Seite heraus. Der Rahmen kann dann zwar richtig bei seinem Anker stehen, +/*N*/ //Positionsmaessig aber ueber der naechsten Seite haengen. Damit das dann +/*N*/ //noch halbwegs brauchbar gedruckt werden kann (HTML) und der Rahmen nicht +/*N*/ //wirr in der Gegend gepaintet wird, wird der Rahmen bei der Seite verankert, +/*N*/ //auf der auch sein Anker sitzt. +/*N*/ if ( GetAnchor()->GetValidSizeFlag() && +/*N*/ Frm().Top() >= GetAnchor()->Frm().Top() && +/*N*/ Frm().Top() < GetAnchor()->Frm().Bottom() ) +/*N*/ { +/*N*/ pNewPage = GetAnchor()->FindPageFrm(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ BOOL bFound = FALSE; +/*N*/ const BOOL bFtn = GetAnchor()->IsInFtn(); +/*N*/ int nDir = INT_MAX; // 1 == Forward, 2 == Backward. +/*N*/ while ( !bFound ) +/*N*/ { +/*N*/ pNewPage->Calc(); +/*N*/ if ( Frm().Top() < pNewPage->Frm().Top() && pNewPage->GetPrev() ) +/*N*/ { +/*N*/ pNewPage = (SwPageFrm*)pNewPage->GetPrev(); +/*N*/ // OD 19.02.2003 #105643# - skip empty page and consider empty +/*N*/ // page at the beginning of the document. +/*N*/ // Assumption about document layout: +/*N*/ // No two empty pages following each other. +/*N*/ if ( pNewPage->IsEmptyPage() ) +/*N*/ { +/*N*/ if ( pNewPage->GetPrev() ) +/*N*/ { +/*N*/ pNewPage = static_cast<SwPageFrm*>(pNewPage->GetPrev()); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ bFound = TRUE; +/*N*/ pNewPage = static_cast<SwPageFrm*>(pNewPage->GetNext()); +/*N*/ } +/*N*/ } +/*N*/ if ( nDir == 2 ) +/*N*/ { +/*?*/ bFound = TRUE; +/*?*/ pNewPage = GetAnchor()->FindPageFrm(); +/*N*/ } +/*N*/ else +/*N*/ nDir = 1; +/*N*/ } +/*N*/ else if ( Frm().Top() > pNewPage->Frm().Bottom() ) +/*N*/ { +/*N*/ if ( nDir == 1 ) +/*N*/ { +/*?*/ bFound = TRUE; +/*?*/ pNewPage = GetAnchor()->FindPageFrm(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ nDir = 2; +/*N*/ if ( !pNewPage->GetNext() ) +/*N*/ { +/*?*/ pNewPage->GetLeaf( bFtn ? MAKEPAGE_NONE : MAKEPAGE_APPEND, +/*?*/ TRUE, GetAnchor()); +/*?*/ bSuperfluous = TRUE; +/*N*/ } +/*N*/ if ( pNewPage->GetNext() ) +/*N*/ { +/*N*/ pNewPage = (SwPageFrm*)pNewPage->GetNext(); +/*N*/ if( pNewPage->IsEmptyPage() ) +/*N*/ { +/*?*/ if( pNewPage->GetNext() ) +/*?*/ pNewPage = (SwPageFrm*)pNewPage->GetNext(); +/*?*/ else +/*?*/ { +/*?*/ bFound = TRUE; +/*?*/ pNewPage = (SwPageFrm*)pNewPage->GetPrev(); +/*?*/ } +/*N*/ } +/*N*/ } +/*N*/ else +/*?*/ bFound = TRUE; +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ bFound = TRUE; +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ if ( pMyPage != pNewPage ) +/*N*/ { +/*N*/ ASSERT( IsLocked(), "AssertPage: Unlocked Frame??" ); +/*N*/ pMyPage->MoveFly( this, pNewPage ); +/*N*/ if ( bSuperfluous && pMyPage->GetPhyPageNum() > pNewPage->GetPhyPageNum() ) +/*?*/ ((SwRootFrm*)pNewPage->GetUpper())->SetSuperfluous(); +/*N*/ } +/*N*/ +/*N*/ } + +/*N*/ BOOL MA_FASTCALL lcl_IsMoveable( SwFlyFrm *pFly, SwLayoutFrm *pLay ) +/*N*/ { +/*N*/ //Waere der Anker auch in der neuen Umgebung noch moveable? +/*N*/ BOOL bRet; +/*N*/ SwLayoutFrm *pUp = pFly->GetAnchor()->GetUpper(); +/*N*/ SwFrm *pNext = pFly->GetAnchor()->GetNext(); +/*N*/ pFly->GetAnchor()->Remove(); +/*N*/ pFly->GetAnchor()->InsertBefore( pLay, pLay->Lower() ); +/*N*/ bRet = pFly->GetAnchor()->IsMoveable(); +/*N*/ pFly->GetAnchor()->Remove(); +/*N*/ pFly->GetAnchor()->InsertBefore( pUp, pNext ); +/*N*/ return bRet; +/*N*/ +/*N*/ } + +// Wer weicht wem aus bzw. welcher Bereich ist "linker"/"rechter" als welcher? +/*N*/ BOOL MA_FASTCALL lcl_Minor( SwRelationOrient eRelO, SwRelationOrient eRelO2, +/*N*/ BOOL bLeft ) +/*N*/ {DBG_BF_ASSERT(0, "STRIP"); return FALSE;//STRIP001 +/*N*/ } + +/*N*/ void SwFlyAtCntFrm::MakeFlyPos() +/*N*/ { +/*N*/ /// OD 02.10.2002 #102646# +/*N*/ /// if fly frame position is valid, nothing is to do, Thus, return +/*N*/ if ( bValidPos ) +/*N*/ { +/*N*/ return; +/*N*/ } +/*N*/ +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// declare and set <pFooter> to footer frame, if fly frame is anchored +/*N*/ /// at a frame belonging to the footer. +/*N*/ const SwFrm* pFooter = GetAnchor()->FindFooterOrHeader(); +/*N*/ if( pFooter && !pFooter->IsFooterFrm() ) +/*N*/ pFooter = NULL; +/*N*/ +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// declare and set <bBrowse> to TRUE, if document is in browser mode and +/*N*/ /// fly frame is anchored at the body, but not at frame belonging to a table. +/*N*/ const FASTBOOL bBrowse = GetAnchor()->IsInDocBody() && !GetAnchor()->IsInTab() ? +/*N*/ GetFmt()->GetDoc()->IsBrowseMode() : FALSE; +/*N*/ +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// declare and init <bInvalidatePage> to FALSE, in order to invalidate +/*N*/ /// page size, if <bInvalidatePage> is set during the calculation of the +/*N*/ /// fly frame position. +/*N*/ FASTBOOL bInvalidatePage = FALSE; +/*N*/ +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// determine fly frame format and its left/right and its upper/lower spacing. +/*N*/ SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); +/*N*/ const SvxLRSpaceItem &rLR = pFmt->GetLRSpace(); +/*N*/ const SvxULSpaceItem &rUL = pFmt->GetULSpace(); +/*N*/ +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// determine, if fly frame has no surrounding. +/*N*/ const SwFmtSurround& rSurround = pFmt->GetSurround(); +/*N*/ const FASTBOOL bNoSurround = +/*N*/ rSurround.GetSurround() == SURROUND_NONE; +/*N*/ const FASTBOOL bWrapThrough = +/*N*/ rSurround.GetSurround() == SURROUND_THROUGHT; +/*N*/ +/*N*/ BOOL bGrow = +/*N*/ !GetAnchor()->IsInTab() || !pFmt->GetFrmSize().GetHeightPercent(); +/*N*/ +/*N*/ for (;;) +/*N*/ { +/*N*/ bValidPos = TRUE; +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( GetAnchor() ); +/*N*/ bValidPos = TRUE; +/*N*/ +/*N*/ //Die Werte in den Attributen muessen ggf. upgedated werden, +/*N*/ //deshalb werden hier Attributinstanzen und Flags benoetigt. +/*N*/ SwFmtVertOrient aVert( pFmt->GetVertOrient() ); +/*N*/ SwFmtHoriOrient aHori( pFmt->GetHoriOrient() ); +/*N*/ BOOL bVertChgd = FALSE, +/*N*/ bHoriChgd = FALSE, +/*N*/ bMoveable = GetAnchor()->IsMoveable(); +/*N*/ +/*N*/ //Wird waehrend der Berechnung der vertikalen Position benutzt +/*N*/ //und enthaelt hinterher den Frm, an dem sich die horizontale +/*N*/ //Positionierung orientieren muss. +/*N*/ const SwFrm *pOrient = GetAnchor(); +/*N*/ +/*N*/ // Dies wird der Frame, der das Zeichen eines am Zeichen gebundenen +/*N*/ // Rahmens enthaelt. +/*N*/ const SwFrm *pAutoOrient = pOrient; +/*N*/ +/*N*/ SwRect *pAutoPos; +/*N*/ if( FLY_AUTO_CNTNT == pFmt->GetAnchor().GetAnchorId() ) +/*N*/ { +/*N*/ const SwFmtAnchor& rAnch = pFmt->GetAnchor(); +/*N*/ if( !aLastCharRect.Height() && +/*N*/ !((SwTxtFrm*)GetAnchor())->GetAutoPos( aLastCharRect, +/*N*/ *rAnch.GetCntntAnchor() ) ) +/*N*/ return; +/*N*/ pAutoPos = &aLastCharRect; +/*N*/ pAutoOrient = ::binfilter::GetVirtualAnchor( this, rAnch.GetCntntAnchor()-> +/*N*/ nContent.GetIndex() ); +/*N*/ } +/*N*/ else +/*N*/ pAutoPos = NULL; +/*N*/ +/*N*/ //Horizontale und vertikale Positionen werden getrennt berechnet. +/*N*/ //Sie koennen jeweils Fix oder Variabel sein. +/*N*/ SWRECTFN( pAutoOrient ) +/*N*/ +/*N*/ //Zuerst die vertikale Position, damit feststeht auf welcher Seite +/*N*/ //bzw. in welchen Upper sich der Fly befindet. +/*N*/ if ( aVert.GetVertOrient() != VERT_NONE ) +/*N*/ { +/*N*/ pOrient = pAutoOrient; +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( pOrient ); +/*N*/ SwTwips nHeight, nAdd; +/*N*/ if ( aVert.GetRelationOrient() == PRTAREA ) +/*N*/ { +/*N*/ nHeight = (pOrient->Prt().*fnRect->fnGetHeight)(); +/*N*/ nAdd = (pOrient->*fnRect->fnGetTopMargin)(); +/*N*/ } +/*N*/ else if( pAutoPos && REL_CHAR == aVert.GetRelationOrient() ) +/*N*/ { +/*N*/ nHeight = (pAutoPos->*fnRect->fnGetHeight)(); +/*N*/ nAdd = (*fnRect->fnYDiff)( (pAutoPos->*fnRect->fnGetTop)(), +/*N*/ (pOrient->Frm().*fnRect->fnGetTop)() ); +/*N*/ } +/*N*/ else +/*N*/ { nHeight = (pOrient->Frm().*fnRect->fnGetHeight)(); +/*N*/ nAdd = 0; +/*N*/ } +/*N*/ SwTwips nRelPosY; +/*N*/ SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)(); +/*N*/ if ( aVert.GetVertOrient() == VERT_CENTER ) +/*N*/ nRelPosY = (nHeight / 2) - (nFrmHeight / 2); +/*N*/ else +/*N*/ { +/*N*/ SwTwips nUpper = bVert ? rLR.GetRight() : rUL.GetUpper(); +/*N*/ if ( aVert.GetVertOrient() == VERT_BOTTOM ) +/*N*/ { +/*N*/ if( bNoSurround ) +/*N*/ nRelPosY = nHeight + nUpper; +/*N*/ else +/*N*/ nRelPosY = nHeight - (nFrmHeight + ( bVert ? +/*N*/ rLR.GetLeft() : rUL.GetLower())); +/*N*/ } +/*N*/ else if( pAutoPos && aVert.GetVertOrient() == VERT_CHAR_BOTTOM ) +/*N*/ { +/*N*/ nRelPosY = nHeight + nUpper; +/*N*/ if( bVert ) +/*N*/ nRelPosY += aFrm.Width(); +/*N*/ } +/*N*/ else +/*N*/ nRelPosY = nUpper; +/*N*/ } +/*N*/ nRelPosY += nAdd; +/*N*/ SwTwips nOTop = (pOrient->Frm().*fnRect->fnGetTop)(); +/*N*/ SwTwips nBot = nRelPosY + nFrmHeight + (*fnRect->fnYDiff)( nOTop, +/*N*/ (pOrient->GetUpper()->*fnRect->fnGetPrtBottom)()); +/*N*/ if( nBot > 0 ) +/*N*/ nRelPosY -= nBot; +/*N*/ if( nRelPosY < 0 ) +/*N*/ nRelPosY = 0; +/*N*/ //Da die relative Position immer zum Anker relativ ist, muss dessen +/*N*/ //Entfernung zum virtuellen Anker aufaddiert werden. +/*N*/ if ( GetAnchor() != pOrient ) +/*N*/ nRelPosY += (*fnRect->fnYDiff)( nOTop, +/*N*/ (GetAnchor()->Frm().*fnRect->fnGetTop)()); +/*N*/ if ( nRelPosY != aVert.GetPos() ) +/*N*/ { aVert.SetPos( nRelPosY ); +/*N*/ bVertChgd = TRUE; +/*N*/ } +/*N*/ if( bVert ) +/*N*/ aRelPos.X() = nRelPosY; +/*N*/ else +/*N*/ aRelPos.Y() = nRelPosY; +/*N*/ } +/*N*/ +/*N*/ pOrient = aVert.GetVertOrient() == VERT_NONE ? +/*N*/ GetAnchor()->GetUpper() : pAutoOrient->GetUpper(); +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( pOrient ); +/*N*/ +/*N*/ SwTwips nRelDiff = 0; +/*N*/ if ( aVert.GetVertOrient() == VERT_NONE ) +/*N*/ { +/*N*/ /// OD 02.10.2002 #102646# - NOTE +/*N*/ /// local variable <nRel> for calculation of relative vertical +/*N*/ /// distance to anchor. +/*N*/ SwTwips nRel; +/*N*/ if( pAutoPos && REL_CHAR == aVert.GetRelationOrient() ) +/*N*/ { +/*N*/ nRel = (*fnRect->fnYDiff)( (pAutoPos->*fnRect->fnGetBottom)(), +/*N*/ (pAutoOrient->Frm().*fnRect->fnGetTop)() ); +/*N*/ nRel -= aVert.GetPos(); +/*N*/ if( pAutoOrient != GetAnchor() ) +/*N*/ { +/*N*/ SwTxtFrm* pTmp = (SwTxtFrm*)GetAnchor(); +/*N*/ SWREFRESHFN( pTmp ) +/*N*/ nRel -=(*fnRect->fnYDiff)((pTmp->Frm().*fnRect->fnGetTop)(), +/*N*/ (pTmp->GetUpper()->*fnRect->fnGetPrtTop)()); +/*N*/ while( pTmp != pAutoOrient ) +/*N*/ { +/*N*/ SWREFRESHFN( pTmp ) +/*N*/ nRel +=(pTmp->GetUpper()->Prt().*fnRect->fnGetHeight)(); +/*N*/ pTmp = pTmp->GetFollow(); +/*N*/ } +/*N*/ SWREFRESHFN( pTmp ) +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ /// OD 02.10.2002 #102646# +/*N*/ /// consider that vertical position can be relativ to "margin" +/*N*/ /// or to "text area". +/*N*/ /// Thus, increase <nRel> by margin height, if position is +/*N*/ /// vertical to "text area" +/*N*/ nRel = aVert.GetPos(); +/*N*/ if ( aVert.GetRelationOrient() == PRTAREA ) +/*N*/ { +/*N*/ nRel += (pAutoOrient->*fnRect->fnGetTopMargin)(); +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ // Einen einspaltigen Bereich koennen wir getrost ignorieren, +/*N*/ // er hat keine Auswirkung auf die Fly-Position +/*N*/ while( pOrient->IsSctFrm() ) +/*N*/ pOrient = pOrient->GetUpper(); +/*N*/ //pOrient ist das LayoutBlatt, das gerade verfolgt wird. +/*N*/ //nRel enthaelt die noch zu verarbeitende relative Entfernung. +/*N*/ //nAvail enthaelt die Strecke die im LayoutBlatt, das gerade +/*N*/ // verfolgt wird zur Verfuegung steht. +/*N*/ +/*N*/ if( nRel <= 0 ) +/*N*/ { +/*N*/ if( bVert ) +/*N*/ aRelPos.X() = 0; +/*N*/ else +/*N*/ aRelPos.Y() = 0; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SWREFRESHFN( GetAnchor() ) +/*N*/ SwTwips nAvail = +/*N*/ (*fnRect->fnYDiff)( (pOrient->*fnRect->fnGetPrtBottom)(), +/*N*/ (GetAnchor()->Frm().*fnRect->fnGetTop)()); +/*N*/ const BOOL bFtn = GetAnchor()->IsInFtn(); +/*N*/ while ( nRel ) +/*N*/ { if ( nRel <= nAvail || +/*N*/ (bBrowse && +/*N*/ ((SwFrm*)pOrient)->Grow( nRel-nAvail, TRUE)) || +/*N*/ (pOrient->IsInTab() && bGrow && +/*N*/ ((SwFrm*)pOrient)->Grow( nRel-nAvail, TRUE))) +/*N*/ { +/*N*/ if( bVert ) +/*N*/ aRelPos.X() = GetAnchor()->Frm().Left() + +/*N*/ GetAnchor()->Frm().Width() - +/*N*/ pOrient->Frm().Left() - +/*N*/ pOrient->Prt().Left() - nAvail + nRel; +/*N*/ else +/*N*/ aRelPos.Y() = pOrient->Frm().Top() + +/*N*/ pOrient->Prt().Top() + pOrient->Prt().Height() +/*N*/ - nAvail + nRel - GetAnchor()->Frm().Top(); +/*N*/ if ( ( bBrowse || ( pOrient->IsInTab() && bGrow ) ) +/*N*/ && nRel - nAvail > 0 ) +/*N*/ { +/*N*/ nRel = ((SwFrm*)pOrient)->Grow( nRel-nAvail ); +/*N*/ SwFrm *pTmp = (SwFrm*) pOrient->FindPageFrm(); +/*N*/ ::binfilter::ValidateSz( pTmp ); +/*N*/ bInvalidatePage = TRUE; +/*N*/ //Schon mal einstellen, weil wir wahrscheinlich +/*N*/ //wegen Invalidierung eine Ehrenrunde drehen. +/*N*/ if( bVert ) +/*N*/ aFrm.Pos().X() = aFrm.Left() - nRel; +/*N*/ else +/*N*/ aFrm.Pos().Y() = aFrm.Top() + nRel; +/*N*/ } +/*N*/ nRel = 0; +/*N*/ } +/*N*/ else if ( bMoveable ) +/*N*/ { //Dem Textfluss folgen. +/*N*/ nRel -= nAvail; +/*N*/ const BOOL bSct = pOrient->IsInSct(); +/*N*/ MakePageType eMakePage = bFtn ? MAKEPAGE_NONE +/*N*/ : MAKEPAGE_APPEND; +/*N*/ if( bSct ) +/*N*/ eMakePage = MAKEPAGE_NOSECTION; +/*N*/ const SwFrm *pTmp = pOrient-> +/*N*/ GetLeaf( eMakePage, TRUE, GetAnchor() ); +/*N*/ if ( pTmp && ( !bSct || pOrient->FindSctFrm()-> +/*N*/ IsAnFollow( pTmp->FindSctFrm() ) ) ) +/*N*/ { +/*N*/ pOrient = pTmp; +/*N*/ bMoveable = +/*N*/ ::binfilter::lcl_IsMoveable( this, (SwLayoutFrm*)pOrient); +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( pOrient ); +/*N*/ SWREFRESHFN( pOrient ) +/*N*/ nAvail = (pOrient->Prt().*fnRect->fnGetHeight)(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ // Wenn wir innerhalb des (spaltigen) Bereichs nicht genug +/*N*/ // Platz ist, wird es Zeit, diesen zu verlassen. Wir gehen +/*N*/ // also in seinen Upper und nehmen als nAvail den Platz, der +/*N*/ // hinter dem Bereich ist. Sollte dieser immer noch nicht +/*N*/ // ausreichen, wandern wir weiter, es hindert uns aber nun +/*N*/ // niemand mehr, neue Seiten anzulegen. +/*N*/ if( bSct ) +/*N*/ { +/*N*/ const SwFrm* pSct = pOrient->FindSctFrm(); +/*N*/ pOrient = pSct->GetUpper(); +/*N*/ nAvail = (*fnRect->fnYDiff)( +/*N*/ (pOrient->*fnRect->fnGetPrtBottom)(), +/*N*/ (pSct->*fnRect->fnGetPrtBottom)() ); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ nRelDiff = nRel; +/*N*/ nRel = 0; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ nRel = 0; +/*N*/ } +/*N*/ if ( !bValidPos ) +/*N*/ continue; +/*N*/ } +/*N*/ } +/*N*/ //Damit das Teil ggf. auf die richtige Seite gestellt und in die +/*N*/ //PrtArea des LayLeaf gezogen werden kann, muss hier seine +/*N*/ //absolute Position berechnet werden. +/*N*/ if( bVert ) +/*N*/ { +/*N*/ aFrm.Pos().X() = GetAnchor()->Frm().Left() - aFrm.Width() + +/*N*/ GetAnchor()->Frm().Width() - aRelPos.X() +nRelDiff; +/*N*/ } +/*N*/ else +/*N*/ aFrm.Pos().Y() = GetAnchor()->Frm().Top() + +/*N*/ (aRelPos.Y() - nRelDiff); +/*N*/ +/*N*/ //Bei automatischer Ausrichtung nicht ueber die Oberkante hinausschiessen. +/*N*/ if ( aVert.GetVertOrient() != VERT_NONE ) +/*N*/ { +/*N*/ SwTwips nTop; +/*N*/ if ( aVert.GetRelationOrient() == PRTAREA ) +/*N*/ nTop = (pOrient->*fnRect->fnGetPrtTop)(); +/*N*/ else +/*N*/ nTop = (pOrient->Frm().*fnRect->fnGetTop)(); +/*N*/ SwTwips nTmp = (Frm().*fnRect->fnGetTop)(); +/*N*/ if( (nTmp = (fnRect->fnYDiff)( nTmp, nTop ) ) < 0 ) +/*N*/ { +/*N*/ if( bVert ) +/*N*/ { +/*N*/ aFrm.Pos().X() += nTmp; +/*N*/ aRelPos.X() = nTop - GetAnchor()->Frm().Left() +/*N*/ - GetAnchor()->Frm().Width(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ aFrm.Pos().Y() = nTop; +/*N*/ aRelPos.Y() = nTop - GetAnchor()->Frm().Top(); +/*N*/ } +/*N*/ bHeightClipped = TRUE; +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ const BOOL bFtn = GetAnchor()->IsInFtn(); +/*N*/ while( pOrient->IsSctFrm() ) +/*N*/ pOrient = pOrient->GetUpper(); +/*N*/ SwTwips nDist = (aFrm.*fnRect->fnBottomDist)( +/*N*/ (pOrient->*fnRect->fnGetPrtBottom)() ); +/*N*/ if( nDist < 0 ) +/*N*/ { +/*N*/ if( ( bBrowse && GetAnchor()->IsMoveable() ) || +/*N*/ ( GetAnchor()->IsInTab() && bGrow ) ) +/*N*/ { +/*N*/ ((SwFrm*)pOrient)->Grow( -nDist ); +/*N*/ SwFrm *pTmp = (SwFrm*) pOrient->FindPageFrm(); +/*N*/ ::binfilter::ValidateSz( pTmp ); +/*N*/ bInvalidatePage = TRUE; +/*N*/ } +/*N*/ +/*N*/ nDist = (aFrm.*fnRect->fnBottomDist)( +/*N*/ (pOrient->*fnRect->fnGetPrtBottom)() ); +/*N*/ while( bMoveable && nDist < 0 ) +/*N*/ { +/*N*/ // Vorsicht, auch innerhalb von Bereichen duerfen keine neuen Seiten angelegt werden +/*N*/ BOOL bSct = pOrient->IsInSct(); +/*N*/ if( bSct ) +/*N*/ { +/*N*/ const SwFrm* pTmp = pOrient->FindSctFrm()->GetUpper(); +/*N*/ nDist = (aFrm.*fnRect->fnBottomDist)( +/*N*/ (pTmp->*fnRect->fnGetPrtBottom)() ); +/*N*/ if( nDist < 0 ) +/*N*/ pOrient = pTmp; +/*N*/ else +/*N*/ break; +/*N*/ bSct = pOrient->IsInSct(); +/*N*/ } +/*N*/ if( !bSct && (Frm().*fnRect->fnGetTop)() == +/*N*/ (pOrient->*fnRect->fnGetPrtTop)() ) +/*N*/ //Das teil passt nimmer, da hilft auch kein moven. +/*N*/ break; +/*N*/ +/*N*/ const SwLayoutFrm *pNextLay = pOrient->GetLeaf( bSct ? +/*N*/ MAKEPAGE_NOSECTION : bFtn ? MAKEPAGE_NONE : MAKEPAGE_APPEND, +/*N*/ TRUE, GetAnchor() ); +/*N*/ if( pNextLay ) +/*N*/ { +/*N*/ SWRECTFNX( pNextLay ) +/*N*/ if( !bSct || ( pOrient->FindSctFrm()->IsAnFollow( +/*N*/ pNextLay->FindSctFrm() ) && +/*N*/ (pNextLay->Prt().*fnRectX->fnGetHeight)() ) ) +/*N*/ { +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( pNextLay ); +/*N*/ if( bVertX ) +/*N*/ aRelPos.X() = GetAnchor()->Frm().Left() + +/*N*/ GetAnchor()->Frm().Width() - +/*N*/ pNextLay->Frm().Left() - +/*N*/ pNextLay->Prt().Left()- +/*N*/ pNextLay->Prt().Width(); +/*N*/ else +/*N*/ aRelPos.Y() = pNextLay->Frm().Top() + +/*N*/ pNextLay->Prt().Top() -GetAnchor()->Frm().Top(); +/*N*/ pOrient = pNextLay; +/*N*/ SWREFRESHFN( pOrient ) +/*N*/ bMoveable = ::binfilter::lcl_IsMoveable( this, +/*N*/ (SwLayoutFrm*)pOrient ); +/*N*/ if ( bMoveable && !pFooter ) +/*N*/ ::binfilter::DeepCalc( pOrient ); +/*N*/ if( bVertX ) +/*N*/ aFrm.Pos().X() = GetAnchor()->Frm().Left() +/*N*/ + GetAnchor()->Frm().Width() +/*N*/ - aRelPos.X() - aFrm.Width(); +/*N*/ else +/*N*/ aFrm.Pos().Y() = GetAnchor()->Frm().Top() +/*N*/ + aRelPos.Y(); +/*N*/ nDist = (aFrm.*fnRect->fnBottomDist)( +/*N*/ (pOrient->*fnRect->fnGetPrtBottom)() ); +/*N*/ } +/*N*/ } +/*N*/ else if( bSct ) +/*N*/ { +/*N*/ // Wenn wir innerhalb des Bereich nicht genug Platz haben, gucken +/*N*/ // wir uns mal die Seite an. +/*N*/ const SwFrm* pTmp = pOrient->FindSctFrm()->GetUpper(); +/*N*/ nDist = (aFrm.*fnRect->fnBottomDist)( +/*N*/ (pTmp->*fnRect->fnGetPrtBottom)() ); +/*N*/ if( nDist < 0 ) +/*N*/ pOrient = pTmp; +/*N*/ else +/*N*/ break; +/*N*/ } +/*N*/ else +/*N*/ bMoveable = FALSE; +/*N*/ } +/*N*/ } +/*N*/ AssertPage(); +/*N*/ +/*N*/ //Horizontale Ausrichtung. +/*N*/ //Die absolute Pos in der vertikalen muss schon mal eingestellt +/*N*/ //werden, sonst habe ich Schwierigkeiten den virtuellen Anker +/*N*/ //zu ermitteln. +/*N*/ if( bVert ) +/*N*/ aFrm.Pos().X() = GetAnchor()->Frm().Left() - aFrm.Width() + +/*N*/ GetAnchor()->Frm().Width() - aRelPos.X(); +/*N*/ else +/*N*/ aFrm.Pos().Y() = aRelPos.Y() + GetAnchor()->Frm().Top(); +/*N*/ //Den Frm besorgen, an dem sich die horizontale Ausrichtung orientiert. +/*N*/ pOrient = ::binfilter::GetVirtualHoriAnchor( pOrient, this ); +/*N*/ +/*N*/ if( !pFooter ) +/*N*/ ::binfilter::DeepCalc( pOrient ); +/*N*/ +/*N*/ // Achtung: pPage ist nicht unbedingt ein PageFrm, es kann auch ein +/*N*/ // SwFlyFrm oder SwCellFrm dahinterstecken +/*N*/ const SwFrm *pPage = pOrient; +/*N*/ while( !pPage->IsPageFrm() && !pPage->IsFlyFrm() && !pPage->IsCellFrm() ) +/*N*/ { +/*N*/ ASSERT( pPage->GetUpper(), "MakeFlyPos: No Page/FlyFrm Found" ); +/*N*/ pPage = pPage->GetUpper(); +/*N*/ } +/*N*/ +/*N*/ const BOOL bEven = !pPage->OnRightPage(); +/*N*/ const BOOL bToggle = aHori.IsPosToggle() && bEven; +/*N*/ BOOL bTmpToggle = bToggle; +/*N*/ BOOL bPageRel = FALSE; +/*N*/ SwTwips nWidth, nAdd; +/*N*/ SWREFRESHFN( pOrient ) +/*N*/ switch ( aHori.GetRelationOrient() ) +/*N*/ { +/*N*/ case PRTAREA: +/*N*/ { +/*N*/ nWidth = (pOrient->Prt().*fnRect->fnGetWidth)(); +/*N*/ nAdd = (pOrient->*fnRect->fnGetLeftMargin)(); +/*N*/ if ( pOrient->IsTxtFrm() ) +/*N*/ nAdd += ((SwTxtFrm*)pOrient)->GetBaseOfstForFly( !bWrapThrough ); +/*N*/ break; +/*N*/ } +/*N*/ case REL_PG_LEFT: +/*N*/ bTmpToggle = !bToggle; +/*N*/ // kein break; +/*N*/ case REL_PG_RIGHT: +/*N*/ { +/*N*/ if ( bTmpToggle ) // linker Seitenrand +/*N*/ { +/*N*/ nAdd = (*fnRect->fnXDiff)((pPage->Frm().*fnRect->fnGetLeft)(), +/*N*/ (pOrient->Frm().*fnRect->fnGetLeft)()); +/*N*/ nWidth = (pPage->*fnRect->fnGetLeftMargin)(); +/*N*/ } +/*N*/ else // rechter Seitenrand +/*N*/ { +/*N*/ nAdd = (*fnRect->fnXDiff)((pPage->*fnRect->fnGetPrtRight)(), +/*N*/ (pOrient->Frm().*fnRect->fnGetLeft)()); +/*N*/ nWidth = (pPage->*fnRect->fnGetRightMargin)(); +/*N*/ } +/*N*/ bPageRel = TRUE; +/*N*/ break; +/*N*/ } +/*N*/ case REL_FRM_LEFT: +/*N*/ bTmpToggle = !bToggle; +/*N*/ // kein break; +/*N*/ case REL_FRM_RIGHT: +/*N*/ { +/*N*/ if ( bTmpToggle ) // linker Absatzrand +/*N*/ { +/*N*/ nWidth = (pOrient->*fnRect->fnGetLeftMargin)(); +/*N*/ nAdd = 0; +/*N*/ } +/*N*/ else // rechter Absatzrand +/*N*/ { +/*N*/ nWidth = (pOrient->*fnRect->fnGetRightMargin)(); +/*N*/ nAdd = (pOrient->Frm().*fnRect->fnGetWidth)()-nWidth; +/*N*/ } +/*N*/ break; +/*N*/ } +/*N*/ case REL_CHAR: +/*N*/ { +/*N*/ if( pAutoPos ) +/*N*/ { +/*N*/ nWidth = 0; +/*N*/ nAdd = (*fnRect->fnXDiff)( (pAutoPos->*fnRect->fnGetLeft)(), +/*N*/ (pAutoOrient->Frm().*fnRect->fnGetLeft)() ); +/*N*/ break; +/*N*/ } +/*N*/ // No Break! +/*N*/ } +/*N*/ case REL_PG_PRTAREA: +/*N*/ { +/*N*/ nWidth = (pPage->Prt().*fnRect->fnGetWidth)(); +/*N*/ nAdd = (*fnRect->fnXDiff)( (pPage->*fnRect->fnGetPrtLeft)(), +/*N*/ (pOrient->Frm().*fnRect->fnGetLeft)()); +/*N*/ bPageRel = TRUE; +/*N*/ break; +/*N*/ } +/*N*/ case REL_PG_FRAME: +/*N*/ { +/*N*/ nWidth = (pPage->Frm().*fnRect->fnGetWidth)(); +/*N*/ nAdd = (*fnRect->fnXDiff)( (pPage->Frm().*fnRect->fnGetLeft)(), +/*N*/ (pOrient->Frm().*fnRect->fnGetLeft)()); +/*N*/ bPageRel = TRUE; +/*N*/ break; +/*N*/ } +/*N*/ default: +/*N*/ { +/*N*/ nWidth = (pOrient->Frm().*fnRect->fnGetWidth)(); +/*N*/ nAdd = pOrient->IsTxtFrm() ? +/*N*/ ((SwTxtFrm*)pOrient)->GetBaseOfstForFly( !bWrapThrough ) : +/*N*/ 0; +/*N*/ break; +/*N*/ } +/*N*/ } +/*N*/ SwTwips nRelPosX = nAdd; +/*N*/ sal_Bool bR2L = GetAnchor()->IsRightToLeft(); +/*N*/ if ( aHori.GetHoriOrient() == HORI_NONE ) +/*N*/ { +/*N*/ if( pAutoPos && REL_CHAR == aHori.GetRelationOrient() ) +/*N*/ { +/*N*/ if( bR2L ) +/*N*/ nRelPosX -= aHori.GetPos(); +/*N*/ else +/*N*/ nRelPosX += aHori.GetPos(); +/*N*/ } +/*N*/ else if( bToggle || ( !aHori.IsPosToggle() && bR2L ) ) +/*N*/ nRelPosX = nWidth - aFrm.Width() - aHori.GetPos() + +/*N*/ ( bR2L ? nAdd : 0 ); +/*N*/ else +/*N*/ nRelPosX += aHori.GetPos(); +/*N*/ //Da die relative Position immer zum Anker relativ ist, +/*N*/ //muss dessen Entfernung zum virtuellen Anker aufaddiert werden. +/*N*/ if ( GetAnchor() != pOrient ) +/*N*/ { +/*N*/ long nTmp = (pOrient->Frm().*fnRect->fnGetLeft)(); +/*N*/ nRelPosX += (*fnRect->fnXDiff)( nTmp, +/*N*/ (GetAnchor()->Frm().*fnRect->fnGetLeft)() ); +/*N*/ //fix(18546): Kleine Notbremse, wenn der Rahmen jetzt so positioniert +/*N*/ //wird, dass er den Anker verdraengt, muessen wir unbedingt agieren. +/*N*/ //fix(22698): in Ergaenzung zu obigem Bug passen wir jetzt etwas +/*N*/ //grundlicher auf. +/*N*/ if( bVert ) +/*N*/ { +/*N*/ if( !bPageRel && nTmp > pAnchor->Frm().Bottom() && +/*N*/ Frm().Right() > GetAnchor()->Frm().Left() ) +/*N*/ { +/*N*/ nTmp = nRelPosX + GetAnchor()->Frm().Top(); +/*N*/ if( nTmp < GetAnchor()->Frm().Bottom() ) +/*N*/ nRelPosX = GetAnchor()->Frm().Height() + 1; +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ if( !bPageRel && nTmp > pAnchor->Frm().Right() && +/*N*/ Frm().Top() < GetAnchor()->Frm().Bottom() ) +/*N*/ { +/*N*/ nTmp = aRelPos.X() + GetAnchor()->Frm().Left(); +/*N*/ if ( nTmp < GetAnchor()->Frm().Right() ) +/*N*/ nRelPosX = GetAnchor()->Frm().Width()+1; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if( bVert ) +/*N*/ { +/*N*/ if( GetAnchor()->Frm().Top() + nRelPosX + aFrm.Height() > +/*N*/ pPage->Frm().Bottom() ) +/*N*/ nRelPosX = pPage->Frm().Bottom() - GetAnchor()->Frm().Top() +/*N*/ - aFrm.Height(); +/*N*/ if( GetAnchor()->Frm().Top() + nRelPosX < pPage->Frm().Top() ) +/*N*/ nRelPosX = pPage->Frm().Top() - GetAnchor()->Frm().Top(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ if( GetAnchor()->Frm().Left() + nRelPosX + aFrm.Width() > +/*N*/ pPage->Frm().Right() ) +/*N*/ nRelPosX = pPage->Frm().Right() - +/*N*/ GetAnchor()->Frm().Left() - aFrm.Width(); +/*N*/ if( GetAnchor()->Frm().Left() + nRelPosX < pPage->Frm().Left() ) +/*N*/ nRelPosX = pPage->Frm().Left() - GetAnchor()->Frm().Left(); +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SwHoriOrient eHOri = aHori.GetHoriOrient(); +/*N*/ SwRelationOrient eRelO = aHori.GetRelationOrient(); +/*N*/ if( bToggle ) +/*N*/ { +/*N*/ if( HORI_RIGHT == eHOri ) +/*N*/ eHOri = HORI_LEFT; +/*N*/ else if( HORI_LEFT == eHOri ) +/*N*/ eHOri = HORI_RIGHT; +/*N*/ if( REL_PG_RIGHT == eRelO ) +/*N*/ eRelO = REL_PG_LEFT; +/*N*/ else if( REL_PG_LEFT == eRelO ) +/*N*/ eRelO = REL_PG_RIGHT; +/*N*/ else if( REL_FRM_RIGHT == eRelO ) +/*N*/ eRelO = REL_FRM_LEFT; +/*N*/ else if( REL_FRM_LEFT == eRelO ) +/*N*/ eRelO = REL_FRM_RIGHT; +/*N*/ } +/*N*/ if( bVert ) +/*N*/ { +/*N*/ if ( eHOri == HORI_CENTER ) +/*N*/ nRelPosX = (nWidth / 2) - (aFrm.Height() / 2); +/*N*/ else if ( eHOri == HORI_RIGHT ) +/*N*/ nRelPosX = nWidth - (aFrm.Height() + rUL.GetLower()); +/*N*/ else +/*N*/ nRelPosX = rUL.GetUpper(); +/*N*/ nRelPosX += nAdd; +/*N*/ +/*N*/ if( GetAnchor() != pOrient ) +/*N*/ nRelPosX += pOrient->Frm().Top() - +/*N*/ GetAnchor()->Frm().Top(); +/*N*/ +/*N*/ if( GetAnchor()->Frm().Top() + nRelPosX + aFrm.Height() > +/*N*/ pPage->Frm().Bottom() ) +/*N*/ nRelPosX = pPage->Frm().Bottom() - GetAnchor()->Frm().Top() +/*N*/ - aFrm.Height(); +/*N*/ if( GetAnchor()->Frm().Top() + nRelPosX < pPage->Frm().Top() ) +/*N*/ nRelPosX = pPage->Frm().Top() - GetAnchor()->Frm().Top(); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ if ( eHOri == HORI_CENTER ) +/*N*/ nRelPosX = (nWidth / 2) - (aFrm.Width() / 2); +/*N*/ else if ( eHOri == HORI_RIGHT ) +/*N*/ nRelPosX = nWidth - (aFrm.Width() + rLR.GetRight()); +/*N*/ else +/*N*/ nRelPosX = rLR.GetLeft(); +/*N*/ nRelPosX += nAdd; +/*N*/ +/*N*/ //Da die relative Position immer zum Anker relativ ist, +/*N*/ //muss dessen Entfernung zum virtuellen Anker aufaddiert werden. +/*N*/ if( GetAnchor() != pOrient ) +/*N*/ nRelPosX += pOrient->Frm().Left() - +/*N*/ GetAnchor()->Frm().Left(); +/*N*/ if( GetAnchor()->Frm().Left() + nRelPosX + aFrm.Width() > +/*N*/ pPage->Frm().Right() ) +/*N*/ nRelPosX = pPage->Frm().Right() - GetAnchor()->Frm().Left() +/*N*/ - aFrm.Width(); +/*N*/ if( GetAnchor()->Frm().Left() + nRelPosX < pPage->Frm().Left() ) +/*N*/ nRelPosX = pPage->Frm().Left() - GetAnchor()->Frm().Left(); +/*N*/ } +/*N*/ +/*N*/ //Es muss allen Rahmen ausgewichen werden, die die selbe +/*N*/ //automatische Ausrichtung haben und die unter dem Rahmen liegen. +/*N*/ if ( HORI_CENTER != eHOri && REL_CHAR != eRelO ) +/*N*/ { +/*N*/ Point aTmpPos = (GetAnchor()->Frm().*fnRect->fnGetPos)(); +/*N*/ if( bVert ) +/*N*/ { +/*N*/ aTmpPos.X() -= aRelPos.X() + aFrm.Width(); +/*N*/ aTmpPos.Y() += nRelPosX; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ aTmpPos.X() += nRelPosX; +/*N*/ aTmpPos.Y() += aRelPos.Y(); +/*N*/ } +/*N*/ SwRect aTmpFrm( aTmpPos, Frm().SSize() ); +/*N*/ const UINT32 nMyOrd = GetVirtDrawObj()->GetOrdNum(); +/*N*/ const SwPageFrm *pPage = FindPageFrm(); +/*N*/ SwOrderIter aIter( pPage, TRUE ); +/*N*/ const SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)aIter.Bottom())->GetFlyFrm(); +/*N*/ const SwFrm *pKontext = ::binfilter::FindKontext( GetAnchor(), FRM_COLUMN ); +/*N*/ ULONG nMyIndex = ((SwTxtFrm*)GetAnchor())->GetTxtNode()->GetIndex(); +/*N*/ while ( pFly && nMyOrd > pFly->GetVirtDrawObj()->GetOrdNumDirect() ) +/*N*/ { +/*N*/ if ( pFly->IsFlyAtCntFrm() && //pFly->IsValid() && +/*N*/ (pFly->Frm().*fnRect->fnBottomDist)( +/*N*/ (aTmpFrm.*fnRect->fnGetTop)() ) < 0 && +/*N*/ (aTmpFrm.*fnRect->fnBottomDist)( +/*N*/ (pFly->Frm().*fnRect->fnGetTop)() ) < 0 && +/*N*/ ::binfilter::FindKontext( pFly->GetAnchor(), FRM_COLUMN ) == pKontext ) +/*N*/ { +/*N*/ ULONG nOtherIndex = ((SwTxtFrm*)pFly->GetAnchor()) +/*N*/ ->GetTxtNode()->GetIndex(); +/*N*/ if( nMyIndex >= nOtherIndex ) +/*N*/ { +/*N*/ const SwFmtHoriOrient &rHori = +/*N*/ pFly->GetFmt()->GetHoriOrient(); +/*N*/ SwRelationOrient eRelO2 = rHori.GetRelationOrient(); +/*N*/ if( REL_CHAR != eRelO2 ) +/*N*/ { +/*N*/ SwHoriOrient eHOri2 = rHori.GetHoriOrient(); +/*N*/ if( bEven && rHori.IsPosToggle() ) +/*N*/ { +/*N*/ if( HORI_RIGHT == eHOri2 ) +/*N*/ eHOri2 = HORI_LEFT; +/*N*/ else if( HORI_LEFT == eHOri2 ) +/*N*/ eHOri2 = HORI_RIGHT; +/*N*/ if( REL_PG_RIGHT == eRelO2 ) +/*N*/ eRelO2 = REL_PG_LEFT; +/*N*/ else if( REL_PG_LEFT == eRelO2 ) +/*N*/ eRelO2 = REL_PG_RIGHT; +/*N*/ else if( REL_FRM_RIGHT == eRelO2 ) +/*N*/ eRelO2 = REL_FRM_LEFT; +/*N*/ else if( REL_FRM_LEFT == eRelO2 ) +/*N*/ eRelO2 = REL_FRM_RIGHT; +/*N*/ } +/*N*/ if ( eHOri2 == eHOri && +/*N*/ lcl_Minor( eRelO, eRelO2, HORI_LEFT == eHOri ) ) +/*N*/ { +/*N*/ //Die Berechnung wird dadurch etwas aufwendiger, das die +/*N*/ //Ausgangsbasis der Flys unterschiedlich sein koennen. +/*N*/ if( bVert ) +/*N*/ { +/*N*/ const SvxULSpaceItem &rULI = pFly->GetFmt()->GetULSpace(); +/*N*/ const SwTwips nFlyTop = pFly->Frm().Top() - rULI.GetUpper(); +/*N*/ const SwTwips nFlyBot = pFly->Frm().Bottom() + rULI.GetLower(); +/*N*/ if( nFlyTop <= aTmpFrm.Bottom() + rUL.GetLower() && +/*N*/ nFlyBot >= aTmpFrm.Top() - rUL.GetUpper() ) +/*N*/ { +/*N*/ if ( eHOri == HORI_LEFT ) +/*N*/ { +/*N*/ SwTwips nTmp = nFlyBot + 1 +/*N*/ + rUL.GetUpper() +/*N*/ - GetAnchor()->Frm().Top(); +/*N*/ if( nTmp > nRelPosX && +/*N*/ nTmp + Frm().Height() + +/*N*/ GetAnchor()->Frm().Top() + +/*N*/ rUL.GetLower() <= +/*N*/ pPage->Frm().Height() + +/*N*/ pPage->Frm().Top() ) +/*N*/ { +/*N*/ nRelPosX = nTmp; +/*N*/ } +/*N*/ } +/*N*/ else if ( eHOri == HORI_RIGHT ) +/*N*/ { +/*N*/ SwTwips nTmp = nFlyTop - 1 +/*N*/ - rUL.GetLower() +/*N*/ - Frm().Height() +/*N*/ - GetAnchor()->Frm().Top(); +/*N*/ if( nTmp < nRelPosX && +/*N*/ nTmp - rUL.GetUpper() + +/*N*/ GetAnchor()->Frm().Top() +/*N*/ >= pPage->Frm().Top() ) +/*N*/ { +/*N*/ nRelPosX = nTmp; +/*N*/ } +/*N*/ } +/*N*/ aTmpFrm.Pos().Y() = GetAnchor()->Frm().Top() + nRelPosX; +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ const SvxLRSpaceItem &rLRI = pFly->GetFmt()->GetLRSpace(); +/*N*/ const SwTwips nFlyLeft = pFly->Frm().Left() - rLRI.GetLeft(); +/*N*/ const SwTwips nFlyRight = pFly->Frm().Right() + rLRI.GetRight(); +/*N*/ if( nFlyLeft <= aTmpFrm.Right() + rLR.GetRight() && +/*N*/ nFlyRight >= aTmpFrm.Left() - rLR.GetLeft() ) +/*N*/ { +/*N*/ if ( eHOri == HORI_LEFT ) +/*N*/ { +/*N*/ SwTwips nTmp = nFlyRight + 1 +/*N*/ + rLR.GetLeft() +/*N*/ - GetAnchor()->Frm().Left(); +/*N*/ if( nTmp > nRelPosX && +/*N*/ nTmp + Frm().Width() + +/*N*/ GetAnchor()->Frm().Left() + +/*N*/ rLR.GetRight() <= +/*N*/ pPage->Frm().Width() + +/*N*/ pPage->Frm().Left() ) +/*N*/ { +/*N*/ nRelPosX = nTmp; +/*N*/ } +/*N*/ } +/*N*/ else if ( eHOri == HORI_RIGHT ) +/*N*/ { +/*N*/ SwTwips nTmp = nFlyLeft - 1 +/*N*/ - rLR.GetRight() +/*N*/ - Frm().Width() +/*N*/ - GetAnchor()->Frm().Left(); +/*N*/ if( nTmp < nRelPosX && +/*N*/ nTmp - rLR.GetLeft() + +/*N*/ GetAnchor()->Frm().Left() +/*N*/ >= pPage->Frm().Left() ) +/*N*/ { +/*N*/ nRelPosX = nTmp; +/*N*/ } +/*N*/ } +/*N*/ aTmpFrm.Pos().X() = GetAnchor()->Frm().Left() + nRelPosX; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ pFly = ((SwVirtFlyDrawObj*)aIter.Next())->GetFlyFrm(); +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ if ( aHori.GetPos() != nRelPosX ) +/*N*/ { aHori.SetPos( nRelPosX ); +/*N*/ bHoriChgd = TRUE; +/*N*/ } +/*N*/ } +/*N*/ if( bVert ) +/*N*/ aRelPos.Y() = nRelPosX; +/*N*/ else +/*N*/ aRelPos.X() = nRelPosX; +/*N*/ AssertPage(); +/*N*/ +/*N*/ //Die AbsPos ergibt sich aus der Absoluten Position des Ankers +/*N*/ //plus der relativen Position +/*N*/ if( bVert ) +/*N*/ { +/*N*/ aFrm.Pos().X() = GetAnchor()->Frm().Left() + +/*N*/ GetAnchor()->Frm().Width() - +/*N*/ aFrm.Width() - aRelPos.X(); +/*N*/ aFrm.Pos().Y() = GetAnchor()->Frm().Top() + aRelPos.Y(); +/*N*/ AssertPage(); +/*N*/ } +/*N*/ else +/*N*/ aFrm.Pos( aRelPos + GetAnchor()->Frm().Pos() ); +/*N*/ //Und ggf. noch die aktuellen Werte im Format updaten, dabei darf +/*N*/ //zu diesem Zeitpunkt natuerlich kein Modify verschickt werden. +/*N*/ pFmt->LockModify(); +/*N*/ if ( bVertChgd ) +/*N*/ pFmt->SetAttr( aVert ); +/*N*/ if ( bHoriChgd ) +/*N*/ pFmt->SetAttr( aHori ); +/*N*/ pFmt->UnlockModify(); +/*N*/ +/*N*/ break; +/*N*/ } /// OD 02.10.2002 #102646# - End of loop +/*N*/ +/*N*/ if ( bInvalidatePage ) +/*N*/ FindPageFrm()->InvalidateSize(); +/*N*/ if ( !bValidPos && !GetAnchor()->IsValid() ) +/*N*/ { +/*N*/ // ASSERT( StackHack::IsLocked(), "invalid Anchor" ); +/*N*/ bValidPos = TRUE; +/*N*/ } +/*N*/ } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |