| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #include "pagefrm.hxx" |
| #include "rootfrm.hxx" |
| #include "cntfrm.hxx" |
| #include "node.hxx" |
| #include "doc.hxx" |
| #include "frmtool.hxx" |
| #include "flyfrm.hxx" |
| #include <frmfmt.hxx> |
| #include <cellfrm.hxx> |
| #include <rowfrm.hxx> |
| #include <swtable.hxx> |
| |
| #include "tabfrm.hxx" |
| #include "sectfrm.hxx" |
| #include "flyfrms.hxx" |
| #include "ftnfrm.hxx" |
| #include "txtftn.hxx" |
| #include "fmtftn.hxx" |
| #include <txtfrm.hxx> // SwTxtFrm |
| #include <switerator.hxx> |
| |
| /************************************************************************* |
| |* |
| |* FindBodyCont, FindLastBodyCntnt() |
| |* |
| |* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb |
| |* der Seite. |
| |* Ersterstellung MA 15. Feb. 93 |
| |* Letzte Aenderung MA 18. Apr. 94 |
| |* |
| |*************************************************************************/ |
| SwLayoutFrm *SwFtnBossFrm::FindBodyCont() |
| { |
| SwFrm *pLay = Lower(); |
| while ( pLay && !pLay->IsBodyFrm() ) |
| pLay = pLay->GetNext(); |
| return (SwLayoutFrm*)pLay; |
| } |
| |
| SwCntntFrm *SwPageFrm::FindLastBodyCntnt() |
| { |
| SwCntntFrm *pRet = FindFirstBodyCntnt(); |
| SwCntntFrm *pNxt = pRet; |
| while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) ) |
| { pRet = pNxt; |
| pNxt = pNxt->FindNextCnt(); |
| } |
| return pRet; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwLayoutFrm::ContainsCntnt |
| |* |
| |* Beschreibung Prueft, ob der Frame irgendwo in seiner |
| |* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt; |
| |* Falls ja wird der erste gefundene CntntFrm zurueckgegeben. |
| |* |
| |* Ersterstellung MA 13. May. 92 |
| |* Letzte Aenderung MA 20. Apr. 94 |
| |* |
| |*************************************************************************/ |
| |
| const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const |
| { |
| //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat |
| //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der |
| //this verlassen wird. |
| //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section |
| //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht |
| //werden. |
| |
| const SwLayoutFrm *pLayLeaf = this; |
| do |
| { |
| while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) && |
| pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() ) |
| pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower(); |
| |
| if( pLayLeaf->IsSctFrm() && pLayLeaf != this ) |
| { |
| const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt(); |
| if( pCnt ) |
| return pCnt; |
| if( pLayLeaf->GetNext() ) |
| { |
| if( pLayLeaf->GetNext()->IsLayoutFrm() ) |
| { |
| pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext(); |
| continue; |
| } |
| else |
| return (SwCntntFrm*)pLayLeaf->GetNext(); |
| } |
| } |
| else if ( pLayLeaf->Lower() ) |
| return (SwCntntFrm*)pLayLeaf->Lower(); |
| |
| pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); |
| if( !IsAnLower( pLayLeaf) ) |
| return 0; |
| } while( pLayLeaf ); |
| return 0; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwLayoutFrm::FirstCell |
| |* |
| |* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle |
| |* hineinzukommen. Dort hangelt es sich wieder hoch zum |
| |* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein |
| |* ContainsCntnt()->GetUpper() mehr... |
| |* Ersterstellung AMA 17. Mar. 99 |
| |* Letzte Aenderung AMA 17. Mar. 99 |
| |* |
| |*************************************************************************/ |
| |
| const SwCellFrm *SwLayoutFrm::FirstCell() const |
| { |
| const SwFrm* pCnt = ContainsAny(); |
| while( pCnt && !pCnt->IsCellFrm() ) |
| pCnt = pCnt->GetUpper(); |
| return (const SwCellFrm*)pCnt; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwLayoutFrm::ContainsAny |
| |* |
| |* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch |
| |* Bereiche und Tabellen zurueckgegeben werden. |
| |* Ersterstellung AMA 10. Mar. 99 |
| |* Letzte Aenderung AMA 10. Mar. 99 |
| |* |
| |*************************************************************************/ |
| |
| // --> OD 2006-02-01 #130797# |
| // New parameter <_bInvestigateFtnForSections> controls investigation of |
| // content of footnotes for sections. |
| const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const |
| { |
| //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat |
| //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der |
| //this verlassen wird. |
| // Oder bis wir einen SectionFrm oder TabFrm gefunden haben |
| |
| const SwLayoutFrm *pLayLeaf = this; |
| // --> OD 2006-02-01 #130797# |
| const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections; |
| // <-- |
| do |
| { |
| while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm()) |
| || pLayLeaf == this ) && |
| pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() ) |
| pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower(); |
| |
| if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() ) |
| && pLayLeaf != this ) |
| { |
| // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck, |
| // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden. |
| return pLayLeaf; |
| } |
| else if ( pLayLeaf->Lower() ) |
| return (SwCntntFrm*)pLayLeaf->Lower(); |
| |
| pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); |
| if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() ) |
| { |
| do |
| { |
| pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); |
| } while( pLayLeaf && pLayLeaf->IsInFtn() ); |
| } |
| if( !IsAnLower( pLayLeaf) ) |
| return 0; |
| } while( pLayLeaf ); |
| return 0; |
| } |
| |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::GetLower() |
| |* |
| |* Ersterstellung MA 27. Jul. 92 |
| |* Letzte Aenderung MA 09. Oct. 97 |
| |* |
| |*************************************************************************/ |
| const SwFrm* SwFrm::GetLower() const |
| { |
| return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0; |
| } |
| |
| SwFrm* SwFrm::GetLower() |
| { |
| return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwLayoutFrm::IsAnLower() |
| |* |
| |* Ersterstellung MA 18. Mar. 93 |
| |* Letzte Aenderung MA 18. Mar. 93 |
| |* |
| |*************************************************************************/ |
| sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const |
| { |
| const SwFrm *pUp = pAssumed; |
| while ( pUp ) |
| { |
| if ( pUp == this ) |
| return sal_True; |
| if ( pUp->IsFlyFrm() ) |
| pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm(); |
| else |
| pUp = pUp->GetUpper(); |
| } |
| return sal_False; |
| } |
| |
| /** method to check relative position of layout frame to |
| a given layout frame. |
| |
| OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in |
| <txtftn.cxx> for #104840#. |
| |
| @param _aCheckRefLayFrm |
| constant reference of an instance of class <SwLayoutFrm> which |
| is used as the reference for the relative position check. |
| |
| @author OD |
| |
| @return true, if <this> is positioned before the layout frame <p> |
| */ |
| bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const |
| { |
| ASSERT( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>."); |
| ASSERT( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>."); |
| |
| bool bReturn; |
| |
| // check, if on different pages |
| const SwPageFrm *pMyPage = FindPageFrm(); |
| const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm(); |
| if( pMyPage != pCheckRefPage ) |
| { |
| // being on different page as check reference |
| bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum(); |
| } |
| else |
| { |
| // being on same page as check reference |
| // --> search my supreme parent <pUp>, which doesn't contain check reference. |
| const SwLayoutFrm* pUp = this; |
| while ( pUp->GetUpper() && |
| !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm ) |
| ) |
| pUp = pUp->GetUpper(); |
| if( !pUp->GetUpper() ) |
| { |
| // can occur, if <this> is a fly frm |
| bReturn = false; |
| } |
| else |
| { |
| // travel through the next's of <pUp> and check if one of these |
| // contain the check reference. |
| SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext(); |
| while ( pUpNext && |
| !pUpNext->IsAnLower( _pCheckRefLayFrm ) ) |
| { |
| pUpNext = (SwLayoutFrm*)pUpNext->GetNext(); |
| } |
| bReturn = pUpNext != 0; |
| } |
| } |
| |
| return bReturn; |
| } |
| |
| // |
| // Local helper functions for GetNextLayoutLeaf |
| // |
| |
| const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext ) |
| { |
| const SwFrm* pRet = 0; |
| if ( pFrm->IsFlyFrm() ) |
| pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink(); |
| else |
| pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev(); |
| |
| return pRet; |
| } |
| |
| const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd ) |
| { |
| if ( !pFrm->IsLayoutFrm() ) |
| return 0; |
| |
| return bFwd ? |
| static_cast<const SwLayoutFrm*>(pFrm)->Lower() : |
| static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower(); |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::ImplGetNextLayoutLeaf |
| |* |
| |* Finds the next layout leaf. This is a layout frame, which does not |
| * have a lower which is a LayoutFrame. That means, pLower can be 0 or a |
| * content frame. |
| * |
| * However, pLower may be a TabFrm |
| * |
| |*************************************************************************/ |
| |
| const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const |
| { |
| const SwFrm *pFrm = this; |
| const SwLayoutFrm *pLayoutFrm = 0; |
| const SwFrm *p = 0; |
| bool bGoingUp = !bFwd; // false for forward, true for backward |
| do { |
| |
| bool bGoingFwdOrBwd = false, bGoingDown = false; |
| |
| bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) ); |
| if ( !bGoingDown ) |
| { |
| // I cannot go down, because either I'm currently going up or |
| // because the is no lower. |
| // I'll try to go forward: |
| bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) ); |
| if ( !bGoingFwdOrBwd ) |
| { |
| // I cannot go forward, because there is no next frame. |
| // I'll try to go up: |
| bGoingUp = (0 != (p = pFrm->GetUpper() ) ); |
| if ( !bGoingUp ) |
| { |
| // I cannot go up, because there is no upper frame. |
| return 0; |
| } |
| } |
| } |
| |
| // If I could not go down or forward, I'll have to go up |
| bGoingUp = !bGoingFwdOrBwd && !bGoingDown; |
| |
| pFrm = p; |
| p = lcl_GetLower( pFrm, true ); |
| |
| } while( ( p && !p->IsFlowFrm() ) || |
| pFrm == this || |
| 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) || |
| pLayoutFrm->IsAnLower( this ) ); |
| |
| return pLayoutFrm; |
| } |
| |
| |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::ImplGetNextCntntFrm( bool ) |
| |* |
| |* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen, |
| |* wenn es einen gibt und nicht gerade zuvor um eine Ebene |
| |* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab |
| |* fuehren!). Damit wird sichergestellt, dass beim |
| |* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn |
| |* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen, |
| |* weil im weiteren ja vom letzten Frm innerhalb eines anderen |
| |* Frms rueckwaerts gegangen wird. |
| |* Vorwaetzwander funktioniert analog. |
| |* |
| |* Ersterstellung ?? |
| |* Letzte Aenderung MA 30. Oct. 97 |
| |* |
| |*************************************************************************/ |
| |
| // Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in |
| // die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden |
| const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const |
| { |
| const SwFrm *pFrm = this; |
| // #100926# |
| SwCntntFrm *pCntntFrm = 0; |
| sal_Bool bGoingUp = sal_False; |
| do { |
| const SwFrm *p = 0; |
| sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False; |
| |
| bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) ); |
| if ( !bGoingDown ) |
| { |
| bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) ); |
| if ( !bGoingFwdOrBwd ) |
| { |
| bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) ); |
| if ( !bGoingUp ) |
| { |
| return 0; |
| } |
| } |
| } |
| |
| bGoingUp = !(bGoingFwdOrBwd || bGoingDown); |
| |
| if ( !bFwd ) |
| { |
| if( bGoingDown && p ) |
| while ( p->GetNext() ) |
| p = p->GetNext(); |
| } |
| |
| pFrm = p; |
| } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) )); |
| |
| return pCntntFrm; |
| } |
| |
| |
| |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(), |
| |* FindPageFrm(), FindColFrm() |
| |* |
| |* Ersterstellung ?? |
| |* Letzte Aenderung MA 05. Sep. 93 |
| |* |
| |*************************************************************************/ |
| SwPageFrm* SwFrm::FindPageFrm() |
| { |
| SwFrm *pRet = this; |
| while ( pRet && !pRet->IsPageFrm() ) |
| { |
| if ( pRet->GetUpper() ) |
| pRet = pRet->GetUpper(); |
| else if ( pRet->IsFlyFrm() ) |
| { |
| // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> |
| if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() ) |
| pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm(); |
| else |
| pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm(); |
| } |
| else |
| return 0; |
| } |
| return (SwPageFrm*)pRet; |
| } |
| |
| SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes ) |
| { |
| SwFrm *pRet = this; |
| // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige |
| // Bereiche enthalten dort keine Fussnotentexte |
| if( pRet->IsInTab() ) |
| pRet = pRet->FindTabFrm(); |
| while ( pRet && !pRet->IsFtnBossFrm() ) |
| { |
| if ( pRet->GetUpper() ) |
| pRet = pRet->GetUpper(); |
| else if ( pRet->IsFlyFrm() ) |
| { |
| // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> |
| if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() ) |
| pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm(); |
| else |
| pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm(); |
| } |
| else |
| return 0; |
| } |
| if( bFootnotes && pRet && pRet->IsColumnFrm() && |
| !pRet->GetNext() && !pRet->GetPrev() ) |
| { |
| SwSectionFrm* pSct = pRet->FindSctFrm(); |
| ASSERT( pSct, "FindFtnBossFrm: Single column outside section?" ); |
| if( !pSct->IsFtnAtEnd() ) |
| return pSct->FindFtnBossFrm( sal_True ); |
| } |
| return (SwFtnBossFrm*)pRet; |
| } |
| |
| SwTabFrm* SwFrm::ImplFindTabFrm() |
| { |
| SwFrm *pRet = this; |
| while ( !pRet->IsTabFrm() ) |
| { |
| pRet = pRet->GetUpper(); |
| if ( !pRet ) |
| return 0; |
| } |
| return (SwTabFrm*)pRet; |
| } |
| |
| SwSectionFrm* SwFrm::ImplFindSctFrm() |
| { |
| SwFrm *pRet = this; |
| while ( !pRet->IsSctFrm() ) |
| { |
| pRet = pRet->GetUpper(); |
| if ( !pRet ) |
| return 0; |
| } |
| return (SwSectionFrm*)pRet; |
| } |
| |
| SwFtnFrm *SwFrm::ImplFindFtnFrm() |
| { |
| SwFrm *pRet = this; |
| while ( !pRet->IsFtnFrm() ) |
| { |
| pRet = pRet->GetUpper(); |
| if ( !pRet ) |
| return 0; |
| } |
| return (SwFtnFrm*)pRet; |
| } |
| |
| SwFlyFrm *SwFrm::ImplFindFlyFrm() |
| { |
| const SwFrm *pRet = this; |
| do |
| { |
| if ( pRet->IsFlyFrm() ) |
| return (SwFlyFrm*)pRet; |
| else |
| pRet = pRet->GetUpper(); |
| } while ( pRet ); |
| return 0; |
| } |
| |
| SwFrm *SwFrm::FindColFrm() |
| { |
| SwFrm *pFrm = this; |
| do |
| { pFrm = pFrm->GetUpper(); |
| } while ( pFrm && !pFrm->IsColumnFrm() ); |
| return pFrm; |
| } |
| |
| SwFrm* SwFrm::FindFooterOrHeader() |
| { |
| SwFrm* pRet = this; |
| do |
| { if ( pRet->GetType() & 0x0018 ) //Header und Footer |
| return pRet; |
| else if ( pRet->GetUpper() ) |
| pRet = pRet->GetUpper(); |
| else if ( pRet->IsFlyFrm() ) |
| pRet = ((SwFlyFrm*)pRet)->AnchorFrm(); |
| else |
| return 0; |
| } while ( pRet ); |
| return pRet; |
| } |
| |
| const SwFtnFrm* SwFtnContFrm::FindFootNote() const |
| { |
| const SwFtnFrm* pRet = (SwFtnFrm*)Lower(); |
| if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() ) |
| return pRet; |
| return NULL; |
| } |
| |
| const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const |
| { |
| const SwPageFrm* pRet = 0; |
| |
| SwRect aRect; |
| if ( pSize ) |
| { |
| aRect.Pos() = rPt; |
| aRect.SSize() = *pSize; |
| } |
| |
| const SwFrm* pPage = Lower(); |
| |
| if ( !bExtend ) |
| { |
| if( !Frm().IsInside( rPt ) ) |
| return 0; |
| |
| // skip pages above point: |
| while( pPage && rPt.Y() > pPage->Frm().Bottom() ) |
| pPage = pPage->GetNext(); |
| } |
| |
| ASSERT( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" ) |
| sal_uInt16 nPageIdx = 0; |
| |
| while ( pPage && !pRet ) |
| { |
| const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm(); |
| |
| if ( (!pSize && rBoundRect.IsInside(rPt)) || |
| (pSize && rBoundRect.IsOver(aRect)) ) |
| { |
| pRet = static_cast<const SwPageFrm*>(pPage); |
| } |
| |
| pPage = pPage->GetNext(); |
| } |
| |
| return pRet; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrmFrm::GetAttrSet() |
| |* |
| |* Ersterstellung MA 02. Aug. 93 |
| |* Letzte Aenderung MA 02. Aug. 93 |
| |* |
| |*************************************************************************/ |
| const SwAttrSet* SwFrm::GetAttrSet() const |
| { |
| if ( IsCntntFrm() ) |
| return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet(); |
| else |
| return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet(); |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos() |
| |* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert |
| |* nur SwCntntFrms. |
| |* |
| |* Beschreibung Invalidiert die Position des Naechsten Frames. |
| |* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste |
| |* CntntFrm der im gleichen Fluss liegt wie ich: |
| |* - Body, |
| |* - Fussnoten, |
| |* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des |
| |* Bereiches weiterzuleiten. |
| |* - dito fuer Flys. |
| |* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle |
| |* auf. |
| |* - Tabellen verhalten sich prinzipiell analog zu den Cntnts |
| |* - Bereiche ebenfalls |
| |* Ersterstellung AK 14-Feb-1991 |
| |* Letzte Aenderung AMA 10. Mar. 99 |
| |* |
| |*************************************************************************/ |
| |
| // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode, |
| // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms. |
| SwFrm* lcl_NextFrm( SwFrm* pFrm ) |
| { |
| SwFrm *pRet = 0; |
| sal_Bool bGoingUp = sal_False; |
| do { |
| SwFrm *p = 0; |
| |
| sal_Bool bGoingFwd = sal_False; |
| sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0))); |
| |
| if( !bGoingDown ) |
| { |
| bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext()))); |
| if ( !bGoingFwd ) |
| { |
| bGoingUp = (0 != (p = pFrm->GetUpper())); |
| if ( !bGoingUp ) |
| { |
| return 0; |
| } |
| } |
| } |
| bGoingUp = !(bGoingFwd || bGoingDown); |
| pFrm = p; |
| } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp && |
| ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) ); |
| return pRet; |
| } |
| |
| SwFrm *SwFrm::_FindNext() |
| { |
| sal_Bool bIgnoreTab = sal_False; |
| SwFrm *pThis = this; |
| |
| if ( IsTabFrm() ) |
| { |
| //Der letzte Cntnt der Tabelle wird |
| //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh. |
| //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. |
| if ( ((SwTabFrm*)this)->GetFollow() ) |
| return ((SwTabFrm*)this)->GetFollow(); |
| |
| pThis = ((SwTabFrm*)this)->FindLastCntnt(); |
| if ( !pThis ) |
| pThis = this; |
| bIgnoreTab = sal_True; |
| } |
| else if ( IsSctFrm() ) |
| { |
| //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger |
| // geliefert. |
| if ( ((SwSectionFrm*)this)->GetFollow() ) |
| return ((SwSectionFrm*)this)->GetFollow(); |
| |
| pThis = ((SwSectionFrm*)this)->FindLastCntnt(); |
| if ( !pThis ) |
| pThis = this; |
| } |
| else if ( IsCntntFrm() ) |
| { |
| if( ((SwCntntFrm*)this)->GetFollow() ) |
| return ((SwCntntFrm*)this)->GetFollow(); |
| } |
| else if ( IsRowFrm() ) |
| { |
| SwFrm* pMyUpper = GetUpper(); |
| if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() ) |
| return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower(); |
| else return NULL; |
| } |
| else |
| return NULL; |
| |
| SwFrm* pRet = NULL; |
| const sal_Bool bFtn = pThis->IsInFtn(); |
| if ( !bIgnoreTab && pThis->IsInTab() ) |
| { |
| SwLayoutFrm *pUp = pThis->GetUpper(); |
| while ( !pUp->IsCellFrm() ) |
| pUp = pUp->GetUpper(); |
| ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); |
| SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell(); |
| if ( pNxt ) |
| pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt(); |
| if ( !pNxt ) |
| { |
| pNxt = lcl_NextFrm( pThis ); |
| if ( pUp->IsAnLower( pNxt ) ) |
| pRet = pNxt; |
| } |
| else |
| pRet = pNxt; |
| } |
| else |
| { |
| const sal_Bool bBody = pThis->IsInDocBody(); |
| SwFrm *pNxtCnt = lcl_NextFrm( pThis ); |
| if ( pNxtCnt ) |
| { |
| if ( bBody || bFtn ) |
| { |
| while ( pNxtCnt ) |
| { |
| // OD 02.04.2003 #108446# - check for endnote, only if found |
| // next content isn't contained in a section, that collect its |
| // endnotes at its end. |
| bool bEndn = IsInSct() && !IsSctFrm() && |
| ( !pNxtCnt->IsInSct() || |
| !pNxtCnt->FindSctFrm()->IsEndnAtEnd() |
| ); |
| if ( ( bBody && pNxtCnt->IsInDocBody() ) || |
| ( pNxtCnt->IsInFtn() && |
| ( bFtn || |
| ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() ) |
| ) |
| ) |
| ) |
| { |
| pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() |
| : (SwFrm*)pNxtCnt; |
| break; |
| } |
| pNxtCnt = lcl_NextFrm( pNxtCnt ); |
| } |
| } |
| else if ( pThis->IsInFly() ) |
| { |
| pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() |
| : (SwFrm*)pNxtCnt; |
| } |
| else //Fuss-/oder Kopfbereich |
| { |
| const SwFrm *pUp = pThis->GetUpper(); |
| const SwFrm *pCntUp = pNxtCnt->GetUpper(); |
| while ( pUp && pUp->GetUpper() && |
| !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) |
| pUp = pUp->GetUpper(); |
| while ( pCntUp && pCntUp->GetUpper() && |
| !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) |
| pCntUp = pCntUp->GetUpper(); |
| if ( pCntUp == pUp ) |
| { |
| pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() |
| : (SwFrm*)pNxtCnt; |
| } |
| } |
| } |
| } |
| if( pRet && pRet->IsInSct() ) |
| { |
| SwSectionFrm* pSct = pRet->FindSctFrm(); |
| //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich |
| //liefern, der die Fussnoten umfasst |
| if( !pSct->IsAnLower( this ) && |
| (!bFtn || pSct->IsInFtn() ) ) |
| return pSct; |
| } |
| return pRet; |
| } |
| |
| // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn> |
| SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn ) |
| { |
| SwFrm *pThis = this; |
| |
| if ( IsTabFrm() ) |
| { |
| if ( ((SwTabFrm*)this)->GetFollow() ) |
| { |
| pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt(); |
| if( pThis ) |
| return (SwCntntFrm*)pThis; |
| } |
| pThis = ((SwTabFrm*)this)->FindLastCntnt(); |
| if ( !pThis ) |
| return 0; |
| } |
| else if ( IsSctFrm() ) |
| { |
| if ( ((SwSectionFrm*)this)->GetFollow() ) |
| { |
| pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt(); |
| if( pThis ) |
| return (SwCntntFrm*)pThis; |
| } |
| pThis = ((SwSectionFrm*)this)->FindLastCntnt(); |
| if ( !pThis ) |
| return 0; |
| } |
| else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() ) |
| return ((SwCntntFrm*)this)->GetFollow(); |
| |
| if ( pThis->IsCntntFrm() ) |
| { |
| const sal_Bool bBody = pThis->IsInDocBody(); |
| const sal_Bool bFtn = pThis->IsInFtn(); |
| SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm(); |
| if ( pNxtCnt ) |
| { |
| // --> OD 2005-12-01 #i27138# |
| if ( bBody || ( bFtn && !_bInSameFtn ) ) |
| // <-- |
| { |
| // handling for environments 'footnotes' and 'document body frames': |
| while ( pNxtCnt ) |
| { |
| if ( (bBody && pNxtCnt->IsInDocBody()) || |
| (bFtn && pNxtCnt->IsInFtn()) ) |
| return pNxtCnt; |
| pNxtCnt = pNxtCnt->GetNextCntntFrm(); |
| } |
| } |
| // --> OD 2005-12-01 #i27138# |
| else if ( bFtn && _bInSameFtn ) |
| { |
| // handling for environments 'each footnote': |
| // Assure that found next content frame belongs to the same footnotes |
| const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() ); |
| const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() ); |
| ASSERT( pFtnFrmOfCurr, |
| "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." ); |
| if ( pFtnFrmOfNext == pFtnFrmOfCurr ) |
| { |
| return pNxtCnt; |
| } |
| else if ( pFtnFrmOfCurr->GetFollow() ) |
| { |
| // next content frame has to be the first content frame |
| // in the follow footnote, which contains a content frame. |
| SwFtnFrm* pFollowFtnFrmOfCurr( |
| const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); |
| pNxtCnt = 0L; |
| do { |
| pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow(); |
| pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt(); |
| } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() ); |
| return pNxtCnt; |
| } |
| else |
| { |
| // current content frame is the last content frame in the |
| // footnote - no next content frame exists. |
| return 0L; |
| } |
| } |
| // <-- |
| else if ( pThis->IsInFly() ) |
| // handling for environments 'unlinked fly frame' and |
| // 'group of linked fly frames': |
| return pNxtCnt; |
| else |
| { |
| // handling for environments 'page header' and 'page footer': |
| const SwFrm *pUp = pThis->GetUpper(); |
| const SwFrm *pCntUp = pNxtCnt->GetUpper(); |
| while ( pUp && pUp->GetUpper() && |
| !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) |
| pUp = pUp->GetUpper(); |
| while ( pCntUp && pCntUp->GetUpper() && |
| !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) |
| pCntUp = pCntUp->GetUpper(); |
| if ( pCntUp == pUp ) |
| return pNxtCnt; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| /** method to determine previous content frame in the same environment |
| for a flow frame (content frame, table frame, section frame) |
| |
| OD 2005-11-30 #i27138# |
| |
| @author OD |
| */ |
| SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn ) |
| { |
| if ( !IsFlowFrm() ) |
| { |
| // nothing to do, if current frame isn't a flow frame. |
| return 0L; |
| } |
| |
| SwCntntFrm* pPrevCntntFrm( 0L ); |
| |
| // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel |
| // through the layout, a content frame, at which the travel starts, is needed. |
| SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this); |
| |
| // perform shortcut, if current frame is a follow, and |
| // determine <pCurrCntntFrm>, if current frame is a table or section frame |
| if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() ) |
| { |
| // previous content frame is its master content frame |
| pPrevCntntFrm = pCurrCntntFrm->FindMaster(); |
| } |
| else if ( IsTabFrm() ) |
| { |
| SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) ); |
| if ( pTabFrm->IsFollow() ) |
| { |
| // previous content frame is the last content of its master table frame |
| pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt(); |
| } |
| else |
| { |
| // start content frame for the search is the first content frame of |
| // the table frame. |
| pCurrCntntFrm = pTabFrm->ContainsCntnt(); |
| } |
| } |
| else if ( IsSctFrm() ) |
| { |
| SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) ); |
| if ( pSectFrm->IsFollow() ) |
| { |
| // previous content frame is the last content of its master section frame |
| pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt(); |
| } |
| else |
| { |
| // start content frame for the search is the first content frame of |
| // the section frame. |
| pCurrCntntFrm = pSectFrm->ContainsCntnt(); |
| } |
| } |
| |
| // search for next content frame, depending on the environment, in which |
| // the current frame is in. |
| if ( !pPrevCntntFrm && pCurrCntntFrm ) |
| { |
| pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm(); |
| if ( pPrevCntntFrm ) |
| { |
| if ( pCurrCntntFrm->IsInFly() ) |
| { |
| // handling for environments 'unlinked fly frame' and |
| // 'group of linked fly frames': |
| // Nothing to do, <pPrevCntntFrm> is the one |
| } |
| else |
| { |
| const bool bInDocBody = pCurrCntntFrm->IsInDocBody(); |
| const bool bInFtn = pCurrCntntFrm->IsInFtn(); |
| if ( bInDocBody || ( bInFtn && !_bInSameFtn ) ) |
| { |
| // handling for environments 'footnotes' and 'document body frames': |
| // Assure that found previous frame is also in one of these |
| // environments. Otherwise, travel further |
| while ( pPrevCntntFrm ) |
| { |
| if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) || |
| ( bInFtn && pPrevCntntFrm->IsInFtn() ) ) |
| { |
| break; |
| } |
| pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm(); |
| } |
| } |
| else if ( bInFtn && _bInSameFtn ) |
| { |
| // handling for environments 'each footnote': |
| // Assure that found next content frame belongs to the same footnotes |
| const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() ); |
| const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() ); |
| if ( pFtnFrmOfPrev != pFtnFrmOfCurr ) |
| { |
| if ( pFtnFrmOfCurr->GetMaster() ) |
| { |
| SwFtnFrm* pMasterFtnFrmOfCurr( |
| const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); |
| pPrevCntntFrm = 0L; |
| // --> OD 2007-07-05 #146872# |
| // correct wrong loop-condition |
| do { |
| pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster(); |
| pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt(); |
| } while ( !pPrevCntntFrm && |
| pMasterFtnFrmOfCurr->GetMaster() ); |
| // <-- |
| } |
| else |
| { |
| // current content frame is the first content in the |
| // footnote - no previous content exists. |
| pPrevCntntFrm = 0L;; |
| } |
| } |
| } |
| else |
| { |
| // handling for environments 'page header' and 'page footer': |
| // Assure that found previous frame is also in the same |
| // page header respectively page footer as <pCurrCntntFrm> |
| // Note: At this point its clear, that <pCurrCntntFrm> has |
| // to be inside a page header or page footer and that |
| // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are |
| // inside a fly frame. |
| // Thus, method <FindFooterOrHeader()> can be used. |
| ASSERT( pCurrCntntFrm->FindFooterOrHeader(), |
| "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" ); |
| ASSERT( !pPrevCntntFrm->IsInFly(), |
| "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." ); |
| if ( pPrevCntntFrm->FindFooterOrHeader() != |
| pCurrCntntFrm->FindFooterOrHeader() ) |
| { |
| pPrevCntntFrm = 0L; |
| } |
| } |
| } |
| } |
| } |
| |
| return pPrevCntntFrm; |
| } |
| |
| SwFrm *SwFrm::_FindPrev() |
| { |
| sal_Bool bIgnoreTab = sal_False; |
| SwFrm *pThis = this; |
| |
| if ( IsTabFrm() ) |
| { |
| //Der erste Cntnt der Tabelle wird |
| //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh. |
| //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. |
| if ( ((SwTabFrm*)this)->IsFollow() ) |
| return ((SwTabFrm*)this)->FindMaster(); |
| else |
| pThis = ((SwTabFrm*)this)->ContainsCntnt(); |
| bIgnoreTab = sal_True; |
| } |
| |
| if ( pThis && pThis->IsCntntFrm() ) |
| { |
| SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm(); |
| if( !pPrvCnt ) |
| return 0; |
| if ( !bIgnoreTab && pThis->IsInTab() ) |
| { |
| SwLayoutFrm *pUp = pThis->GetUpper(); |
| while ( !pUp->IsCellFrm() ) |
| pUp = pUp->GetUpper(); |
| ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); |
| if ( pUp->IsAnLower( pPrvCnt ) ) |
| return pPrvCnt; |
| } |
| else |
| { |
| SwFrm* pRet; |
| const sal_Bool bBody = pThis->IsInDocBody(); |
| const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn(); |
| if ( bBody || bFtn ) |
| { |
| while ( pPrvCnt ) |
| { |
| if ( (bBody && pPrvCnt->IsInDocBody()) || |
| (bFtn && pPrvCnt->IsInFtn()) ) |
| { |
| pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() |
| : (SwFrm*)pPrvCnt; |
| return pRet; |
| } |
| pPrvCnt = pPrvCnt->GetPrevCntntFrm(); |
| } |
| } |
| else if ( pThis->IsInFly() ) |
| { |
| pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() |
| : (SwFrm*)pPrvCnt; |
| return pRet; |
| } |
| else //Fuss-/oder Kopfbereich oder Fly |
| { |
| const SwFrm *pUp = pThis->GetUpper(); |
| const SwFrm *pCntUp = pPrvCnt->GetUpper(); |
| while ( pUp && pUp->GetUpper() && |
| !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) |
| pUp = pUp->GetUpper(); |
| while ( pCntUp && pCntUp->GetUpper() ) |
| pCntUp = pCntUp->GetUpper(); |
| if ( pCntUp == pUp ) |
| { |
| pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() |
| : (SwFrm*)pPrvCnt; |
| return pRet; |
| } |
| } |
| } |
| } |
| return 0; |
| } |
| |
| void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn ) |
| { |
| SwFrm *pFrm; |
| if ( 0 != (pFrm = _FindNext()) ) |
| { |
| if( pFrm->IsSctFrm() ) |
| { |
| while( pFrm && pFrm->IsSctFrm() ) |
| { |
| if( ((SwSectionFrm*)pFrm)->GetSection() ) |
| { |
| SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); |
| if( pTmp ) |
| pTmp->InvalidatePos(); |
| else if( !bNoFtn ) |
| ((SwSectionFrm*)pFrm)->InvalidateFtnPos(); |
| if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) |
| pFrm->InvalidatePos(); |
| return; |
| } |
| pFrm = pFrm->FindNext(); |
| } |
| if( pFrm ) |
| { |
| if ( pFrm->IsSctFrm()) |
| { // Damit der Inhalt eines Bereichs die Chance erhaelt, |
| // die Seite zu wechseln, muss er ebenfalls invalidiert werden. |
| SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); |
| if( pTmp ) |
| pTmp->InvalidatePos(); |
| if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) |
| pFrm->InvalidatePos(); |
| } |
| else |
| pFrm->InvalidatePos(); |
| } |
| } |
| else |
| pFrm->InvalidatePos(); |
| } |
| } |
| |
| /** method to invalidate printing area of next frame |
| |
| OD 09.01.2004 #i11859# |
| |
| @author OD |
| |
| FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm |
| */ |
| void SwFrm::InvalidateNextPrtArea() |
| { |
| // determine next frame |
| SwFrm* pNextFrm = FindNext(); |
| // skip empty section frames and hidden text frames |
| { |
| while ( pNextFrm && |
| ( ( pNextFrm->IsSctFrm() && |
| !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) || |
| ( pNextFrm->IsTxtFrm() && |
| static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) ) |
| { |
| pNextFrm = pNextFrm->FindNext(); |
| } |
| } |
| |
| // Invalidate printing area of found next frame |
| if ( pNextFrm ) |
| { |
| if ( pNextFrm->IsSctFrm() ) |
| { |
| // Invalidate printing area of found section frame, if |
| // (1) this text frame isn't in a section OR |
| // (2) found section frame isn't a follow of the section frame this |
| // text frame is in. |
| if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm ) |
| { |
| pNextFrm->InvalidatePrt(); |
| } |
| |
| // Invalidate printing area of first content in found section. |
| SwFrm* pFstCntntOfSctFrm = |
| static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny(); |
| if ( pFstCntntOfSctFrm ) |
| { |
| pFstCntntOfSctFrm->InvalidatePrt(); |
| } |
| } |
| else |
| { |
| pNextFrm->InvalidatePrt(); |
| } |
| } |
| } |
| |
| /************************************************************************* |
| |* |
| |* lcl_IsInColSect() |
| |* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht, |
| |* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist. |
| |* |
| |*************************************************************************/ |
| |
| sal_Bool lcl_IsInColSct( const SwFrm *pUp ) |
| { |
| sal_Bool bRet = sal_False; |
| while( pUp ) |
| { |
| if( pUp->IsColumnFrm() ) |
| bRet = sal_True; |
| else if( pUp->IsSctFrm() ) |
| return bRet; |
| else if( pUp->IsTabFrm() ) |
| return sal_False; |
| pUp = pUp->GetUpper(); |
| } |
| return sal_False; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::IsMoveable(); |
| |* |
| |* Ersterstellung MA 09. Mar. 93 |
| |* Letzte Aenderung MA 05. May. 95 |
| |* |
| |*************************************************************************/ |
| /** determine, if frame is moveable in given environment |
| |
| OD 08.08.2003 #110978# |
| method replaced 'old' method <sal_Bool IsMoveable() const>. |
| Determines, if frame is moveable in given environment. if no environment |
| is given (parameter _pLayoutFrm == 0L), the movability in the actual |
| environment (<this->GetUpper()) is checked. |
| |
| @author OD |
| */ |
| |
| bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const |
| { |
| bool bRetVal = false; |
| |
| if ( !_pLayoutFrm ) |
| { |
| _pLayoutFrm = GetUpper(); |
| } |
| |
| if ( _pLayoutFrm && IsFlowFrm() ) |
| { |
| if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) ) |
| { |
| bRetVal = true; |
| } |
| else if ( _pLayoutFrm->IsInFly() || |
| _pLayoutFrm->IsInDocBody() || |
| _pLayoutFrm->IsInFtn() ) |
| { |
| if ( _pLayoutFrm->IsInTab() && !IsTabFrm() && |
| ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) ) |
| { |
| bRetVal = false; |
| } |
| else |
| { |
| if ( _pLayoutFrm->IsInFly() ) |
| { |
| // if fly frame has a follow (next linked fly frame), |
| // frame is moveable. |
| if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() ) |
| { |
| bRetVal = true; |
| } |
| else |
| { |
| // if environment is columned, frame is moveable, if |
| // it isn't in last column. |
| // search for column frame |
| const SwFrm* pCol = _pLayoutFrm; |
| while ( pCol && !pCol->IsColumnFrm() ) |
| { |
| pCol = pCol->GetUpper(); |
| } |
| // frame is moveable, if found column frame isn't last one. |
| if ( pCol && pCol->GetNext() ) |
| { |
| bRetVal = true; |
| } |
| } |
| } |
| else |
| { |
| bRetVal = true; |
| } |
| } |
| } |
| } |
| |
| return bRetVal; |
| } |
| |
| /************************************************************************* |
| |* |
| |* SwFrm::SetInfFlags(); |
| |* |
| |* Ersterstellung MA 05. Apr. 94 |
| |* Letzte Aenderung MA 05. Apr. 94 |
| |* |
| |*************************************************************************/ |
| void SwFrm::SetInfFlags() |
| { |
| if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen |
| return; //lieferbar |
| |
| bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False; |
| |
| SwFrm *pFrm = this; |
| if( IsFtnContFrm() ) |
| bInfFtn = sal_True; |
| do |
| { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt |
| if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper() |
| && pFrm->GetUpper()->IsPageFrm() ) |
| bInfBody = sal_True; |
| else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() ) |
| { |
| bInfTab = sal_True; |
| } |
| else if ( pFrm->IsFlyFrm() ) |
| bInfFly = sal_True; |
| else if ( pFrm->IsSctFrm() ) |
| bInfSct = sal_True; |
| else if ( pFrm->IsFtnFrm() ) |
| bInfFtn = sal_True; |
| |
| pFrm = pFrm->GetUpper(); |
| |
| } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix |
| } |
| |
| /*-----------------22.8.2001 14:30------------------ |
| * SwFrm::SetDirFlags( sal_Bool ) |
| * actualizes the vertical or the righttoleft-flags. |
| * If the property is derived, it's from the upper or (for fly frames) from |
| * the anchor. Otherwise we've to call a virtual method to check the property. |
| * --------------------------------------------------*/ |
| |
| void SwFrm::SetDirFlags( sal_Bool bVert ) |
| { |
| if( bVert ) |
| { |
| // OD 2004-01-21 #114969# - if derived, valid vertical flag only if |
| // vertical flag of upper/anchor is valid. |
| if( bDerivedVert ) |
| { |
| const SwFrm* pAsk = IsFlyFrm() ? |
| ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); |
| |
| ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) |
| |
| if( pAsk ) |
| { |
| bVertical = pAsk->IsVertical() ? 1 : 0; |
| bReverse = pAsk->IsReverse() ? 1 : 0; |
| |
| bVertLR = pAsk->IsVertLR() ? 1 : 0; |
| //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin |
| if ( !pAsk->bInvalidVert ) |
| bInvalidVert = sal_False; |
| } |
| } |
| else |
| CheckDirection( bVert ); |
| } |
| else |
| { |
| sal_Bool bInv = 0; |
| if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L! |
| CheckDirection( bVert ); |
| if( bDerivedR2L ) |
| { |
| const SwFrm* pAsk = IsFlyFrm() ? |
| ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); |
| |
| ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) |
| |
| if( pAsk ) |
| bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0; |
| if( !pAsk || pAsk->bInvalidR2L ) |
| bInv = bInvalidR2L; |
| } |
| bInvalidR2L = bInv; |
| } |
| } |
| |
| SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType ) |
| { |
| SwFrm* pTmpFrm = this; |
| while ( !pTmpFrm->IsCellFrm() ) |
| pTmpFrm = pTmpFrm->GetUpper(); |
| |
| ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" ) |
| return ((SwCellFrm*)pTmpFrm)->GetFollowCell(); |
| } |
| |
| SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType ) |
| { |
| SwFrm* pTmpFrm = this; |
| while ( !pTmpFrm->IsCellFrm() ) |
| pTmpFrm = pTmpFrm->GetUpper(); |
| |
| ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" ) |
| return ((SwCellFrm*)pTmpFrm)->GetPreviousCell(); |
| } |
| |
| SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow, |
| const SwCellFrm& rOrigCell, |
| const SwRowFrm& rCorrRow, |
| bool bInFollow ) |
| { |
| SwCellFrm* pRet = NULL; |
| SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower(); |
| SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower(); |
| |
| while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) ) |
| { |
| pCell = (SwCellFrm*)pCell->GetNext(); |
| pCorrCell = (SwCellFrm*)pCorrCell->GetNext(); |
| } |
| |
| ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" ) |
| |
| if ( pCell != &rOrigCell ) |
| { |
| // rOrigCell must be a lower of pCell. We need to recurse into the rows: |
| ASSERT( pCell->Lower() && pCell->Lower()->IsRowFrm(), |
| "lcl_FindCorrespondingCellFrm does not work" ) |
| |
| SwRowFrm* pRow = (SwRowFrm*)pCell->Lower(); |
| while ( !pRow->IsAnLower( &rOrigCell ) ) |
| pRow = (SwRowFrm*)pRow->GetNext(); |
| |
| SwRowFrm* pCorrRow = 0; |
| if ( bInFollow ) |
| pCorrRow = pRow->GetFollowRow(); |
| else |
| { |
| SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower()); |
| |
| if ( pTmpRow && pTmpRow->GetFollowRow() == pRow ) |
| pCorrRow = pTmpRow; |
| } |
| |
| if ( pCorrRow ) |
| pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow ); |
| } |
| else |
| pRet = pCorrCell; |
| |
| return pRet; |
| } |
| |
| // VERSION OF GetFollowCell() that assumes that we always have a follow flow line: |
| SwCellFrm* SwCellFrm::GetFollowCell() const |
| { |
| SwCellFrm* pRet = NULL; |
| |
| // NEW TABLES |
| // Covered cells do not have follow cells! |
| const long nRowSpan = GetLayoutRowSpan(); |
| if ( nRowSpan < 1 ) |
| return NULL; |
| |
| // find most upper row frame |
| const SwFrm* pRow = GetUpper(); |
| while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) |
| pRow = pRow->GetUpper(); |
| |
| if ( !pRow ) |
| return NULL; |
| |
| const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() ); |
| if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() ) |
| return NULL; |
| |
| const SwCellFrm* pThisCell = this; |
| |
| // Get last cell of the current table frame that belongs to the rowspan: |
| if ( nRowSpan > 1 ) |
| { |
| // optimization: Will end of row span be in last row or exceed row? |
| long nMax = 0; |
| while ( pRow->GetNext() && ++nMax < nRowSpan ) |
| pRow = pRow->GetNext(); |
| |
| if ( !pRow->GetNext() ) |
| { |
| pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true ); |
| pRow = pThisCell->GetUpper(); |
| } |
| } |
| |
| const SwRowFrm* pFollowRow = NULL; |
| if ( !pRow->GetNext() && |
| NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) && |
| ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) ) |
| pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true ); |
| |
| return pRet; |
| } |
| |
| // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL |
| SwCellFrm* SwCellFrm::GetPreviousCell() const |
| { |
| SwCellFrm* pRet = NULL; |
| |
| // NEW TABLES |
| // Covered cells do not have previous cells! |
| if ( GetLayoutRowSpan() < 1 ) |
| return NULL; |
| |
| // find most upper row frame |
| const SwFrm* pRow = GetUpper(); |
| while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) |
| pRow = pRow->GetUpper(); |
| |
| ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" ); |
| |
| SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); |
| |
| if ( pTab->IsFollow() ) |
| { |
| const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); |
| const bool bIsInFirstLine = ( pTmp == pRow ); |
| |
| if ( bIsInFirstLine ) |
| { |
| SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster(); |
| if ( pMaster && pMaster->HasFollowFlowLine() ) |
| { |
| SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower()); |
| if ( pMasterRow ) |
| pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false ); |
| if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 ) |
| pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true )); |
| } |
| } |
| } |
| |
| return pRet; |
| } |
| |
| // --> NEW TABLES |
| const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const |
| { |
| const SwCellFrm* pRet = 0; |
| |
| const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper()); |
| |
| if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) ) |
| return *this; |
| |
| ASSERT( pTableFrm && |
| ( bStart && GetTabBox()->getRowSpan() < 1 || |
| !bStart && GetLayoutRowSpan() > 1 ), |
| "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" ) |
| |
| if ( pTableFrm ) |
| { |
| const SwTable* pTable = pTableFrm->GetTable(); |
| |
| sal_uInt16 nMax = USHRT_MAX; |
| if ( bCurrentTableOnly ) |
| { |
| const SwFrm* pCurrentRow = GetUpper(); |
| const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() && |
| !pTableFrm->IsInHeadline( *pCurrentRow ); |
| |
| // check how many rows we are allowed to go up or down until we reach the end of |
| // the current table frame: |
| nMax = 0; |
| while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() ) |
| { |
| if ( bStart ) |
| { |
| // do not enter a repeated headline: |
| if ( bDoNotEnterHeadline && pTableFrm->IsFollow() && |
| pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) ) |
| break; |
| |
| pCurrentRow = pCurrentRow->GetPrev(); |
| } |
| else |
| pCurrentRow = pCurrentRow->GetNext(); |
| |
| ++nMax; |
| } |
| } |
| |
| // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly |
| // is set) we assure that we find a rMasterBox that has a SwCellFrm in |
| // the current table frame: |
| const SwTableBox& rMasterBox = bStart ? |
| GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) : |
| GetTabBox()->FindEndOfRowSpan( *pTable, nMax ); |
| |
| SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() ); |
| |
| for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() ) |
| { |
| if ( pMasterCell->GetTabBox() == &rMasterBox ) |
| { |
| const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper()); |
| |
| if ( bCurrentTableOnly ) |
| { |
| if ( pMasterTable == pTableFrm ) |
| { |
| pRet = pMasterCell; |
| break; |
| } |
| } |
| else |
| { |
| if ( pMasterTable == pTableFrm || |
| ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) || |
| (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) ) |
| { |
| pRet = pMasterCell; |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" ) |
| |
| return *pRet; |
| } |
| // <-- NEW TABLES |
| |
| const SwRowFrm* SwFrm::IsInSplitTableRow() const |
| { |
| ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) |
| |
| const SwFrm* pRow = this; |
| |
| // find most upper row frame |
| while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) |
| pRow = pRow->GetUpper(); |
| |
| if ( !pRow ) return NULL; |
| |
| ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) |
| |
| const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); |
| // --> OD 2006-06-28 #b6443897# |
| // If most upper row frame is a headline row, the current frame |
| // can't be in a splitted table row. Thus, add corresponding condition. |
| if ( pRow->GetNext() || |
| pTab->GetTable()->IsHeadline( |
| *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) || |
| !pTab->HasFollowFlowLine() || |
| !pTab->GetFollow() ) |
| return NULL; |
| // <-- |
| |
| // skip headline |
| const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow(); |
| |
| ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" ) |
| |
| return pFollowRow; |
| } |
| |
| const SwRowFrm* SwFrm::IsInFollowFlowRow() const |
| { |
| ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) |
| |
| // find most upper row frame |
| const SwFrm* pRow = this; |
| while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) |
| pRow = pRow->GetUpper(); |
| |
| if ( !pRow ) return NULL; |
| |
| ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) |
| |
| const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); |
| |
| const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0; |
| |
| if ( !pMaster || !pMaster->HasFollowFlowLine() ) |
| return NULL; |
| |
| const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); |
| const bool bIsInFirstLine = ( pTmp == pRow ); |
| |
| if ( !bIsInFirstLine ) |
| return NULL; |
| |
| const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower()); |
| return pMasterRow; |
| } |
| |
| bool SwFrm::IsInBalancedSection() const |
| { |
| bool bRet = false; |
| |
| if ( IsInSct() ) |
| { |
| const SwSectionFrm* pSectionFrm = FindSctFrm(); |
| if ( pSectionFrm ) |
| bRet = pSectionFrm->IsBalancedSection(); |
| } |
| return bRet; |
| } |
| |
| /* |
| * SwLayoutFrm::GetLastLower() |
| */ |
| const SwFrm* SwLayoutFrm::GetLastLower() const |
| { |
| const SwFrm* pRet = Lower(); |
| if ( !pRet ) |
| return 0; |
| while ( pRet->GetNext() ) |
| pRet = pRet->GetNext(); |
| return pRet; |
| } |