diff options
Diffstat (limited to 'bf_sw/source/core/layout/sw_trvlfrm.cxx')
-rw-r--r-- | bf_sw/source/core/layout/sw_trvlfrm.cxx | 673 |
1 files changed, 673 insertions, 0 deletions
diff --git a/bf_sw/source/core/layout/sw_trvlfrm.cxx b/bf_sw/source/core/layout/sw_trvlfrm.cxx new file mode 100644 index 000000000..54b363ab5 --- /dev/null +++ b/bf_sw/source/core/layout/sw_trvlfrm.cxx @@ -0,0 +1,673 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#ifdef _MSC_VER +#pragma hdrstop +#endif + + +#include <hintids.hxx> + +#include <tools/bigint.hxx> +#include <bf_svx/protitem.hxx> +#include <fmtpdsc.hxx> +#include <pagedesc.hxx> + +#include <pagefrm.hxx> +#include <ftnfrm.hxx> + +#include <horiornt.hxx> + +#include <flyfrm.hxx> +#include <tabfrm.hxx> +#include <txtfrm.hxx> +#include <doc.hxx> +#include <pam.hxx> +#include <swtable.hxx> +#include <crstate.hxx> +#include <frmtool.hxx> +#include <hints.hxx> + +namespace binfilter { + + +/************************************************************************* +|* +|* SwFlyFrm::GetCrsrOfst() +|* +|*************************************************************************/ +//Problem: Wenn zwei Flys genau gleich gross sind und auf derselben +//Position stehen, so liegt jeder innerhalb des anderen. +//Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines +//anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet +//und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer +//endlosen Rekursion fuehren. +//Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das +//GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der +//am weitesten oben liegt. + + +/************************************************************************* +|* +|* Beschreibung Layoutabhaengiges Cursortravelling +|* +|*************************************************************************/ + + +/*N*/ const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt ) +/*N*/ { +/*N*/ return pCnt->GetNextCntntFrm(); +/*N*/ } + + +/*N*/ typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* ); + + +//Ueberspringen geschuetzter Tabellenzellen. Optional auch +//Ueberspringen von wiederholten Headlines. +//MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen. +const SwCntntFrm * MA_FASTCALL lcl_MissProtectedFrames( + const SwCntntFrm *pCnt, + GetNxtPrvCnt fnNxtPrv, + bool /* bMissHeadline */, + bool bInReadOnly +) +{ + if ( pCnt && pCnt->IsInTab() ) + { + BOOL bProtect = TRUE; + while ( pCnt && bProtect ) + { + const SwLayoutFrm *pCell = pCnt->GetUpper(); + while ( pCell && !pCell->IsCellFrm() ) + pCell = pCell->GetUpper(); + + if ( !pCell + || ( bInReadOnly + || !pCell->GetFmt()->GetProtect().IsCntntProtected() + ) + ) + bProtect = FALSE; + else + pCnt = (*fnNxtPrv)( pCnt ); + } + } + else if ( !bInReadOnly ) + while ( pCnt && pCnt->IsProtected() ) + pCnt = (*fnNxtPrv)( pCnt ); + + return pCnt; +} + + + + +/************************************************************************* +|* +|* SwLayoutFrm::GetCntntPos() +|* +|* Beschreibung Es wird der nachstliegende Cntnt zum uebergebenen +|* gesucht. Betrachtet werden die vorhergehende, die +|* aktuelle und die folgende Seite. +|* Wenn kein Inhalt gefunden wird, so wird der Bereich + * erweitert bis einer gefunden wird. +|* Zurueckgegeben wird die 'Semantisch richtige' Position +|* innerhalb der PrtArea des gefundenen CntntFrm +|* +|*************************************************************************/ +/*N*/ ULONG CalcDiff( const Point &rPt1, const Point &rPt2 ) +/*N*/ { +/*N*/ //Jetzt die Entfernung zwischen den beiden Punkten berechnen. +/*N*/ //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2 +/*N*/ sal_uInt32 dX = Max( rPt1.X(), rPt2.X() ) - +/*N*/ Min( rPt1.X(), rPt2.X() ), +/*N*/ dY = Max( rPt1.Y(), rPt2.Y() ) - +/*N*/ Min( rPt1.Y(), rPt2.Y() ); +/*N*/ BigInt dX1( dX ), dY1( dY ); +/*N*/ dX1 *= dX1; dY1 *= dY1; +/*N*/ return ::binfilter::SqRt( dX1 + dY1 ); +/*N*/ } + +// lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem +// auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang +// Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer. +// Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt, +// eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn +// dessen Abstand zum Punkt geringer ist. + +/*N*/ const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt ) +/*N*/ { +/*N*/ const SwLayoutFrm* pUp = pCnt->GetUpper(); +/*N*/ while( pUp ) +/*N*/ { +/*N*/ if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() ) +/*N*/ { +/*N*/ if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() ) +/*?*/ return pUp; +/*N*/ return NULL; +/*N*/ } +/*N*/ if( pUp->IsFtnContFrm() ) +/*?*/ return pUp->Frm().IsInside( rPt ) ? pUp : NULL; +/*N*/ pUp = pUp->GetUpper(); +/*N*/ } +/*?*/ return NULL; +/*N*/ } + +//Fuer MSC keine Optimierung mit e (enable register...) hier, sonst gibts +//einen Bug (ID: 2857) +/*N*/ #ifdef _MSC_VER +/*N*/ #pragma optimize("e",off) +/*N*/ #endif + +/*N*/ const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint, +/*N*/ const BOOL bDontLeave, +/*N*/ const BOOL bBodyOnly, +/*N*/ const BOOL bCalc, +/*N*/ const SwCrsrMoveState *pCMS, +/*N*/ const BOOL bDefaultExpand ) const +/*N*/ { +/*N*/ //Ersten CntntFrm ermitteln. +/*N*/ const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ? +/*N*/ (SwLayoutFrm*)GetPrev() : this; +/*N*/ const SwCntntFrm *pCntnt = pStart->ContainsCntnt(); +/*N*/ +/*N*/ if ( !pCntnt && (GetPrev() && !bDontLeave) ) +/*N*/ pCntnt = ContainsCntnt(); +/*N*/ +/*N*/ if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() ) +/*N*/ while ( pCntnt && !pCntnt->IsInDocBody() ) +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ +/*N*/ const SwCntntFrm *pActual= pCntnt; +/*N*/ const SwLayoutFrm *pInside = NULL; +/*N*/ USHORT nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0); +/*N*/ Point aPoint = rPoint; +/*N*/ ULONG nDistance = ULONG_MAX; +/*N*/ +/*N*/ while ( TRUE ) //Sicherheitsschleifchen, damit immer einer gefunden wird. +/*N*/ { +/*N*/ while ( pCntnt && +/*N*/ ((!bDontLeave || IsAnLower( pCntnt )) && +/*N*/ (pCntnt->GetPhyPageNum() <= nMaxPage)) ) +/*N*/ { +/*N*/ if ( ( bCalc || pCntnt->Frm().Width() ) && +/*N*/ ( !bBodyOnly || pCntnt->IsInDocBody() ) ) +/*N*/ { +/*N*/ //Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section) +/*N*/ //liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht. +/*N*/ const SwCntntFrm *pComp = pCntnt; +/*N*/ pCntnt = ::binfilter::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, FALSE, +/*N*/ pCMS ? pCMS->bSetInReadOnly : FALSE ); +/*N*/ if ( pComp != pCntnt ) +/*N*/ continue; +/*N*/ +/*N*/ if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() ) +/*N*/ { +/*N*/ if ( bCalc ) +/*N*/ pCntnt->Calc(); +/*N*/ +/*N*/ SwRect aCntFrm( pCntnt->UnionFrm() ); +/*N*/ if ( aCntFrm.IsInside( rPoint ) ) +/*N*/ { +/*N*/ pActual = pCntnt; +/*N*/ aPoint = rPoint; +/*N*/ break; +/*N*/ } +/*N*/ //Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird +/*N*/ //jetzt berechnet. +/*N*/ Point aCntntPoint( rPoint ); +/*N*/ +/*N*/ //Erst die Vertikale Position einstellen +/*N*/ if ( aCntFrm.Top() > aCntntPoint.Y() ) +/*N*/ aCntntPoint.Y() = aCntFrm.Top(); +/*N*/ else if ( aCntFrm.Bottom() < aCntntPoint.Y() ) +/*N*/ aCntntPoint.Y() = aCntFrm.Bottom(); +/*N*/ +/*N*/ //Jetzt die Horizontale Position +/*N*/ if ( aCntFrm.Left() > aCntntPoint.X() ) +/*N*/ aCntntPoint.X() = aCntFrm.Left(); +/*N*/ else if ( aCntFrm.Right() < aCntntPoint.X() ) +/*N*/ aCntntPoint.X() = aCntFrm.Right(); +/*N*/ +/*N*/ // pInside ist ein Seitenbereich, in dem der Punkt liegt, +/*N*/ // sobald pInside!=0 ist, werden nur noch Frames akzeptiert, +/*N*/ // die innerhalb liegen. +/*N*/ if( !pInside || ( pInside->IsAnLower( pCntnt ) && +/*N*/ ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) ) +/*N*/ { +/*N*/ const ULONG nDiff = ::binfilter::CalcDiff( aCntntPoint, rPoint ); +/*N*/ BOOL bBetter = nDiff < nDistance; // Dichter dran +/*N*/ if( !pInside ) +/*N*/ { +/*N*/ pInside = lcl_Inside( pCntnt, rPoint ); +/*N*/ if( pInside ) // Im "richtigen" Seitenteil +/*N*/ bBetter = TRUE; +/*N*/ } +/*N*/ if( bBetter ) +/*N*/ { +/*N*/ aPoint = aCntntPoint; +/*N*/ nDistance = nDiff; +/*N*/ pActual = pCntnt; +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ if ( bBodyOnly ) +/*N*/ while ( pCntnt && !pCntnt->IsInDocBody() ) +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ } +/*N*/ if ( !pActual ) +/*N*/ { //Wenn noch keiner gefunden wurde muss der Suchbereich erweitert +/*N*/ //werden, irgenwann muessen wir einen Finden! +/*N*/ //MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im +/*N*/ //Body suchen, koennen wir den Suchbereich gleich in einem +/*N*/ //Schritt hinreichend erweitern. +/*N*/ if ( bBodyOnly ) +/*N*/ { +/*N*/ while ( !pCntnt && pStart->GetPrev() ) +/*N*/ { +/*N*/ ++nMaxPage; +/*N*/ if( !pStart->GetPrev()->IsLayoutFrm() ) +/*N*/ return 0; +/*N*/ pStart = (SwLayoutFrm*)pStart->GetPrev(); +/*N*/ pCntnt = pStart->IsInDocBody() +/*N*/ ? pStart->ContainsCntnt() +/*N*/ : pStart->FindPageFrm()->FindFirstBodyCntnt(); +/*N*/ } +/*N*/ if ( !pCntnt ) //irgendwann muessen wir mit irgendeinem Anfangen! +/*N*/ { +/*N*/ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt(); +/*N*/ while ( pCntnt && !pCntnt->IsInDocBody() ) +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ if ( !pCntnt ) +/*N*/ return 0; //Es gibt noch keine Dokumentinhalt! +/*N*/ } +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ ++nMaxPage; +/*N*/ if ( pStart->GetPrev() ) +/*N*/ { +/*N*/ if( !pStart->GetPrev()->IsLayoutFrm() ) +/*N*/ return 0; +/*N*/ pStart = (SwLayoutFrm*)pStart->GetPrev(); +/*N*/ pCntnt = pStart->ContainsCntnt(); +/*N*/ } +/*N*/ else //irgendwann muessen wir mit irgendeinem Anfangen! +/*N*/ pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt(); +/*N*/ } +/*N*/ pActual = pCntnt; +/*N*/ } +/*N*/ else +/*N*/ break; +/*N*/ } +/*N*/ +/*N*/ #ifdef DBG_UTIL +/*N*/ OSL_ENSURE( pActual, "Keinen Cntnt gefunden." ); +/*N*/ if ( bBodyOnly ) +/*N*/ OSL_ENSURE( pActual->IsInDocBody(), "Cnt nicht im Body." ); +/*N*/ #endif +/*N*/ +/*N*/ //Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte +/*N*/ //TblHedlines. +/*N*/ if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL ) +/*N*/ { +/*N*/ const SwTabFrm *pTab = pActual->FindTabFrm(); +/*N*/ if ( pTab->IsFollow() && pTab->GetTable()->IsHeadlineRepeat() && +/*N*/ ((SwLayoutFrm*)pTab->Lower())->IsAnLower( pActual ) ) +/*N*/ { +/*N*/ ((SwCrsrMoveState*)pCMS)->bStop = TRUE; +/*N*/ return 0; +/*N*/ } +/*N*/ } +/*N*/ +/*N*/ //Jetzt noch eine kleine Korrektur beim ersten/letzten +/*N*/ Size aActualSize( pActual->Prt().SSize() ); +/*N*/ if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() ) +/*N*/ aActualSize.Height() = pActual->GetUpper()->Prt().Height(); +/*N*/ +/*N*/ SWRECTFN( pActual ) +/*N*/ if ( !pActual->GetPrev() && +/*N*/ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(), +/*N*/ bVert ? rPoint.X() : rPoint.Y() ) > 0 ) +/*N*/ { +/*N*/ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top(); +/*N*/ aPoint.X() = pActual->Frm().Left() + +/*N*/ ( pActual->IsRightToLeft() || bVert ? +/*N*/ pActual->Prt().Right() : +/*N*/ pActual->Prt().Left() ); +/*N*/ } +/*N*/ else if ( !pActual->GetNext() && +/*N*/ (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(), +/*N*/ bVert ? rPoint.X() : rPoint.Y() ) < 0 ) +/*N*/ { +/*N*/ aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom(); +/*N*/ aPoint.X() = pActual->Frm().Left() + +/*N*/ ( pActual->IsRightToLeft() || bVert ? +/*N*/ pActual->Prt().Left() : +/*N*/ pActual->Prt().Right() ); +/*N*/ } +/*N*/ +/*N*/ //Und den Point in die PrtArea bringen +/*N*/ if ( bCalc ) +/*N*/ pActual->Calc(); +/*N*/ const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(), +/*N*/ aActualSize ); +/*N*/ if ( aPoint.Y() < aRect.Top() ) +/*N*/ aPoint.Y() = aRect.Top(); +/*N*/ else if ( aPoint.Y() > aRect.Bottom() ) +/*N*/ aPoint.Y() = aRect.Bottom(); +/*N*/ if ( aPoint.X() < aRect.Left() ) +/*N*/ aPoint.X() = aRect.Left(); +/*N*/ else if ( aPoint.X() > aRect.Right() ) +/*N*/ aPoint.X() = aRect.Right(); +/*N*/ rPoint = aPoint; +/*N*/ return pActual; +/*N*/ } + +/*N*/ #ifdef _MSC_VER +/*N*/ #pragma optimize("",on) +/*N*/ #endif + +/************************************************************************* +|* +|* SwPageFrm::GetCntntPosition() +|* +|* Beschreibung Analog zu SwLayoutFrm::GetCntntPos(). +|* Spezialisiert fuer Felder in Rahmen. +|* +|*************************************************************************/ +/*N*/ void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const +/*N*/ { +/*N*/ //Ersten CntntFrm ermitteln. +/*N*/ const SwCntntFrm *pCntnt = ContainsCntnt(); +/*N*/ if ( pCntnt ) +/*N*/ { +/*N*/ //Einen weiter zurueck schauen (falls moeglich). +/*N*/ const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm(); +/*N*/ while ( pTmp && !pTmp->IsInDocBody() ) +/*?*/ pTmp = pTmp->GetPrevCntntFrm(); +/*N*/ if ( pTmp ) +/*?*/ pCntnt = pTmp; +/*N*/ } +/*N*/ else +/*?*/ pCntnt = GetUpper()->ContainsCntnt(); +/*N*/ +/*N*/ const SwCntntFrm *pAct = pCntnt; +/*N*/ Point aAct = rPt; +/*N*/ ULONG nDist = ULONG_MAX; +/*N*/ +/*N*/ while ( pCntnt ) +/*N*/ { +/*N*/ SwRect aCntFrm( pCntnt->UnionFrm() ); +/*N*/ if ( aCntFrm.IsInside( rPt ) ) +/*N*/ { +/*N*/ //dichter gehts nimmer. +/*?*/ pAct = pCntnt; +/*?*/ break; +/*N*/ } +/*N*/ +/*N*/ //Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen. +/*N*/ Point aPoint( rPt ); +/*N*/ +/*N*/ //Erst die vertikale Position einstellen +/*N*/ if ( aCntFrm.Top() > rPt.Y() ) +/*N*/ aPoint.Y() = aCntFrm.Top(); +/*N*/ else if ( aCntFrm.Bottom() < rPt.Y() ) +/*N*/ aPoint.Y() = aCntFrm.Bottom(); +/*N*/ +/*N*/ //Jetzt die horizontale Position +/*N*/ if ( aCntFrm.Left() > rPt.X() ) +/*N*/ aPoint.X() = aCntFrm.Left(); +/*N*/ else if ( aCntFrm.Right() < rPt.X() ) +/*N*/ aPoint.X() = aCntFrm.Right(); +/*N*/ +/*N*/ const ULONG nDiff = ::binfilter::CalcDiff( aPoint, rPt ); +/*N*/ if ( nDiff < nDist ) +/*N*/ { +/*N*/ aAct = aPoint; +/*N*/ nDist = nDiff; +/*N*/ pAct = pCntnt; +/*N*/ } +/*N*/ else if ( aCntFrm.Top() > Frm().Bottom() ) +/*N*/ //Dichter wirds im Sinne der Felder nicht mehr! +/*N*/ break; +/*N*/ +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ while ( pCntnt && !pCntnt->IsInDocBody() ) +/*N*/ pCntnt = pCntnt->GetNextCntntFrm(); +/*N*/ } +/*N*/ +/*N*/ //Und den Point in die PrtArea bringen +/*N*/ const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() ); +/*N*/ if ( aAct.Y() < aRect.Top() ) +/*N*/ aAct.Y() = aRect.Top(); +/*N*/ else if ( aAct.Y() > aRect.Bottom() ) +/*N*/ aAct.Y() = aRect.Bottom(); +/*N*/ if ( aAct.X() < aRect.Left() ) +/*?*/ aAct.X() = aRect.Left(); +/*N*/ else if ( aAct.X() > aRect.Right() ) +/*N*/ aAct.X() = aRect.Right(); +/*N*/ +/*N*/ if( !pAct->IsValid() ) +/*N*/ { +/*N*/ // CntntFrm nicht formatiert -> immer auf Node-Anfang +/*?*/ SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode(); +/*?*/ OSL_ENSURE( pCNd, "Wo ist mein CntntNode?" ); +/*?*/ rPos.nNode = *pCNd; +/*?*/ rPos.nContent.Assign( pCNd, 0 ); +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ SwCrsrMoveState aTmpState( MV_SETONLYTEXT ); +/*N*/ pAct->GetCrsrOfst( &rPos, aAct, &aTmpState ); +/*N*/ } +/*N*/ } + +/************************************************************************* +|* +|* SwFrm::IsProtected() +|* +|* Beschreibung Ist der Frm bzw. die Section in der er steht +|* geschuetzt? +|* Auch Fly in Fly in ... und Fussnoten +|* +|*************************************************************************/ +/*N*/ BOOL SwFrm::IsProtected() const +/*N*/ { +/*N*/ //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein. +/*N*/ //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker. +/*N*/ const SwFrm *pFrm = this; +/*N*/ do +/*N*/ { +/*N*/ if ( pFrm->IsCntntFrm() ) +/*N*/ { +/*N*/ if ( ((SwCntntFrm*)pFrm)->GetNode() && +/*N*/ ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() ) +/*N*/ return TRUE; +/*N*/ } +/*N*/ else +/*N*/ { +/*N*/ if ( ((SwLayoutFrm*)pFrm)->GetFmt() && +/*N*/ ((SwLayoutFrm*)pFrm)->GetFmt()-> +/*N*/ GetProtect().IsCntntProtected() ) +/*N*/ return TRUE; +/*N*/ } +/*N*/ if ( pFrm->IsFlyFrm() ) +/*N*/ { +/*N*/ //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette +/*N*/ //vorgegeben werden. +/*N*/ if ( ((SwFlyFrm*)pFrm)->GetPrevLink() ) +/*N*/ { +/*N*/ SwFlyFrm *pMaster = (SwFlyFrm*)pFrm; +/*N*/ do +/*N*/ { pMaster = pMaster->GetPrevLink(); +/*N*/ } while ( pMaster->GetPrevLink() ); +/*N*/ if ( pMaster->IsProtected() ) +/*N*/ return TRUE; +/*N*/ } +/*N*/ pFrm = ((SwFlyFrm*)pFrm)->GetAnchor(); +/*N*/ } +/*N*/ else if ( pFrm->IsFtnFrm() ) +/*N*/ pFrm = ((SwFtnFrm*)pFrm)->GetRef(); +/*N*/ else +/*N*/ pFrm = pFrm->GetUpper(); +/*N*/ +/*N*/ } while ( pFrm ); +/*N*/ +/*N*/ return FALSE; +/*N*/ } + +/************************************************************************* +|* +|* SwFrm::GetPhyPageNum() +|* Beschreibung: Liefert die physikalische Seitennummer +|* +|*************************************************************************/ +/*N*/ USHORT SwFrm::GetPhyPageNum() const +/*N*/ { +/*N*/ const SwPageFrm *pPage = FindPageFrm(); +/*N*/ return pPage ? pPage->GetPhyPageNum() : 0; +/*N*/ } + +/*-------------------------------------------------- + * SwFrm::WannaRightPage() + * decides if the page want to be a rightpage or not. + * If the first content of the page has a page descriptor, + * we take the follow of the page descriptor of the last not empty page. + * If this descriptor allows only right(left) pages and the page + * isn't an empty page then it wanna be such right(left) page. + * If the descriptor allows right and left pages, we look for a number offset + * in the first content. If there is one, odd number results right pages, + * even number results left pages. + * If there is no number offset, we take the physical page number instead, + * but a previous empty page don't count. + * --------------------------------------------------*/ + +/*N*/ BOOL SwFrm::WannaRightPage() const +/*N*/ { +/*N*/ const SwPageFrm *pPage = FindPageFrm(); +/*N*/ if ( !pPage || !pPage->GetUpper() ) +/*?*/ return TRUE; +/*N*/ +/*N*/ const SwFrm *pFlow = pPage->FindFirstBodyCntnt(); +/*N*/ SwPageDesc *pDesc = 0; +/*N*/ USHORT nPgNum = 0; +/*N*/ if ( pFlow ) +/*N*/ { +/*N*/ if ( pFlow->IsInTab() ) +/*N*/ pFlow = pFlow->FindTabFrm(); +/*N*/ const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow ); +/*N*/ if ( !pTmp->IsFollow() ) +/*N*/ { +/*N*/ const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc(); +/*N*/ pDesc = (SwPageDesc*)rPgDesc.GetPageDesc(); +/*N*/ nPgNum = rPgDesc.GetNumOffset(); +/*N*/ } +/*N*/ } +/*N*/ if ( !pDesc ) +/*N*/ { +/*N*/ SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev(); +/*N*/ if( pPrv && pPrv->IsEmptyPage() ) +/*N*/ pPrv = (SwPageFrm*)pPrv->GetPrev(); +/*N*/ if( pPrv ) +/*N*/ pDesc = pPrv->GetPageDesc()->GetFollow(); +/*N*/ else +/*N*/ { +/*N*/ const SwDoc* pDoc = pPage->GetFmt()->GetDoc(); +/*N*/ pDesc = (SwPageDesc*)&pDoc->GetPageDesc( 0 ); +/*N*/ } +/*N*/ } +/*N*/ OSL_ENSURE( pDesc, "No pagedescriptor" ); +/*N*/ BOOL bOdd; +/*N*/ if( nPgNum ) +/*N*/ bOdd = nPgNum % 2 ? TRUE : FALSE; +/*N*/ else +/*N*/ { +/*N*/ bOdd = pPage->OnRightPage(); +/*N*/ if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() ) +/*N*/ bOdd = !bOdd; +/*N*/ } +/*N*/ if( !pPage->IsEmptyPage() ) +/*N*/ { +/*N*/ if( !pDesc->GetRightFmt() ) +/*N*/ bOdd = FALSE; +/*N*/ else if( !pDesc->GetLeftFmt() ) +/*N*/ bOdd = TRUE; +/*N*/ } +/*N*/ return bOdd; +/*N*/ } + +/************************************************************************* +|* +|* SwFrm::GetVirtPageNum() +|* Beschreibung: Liefert die virtuelle Seitennummer mit Offset +|* +|*************************************************************************/ +/*N*/ USHORT SwFrm::GetVirtPageNum() const +/*N*/ { +/*N*/ const SwPageFrm *pPage = FindPageFrm(); +/*N*/ if ( !pPage || !pPage->GetUpper() ) +/*?*/ return 0; +/*N*/ +/*N*/ USHORT nPhyPage = pPage->GetPhyPageNum(); +/*N*/ +/*N*/ //Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen. +/*N*/ //Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen +/*N*/ //wir jetzt gezielt ueber die Abhaengigkeiten. +/*N*/ //von den PageDescs bekommen wir die Attribute, von den Attributen +/*N*/ //wiederum bekommen wir die Absaetze. +/*N*/ const SwPageFrm *pVirtPage = 0; +/*N*/ const SwFrm *pFrm = 0; +/*N*/ const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool(); +/*N*/ const SfxPoolItem* pItem; +/*N*/ USHORT nMaxItems = rPool.GetItemCount( RES_PAGEDESC ); +/*N*/ for( USHORT n = 0; n < nMaxItems; ++n ) +/*N*/ { +/*N*/ if( 0 == (pItem = rPool.GetItem( RES_PAGEDESC, n ) )) +/*N*/ continue; +/*N*/ +/*N*/ const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem; +/*N*/ if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() ) +/*N*/ { +/*N*/ const SwModify *pMod = pDesc->GetDefinedIn(); +/*N*/ SwVirtPageNumInfo aInfo( pPage ); +/*N*/ pMod->GetInfo( aInfo ); +/*N*/ if ( aInfo.GetPage() ) +/*N*/ { +/*N*/ if( !pVirtPage || ( pVirtPage && aInfo.GetPage()-> +/*N*/ GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) ) +/*N*/ { +/*N*/ pVirtPage = aInfo.GetPage(); +/*N*/ pFrm = aInfo.GetFrm(); +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ } +/*N*/ if ( pFrm ) +/*N*/ return nPhyPage - pFrm->GetPhyPageNum() + +/*N*/ pFrm->GetAttrSet()->GetPageDesc().GetNumOffset(); +/*N*/ return nPhyPage; +/*N*/ } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |