Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "pagefrm.hxx"
21 : #include "rootfrm.hxx"
22 : #include "cntfrm.hxx"
23 : #include "dflyobj.hxx"
24 : #include "dcontact.hxx"
25 : #include "ftnfrm.hxx"
26 : #include "frmtool.hxx"
27 : #include "hints.hxx"
28 : #include "sectfrm.hxx"
29 :
30 : #include <svx/svdpage.hxx>
31 : #include <editeng/ulspitem.hxx>
32 : #include <fmtornt.hxx>
33 : #include <fmtfsize.hxx>
34 : #include "ndole.hxx"
35 : #include "tabfrm.hxx"
36 : #include "flyfrms.hxx"
37 : #include <fmtfollowtextflow.hxx>
38 : #include <environmentofanchoredobject.hxx>
39 : #include <sortedobjs.hxx>
40 : #include <viewimp.hxx>
41 : #include <IDocumentSettingAccess.hxx>
42 : #include <IDocumentDrawModelAccess.hxx>
43 :
44 : using namespace ::com::sun::star;
45 :
46 2336 : SwFlyFreeFrm::SwFlyFreeFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
47 : SwFlyFrm( pFmt, pSib, pAnch ),
48 : pPage( 0 ),
49 : // #i34753#
50 : mbNoMakePos( false ),
51 : // #i37068#
52 : mbNoMoveOnCheckClip( false ),
53 2336 : maUnclippedFrm( )
54 : {
55 2336 : }
56 :
57 4672 : SwFlyFreeFrm::~SwFlyFreeFrm()
58 : {
59 : // #i28701# - use new method <GetPageFrm()>
60 2336 : if( GetPageFrm() )
61 : {
62 246 : if( GetFmt()->GetDoc()->IsInDtor() )
63 : {
64 : // #i29879# - remove also to-frame anchored Writer
65 : // fly frame from page.
66 : const bool bRemoveFromPage =
67 0 : GetPageFrm()->GetSortedObjs() &&
68 0 : ( IsFlyAtCntFrm() ||
69 0 : ( GetAnchorFrm() && GetAnchorFrm()->IsFlyFrm() ) );
70 0 : if ( bRemoveFromPage )
71 : {
72 0 : GetPageFrm()->GetSortedObjs()->Remove( *this );
73 : }
74 : }
75 : else
76 : {
77 246 : SwRect aTmp( GetObjRectWithSpaces() );
78 246 : SwFlyFreeFrm::NotifyBackground( GetPageFrm(), aTmp, PREP_FLY_LEAVE );
79 : }
80 : }
81 2336 : }
82 :
83 : // #i28701#
84 898990 : TYPEINIT1(SwFlyFreeFrm,SwFlyFrm);
85 : /** Notifies the background (all CntntFrms that currently are overlapping).
86 : *
87 : * Additionally, the window is also directly invalidated (especially where
88 : * there are no overlapping CntntFrms).
89 : * This also takes CntntFrms within other Flys into account.
90 : */
91 6508 : void SwFlyFreeFrm::NotifyBackground( SwPageFrm *pPageFrm,
92 : const SwRect& rRect, PrepareHint eHint )
93 : {
94 6508 : ::Notify_Background( GetVirtDrawObj(), pPageFrm, rRect, eHint, true );
95 6508 : }
96 :
97 6666 : void SwFlyFreeFrm::MakeAll()
98 : {
99 6666 : if ( !GetFmt()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) )
100 : {
101 0 : return;
102 : }
103 :
104 6666 : if ( !GetAnchorFrm() || IsLocked() || IsColLocked() )
105 0 : return;
106 : // #i28701# - use new method <GetPageFrm()>
107 6666 : if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() )
108 : {
109 0 : SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm();
110 0 : SwPageFrm *pPageFrm = pFly ? pFly->FindPageFrm() : NULL;
111 0 : if( pPageFrm )
112 0 : pPageFrm->AppendFlyToPage( this );
113 : }
114 6666 : if( !GetPageFrm() )
115 0 : return;
116 :
117 6666 : Lock(); // The curtain drops
118 :
119 : // takes care of the notification in the dtor
120 6666 : const SwFlyNotify aNotify( this );
121 :
122 6666 : if ( IsClipped() )
123 : {
124 266 : mbValidSize = bHeightClipped = bWidthClipped = false;
125 : // no invalidation of position,
126 : // if anchored object is anchored inside a Writer fly frame,
127 : // its position is already locked, and it follows the text flow.
128 : // #i34753# - add condition:
129 : // no invalidation of position, if no direct move is requested in <CheckClip(..)>
130 406 : if ( !IsNoMoveOnCheckClip() &&
131 70 : !( PositionLocked() &&
132 0 : GetAnchorFrm()->IsInFly() &&
133 0 : GetFrmFmt().GetFollowTextFlow().GetValue() ) )
134 : {
135 70 : mbValidPos = false;
136 : }
137 : }
138 :
139 : // #i81146# new loop control
140 6666 : sal_uInt16 nLoopControlRuns = 0;
141 6666 : const sal_uInt16 nLoopControlMax = 10;
142 :
143 22710 : while ( !mbValidPos || !mbValidSize || !mbValidPrtArea || bFormatHeightOnly || !m_bValidContentPos )
144 : {
145 9378 : SWRECTFN( this )
146 : const SwFmtFrmSize *pSz;
147 : { // Additional scope, so aAccess will be destroyed before the check!
148 :
149 9378 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
150 9378 : const SwBorderAttrs &rAttrs = *aAccess.Get();
151 9378 : pSz = &rAttrs.GetAttrSet().GetFrmSize();
152 :
153 : // Only set when the flag is set!
154 9378 : if ( !mbValidSize )
155 : {
156 6914 : mbValidPrtArea = false;
157 : }
158 :
159 9378 : if ( !mbValidPrtArea )
160 : {
161 6914 : MakePrtArea( rAttrs );
162 6914 : m_bValidContentPos = false;
163 : }
164 :
165 9378 : if ( !mbValidSize || bFormatHeightOnly )
166 : {
167 6914 : mbValidSize = false;
168 6914 : Format( &rAttrs );
169 6914 : bFormatHeightOnly = false;
170 : }
171 :
172 9378 : if ( !mbValidPos )
173 : {
174 4542 : const Point aOldPos( (Frm().*fnRect->fnGetPos)() );
175 : // #i26791# - use new method <MakeObjPos()>
176 : // #i34753# - no positioning, if requested.
177 4542 : if ( IsNoMakePos() )
178 2 : mbValidPos = true;
179 : else
180 : // #i26791# - use new method <MakeObjPos()>
181 4540 : MakeObjPos();
182 4542 : if( aOldPos == (Frm().*fnRect->fnGetPos)() )
183 : {
184 1840 : if( !mbValidPos && GetAnchorFrm()->IsInSct() &&
185 0 : !GetAnchorFrm()->FindSctFrm()->IsValid() )
186 0 : mbValidPos = true;
187 : }
188 : else
189 2702 : mbValidSize = false;
190 : }
191 :
192 9378 : if ( !m_bValidContentPos )
193 7840 : MakeContentPos( rAttrs );
194 : }
195 :
196 9378 : if ( mbValidPos && mbValidSize )
197 : {
198 6676 : ++nLoopControlRuns;
199 :
200 : OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrm::MakeAll" );
201 :
202 13352 : if ( nLoopControlRuns < nLoopControlMax )
203 6676 : CheckClip( *pSz );
204 : }
205 : else
206 2702 : nLoopControlRuns = 0;
207 : }
208 6666 : Unlock();
209 :
210 : #if OSL_DEBUG_LEVEL > 0
211 : SWRECTFN( this )
212 : OSL_ENSURE( bHeightClipped || ( (Frm().*fnRect->fnGetHeight)() > 0 &&
213 : (Prt().*fnRect->fnGetHeight)() > 0),
214 : "SwFlyFreeFrm::Format(), flipping Fly." );
215 :
216 : #endif
217 : }
218 :
219 : /** determines, if direct environment of fly frame has 'auto' size
220 :
221 : #i17297#
222 : start with anchor frame and search via <GetUpper()> for a header, footer,
223 : row or fly frame stopping at page frame.
224 : return <true>, if such a frame is found and it has 'auto' size.
225 : otherwise <false> is returned.
226 :
227 : @return boolean indicating, that direct environment has 'auto' size
228 : */
229 2 : bool SwFlyFreeFrm::HasEnvironmentAutoSize() const
230 : {
231 2 : bool bRetVal = false;
232 :
233 2 : const SwFrm* pToBeCheckedFrm = GetAnchorFrm();
234 10 : while ( pToBeCheckedFrm &&
235 4 : !pToBeCheckedFrm->IsPageFrm() )
236 : {
237 10 : if ( pToBeCheckedFrm->IsHeaderFrm() ||
238 4 : pToBeCheckedFrm->IsFooterFrm() ||
239 8 : pToBeCheckedFrm->IsRowFrm() ||
240 2 : pToBeCheckedFrm->IsFlyFrm() )
241 : {
242 : bRetVal = ATT_FIX_SIZE !=
243 2 : pToBeCheckedFrm->GetAttrSet()->GetFrmSize().GetHeightSizeType();
244 2 : break;
245 : }
246 : else
247 : {
248 2 : pToBeCheckedFrm = pToBeCheckedFrm->GetUpper();
249 : }
250 : }
251 :
252 2 : return bRetVal;
253 : }
254 :
255 6676 : void SwFlyFreeFrm::CheckClip( const SwFmtFrmSize &rSz )
256 : {
257 : // It's probably time now to take appropriate measures, if the Fly
258 : // doesn't fit into its surrounding.
259 : // First, the Fly gives up its position, then it's formatted.
260 : // Only if it still doesn't fit after giving up its position, the
261 : // width or height are given up as well. The frame will be squeezed
262 : // as much as needed.
263 :
264 6676 : const SwVirtFlyDrawObj *pObj = GetVirtDrawObj();
265 6676 : SwRect aClip, aTmpStretch;
266 6676 : ::CalcClipRect( pObj, aClip, true );
267 6676 : ::CalcClipRect( pObj, aTmpStretch, false );
268 6676 : aClip._Intersection( aTmpStretch );
269 :
270 6676 : const long nBot = Frm().Top() + Frm().Height();
271 6676 : const long nRig = Frm().Left() + Frm().Width();
272 6676 : const long nClipBot = aClip.Top() + aClip.Height();
273 6676 : const long nClipRig = aClip.Left() + aClip.Width();
274 :
275 6676 : const bool bBot = nBot > nClipBot;
276 6676 : const bool bRig = nRig > nClipRig;
277 6676 : if ( bBot || bRig )
278 : {
279 300 : bool bAgain = false;
280 : // #i37068# - no move, if it's requested
281 622 : if ( bBot && !IsNoMoveOnCheckClip() &&
282 400 : !GetDrawObjs() && !GetAnchorFrm()->IsInTab() )
283 : {
284 50 : SwFrm* pHeader = FindFooterOrHeader();
285 : // In a header, correction of the position is no good idea.
286 : // If the fly moves, some paragraphs have to be formatted, this
287 : // could cause a change of the height of the headerframe,
288 : // now the flyframe can change its position and so on ...
289 50 : if ( !pHeader || !pHeader->IsHeaderFrm() )
290 : {
291 32 : const long nOld = Frm().Top();
292 32 : Frm().Pos().Y() = std::max( aClip.Top(), nClipBot - Frm().Height() );
293 32 : if ( Frm().Top() != nOld )
294 6 : bAgain = true;
295 32 : bHeightClipped = true;
296 : }
297 : }
298 300 : if ( bRig )
299 : {
300 50 : const long nOld = Frm().Left();
301 50 : Frm().Pos().X() = std::max( aClip.Left(), nClipRig - Frm().Width() );
302 50 : if ( Frm().Left() != nOld )
303 : {
304 4 : const SwFmtHoriOrient &rH = GetFmt()->GetHoriOrient();
305 : // Left-aligned ones may not be moved to the left when they
306 : // are avoiding another one.
307 4 : if( rH.GetHoriOrient() == text::HoriOrientation::LEFT )
308 0 : Frm().Pos().X() = nOld;
309 : else
310 4 : bAgain = true;
311 : }
312 50 : bWidthClipped = true;
313 : }
314 300 : if ( bAgain )
315 10 : mbValidSize = false;
316 : else
317 : {
318 : // If we reach this branch, the Frm protrudes into forbidden
319 : // areas, and correcting the position is not allowed or not
320 : // possible or not required.
321 :
322 : // For Flys with OLE objects as lower, we make sure that
323 : // we always resize proportionally
324 290 : Size aOldSize( Frm().SSize() );
325 :
326 : // First, setup the FrmRect, then transfer it to the Frm.
327 290 : SwRect aFrmRect( Frm() );
328 :
329 290 : if ( bBot )
330 : {
331 266 : long nDiff = nClipBot;
332 266 : nDiff -= aFrmRect.Top(); // nDiff represents the available distance
333 266 : nDiff = aFrmRect.Height() - nDiff;
334 266 : aFrmRect.Height( aFrmRect.Height() - nDiff );
335 266 : bHeightClipped = true;
336 : }
337 290 : if ( bRig )
338 : {
339 46 : long nDiff = nClipRig;
340 46 : nDiff -= aFrmRect.Left();// nDiff represents the available distance
341 46 : nDiff = aFrmRect.Width() - nDiff;
342 46 : aFrmRect.Width( aFrmRect.Width() - nDiff );
343 46 : bWidthClipped = true;
344 : }
345 :
346 : // #i17297# - no proportional
347 : // scaling of graphics in environments, which determines its size
348 : // by its content ('auto' size). Otherwise layout loops can occur and
349 : // layout sizes of the environment can be incorrect.
350 : // Such environment are:
351 : // (1) header and footer frames with 'auto' size
352 : // (2) table row frames with 'auto' size
353 : // (3) fly frames with 'auto' size
354 : // Note: section frames seems to be not critical - didn't found
355 : // any critical layout situation so far.
356 292 : if ( Lower() && Lower()->IsNoTxtFrm() &&
357 4 : ( static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() ||
358 2 : !HasEnvironmentAutoSize() ) )
359 : {
360 : // If width and height got adjusted, then the bigger
361 : // change is relevant.
362 0 : if ( aFrmRect.Width() != aOldSize.Width() &&
363 0 : aFrmRect.Height()!= aOldSize.Height() )
364 : {
365 0 : if ( (aOldSize.Width() - aFrmRect.Width()) >
366 0 : (aOldSize.Height()- aFrmRect.Height()) )
367 0 : aFrmRect.Height( aOldSize.Height() );
368 : else
369 0 : aFrmRect.Width( aOldSize.Width() );
370 : }
371 :
372 : // Adjusted the width? change height proportionally
373 0 : if( aFrmRect.Width() != aOldSize.Width() )
374 : {
375 0 : aFrmRect.Height( aFrmRect.Width() * aOldSize.Height() /
376 0 : aOldSize.Width() );
377 0 : bHeightClipped = true;
378 : }
379 : // Adjusted the height? change width proportionally
380 0 : else if( aFrmRect.Height() != aOldSize.Height() )
381 : {
382 0 : aFrmRect.Width( aFrmRect.Height() * aOldSize.Width() /
383 0 : aOldSize.Height() );
384 0 : bWidthClipped = true;
385 : }
386 :
387 : // #i17297# - reactivate change
388 : // of size attribute for fly frames containing an ole object.
389 :
390 : // Added the aFrmRect.HasArea() hack, because
391 : // the environment of the ole object does not have to be valid
392 : // at this moment, or even worse, it does not have to have a
393 : // resonable size. In this case we do not want to change to
394 : // attributes permanentely. Maybe one day somebody dares to remove
395 : // this code.
396 0 : if ( aFrmRect.HasArea() &&
397 0 : static_cast<SwCntntFrm*>(Lower())->GetNode()->GetOLENode() &&
398 0 : ( bWidthClipped || bHeightClipped ) )
399 : {
400 0 : SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt();
401 0 : pFmt->LockModify();
402 0 : SwFmtFrmSize aFrmSize( rSz );
403 0 : aFrmSize.SetWidth( aFrmRect.Width() );
404 0 : aFrmSize.SetHeight( aFrmRect.Height() );
405 0 : pFmt->SetFmtAttr( aFrmSize );
406 0 : pFmt->UnlockModify();
407 : }
408 : }
409 :
410 : // Now change the Frm; for columns, we put the new values into the attributes,
411 : // otherwise we'll end up with unwanted side-effects/oscillations
412 290 : const long nPrtHeightDiff = Frm().Height() - Prt().Height();
413 290 : const long nPrtWidthDiff = Frm().Width() - Prt().Width();
414 290 : maUnclippedFrm = SwRect( Frm() );
415 290 : Frm().Height( aFrmRect.Height() );
416 290 : Frm().Width ( std::max( long(MINLAY), aFrmRect.Width() ) );
417 290 : if ( Lower() && Lower()->IsColumnFrm() )
418 : {
419 0 : ColLock(); //lock grow/shrink
420 0 : const Size aTmpOldSize( Prt().SSize() );
421 0 : Prt().Height( Frm().Height() - nPrtHeightDiff );
422 0 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
423 0 : ChgLowersProp( aTmpOldSize );
424 0 : SwFrm *pLow = Lower();
425 0 : do
426 0 : { pLow->Calc();
427 : // also calculate the (Column)BodyFrm
428 0 : ((SwLayoutFrm*)pLow)->Lower()->Calc();
429 0 : pLow = pLow->GetNext();
430 : } while ( pLow );
431 0 : ::CalcCntnt( this );
432 0 : ColUnlock();
433 0 : if ( !mbValidSize && !bWidthClipped )
434 0 : bFormatHeightOnly = mbValidSize = true;
435 : }
436 : else
437 : {
438 290 : Prt().Height( Frm().Height() - nPrtHeightDiff );
439 290 : Prt().Width ( Frm().Width() - nPrtWidthDiff );
440 : }
441 : }
442 : }
443 :
444 : // #i26945#
445 : OSL_ENSURE( Frm().Height() >= 0,
446 : "<SwFlyFreeFrm::CheckClip(..)> - fly frame has negative height now." );
447 6676 : }
448 :
449 : /** method to determine, if a <MakeAll()> on the Writer fly frame is possible
450 : #i43771#
451 : */
452 15463 : bool SwFlyFreeFrm::IsFormatPossible() const
453 : {
454 46389 : return SwFlyFrm::IsFormatPossible() &&
455 15463 : ( GetPageFrm() ||
456 15463 : ( GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) );
457 : }
458 :
459 210 : SwFlyLayFrm::SwFlyLayFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) :
460 210 : SwFlyFreeFrm( pFmt, pSib, pAnch )
461 : {
462 210 : bLayout = true;
463 210 : }
464 :
465 : // #i28701#
466 21861 : TYPEINIT1(SwFlyLayFrm,SwFlyFreeFrm);
467 :
468 96 : void SwFlyLayFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
469 : {
470 96 : sal_uInt16 nWhich = pNew ? pNew->Which() : 0;
471 :
472 96 : SwFmtAnchor *pAnch = 0;
473 158 : if( RES_ATTRSET_CHG == nWhich && SfxItemState::SET ==
474 62 : ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, false,
475 62 : (const SfxPoolItem**)&pAnch ))
476 : ; // GetItemState sets the anchor pointer!
477 :
478 88 : else if( RES_ANCHOR == nWhich )
479 : {
480 : // Change of anchor. I'm attaching myself to the new place.
481 : // It's not allowed to change the anchor type. This is only
482 : // possible via SwFEShell.
483 0 : pAnch = (SwFmtAnchor*)pNew;
484 : }
485 :
486 96 : if( pAnch )
487 : {
488 : OSL_ENSURE( pAnch->GetAnchorId() ==
489 : GetFmt()->GetAnchor().GetAnchorId(),
490 : "8-) Invalid change of anchor type." );
491 :
492 : // Unregister, get hold of the page, attach to the corresponding LayoutFrm.
493 8 : SwRect aOld( GetObjRectWithSpaces() );
494 : // #i28701# - use new method <GetPageFrm()>
495 8 : SwPageFrm *pOldPage = GetPageFrm();
496 8 : AnchorFrm()->RemoveFly( this );
497 :
498 8 : if ( FLY_AT_PAGE == pAnch->GetAnchorId() )
499 : {
500 8 : sal_uInt16 nPgNum = pAnch->GetPageNum();
501 8 : SwRootFrm *pRoot = getRootFrm();
502 8 : SwPageFrm *pTmpPage = (SwPageFrm*)pRoot->Lower();
503 24 : for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i,
504 8 : pTmpPage = (SwPageFrm*)pTmpPage->GetNext() )
505 : {
506 8 : if ( i == nPgNum )
507 : {
508 : // #i50432# - adjust synopsis of <PlaceFly(..)>
509 8 : pTmpPage->PlaceFly( this, 0 );
510 : }
511 : }
512 8 : if( !pTmpPage )
513 : {
514 8 : pRoot->SetAssertFlyPages();
515 8 : pRoot->AssertFlyPages();
516 : }
517 : }
518 : else
519 : {
520 0 : SwNodeIndex aIdx( pAnch->GetCntntAnchor()->nNode );
521 0 : SwCntntFrm *pCntnt = GetFmt()->GetDoc()->GetNodes().GoNext( &aIdx )->
522 0 : GetCntntNode()->getLayoutFrm( getRootFrm(), 0, 0, false );
523 0 : if( pCntnt )
524 : {
525 0 : SwFlyFrm *pTmp = pCntnt->FindFlyFrm();
526 0 : if( pTmp )
527 0 : pTmp->AppendFly( this );
528 0 : }
529 : }
530 : // #i28701# - use new method <GetPageFrm()>
531 8 : if ( pOldPage && pOldPage != GetPageFrm() )
532 0 : NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE );
533 8 : SetCompletePaint();
534 8 : InvalidateAll();
535 8 : SetNotifyBack();
536 : }
537 : else
538 88 : SwFlyFrm::Modify( pOld, pNew );
539 96 : }
540 :
541 4014 : void SwPageFrm::AppendFlyToPage( SwFlyFrm *pNew )
542 : {
543 4014 : if ( !pNew->GetVirtDrawObj()->IsInserted() )
544 132 : getRootFrm()->GetDrawPage()->InsertObject(
545 132 : (SdrObject*)pNew->GetVirtDrawObj(),
546 264 : pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() );
547 :
548 4014 : InvalidateSpelling();
549 4014 : InvalidateSmartTags();
550 4014 : InvalidateAutoCompleteWords();
551 4014 : InvalidateWordCount();
552 :
553 4014 : if ( GetUpper() )
554 : {
555 4014 : ((SwRootFrm*)GetUpper())->SetIdleFlags();
556 4014 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
557 : }
558 :
559 4014 : SdrObject* pObj = pNew->GetVirtDrawObj();
560 : OSL_ENSURE( pNew->GetAnchorFrm(), "Fly without Anchor" );
561 4014 : SwFlyFrm* pFly = (SwFlyFrm*)pNew->GetAnchorFrm()->FindFlyFrm();
562 4014 : if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() )
563 : {
564 : //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
565 6 : sal_uInt32 nNewNum = pObj->GetOrdNumDirect();
566 6 : if ( pObj->GetPage() )
567 6 : pObj->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum );
568 : else
569 0 : pFly->GetVirtDrawObj()->SetOrdNum( nNewNum );
570 : }
571 :
572 : // Don't look further at Flys that sit inside the Cntnt.
573 4014 : if ( pNew->IsFlyInCntFrm() )
574 1546 : InvalidateFlyInCnt();
575 : else
576 : {
577 2468 : InvalidateFlyCntnt();
578 :
579 2468 : if ( !pSortedObjs )
580 810 : pSortedObjs = new SwSortedObjs();
581 :
582 2468 : const bool bSucessInserted = pSortedObjs->Insert( *pNew );
583 : OSL_ENSURE( bSucessInserted, "Fly not inserted in Sorted." );
584 : (void) bSucessInserted;
585 :
586 : // #i87493#
587 : OSL_ENSURE( pNew->GetPageFrm() == 0 || pNew->GetPageFrm() == this,
588 : "<SwPageFrm::AppendFlyToPage(..)> - anchored fly frame seems to be registered at another page frame. Serious defect -> please inform OD." );
589 : // #i28701# - use new method <SetPageFrm(..)>
590 2468 : pNew->SetPageFrm( this );
591 2468 : pNew->InvalidatePage( this );
592 : // #i28701#
593 2468 : pNew->UnlockPosition();
594 :
595 : // Notify accessible layout. That's required at this place for
596 : // frames only where the anchor is moved. Creation of new frames
597 : // is additionally handled by the SwFrmNotify class.
598 7404 : if( GetUpper() &&
599 2468 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
600 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
601 : {
602 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
603 0 : ->AddAccessibleFrm( pNew );
604 : }
605 : }
606 :
607 : // #i28701# - correction: consider also drawing objects
608 4014 : if ( pNew->GetDrawObjs() )
609 : {
610 2 : SwSortedObjs &rObjs = *pNew->GetDrawObjs();
611 18 : for ( size_t i = 0; i < rObjs.size(); ++i )
612 : {
613 16 : SwAnchoredObject* pTmpObj = rObjs[i];
614 16 : if ( pTmpObj->ISA(SwFlyFrm) )
615 : {
616 0 : SwFlyFrm* pTmpFly = static_cast<SwFlyFrm*>(pTmpObj);
617 : // #i28701# - use new method <GetPageFrm()>
618 0 : if ( pTmpFly->IsFlyFreeFrm() && !pTmpFly->GetPageFrm() )
619 0 : AppendFlyToPage( pTmpFly );
620 : }
621 16 : else if ( pTmpObj->ISA(SwAnchoredDrawObject) )
622 : {
623 : // #i87493#
624 16 : if ( pTmpObj->GetPageFrm() != this )
625 : {
626 16 : if ( pTmpObj->GetPageFrm() != 0 )
627 : {
628 0 : pTmpObj->GetPageFrm()->RemoveDrawObjFromPage( *pTmpObj );
629 : }
630 16 : AppendDrawObjToPage( *pTmpObj );
631 : }
632 : }
633 : }
634 : }
635 4014 : }
636 :
637 386 : void SwPageFrm::RemoveFlyFromPage( SwFlyFrm *pToRemove )
638 : {
639 386 : const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum();
640 386 : getRootFrm()->GetDrawPage()->RemoveObject( nOrdNum );
641 386 : pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum );
642 :
643 386 : if ( GetUpper() )
644 : {
645 386 : if ( !pToRemove->IsFlyInCntFrm() )
646 378 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
647 386 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
648 : }
649 :
650 : // Don't look further at Flys that sit inside the Cntnt.
651 386 : if ( pToRemove->IsFlyInCntFrm() )
652 394 : return;
653 :
654 : // Don't delete collections just yet. This will happen at the end of the
655 : // action in the RemoveSuperfluous of the page, kicked off by a method of
656 : // the same name in the root.
657 : // The FlyColl might be gone already, because the page's dtor is being
658 : // executed.
659 : // Remove it _before_ disposing accessible frames to avoid accesses to
660 : // the Frm from event handlers.
661 378 : if (pSortedObjs)
662 : {
663 378 : pSortedObjs->Remove(*pToRemove);
664 378 : if (!pSortedObjs->size())
665 : {
666 74 : delete pSortedObjs;
667 74 : pSortedObjs = 0;
668 : }
669 : }
670 :
671 : // Notify accessible layout. That's required at this place for
672 : // frames only where the anchor is moved. Creation of new frames
673 : // is additionally handled by the SwFrmNotify class.
674 1134 : if( GetUpper() &&
675 378 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
676 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
677 : {
678 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
679 0 : ->DisposeAccessibleFrm( pToRemove, true );
680 : }
681 :
682 : // #i28701# - use new method <SetPageFrm(..)>
683 378 : pToRemove->SetPageFrm( 0L );
684 : }
685 :
686 32 : void SwPageFrm::MoveFly( SwFlyFrm *pToMove, SwPageFrm *pDest )
687 : {
688 : // Invalidations
689 32 : if ( GetUpper() )
690 : {
691 32 : ((SwRootFrm*)GetUpper())->SetIdleFlags();
692 32 : if ( !pToMove->IsFlyInCntFrm() && pDest->GetPhyPageNum() < GetPhyPageNum() )
693 32 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
694 : }
695 :
696 32 : pDest->InvalidateSpelling();
697 32 : pDest->InvalidateSmartTags();
698 32 : pDest->InvalidateAutoCompleteWords();
699 32 : pDest->InvalidateWordCount();
700 :
701 32 : if ( pToMove->IsFlyInCntFrm() )
702 : {
703 0 : pDest->InvalidateFlyInCnt();
704 32 : return;
705 : }
706 :
707 : // Notify accessible layout. That's required at this place for
708 : // frames only where the anchor is moved. Creation of new frames
709 : // is additionally handled by the SwFrmNotify class.
710 96 : if( GetUpper() &&
711 32 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
712 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
713 : {
714 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
715 0 : ->DisposeAccessibleFrm( pToMove, true );
716 : }
717 :
718 : // The FlyColl might be gone already, because the page's dtor is being executed.
719 32 : if ( pSortedObjs )
720 : {
721 32 : pSortedObjs->Remove( *pToMove );
722 32 : if ( !pSortedObjs->size() )
723 2 : { DELETEZ( pSortedObjs );
724 : }
725 : }
726 :
727 : // Register
728 32 : if ( !pDest->GetSortedObjs() )
729 4 : pDest->pSortedObjs = new SwSortedObjs();
730 :
731 32 : const bool bSucessInserted = pDest->GetSortedObjs()->Insert( *pToMove );
732 : OSL_ENSURE( bSucessInserted, "Fly not inserted in Sorted." );
733 : (void) bSucessInserted;
734 :
735 : // #i28701# - use new method <SetPageFrm(..)>
736 32 : pToMove->SetPageFrm( pDest );
737 32 : pToMove->InvalidatePage( pDest );
738 32 : pToMove->SetNotifyBack();
739 32 : pDest->InvalidateFlyCntnt();
740 : // #i28701#
741 32 : pToMove->UnlockPosition();
742 :
743 : // Notify accessible layout. That's required at this place for
744 : // frames only where the anchor is moved. Creation of new frames
745 : // is additionally handled by the SwFrmNotify class.
746 96 : if( GetUpper() &&
747 32 : static_cast< SwRootFrm * >( GetUpper() )->IsAnyShellAccessible() &&
748 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell() )
749 : {
750 0 : static_cast< SwRootFrm * >( GetUpper() )->GetCurrShell()->Imp()
751 0 : ->AddAccessibleFrm( pToMove );
752 : }
753 :
754 : // #i28701# - correction: move lowers of Writer fly frame
755 32 : if ( pToMove->GetDrawObjs() )
756 : {
757 0 : SwSortedObjs &rObjs = *pToMove->GetDrawObjs();
758 0 : for ( size_t i = 0; i < rObjs.size(); ++i )
759 : {
760 0 : SwAnchoredObject* pObj = rObjs[i];
761 0 : if ( pObj->ISA(SwFlyFrm) )
762 : {
763 0 : SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
764 0 : if ( pFly->IsFlyFreeFrm() )
765 : {
766 : // #i28701# - use new method <GetPageFrm()>
767 0 : SwPageFrm* pPageFrm = pFly->GetPageFrm();
768 0 : if ( pPageFrm )
769 0 : pPageFrm->MoveFly( pFly, pDest );
770 : else
771 0 : pDest->AppendFlyToPage( pFly );
772 : }
773 : }
774 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
775 : {
776 0 : RemoveDrawObjFromPage( *pObj );
777 0 : pDest->AppendDrawObjToPage( *pObj );
778 : }
779 : }
780 : }
781 : }
782 :
783 4194 : void SwPageFrm::AppendDrawObjToPage( SwAnchoredObject& _rNewObj )
784 : {
785 4194 : if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
786 : {
787 : OSL_FAIL( "SwPageFrm::AppendDrawObjToPage(..) - anchored object of unexpected type -> object not appended" );
788 0 : return;
789 : }
790 :
791 4194 : if ( GetUpper() )
792 : {
793 4194 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
794 : }
795 :
796 : OSL_ENSURE( _rNewObj.GetAnchorFrm(), "anchored draw object without anchor" );
797 4194 : SwFlyFrm* pFlyFrm = (SwFlyFrm*)_rNewObj.GetAnchorFrm()->FindFlyFrm();
798 4274 : if ( pFlyFrm &&
799 80 : _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrm->GetVirtDrawObj()->GetOrdNum() )
800 : {
801 : //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
802 20 : sal_uInt32 nNewNum = _rNewObj.GetDrawObj()->GetOrdNumDirect();
803 20 : if ( _rNewObj.GetDrawObj()->GetPage() )
804 20 : _rNewObj.DrawObj()->GetPage()->SetObjectOrdNum( pFlyFrm->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum );
805 : else
806 0 : pFlyFrm->GetVirtDrawObj()->SetOrdNum( nNewNum );
807 : }
808 :
809 4194 : if ( FLY_AS_CHAR == _rNewObj.GetFrmFmt().GetAnchor().GetAnchorId() )
810 : {
811 994 : return;
812 : }
813 :
814 3200 : if ( !pSortedObjs )
815 : {
816 948 : pSortedObjs = new SwSortedObjs();
817 : }
818 3200 : if ( !pSortedObjs->Insert( _rNewObj ) )
819 : {
820 : OSL_ENSURE( pSortedObjs->Contains( _rNewObj ),
821 : "Drawing object not appended into list <pSortedObjs>." );
822 : }
823 : // #i87493#
824 : OSL_ENSURE( _rNewObj.GetPageFrm() == 0 || _rNewObj.GetPageFrm() == this,
825 : "<SwPageFrm::AppendDrawObjToPage(..)> - anchored draw object seems to be registered at another page frame. Serious defect -> please inform OD." );
826 3200 : _rNewObj.SetPageFrm( this );
827 :
828 : // invalidate page in order to force a reformat of object layout of the page.
829 3200 : InvalidateFlyLayout();
830 : }
831 :
832 774 : void SwPageFrm::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj )
833 : {
834 774 : if ( !_rToRemoveObj.ISA(SwAnchoredDrawObject) )
835 : {
836 : OSL_FAIL( "SwPageFrm::RemoveDrawObjFromPage(..) - anchored object of unexpected type -> object not removed" );
837 774 : return;
838 : }
839 :
840 774 : if ( pSortedObjs )
841 : {
842 774 : pSortedObjs->Remove( _rToRemoveObj );
843 774 : if ( !pSortedObjs->size() )
844 : {
845 80 : DELETEZ( pSortedObjs );
846 : }
847 774 : if ( GetUpper() )
848 : {
849 774 : if (FLY_AS_CHAR !=
850 774 : _rToRemoveObj.GetFrmFmt().GetAnchor().GetAnchorId())
851 : {
852 774 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
853 774 : InvalidatePage();
854 : }
855 774 : ((SwRootFrm*)GetUpper())->InvalidateBrowseWidth();
856 : }
857 : }
858 774 : _rToRemoveObj.SetPageFrm( 0 );
859 : }
860 :
861 : // #i50432# - adjust method description and synopsis.
862 70 : void SwPageFrm::PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt )
863 : {
864 : // #i50432# - consider the case that page is an empty page:
865 : // In this case append the fly frame at the next page
866 : OSL_ENSURE( !IsEmptyPage() || GetNext(),
867 : "<SwPageFrm::PlaceFly(..)> - empty page with no next page! -> fly frame appended at empty page" );
868 70 : if ( IsEmptyPage() && GetNext() )
869 : {
870 0 : static_cast<SwPageFrm*>(GetNext())->PlaceFly( pFly, pFmt );
871 : }
872 : else
873 : {
874 : // If we received a Fly, we use that one. Otherwise, create a new
875 : // one using the Format.
876 70 : if ( pFly )
877 8 : AppendFly( pFly );
878 : else
879 : { OSL_ENSURE( pFmt, ":-( No Format given for Fly." );
880 62 : pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, this, this );
881 62 : AppendFly( pFly );
882 62 : ::RegistFlys( this, pFly );
883 : }
884 : }
885 70 : }
886 :
887 : // #i18732# - adjustments for following text flow or not
888 : // AND alignment at 'page areas' for to paragraph/to character anchored objects
889 : // #i22305# - adjustment for following text flow for to frame anchored objects
890 : // #i29778# - Because calculating the floating screen object's position
891 : // (Writer fly frame or drawing object) doesn't perform a calculation on its
892 : // upper frames and its anchor frame, a calculation of the upper frames in this
893 : // method is no longer sensible.
894 : // #i28701# - if document compatibility option 'Consider wrapping style influence
895 : // on object positioning' is ON, the clip area corresponds to the one as the
896 : // object doesn't follow the text flow.
897 13358 : bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, bool bMove )
898 : {
899 13358 : bool bRet = true;
900 13358 : if ( pSdrObj->ISA(SwVirtFlyDrawObj) )
901 : {
902 13358 : const SwFlyFrm* pFly = ((const SwVirtFlyDrawObj*)pSdrObj)->GetFlyFrm();
903 13358 : const bool bFollowTextFlow = pFly->GetFmt()->GetFollowTextFlow().GetValue();
904 : // #i28701#
905 : const bool bConsiderWrapOnObjPos =
906 13358 : pFly->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
907 13358 : const SwFmtVertOrient &rV = pFly->GetFmt()->GetVertOrient();
908 13358 : if( pFly->IsFlyLayFrm() )
909 : {
910 : const SwFrm* pClip;
911 : // #i22305#
912 : // #i28701#
913 612 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
914 : {
915 600 : pClip = pFly->GetAnchorFrm()->FindPageFrm();
916 : }
917 : else
918 : {
919 12 : pClip = pFly->GetAnchorFrm();
920 : }
921 :
922 612 : rRect = pClip->Frm();
923 612 : SWRECTFN( pClip )
924 :
925 : // vertical clipping: Top and Bottom, also to PrtArea if necessary
926 1016 : if( rV.GetVertOrient() != text::VertOrientation::NONE &&
927 404 : rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
928 : {
929 380 : (rRect.*fnRect->fnSetTop)( (pClip->*fnRect->fnGetPrtTop)() );
930 380 : (rRect.*fnRect->fnSetBottom)( (pClip->*fnRect->fnGetPrtBottom)() );
931 : }
932 : // horizontal clipping: Top and Bottom, also to PrtArea if necessary
933 612 : const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
934 1000 : if( rH.GetHoriOrient() != text::HoriOrientation::NONE &&
935 388 : rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
936 : {
937 380 : (rRect.*fnRect->fnSetLeft)( (pClip->*fnRect->fnGetPrtLeft)() );
938 380 : (rRect.*fnRect->fnSetRight)((pClip->*fnRect->fnGetPrtRight)());
939 : }
940 : }
941 12746 : else if( pFly->IsFlyAtCntFrm() )
942 : {
943 : // #i18732# - consider following text flow or not
944 : // AND alignment at 'page areas'
945 12746 : const SwFrm* pVertPosOrientFrm = pFly->GetVertPosOrientFrm();
946 12746 : if ( !pVertPosOrientFrm )
947 : {
948 : OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing .");
949 0 : pVertPosOrientFrm = pFly->GetAnchorFrm();
950 : }
951 :
952 12746 : if ( !bFollowTextFlow || bConsiderWrapOnObjPos )
953 : {
954 12746 : const SwLayoutFrm* pClipFrm = pVertPosOrientFrm->FindPageFrm();
955 12746 : if (!pClipFrm)
956 : {
957 : OSL_FAIL("!pClipFrm: "
958 : "if you can reproduce this please file a bug");
959 0 : return false;
960 : }
961 19122 : rRect = bMove ? pClipFrm->GetUpper()->Frm()
962 19122 : : pClipFrm->Frm();
963 : // #i26945# - consider that a table, during
964 : // its format, can exceed its upper printing area bottom.
965 : // Thus, enlarge the clip rectangle, if such a case occurred
966 12746 : if ( pFly->GetAnchorFrm()->IsInTab() )
967 : {
968 : const SwTabFrm* pTabFrm = const_cast<SwFlyFrm*>(pFly)
969 132 : ->GetAnchorFrmContainingAnchPos()->FindTabFrm();
970 132 : SwRect aTmp( pTabFrm->Prt() );
971 132 : aTmp += pTabFrm->Frm().Pos();
972 132 : rRect.Union( aTmp );
973 : // #i43913# - consider also the cell frame
974 : const SwFrm* pCellFrm = const_cast<SwFlyFrm*>(pFly)
975 132 : ->GetAnchorFrmContainingAnchPos()->GetUpper();
976 264 : while ( pCellFrm && !pCellFrm->IsCellFrm() )
977 : {
978 0 : pCellFrm = pCellFrm->GetUpper();
979 : }
980 132 : if ( pCellFrm )
981 : {
982 132 : aTmp = pCellFrm->Prt();
983 132 : aTmp += pCellFrm->Frm().Pos();
984 132 : rRect.Union( aTmp );
985 : }
986 12746 : }
987 : }
988 0 : else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ||
989 0 : rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
990 : {
991 : // new class <SwEnvironmentOfAnchoredObject>
992 : objectpositioning::SwEnvironmentOfAnchoredObject
993 0 : aEnvOfObj( bFollowTextFlow );
994 : const SwLayoutFrm& rVertClipFrm =
995 0 : aEnvOfObj.GetVertEnvironmentLayoutFrm( *pVertPosOrientFrm );
996 0 : if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME )
997 : {
998 0 : rRect = rVertClipFrm.Frm();
999 : }
1000 0 : else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )
1001 : {
1002 0 : if ( rVertClipFrm.IsPageFrm() )
1003 : {
1004 0 : rRect = static_cast<const SwPageFrm&>(rVertClipFrm).PrtWithoutHeaderAndFooter();
1005 : }
1006 : else
1007 : {
1008 0 : rRect = rVertClipFrm.Frm();
1009 : }
1010 : }
1011 : const SwLayoutFrm* pHoriClipFrm =
1012 0 : pFly->GetAnchorFrm()->FindPageFrm()->GetUpper();
1013 0 : SWRECTFN( pFly->GetAnchorFrm() )
1014 0 : (rRect.*fnRect->fnSetLeft)( (pHoriClipFrm->Frm().*fnRect->fnGetLeft)() );
1015 0 : (rRect.*fnRect->fnSetRight)((pHoriClipFrm->Frm().*fnRect->fnGetRight)());
1016 : }
1017 : else
1018 : {
1019 : // #i26945#
1020 : const SwFrm *pClip =
1021 0 : const_cast<SwFlyFrm*>(pFly)->GetAnchorFrmContainingAnchPos();
1022 0 : SWRECTFN( pClip )
1023 0 : const SwLayoutFrm *pUp = pClip->GetUpper();
1024 0 : const SwFrm *pCell = pUp->IsCellFrm() ? pUp : 0;
1025 : sal_uInt16 nType = bMove ? FRM_ROOT | FRM_FLY | FRM_HEADER |
1026 : FRM_FOOTER | FRM_FTN
1027 : : FRM_BODY | FRM_FLY | FRM_HEADER |
1028 0 : FRM_FOOTER | FRM_CELL| FRM_FTN;
1029 :
1030 0 : while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrm() )
1031 : {
1032 0 : pUp = pUp->GetUpper();
1033 0 : if ( !pCell && pUp->IsCellFrm() )
1034 0 : pCell = pUp;
1035 : }
1036 0 : if ( bMove )
1037 : {
1038 0 : if ( pUp->IsRootFrm() )
1039 : {
1040 0 : rRect = pUp->Prt();
1041 0 : rRect += pUp->Frm().Pos();
1042 0 : pUp = 0;
1043 : }
1044 : }
1045 0 : if ( pUp )
1046 : {
1047 0 : if ( pUp->GetType() & FRM_BODY )
1048 : {
1049 : const SwPageFrm *pPg;
1050 0 : if ( pUp->GetUpper() != (pPg = pFly->FindPageFrm()) )
1051 0 : pUp = pPg->FindBodyCont();
1052 0 : if (pUp)
1053 : {
1054 0 : rRect = pUp->GetUpper()->Frm();
1055 0 : (rRect.*fnRect->fnSetTop)( (pUp->*fnRect->fnGetPrtTop)() );
1056 0 : (rRect.*fnRect->fnSetBottom)((pUp->*fnRect->fnGetPrtBottom)());
1057 : }
1058 : }
1059 : else
1060 : {
1061 0 : if( ( pUp->GetType() & (FRM_FLY | FRM_FTN ) ) &&
1062 0 : !pUp->Frm().IsInside( pFly->Frm().Pos() ) )
1063 : {
1064 0 : if( pUp->IsFlyFrm() )
1065 : {
1066 0 : SwFlyFrm *pTmpFly = (SwFlyFrm*)pUp;
1067 0 : while( pTmpFly->GetNextLink() )
1068 : {
1069 0 : pTmpFly = pTmpFly->GetNextLink();
1070 0 : if( pTmpFly->Frm().IsInside( pFly->Frm().Pos() ) )
1071 0 : break;
1072 : }
1073 0 : pUp = pTmpFly;
1074 : }
1075 0 : else if( pUp->IsInFtn() )
1076 : {
1077 0 : const SwFtnFrm *pTmp = pUp->FindFtnFrm();
1078 0 : while( pTmp->GetFollow() )
1079 : {
1080 0 : pTmp = pTmp->GetFollow();
1081 0 : if( pTmp->Frm().IsInside( pFly->Frm().Pos() ) )
1082 0 : break;
1083 : }
1084 0 : pUp = pTmp;
1085 : }
1086 : }
1087 0 : rRect = pUp->Prt();
1088 0 : rRect.Pos() += pUp->Frm().Pos();
1089 0 : if ( pUp->GetType() & (FRM_HEADER | FRM_FOOTER) )
1090 : {
1091 0 : rRect.Left ( pUp->GetUpper()->Frm().Left() );
1092 0 : rRect.Width( pUp->GetUpper()->Frm().Width());
1093 : }
1094 0 : else if ( pUp->IsCellFrm() ) //MA_FLY_HEIGHT
1095 : {
1096 0 : const SwFrm *pTab = pUp->FindTabFrm();
1097 : (rRect.*fnRect->fnSetBottom)(
1098 0 : (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1099 : // expand to left and right cell border
1100 0 : rRect.Left ( pUp->Frm().Left() );
1101 0 : rRect.Width( pUp->Frm().Width() );
1102 : }
1103 : }
1104 : }
1105 0 : if ( pCell )
1106 : {
1107 : // CellFrms might also sit in unallowed areas. In this case,
1108 : // the Fly is allowed to do so as well
1109 0 : SwRect aTmp( pCell->Prt() );
1110 0 : aTmp += pCell->Frm().Pos();
1111 0 : rRect.Union( aTmp );
1112 : }
1113 : }
1114 : }
1115 : else
1116 : {
1117 0 : const SwFrm *pUp = pFly->GetAnchorFrm()->GetUpper();
1118 0 : SWRECTFN( pFly->GetAnchorFrm() )
1119 0 : while( pUp->IsColumnFrm() || pUp->IsSctFrm() || pUp->IsColBodyFrm())
1120 0 : pUp = pUp->GetUpper();
1121 0 : rRect = pUp->Frm();
1122 0 : if( !pUp->IsBodyFrm() )
1123 : {
1124 0 : rRect += pUp->Prt().Pos();
1125 0 : rRect.SSize( pUp->Prt().SSize() );
1126 0 : if ( pUp->IsCellFrm() )
1127 : {
1128 0 : const SwFrm *pTab = pUp->FindTabFrm();
1129 : (rRect.*fnRect->fnSetBottom)(
1130 0 : (pTab->GetUpper()->*fnRect->fnGetPrtBottom)() );
1131 : }
1132 : }
1133 0 : else if ( pUp->GetUpper()->IsPageFrm() )
1134 : {
1135 : // Objects anchored as character may exceed right margin
1136 : // of body frame:
1137 0 : (rRect.*fnRect->fnSetRight)( (pUp->GetUpper()->Frm().*fnRect->fnGetRight)() );
1138 : }
1139 0 : long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1140 : long nTop;
1141 0 : const SwFmt *pFmt = ((SwContact*)GetUserCall(pSdrObj))->GetFmt();
1142 0 : const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1143 0 : if( bMove )
1144 : {
1145 0 : nTop = bVert ? ((SwFlyInCntFrm*)pFly)->GetRefPoint().X() :
1146 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y();
1147 0 : nTop = (*fnRect->fnYInc)( nTop, -nHeight );
1148 0 : long nWidth = (pFly->Frm().*fnRect->fnGetWidth)();
1149 : (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1150 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().Y() :
1151 0 : ((SwFlyInCntFrm*)pFly)->GetRefPoint().X(), nWidth );
1152 0 : nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper();
1153 : }
1154 : else
1155 : {
1156 0 : nTop = (*fnRect->fnYInc)( (pFly->Frm().*fnRect->fnGetBottom)(),
1157 0 : rUL.GetLower() - nHeight );
1158 0 : nHeight = 2*nHeight - (pFly->Frm().*fnRect->fnGetHeight)()
1159 0 : - rUL.GetLower() - rUL.GetUpper();
1160 : }
1161 0 : (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1162 : }
1163 : }
1164 : else
1165 : {
1166 0 : const SwDrawContact *pC = (const SwDrawContact*)GetUserCall(pSdrObj);
1167 0 : const SwFrmFmt *pFmt = (const SwFrmFmt*)pC->GetFmt();
1168 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1169 0 : if ( FLY_AS_CHAR == rAnch.GetAnchorId() )
1170 : {
1171 0 : const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1172 0 : if( !pAnchorFrm )
1173 : {
1174 : OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." );
1175 0 : ((SwDrawContact*)pC)->ConnectToLayout();
1176 0 : pAnchorFrm = pC->GetAnchorFrm();
1177 : }
1178 0 : const SwFrm* pUp = pAnchorFrm->GetUpper();
1179 0 : rRect = pUp->Prt();
1180 0 : rRect += pUp->Frm().Pos();
1181 0 : SWRECTFN( pAnchorFrm )
1182 0 : long nHeight = (9*(rRect.*fnRect->fnGetHeight)())/10;
1183 : long nTop;
1184 0 : const SvxULSpaceItem &rUL = pFmt->GetULSpace();
1185 0 : SwRect aSnapRect( pSdrObj->GetSnapRect() );
1186 0 : long nTmpH = 0;
1187 0 : if( bMove )
1188 : {
1189 0 : nTop = (*fnRect->fnYInc)( bVert ? pSdrObj->GetAnchorPos().X() :
1190 0 : pSdrObj->GetAnchorPos().Y(), -nHeight );
1191 0 : long nWidth = (aSnapRect.*fnRect->fnGetWidth)();
1192 : (rRect.*fnRect->fnSetLeftAndWidth)( bVert ?
1193 0 : pSdrObj->GetAnchorPos().Y() :
1194 0 : pSdrObj->GetAnchorPos().X(), nWidth );
1195 : }
1196 : else
1197 : {
1198 : // #i26791# - value of <nTmpH> is needed to
1199 : // calculate value of <nTop>.
1200 0 : nTmpH = bVert ? pSdrObj->GetCurrentBoundRect().GetWidth() :
1201 0 : pSdrObj->GetCurrentBoundRect().GetHeight();
1202 0 : nTop = (*fnRect->fnYInc)( (aSnapRect.*fnRect->fnGetTop)(),
1203 0 : rUL.GetLower() + nTmpH - nHeight );
1204 : }
1205 0 : nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper();
1206 0 : (rRect.*fnRect->fnSetTopAndHeight)( nTop, nHeight );
1207 : }
1208 : else
1209 : {
1210 : // restrict clip rectangle for drawing
1211 : // objects in header/footer to the page frame.
1212 : // #i26791#
1213 0 : const SwFrm* pAnchorFrm = pC->GetAnchorFrm( pSdrObj );
1214 0 : if ( pAnchorFrm && pAnchorFrm->FindFooterOrHeader() )
1215 : {
1216 : // clip frame is the page frame the header/footer is on.
1217 0 : const SwFrm* pClipFrm = pAnchorFrm->FindPageFrm();
1218 0 : rRect = pClipFrm->Frm();
1219 : }
1220 : else
1221 : {
1222 0 : bRet = false;
1223 : }
1224 : }
1225 : }
1226 13358 : return bRet;
1227 270 : }
1228 :
1229 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|