1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: trvlfrm.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
37 #include <tools/bigint.hxx>
38 #include <svx/protitem.hxx>
39 #include <vcl/settings.hxx>
40 #include <vcl/outdev.hxx>
41 #include <fmtpdsc.hxx>
42 #include <fmtsrnd.hxx>
43 #include <pagedesc.hxx>
44 #include <pagefrm.hxx>
45 #include <rootfrm.hxx>
51 #include <cellfrm.hxx>
54 #include <viewopt.hxx>
58 #include <swtable.hxx>
59 #include <dflyobj.hxx>
60 #include <crstate.hxx>
61 #include <frmtool.hxx>
63 // OD 2004-05-24 #i28701#
64 #include <sortedobjs.hxx>
68 #include <swselectionlist.hxx>
70 //Fuer SwFlyFrm::GetCrsrOfst
71 class SwCrsrOszControl
74 // damit schon der Compiler die Klasse initialisieren kann, keinen
75 // DTOR und member als publics:
76 const SwFlyFrm
*pEntry
;
77 const SwFlyFrm
*pStk1
;
78 const SwFlyFrm
*pStk2
;
81 // SwCrsrOszControl() : pStk1( 0 ), pStk2( 0 ) {}; // ; <- ????
83 BOOL
ChkOsz( const SwFlyFrm
*pFly
)
86 if ( pFly
!= pStk1
&& pFly
!= pStk2
)
94 void Entry( const SwFlyFrm
*pFly
)
97 pEntry
= pStk1
= pFly
;
99 void Exit( const SwFlyFrm
*pFly
)
101 if ( pFly
== pEntry
)
102 pEntry
= pStk1
= pStk2
= 0;
106 static SwCrsrOszControl aOszCtrl
= { 0, 0, 0 };
108 /*************************************************************************
110 |* SwLayoutFrm::GetCrsrOfst()
112 |* Beschreibung: Sucht denjenigen CntntFrm, innerhalb dessen
113 |* PrtArea der Point liegt.
114 |* Ersterstellung MA 20. Jul. 92
115 |* Letzte Aenderung MA 23. May. 95
117 |*************************************************************************/
118 BOOL
SwLayoutFrm::GetCrsrOfst( SwPosition
*pPos
, Point
&rPoint
,
119 SwCrsrMoveState
* pCMS
) const
122 const SwFrm
*pFrm
= Lower();
123 while ( !bRet
&& pFrm
)
127 // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
128 const bool bCntntCheck
= pFrm
->IsTxtFrm() && pCMS
&& pCMS
->bCntntCheck
;
129 const SwRect
aPaintRect( bCntntCheck
?
134 if ( aPaintRect
.IsInside( rPoint
) &&
135 ( bCntntCheck
|| pFrm
->GetCrsrOfst( pPos
, rPoint
, pCMS
) ) )
138 pFrm
= pFrm
->GetNext();
139 if ( pCMS
&& pCMS
->bStop
)
145 /*************************************************************************
147 |* SwPageFrm::GetCrsrOfst()
149 |* Beschreibung: Sucht die Seite, innerhalb der der gesuchte Point
151 |* Ersterstellung MA 20. Jul. 92
152 |* Letzte Aenderung MA 18. Jul. 96
154 |*************************************************************************/
156 BOOL
SwPageFrm::GetCrsrOfst( SwPosition
*pPos
, Point
&rPoint
,
157 SwCrsrMoveState
* pCMS
) const
160 Point
aPoint( rPoint
);
162 // check, if we have to adjust the point
163 if ( !Frm().IsInside( aPoint
) )
165 aPoint
.X() = Max( aPoint
.X(), Frm().Left() );
166 aPoint
.X() = Min( aPoint
.X(), Frm().Right() );
167 aPoint
.Y() = Max( aPoint
.Y(), Frm().Top() );
168 aPoint
.Y() = Min( aPoint
.Y(), Frm().Bottom() );
171 //Koennte ein Freifliegender gemeint sein?
172 //Wenn sein Inhalt geschuetzt werden soll, so ist nix mit Crsr
173 //hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
174 if ( GetSortedObjs() )
176 SwOrderIter
aIter( this );
180 const SwVirtFlyDrawObj
* pObj
=
181 static_cast<const SwVirtFlyDrawObj
*>(aIter());
182 const SwFlyFrm
* pFly
= pObj
? pObj
->GetFlyFrm() : 0;
184 ( ( pCMS
? pCMS
->bSetInReadOnly
: FALSE
) ||
185 !pFly
->IsProtected() ) &&
186 pFly
->GetCrsrOfst( pPos
, aPoint
, pCMS
) )
192 if ( pCMS
&& pCMS
->bStop
)
200 //Wenn kein Cntnt unterhalb der Seite 'antwortet', so korrigieren
201 //wir den StartPoint und fangen nochmal eine Seite vor der
202 //aktuellen an. Mit Flys ist es dann allerdings vorbei.
203 if ( SwLayoutFrm::GetCrsrOfst( pPos
, aPoint
, pCMS
) )
207 if ( pCMS
&& (pCMS
->bStop
|| pCMS
->bExactOnly
) )
209 ((SwCrsrMoveState
*)pCMS
)->bStop
= TRUE
;
212 const SwCntntFrm
*pCnt
= GetCntntPos( aPoint
, FALSE
, FALSE
, FALSE
, pCMS
, FALSE
);
213 if ( pCMS
&& pCMS
->bStop
)
216 ASSERT( pCnt
, "Crsr is gone to a Black hole" );
217 if( pCMS
&& pCMS
->pFill
&& pCnt
->IsTxtFrm() )
218 bRet
= pCnt
->GetCrsrOfst( pPos
, rPoint
, pCMS
);
220 bRet
= pCnt
->GetCrsrOfst( pPos
, aPoint
, pCMS
);
224 // Set point to pCnt, delete mark
225 // this may happen, if pCnt is hidden
226 *pPos
= SwPosition( *pCnt
->GetNode(), SwIndex( (SwTxtNode
*)pCnt
->GetNode(), 0 ) );
238 bool SwLayoutFrm::FillSelection( SwSelectionList
& rList
, const SwRect
& rRect
) const
241 if( rRect
.IsOver(PaintArea()) )
243 const SwFrm
* pFrm
= Lower();
246 pFrm
->FillSelection( rList
, rRect
);
247 pFrm
= pFrm
->GetNext();
253 bool SwPageFrm::FillSelection( SwSelectionList
& rList
, const SwRect
& rRect
) const
256 if( rRect
.IsOver(PaintArea()) )
258 bRet
= SwLayoutFrm::FillSelection( rList
, rRect
);
259 if( GetSortedObjs() )
261 const SwSortedObjs
&rObjs
= *GetSortedObjs();
262 for ( USHORT i
= 0; i
< rObjs
.Count(); ++i
)
264 const SwAnchoredObject
* pAnchoredObj
= rObjs
[i
];
265 if( !pAnchoredObj
->ISA(SwFlyFrm
) )
267 const SwFlyFrm
* pFly
= static_cast<const SwFlyFrm
*>(pAnchoredObj
);
268 if( pFly
->FillSelection( rList
, rRect
) )
276 bool SwRootFrm::FillSelection( SwSelectionList
& aSelList
, const SwRect
& rRect
) const
278 const SwFrm
*pPage
= Lower();
279 const long nBottom
= rRect
.Bottom();
282 if( pPage
->Frm().Top() < nBottom
)
284 if( pPage
->Frm().Bottom() > rRect
.Top() )
285 pPage
->FillSelection( aSelList
, rRect
);
286 pPage
= pPage
->GetNext();
291 return !aSelList
.isEmpty();
294 /*************************************************************************
296 |* SwRootFrm::GetCrsrOfst()
298 |* Beschreibung: Reicht Primaer den Aufruf an die erste Seite weiter.
299 |* Wenn der 'reingereichte Point veraendert wird,
300 |* so wird FALSE zurueckgegeben.
301 |* Ersterstellung MA 01. Jun. 92
302 |* Letzte Aenderung MA 30. Nov. 94
304 |*************************************************************************/
305 BOOL
SwRootFrm::GetCrsrOfst( SwPosition
*pPos
, Point
&rPoint
,
306 SwCrsrMoveState
* pCMS
) const
308 sal_Bool bOldAction
= IsCallbackActionEnabled();
309 ((SwRootFrm
*)this)->SetCallbackActionEnabled( FALSE
);
310 ASSERT( (Lower() && Lower()->IsPageFrm()), "Keinen PageFrm gefunden." );
311 if( pCMS
&& pCMS
->pFill
)
312 ((SwCrsrMoveState
*)pCMS
)->bFillRet
= FALSE
;
313 Point aOldPoint
= rPoint
;
316 // search for page containing rPoint. The borders around the pages are considerd
317 const SwPageFrm
* pPage
= GetPageAtPos( rPoint
, 0, true );
319 // --> OD 2008-12-23 #i95626#
320 // special handling for <rPoint> beyond root frames area
322 rPoint
.X() > Frm().Right() &&
323 rPoint
.Y() > Frm().Bottom() )
325 pPage
= dynamic_cast<const SwPageFrm
*>(Lower());
326 while ( pPage
&& pPage
->GetNext() )
328 pPage
= dynamic_cast<const SwPageFrm
*>(pPage
->GetNext());
334 pPage
->SwPageFrm::GetCrsrOfst( pPos
, rPoint
, pCMS
);
337 ((SwRootFrm
*)this)->SetCallbackActionEnabled( bOldAction
);
343 return pCMS
->bFillRet
;
345 return aOldPoint
== rPoint
;
348 /*************************************************************************
350 |* SwCellFrm::GetCrsrOfst()
352 |* Beschreibung Wenn es sich um eine Cntnt-tragende Cell handelt wird
353 |* der Crsr notfalls mit Gewalt in einen der CntntFrms
355 |* In geschuetzte Zellen gibt es hier keinen Eingang.
356 |* Ersterstellung MA 04. Jun. 93
357 |* Letzte Aenderung MA 23. May. 95
359 |*************************************************************************/
360 BOOL
SwCellFrm::GetCrsrOfst( SwPosition
*pPos
, Point
&rPoint
,
361 SwCrsrMoveState
* pCMS
) const
363 // cell frame does not necessarily have a lower (split table cell)
367 if ( !(pCMS
?pCMS
->bSetInReadOnly
:FALSE
) &&
368 GetFmt()->GetProtect().IsCntntProtected() )
371 if ( pCMS
&& pCMS
->eState
== MV_TBLSEL
)
373 const SwTabFrm
*pTab
= FindTabFrm();
374 if ( pTab
->IsFollow() && pTab
->IsInHeadline( *this ) )
376 ((SwCrsrMoveState
*)pCMS
)->bStop
= TRUE
;
383 if ( Lower()->IsLayoutFrm() )
384 return SwLayoutFrm::GetCrsrOfst( pPos
, rPoint
, pCMS
);
390 const SwFrm
*pFrm
= Lower();
391 while ( pFrm
&& !bRet
)
394 if ( pFrm
->Frm().IsInside( rPoint
) )
396 bRet
= pFrm
->GetCrsrOfst( pPos
, rPoint
, pCMS
);
397 if ( pCMS
&& pCMS
->bStop
)
400 pFrm
= pFrm
->GetNext();
404 Point
*pPoint
= pCMS
&& pCMS
->pFill
? new Point( rPoint
) : NULL
;
405 const SwCntntFrm
*pCnt
= GetCntntPos( rPoint
, TRUE
);
406 if( pPoint
&& pCnt
->IsTxtFrm() )
408 pCnt
->GetCrsrOfst( pPos
, *pPoint
, pCMS
);
412 pCnt
->GetCrsrOfst( pPos
, rPoint
, pCMS
);
422 /*************************************************************************
424 |* SwFlyFrm::GetCrsrOfst()
426 |* Ersterstellung MA 15. Dec. 92
427 |* Letzte Aenderung MA 23. May. 95
429 |*************************************************************************/
430 //Problem: Wenn zwei Flys genau gleich gross sind und auf derselben
431 //Position stehen, so liegt jeder innerhalb des anderen.
432 //Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines
433 //anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet
434 //und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer
435 //endlosen Rekursion fuehren.
436 //Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das
437 //GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der
438 //am weitesten oben liegt.
440 BOOL
SwFlyFrm::GetCrsrOfst( SwPosition
*pPos
, Point
&rPoint
,
441 SwCrsrMoveState
* pCMS
) const
443 aOszCtrl
.Entry( this );
445 //Wenn der Point innerhalb des Fly sitzt wollen wir energisch
446 //versuchen den Crsr hineinzusetzen.
447 //Wenn der Point allerdings in einem Flys sitzt, der sich vollstaendig
448 //innerhalb des aktuellen befindet, so wird fuer diesen das
449 //GetCrsrOfst gerufen.
451 BOOL bInside
= Frm().IsInside( rPoint
) && Lower(),
454 //Wenn der Frm eine Grafik enthaelt, aber nur Text gewuenscht ist, so
455 //nimmt er den Crsr grundsaetzlich nicht an.
456 if ( bInside
&& pCMS
&& pCMS
->eState
== MV_SETONLYTEXT
&&
457 (!Lower() || Lower()->IsNoTxtFrm()) )
460 const SwPageFrm
*pPage
= FindPageFrm();
461 if ( bInside
&& pPage
&& pPage
->GetSortedObjs() )
463 SwOrderIter
aIter( pPage
);
465 while ( aIter() && !bRet
)
467 const SwVirtFlyDrawObj
* pObj
= static_cast<const SwVirtFlyDrawObj
*>(aIter());
468 const SwFlyFrm
* pFly
= pObj
? pObj
->GetFlyFrm() : 0;
469 if ( pFly
&& pFly
->Frm().IsInside( rPoint
) &&
470 Frm().IsInside( pFly
->Frm() ) )
472 if ( aOszCtrl
.ChkOsz( pFly
) ||
473 TRUE
== (bRet
= pFly
->GetCrsrOfst( pPos
, rPoint
, pCMS
)))
475 if ( pCMS
&& pCMS
->bStop
)
482 while ( bInside
&& !bRet
)
484 const SwFrm
*pFrm
= Lower();
485 while ( pFrm
&& !bRet
)
488 if ( pFrm
->Frm().IsInside( rPoint
) )
490 bRet
= pFrm
->GetCrsrOfst( pPos
, rPoint
, pCMS
);
491 if ( pCMS
&& pCMS
->bStop
)
494 pFrm
= pFrm
->GetNext();
498 Point
*pPoint
= pCMS
&& pCMS
->pFill
? new Point( rPoint
) : NULL
;
499 const SwCntntFrm
*pCnt
= GetCntntPos(
500 rPoint
, TRUE
, FALSE
, FALSE
, pCMS
);
501 if ( pCMS
&& pCMS
->bStop
)
503 if( pPoint
&& pCnt
->IsTxtFrm() )
505 pCnt
->GetCrsrOfst( pPos
, *pPoint
, pCMS
);
509 pCnt
->GetCrsrOfst( pPos
, rPoint
, pCMS
);
514 aOszCtrl
.Exit( this );
518 /*************************************************************************
520 |* Beschreibung Layoutabhaengiges Cursortravelling
521 |* Ersterstellung MA 23. Jul. 92
522 |* Letzte Aenderung MA 06. Sep. 93
524 |*************************************************************************/
525 BOOL
SwCntntFrm::LeftMargin(SwPaM
*pPam
) const
527 if( pPam
->GetNode() != (SwCntntNode
*)GetNode() )
529 ((SwCntntNode
*)GetNode())->
530 MakeStartIndex((SwIndex
*) &pPam
->GetPoint()->nContent
);
534 BOOL
SwCntntFrm::RightMargin(SwPaM
*pPam
, BOOL
) const
536 if( pPam
->GetNode() != (SwCntntNode
*)GetNode() )
538 ((SwCntntNode
*)GetNode())->
539 MakeEndIndex((SwIndex
*) &pPam
->GetPoint()->nContent
);
543 const SwCntntFrm
*lcl_GetNxtCnt( const SwCntntFrm
* pCnt
)
545 return pCnt
->GetNextCntntFrm();
548 const SwCntntFrm
*lcl_GetPrvCnt( const SwCntntFrm
* pCnt
)
550 return pCnt
->GetPrevCntntFrm();
553 typedef const SwCntntFrm
*(*GetNxtPrvCnt
)( const SwCntntFrm
* );
555 //Frame in wiederholter Headline?
556 BOOL
lcl_IsInRepeatedHeadline( const SwFrm
*pFrm
,
557 const SwTabFrm
** ppTFrm
= 0 )
559 const SwTabFrm
*pTab
= pFrm
->FindTabFrm();
562 return pTab
&& pTab
->IsFollow() && pTab
->IsInHeadline( *pFrm
);
566 //Ueberspringen geschuetzter Tabellenzellen. Optional auch
567 //Ueberspringen von wiederholten Headlines.
568 //MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen.
569 // FME: Skip follow flow cells
570 const SwCntntFrm
* MA_FASTCALL
lcl_MissProtectedFrames( const SwCntntFrm
*pCnt
,
571 GetNxtPrvCnt fnNxtPrv
,
574 BOOL bMissFollowFlowLine
)
576 if ( pCnt
&& pCnt
->IsInTab() )
578 BOOL bProtect
= TRUE
;
579 while ( pCnt
&& bProtect
)
581 const SwLayoutFrm
*pCell
= pCnt
->GetUpper();
582 while ( pCell
&& !pCell
->IsCellFrm() )
583 pCell
= pCell
->GetUpper();
585 ( ( bInReadOnly
|| !pCell
->GetFmt()->GetProtect().IsCntntProtected() ) &&
586 ( !bMissHeadline
|| !lcl_IsInRepeatedHeadline( pCell
) ) &&
587 ( !bMissFollowFlowLine
|| !pCell
->IsInFollowFlowRow() ) ) &&
588 !pCell
->IsCoveredCell() )
591 pCnt
= (*fnNxtPrv
)( pCnt
);
594 else if ( !bInReadOnly
)
595 while ( pCnt
&& pCnt
->IsProtected() )
596 pCnt
= (*fnNxtPrv
)( pCnt
);
601 BOOL MA_FASTCALL
lcl_UpDown( SwPaM
*pPam
, const SwCntntFrm
*pStart
,
602 GetNxtPrvCnt fnNxtPrv
, BOOL bInReadOnly
)
604 ASSERT( pPam
->GetNode() == (SwCntntNode
*)pStart
->GetNode(),
605 "lcl_UpDown arbeitet nicht fuer andere." );
607 const SwCntntFrm
*pCnt
= 0;
609 //Wenn gerade eine Tabellenselection laeuft muss ein bischen getricktst
610 //werden: Beim hochlaufen an den Anfang der Zelle gehen, beim runterlaufen
611 //an das Ende der Zelle gehen.
612 BOOL bTblSel
= false;
613 if ( pStart
->IsInTab() &&
614 pPam
->GetNode( TRUE
)->StartOfSectionNode() !=
615 pPam
->GetNode( FALSE
)->StartOfSectionNode() )
618 const SwLayoutFrm
*pCell
= pStart
->GetUpper();
619 while ( !pCell
->IsCellFrm() )
620 pCell
= pCell
->GetUpper();
623 // Check, if cell has a Prev/Follow cell:
625 const bool bFwd
= ( fnNxtPrv
== lcl_GetNxtCnt
);
626 const SwLayoutFrm
* pTmpCell
= bFwd
?
627 ((SwCellFrm
*)pCell
)->GetFollowCell() :
628 ((SwCellFrm
*)pCell
)->GetPreviousCell();
630 const SwCntntFrm
* pTmpStart
= pStart
;
631 while ( pTmpCell
&& 0 != ( pTmpStart
= pTmpCell
->ContainsCntnt() ) )
635 ((SwCellFrm
*)pCell
)->GetFollowCell() :
636 ((SwCellFrm
*)pCell
)->GetPreviousCell();
638 const SwCntntFrm
*pNxt
= pCnt
= pTmpStart
;
640 while ( pCell
->IsAnLower( pNxt
) )
643 pNxt
= (*fnNxtPrv
)( pNxt
);
647 pCnt
= (*fnNxtPrv
)( pCnt
? pCnt
: pStart
);
648 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
651 const SwTabFrm
*pStTab
= pStart
->FindTabFrm();
652 const SwTabFrm
*pTable
= 0;
653 const BOOL bTab
= pStTab
|| (pCnt
&& pCnt
->IsInTab()) ? TRUE
: FALSE
;
654 BOOL bEnd
= bTab
? FALSE
: TRUE
;
656 const SwFrm
* pVertRefFrm
= pStart
;
657 if ( bTblSel
&& pStTab
)
658 pVertRefFrm
= pStTab
;
659 SWRECTFN( pVertRefFrm
)
665 // pStart or pCnt is inside a table. nX will be used for travelling:
667 SwRect
aRect( pStart
->Frm() );
668 pStart
->GetCharRect( aRect
, *pPam
->GetPoint() );
669 Point aCenter
= aRect
.Center();
670 nX
= bVert
? aCenter
.Y() : aCenter
.X();
672 pTable
= pCnt
? pCnt
->FindTabFrm() : 0;
677 !pStTab
->GetUpper()->IsInTab() &&
678 !pTable
->GetUpper()->IsInTab() )
680 const SwFrm
*pCell
= pStart
->GetUpper();
681 while ( pCell
&& !pCell
->IsCellFrm() )
682 pCell
= pCell
->GetUpper();
683 ASSERT( pCell
, "Zelle nicht gefunden." );
684 nX
= (pCell
->Frm().*fnRect
->fnGetLeft
)() +
685 (pCell
->Frm().*fnRect
->fnGetWidth
)() / 2;
687 //Der Fluss fuehrt von einer Tabelle in die nachste. Der X-Wert
688 //muss ausgehend von der Mitte der Startzelle um die Verschiebung
689 //der Tabellen korrigiert werden.
690 if ( pStTab
!= pTable
)
692 nX
+= (pTable
->Frm().*fnRect
->fnGetLeft
)() -
693 (pStTab
->Frm().*fnRect
->fnGetLeft
)();
698 // Restrict nX to the left and right borders of pTab:
699 // (is this really necessary?)
701 if ( !pTable
->GetUpper()->IsInTab() )
703 const sal_Bool bRTL
= pTable
->IsRightToLeft();
704 const long nPrtLeft
= bRTL
?
705 (pTable
->*fnRect
->fnGetPrtRight
)() :
706 (pTable
->*fnRect
->fnGetPrtLeft
)();
707 if ( bRTL
!= nX
< nPrtLeft
)
711 const long nPrtRight
= bRTL
?
712 (pTable
->*fnRect
->fnGetPrtLeft
)() :
713 (pTable
->*fnRect
->fnGetPrtRight
)();
714 if ( bRTL
!= nX
> nPrtRight
)
722 //Wenn ich im DokumentBody bin, so will ich da auch bleiben
723 if ( pStart
->IsInDocBody() )
725 while ( pCnt
&& (!pCnt
->IsInDocBody() ||
726 (pCnt
->IsTxtFrm() && ((SwTxtFrm
*)pCnt
)->IsHiddenNow())))
728 pCnt
= (*fnNxtPrv
)( pCnt
);
729 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
733 //Wenn ich im Fussnotenbereich bin, so versuche ich notfalls den naechsten
734 //Fussnotenbereich zu erreichen.
735 else if ( pStart
->IsInFtn() )
737 while ( pCnt
&& (!pCnt
->IsInFtn() ||
738 (pCnt
->IsTxtFrm() && ((SwTxtFrm
*)pCnt
)->IsHiddenNow())))
740 pCnt
= (*fnNxtPrv
)( pCnt
);
741 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
745 //In Flys kann es Blind weitergehen solange ein Cntnt
747 else if ( pStart
->IsInFly() )
749 if ( pCnt
&& pCnt
->IsTxtFrm() && ((SwTxtFrm
*)pCnt
)->IsHiddenNow() )
751 pCnt
= (*fnNxtPrv
)( pCnt
);
752 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
756 //Andernfalls weigere ich mich einfach den derzeitigen Bereich zu
760 const SwFrm
*pUp
= pStart
->GetUpper(); //Head/Foot
761 while ( pUp
&& pUp
->GetUpper() && !(pUp
->GetType() & 0x0018 ) )
762 pUp
= pUp
->GetUpper();
764 const SwFrm
*pCntUp
= pCnt
->GetUpper();
765 while ( pCntUp
&& !bSame
)
766 { if ( pUp
== pCntUp
)
769 pCntUp
= pCntUp
->GetUpper();
773 else if ( pCnt
&& pCnt
->IsTxtFrm() && ((SwTxtFrm
*)pCnt
)->IsHiddenNow() ) // i73332
775 pCnt
= (*fnNxtPrv
)( pCnt
);
776 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
785 { const SwTabFrm
*pTab
= pCnt
->FindTabFrm();
790 if ( pTab
!= pTable
)
792 //Der Fluss fuehrt von einer Tabelle in die nachste. Der
793 //X-Wert muss um die Verschiebung der Tabellen korrigiert
796 !pTab
->GetUpper()->IsInTab() &&
797 !pTable
->GetUpper()->IsInTab() )
798 nX
+= pTab
->Frm().Left() - pTable
->Frm().Left();
801 const SwLayoutFrm
*pCell
= pTable
? pCnt
->GetUpper() : 0;
802 while ( pCell
&& !pCell
->IsCellFrm() )
803 pCell
= pCell
->GetUpper();
809 long nTmpTop
= (pCell
->Frm().*fnRect
->fnGetTop
)();
815 aInsideCell
= Point( nTmpTop
, nX
);
818 aInsideCell
= Point( nX
, nTmpTop
);
821 long nTmpTop
= (pCnt
->Frm().*fnRect
->fnGetTop
)();
827 aInsideCnt
= Point( nTmpTop
, nX
);
830 aInsideCnt
= Point( nX
, nTmpTop
);
832 if ( pCell
&& pCell
->Frm().IsInside( aInsideCell
) )
835 //Jetzt noch schnell den richtigen Cntnt in der Zelle
837 if ( !pCnt
->Frm().IsInside( aInsideCnt
) )
839 pCnt
= pCell
->ContainsCntnt();
840 if ( fnNxtPrv
== lcl_GetPrvCnt
)
841 while ( pCell
->IsAnLower(pCnt
->GetNextCntntFrm()) )
842 pCnt
= pCnt
->GetNextCntntFrm();
845 else if ( pCnt
->Frm().IsInside( aInsideCnt
) )
851 pCnt
= (*fnNxtPrv
)( pCnt
);
852 pCnt
= ::lcl_MissProtectedFrames( pCnt
, fnNxtPrv
, TRUE
, bInReadOnly
, bTblSel
);
857 (pCnt
&& pCnt
->IsTxtFrm() && ((SwTxtFrm
*)pCnt
)->IsHiddenNow()));
860 { // setze den Point auf den Content-Node
861 SwCntntNode
*pCNd
= (SwCntntNode
*)pCnt
->GetNode();
862 pPam
->GetPoint()->nNode
= *pCNd
;
863 if ( fnNxtPrv
== lcl_GetPrvCnt
)
864 pCNd
->MakeEndIndex( (SwIndex
*)&pPam
->GetPoint()->nContent
);
866 pCNd
->MakeStartIndex( (SwIndex
*)&pPam
->GetPoint()->nContent
);
872 BOOL
SwCntntFrm::UnitUp( SwPaM
* pPam
, const SwTwips
, BOOL bInReadOnly
) const
874 return ::lcl_UpDown( pPam
, this, lcl_GetPrvCnt
, bInReadOnly
);
877 BOOL
SwCntntFrm::UnitDown( SwPaM
* pPam
, const SwTwips
, BOOL bInReadOnly
) const
879 return ::lcl_UpDown( pPam
, this, lcl_GetNxtCnt
, bInReadOnly
);
882 /*************************************************************************
884 |* SwRootFrm::GetCurrPage()
886 |* Beschreibung: Liefert die Nummer der aktuellen Seite.
887 |* Wenn die Methode einen PaM bekommt, so ist die aktuelle Seite
888 |* diejenige in der der PaM sitzt. Anderfalls ist die aktuelle
889 |* Seite die erste Seite innerhalb der VisibleArea.
890 |* Es wird nur auf den vorhandenen Seiten gearbeitet!
891 |* Ersterstellung MA 20. May. 92
892 |* Letzte Aenderung MA 09. Oct. 97
894 |*************************************************************************/
895 USHORT
SwRootFrm::GetCurrPage( const SwPaM
*pActualCrsr
) const
897 ASSERT( pActualCrsr
, "Welche Seite soll's denn sein?" );
898 const SwFrm
*pActFrm
= GetFmt()->GetDoc()->GetNodes()[pActualCrsr
->GetPoint()->nNode
]->
899 GetCntntNode()->GetFrm( 0,
900 pActualCrsr
->GetPoint(),
902 return pActFrm
->FindPageFrm()->GetPhyPageNum();
905 /*************************************************************************
907 |* SwRootFrm::SetCurrPage()
909 |* Beschreibung: Liefert einen PaM der am Anfang der gewuenschten
911 |* Formatiert wird soweit notwendig
912 |* Liefert Null, wenn die Operation nicht moeglich ist.
913 |* Der PaM sitzt in der letzten Seite, wenn die Seitenzahl zu gross
915 |* Ersterstellung MA 20. May. 92
916 |* Letzte Aenderung MA 09. Oct. 97
918 |*************************************************************************/
919 USHORT
SwRootFrm::SetCurrPage( SwCursor
* pToSet
, USHORT nPageNum
)
921 ASSERT( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
923 SwPageFrm
*pPage
= (SwPageFrm
*)Lower();
925 while ( !bEnd
&& pPage
->GetPhyPageNum() != nPageNum
)
926 { if ( pPage
->GetNext() )
927 pPage
= (SwPageFrm
*)pPage
->GetNext();
929 { //Ersten CntntFrm Suchen, und solange Formatieren bis
930 //eine neue Seite angefangen wird oder bis die CntntFrm's alle
932 const SwCntntFrm
*pCntnt
= pPage
->ContainsCntnt();
933 while ( pCntnt
&& pPage
->IsAnLower( pCntnt
) )
936 pCntnt
= pCntnt
->GetNextCntntFrm();
938 //Jetzt ist entweder eine neue Seite da, oder die letzte Seite
940 if ( pPage
->GetNext() )
941 pPage
= (SwPageFrm
*)pPage
->GetNext();
946 //pPage zeigt jetzt auf die 'gewuenschte' Seite. Jetzt muss noch der
947 //PaM auf den Anfang des ersten CntntFrm im Body-Text erzeugt werden.
948 //Wenn es sich um eine Fussnotenseite handelt, wird der PaM in die erste
950 const SwCntntFrm
*pCntnt
= pPage
->ContainsCntnt();
951 if ( pPage
->IsFtnPage() )
952 while ( pCntnt
&& !pCntnt
->IsInFtn() )
953 pCntnt
= pCntnt
->GetNextCntntFrm();
955 while ( pCntnt
&& !pCntnt
->IsInDocBody() )
956 pCntnt
= pCntnt
->GetNextCntntFrm();
959 SwCntntNode
* pCNd
= (SwCntntNode
*)pCntnt
->GetNode();
960 pToSet
->GetPoint()->nNode
= *pCNd
;
961 pCNd
->MakeStartIndex( (SwIndex
*)&pToSet
->GetPoint()->nContent
);
962 pToSet
->GetPoint()->nContent
= ((SwTxtFrm
*)pCntnt
)->GetOfst();
964 SwShellCrsr
* pSCrsr
= dynamic_cast<SwShellCrsr
*>(pToSet
);
967 Point
&rPt
= pSCrsr
->GetPtPos();
968 rPt
= pCntnt
->Frm().Pos();
969 rPt
+= pCntnt
->Prt().Pos();
971 return pPage
->GetPhyPageNum();
976 /*************************************************************************
978 |* SwCntntFrm::StartxxPage(), EndxxPage()
980 |* Beschreibung Cursor an Anfang/Ende der aktuellen/vorherigen/
981 |* naechsten Seite. Alle sechs Methoden rufen GetFrmInPage() mit der
982 |* entsprechenden Parametrisierung.
983 |* Zwei Parameter steuern die Richtung: einer bestimmt die Seite, der
984 |* andere Anfang/Ende.
985 |* Fuer die Bestimmung der Seite und des Cntnt (Anfang/Ende) werden
986 |* die im folgenden definierten Funktionen benutzt.
987 |* Ersterstellung MA 15. Oct. 92
988 |* Letzte Aenderung MA 28. Feb. 93
990 |*************************************************************************/
991 SwCntntFrm
*GetFirstSub( const SwLayoutFrm
*pLayout
)
993 return ((SwPageFrm
*)pLayout
)->FindFirstBodyCntnt();
996 SwCntntFrm
*GetLastSub( const SwLayoutFrm
*pLayout
)
998 return ((SwPageFrm
*)pLayout
)->FindLastBodyCntnt();
1001 SwLayoutFrm
*GetNextFrm( const SwLayoutFrm
*pFrm
)
1003 SwLayoutFrm
*pNext
=
1004 (pFrm
->GetNext() && pFrm
->GetNext()->IsLayoutFrm()) ?
1005 (SwLayoutFrm
*)pFrm
->GetNext() : 0;
1006 // #i39402# in case of an empty page
1007 if(pNext
&& !pNext
->ContainsCntnt())
1008 pNext
= (pNext
->GetNext() && pNext
->GetNext()->IsLayoutFrm()) ?
1009 (SwLayoutFrm
*)pNext
->GetNext() : 0;
1013 SwLayoutFrm
*GetThisFrm( const SwLayoutFrm
*pFrm
)
1015 return (SwLayoutFrm
*)pFrm
;
1018 SwLayoutFrm
*GetPrevFrm( const SwLayoutFrm
*pFrm
)
1020 SwLayoutFrm
*pPrev
=
1021 (pFrm
->GetPrev() && pFrm
->GetPrev()->IsLayoutFrm()) ?
1022 (SwLayoutFrm
*)pFrm
->GetPrev() : 0;
1023 // #i39402# in case of an empty page
1024 if(pPrev
&& !pPrev
->ContainsCntnt())
1025 pPrev
= (pPrev
->GetPrev() && pPrev
->GetPrev()->IsLayoutFrm()) ?
1026 (SwLayoutFrm
*)pPrev
->GetPrev() : 0;
1030 //Jetzt koennen auch die Funktionspointer initalisiert werden;
1031 //sie sind in cshtyp.hxx declariert.
1032 SwPosPage fnPageStart
= GetFirstSub
;
1033 SwPosPage fnPageEnd
= GetLastSub
;
1034 SwWhichPage fnPagePrev
= GetPrevFrm
;
1035 SwWhichPage fnPageCurr
= GetThisFrm
;
1036 SwWhichPage fnPageNext
= GetNextFrm
;
1038 //Liefert den ersten/den letzten Contentframe (gesteuert ueber
1039 //den Parameter fnPosPage) in der
1040 //aktuellen/vorhergehenden/folgenden Seite (gesteuert durch den
1041 //Parameter fnWhichPage).
1042 BOOL
GetFrmInPage( const SwCntntFrm
*pCnt
, SwWhichPage fnWhichPage
,
1043 SwPosPage fnPosPage
, SwPaM
*pPam
)
1045 //Erstmal die gewuenschte Seite besorgen, anfangs die aktuelle, dann
1046 //die die per fnWichPage gewuenscht wurde
1047 const SwLayoutFrm
*pLayoutFrm
= pCnt
->FindPageFrm();
1048 if ( !pLayoutFrm
|| (0 == (pLayoutFrm
= (*fnWhichPage
)(pLayoutFrm
))) )
1051 //Jetzt den gewuenschen CntntFrm unterhalb der Seite
1052 if( 0 == (pCnt
= (*fnPosPage
)(pLayoutFrm
)) )
1056 // repeated headlines in tables
1057 if ( pCnt
->IsInTab() && fnPosPage
== GetFirstSub
)
1059 const SwTabFrm
* pTab
= pCnt
->FindTabFrm();
1060 if ( pTab
->IsFollow() )
1062 if ( pTab
->IsInHeadline( *pCnt
) )
1064 SwLayoutFrm
* pRow
= pTab
->GetFirstNonHeadlineRow();
1067 // We are in the first line of a follow table
1068 // with repeated headings.
1069 // To actually make a "real" move we take the first content
1071 pCnt
= pRow
->ContainsCntnt();
1079 SwCntntNode
*pCNd
= (SwCntntNode
*)pCnt
->GetNode();
1080 pPam
->GetPoint()->nNode
= *pCNd
;
1082 if( fnPosPage
== GetFirstSub
)
1083 nIdx
= ((SwTxtFrm
*)pCnt
)->GetOfst();
1085 nIdx
= pCnt
->GetFollow() ?
1086 ((SwTxtFrm
*)pCnt
)->GetFollow()->GetOfst()-1 : pCNd
->Len();
1087 pPam
->GetPoint()->nContent
.Assign( pCNd
, nIdx
);
1092 /*************************************************************************
1094 |* SwLayoutFrm::GetCntntPos()
1096 |* Beschreibung Es wird der nachstliegende Cntnt zum uebergebenen
1097 |* gesucht. Betrachtet werden die vorhergehende, die
1098 |* aktuelle und die folgende Seite.
1099 |* Wenn kein Inhalt gefunden wird, so wird der Bereich
1100 * erweitert bis einer gefunden wird.
1101 |* Zurueckgegeben wird die 'Semantisch richtige' Position
1102 |* innerhalb der PrtArea des gefundenen CntntFrm
1103 |* Ersterstellung MA 15. Jul. 92
1104 |* Letzte Aenderung MA 09. Jan. 97
1106 |*************************************************************************/
1107 ULONG
CalcDiff( const Point
&rPt1
, const Point
&rPt2
)
1109 //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
1110 //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
1111 sal_uInt32 dX
= Max( rPt1
.X(), rPt2
.X() ) -
1112 Min( rPt1
.X(), rPt2
.X() ),
1113 dY
= Max( rPt1
.Y(), rPt2
.Y() ) -
1114 Min( rPt1
.Y(), rPt2
.Y() );
1115 BigInt
dX1( dX
), dY1( dY
);
1116 dX1
*= dX1
; dY1
*= dY1
;
1117 return ::SqRt( dX1
+ dY1
);
1120 // lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem
1121 // auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang
1122 // Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer.
1123 // Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt,
1124 // eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn
1125 // dessen Abstand zum Punkt geringer ist.
1127 const SwLayoutFrm
* lcl_Inside( const SwCntntFrm
*pCnt
, Point
& rPt
)
1129 const SwLayoutFrm
* pUp
= pCnt
->GetUpper();
1132 if( pUp
->IsPageBodyFrm() || pUp
->IsFooterFrm() || pUp
->IsHeaderFrm() )
1134 if( rPt
.Y() >= pUp
->Frm().Top() && rPt
.Y() <= pUp
->Frm().Bottom() )
1138 if( pUp
->IsFtnContFrm() )
1139 return pUp
->Frm().IsInside( rPt
) ? pUp
: NULL
;
1140 pUp
= pUp
->GetUpper();
1145 const SwCntntFrm
*SwLayoutFrm::GetCntntPos( Point
& rPoint
,
1146 const BOOL bDontLeave
,
1147 const BOOL bBodyOnly
,
1149 const SwCrsrMoveState
*pCMS
,
1150 const BOOL bDefaultExpand
) const
1152 //Ersten CntntFrm ermitteln.
1153 const SwLayoutFrm
*pStart
= (!bDontLeave
&& bDefaultExpand
&& GetPrev()) ?
1154 (SwLayoutFrm
*)GetPrev() : this;
1155 const SwCntntFrm
*pCntnt
= pStart
->ContainsCntnt();
1157 if ( !pCntnt
&& (GetPrev() && !bDontLeave
) )
1158 pCntnt
= ContainsCntnt();
1160 if ( bBodyOnly
&& pCntnt
&& !pCntnt
->IsInDocBody() )
1161 while ( pCntnt
&& !pCntnt
->IsInDocBody() )
1162 pCntnt
= pCntnt
->GetNextCntntFrm();
1164 const SwCntntFrm
*pActual
= pCntnt
;
1165 const SwLayoutFrm
*pInside
= NULL
;
1166 USHORT nMaxPage
= GetPhyPageNum() + (bDefaultExpand
? 1 : 0);
1167 Point aPoint
= rPoint
;
1168 ULONG nDistance
= ULONG_MAX
;
1170 while ( TRUE
) //Sicherheitsschleifchen, damit immer einer gefunden wird.
1173 ((!bDontLeave
|| IsAnLower( pCntnt
)) &&
1174 (pCntnt
->GetPhyPageNum() <= nMaxPage
)) )
1176 if ( ( bCalc
|| pCntnt
->Frm().Width() ) &&
1177 ( !bBodyOnly
|| pCntnt
->IsInDocBody() ) )
1179 //Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section)
1180 //liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht.
1181 const SwCntntFrm
*pComp
= pCntnt
;
1182 pCntnt
= ::lcl_MissProtectedFrames( pCntnt
, lcl_GetNxtCnt
, FALSE
,
1183 pCMS
? pCMS
->bSetInReadOnly
: FALSE
, FALSE
);
1184 if ( pComp
!= pCntnt
)
1187 if ( !pCntnt
->IsTxtFrm() || !((SwTxtFrm
*)pCntnt
)->IsHiddenNow() )
1192 SwRect
aCntFrm( pCntnt
->UnionFrm() );
1193 if ( aCntFrm
.IsInside( rPoint
) )
1199 //Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird
1201 Point
aCntntPoint( rPoint
);
1203 //Erst die Vertikale Position einstellen
1204 if ( aCntFrm
.Top() > aCntntPoint
.Y() )
1205 aCntntPoint
.Y() = aCntFrm
.Top();
1206 else if ( aCntFrm
.Bottom() < aCntntPoint
.Y() )
1207 aCntntPoint
.Y() = aCntFrm
.Bottom();
1209 //Jetzt die Horizontale Position
1210 if ( aCntFrm
.Left() > aCntntPoint
.X() )
1211 aCntntPoint
.X() = aCntFrm
.Left();
1212 else if ( aCntFrm
.Right() < aCntntPoint
.X() )
1213 aCntntPoint
.X() = aCntFrm
.Right();
1215 // pInside ist ein Seitenbereich, in dem der Punkt liegt,
1216 // sobald pInside!=0 ist, werden nur noch Frames akzeptiert,
1217 // die innerhalb liegen.
1218 if( !pInside
|| ( pInside
->IsAnLower( pCntnt
) &&
1219 ( !pCntnt
->IsInFtn() || pInside
->IsFtnContFrm() ) ) )
1221 const ULONG nDiff
= ::CalcDiff( aCntntPoint
, rPoint
);
1222 BOOL bBetter
= nDiff
< nDistance
; // Dichter dran
1225 pInside
= lcl_Inside( pCntnt
, rPoint
);
1226 if( pInside
) // Im "richtigen" Seitenteil
1231 aPoint
= aCntntPoint
;
1238 pCntnt
= pCntnt
->GetNextCntntFrm();
1240 while ( pCntnt
&& !pCntnt
->IsInDocBody() )
1241 pCntnt
= pCntnt
->GetNextCntntFrm();
1244 { //Wenn noch keiner gefunden wurde muss der Suchbereich erweitert
1245 //werden, irgenwann muessen wir einen Finden!
1246 //MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im
1247 //Body suchen, koennen wir den Suchbereich gleich in einem
1248 //Schritt hinreichend erweitern.
1251 while ( !pCntnt
&& pStart
->GetPrev() )
1254 if( !pStart
->GetPrev()->IsLayoutFrm() )
1256 pStart
= (SwLayoutFrm
*)pStart
->GetPrev();
1257 pCntnt
= pStart
->IsInDocBody()
1258 ? pStart
->ContainsCntnt()
1259 : pStart
->FindPageFrm()->FindFirstBodyCntnt();
1261 if ( !pCntnt
) //irgendwann muessen wir mit irgendeinem Anfangen!
1263 pCntnt
= pStart
->FindPageFrm()->GetUpper()->ContainsCntnt();
1264 while ( pCntnt
&& !pCntnt
->IsInDocBody() )
1265 pCntnt
= pCntnt
->GetNextCntntFrm();
1267 return 0; //Es gibt noch keine Dokumentinhalt!
1273 if ( pStart
->GetPrev() )
1275 if( !pStart
->GetPrev()->IsLayoutFrm() )
1277 pStart
= (SwLayoutFrm
*)pStart
->GetPrev();
1278 pCntnt
= pStart
->ContainsCntnt();
1280 else //irgendwann muessen wir mit irgendeinem Anfangen!
1281 pCntnt
= pStart
->FindPageFrm()->GetUpper()->ContainsCntnt();
1290 ASSERT( pActual
, "Keinen Cntnt gefunden." );
1292 ASSERT( pActual
->IsInDocBody(), "Cnt nicht im Body." );
1295 //Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte
1297 if ( pActual
->IsInTab() && pCMS
&& pCMS
->eState
== MV_TBLSEL
)
1299 const SwTabFrm
*pTab
= pActual
->FindTabFrm();
1300 if ( pTab
->IsFollow() && pTab
->IsInHeadline( *pActual
) )
1302 ((SwCrsrMoveState
*)pCMS
)->bStop
= TRUE
;
1307 //Jetzt noch eine kleine Korrektur beim ersten/letzten
1308 Size
aActualSize( pActual
->Prt().SSize() );
1309 if ( aActualSize
.Height() > pActual
->GetUpper()->Prt().Height() )
1310 aActualSize
.Height() = pActual
->GetUpper()->Prt().Height();
1313 if ( !pActual
->GetPrev() &&
1314 (*fnRect
->fnYDiff
)( (pActual
->*fnRect
->fnGetPrtTop
)(),
1315 bVert
? rPoint
.X() : rPoint
.Y() ) > 0 )
1317 aPoint
.Y() = pActual
->Frm().Top() + pActual
->Prt().Top();
1318 aPoint
.X() = pActual
->Frm().Left() +
1319 ( pActual
->IsRightToLeft() || bVert
?
1320 pActual
->Prt().Right() :
1321 pActual
->Prt().Left() );
1323 else if ( !pActual
->GetNext() &&
1324 (*fnRect
->fnYDiff
)( (pActual
->*fnRect
->fnGetPrtBottom
)(),
1325 bVert
? rPoint
.X() : rPoint
.Y() ) < 0 )
1327 aPoint
.Y() = pActual
->Frm().Top() + pActual
->Prt().Bottom();
1328 aPoint
.X() = pActual
->Frm().Left() +
1329 ( pActual
->IsRightToLeft() || bVert
?
1330 pActual
->Prt().Left() :
1331 pActual
->Prt().Right() );
1334 //Und den Point in die PrtArea bringen
1337 const SwRect
aRect( pActual
->Frm().Pos() + pActual
->Prt().Pos(),
1339 if ( aPoint
.Y() < aRect
.Top() )
1340 aPoint
.Y() = aRect
.Top();
1341 else if ( aPoint
.Y() > aRect
.Bottom() )
1342 aPoint
.Y() = aRect
.Bottom();
1343 if ( aPoint
.X() < aRect
.Left() )
1344 aPoint
.X() = aRect
.Left();
1345 else if ( aPoint
.X() > aRect
.Right() )
1346 aPoint
.X() = aRect
.Right();
1351 /*************************************************************************
1353 |* SwPageFrm::GetCntntPosition()
1355 |* Beschreibung Analog zu SwLayoutFrm::GetCntntPos().
1356 |* Spezialisiert fuer Felder in Rahmen.
1358 |* Ersterstellung MA 22. Mar. 95
1359 |* Letzte Aenderung MA 07. Nov. 95
1361 |*************************************************************************/
1362 void SwPageFrm::GetCntntPosition( const Point
&rPt
, SwPosition
&rPos
) const
1364 //Ersten CntntFrm ermitteln.
1365 const SwCntntFrm
*pCntnt
= ContainsCntnt();
1368 //Einen weiter zurueck schauen (falls moeglich).
1369 const SwCntntFrm
*pTmp
= pCntnt
->GetPrevCntntFrm();
1370 while ( pTmp
&& !pTmp
->IsInDocBody() )
1371 pTmp
= pTmp
->GetPrevCntntFrm();
1376 pCntnt
= GetUpper()->ContainsCntnt();
1378 const SwCntntFrm
*pAct
= pCntnt
;
1380 ULONG nDist
= ULONG_MAX
;
1384 SwRect
aCntFrm( pCntnt
->UnionFrm() );
1385 if ( aCntFrm
.IsInside( rPt
) )
1387 //dichter gehts nimmer.
1392 //Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen.
1393 Point
aPoint( rPt
);
1395 //Erst die vertikale Position einstellen
1396 if ( aCntFrm
.Top() > rPt
.Y() )
1397 aPoint
.Y() = aCntFrm
.Top();
1398 else if ( aCntFrm
.Bottom() < rPt
.Y() )
1399 aPoint
.Y() = aCntFrm
.Bottom();
1401 //Jetzt die horizontale Position
1402 if ( aCntFrm
.Left() > rPt
.X() )
1403 aPoint
.X() = aCntFrm
.Left();
1404 else if ( aCntFrm
.Right() < rPt
.X() )
1405 aPoint
.X() = aCntFrm
.Right();
1407 const ULONG nDiff
= ::CalcDiff( aPoint
, rPt
);
1408 if ( nDiff
< nDist
)
1414 else if ( aCntFrm
.Top() > Frm().Bottom() )
1415 //Dichter wirds im Sinne der Felder nicht mehr!
1418 pCntnt
= pCntnt
->GetNextCntntFrm();
1419 while ( pCntnt
&& !pCntnt
->IsInDocBody() )
1420 pCntnt
= pCntnt
->GetNextCntntFrm();
1423 //Und den Point in die PrtArea bringen
1424 const SwRect
aRect( pAct
->Frm().Pos() + pAct
->Prt().Pos(), pAct
->Prt().SSize() );
1425 if ( aAct
.Y() < aRect
.Top() )
1426 aAct
.Y() = aRect
.Top();
1427 else if ( aAct
.Y() > aRect
.Bottom() )
1428 aAct
.Y() = aRect
.Bottom();
1429 if ( aAct
.X() < aRect
.Left() )
1430 aAct
.X() = aRect
.Left();
1431 else if ( aAct
.X() > aRect
.Right() )
1432 aAct
.X() = aRect
.Right();
1434 if( !pAct
->IsValid() )
1436 // CntntFrm nicht formatiert -> immer auf Node-Anfang
1437 SwCntntNode
* pCNd
= (SwCntntNode
*)pAct
->GetNode();
1438 ASSERT( pCNd
, "Wo ist mein CntntNode?" );
1440 rPos
.nContent
.Assign( pCNd
, 0 );
1444 SwCrsrMoveState
aTmpState( MV_SETONLYTEXT
);
1445 pAct
->GetCrsrOfst( &rPos
, aAct
, &aTmpState
);
1449 /*************************************************************************
1451 |* SwRootFrm::GetNextPrevCntntPos()
1453 |* Beschreibung Es wird der naechstliegende Cntnt zum uebergebenen
1454 |* Point gesucht. Es wird nur im BodyText gesucht.
1455 |* Ersterstellung MA 15. Jul. 92
1456 |* Letzte Aenderung JP 11.10.2001
1458 |*************************************************************************/
1460 // --> OD 2005-05-25 #123110# - helper class to disable creation of an action
1461 // by a callback event - e.g., change event from a drawing object
1462 class DisableCallbackAction
1465 SwRootFrm
& mrRootFrm
;
1466 BOOL mbOldCallbackActionState
;
1469 DisableCallbackAction( const SwRootFrm
& _rRootFrm
) :
1470 mrRootFrm( const_cast<SwRootFrm
&>(_rRootFrm
) ),
1471 mbOldCallbackActionState( _rRootFrm
.IsCallbackActionEnabled() )
1473 mrRootFrm
.SetCallbackActionEnabled( FALSE
);
1476 ~DisableCallbackAction()
1478 mrRootFrm
.SetCallbackActionEnabled( mbOldCallbackActionState
);
1483 //!!!!! Es wird nur der vertikal naechstliegende gesucht.
1484 //JP 11.10.2001: only in tables we try to find the right column - Bug 72294
1485 Point
SwRootFrm::GetNextPrevCntntPos( const Point
& rPoint
, BOOL bNext
) const
1487 // --> OD 2005-05-25 #123110# - disable creation of an action by a callback
1488 // event during processing of this method. Needed because formatting is
1489 // triggered by this method.
1490 DisableCallbackAction
aDisableCallbackAction( *this );
1492 //Ersten CntntFrm und seinen Nachfolger im Body-Bereich suchen
1493 //Damit wir uns nicht tot suchen (und vor allem nicht zuviel formatieren)
1494 //gehen wir schon mal von der richtigen Seite aus.
1495 SwLayoutFrm
*pPage
= (SwLayoutFrm
*)Lower();
1497 while( pPage
->GetNext() && pPage
->Frm().Bottom() < rPoint
.Y() )
1498 pPage
= (SwLayoutFrm
*)pPage
->GetNext();
1500 const SwCntntFrm
*pCnt
= pPage
? pPage
->ContainsCntnt() : ContainsCntnt();
1501 while ( pCnt
&& !pCnt
->IsInDocBody() )
1502 pCnt
= pCnt
->GetNextCntntFrm();
1505 return Point( 0, 0 );
1510 // Solange der Point vor dem ersten CntntFrm liegt und es noch
1511 // vorhergehende Seiten gibt gehe ich jeweils eine Seite nach vorn.
1512 while ( rPoint
.Y() < pCnt
->Frm().Top() && pPage
->GetPrev() )
1514 pPage
= (SwLayoutFrm
*)pPage
->GetPrev();
1515 pCnt
= pPage
->ContainsCntnt();
1518 pPage
= (SwLayoutFrm
*)pPage
->GetPrev();
1520 pCnt
= pPage
->ContainsCntnt();
1522 return ContainsCntnt()->UnionFrm().Pos();
1528 //Liegt der Point ueber dem ersten CntntFrm?
1529 if ( rPoint
.Y() < pCnt
->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt
) )
1530 return pCnt
->UnionFrm().Pos();
1534 //Liegt der Point im aktuellen CntntFrm?
1535 SwRect
aCntFrm( pCnt
->UnionFrm() );
1536 if ( aCntFrm
.IsInside( rPoint
) && !lcl_IsInRepeatedHeadline( pCnt
))
1539 //Ist der aktuelle der letzte CntntFrm? ||
1540 //Wenn der naechste CntntFrm hinter dem Point liegt, ist der
1541 //aktuelle der gesuchte.
1542 const SwCntntFrm
*pNxt
= pCnt
->GetNextCntntFrm();
1543 while ( pNxt
&& !pNxt
->IsInDocBody() )
1544 pNxt
= pNxt
->GetNextCntntFrm();
1546 //Liegt der Point hinter dem letzten CntntFrm?
1548 return Point( aCntFrm
.Right(), aCntFrm
.Bottom() );
1550 //Wenn der naechste CntntFrm hinter dem Point liegt ist er der
1552 const SwTabFrm
* pTFrm
;
1554 if( pNxt
->Frm().Top() > rPoint
.Y() &&
1555 !lcl_IsInRepeatedHeadline( pCnt
, &pTFrm
) &&
1556 ( !pTFrm
|| pNxt
->Frm().Left() > rPoint
.X() ))
1559 return pNxt
->Frm().Pos();
1560 return Point( aCntFrm
.Right(), aCntFrm
.Bottom() );
1564 return Point( 0, 0 );
1567 /*************************************************************************
1569 |* SwRootFrm::GetPagePos()
1571 |* Beschreibung: Liefert die absolute Dokumentpositon der gewuenschten
1573 |* Formatiert wird nur soweit notwendig und nur dann wenn bFormat=TRUE
1574 |* Liefert Null, wenn die Operation nicht moeglich ist.
1575 |* Die Pos ist die der letzten Seite, wenn die Seitenzahl zu gross
1577 |* Ersterstellung MA 01. Jun. 92
1578 |* Letzte Aenderung MA 09. Oct. 97
1580 |*************************************************************************/
1581 Point
SwRootFrm::GetPagePos( USHORT nPageNum
) const
1583 ASSERT( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
1585 const SwPageFrm
*pPage
= (const SwPageFrm
*)Lower();
1588 if ( pPage
->GetPhyPageNum() >= nPageNum
|| !pPage
->GetNext() )
1590 pPage
= (const SwPageFrm
*)pPage
->GetNext();
1592 return pPage
->Frm().Pos();
1595 /** get page frame by phyiscal page number
1597 OD 14.01.2003 #103492#
1599 @return pointer to the page frame with the given physical page number
1601 SwPageFrm
* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum
) const
1603 const SwPageFrm
* pPageFrm
= static_cast<const SwPageFrm
*>( Lower() );
1604 while ( pPageFrm
&& pPageFrm
->GetPhyPageNum() < _nPageNum
)
1606 pPageFrm
= static_cast<const SwPageFrm
*>( pPageFrm
->GetNext() );
1609 if ( pPageFrm
&& pPageFrm
->GetPhyPageNum() == _nPageNum
)
1611 return const_cast<SwPageFrm
*>( pPageFrm
);
1619 /*************************************************************************
1621 |* SwRootFrm::IsDummyPage(USHORT)
1623 |* Description: Returns TRUE, when the given physical pagenumber does't exist
1624 |* or this page is an empty page.
1625 |*************************************************************************/
1626 BOOL
SwRootFrm::IsDummyPage( USHORT nPageNum
) const
1628 if( !Lower() || !nPageNum
|| nPageNum
> GetPageNum() )
1631 const SwPageFrm
*pPage
= (const SwPageFrm
*)Lower();
1632 while( pPage
&& nPageNum
< pPage
->GetPhyPageNum() )
1633 pPage
= (const SwPageFrm
*)pPage
->GetNext();
1634 return pPage
? pPage
->IsEmptyPage() : TRUE
;
1638 /*************************************************************************
1640 |* SwFrm::IsProtected()
1642 |* Beschreibung Ist der Frm bzw. die Section in der er steht
1644 |* Auch Fly in Fly in ... und Fussnoten
1646 |* Ersterstellung MA 28. Jul. 93
1647 |* Letzte Aenderung MA 06. Nov. 97
1649 |*************************************************************************/
1650 BOOL
SwFrm::IsProtected() const
1652 if (this->IsCntntFrm() && ((SwCntntFrm
*)this)->GetNode())
1654 const SwDoc
*pDoc
=((SwCntntFrm
*)this)->GetNode()->GetDoc();
1655 bool isFormProtected
=pDoc
->get(IDocumentSettingAccess::PROTECT_FORM
);
1656 if (isFormProtected
)
1658 return FALSE
; // TODO a hack for now, well deal with it laster, I we return true here we have a "double" locking
1661 //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein.
1662 //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker.
1663 const SwFrm
*pFrm
= this;
1666 if ( pFrm
->IsCntntFrm() )
1668 if ( ((SwCntntFrm
*)pFrm
)->GetNode() &&
1669 ((SwCntntFrm
*)pFrm
)->GetNode()->IsInProtectSect() )
1674 if ( ((SwLayoutFrm
*)pFrm
)->GetFmt() &&
1675 ((SwLayoutFrm
*)pFrm
)->GetFmt()->
1676 GetProtect().IsCntntProtected() )
1678 if ( pFrm
->IsCoveredCell() )
1681 if ( pFrm
->IsFlyFrm() )
1683 //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette
1684 //vorgegeben werden.
1685 if ( ((SwFlyFrm
*)pFrm
)->GetPrevLink() )
1687 SwFlyFrm
*pMaster
= (SwFlyFrm
*)pFrm
;
1689 { pMaster
= pMaster
->GetPrevLink();
1690 } while ( pMaster
->GetPrevLink() );
1691 if ( pMaster
->IsProtected() )
1694 pFrm
= ((SwFlyFrm
*)pFrm
)->GetAnchorFrm();
1696 else if ( pFrm
->IsFtnFrm() )
1697 pFrm
= ((SwFtnFrm
*)pFrm
)->GetRef();
1699 pFrm
= pFrm
->GetUpper();
1706 /*************************************************************************
1708 |* SwFrm::GetPhyPageNum()
1709 |* Beschreibung: Liefert die physikalische Seitennummer
1711 |* Ersterstellung OK 06.07.93 08:35
1712 |* Letzte Aenderung MA 30. Nov. 94
1714 |*************************************************************************/
1715 USHORT
SwFrm::GetPhyPageNum() const
1717 const SwPageFrm
*pPage
= FindPageFrm();
1718 return pPage
? pPage
->GetPhyPageNum() : 0;
1721 /*-----------------26.02.01 11:25-------------------
1722 * SwFrm::WannaRightPage()
1723 * decides if the page want to be a rightpage or not.
1724 * If the first content of the page has a page descriptor,
1725 * we take the follow of the page descriptor of the last not empty page.
1726 * If this descriptor allows only right(left) pages and the page
1727 * isn't an empty page then it wanna be such right(left) page.
1728 * If the descriptor allows right and left pages, we look for a number offset
1729 * in the first content. If there is one, odd number results right pages,
1730 * even number results left pages.
1731 * If there is no number offset, we take the physical page number instead,
1732 * but a previous empty page don't count.
1733 * --------------------------------------------------*/
1735 BOOL
SwFrm::WannaRightPage() const
1737 const SwPageFrm
*pPage
= FindPageFrm();
1738 if ( !pPage
|| !pPage
->GetUpper() )
1741 const SwFrm
*pFlow
= pPage
->FindFirstBodyCntnt();
1742 SwPageDesc
*pDesc
= 0;
1746 if ( pFlow
->IsInTab() )
1747 pFlow
= pFlow
->FindTabFrm();
1748 const SwFlowFrm
*pTmp
= SwFlowFrm::CastFlowFrm( pFlow
);
1749 if ( !pTmp
->IsFollow() )
1751 const SwFmtPageDesc
& rPgDesc
= pFlow
->GetAttrSet()->GetPageDesc();
1752 pDesc
= (SwPageDesc
*)rPgDesc
.GetPageDesc();
1753 nPgNum
= rPgDesc
.GetNumOffset();
1758 SwPageFrm
*pPrv
= (SwPageFrm
*)pPage
->GetPrev();
1759 if( pPrv
&& pPrv
->IsEmptyPage() )
1760 pPrv
= (SwPageFrm
*)pPrv
->GetPrev();
1762 pDesc
= pPrv
->GetPageDesc()->GetFollow();
1765 const SwDoc
* pDoc
= pPage
->GetFmt()->GetDoc();
1766 pDesc
= (SwPageDesc
*)&pDoc
->GetPageDesc( 0 );
1769 ASSERT( pDesc
, "No pagedescriptor" );
1772 bOdd
= nPgNum
% 2 ? TRUE
: FALSE
;
1775 bOdd
= pPage
->OnRightPage();
1776 if( pPage
->GetPrev() && ((SwPageFrm
*)pPage
->GetPrev())->IsEmptyPage() )
1779 if( !pPage
->IsEmptyPage() )
1781 if( !pDesc
->GetRightFmt() )
1783 else if( !pDesc
->GetLeftFmt() )
1789 /*************************************************************************
1791 |* SwFrm::GetVirtPageNum()
1792 |* Beschreibung: Liefert die virtuelle Seitennummer mit Offset
1794 |* Ersterstellung OK 06.07.93 08:35
1795 |* Letzte Aenderung MA 30. Nov. 94
1797 |*************************************************************************/
1798 USHORT
SwFrm::GetVirtPageNum() const
1800 const SwPageFrm
*pPage
= FindPageFrm();
1801 if ( !pPage
|| !pPage
->GetUpper() )
1804 USHORT nPhyPage
= pPage
->GetPhyPageNum();
1805 if ( !((SwRootFrm
*)pPage
->GetUpper())->IsVirtPageNum() )
1808 //Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen.
1809 //Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen
1810 //wir jetzt gezielt ueber die Abhaengigkeiten.
1811 //von den PageDescs bekommen wir die Attribute, von den Attributen
1812 //wiederum bekommen wir die Absaetze.
1813 const SwPageFrm
*pVirtPage
= 0;
1814 const SwFrm
*pFrm
= 0;
1815 const SfxItemPool
&rPool
= pPage
->GetFmt()->GetDoc()->GetAttrPool();
1816 const SfxPoolItem
* pItem
;
1817 USHORT nMaxItems
= rPool
.GetItemCount( RES_PAGEDESC
);
1818 for( USHORT n
= 0; n
< nMaxItems
; ++n
)
1820 if( 0 == (pItem
= rPool
.GetItem( RES_PAGEDESC
, n
) ))
1823 const SwFmtPageDesc
*pDesc
= (SwFmtPageDesc
*)pItem
;
1824 if ( pDesc
->GetNumOffset() && pDesc
->GetDefinedIn() )
1826 const SwModify
*pMod
= pDesc
->GetDefinedIn();
1827 SwVirtPageNumInfo
aInfo( pPage
);
1828 pMod
->GetInfo( aInfo
);
1829 if ( aInfo
.GetPage() )
1831 if( !pVirtPage
|| ( pVirtPage
&& aInfo
.GetPage()->
1832 GetPhyPageNum() > pVirtPage
->GetPhyPageNum() ) )
1834 pVirtPage
= aInfo
.GetPage();
1835 pFrm
= aInfo
.GetFrm();
1841 return nPhyPage
- pFrm
->GetPhyPageNum() +
1842 pFrm
->GetAttrSet()->GetPageDesc().GetNumOffset();
1846 /*************************************************************************
1848 |* SwRootFrm::MakeTblCrsrs()
1850 |* Ersterstellung MA 14. May. 93
1851 |* Letzte Aenderung MA 02. Feb. 94
1853 |*************************************************************************/
1854 //Ermitteln und einstellen derjenigen Zellen die von der Selektion
1855 //eingeschlossen sind.
1857 bool SwRootFrm::MakeTblCrsrs( SwTableCursor
& rTblCrsr
)
1859 //Union-Rects und Tabellen (Follows) der Selektion besorgen.
1860 ASSERT( rTblCrsr
.GetCntntNode() && rTblCrsr
.GetCntntNode( FALSE
),
1861 "Tabselection nicht auf Cnt." );
1865 // For new table models there's no need to ask the layout..
1866 if( rTblCrsr
.NewTableSelection() )
1871 SwShellCrsr
* pShCrsr
= dynamic_cast<SwShellCrsr
*>(&rTblCrsr
);
1875 aPtPt
= pShCrsr
->GetPtPos();
1876 aMkPt
= pShCrsr
->GetMkPos();
1880 // --> FME 2008-01-14 #151012# Made code robust here:
1881 const SwCntntNode
* pTmpStartNode
= rTblCrsr
.GetCntntNode();
1882 const SwCntntNode
* pTmpEndNode
= rTblCrsr
.GetCntntNode(FALSE
);
1884 const SwFrm
* pTmpStartFrm
= pTmpStartNode
? pTmpStartNode
->GetFrm( &aPtPt
, 0, FALSE
) : 0;
1885 const SwFrm
* pTmpEndFrm
= pTmpEndNode
? pTmpEndNode
->GetFrm( &aMkPt
, 0, FALSE
) : 0;
1887 const SwLayoutFrm
* pStart
= pTmpStartFrm
? pTmpStartFrm
->GetUpper() : 0;
1888 const SwLayoutFrm
* pEnd
= pTmpEndFrm
? pTmpEndFrm
->GetUpper() : 0;
1890 ASSERT( pStart
&& pEnd
, "MakeTblCrsrs: Good to have the code robust here!" )
1893 /* #109590# Only change table boxes if the frames are
1894 valid. Needed because otherwise the table cursor after moving
1895 table cells by dnd resulted in an empty tables cursor. */
1896 if ( pStart
&& pEnd
&& pStart
->IsValid() && pEnd
->IsValid())
1898 SwSelUnions aUnions
;
1899 ::MakeSelUnions( aUnions
, pStart
, pEnd
);
1903 const BOOL bReadOnlyAvailable
= rTblCrsr
.IsReadOnlyAvailable();
1905 for ( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
1907 SwSelUnion
*pUnion
= aUnions
[i
];
1908 const SwTabFrm
*pTable
= pUnion
->GetTable();
1910 // Skip any repeated headlines in the follow:
1911 SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
1912 pTable
->GetFirstNonHeadlineRow() :
1913 (SwLayoutFrm
*)pTable
->Lower();
1917 if ( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
1919 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
1921 while ( pCell
&& pRow
->IsAnLower( pCell
) )
1923 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
1924 if( IsFrmInTblSel( pUnion
->GetUnion(), pCell
) &&
1925 (bReadOnlyAvailable
||
1926 !pCell
->GetFmt()->GetProtect().IsCntntProtected()))
1928 SwTableBox
* pInsBox
= (SwTableBox
*)
1929 ((SwCellFrm
*)pCell
)->GetTabBox();
1930 aNew
.Insert( pInsBox
);
1932 if ( pCell
->GetNext() )
1934 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
1935 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
1936 pCell
= pCell
->FirstCell();
1940 const SwLayoutFrm
* pLastCell
= pCell
;
1943 pCell
= pCell
->GetNextLayoutLeaf();
1944 } while ( pCell
&& pLastCell
->IsAnLower( pCell
) );
1945 // Fuer (spaltige) Bereiche...
1946 if( pCell
&& pCell
->IsInTab() )
1948 while( !pCell
->IsCellFrm() )
1950 pCell
= pCell
->GetUpper();
1951 ASSERT( pCell
, "Where's my cell?" );
1957 pRow
= (SwLayoutFrm
*)pRow
->GetNext();
1961 rTblCrsr
.ActualizeSelection( aNew
);
1969 /*************************************************************************
1971 |* SwRootFrm::CalcFrmRects
1973 |* Ersterstellung MA 24. Aug. 92
1974 |* Letzte Aenderung MA 24. Aug. 93
1976 |*************************************************************************/
1979 * nun koennen folgende Situationen auftreten:
1980 * 1. Start und Ende liegen in einer Bildschirm - Zeile und im
1982 * -> aus Start und End ein Rectangle, dann Ok
1983 * 2. Start und Ende liegen in einem Frame (dadurch im gleichen Node!)
1984 * -> Start nach rechts, End nach links erweitern,
1985 * und bei mehr als 2 Bildschirm - Zeilen, das dazwischen
1986 * liegende berechnen
1987 * 3. Start und Ende liegen in verschiedenen Frames
1988 * -> Start nach rechts erweitern, bis Frame-Ende Rect berechnen
1989 * Ende nach links erweitern, bis Frame-Start Rect berechnen
1990 * und bei mehr als 2 Frames von allen dazwischen liegenden
1991 * Frames die PrtArea dazu.
1992 * 4. Wenn es sich um eine Tabellenselektion handelt wird fuer jeden
1993 * PaM im Ring der CellFrm besorgt, dessen PrtArea wird zu den
1994 * Rechtecken addiert.
1996 * Grosser Umbau wg. der FlyFrm; denn diese muessen ausgespart werden.
1997 * Ausnahmen: - Der Fly in dem die Selektion stattfindet (wenn sie in einem Fly
1999 * - Die Flys, die vom Text unterlaufen werden.
2000 * Arbeitsweise: Zuerst wird eine SwRegion mit der Root initialisiert.
2001 * Aus der Region werden die zu invertierenden Bereiche
2002 * ausgestantzt. Die Region wird Komprimiert und letztlich
2003 * invertiert. Damit liegen dann die zu invertierenden
2005 * Am Ende werden die Flys aus der Region ausgestanzt.
2008 inline void Sub( SwRegionRects
& rRegion
, const SwRect
& rRect
)
2010 if( rRect
.Width() > 1 && rRect
.Height() > 1 &&
2011 rRect
.IsOver( rRegion
.GetOrigin() ))
2015 void SwRootFrm::CalcFrmRects( SwShellCrsr
&rCrsr
, BOOL bIsTblMode
)
2017 const SwNodes
&rNds
= GetFmt()->GetDoc()->GetNodes();
2018 SwPosition
*pStartPos
= rCrsr
.Start(),
2019 *pEndPos
= rCrsr
.GetPoint() == pStartPos
?
2020 rCrsr
.GetMark() : rCrsr
.GetPoint();
2022 ViewShell
*pSh
= GetShell();
2024 // --> FME 2004-06-08 #i12836# enhanced pdf
2025 SwRegionRects
aRegion( pSh
&& !pSh
->GetViewOptions()->IsPDFExport() ?
2029 if( !pStartPos
->nNode
.GetNode().IsCntntNode() ||
2030 !pStartPos
->nNode
.GetNode().GetCntntNode()->GetFrm() ||
2031 ( pStartPos
->nNode
!= pEndPos
->nNode
&&
2032 ( !pEndPos
->nNode
.GetNode().IsCntntNode() ||
2033 !pEndPos
->nNode
.GetNode().GetCntntNode()->GetFrm() ) ) )
2035 /* For SelectAll we will need something like this later on...
2036 const SwFrm* pPageFrm = GetLower();
2039 SwRect aTmp( pPageFrm->Prt() );
2040 aTmp.Pos() += pPageFrm->Frm().Pos();
2041 Sub( aRegion, aTmp );
2042 pPageFrm = pPageFrm->GetNext();
2045 rCrsr.Remove( 0, rCrsr.Count() );
2046 rCrsr.Insert( &aRegion, 0 );
2051 //Erstmal die CntntFrms zum Start und End besorgen, die brauch ich auf
2053 const SwCntntFrm
*pStartFrm
= rNds
[ pStartPos
->nNode
]->
2054 GetCntntNode()->GetFrm( &rCrsr
.GetSttPos(), pStartPos
);
2056 const SwCntntFrm
*pEndFrm
= rNds
[ pEndPos
->nNode
]->
2057 GetCntntNode()->GetFrm( &rCrsr
.GetEndPos(), pEndPos
);
2059 ASSERT( (pStartFrm
&& pEndFrm
), "Keine CntntFrms gefunden." );
2061 //Damit die FlyFrms, in denen selektierte Frames stecken, nicht
2063 SwSortedObjs aSortObjs
;
2064 if ( pStartFrm
->IsInFly() )
2066 const SwAnchoredObject
* pObj
= pStartFrm
->FindFlyFrm();
2067 aSortObjs
.Insert( *(const_cast<SwAnchoredObject
*>(pObj
)) );
2068 const SwAnchoredObject
* pObj2
= pEndFrm
->FindFlyFrm();
2069 aSortObjs
.Insert( *(const_cast<SwAnchoredObject
*>(pObj2
)) );
2072 //Fall 4: Tabellenselection
2075 const SwFrm
*pCell
= pStartFrm
->GetUpper();
2076 while ( !pCell
->IsCellFrm() )
2077 pCell
= pCell
->GetUpper();
2078 SwRect
aTmp( pCell
->Prt() );
2079 aTmp
.Pos() += pCell
->Frm().Pos();
2080 aRegion
.ChangeOrigin( aTmp
);
2081 aRegion
.Remove( 0, aRegion
.Count() );
2082 aRegion
.Insert( aTmp
, 0 );
2086 // falls eine nicht erlaubte Selection besteht, dann korrigiere das
2087 // nicht erlaubt ist Header/Footer/TableHeadline ueber 2 Seiten
2088 do { // middle check loop
2089 const SwLayoutFrm
* pSttLFrm
= pStartFrm
->GetUpper();
2090 const USHORT cHdFtTblHd
= FRM_HEADER
| FRM_FOOTER
| FRM_TAB
;
2092 ! (cHdFtTblHd
& pSttLFrm
->GetType() ))
2093 pSttLFrm
= pSttLFrm
->GetUpper();
2096 const SwLayoutFrm
* pEndLFrm
= pEndFrm
->GetUpper();
2098 ! (cHdFtTblHd
& pEndLFrm
->GetType() ))
2099 pEndLFrm
= pEndLFrm
->GetUpper();
2103 ASSERT( pEndLFrm
->GetType() == pSttLFrm
->GetType(),
2104 "Selection ueber unterschiedliche Inhalte" );
2105 switch( pSttLFrm
->GetType() )
2109 // auf unterschiedlichen Seiten ??
2110 // dann immer auf die Start-Seite
2111 if( pEndLFrm
->FindPageFrm() != pSttLFrm
->FindPageFrm() )
2113 // End- auf den Start-CntntFrame setzen
2114 if( pStartPos
== rCrsr
.GetPoint() )
2115 pEndFrm
= pStartFrm
;
2117 pStartFrm
= pEndFrm
;
2121 // auf unterschiedlichen Seiten ??
2123 // dann teste auf Tabelle-Headline
2125 const SwTabFrm
* pTabFrm
= (SwTabFrm
*)pSttLFrm
;
2126 if( ( pTabFrm
->GetFollow() ||
2127 ((SwTabFrm
*)pEndLFrm
)->GetFollow() ) &&
2128 pTabFrm
->GetTable()->GetRowsToRepeat() > 0 &&
2129 pTabFrm
->GetLower() != ((SwTabFrm
*)pEndLFrm
)->GetLower() &&
2130 ( lcl_IsInRepeatedHeadline( pStartFrm
) ||
2131 lcl_IsInRepeatedHeadline( pEndFrm
) ) )
2133 // End- auf den Start-CntntFrame setzen
2134 if( pStartPos
== rCrsr
.GetPoint() )
2135 pEndFrm
= pStartFrm
;
2137 pStartFrm
= pEndFrm
;
2144 SwCrsrMoveState
aTmpState( MV_NONE
);
2145 aTmpState
.b2Lines
= sal_True
;
2146 aTmpState
.bNoScroll
= sal_True
;
2147 aTmpState
.nCursorBidiLevel
= pStartFrm
->IsRightToLeft() ? 1 : 0;
2149 //CntntRects zu Start- und EndFrms.
2150 SwRect aStRect
, aEndRect
;
2151 pStartFrm
->GetCharRect( aStRect
, *pStartPos
, &aTmpState
);
2152 Sw2LinesPos
*pSt2Pos
= aTmpState
.p2Lines
;
2153 aTmpState
.p2Lines
= NULL
;
2154 aTmpState
.nCursorBidiLevel
= pEndFrm
->IsRightToLeft() ? 1 : 0;
2156 pEndFrm
->GetCharRect ( aEndRect
, *pEndPos
, &aTmpState
);
2157 Sw2LinesPos
*pEnd2Pos
= aTmpState
.p2Lines
;
2159 SwRect
aStFrm ( pStartFrm
->UnionFrm( sal_True
) );
2160 aStFrm
.Intersection( pStartFrm
->PaintArea() );
2161 SwRect
aEndFrm( pStartFrm
== pEndFrm
? aStFrm
:
2162 pEndFrm
->UnionFrm( sal_True
) );
2163 if( pStartFrm
!= pEndFrm
)
2164 aEndFrm
.Intersection( pEndFrm
->PaintArea() );
2165 SWRECTFN( pStartFrm
)
2166 const BOOL bR2L
= pStartFrm
->IsRightToLeft();
2167 const BOOL bEndR2L
= pEndFrm
->IsRightToLeft();
2169 // If there's no doubleline portion involved or start and end are both
2170 // in the same doubleline portion, all works fine, but otherwise
2171 // we need the following...
2172 if( pSt2Pos
!= pEnd2Pos
&& ( !pSt2Pos
|| !pEnd2Pos
||
2173 pSt2Pos
->aPortion
!= pEnd2Pos
->aPortion
) )
2175 // If we have a start(end) position inside a doubleline portion
2176 // the surrounded part of the doubleline portion is subtracted
2177 // from the region and the aStRect(aEndRect) is set to the
2178 // end(start) of the doubleline portion.
2181 SwRect
aTmp( aStRect
);
2183 // BiDi-Portions are swimming against the current.
2184 const sal_Bool bPorR2L
= ( MT_BIDI
== pSt2Pos
->nMultiType
) ?
2188 if( MT_BIDI
== pSt2Pos
->nMultiType
&&
2189 (pSt2Pos
->aPortion2
.*fnRect
->fnGetWidth
)() )
2191 // nested bidi portion
2192 long nRightAbs
= (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)();
2193 nRightAbs
-= (pSt2Pos
->aPortion2
.*fnRect
->fnGetLeft
)();
2194 long nLeftAbs
= nRightAbs
- (pSt2Pos
->aPortion2
.*fnRect
->fnGetWidth
)();
2196 (aTmp
.*fnRect
->fnSetRight
)( nRightAbs
);
2198 if ( ! pEnd2Pos
|| pEnd2Pos
->aPortion
!= pSt2Pos
->aPortion
)
2200 SwRect
aTmp2( pSt2Pos
->aPortion
);
2201 (aTmp2
.*fnRect
->fnSetRight
)( nLeftAbs
);
2202 aTmp2
.Intersection( aEndFrm
);
2203 Sub( aRegion
, aTmp2
);
2209 (aTmp
.*fnRect
->fnSetLeft
)(
2210 (pSt2Pos
->aPortion
.*fnRect
->fnGetLeft
)() );
2212 (aTmp
.*fnRect
->fnSetRight
)(
2213 (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)() );
2216 if( MT_ROT_90
== pSt2Pos
->nMultiType
||
2217 (pSt2Pos
->aPortion
.*fnRect
->fnGetTop
)() ==
2218 (aTmp
.*fnRect
->fnGetTop
)() )
2220 (aTmp
.*fnRect
->fnSetTop
)(
2221 (pSt2Pos
->aLine
.*fnRect
->fnGetTop
)() );
2224 aTmp
.Intersection( aStFrm
);
2225 Sub( aRegion
, aTmp
);
2227 SwTwips nTmp
= (pSt2Pos
->aLine
.*fnRect
->fnGetBottom
)();
2228 if( MT_ROT_90
!= pSt2Pos
->nMultiType
&&
2229 (aStRect
.*fnRect
->fnBottomDist
)( nTmp
) > 0 )
2231 (aTmp
.*fnRect
->fnSetTop
)( (aTmp
.*fnRect
->fnGetBottom
)() );
2232 (aTmp
.*fnRect
->fnSetBottom
)( nTmp
);
2233 if( (aStRect
.*fnRect
->fnBottomDist
)(
2234 (pSt2Pos
->aPortion
.*fnRect
->fnGetBottom
)() ) > 0 )
2237 (aTmp
.*fnRect
->fnSetRight
)(
2238 (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)() );
2240 (aTmp
.*fnRect
->fnSetLeft
)(
2241 (pSt2Pos
->aPortion
.*fnRect
->fnGetLeft
)() );
2243 aTmp
.Intersection( aStFrm
);
2244 Sub( aRegion
, aTmp
);
2247 aStRect
= pSt2Pos
->aLine
;
2248 (aStRect
.*fnRect
->fnSetLeft
)( bR2L
?
2249 (pSt2Pos
->aPortion
.*fnRect
->fnGetLeft
)() :
2250 (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)() );
2251 (aStRect
.*fnRect
->fnSetWidth
)( 1 );
2256 SWRECTFNX( pEndFrm
)
2257 SwRect
aTmp( aEndRect
);
2259 // BiDi-Portions are swimming against the current.
2260 const sal_Bool bPorR2L
= ( MT_BIDI
== pEnd2Pos
->nMultiType
) ?
2264 if( MT_BIDI
== pEnd2Pos
->nMultiType
&&
2265 (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetWidth
)() )
2267 // nested bidi portion
2268 long nRightAbs
= (pEnd2Pos
->aPortion
.*fnRectX
->fnGetRight
)();
2269 nRightAbs
= nRightAbs
- (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetLeft
)();
2270 long nLeftAbs
= nRightAbs
- (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetWidth
)();
2272 (aTmp
.*fnRectX
->fnSetLeft
)( nLeftAbs
);
2274 if ( ! pSt2Pos
|| pSt2Pos
->aPortion
!= pEnd2Pos
->aPortion
)
2276 SwRect
aTmp2( pEnd2Pos
->aPortion
);
2277 (aTmp2
.*fnRectX
->fnSetLeft
)( nRightAbs
);
2278 aTmp2
.Intersection( aEndFrm
);
2279 Sub( aRegion
, aTmp2
);
2285 (aTmp
.*fnRectX
->fnSetRight
)(
2286 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetRight
)() );
2288 (aTmp
.*fnRectX
->fnSetLeft
)(
2289 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetLeft
)() );
2292 if( MT_ROT_90
== pEnd2Pos
->nMultiType
||
2293 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetBottom
)() ==
2294 (aEndRect
.*fnRectX
->fnGetBottom
)() )
2296 (aTmp
.*fnRectX
->fnSetBottom
)(
2297 (pEnd2Pos
->aLine
.*fnRectX
->fnGetBottom
)() );
2300 aTmp
.Intersection( aEndFrm
);
2301 Sub( aRegion
, aTmp
);
2303 // The next statement means neither ruby nor rotate(90):
2304 if( !( MT_RUBY
& pEnd2Pos
->nMultiType
) )
2306 SwTwips nTmp
= (pEnd2Pos
->aLine
.*fnRectX
->fnGetTop
)();
2307 if( (aEndRect
.*fnRectX
->fnGetTop
)() != nTmp
)
2309 (aTmp
.*fnRectX
->fnSetBottom
)(
2310 (aTmp
.*fnRectX
->fnGetTop
)() );
2311 (aTmp
.*fnRectX
->fnSetTop
)( nTmp
);
2312 if( (aEndRect
.*fnRectX
->fnGetTop
)() !=
2313 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetTop
)() )
2315 (aTmp
.*fnRectX
->fnSetLeft
)(
2316 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetLeft
)() );
2318 (aTmp
.*fnRectX
->fnSetRight
)(
2319 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetRight
)() );
2320 aTmp
.Intersection( aEndFrm
);
2321 Sub( aRegion
, aTmp
);
2325 aEndRect
= pEnd2Pos
->aLine
;
2326 (aEndRect
.*fnRectX
->fnSetLeft
)( bEndR2L
?
2327 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetRight
)() :
2328 (pEnd2Pos
->aPortion
.*fnRectX
->fnGetLeft
)() );
2329 (aEndRect
.*fnRectX
->fnSetWidth
)( 1 );
2332 else if( pSt2Pos
&& pEnd2Pos
&&
2333 MT_BIDI
== pSt2Pos
->nMultiType
&&
2334 MT_BIDI
== pEnd2Pos
->nMultiType
&&
2335 pSt2Pos
->aPortion
== pEnd2Pos
->aPortion
&&
2336 pSt2Pos
->aPortion2
!= pEnd2Pos
->aPortion2
)
2338 // This is the ugly special case, where the selection starts and
2339 // ends in the same bidi portion but one start or end is inside a
2340 // nested bidi portion.
2342 if ( (pSt2Pos
->aPortion2
.*fnRect
->fnGetWidth
)() )
2344 SwRect
aTmp( aStRect
);
2345 long nRightAbs
= (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)();
2346 nRightAbs
-= (pSt2Pos
->aPortion2
.*fnRect
->fnGetLeft
)();
2347 long nLeftAbs
= nRightAbs
- (pSt2Pos
->aPortion2
.*fnRect
->fnGetWidth
)();
2349 (aTmp
.*fnRect
->fnSetRight
)( nRightAbs
);
2350 aTmp
.Intersection( aStFrm
);
2351 Sub( aRegion
, aTmp
);
2353 aStRect
= pSt2Pos
->aLine
;
2354 (aStRect
.*fnRect
->fnSetLeft
)( bR2L
? nRightAbs
: nLeftAbs
);
2355 (aStRect
.*fnRect
->fnSetWidth
)( 1 );
2358 SWRECTFNX( pEndFrm
)
2359 if ( (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetWidth
)() )
2361 SwRect
aTmp( aEndRect
);
2362 long nRightAbs
= (pEnd2Pos
->aPortion
.*fnRectX
->fnGetRight
)();
2363 nRightAbs
-= (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetLeft
)();
2364 long nLeftAbs
= nRightAbs
- (pEnd2Pos
->aPortion2
.*fnRectX
->fnGetWidth
)();
2366 (aTmp
.*fnRectX
->fnSetLeft
)( nLeftAbs
);
2367 aTmp
.Intersection( aEndFrm
);
2368 Sub( aRegion
, aTmp
);
2370 aEndRect
= pEnd2Pos
->aLine
;
2371 (aEndRect
.*fnRectX
->fnSetLeft
)( bEndR2L
? nLeftAbs
: nRightAbs
);
2372 (aEndRect
.*fnRectX
->fnSetWidth
)( 1 );
2376 // The charrect may be outside the paintarea (for cursortravelling)
2377 // but the selection has to be restricted to the paintarea
2378 if( aStRect
.Left() < aStFrm
.Left() )
2379 aStRect
.Left( aStFrm
.Left() );
2380 else if( aStRect
.Left() > aStFrm
.Right() )
2381 aStRect
.Left( aStFrm
.Right() );
2382 SwTwips nTmp
= aStRect
.Right();
2383 if( nTmp
< aStFrm
.Left() )
2384 aStRect
.Right( aStFrm
.Left() );
2385 else if( nTmp
> aStFrm
.Right() )
2386 aStRect
.Right( aStFrm
.Right() );
2387 if( aEndRect
.Left() < aEndFrm
.Left() )
2388 aEndRect
.Left( aEndFrm
.Left() );
2389 else if( aEndRect
.Left() > aEndFrm
.Right() )
2390 aEndRect
.Left( aEndFrm
.Right() );
2391 nTmp
= aEndRect
.Right();
2392 if( nTmp
< aEndFrm
.Left() )
2393 aEndRect
.Right( aEndFrm
.Left() );
2394 else if( nTmp
> aEndFrm
.Right() )
2395 aEndRect
.Right( aEndFrm
.Right() );
2397 if( pStartFrm
== pEndFrm
)
2399 sal_Bool bSameRotatedOrBidi
= pSt2Pos
&& pEnd2Pos
&&
2400 ( MT_BIDI
& pSt2Pos
->nMultiType
) &&
2401 pSt2Pos
->aPortion
== pEnd2Pos
->aPortion
;
2402 //case 1: (Same frame and same row)
2403 if( bSameRotatedOrBidi
||
2404 (aStRect
.*fnRect
->fnGetTop
)() == (aEndRect
.*fnRect
->fnGetTop
)() )
2406 Point
aTmpSt( aStRect
.Pos() );
2407 Point
aTmpEnd( aEndRect
.Right(), aEndRect
.Bottom() );
2408 if( bSameRotatedOrBidi
|| bR2L
)
2410 if( aTmpSt
.Y() > aTmpEnd
.Y() )
2412 long nTmpY
= aTmpEnd
.Y();
2413 aTmpEnd
.Y() = aTmpSt
.Y();
2416 if( aTmpSt
.X() > aTmpEnd
.X() )
2418 long nTmpX
= aTmpEnd
.X();
2419 aTmpEnd
.X() = aTmpSt
.X();
2424 SwRect aTmp
= SwRect( aTmpSt
, aTmpEnd
);
2425 // Bug 34888: falls Inhalt selektiert ist, der keinen Platz
2426 // einnimmt (z.B. PostIts,RefMarks, TOXMarks),
2427 // dann mindestens die Breite des Crsr setzen.
2428 if( 1 == (aTmp
.*fnRect
->fnGetWidth
)() &&
2429 pStartPos
->nContent
.GetIndex() !=
2430 pEndPos
->nContent
.GetIndex() )
2432 OutputDevice
* pOut
= pSh
->GetOut();
2433 long nCrsrWidth
= pOut
->GetSettings().GetStyleSettings().
2435 (aTmp
.*fnRect
->fnSetWidth
)( pOut
->PixelToLogic(
2436 Size( nCrsrWidth
, 0 ) ).Width() );
2438 aTmp
.Intersection( aStFrm
);
2439 Sub( aRegion
, aTmp
);
2441 //case 2: (Same frame, but not the same line)
2444 SwTwips lLeft
, lRight
;
2445 if( pSt2Pos
&& pEnd2Pos
&& pSt2Pos
->aPortion
== pEnd2Pos
->aPortion
)
2447 lLeft
= (pSt2Pos
->aPortion
.*fnRect
->fnGetLeft
)();
2448 lRight
= (pSt2Pos
->aPortion
.*fnRect
->fnGetRight
)();
2452 lLeft
= (pStartFrm
->Frm().*fnRect
->fnGetLeft
)() +
2453 (pStartFrm
->Prt().*fnRect
->fnGetLeft
)();
2454 lRight
= (pStartFrm
->Frm().*fnRect
->fnGetLeft
)() +
2455 (pStartFrm
->Prt().*fnRect
->fnGetRight
)();
2457 if( lLeft
< (aStFrm
.*fnRect
->fnGetLeft
)() )
2458 lLeft
= (aStFrm
.*fnRect
->fnGetLeft
)();
2459 if( lRight
> (aStFrm
.*fnRect
->fnGetRight
)() )
2460 lRight
= (aStFrm
.*fnRect
->fnGetRight
)();
2461 SwRect
aSubRect( aStRect
);
2464 (aSubRect
.*fnRect
->fnSetLeft
)( lLeft
);
2466 (aSubRect
.*fnRect
->fnSetRight
)( lRight
);
2467 Sub( aRegion
, aSubRect
);
2469 //If there's at least a twips between start- and endline,
2470 //so the whole area between will be added.
2471 SwTwips aTmpBottom
= (aStRect
.*fnRect
->fnGetBottom
)();
2472 SwTwips aTmpTop
= (aEndRect
.*fnRect
->fnGetTop
)();
2473 if( aTmpBottom
!= aTmpTop
)
2475 (aSubRect
.*fnRect
->fnSetLeft
)( lLeft
);
2476 (aSubRect
.*fnRect
->fnSetRight
)( lRight
);
2477 (aSubRect
.*fnRect
->fnSetTop
)( aTmpBottom
);
2478 (aSubRect
.*fnRect
->fnSetBottom
)( aTmpTop
);
2479 Sub( aRegion
, aSubRect
);
2482 aSubRect
= aEndRect
;
2484 (aSubRect
.*fnRect
->fnSetRight
)( lRight
);
2486 (aSubRect
.*fnRect
->fnSetLeft
)( lLeft
);
2487 Sub( aRegion
, aSubRect
);
2490 //case 3: (Different frames, maybe with ohther frames between
2493 //The startframe first...
2494 SwRect
aSubRect( aStRect
);
2496 (aSubRect
.*fnRect
->fnSetLeft
)( (aStFrm
.*fnRect
->fnGetLeft
)());
2498 (aSubRect
.*fnRect
->fnSetRight
)( (aStFrm
.*fnRect
->fnGetRight
)());
2499 Sub( aRegion
, aSubRect
);
2500 SwTwips nTmpTwips
= (aStRect
.*fnRect
->fnGetBottom
)();
2501 if( (aStFrm
.*fnRect
->fnGetBottom
)() != nTmpTwips
)
2504 (aSubRect
.*fnRect
->fnSetTop
)( nTmpTwips
);
2505 Sub( aRegion
, aSubRect
);
2508 //Now the frames between, if there are any
2509 BOOL bBody
= pStartFrm
->IsInDocBody();
2510 const SwTableBox
* pCellBox
= pStartFrm
->GetUpper()->IsCellFrm() ?
2511 ((SwCellFrm
*)pStartFrm
->GetUpper())->GetTabBox() : 0;
2512 const SwCntntFrm
*pCntnt
= pStartFrm
->GetNextCntntFrm();
2515 // --> OD 2006-01-24 #123908# - introduce robust code:
2516 // The stacktrace issue reveals that <pCntnt> could be NULL.
2517 // One root cause found by AMA - see #130650#
2519 "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2520 while ( pCntnt
&& pCntnt
!= pEndFrm
)
2523 if ( pCntnt
->IsInFly() )
2525 const SwAnchoredObject
* pObj
= pCntnt
->FindFlyFrm();
2526 aSortObjs
.Insert( *(const_cast<SwAnchoredObject
*>(pObj
)) );
2529 // Consider only frames which have the same IsInDocBody value like pStartFrm
2530 // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
2531 // same cell frame (or its follow cell)
2532 const SwTableBox
* pTmpCellBox
= pCntnt
->GetUpper()->IsCellFrm() ?
2533 ((SwCellFrm
*)pCntnt
->GetUpper())->GetTabBox() : 0;
2534 if ( bBody
== pCntnt
->IsInDocBody() &&
2535 ( !pCellBox
|| pCellBox
== pTmpCellBox
) )
2537 SwRect
aCRect( pCntnt
->UnionFrm( sal_True
) );
2538 aCRect
.Intersection( pCntnt
->PaintArea() );
2539 if( aCRect
.IsOver( aRegion
.GetOrigin() ))
2541 SwRect
aTmp( aPrvRect
);
2542 aTmp
.Union( aCRect
);
2543 if ( (aPrvRect
.Height() * aPrvRect
.Width() +
2544 aCRect
.Height() * aCRect
.Width()) ==
2545 (aTmp
.Height() * aTmp
.Width()) )
2547 aPrvRect
.Union( aCRect
);
2551 if ( aPrvRect
.HasArea() )
2552 Sub( aRegion
, aPrvRect
);
2557 pCntnt
= pCntnt
->GetNextCntntFrm();
2558 // --> OD 2006-01-24 #123908#
2560 "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2563 if ( aPrvRect
.HasArea() )
2564 Sub( aRegion
, aPrvRect
);
2566 //At least the endframe...
2567 bVert
= pEndFrm
->IsVertical();
2568 bRev
= pEndFrm
->IsReverse();
2569 fnRect
= bVert
? ( bRev
? fnRectVL2R
: fnRectVert
) :
2570 ( bRev
? fnRectB2T
: fnRectHori
);
2571 nTmpTwips
= (aEndRect
.*fnRect
->fnGetTop
)();
2572 if( (aEndFrm
.*fnRect
->fnGetTop
)() != nTmpTwips
)
2575 (aSubRect
.*fnRect
->fnSetBottom
)( nTmpTwips
);
2576 Sub( aRegion
, aSubRect
);
2578 aSubRect
= aEndRect
;
2580 (aSubRect
.*fnRect
->fnSetRight
)((aEndFrm
.*fnRect
->fnGetRight
)());
2582 (aSubRect
.*fnRect
->fnSetLeft
)( (aEndFrm
.*fnRect
->fnGetLeft
)() );
2583 Sub( aRegion
, aSubRect
);
2586 // aRegion.Compress( FALSE );
2592 //Flys mit Durchlauf ausstanzen. Nicht ausgestanzt werden Flys:
2593 //- die Lower des StartFrm/EndFrm sind (FlyInCnt und alle Flys die wiederum
2595 //- in der Z-Order ueber denjenigen Flys stehen in denen sich der StartFrm
2597 const SwPageFrm
*pPage
= pStartFrm
->FindPageFrm();
2598 const SwPageFrm
*pEndPage
= pEndFrm
->FindPageFrm();
2602 if ( pPage
->GetSortedObjs() )
2604 const SwSortedObjs
&rObjs
= *pPage
->GetSortedObjs();
2605 for ( USHORT i
= 0; i
< rObjs
.Count(); ++i
)
2607 SwAnchoredObject
* pAnchoredObj
= rObjs
[i
];
2608 if ( !pAnchoredObj
->ISA(SwFlyFrm
) )
2610 const SwFlyFrm
* pFly
= static_cast<const SwFlyFrm
*>(pAnchoredObj
);
2611 const SwVirtFlyDrawObj
* pObj
= pFly
->GetVirtDrawObj();
2612 const SwFmtSurround
&rSur
= pFly
->GetFmt()->GetSurround();
2613 if ( !pFly
->IsAnLower( pStartFrm
) &&
2614 (rSur
.GetSurround() != SURROUND_THROUGHT
&&
2615 !rSur
.IsContour()) )
2617 if ( aSortObjs
.Contains( *pAnchoredObj
) )
2621 const UINT32 nPos
= pObj
->GetOrdNum();
2622 for ( USHORT k
= 0; bSub
&& k
< aSortObjs
.Count(); ++k
)
2624 ASSERT( aSortObjs
[k
]->ISA(SwFlyFrm
),
2625 "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
2626 const SwFlyFrm
* pTmp
= static_cast<SwFlyFrm
*>(aSortObjs
[k
]);
2628 { if ( nPos
< pTmp
->GetVirtDrawObj()->GetOrdNumDirect() )
2631 pTmp
= pTmp
->GetAnchorFrm()->FindFlyFrm();
2632 } while ( bSub
&& pTmp
);
2635 Sub( aRegion
, pFly
->Frm() );
2639 if ( pPage
== pEndPage
)
2642 pPage
= (SwPageFrm
*)pPage
->GetNext();
2645 //Weil's besser aussieht noch die DropCaps ausschliessen.
2647 if ( pStartFrm
->IsTxtFrm() )
2649 if ( ((SwTxtFrm
*)pStartFrm
)->GetDropRect( aDropRect
) )
2650 Sub( aRegion
, aDropRect
);
2652 if ( pEndFrm
!= pStartFrm
&& pEndFrm
->IsTxtFrm() )
2654 if ( ((SwTxtFrm
*)pEndFrm
)->GetDropRect( aDropRect
) )
2655 Sub( aRegion
, aDropRect
);
2658 rCrsr
.Remove( 0, rCrsr
.Count() );
2659 rCrsr
.Insert( &aRegion
, 0 );