xref: /AOO41X/main/sw/source/core/layout/flylay.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #include "doc.hxx"
31 #include "pagefrm.hxx"
32 #include "rootfrm.hxx"
33 #include "cntfrm.hxx"
34 #include "dview.hxx"
35 #include "dflyobj.hxx"
36 #include "dcontact.hxx"
37 #include "flyfrm.hxx"
38 #include "ftnfrm.hxx"
39 #include "frmtool.hxx"
40 #include "frmfmt.hxx"
41 #include "errhdl.hxx"
42 #include "hints.hxx"
43 #include "pam.hxx"
44 #include "sectfrm.hxx"
45 
46 
47 #include <svx/svdpage.hxx>
48 #include <editeng/ulspitem.hxx>
49 #include <fmtanchr.hxx>
50 #include <fmtornt.hxx>
51 #include <fmtfsize.hxx>
52 #include "ndole.hxx"
53 #include "tabfrm.hxx"
54 #include "flyfrms.hxx"
55 // OD 22.09.2003 #i18732#
56 #include <fmtfollowtextflow.hxx>
57 // OD 29.10.2003 #113049#
58 #include <environmentofanchoredobject.hxx>
59 // OD 2004-05-24 #i28701#
60 #include <sortedobjs.hxx>
61 #include <viewsh.hxx>
62 #include <viewimp.hxx>
63 
64 
65 using namespace ::com::sun::star;
66 
67 
68 /*************************************************************************
69 |*
70 |*	SwFlyFreeFrm::SwFlyFreeFrm(), ~SwFlyFreeFrm()
71 |*
72 |*	Ersterstellung		MA 03. Dec. 92
73 |*	Letzte Aenderung	MA 09. Apr. 99
74 |*
75 |*************************************************************************/
76 
77 SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
78 	SwFlyFrm( pFmt, pSib, pAnch ),
79     pPage( 0 ),
80     // --> OD 2004-11-15 #i34753#
81     mbNoMakePos( false ),
82     // <--
83     // --> OD 2004-11-12 #i37068#
84     mbNoMoveOnCheckClip( false )
85     // <--
86 {
87 }
88 
89 SwFlyFreeFrm::~SwFlyFreeFrm()
90 {
91 	//und Tschuess.
92     // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
93     if( GetPageFrm() )
94     {
95         if( GetFmt()->GetDoc()->IsInDtor() )
96         {
97             // --> OD 2004-06-04 #i29879# - remove also to-frame anchored Writer
98             // fly frame from page.
99             const bool bRemoveFromPage =
100                     GetPageFrm()->GetSortedObjs() &&
101                     ( IsFlyAtCntFrm() ||
102                       ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
103             if ( bRemoveFromPage )
104             {
105                 GetPageFrm()->GetSortedObjs()->Remove( *this );
106             }
107         }
108         else
109         {
110             SwRect aTmp( GetObjRectWithSpaces() );
111             SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
112         }
113     }
114 }
115 
116 // --> OD 2004-06-29 #i28701#
117 TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
118 // <--
119 /*************************************************************************
120 |*
121 |*	SwFlyFreeFrm::NotifyBackground()
122 |*
123 |*	Beschreibung		Benachrichtigt den Hintergrund (alle CntntFrms die
124 |*		gerade ueberlappt werden. Ausserdem wird das Window in einigen
125 |* 		Faellen direkt invalidiert (vor allem dort, wo keine CntntFrms
126 |*		ueberlappt werden.
127 |* 		Es werden auch die CntntFrms innerhalb von anderen Flys
128 |*		beruecksichtigt.
129 |*	Ersterstellung		MA 03. Dec. 92
130 |*	Letzte Aenderung	MA 26. Aug. 93
131 |*
132 |*************************************************************************/
133 
134 void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
135 									 const SwRect& rRect, PrepareHint eHint )
136 {
137     ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, sal_True );
138 }
139 
140 /*************************************************************************
141 |*
142 |*	SwFlyFreeFrm::MakeAll()
143 |*
144 |*	Ersterstellung		MA 18. Feb. 94
145 |*	Letzte Aenderung	MA 03. Mar. 97
146 |*
147 |*************************************************************************/
148 
149 void SwFlyFreeFrm::MakeAll()
150 {
151     // OD 2004-01-19 #110582#
152     if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
153     {
154         return;
155     }
156 
157     if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
158 		return;
159     // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
160     if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
161     {
162         SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
163         SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
164         if( pPageFrm )
165             pPageFrm->AppendFlyToPage( this );
166     }
167     if( !GetPageFrm() )
168         return;
169 
170 	Lock();	//Der Vorhang faellt
171 
172 	//uebernimmt im DTor die Benachrichtigung
173 	const SwFlyNotify aNotify( this );
174 
175 	if ( IsClipped() )
176     {
177         bValidSize = bHeightClipped = bWidthClipped = sal_False;
178         // --> OD 2004-11-03 #114798# - no invalidation of position,
179         // if anchored object is anchored inside a Writer fly frame,
180         // its position is already locked, and it follows the text flow.
181         // --> OD 2004-11-15 #i34753# - add condition:
182         // no invalidation of position, if no direct move is requested in <CheckClip(..)>
183         if ( !IsNoMoveOnCheckClip() &&
184              !( PositionLocked() &&
185                 GetAnchorFrm()->IsInFly() &&
186                 GetFrmFmt().GetFollowTextFlow().GetValue() ) )
187         // <--
188         {
189             bValidPos = sal_False;
190         }
191         // <--
192     }
193 
194     // FME 2007-08-30 #i81146# new loop control
195     sal_uInt16 nLoopControlRuns = 0;
196     const sal_uInt16 nLoopControlMax = 10;
197 
198 	while ( !bValidPos || !bValidSize || !bValidPrtArea || bFormatHeightOnly )
199 	{
200         SWRECTFN( this )
201         const SwFmtFrmSize *pSz;
202 		{	//Zusaetzlicher Scope, damit aAccess vor dem Check zerstoert wird!
203 
204 			SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
205 			const SwBorderAttrs &rAttrs = *aAccess.Get();
206 			pSz = &rAttrs.GetAttrSet().GetFrmSize();
207 
208 			//Nur einstellen wenn das Flag gesetzt ist!!
209 			if ( !bValidSize )
210 			{
211 				bValidPrtArea = sal_False;
212 /*
213                 // This is also done in the Format function, so I think
214                 // this code is not necessary anymore:
215                 const Size aRelSize( CalcRel( *pSz ) );
216 				const SwTwips nMin = MINFLY + rAttrs.CalcLeftLine()+rAttrs.CalcRightLine();
217                 long nDiff = bVert ? aRelSize.Height() : aRelSize.Width();
218                 if( nDiff < nMin )
219                     nDiff = nMin;
220                 nDiff -= (aFrm.*fnRect->fnGetWidth)();
221                 if( nDiff )
222                 {
223                     (aFrm.*fnRect->fnAddRight)( nDiff );
224                     bValidPos = sal_False;
225                 }
226 */
227 			}
228 
229 			if ( !bValidPrtArea )
230 				MakePrtArea( rAttrs );
231 
232 			if ( !bValidSize || bFormatHeightOnly )
233 			{
234 				bValidSize = sal_False;
235 				Format( &rAttrs );
236 				bFormatHeightOnly = sal_False;
237 			}
238 
239 			if ( !bValidPos )
240 			{
241                 const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
242                 // OD 2004-03-23 #i26791# - use new method <MakeObjPos()>
243                 // --> OD 2004-11-15 #i34753# - no positioning, if requested.
244                 if ( IsNoMakePos() )
245                     bValidPos = sal_True;
246                 else
247                     // OD 2004-03-23 #i26791# - use new method <MakeObjPos()>
248                     MakeObjPos();
249                 // <--
250                 if( aOldPos == (Frm().*fnRect->fnGetPos)() )
251 				{
252                     if( !bValidPos && GetAnchorFrm()->IsInSct() &&
253                         !GetAnchorFrm()->FindSctFrm()->IsValid() )
254 						bValidPos = sal_True;
255 				}
256 				else
257 					bValidSize = sal_False;
258 			}
259 		}
260 
261         if ( bValidPos && bValidSize )
262         {
263             ++nLoopControlRuns;
264 
265 #if OSL_DEBUG_LEVEL > 1
266             ASSERT( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" )
267 #endif
268 
269             if ( nLoopControlRuns < nLoopControlMax )
270 			    CheckClip( *pSz );
271         }
272         else
273             nLoopControlRuns = 0;
274 	}
275 	Unlock();
276 
277 #ifdef DBG_UTIL
278     SWRECTFN( this )
279     ASSERT( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
280             (Prt().*fnRect->fnGetHeight)() > 0),
281 			"SwFlyFreeFrm::Format(), flipping Fly." );
282 
283 #endif
284 }
285 
286 /** determines, if direct environment of fly frame has 'auto' size
287 
288     OD 07.08.2003 #i17297#, #111066#, #111070#
289     start with anchor frame and search via <GetUpper()> for a header, footer,
290     row or fly frame stopping at page frame.
291     return <true>, if such a frame is found and it has 'auto' size.
292     otherwise <false> is returned.
293 
294     @author OD
295 
296     @return boolean indicating, that direct environment has 'auto' size
297 */
298 bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
299 {
300     bool bRetVal = false;
301 
302     const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
303     while ( pToBeCheckedFrm &&
304             !pToBeCheckedFrm->IsPageFrm() )
305     {
306         if ( pToBeCheckedFrm->IsHeaderFrm() ||
307              pToBeCheckedFrm->IsFooterFrm() ||
308              pToBeCheckedFrm->IsRowFrm() ||
309              pToBeCheckedFrm->IsFlyFrm() )
310         {
311             bRetVal = ATT_FIX_SIZE !=
312                       pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
313             break;
314         }
315         else
316         {
317             pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
318         }
319     }
320 
321     return bRetVal;
322 }
323 
324 /*************************************************************************
325 |*
326 |*	SwFlyFreeFrm::CheckClip()
327 |*
328 |*	Ersterstellung		MA 21. Feb. 94
329 |*	Letzte Aenderung	MA 03. Mar. 97
330 |*
331 |*************************************************************************/
332 
333 void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
334 {
335 	//Jetzt ist es ggf. an der Zeit geignete Massnahmen zu ergreifen wenn
336 	//der Fly nicht in seine Umgebung passt.
337     //Zuerst gibt der Fly seine Position auf. Danach wird er zunaechst
338     //formatiert. Erst wenn er auch durch die Aufgabe der Position nicht
339 	//passt wird die Breite oder Hoehe aufgegeben - der Rahmen wird soweit
340 	//wie notwendig zusammengequetscht.
341 
342 	const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
343 	SwRect aClip, aTmpStretch;
344 	::CalcClipRect( pObj, aClip, sal_True );
345 	::CalcClipRect( pObj, aTmpStretch, sal_False );
346 	aClip._Intersection( aTmpStretch );
347 
348     const long nBot = Frm().Top() + Frm().Height();
349     const long nRig = Frm().Left() + Frm().Width();
350     const long nClipBot = aClip.Top() + aClip.Height();
351     const long nClipRig = aClip.Left() + aClip.Width();
352 
353 	const sal_Bool bBot = nBot > nClipBot;
354 	const sal_Bool bRig = nRig > nClipRig;
355 	if ( bBot || bRig )
356 	{
357 		sal_Bool bAgain = sal_False;
358         // --> OD 2004-11-12 #i37068# - no move, if it's requested
359         if ( bBot && !IsNoMoveOnCheckClip() &&
360              !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
361         // <--
362 		{
363 			SwFrm* pHeader = FindFooterOrHeader();
364 			// In a header, correction of the position is no good idea.
365 			// If the fly moves, some paragraphs has to be formatted, this
366             // could cause a change of the height of the headerframe,
367 			// now the flyframe can change its position and so on ...
368             if ( !pHeader || !pHeader->IsHeaderFrm() )
369 			{
370 				const long nOld = Frm().Top();
371                 Frm().Pos().Y() = Max( aClip.Top(), nClipBot - Frm().Height() );
372                 if ( Frm().Top() != nOld )
373 					bAgain = sal_True;
374 				bHeightClipped = sal_True;
375 			}
376 		}
377 		if ( bRig )
378 		{
379 			const long nOld = Frm().Left();
380             Frm().Pos().X() = Max( aClip.Left(), nClipRig - Frm().Width() );
381 			if ( Frm().Left() != nOld )
382 			{
383 				const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
384 				// Links ausgerichtete duerfen nicht nach links verschoben werden,
385 				// wenn sie einem anderen ausweichen.
386                 if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
387 					Frm().Pos().X() = nOld;
388 				else
389 					bAgain = sal_True;
390 			}
391 			bWidthClipped = sal_True;
392 		}
393 		if ( bAgain )
394 			bValidSize = sal_False;
395 		else
396 		{
397 			//Wenn wir hier ankommen ragt der Frm in unerlaubte Bereiche
398 			//hinein, und eine Positionskorrektur ist nicht erlaubt bzw.
399 			//moeglich oder noetig.
400 
401 			//Fuer Flys mit OLE-Objekten als Lower sorgen wir dafuer, dass
402 			//immer proportional Resized wird.
403 			Size aOldSize( Frm().SSize() );
404 
405 			//Zuerst wird das FrmRect eingestellt, und dann auf den Frm
406 			//uebertragen.
407 			SwRect aFrmRect( Frm() );
408 
409 			if ( bBot )
410 			{
411 				long nDiff = nClipBot;
412                 nDiff -= aFrmRect.Top(); //nDiff ist die verfuegbare Strecke.
413 				nDiff = aFrmRect.Height() - nDiff;
414 				aFrmRect.Height( aFrmRect.Height() - nDiff );
415 				bHeightClipped = sal_True;
416 			}
417 			if ( bRig )
418 			{
419 				long nDiff = nClipRig;
420                 nDiff -= aFrmRect.Left();//nDiff ist die verfuegbare Strecke.
421 				nDiff = aFrmRect.Width() - nDiff;
422 				aFrmRect.Width( aFrmRect.Width() - nDiff );
423 				bWidthClipped = sal_True;
424 			}
425 
426             // OD 06.08.2003 #i17297#, #111066#, #111070# - no proportional
427             // scaling of graphics in environments, which determines its size
428             // by its content ('auto' size). Otherwise layout loops can occur and
429             // layout sizes of the environment can be incorrect.
430             // Such environment are:
431             // (1) header and footer frames with 'auto' size
432             // (2) table row frames with 'auto' size
433             // (3) fly frames with 'auto' size
434 			// Note: section frames seems to be not critical - didn't found
435             //       any critical layout situation so far.
436             if ( Lower() && Lower()->IsNoTxtFrm() &&
437                  ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
438                    !HasEnvironmentAutoSize() ) )
439 			{
440 				//Wenn Breite und Hoehe angepasst wurden, so ist die
441 				//groessere Veraenderung massgeblich.
442 				if ( aFrmRect.Width() != aOldSize.Width() &&
443 					 aFrmRect.Height()!= aOldSize.Height() )
444 				{
445 					if ( (aOldSize.Width() - aFrmRect.Width()) >
446 						 (aOldSize.Height()- aFrmRect.Height())	)
447 						aFrmRect.Height( aOldSize.Height() );
448 					else
449 						aFrmRect.Width( aOldSize.Width() );
450 				}
451 
452 				//Breite angepasst? - Hoehe dann proportional verkleinern
453 				if( aFrmRect.Width() != aOldSize.Width() )
454                 {
455 					aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
456 									 aOldSize.Width() );
457                     bHeightClipped = sal_True;
458                 }
459 				//Hoehe angepasst? - Breite dann proportional verkleinern
460                 else if( aFrmRect.Height() != aOldSize.Height() )
461                 {
462 					aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
463 									aOldSize.Height() );
464                     bWidthClipped = sal_True;
465                 }
466 
467                 // OD 07.08.2003 #i17297#, #111066#, #111070# - reactivate change
468                 // of size attribute for fly frames containing an ole object.
469                 // FME: 2004-05-19 Added the aFrmRect.HasArea() hack, because
470                 // the environment of the ole object does not have to be valid
471                 // at this moment, or even worse, it does not have to have a
472                 // resonable size. In this case we do not want to change to
473                 // attributes permanentely. Maybe one day somebody dares to remove
474                 // this code.
475                 if ( aFrmRect.HasArea() &&
476                      static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
477                      ( bWidthClipped || bHeightClipped ) )
478                 {
479                     SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
480                     pFmt->LockModify();
481                     SwFmtFrmSize aFrmSize( rSz );
482                     aFrmSize.SetWidth( aFrmRect.Width() );
483                     aFrmSize.SetHeight( aFrmRect.Height() );
484                     pFmt->SetFmtAttr( aFrmSize );
485                     pFmt->UnlockModify();
486                 }
487 			}
488 
489 			//Jetzt die Einstellungen am Frm vornehmen, bei Spalten werden
490 			//die neuen Werte in die Attribute eingetragen, weil es sonst
491 			//ziemlich fiese Oszillationen gibt.
492 			const long nPrtHeightDiff = Frm().Height() - Prt().Height();
493 			const long nPrtWidthDiff  = Frm().Width()  - Prt().Width();
494 			Frm().Height( aFrmRect.Height() );
495 			Frm().Width ( Max( long(MINLAY), aFrmRect.Width() ) );
496 			if ( Lower() && Lower()->IsColumnFrm() )
497 			{
498 				ColLock();	//Grow/Shrink locken.
499                 const Size aTmpOldSize( Prt().SSize() );
500 				Prt().Height( Frm().Height() - nPrtHeightDiff );
501 				Prt().Width ( Frm().Width()  - nPrtWidthDiff );
502                 ChgLowersProp( aTmpOldSize );
503 				SwFrm *pLow = Lower();
504 				do
505 				{	pLow->Calc();
506 					// auch den (Column)BodyFrm mitkalkulieren
507 					((SwLayoutFrm*)pLow)->Lower()->Calc();
508 					pLow = pLow->GetNext();
509 				} while ( pLow );
510 				::CalcCntnt( this );
511 				ColUnlock();
512 				if ( !bValidSize && !bWidthClipped )
513 					bFormatHeightOnly = bValidSize = sal_True;
514 			}
515 			else
516 			{
517 				Prt().Height( Frm().Height() - nPrtHeightDiff );
518 				Prt().Width ( Frm().Width()  - nPrtWidthDiff );
519 			}
520 		}
521 	}
522 
523     // --> OD 2004-10-14 #i26945#
524     ASSERT( Frm().Height() >= 0,
525             "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
526     // <--
527 }
528 
529 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
530 
531     OD 2005-03-03 #i43771#
532 
533     @author OD
534 */
535 bool SwFlyFreeFrm::IsFormatPossible() const
536 {
537     return SwFlyFrm::IsFormatPossible() &&
538            ( GetPageFrm() ||
539              ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
540 }
541 
542 /*************************************************************************
543 |*
544 |*	SwFlyLayFrm::SwFlyLayFrm()
545 |*
546 |*	Ersterstellung		MA 25. Aug. 92
547 |*	Letzte Aenderung	MA 09. Apr. 99
548 |*
549 |*************************************************************************/
550 
551 SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
552 	SwFlyFreeFrm( pFmt, pSib, pAnch )
553 {
554 	bLayout = sal_True;
555 }
556 
557 // --> OD 2004-06-29 #i28701#
558 TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
559 // <--
560 /*************************************************************************
561 |*
562 |*	SwFlyLayFrm::Modify()
563 |*
564 |*	Ersterstellung		MA 08. Feb. 93
565 |*	Letzte Aenderung	MA 28. Aug. 93
566 |*
567 |*************************************************************************/
568 
569 void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
570 {
571 	sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
572 
573 	SwFmtAnchor *pAnch = 0;
574 	if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET ==
575 		((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False,
576 			(const SfxPoolItem**)&pAnch ))
577 		;		// Beim GetItemState wird der AnkerPointer gesetzt !
578 
579 	else if( RES_ANCHOR == nWhich )
580 	{
581 		//Ankerwechsel, ich haenge mich selbst um.
582 		//Es darf sich nicht um einen Wechsel des Ankertyps handeln,
583 		//dies ist nur ueber die SwFEShell moeglich.
584 		pAnch = (SwFmtAnchor*)pNew;
585 	}
586 
587 	if( pAnch )
588 	{
589 		ASSERT( pAnch->GetAnchorId() ==
590 				GetFmt()->GetAnchor().GetAnchorId(),
591 				"8-) Unzulaessiger Wechsel des Ankertyps." );
592 
593 		//Abmelden, Seite besorgen, an den entsprechenden LayoutFrm
594 		//haengen.
595         SwRect aOld( GetObjRectWithSpaces() );
596         // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
597         SwPageFrm *pOldPage = GetPageFrm();
598         AnchorFrm()->RemoveFly( this );
599 
600         if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
601         {
602 			sal_uInt16 nPgNum = pAnch->GetPageNum();
603 			SwRootFrm *pRoot = getRootFrm();
604             SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
605             for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
606                                 pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
607 			{
608 				if ( i == nPgNum )
609                 {
610                     // --> OD 2005-06-09 #i50432# - adjust synopsis of <PlaceFly(..)>
611                     pTmpPage->PlaceFly( this, 0 );
612                     // <--
613                 }
614 			}
615             if( !pTmpPage )
616 			{
617 				pRoot->SetAssertFlyPages();
618 				pRoot->AssertFlyPages();
619 			}
620 		}
621 		else
622 		{
623 			SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
624 			SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
625 						 GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, sal_False );
626 			if( pCntnt )
627 			{
628 				SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
629 				if( pTmp )
630 					pTmp->AppendFly( this );
631 			}
632 		}
633         // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
634         if ( pOldPage && pOldPage != GetPageFrm() )
635 			NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
636 		SetCompletePaint();
637 		InvalidateAll();
638 		SetNotifyBack();
639 	}
640 	else
641 		SwFlyFrm::Modify( pOld, pNew );
642 }
643 
644 /*************************************************************************
645 |*
646 |*	SwPageFrm::AppendFly()
647 |*
648 |*	Ersterstellung		MA 10. Oct. 92
649 |*	Letzte Aenderung	MA 08. Jun. 96
650 |*
651 |*************************************************************************/
652 
653 void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
654 {
655 	if ( !pNew->GetVirtDrawObj()->IsInserted() )
656 		getRootFrm()->GetDrawPage()->InsertObject(
657 				(SdrObject*)pNew->GetVirtDrawObj(),
658 				pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
659 
660 	InvalidateSpelling();
661     InvalidateSmartTags();  // SMARTTAGS
662 	InvalidateAutoCompleteWords();
663     InvalidateWordCount();
664 
665 	if ( GetUpper() )
666 	{
667 		((SwRootFrm*)GetUpper())->SetIdleFlags();
668 		((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
669 	}
670 
671     SdrObject* pObj = pNew->GetVirtDrawObj();
672     ASSERT( pNew->GetAnchorFrm(), "Fly without Anchor" );
673     const SwFlyFrm* pFly = pNew->GetAnchorFrm()->FindFlyFrm();
674 	if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
675 	{
676         sal_uInt32 nNewNum = pFly->GetVirtDrawObj()->GetOrdNumDirect();
677 		if ( pObj->GetPage() )
678 			pObj->GetPage()->SetObjectOrdNum( pObj->GetOrdNumDirect(), nNewNum);
679 		else
680 			pObj->SetOrdNum( nNewNum );
681 	}
682 
683 	//Flys die im Cntnt sitzen beachten wir nicht weiter.
684 	if ( pNew->IsFlyInCntFrm() )
685 		InvalidateFlyInCnt();
686     else
687     {
688         InvalidateFlyCntnt();
689 
690         if ( !pSortedObjs )
691             pSortedObjs = new SwSortedObjs();
692 
693 #if OSL_DEBUG_LEVEL > 1
694         const bool bSucessInserted =
695 #endif
696         pSortedObjs->Insert( *pNew );
697 #if OSL_DEBUG_LEVEL > 1
698         ASSERT( bSucessInserted, "Fly nicht in Sorted eingetragen." )
699         (void) bSucessInserted;
700 #endif
701 
702         // --> OD 2008-04-22 #i87493#
703         ASSERT( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
704                 "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
705         // <--
706         // --> OD 2004-06-30 #i28701# - use new method <SetPageFrm(..)>
707         pNew->SetPageFrm( this );
708         pNew->InvalidatePage( this );
709         // OD 2004-05-17 #i28701#
710         pNew->UnlockPosition();
711 
712 		// Notify accessible layout. That's required at this place for
713 		// frames only where the anchor is moved. Creation of new frames
714 		// is additionally handled by the SwFrmNotify class.
715 		if( GetUpper() &&
716 			static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
717 		 	static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
718 		{
719 			static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
720 									  ->AddAccessibleFrm( pNew );
721 		}
722     }
723 
724     // --> OD 2004-06-09 #i28701# - correction: consider also drawing objects
725     if ( pNew->GetDrawObjs() )
726     {
727         SwSortedObjs &rObjs = *pNew->GetDrawObjs();
728         for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
729         {
730             SwAnchoredObject* pTmpObj = rObjs[i];
731             if ( pTmpObj->ISA(SwFlyFrm) )
732             {
733                 SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
734                 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
735                 if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
736                     AppendFlyToPage( pTmpFly );
737             }
738             else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
739             {
740                 // --> OD 2008-04-22 #i87493#
741 //                AppendDrawObjToPage( *pTmpObj );
742                 if ( pTmpObj->GetPageFrm() != this )
743                 {
744                     if ( pTmpObj->GetPageFrm() != 0 )
745                     {
746                         pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
747                     }
748                     AppendDrawObjToPage( *pTmpObj );
749                 }
750                 // <--
751             }
752         }
753     }
754 }
755 
756 /*************************************************************************
757 |*
758 |*	SwPageFrm::RemoveFly()
759 |*
760 |*	Ersterstellung		MA 10. Oct. 92
761 |*	Letzte Aenderung	MA 26. Aug. 96
762 |*
763 |*************************************************************************/
764 
765 void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
766 {
767 	const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
768 	getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
769 	pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
770 
771 	if ( GetUpper() )
772 	{
773 		if ( !pToRemove->IsFlyInCntFrm() )
774 			((SwRootFrm*)GetUpper())->SetSuperfluous();
775 		((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
776 	}
777 
778 	//Flys die im Cntnt sitzen beachten wir nicht weiter.
779 	if ( pToRemove->IsFlyInCntFrm() )
780 		return;
781 
782 	// Notify accessible layout. That's required at this place for
783 	// frames only where the anchor is moved. Creation of new frames
784 	// is additionally handled by the SwFrmNotify class.
785 	if( GetUpper() &&
786 		static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
787 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
788 	{
789 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
790 								  ->DisposeAccessibleFrm( pToRemove, sal_True );
791 	}
792 
793 	//Collections noch nicht loeschen. Das passiert am Ende
794 	//der Action im RemoveSuperfluous der Seite - angestossen von gleich-
795 	//namiger Methode der Root.
796 	//Die FlyColl kann bereits weg sein, weil der DTor der Seite
797 	//gerade 'laeuft'
798 	if ( pSortedObjs )
799 	{
800         pSortedObjs->Remove( *pToRemove );
801 		if ( !pSortedObjs->Count() )
802 		{	DELETEZ( pSortedObjs );
803 		}
804 	}
805     // --> OD 2004-06-30 #i28701# - use new method <SetPageFrm(..)>
806     pToRemove->SetPageFrm( 0L );
807 }
808 
809 /*************************************************************************
810 |*
811 |*	SwPageFrm::MoveFly
812 |*
813 |*	Ersterstellung		MA 25. Jan. 97
814 |*	Letzte Aenderung	MA 25. Jan. 97
815 |*
816 |*************************************************************************/
817 
818 void SwPageFrm::MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest )
819 {
820 	//Invalidierungen
821 	if ( GetUpper() )
822 	{
823 		((SwRootFrm*)GetUpper())->SetIdleFlags();
824 		if ( !pToMove->IsFlyInCntFrm() && pDest->GetPhyPageNum() < GetPhyPageNum() )
825 			((SwRootFrm*)GetUpper())->SetSuperfluous();
826 	}
827 
828 	pDest->InvalidateSpelling();
829     pDest->InvalidateSmartTags();   // SMARTTAGS
830 	pDest->InvalidateAutoCompleteWords();
831     pDest->InvalidateWordCount();
832 
833     if ( pToMove->IsFlyInCntFrm() )
834 	{
835 		pDest->InvalidateFlyInCnt();
836 		return;
837 	}
838 
839 	// Notify accessible layout. That's required at this place for
840 	// frames only where the anchor is moved. Creation of new frames
841 	// is additionally handled by the SwFrmNotify class.
842 	if( GetUpper() &&
843 		static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
844 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
845 	{
846 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
847 								  ->DisposeAccessibleFrm( pToMove, sal_True );
848 	}
849 
850 	//Die FlyColl kann bereits weg sein, weil der DTor der Seite
851 	//gerade 'laeuft'
852 	if ( pSortedObjs )
853 	{
854         pSortedObjs->Remove( *pToMove );
855 		if ( !pSortedObjs->Count() )
856 		{	DELETEZ( pSortedObjs );
857 		}
858 	}
859 
860 	//Anmelden
861 	if ( !pDest->GetSortedObjs() )
862         pDest->pSortedObjs = new SwSortedObjs();
863 
864 #if OSL_DEBUG_LEVEL > 1
865     const bool bSucessInserted =
866 #endif
867     pDest->GetSortedObjs()->Insert( *pToMove );
868 #if OSL_DEBUG_LEVEL > 1
869 	ASSERT( bSucessInserted, "Fly nicht in Sorted eingetragen." )
870     (void) bSucessInserted;
871 #endif
872 
873     // --> OD 2004-06-30 #i28701# - use new method <SetPageFrm(..)>
874     pToMove->SetPageFrm( pDest );
875 	pToMove->InvalidatePage( pDest );
876 	pToMove->SetNotifyBack();
877 	pDest->InvalidateFlyCntnt();
878     // OD 2004-05-17 #i28701#
879     pToMove->UnlockPosition();
880 
881 	// Notify accessible layout. That's required at this place for
882 	// frames only where the anchor is moved. Creation of new frames
883 	// is additionally handled by the SwFrmNotify class.
884 	if( GetUpper() &&
885 		static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
886 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
887 	{
888 		static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
889 								  ->AddAccessibleFrm( pToMove );
890 	}
891 
892     // --> OD 2004-06-09 #i28701# - correction: move lowers of Writer fly frame
893     if ( pToMove->GetDrawObjs() )
894     {
895         SwSortedObjs &rObjs = *pToMove->GetDrawObjs();
896         for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
897         {
898             SwAnchoredObject* pObj = rObjs[i];
899             if ( pObj->ISA(SwFlyFrm) )
900             {
901                 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
902                 if ( pFly->IsFlyFreeFrm() )
903                 {
904                     // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
905                     SwPageFrm* pPageFrm = pFly->GetPageFrm();
906                     if ( pPageFrm )
907                         pPageFrm->MoveFly( pFly, pDest );
908                     else
909                         pDest->AppendFlyToPage( pFly );
910                 }
911             }
912             else if ( pObj->ISA(SwAnchoredDrawObject) )
913             {
914                 RemoveDrawObjFromPage( *pObj );
915                 pDest->AppendDrawObjToPage( *pObj );
916             }
917         }
918     }
919 }
920 
921 /*************************************************************************
922 |*
923 |*  SwPageFrm::AppendDrawObjToPage(), RemoveDrawObjFromPage()
924 |*
925 |*  --> OD 2004-07-02 #i28701# - new methods
926 |*
927 |*************************************************************************/
928 void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
929 {
930     if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
931     {
932         ASSERT( false,
933                 "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexcepted type -> object not appended" );
934         return;
935     }
936 
937     if ( GetUpper() )
938     {
939         ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
940     }
941 
942     ASSERT( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
943     const SwFlyFrm* pFlyFrm = _rNewObj.GetAnchorFrm()->FindFlyFrm();
944     if ( pFlyFrm &&
945          _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
946     {
947         sal_uInt32 nNewNum = pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect();
948         if ( _rNewObj.GetDrawObj()->GetPage() )
949             _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum(
950                             _rNewObj.GetDrawObj()->GetOrdNumDirect(), nNewNum);
951         else
952             _rNewObj.DrawObj()->SetOrdNum( nNewNum );
953     }
954 
955     if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
956     {
957         return;
958     }
959 
960     if ( !pSortedObjs )
961     {
962         pSortedObjs = new SwSortedObjs();
963     }
964     if ( !pSortedObjs->Insert( _rNewObj ) )
965     {
966 #ifdef DBG_UTIL
967         ASSERT( pSortedObjs->Contains( _rNewObj ),
968                 "Drawing object not appended into list <pSortedObjs>." );
969 #endif
970     }
971     // --> OD 2008-04-22 #i87493#
972     ASSERT( _rNewObj.GetPageFrm() == 0 || _rNewObj.GetPageFrm() == this,
973             "<SwPageFrm::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect -> please inform OD." );
974     // <--
975     _rNewObj.SetPageFrm( this );
976 
977     // invalidate page in order to force a reformat of object layout of the page.
978     InvalidateFlyLayout();
979 }
980 
981 void SwPageFrm::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj )
982 {
983     if ( !_rToRemoveObj.ISA(SwAnchoredDrawObject) )
984     {
985         ASSERT( false,
986                 "SwPageFrm::RemoveDrawObjFromPage(..) - anchored object of unexcepted type -> object not removed" );
987         return;
988     }
989 
990     if ( pSortedObjs )
991     {
992         pSortedObjs->Remove( _rToRemoveObj );
993         if ( !pSortedObjs->Count() )
994         {
995             DELETEZ( pSortedObjs );
996         }
997         if ( GetUpper() )
998         {
999             if (FLY_AS_CHAR !=
1000                     _rToRemoveObj.GetFrmFmt().GetAnchor().GetAnchorId())
1001             {
1002                 ((SwRootFrm*)GetUpper())->SetSuperfluous();
1003                 InvalidatePage();
1004             }
1005             ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
1006         }
1007     }
1008     _rToRemoveObj.SetPageFrm( 0 );
1009 }
1010 
1011 /*************************************************************************
1012 |*
1013 |*	SwPageFrm::PlaceFly
1014 |*
1015 |*	Ersterstellung		MA 08. Feb. 93
1016 |*	Letzte Aenderung	MA 27. Feb. 93
1017 |*
1018 |*************************************************************************/
1019 
1020 // --> OD 2005-06-09 #i50432# - adjust method description and synopsis.
1021 void SwPageFrm::PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt )
1022 {
1023     // --> OD 2005-06-09 #i50432# - consider the case that page is an empty page:
1024     // In this case append the fly frame at the next page
1025     ASSERT( !IsEmptyPage() || GetNext(),
1026             "<SwPageFrm::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
1027     if ( IsEmptyPage() && GetNext() )
1028     {
1029         static_cast<SwPageFrm*>(GetNext())->PlaceFly( pFly, pFmt );
1030     }
1031     else
1032     {
1033         //Wenn ein Fly uebergeben wurde, so benutzen wir diesen, ansonsten wird
1034         //mit dem Format einer erzeugt.
1035         if ( pFly )
1036             AppendFly( pFly );
1037         else
1038         {   ASSERT( pFmt, ":-( kein Format fuer Fly uebergeben." );
1039             pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
1040             AppendFly( pFly );
1041             ::RegistFlys( this, pFly );
1042         }
1043     }
1044     // <--
1045 }
1046 
1047 /*************************************************************************
1048 |*
1049 |*	::CalcClipRect
1050 |*
1051 |*	Ersterstellung		AMA 24. Sep. 96
1052 |*	Letzte Aenderung	MA  18. Dec. 96
1053 |*
1054 |*************************************************************************/
1055 // OD 22.09.2003 #i18732# - adjustments for following text flow or not
1056 // AND alignment at 'page areas' for to paragraph/to character anchored objects
1057 // OD 06.11.2003 #i22305# - adjustment for following text flow
1058 // for to frame anchored objects
1059 // OD 2004-06-02 #i29778# - Because the calculation of the position of the
1060 // floating screen object (Writer fly frame or drawing object) doesn't perform
1061 // a calculation on its upper frames and its anchor frame, a calculation of
1062 // the upper frames in this method no longer sensible.
1063 // --> OD 2004-07-06 #i28701# - if document compatibility option 'Consider
1064 // wrapping style influence on object positioning' is ON, the clip area
1065 // corresponds to the one as the object doesn't follows the text flow.
1066 sal_Bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, sal_Bool bMove )
1067 {
1068 	sal_Bool bRet = sal_True;
1069 	if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
1070 	{
1071         const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
1072         const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
1073         // --> OD 2004-07-06 #i28701#
1074         const bool bConsiderWrapOnObjPos =
1075                                 pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
1076         // <--
1077         const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
1078         if( pFly->IsFlyLayFrm() )
1079 		{
1080             const SwFrm* pClip;
1081             // OD 06.11.2003 #i22305#
1082             // --> OD 2004-07-06 #i28701#
1083             if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
1084             {
1085                 pClip = pFly->GetAnchorFrm()->FindPageFrm();
1086             }
1087             else
1088             {
1089                 pClip = pFly->GetAnchorFrm();
1090             }
1091 
1092 			rRect = pClip->Frm();
1093             SWRECTFN( pClip )
1094 
1095 			//Vertikales clipping: Top und Bottom, ggf. an PrtArea
1096             if( rV.GetVertOrient() != text::VertOrientation::NONE &&
1097                 rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1098 			{
1099                 (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
1100                 (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
1101 			}
1102 			//Horizontales clipping: Left und Right, ggf. an PrtArea
1103 			const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
1104             if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
1105                 rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
1106 			{
1107                 (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
1108                 (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
1109 			}
1110 		}
1111 		else if( pFly->IsFlyAtCntFrm() )
1112 		{
1113             // OD 22.09.2003 #i18732# - consider following text flow or not
1114             // AND alignment at 'page areas'
1115             const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
1116             if ( !pVertPosOrientFrm )
1117             {
1118                 ASSERT( false,
1119                         "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
1120                 pVertPosOrientFrm = pFly->GetAnchorFrm();
1121             }
1122 
1123             if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
1124             {
1125                 const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
1126                 rRect = bMove ? pClipFrm->GetUpper()->Frm()
1127                               : pClipFrm->Frm();
1128                 // --> OD 2004-10-14 #i26945# - consider that a table, during
1129                 // its format, can exceed its upper printing area bottom.
1130                 // Thus, enlarge the clip rectangle, if such a case occured
1131                 if ( pFly->GetAnchorFrm()->IsInTab() )
1132                 {
1133                     const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
1134                                 ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
1135                     SwRect aTmp( pTabFrm->Prt() );
1136                     aTmp += pTabFrm->Frm().Pos();
1137                     rRect.Union( aTmp );
1138                     // --> OD 2005-03-30 #i43913# - consider also the cell frame
1139                     const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
1140                                 ->GetAnchorFrmContainingAnchPos()->GetUpper();
1141                     while ( pCellFrm && !pCellFrm->IsCellFrm() )
1142                     {
1143                         pCellFrm = pCellFrm->GetUpper();
1144                     }
1145                     if ( pCellFrm )
1146                     {
1147                         aTmp = pCellFrm->Prt();
1148                         aTmp += pCellFrm->Frm().Pos();
1149                         rRect.Union( aTmp );
1150                     }
1151                     // <--
1152                 }
1153             }
1154             else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
1155                       rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
1156             {
1157                 // OD 29.10.2003 #113049# - new class <SwEnvironmentOfAnchoredObject>
1158                 objectpositioning::SwEnvironmentOfAnchoredObject
1159                                                 aEnvOfObj( bFollowTextFlow );
1160                 const SwLayoutFrm& rVertClipFrm =
1161                     aEnvOfObj.GetVertEnvironmentLayoutFrm( *pVertPosOrientFrm );
1162                 if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
1163                 {
1164                     rRect = rVertClipFrm.Frm();
1165                 }
1166                 else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
1167                 {
1168                     if ( rVertClipFrm.IsPageFrm() )
1169                     {
1170                         rRect = static_cast<const SwPageFrm&>(rVertClipFrm).PrtWithoutHeaderAndFooter();
1171                     }
1172                     else
1173                     {
1174                         rRect = rVertClipFrm.Frm();
1175                     }
1176                 }
1177                 const SwLayoutFrm* pHoriClipFrm =
1178                         pFly->GetAnchorFrm()->FindPageFrm()->GetUpper();
1179                 SWRECTFN( pFly->GetAnchorFrm() )
1180                 (rRect.*fnRect->fnSetLeft)( (pHoriClipFrm->Frm().*fnRect->fnGetLeft)() );
1181                 (rRect.*fnRect->fnSetRight)((pHoriClipFrm->Frm().*fnRect->fnGetRight)());
1182             }
1183             else
1184             {
1185                 // --> OD 2004-10-11 #i26945#
1186                 const SwFrm *pClip =
1187                         const_cast<SwFlyFrm*>(pFly)->GetAnchorFrmContainingAnchPos();
1188                 // <--
1189                 SWRECTFN( pClip )
1190                 const SwLayoutFrm *pUp = pClip->GetUpper();
1191                 const SwFrm *pCell = pUp->IsCellFrm() ? pUp : 0;
1192                 sal_uInt16 nType = bMove ? FRM_ROOT   | FRM_FLY | FRM_HEADER |
1193                                        FRM_FOOTER | FRM_FTN
1194                                      : FRM_BODY   | FRM_FLY | FRM_HEADER |
1195                                        FRM_FOOTER | FRM_CELL| FRM_FTN;
1196 
1197                 while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrm() )
1198                 {
1199                     pUp = pUp->GetUpper();
1200                     if ( !pCell && pUp->IsCellFrm() )
1201                         pCell = pUp;
1202                 }
1203                 if ( bMove )
1204                 {
1205                     if ( pUp->IsRootFrm() )
1206                     {
1207                         rRect  = pUp->Prt();
1208                         rRect += pUp->Frm().Pos();
1209                         pUp = 0;
1210                     }
1211                 }
1212                 if ( pUp )
1213                 {
1214                     if ( pUp->GetType() & FRM_BODY )
1215                     {
1216                         const SwPageFrm *pPg;
1217                         if ( pUp->GetUpper() != (pPg = pFly->FindPageFrm()) )
1218                             pUp = pPg->FindBodyCont();
1219                         rRect = pUp->GetUpper()->Frm();
1220                         (rRect.*fnRect->fnSetTop)( (pUp->*fnRect->fnGetPrtTop)() );
1221                         (rRect.*fnRect->fnSetBottom)((pUp->*fnRect->fnGetPrtBottom)());
1222                     }
1223                     else
1224                     {
1225                         if( ( pUp->GetType() & (FRM_FLY | FRM_FTN ) ) &&
1226                             !pUp->Frm().IsInside( pFly->Frm().Pos() ) )
1227                         {
1228                             if( pUp->IsFlyFrm() )
1229                             {
1230                                 SwFlyFrm *pTmpFly = (SwFlyFrm*)pUp;
1231                                 while( pTmpFly->GetNextLink() )
1232                                 {
1233                                     pTmpFly = pTmpFly->GetNextLink();
1234                                     if( pTmpFly->Frm().IsInside( pFly->Frm().Pos() ) )
1235                                         break;
1236                                 }
1237                                 pUp = pTmpFly;
1238                             }
1239                             else if( pUp->IsInFtn() )
1240                             {
1241                                 const SwFtnFrm *pTmp = pUp->FindFtnFrm();
1242                                 while( pTmp->GetFollow() )
1243                                 {
1244                                     pTmp = pTmp->GetFollow();
1245                                     if( pTmp->Frm().IsInside( pFly->Frm().Pos() ) )
1246                                         break;
1247                                 }
1248                                 pUp = pTmp;
1249                             }
1250                         }
1251                         rRect = pUp->Prt();
1252                         rRect.Pos() += pUp->Frm().Pos();
1253                         if ( pUp->GetType() & (FRM_HEADER | FRM_FOOTER) )
1254                         {
1255                             rRect.Left ( pUp->GetUpper()->Frm().Left() );
1256                             rRect.Width( pUp->GetUpper()->Frm().Width());
1257                         }
1258                         else if ( pUp->IsCellFrm() )                //MA_FLY_HEIGHT
1259                         {
1260                             const SwFrm *pTab = pUp->FindTabFrm();
1261                             (rRect.*fnRect->fnSetBottom)(
1262                                         (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1263                             // OD 08.08.2003 #110978# - expand to left and right
1264                             // cell border
1265                             rRect.Left ( pUp->Frm().Left() );
1266                             rRect.Width( pUp->Frm().Width() );
1267                         }
1268                     }
1269                 }
1270                 if ( pCell )
1271                 {
1272                     //CellFrms koennen auch in 'unerlaubten' Bereichen stehen, dann
1273                     //darf der Fly das auch.
1274                     SwRect aTmp( pCell->Prt() );
1275                     aTmp += pCell->Frm().Pos();
1276                     rRect.Union( aTmp );
1277                 }
1278             }
1279 		}
1280 		else
1281 		{
1282             const SwFrm *pUp = pFly->GetAnchorFrm()->GetUpper();
1283             SWRECTFN( pFly->GetAnchorFrm() )
1284             while( pUp->IsColumnFrm() || pUp->IsSctFrm() || pUp->IsColBodyFrm())
1285                 pUp = pUp->GetUpper();
1286             rRect = pUp->Frm();
1287             if( !pUp->IsBodyFrm() )
1288             {
1289                 rRect += pUp->Prt().Pos();
1290                 rRect.SSize( pUp->Prt().SSize() );
1291                 if ( pUp->IsCellFrm() )
1292                 {
1293                     const SwFrm *pTab = pUp->FindTabFrm();
1294                     (rRect.*fnRect->fnSetBottom)(
1295                                     (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1296                 }
1297             }
1298             else if ( pUp->GetUpper()->IsPageFrm() )
1299             {
1300                 // #111909# Objects anchored as character may exceed right margin
1301                 // of body frame:
1302                 (rRect.*fnRect->fnSetRight)( (pUp->GetUpper()->Frm().*fnRect->fnGetRight)() );
1303             }
1304             long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1305             long nTop;
1306             const SwFmt *pFmt = ((SwContact*)GetUserCall(pSdrObj))->GetFmt();
1307             const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1308             if( bMove )
1309             {
1310                 nTop = bVert ? ((SwFlyInCntFrm*)pFly)->GetRefPoint().X() :
1311                                ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y();
1312                 nTop = (*fnRect->fnYInc)( nTop, -nHeight );
1313                 long nWidth = (pFly->Frm().*fnRect->fnGetWidth)();
1314                 (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1315                             ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y() :
1316                             ((SwFlyInCntFrm*)pFly)->GetRefPoint().X(), nWidth );
1317                 nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper();
1318 			}
1319             else
1320             {
1321                 nTop = (*fnRect->fnYInc)( (pFly->Frm().*fnRect->fnGetBottom)(),
1322                                            rUL.GetLower() - nHeight );
1323                 nHeight = 2*nHeight - (pFly->Frm().*fnRect->fnGetHeight)()
1324                           - rUL.GetLower() - rUL.GetUpper();
1325             }
1326             (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1327 		}
1328 	}
1329 	else
1330 	{
1331 		const SwDrawContact *pC = (const SwDrawContact*)GetUserCall(pSdrObj);
1332 		const SwFrmFmt  *pFmt = (const SwFrmFmt*)pC->GetFmt();
1333 		const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1334         if ( FLY_AS_CHAR == rAnch.GetAnchorId() )
1335         {
1336             const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1337             if( !pAnchorFrm )
1338             {
1339                 ASSERT( false, "<::CalcClipRect(..)> - missing anchor frame." );
1340                 ((SwDrawContact*)pC)->ConnectToLayout();
1341                 pAnchorFrm = pC->GetAnchorFrm();
1342             }
1343             const SwFrm* pUp = pAnchorFrm->GetUpper();
1344             rRect = pUp->Prt();
1345             rRect += pUp->Frm().Pos();
1346             SWRECTFN( pAnchorFrm )
1347             long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1348             long nTop;
1349             const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1350             SwRect aSnapRect( pSdrObj->GetSnapRect() );
1351             long nTmpH = 0;
1352             if( bMove )
1353             {
1354                 nTop = (*fnRect->fnYInc)( bVert ? pSdrObj->GetAnchorPos().X() :
1355                                        pSdrObj->GetAnchorPos().Y(), -nHeight );
1356                 long nWidth = (aSnapRect.*fnRect->fnGetWidth)();
1357                 (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1358                             pSdrObj->GetAnchorPos().Y() :
1359                             pSdrObj->GetAnchorPos().X(), nWidth );
1360 			}
1361             else
1362             {
1363                 // OD 2004-04-13 #i26791# - value of <nTmpH> is needed to
1364                 // calculate value of <nTop>.
1365                 nTmpH = bVert ? pSdrObj->GetCurrentBoundRect().GetWidth() :
1366                                 pSdrObj->GetCurrentBoundRect().GetHeight();
1367                 nTop = (*fnRect->fnYInc)( (aSnapRect.*fnRect->fnGetTop)(),
1368                                           rUL.GetLower() + nTmpH - nHeight );
1369             }
1370             nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper();
1371             (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1372 		}
1373 		else
1374         {
1375             // OD 23.06.2003 #108784# - restrict clip rectangle for drawing
1376             // objects in header/footer to the page frame.
1377             // OD 2004-03-29 #i26791#
1378             const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1379             if ( pAnchorFrm && pAnchorFrm->FindFooterOrHeader() )
1380             {
1381                 // clip frame is the page frame the header/footer is on.
1382                 const SwFrm* pClipFrm = pAnchorFrm->FindPageFrm();
1383                 rRect = pClipFrm->Frm();
1384             }
1385             else
1386             {
1387                 bRet = sal_False;
1388             }
1389         }
1390 	}
1391 	return bRet;
1392 }
1393