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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <objectformattertxtfrm.hxx>
27 #include <anchoredobject.hxx>
28 #include <sortedobjs.hxx>
29 #include <flyfrms.hxx>
30 #include <txtfrm.hxx>
31 #include <pagefrm.hxx>
32 #include <rowfrm.hxx>
33 #include <layouter.hxx>
34 #include <frmfmt.hxx>
35 #include <fmtanchr.hxx>
36 #include <fmtwrapinfluenceonobjpos.hxx>
37 // --> OD 2004-11-03 #114798#
38 #include <fmtfollowtextflow.hxx>
39 // <--
40 #include <layact.hxx>
41 
42 using namespace ::com::sun::star;
43 
44 // =============================================================================
45 
46 // --> OD 2004-12-03 #115759# - little helper class to forbid follow formatting
47 // for the given text frame
48 class SwForbidFollowFormat
49 {
50 private:
51     SwTxtFrm& mrTxtFrm;
52     const bool bOldFollowFormatAllowed;
53 
54 public:
SwForbidFollowFormat(SwTxtFrm & _rTxtFrm)55     SwForbidFollowFormat( SwTxtFrm& _rTxtFrm )
56         : mrTxtFrm( _rTxtFrm ),
57           bOldFollowFormatAllowed( _rTxtFrm.FollowFormatAllowed() )
58     {
59         mrTxtFrm.ForbidFollowFormat();
60     }
61 
~SwForbidFollowFormat()62     ~SwForbidFollowFormat()
63     {
64         if ( bOldFollowFormatAllowed )
65         {
66             mrTxtFrm.AllowFollowFormat();
67         }
68     }
69 };
70 // <--
71 
72 // =============================================================================
73 // implementation of class <SwObjectFormatterTxtFrm>
74 // =============================================================================
SwObjectFormatterTxtFrm(SwTxtFrm & _rAnchorTxtFrm,const SwPageFrm & _rPageFrm,SwTxtFrm * _pMasterAnchorTxtFrm,SwLayAction * _pLayAction)75 SwObjectFormatterTxtFrm::SwObjectFormatterTxtFrm( SwTxtFrm& _rAnchorTxtFrm,
76                                                   const SwPageFrm& _rPageFrm,
77                                                   SwTxtFrm* _pMasterAnchorTxtFrm,
78                                                   SwLayAction* _pLayAction )
79     : SwObjectFormatter( _rPageFrm, _pLayAction, true ),
80       mrAnchorTxtFrm( _rAnchorTxtFrm ),
81       mpMasterAnchorTxtFrm( _pMasterAnchorTxtFrm )
82 {
83 }
84 
~SwObjectFormatterTxtFrm()85 SwObjectFormatterTxtFrm::~SwObjectFormatterTxtFrm()
86 {
87 }
88 
CreateObjFormatter(SwTxtFrm & _rAnchorTxtFrm,const SwPageFrm & _rPageFrm,SwLayAction * _pLayAction)89 SwObjectFormatterTxtFrm* SwObjectFormatterTxtFrm::CreateObjFormatter(
90                                                 SwTxtFrm& _rAnchorTxtFrm,
91                                                 const SwPageFrm& _rPageFrm,
92                                                 SwLayAction* _pLayAction )
93 {
94     SwObjectFormatterTxtFrm* pObjFormatter = 0L;
95 
96     // determine 'master' of <_rAnchorTxtFrm>, if anchor frame is a follow text frame.
97     SwTxtFrm* pMasterOfAnchorFrm = 0L;
98     if ( _rAnchorTxtFrm.IsFollow() )
99     {
100         pMasterOfAnchorFrm = _rAnchorTxtFrm.FindMaster();
101         while ( pMasterOfAnchorFrm->IsFollow() )
102         {
103             pMasterOfAnchorFrm = pMasterOfAnchorFrm->FindMaster();
104         }
105     }
106 
107     // create object formatter, if floating screen objects are registered
108     // at anchor frame (or at 'master' anchor frame)
109     if ( _rAnchorTxtFrm.GetDrawObjs() ||
110          ( pMasterOfAnchorFrm && pMasterOfAnchorFrm->GetDrawObjs() ) )
111     {
112         pObjFormatter =
113             new SwObjectFormatterTxtFrm( _rAnchorTxtFrm, _rPageFrm,
114                                          pMasterOfAnchorFrm, _pLayAction );
115     }
116 
117     return pObjFormatter;
118 }
119 
GetAnchorFrm()120 SwFrm& SwObjectFormatterTxtFrm::GetAnchorFrm()
121 {
122     return mrAnchorTxtFrm;
123 }
124 
125 // --> OD 2005-01-10 #i40147# - add parameter <_bCheckForMovedFwd>.
DoFormatObj(SwAnchoredObject & _rAnchoredObj,const bool _bCheckForMovedFwd)126 bool SwObjectFormatterTxtFrm::DoFormatObj( SwAnchoredObject& _rAnchoredObj,
127                                            const bool _bCheckForMovedFwd )
128 {
129     // check, if only as-character anchored object have to be formatted, and
130     // check the anchor type
131     if ( FormatOnlyAsCharAnchored() &&
132          !(_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
133     {
134         return true;
135     }
136 
137     // --> OD 2005-07-13 #124218# - consider, if the layout action has to be
138     // restarted due to a delete of a page frame.
139     if ( GetLayAction() && GetLayAction()->IsAgain() )
140     {
141         return false;
142     }
143     // <--
144 
145     bool bSuccess( true );
146 
147     if ( _rAnchoredObj.IsFormatPossible() )
148     {
149         _rAnchoredObj.SetRestartLayoutProcess( false );
150 
151         _FormatObj( _rAnchoredObj );
152         // --> OD 2005-07-13 #124218# - consider, if the layout action has to be
153         // restarted due to a delete of a page frame.
154         if ( GetLayAction() && GetLayAction()->IsAgain() )
155         {
156             return false;
157         }
158         // <--
159 
160         // check, if layout process has to be restarted.
161         // if yes, perform needed invalidations.
162         // --> OD 2004-11-03 #114798# - no restart of layout process,
163         // if anchored object is anchored inside a Writer fly frame,
164         // its position is already locked, and it follows the text flow.
165         const bool bRestart =
166                 _rAnchoredObj.RestartLayoutProcess() &&
167                 !( _rAnchoredObj.PositionLocked() &&
168                    _rAnchoredObj.GetAnchorFrm()->IsInFly() &&
169                    _rAnchoredObj.GetFrmFmt().GetFollowTextFlow().GetValue() );
170         if ( bRestart )
171         // <--
172         {
173             bSuccess = false;
174             _InvalidatePrevObjs( _rAnchoredObj );
175             _InvalidateFollowObjs( _rAnchoredObj, true );
176         }
177 
178         // format anchor text frame, if wrapping style influence of the object
179         // has to be considered and it's <NONE_SUCCESSIVE_POSITIONED>
180         // --> OD 2004-08-25 #i3317# - consider also anchored objects, whose
181         // wrapping style influence is temporarly considered.
182         // --> OD 2005-01-10 #i40147# - consider also anchored objects, for
183         // whose the check of a moved forward anchor frame is requested.
184         // --> OD 2006-07-24 #b6449874# - revise decision made for i3317:
185         // anchored objects, whose wrapping style influence is temporarly considered,
186         // have to be considered in method <SwObjectFormatterTxtFrm::DoFormatObjs()>
187         if ( bSuccess &&
188              _rAnchoredObj.ConsiderObjWrapInfluenceOnObjPos() &&
189              ( _bCheckForMovedFwd ||
190                _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
191                     // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
192                     GetWrapInfluenceOnObjPos( true ) ==
193                         // --> OD 2004-10-18 #i35017# - constant name has changed
194                         text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) )
195         // <--
196         {
197             // --> OD 2004-10-11 #i26945# - check conditions for move forward of
198             // anchor text frame
199             // determine, if anchor text frame has previous frame
200             const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
201 
202             // --> OD 2005-01-11 #i40141# - use new method - it also formats the
203             // section the anchor frame is in.
204             _FormatAnchorFrmForCheckMoveFwd();
205             // <--
206 
207             // --> OD 2004-10-22 #i35911#
208             if ( _rAnchoredObj.HasClearedEnvironment() )
209             {
210                 _rAnchoredObj.SetClearedEnvironment( true );
211                 // --> OD 2005-03-08 #i44049# - consider, that anchor frame
212                 // could already been marked to move forward.
213                 SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
214                 if ( pAnchorPageFrm != _rAnchoredObj.GetPageFrm() )
215                 {
216                     bool bInsert( true );
217                     sal_uInt32 nToPageNum( 0L );
218                     const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
219                     if ( SwLayouter::FrmMovedFwdByObjPos(
220                                             rDoc, mrAnchorTxtFrm, nToPageNum ) )
221                     {
222                         if ( nToPageNum < pAnchorPageFrm->GetPhyPageNum() )
223                             SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
224                         else
225                             bInsert = false;
226                     }
227                     if ( bInsert )
228                     {
229                         SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
230                                                        pAnchorPageFrm->GetPhyPageNum() );
231                         mrAnchorTxtFrm.InvalidatePos();
232                         bSuccess = false;
233                         _InvalidatePrevObjs( _rAnchoredObj );
234                         _InvalidateFollowObjs( _rAnchoredObj, true );
235                     }
236                     else
237                     {
238                         ASSERT( false,
239                                 "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
240                     }
241                 }
242                 // <--
243             }
244             else if ( !mrAnchorTxtFrm.IsFollow() && bDoesAnchorHadPrev )
245             // <--
246             {
247                 // index of anchored object in collection of page numbers and
248                 // anchor types
249                 sal_uInt32 nIdx( CountOfCollected() );
250                 ASSERT( nIdx > 0,
251                         "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchored object not collected!?" );
252                 --nIdx;
253 
254                 sal_uInt32 nToPageNum( 0L );
255                 // --> OD 2005-03-30 #i43913#
256                 bool bDummy( false );
257                 // --> OD 2006-01-27 #i58182# - consider new method signature
258                 if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( nIdx ),
259                                               GetPgNumOfCollected( nIdx ),
260                                               IsCollectedAnchoredAtMaster( nIdx ),
261                                               nToPageNum, bDummy ) )
262                 // <--
263                 {
264                     // --> OD 2005-06-01 #i49987# - consider, that anchor frame
265                     // could already been marked to move forward.
266                     bool bInsert( true );
267                     sal_uInt32 nMovedFwdToPageNum( 0L );
268                     const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
269                     if ( SwLayouter::FrmMovedFwdByObjPos(
270                                             rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
271                     {
272                         if ( nMovedFwdToPageNum < nToPageNum )
273                             SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
274                         else
275                             bInsert = false;
276                     }
277                     if ( bInsert )
278                     {
279                         // Indicate that anchor text frame has to move forward and
280                         // invalidate its position to force a re-format.
281                         SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
282                                                        nToPageNum );
283                         mrAnchorTxtFrm.InvalidatePos();
284 
285                         // Indicate restart of the layout process
286                         bSuccess = false;
287 
288                         // If needed, invalidate previous objects anchored at same anchor
289                         // text frame.
290                         _InvalidatePrevObjs( _rAnchoredObj );
291 
292                         // Invalidate object and following objects for the restart of the
293                         // layout process
294                         _InvalidateFollowObjs( _rAnchoredObj, true );
295                     }
296                     else
297                     {
298                         ASSERT( false,
299                                 "<SwObjectFormatterTxtFrm::DoFormatObj(..)> - anchor frame not marked to move forward" );
300                     }
301                     // <--
302                 }
303             }
304             // <--
305             // --> OD 2005-01-12 #i40155# - mark anchor frame not to wrap around
306             // objects under the condition, that its follow contains all its text.
307             else if ( !mrAnchorTxtFrm.IsFollow() &&
308                       mrAnchorTxtFrm.GetFollow() &&
309                       mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
310             {
311                 SwLayouter::InsertFrmNotToWrap(
312                                 *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
313                                 mrAnchorTxtFrm );
314                 SwLayouter::RemoveMovedFwdFrm(
315                                 *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
316                                 mrAnchorTxtFrm );
317             }
318             // <--
319         }
320     }
321 
322     return bSuccess;
323 }
324 
DoFormatObjs()325 bool SwObjectFormatterTxtFrm::DoFormatObjs()
326 {
327     if ( !mrAnchorTxtFrm.IsValid() )
328     {
329         if ( GetLayAction() &&
330              mrAnchorTxtFrm.FindPageFrm() != &GetPageFrm() )
331         {
332             // notify layout action, thus is can restart the layout process on
333             // a previous page.
334             GetLayAction()->SetAgain();
335         }
336         else
337         {
338             // the anchor text frame has to be valid, thus assert.
339             ASSERT( false,
340                     "<SwObjectFormatterTxtFrm::DoFormatObjs()> called for invalidate anchor text frame." );
341         }
342 
343         return false;
344     }
345 
346     bool bSuccess( true );
347 
348     if ( mrAnchorTxtFrm.IsFollow() )
349     {
350         // Only floating screen objects anchored as-character are directly
351         // registered at a follow text frame. The other floating screen objects
352         // are registered at the 'master' anchor text frame.
353         // Thus, format the other floating screen objects through the 'master'
354         // anchor text frame
355         ASSERT( mpMasterAnchorTxtFrm,
356                 "SwObjectFormatterTxtFrm::DoFormatObjs() - missing 'master' anchor text frame" );
357         bSuccess = _FormatObjsAtFrm( mpMasterAnchorTxtFrm );
358 
359         if ( bSuccess )
360         {
361             // format of as-character anchored floating screen objects - no failure
362             // excepted on the format of these objects.
363             bSuccess = _FormatObjsAtFrm();
364         }
365     }
366     else
367     {
368         bSuccess = _FormatObjsAtFrm();
369     }
370 
371     // --> OD 2006-07-24 #b449874#
372     // consider anchored objects, whose wrapping style influence are temporarly
373     // considered.
374     if ( bSuccess &&
375          ( ConsiderWrapOnObjPos() ||
376            ( !mrAnchorTxtFrm.IsFollow() &&
377              _AtLeastOneObjIsTmpConsiderWrapInfluence() ) ) )
378     // <--
379     {
380         const bool bDoesAnchorHadPrev = ( mrAnchorTxtFrm.GetIndPrev() != 0 );
381 
382         // Format anchor text frame after its objects are formatted.
383         // Note: The format of the anchor frame also formats the invalid
384         //       previous frames of the anchor frame. The format of the previous
385         //       frames is needed to get a correct result of format of the
386         //       anchor frame for the following check for moved forward anchors
387         // --> OD 2005-01-11 #i40141# - use new method - it also formats the
388         // section the anchor frame is in.
389         _FormatAnchorFrmForCheckMoveFwd();
390         // <--
391 
392         sal_uInt32 nToPageNum( 0L );
393         // --> OD 2005-03-30 #i43913#
394         bool bInFollow( false );
395         // <--
396         SwAnchoredObject* pObj = 0L;
397         if ( !mrAnchorTxtFrm.IsFollow() )
398         {
399             pObj = _GetFirstObjWithMovedFwdAnchor(
400                     // --> OD 2004-10-18 #i35017# - constant name has changed
401                     text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
402                     // <--
403                     nToPageNum, bInFollow );
404         }
405         // --> OD 2004-10-25 #i35911#
406         if ( pObj && pObj->HasClearedEnvironment() )
407         {
408             pObj->SetClearedEnvironment( true );
409             // --> OD 2005-03-08 #i44049# - consider, that anchor frame
410             // could already been marked to move forward.
411             SwPageFrm* pAnchorPageFrm( mrAnchorTxtFrm.FindPageFrm() );
412             // --> OD 2005-03-30 #i43913# - consider, that anchor frame
413             // is a follow or is in a follow row, which will move forward.
414             if ( pAnchorPageFrm != pObj->GetPageFrm() ||
415                  bInFollow )
416             // <--
417             {
418                 bool bInsert( true );
419                 sal_uInt32 nTmpToPageNum( 0L );
420                 const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
421                 if ( SwLayouter::FrmMovedFwdByObjPos(
422                                         rDoc, mrAnchorTxtFrm, nTmpToPageNum ) )
423                 {
424                     if ( nTmpToPageNum < pAnchorPageFrm->GetPhyPageNum() )
425                         SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
426                     else
427                         bInsert = false;
428                 }
429                 if ( bInsert )
430                 {
431                     SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm,
432                                                    pAnchorPageFrm->GetPhyPageNum() );
433                     mrAnchorTxtFrm.InvalidatePos();
434                     bSuccess = false;
435                     _InvalidatePrevObjs( *pObj );
436                     _InvalidateFollowObjs( *pObj, true );
437                 }
438                 else
439                 {
440                     ASSERT( false,
441                             "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
442                 }
443             }
444         }
445         else if ( pObj && bDoesAnchorHadPrev )
446         // <--
447         {
448             // Object found, whose anchor is moved forward
449 
450             // --> OD 2005-06-01 #i49987# - consider, that anchor frame
451             // could already been marked to move forward.
452             bool bInsert( true );
453             sal_uInt32 nMovedFwdToPageNum( 0L );
454             const SwDoc& rDoc = *(GetPageFrm().GetFmt()->GetDoc());
455             if ( SwLayouter::FrmMovedFwdByObjPos(
456                                     rDoc, mrAnchorTxtFrm, nMovedFwdToPageNum ) )
457             {
458                 if ( nMovedFwdToPageNum < nToPageNum )
459                     SwLayouter::RemoveMovedFwdFrm( rDoc, mrAnchorTxtFrm );
460                 else
461                     bInsert = false;
462             }
463             if ( bInsert )
464             {
465                 // Indicate that anchor text frame has to move forward and
466                 // invalidate its position to force a re-format.
467                 SwLayouter::InsertMovedFwdFrm( rDoc, mrAnchorTxtFrm, nToPageNum );
468                 mrAnchorTxtFrm.InvalidatePos();
469 
470                 // Indicate restart of the layout process
471                 bSuccess = false;
472 
473                 // If needed, invalidate previous objects anchored at same anchor
474                 // text frame.
475                 _InvalidatePrevObjs( *pObj );
476 
477                 // Invalidate object and following objects for the restart of the
478                 // layout process
479                 _InvalidateFollowObjs( *pObj, true );
480             }
481             else
482             {
483                 ASSERT( false,
484                         "<SwObjectFormatterTxtFrm::DoFormatObjs(..)> - anchor frame not marked to move forward" );
485             }
486             // <--
487         }
488         // <--
489         // --> OD 2005-01-12 #i40155# - mark anchor frame not to wrap around
490         // objects under the condition, that its follow contains all its text.
491         else if ( !mrAnchorTxtFrm.IsFollow() &&
492                   mrAnchorTxtFrm.GetFollow() &&
493                   mrAnchorTxtFrm.GetFollow()->GetOfst() == 0 )
494         {
495             SwLayouter::InsertFrmNotToWrap(
496                             *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
497                             mrAnchorTxtFrm );
498             SwLayouter::RemoveMovedFwdFrm(
499                             *(mrAnchorTxtFrm.FindPageFrm()->GetFmt()->GetDoc()),
500                             mrAnchorTxtFrm );
501         }
502         // <--
503     }
504 
505     return bSuccess;
506 }
507 
_InvalidatePrevObjs(SwAnchoredObject & _rAnchoredObj)508 void SwObjectFormatterTxtFrm::_InvalidatePrevObjs( SwAnchoredObject& _rAnchoredObj )
509 {
510     // invalidate all previous objects, whose wrapping influence on the object
511     // positioning is <NONE_CONCURRENT_POSIITIONED>.
512     // Note: list of objects at anchor frame is sorted by this property.
513     if ( _rAnchoredObj.GetFrmFmt().GetWrapInfluenceOnObjPos().
514                 // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
515                 GetWrapInfluenceOnObjPos( true ) ==
516                 // <--
517                             // --> OD 2004-10-18 #i35017# - constant name has changed
518                             text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
519                             // <--
520     {
521         const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
522         if ( pObjs )
523         {
524             // determine start index
525             sal_Int32 i = pObjs->ListPosOf( _rAnchoredObj ) - 1;
526             for ( ; i >= 0; --i )
527             {
528                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
529                 if ( pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
530                         // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
531                         GetWrapInfluenceOnObjPos( true ) ==
532                         // <--
533                             // --> OD 2004-10-18 #i35017# - constant name has changed
534                             text::WrapInfluenceOnPosition::ONCE_CONCURRENT )
535                             // <--
536                 {
537                     pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
538                 }
539             }
540         }
541     }
542 }
543 
_InvalidateFollowObjs(SwAnchoredObject & _rAnchoredObj,const bool _bInclObj)544 void SwObjectFormatterTxtFrm::_InvalidateFollowObjs( SwAnchoredObject& _rAnchoredObj,
545                                                      const bool _bInclObj )
546 {
547     if ( _bInclObj )
548     {
549         _rAnchoredObj.InvalidateObjPosForConsiderWrapInfluence( true );
550     }
551 
552     const SwSortedObjs* pObjs = GetPageFrm().GetSortedObjs();
553     if ( pObjs )
554     {
555         // determine start index
556         sal_uInt32 i = pObjs->ListPosOf( _rAnchoredObj ) + 1;
557         for ( ; i < pObjs->Count(); ++i )
558         {
559             SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
560             pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
561         }
562     }
563 }
564 
_GetFirstObjWithMovedFwdAnchor(const sal_Int16 _nWrapInfluenceOnPosition,sal_uInt32 & _noToPageNum,bool & _boInFollow)565 SwAnchoredObject* SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(
566                                     const sal_Int16 _nWrapInfluenceOnPosition,
567                                     sal_uInt32& _noToPageNum,
568                                     bool& _boInFollow )
569 {
570     // --> OD 2004-10-18 #i35017# - constant names have changed
571     ASSERT( _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ||
572             _nWrapInfluenceOnPosition == text::WrapInfluenceOnPosition::ONCE_CONCURRENT,
573             "<SwObjectFormatterTxtFrm::_GetFirstObjWithMovedFwdAnchor(..)> - invalid value for parameter <_nWrapInfluenceOnPosition>" );
574     // <--
575 
576     SwAnchoredObject* pRetAnchoredObj = 0L;
577 
578     sal_uInt32 i = 0L;
579     for ( ; i < CountOfCollected(); ++i )
580     {
581         SwAnchoredObject* pAnchoredObj = GetCollectedObj(i);
582         if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() &&
583              pAnchoredObj->GetFrmFmt().GetWrapInfluenceOnObjPos().
584                     // --> OD 2004-10-18 #i35017# - handle ITERATIVE as ONCE_SUCCESSIVE
585                     GetWrapInfluenceOnObjPos( true ) == _nWrapInfluenceOnPosition )
586                     // <--
587         {
588             // --> OD 2004-10-11 #i26945# - use new method <_CheckMovedFwdCondition(..)>
589             // --> OD 2005-03-30 #i43913#
590             // --> OD 2006-01-27 #i58182# - consider new method signature
591             if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( *GetCollectedObj( i ),
592                                           GetPgNumOfCollected( i ),
593                                           IsCollectedAnchoredAtMaster( i ),
594                                           _noToPageNum, _boInFollow ) )
595             {
596                 pRetAnchoredObj = pAnchoredObj;
597                 break;
598             }
599             // <--
600         }
601     }
602 
603     return pRetAnchoredObj;
604 }
605 
606 // --> OD 2006-01-27 #i58182#
607 // - replace private method by corresponding static public method
CheckMovedFwdCondition(SwAnchoredObject & _rAnchoredObj,const sal_uInt32 _nFromPageNum,const bool _bAnchoredAtMasterBeforeFormatAnchor,sal_uInt32 & _noToPageNum,bool & _boInFollow)608 bool SwObjectFormatterTxtFrm::CheckMovedFwdCondition(
609                                             SwAnchoredObject& _rAnchoredObj,
610                                             const sal_uInt32 _nFromPageNum,
611                                             const bool _bAnchoredAtMasterBeforeFormatAnchor,
612                                             sal_uInt32& _noToPageNum,
613                                             bool& _boInFollow )
614 {
615     bool bAnchorIsMovedForward( false );
616 
617     SwPageFrm* pPageFrmOfAnchor = _rAnchoredObj.FindPageFrmOfAnchor();
618     if ( pPageFrmOfAnchor )
619     {
620         const sal_uInt32 nPageNum = pPageFrmOfAnchor->GetPhyPageNum();
621         if ( nPageNum > _nFromPageNum )
622         {
623             _noToPageNum = nPageNum;
624             // --> OD 2006-06-28 #b6443897#
625             // Handling of special case:
626             // If anchor frame is move forward into a follow flow row,
627             // <_noToPageNum> is set to <_nFromPageNum + 1>, because it is
628             // possible that the anchor page frame isn't valid, because the
629             // page distance between master row and follow flow row is greater
630             // than 1.
631             if ( _noToPageNum > (_nFromPageNum + 1) )
632             {
633                 SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
634                 if ( pAnchorFrm->IsInTab() &&
635                      pAnchorFrm->IsInFollowFlowRow() )
636                 {
637                     _noToPageNum = _nFromPageNum + 1;
638                 }
639             }
640             // <--
641             bAnchorIsMovedForward = true;
642         }
643     }
644     // <--
645     // --> OD 2004-11-05 #i26945# - check, if an at-paragraph|at-character
646     // anchored object is now anchored at a follow text frame, which will be
647     // on the next page. Also check, if an at-character anchored object
648     // is now anchored at a text frame,  which is in a follow flow row,
649     // which will be on the next page.
650     if ( !bAnchorIsMovedForward &&
651          _bAnchoredAtMasterBeforeFormatAnchor &&
652         ((_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) ||
653          (_rAnchoredObj.GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_PARA)))
654     {
655         SwFrm* pAnchorFrm = _rAnchoredObj.GetAnchorFrmContainingAnchPos();
656         ASSERT( pAnchorFrm->IsTxtFrm(),
657                 "<SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..) - wrong type of anchor frame>" );
658         SwTxtFrm* pAnchorTxtFrm = static_cast<SwTxtFrm*>(pAnchorFrm);
659         bool bCheck( false );
660         if ( pAnchorTxtFrm->IsFollow() )
661         {
662             bCheck = true;
663         }
664         else if( pAnchorTxtFrm->IsInTab() )
665         {
666             const SwRowFrm* pMasterRow = pAnchorTxtFrm->IsInFollowFlowRow();
667             if ( pMasterRow &&
668                  pMasterRow->FindPageFrm() == pPageFrmOfAnchor )
669             {
670                 bCheck = true;
671             }
672         }
673         if ( bCheck )
674         {
675             // check, if found text frame will be on the next page
676             // by checking, if it's in a column, which has no next.
677             SwFrm* pColFrm = pAnchorTxtFrm->FindColFrm();
678             while ( pColFrm && !pColFrm->GetNext() )
679             {
680                 pColFrm = pColFrm->FindColFrm();
681             }
682             if ( !pColFrm || !pColFrm->GetNext() )
683             {
684                 _noToPageNum = _nFromPageNum + 1;
685                 bAnchorIsMovedForward = true;
686                 // --> OD 2005-03-30 #i43913#
687                 _boInFollow = true;
688                 // <--
689             }
690         }
691     }
692     // <--
693 
694     return bAnchorIsMovedForward;
695 }
696 // <--
697 
698 // --> OD 2005-01-12 #i40140# - helper method to format layout frames used by
699 // method <SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()>
700 // --> OD 2005-03-04 #i44049# - format till a certain lower frame, if provided.
lcl_FormatCntntOfLayoutFrm(SwLayoutFrm * pLayFrm,SwFrm * pLastLowerFrm=0L)701 void lcl_FormatCntntOfLayoutFrm( SwLayoutFrm* pLayFrm,
702                                  SwFrm* pLastLowerFrm = 0L )
703 {
704     SwFrm* pLowerFrm = pLayFrm->GetLower();
705     while ( pLowerFrm )
706     {
707         // --> OD 2005-03-04 #i44049#
708         if ( pLastLowerFrm && pLowerFrm == pLastLowerFrm )
709         {
710             break;
711         }
712         // <--
713         if ( pLowerFrm->IsLayoutFrm() )
714             lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pLowerFrm),
715                                         pLastLowerFrm );
716         else
717             pLowerFrm->Calc();
718 
719         pLowerFrm = pLowerFrm->GetNext();
720     }
721 }
722 // <--
723 /** method to format given anchor text frame and its previous frames
724 
725     OD 2005-11-17 #i56300#
726     Usage: Needed to check, if the anchor text frame is moved forward
727     due to the positioning and wrapping of its anchored objects, and
728     to format the frames, which have become invalid due to the anchored
729     object formatting in the iterative object positioning algorithm
730 
731     @author OD
732 */
FormatAnchorFrmAndItsPrevs(SwTxtFrm & _rAnchorTxtFrm)733 void SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( SwTxtFrm& _rAnchorTxtFrm )
734 {
735     // --> OD 2005-04-13 #i47014# - no format of section and previous columns
736     // for follow text frames.
737     if ( !_rAnchorTxtFrm.IsFollow() )
738     {
739         // if anchor frame is directly inside a section, format this section and
740         // its previous frames.
741         // Note: It's a very simple format without formatting objects.
742         if ( _rAnchorTxtFrm.IsInSct() )
743         {
744             SwFrm* pSectFrm = _rAnchorTxtFrm.GetUpper();
745             while ( pSectFrm )
746             {
747                 if ( pSectFrm->IsSctFrm() || pSectFrm->IsCellFrm() )
748                 {
749                     break;
750                 }
751                 pSectFrm = pSectFrm->GetUpper();
752             }
753             if ( pSectFrm && pSectFrm->IsSctFrm() )
754             {
755                 // --> OD 2005-03-04 #i44049#
756                 _rAnchorTxtFrm.LockJoin();
757                 // <--
758                 SwFrm* pFrm = pSectFrm->GetUpper()->GetLower();
759                 // --> OD 2005-05-23 #i49605# - section frame could move forward
760                 // by the format of its previous frame.
761                 // Thus, check for valid <pFrm>.
762                 while ( pFrm && pFrm != pSectFrm )
763                 // <--
764                 {
765                     if ( pFrm->IsLayoutFrm() )
766                         lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
767                     else
768                         pFrm->Calc();
769 
770                     pFrm = pFrm->GetNext();
771                 }
772                 lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pSectFrm),
773                                             &_rAnchorTxtFrm );
774                 // --> OD 2005-03-04 #i44049#
775                 _rAnchorTxtFrm.UnlockJoin();
776                 // <--
777             }
778         }
779 
780         // --> OD 2005-01-12 #i40140# - if anchor frame is inside a column,
781         // format the content of the previous columns.
782         // Note: It's a very simple format without formatting objects.
783         SwFrm* pColFrmOfAnchor = _rAnchorTxtFrm.FindColFrm();
784         if ( pColFrmOfAnchor )
785         {
786             // --> OD 2005-03-04 #i44049#
787             _rAnchorTxtFrm.LockJoin();
788             // <--
789             SwFrm* pColFrm = pColFrmOfAnchor->GetUpper()->GetLower();
790             while ( pColFrm != pColFrmOfAnchor )
791             {
792                 SwFrm* pFrm = pColFrm->GetLower();
793                 while ( pFrm )
794                 {
795                     if ( pFrm->IsLayoutFrm() )
796                         lcl_FormatCntntOfLayoutFrm( static_cast<SwLayoutFrm*>(pFrm) );
797                     else
798                         pFrm->Calc();
799 
800                     pFrm = pFrm->GetNext();
801                 }
802 
803                 pColFrm = pColFrm->GetNext();
804             }
805             // --> OD 2005-03-04 #i44049#
806             _rAnchorTxtFrm.UnlockJoin();
807             // <--
808         }
809         // <--
810     }
811     // <--
812 
813     // format anchor frame - format of its follow not needed
814     // --> OD 2005-04-08 #i43255# - forbid follow format, only if anchor text
815     // frame is in table
816     if ( _rAnchorTxtFrm.IsInTab() )
817     {
818         SwForbidFollowFormat aForbidFollowFormat( _rAnchorTxtFrm );
819         _rAnchorTxtFrm.Calc();
820     }
821     else
822     {
823         _rAnchorTxtFrm.Calc();
824     }
825 }
826 
827 /** method to format the anchor frame for checking of the move forward condition
828 
829     OD 2005-01-11 #i40141#
830 
831     @author OD
832 */
_FormatAnchorFrmForCheckMoveFwd()833 void SwObjectFormatterTxtFrm::_FormatAnchorFrmForCheckMoveFwd()
834 {
835     SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( mrAnchorTxtFrm );
836 }
837 
838 /** method to determine if at least one anchored object has state
839     <temporarly consider wrapping style influence> set.
840 
841     OD 2006-07-24 #b6449874#
842 
843     @author OD
844 */
_AtLeastOneObjIsTmpConsiderWrapInfluence()845 bool SwObjectFormatterTxtFrm::_AtLeastOneObjIsTmpConsiderWrapInfluence()
846 {
847     bool bRet( false );
848 
849     const SwSortedObjs* pObjs = GetAnchorFrm().GetDrawObjs();
850     if ( pObjs && pObjs->Count() > 1 )
851     {
852         sal_uInt32 i = 0;
853         for ( ; i < pObjs->Count(); ++i )
854         {
855             SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
856             if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
857             {
858                 bRet = true;
859                 break;
860             }
861         }
862     }
863 
864     return bRet;
865 }
866 
867