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