xref: /trunk/main/sw/source/core/layout/frmtool.cxx (revision bcc22a4c08e1268a4f06e54fb146f88ef49f2cdc)
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 
25 #include <hintids.hxx>
26 #include <tools/bigint.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <svx/svdpage.hxx>
29 #include <editeng/brshitem.hxx>
30 #include <editeng/keepitem.hxx>
31 #include <editeng/shaditem.hxx>
32 #include <editeng/ulspitem.hxx>
33 #include <editeng/lrspitem.hxx>
34 #include <editeng/boxitem.hxx>
35 #include <sfx2/printer.hxx>
36 #include <editeng/lspcitem.hxx>
37 #include <fmtornt.hxx>
38 #include <fmtanchr.hxx>
39 #include <fmthdft.hxx>
40 #include <fmtcntnt.hxx>
41 #include <fmtfsize.hxx>
42 #include <fmtsrnd.hxx>
43 #include <docary.hxx>
44 #include <lineinfo.hxx>
45 #include <swmodule.hxx>
46 #include "pagefrm.hxx"
47 #include "colfrm.hxx"
48 #include "doc.hxx"
49 #include "fesh.hxx"
50 #include "viewimp.hxx"
51 #include "viewopt.hxx"
52 #include "pam.hxx"
53 #include "dflyobj.hxx"
54 #include "dcontact.hxx"
55 #include "frmtool.hxx"
56 #include "docsh.hxx"
57 #include "tabfrm.hxx"
58 #include "rowfrm.hxx"
59 #include "ftnfrm.hxx"
60 #include "txtfrm.hxx"
61 #include "notxtfrm.hxx"
62 #include "flyfrms.hxx"
63 #include "layact.hxx"
64 #include "pagedesc.hxx"
65 #include "section.hxx"
66 #include "sectfrm.hxx"
67 #include "node2lay.hxx"
68 #include "ndole.hxx"
69 #include "ndtxt.hxx"
70 #include "swtable.hxx"
71 #include "hints.hxx"
72 #include <layhelp.hxx>
73 #include <laycache.hxx>
74 #include <rootfrm.hxx>
75 #include "mdiexp.hxx"
76 #include "statstr.hrc"
77 #include <paratr.hxx>
78 #include <sortedobjs.hxx>
79 #include <objectformatter.hxx>
80 #include <switerator.hxx>
81 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
82 #include <drawdoc.hxx>
83 
84 // ftnfrm.cxx:
85 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
86 
87 using namespace ::com::sun::star;
88 
89 
90 sal_Bool bObjsDirect = sal_True;
91 sal_Bool bDontCreateObjects = sal_False;
92 sal_Bool bSetCompletePaintOnInvalidate = sal_False;
93 
94 sal_uInt8 StackHack::nCnt = 0;
95 sal_Bool StackHack::bLocked = sal_False;
96 
97 
98 
99 /*************************************************************************/
100 
101 SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
102     pFrm( pF ),
103     aFrm( pF->Frm() ),
104     aPrt( pF->Prt() ),
105     bInvaKeep( sal_False ),
106     bValidSize( pF->GetValidSizeFlag() ),
107     mbFrmDeleted( false )     // #i49383#
108 {
109     if ( pF->IsTxtFrm() )
110     {
111         mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
112         mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
113     }
114     else
115     {
116         mnFlyAnchorOfst = 0;
117         mnFlyAnchorOfstNoWrap = 0;
118     }
119 
120     bHadFollow = pF->IsCntntFrm() ?
121                     (((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
122                     sal_False;
123 }
124 
125 /*************************************************************************/
126 
127 SwFrmNotify::~SwFrmNotify()
128 {
129     // #i49383#
130     if ( mbFrmDeleted )
131     {
132         return;
133     }
134 
135     SWRECTFN( pFrm )
136     const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
137     const sal_Bool bChgWidth =
138             (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
139     const sal_Bool bChgHeight =
140             (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
141     const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
142        ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
143          ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );
144 
145     if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
146     {
147         SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
148 
149         if ( !pFlow->IsFollow() )
150         {
151             if ( !pFrm->GetIndPrev() )
152             {
153                 if ( bInvaKeep )
154                 {
155                     SwFrm *pPre = pFrm->FindPrev();
156                     if ( pPre && pPre->IsFlowFrm() )
157                     {
158                         // 1. pPre wants to keep with me:
159                         bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
160 
161                         // 2. pPre is a table and the last row wants to keep with me:
162                         if ( !bInvalidPrePos && pPre->IsTabFrm() )
163                         {
164                             SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
165                             if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
166                             {
167                                 SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
168                                 if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
169                                     bInvalidPrePos = true;
170                             }
171                         }
172 
173                         if ( bInvalidPrePos )
174                             pPre->InvalidatePos();
175                     }
176                 }
177             }
178             else if ( !pFlow->HasFollow() )
179             {
180                 long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
181                 long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
182                 if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
183                     pFlow->CheckKeep();
184             }
185         }
186     }
187 
188     if ( bAbsP )
189     {
190         pFrm->SetCompletePaint();
191 
192         SwFrm* pNxt = pFrm->GetIndNext();
193         // #121888# - skip empty section frames
194         while ( pNxt &&
195                 pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
196         {
197             pNxt = pNxt->GetIndNext();
198         }
199 
200         if ( pNxt )
201             pNxt->InvalidatePos();
202         else
203         {
204             // #104100# - correct condition for setting retouche
205             // flag for vertical layout.
206             if( pFrm->IsRetoucheFrm() &&
207                 (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
208             {
209                 pFrm->SetRetouche();
210             }
211 
212             // A fresh follow frame does not have to be invalidated, because
213             // it is already formatted:
214             if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
215             {
216                 if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
217                     pFrm->InvalidateNextPos();
218             }
219         }
220     }
221 
222     //Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
223     const sal_Bool bPrtWidth =
224             (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
225     const sal_Bool bPrtHeight =
226             (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
227     if ( bPrtWidth || bPrtHeight )
228     {
229         //UUUU
230         drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(pFrm->getSdrAllFillAttributesHelper());
231 
232         if(aFillAttributes.get() && aFillAttributes->isUsed())
233         {
234             //UUUU use SetCompletePaint if needed
235             if(aFillAttributes->needCompleteRepaint())
236             {
237                 pFrm->SetCompletePaint();
238             }
239         }
240         else
241         {
242             const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
243             if(GPOS_NONE != ePos && GPOS_TILED != ePos)
244                 pFrm->SetCompletePaint();
245         }
246     }
247     else
248     {
249         // #97597# - consider case that *only* margins between
250         // frame and printing area has changed. Then, frame has to be repainted,
251         // in order to force paint of the margin areas.
252         if ( !bAbsP && (bChgWidth || bChgHeight) )
253         {
254             pFrm->SetCompletePaint();
255         }
256     }
257 
258     const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
259     if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
260          bPrtWidth || bPrtHeight || bChgFlyBasePos )
261     {
262         if( pFrm->IsAccessibleFrm() )
263         {
264             SwRootFrm *pRootFrm = pFrm->getRootFrm();
265             if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
266                 pRootFrm->GetCurrShell() )
267             {
268                 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
269             }
270         }
271 
272         // Notification of anchored objects
273         if ( pFrm->GetDrawObjs() )
274         {
275             const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
276             SwPageFrm* pPageFrm = 0;
277             for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
278             {
279                 // OD 2004-03-31 #i26791# - no general distinction between
280                 // Writer fly frames and drawing objects
281                 bool bNotify = false;
282                 bool bNotifySize = false;
283                 SwAnchoredObject* pObj = rObjs[i];
284                 SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
285                 // --> OD 2004-12-08 #115759#
286                 const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
287                 if ( !bAnchoredAsChar )
288                 // <--
289                 {
290                     // Notify object, which aren't anchored as-character:
291 
292                     // always notify objects, if frame position has changed
293                     // or if the object is to-page|to-fly anchored.
294                     if ( bAbsP ||
295                          pContact->ObjAnchoredAtPage() ||
296                          pContact->ObjAnchoredAtFly() )
297                     {
298                         bNotify = true;
299 
300                         // assure that to-fly anchored Writer fly frames are
301                         // registered at the correct page frame, if frame
302                         // position has changed.
303                         if ( bAbsP && pContact->ObjAnchoredAtFly() &&
304                              pObj->ISA(SwFlyFrm) )
305                         {
306                             // determine to-fly anchored Writer fly frame
307                             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
308                             // determine page frame of to-fly anchored
309                             // Writer fly frame
310                             SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
311                             // determine page frame, if needed.
312                             if ( !pPageFrm )
313                             {
314                                 pPageFrm = pFrm->FindPageFrm();
315                             }
316                             if ( pPageFrm != pFlyPageFrm )
317                             {
318                                 ASSERT( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
319                                 if( pFlyPageFrm )
320                                     pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
321                                 else
322                                     pPageFrm->AppendFlyToPage( pFlyFrm );
323                             }
324                         }
325                     }
326                     // otherwise the objects are notified in dependence to
327                     // its positioning and alignment
328                     else
329                     {
330                         const SwFmtVertOrient& rVert =
331                                         pContact->GetFmt()->GetVertOrient();
332                         if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
333                                rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
334                                rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
335                              ( bChgHeight || bPrtHeight ) )
336                         {
337                             bNotify = true;
338                         }
339                         if ( !bNotify )
340                         {
341                             const SwFmtHoriOrient& rHori =
342                                         pContact->GetFmt()->GetHoriOrient();
343                             if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
344                                    rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
345                                    rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
346                                  ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
347                             {
348                                 bNotify = true;
349                             }
350                         }
351                     }
352                 }
353                 else if ( bPrtWidth )
354                 {
355                     // Notify as-character anchored objects, if printing area
356                     // width has changed.
357                     bNotify = true;
358                     bNotifySize = true;
359                 }
360 
361                 // perform notification via the corresponding invalidations
362                 if ( bNotify )
363                 {
364                     if ( pObj->ISA(SwFlyFrm) )
365                     {
366                         SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
367                         if ( bNotifySize )
368                             pFlyFrm->_InvalidateSize();
369                         // --> OD 2004-12-08 #115759# - no invalidation of
370                         // position for as-character anchored objects.
371                         if ( !bAnchoredAsChar )
372                         {
373                             pFlyFrm->_InvalidatePos();
374                         }
375                         // <--
376                         pFlyFrm->_Invalidate();
377                     }
378                     else if ( pObj->ISA(SwAnchoredDrawObject) )
379                     {
380                         // --> OD 2004-12-08 #115759# - no invalidation of
381                         // position for as-character anchored objects.
382                         if ( !bAnchoredAsChar )
383                         {
384                             pObj->InvalidateObjPos();
385                         }
386                         // <--
387                     }
388                     else
389                     {
390                         ASSERT( false,
391                                 "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
392                     }
393                 }
394             }
395         }
396     }
397     else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
398     {
399         SwRootFrm *pRootFrm = pFrm->getRootFrm();
400         if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
401             pRootFrm->GetCurrShell() )
402         {
403             pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
404         }
405     }
406 
407     // #i9046# Automatic frame width
408     SwFlyFrm* pFly = 0;
409     // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
410     // necessarily have to have an upper!
411     if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
412     // <--
413     {
414         // --> OD 2006-05-08 #i61999#
415         // no invalidation of columned Writer fly frames, because automatic
416         // width doesn't make sense for such Writer fly frames.
417         if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
418         {
419             const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
420 
421             // This could be optimized. Basically the fly frame only has to
422             // be invalidated, if the first line of pFrm (if pFrm is a content
423             // frame, for other frame types its the print area) has changed its
424             // size and pFrm was responsible for the current width of pFly. On
425             // the other hand, this is only rarely used and re-calculation of
426             // the fly frame does not cause too much trouble. So we keep it this
427             // way:
428             if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
429             {
430                 // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
431                 // of as-character anchored fly frames not needed and can cause
432                 // layout loops
433                 if ( !pFly->ISA(SwFlyInCntFrm) )
434                 {
435                     pFly->InvalidatePos();
436                 }
437                 // <--
438                 pFly->InvalidateSize();
439             }
440         }
441         // <--
442     }
443 }
444 
445 /*************************************************************************/
446 
447 SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
448     SwFrmNotify( pLayFrm ),
449     bLowersComplete( sal_False )
450 {
451 }
452 
453 /*************************************************************************/
454 
455 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
456 // frames inclusive its floating screen objects, which are lowers of the given
457 // layout frame
458 void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
459 {
460     if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
461     {
462         _rLayoutFrm.InvalidateObjs( true, false );
463     }
464 
465     SwFrm* pLowerFrm = _rLayoutFrm.Lower();
466     while ( pLowerFrm )
467     {
468         pLowerFrm->InvalidatePos();
469         if ( pLowerFrm->IsTxtFrm() )
470         {
471             static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
472         }
473         else if ( pLowerFrm->IsTabFrm() )
474         {
475             pLowerFrm->InvalidatePrt();
476         }
477 
478         pLowerFrm->InvalidateObjs( true, false );
479 
480         pLowerFrm = pLowerFrm->GetNext();
481     };
482 }
483 
484 SwLayNotify::~SwLayNotify()
485 {
486     // --> OD 2005-07-29 #i49383#
487     if ( mbFrmDeleted )
488     {
489         return;
490     }
491     // <--
492 
493     SwLayoutFrm *pLay = GetLay();
494     SWRECTFN( pLay )
495     sal_Bool bNotify = sal_False;
496     if ( pLay->Prt().SSize() != aPrt.SSize() )
497     {
498         if ( !IsLowersComplete() )
499         {
500             sal_Bool bInvaPercent;
501 
502             if ( pLay->IsRowFrm() )
503             {
504                 bInvaPercent = sal_True;
505                 long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
506                 if( nNew != (aPrt.*fnRect->fnGetHeight)() )
507                      ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
508                 if( (pLay->Prt().*fnRect->fnGetWidth)()
509                     != (aPrt.*fnRect->fnGetWidth)() )
510                      ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
511             }
512             else
513             {
514                 //Proportionale Anpassung der innenliegenden.
515                 //1. Wenn der Formatierte kein Fly ist
516                 //2. Wenn er keine Spalten enthaelt
517                 //3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
518                 //   Hoehe danebenliegen.
519                 //4. niemals bei SectionFrms.
520                 sal_Bool bLow;
521                 if( pLay->IsFlyFrm() )
522                 {
523                     if ( pLay->Lower() )
524                     {
525                         bLow = !pLay->Lower()->IsColumnFrm() ||
526                             (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
527                              != (pLay->Prt().*fnRect->fnGetHeight)();
528                     }
529                     else
530                         bLow = sal_False;
531                 }
532                 else if( pLay->IsSctFrm() )
533                 {
534                     if ( pLay->Lower() )
535                     {
536                         if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
537                             bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
538                         else
539                             bLow = pLay->Prt().Width() != aPrt.Width();
540                     }
541                     else
542                         bLow = sal_False;
543                 }
544                 else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
545                     bLow = pLay->Prt().Width() != aPrt.Width();
546                 else
547                     bLow = sal_True;
548                 bInvaPercent = bLow;
549                 if ( bLow )
550                 {
551                     pLay->ChgLowersProp( aPrt.SSize() );
552                 }
553                 //Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
554                 //Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
555                 //mithin muss also der 'moeglicherweise passende' Invalidiert werden.
556                 //Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
557                 //Uppers um eine Moveable-Section handelt.
558                 //Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
559                 //geworden ist.
560                 if ( (pLay->Prt().Height() > aPrt.Height() ||
561                       pLay->Prt().Width()  > aPrt.Width()) &&
562                      (pLay->IsMoveable() || pLay->IsFlyFrm()) )
563                 {
564                     SwFrm *pTmpFrm = pLay->Lower();
565                     if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
566                     {
567                         while ( pTmpFrm->GetNext() )
568                             pTmpFrm = pTmpFrm->GetNext();
569                         pTmpFrm->InvalidateNextPos();
570                     }
571                 }
572             }
573             bNotify = sal_True;
574             //TEUER!! aber wie macht man es geschickter?
575             if( bInvaPercent )
576                 pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
577         }
578         if ( pLay->IsTabFrm() )
579             //Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird.
580             ((SwTabFrm*)pLay)->SetComplete();
581         else
582         {
583             const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
584             if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
585                   !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
586             //Damit die untergeordneten sauber retouchiert werden.
587             //Problembsp: Flys an den Henkeln packen und verkleinern.
588             //Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
589             pLay->SetCompletePaint();
590         }
591     }
592     //Lower benachrichtigen wenn sich die Position veraendert hat.
593     const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
594     const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
595     const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize();
596 
597     if ( bPos && pLay->Lower() && !IsLowersComplete() )
598         pLay->Lower()->InvalidatePos();
599 
600     if ( bPrtPos )
601         pLay->SetCompletePaint();
602 
603     //Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
604     if ( bSize )
605     {
606         if( pLay->GetNext() )
607         {
608             if ( pLay->GetNext()->IsLayoutFrm() )
609                 pLay->GetNext()->_InvalidatePos();
610             else
611                 pLay->GetNext()->InvalidatePos();
612         }
613         else if( pLay->IsSctFrm() )
614             pLay->InvalidateNextPos();
615     }
616     if ( !IsLowersComplete() &&
617          !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
618             pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
619          (bPos || bNotify) && !(pLay->GetType() & 0x1823) )  //Tab, Row, FtnCont, Root, Page
620     {
621         // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
622         // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
623         // if <pLay> is a cell frame, and its table frame resp. its parent table
624         // frame is locked.
625         // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
626         // only if position of layout frame has changed.
627         bool bUnlockPosOfObjs( bPos );
628         if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
629         {
630             SwTabFrm* pTabFrm( pLay->FindTabFrm() );
631             if ( pTabFrm &&
632                  ( pTabFrm->IsJoinLocked() ||
633                    ( pTabFrm->IsFollow() &&
634                      pTabFrm->FindMaster()->IsJoinLocked() ) ) )
635             {
636                 bUnlockPosOfObjs = false;
637             }
638         }
639         // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
640         // of position of lower objects is allowed.
641         else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
642         {
643             bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
644         }
645         // <--
646         // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
647         else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
648         {
649             bUnlockPosOfObjs = false;
650         }
651         // <--
652         pLay->NotifyLowerObjs( bUnlockPosOfObjs );
653         // <--
654     }
655     if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
656     {
657         // OD 2004-05-11 #i28701#
658         ::lcl_InvalidatePosOfLowers( *pLay );
659     }
660     if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
661           && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
662         ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
663 }
664 
665 /*************************************************************************/
666 
667 SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
668     SwLayNotify( pFlyFrm ),
669     // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
670     // the Writer fly frame is currently registered at.
671     pOldPage( pFlyFrm->GetPageFrm() ),
672     // <--
673     aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
674 {
675 }
676 
677 /*************************************************************************/
678 
679 SwFlyNotify::~SwFlyNotify()
680 {
681     // --> OD 2005-07-29 #i49383#
682     if ( mbFrmDeleted )
683     {
684         return;
685     }
686     // <--
687 
688     SwFlyFrm *pFly = GetFly();
689     if ( pFly->IsNotifyBack() )
690     {
691         ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
692         SwViewImp *pImp = pSh ? pSh->Imp() : 0;
693         if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
694         {
695             //Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
696             //dass die alte Seite inzwischen vernichtet wurde!
697             ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
698             // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
699             // if Writer fly frame has changed its page
700             if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
701                  pFly->GetPageFrm() != pOldPage )
702             {
703                 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
704             }
705             // <--
706         }
707         pFly->ResetNotifyBack();
708     }
709 
710     //Haben sich Groesse oder Position geaendert, so sollte die View
711     //das wissen.
712     SWRECTFN( pFly )
713     const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
714     const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
715     const bool bPrtChgd = aPrt != pFly->Prt();
716     if ( bPosChgd || bFrmChgd || bPrtChgd )
717     {
718         pFly->NotifyDrawObj();
719     }
720     if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
721     {
722         // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
723         // reason: New positioning and alignment (e.g. to-paragraph anchored,
724         // but aligned at page) are introduced.
725         // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
726         // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
727 
728         if ( pFly->IsFlyAtCntFrm() )
729         {
730             SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
731             if ( pNxt )
732             {
733                 pNxt->InvalidatePos();
734             }
735         }
736 
737         // --> OD 2004-11-05 #i26945# - notify anchor.
738         // Needed for negative positioned Writer fly frames
739         if ( pFly->GetAnchorFrm()->IsTxtFrm() )
740         {
741             pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
742         }
743         // <--
744     }
745 
746     // OD 2004-05-13 #i28701#
747     // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
748     // further notifications/invalidations, if format is called by grow/shrink
749     if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
750          ( !pFly->ISA(SwFlyFreeFrm) ||
751            !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
752     // <--
753     {
754         // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
755         // on changed frame height.
756         // Note: It doesn't seem to be necessary and can cause layout loops.
757         if ( bPosChgd )
758         // <--
759         {
760             // indicate a restart of the layout process
761             pFly->SetRestartLayoutProcess( true );
762         }
763         else
764         {
765             // lock position
766             pFly->LockPosition();
767 
768             if ( !pFly->ConsiderForTextWrap() )
769             {
770                 // indicate that object has to be considered for text wrap
771                 pFly->SetConsiderForTextWrap( true );
772                 // invalidate 'background' in order to allow its 'background'
773                 // to wrap around it.
774                 pFly->NotifyBackground( pFly->GetPageFrm(),
775                                         pFly->GetObjRectWithSpaces(),
776                                         PREP_FLY_ARRIVE );
777                 // invalidate position of anchor frame in order to force
778                 // a re-format of the anchor frame, which also causes a
779                 // re-format of the invalid previous frames of the anchor frame.
780                 pFly->AnchorFrm()->InvalidatePos();
781             }
782         }
783     }
784 }
785 
786 /*************************************************************************/
787 
788 SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
789     SwFrmNotify( pCntntFrm ),
790     // OD 08.01.2004 #i11859#
791     mbChkHeightOfLastLine( false ),
792     mnHeightOfLastLine( 0L ),
793     // OD 2004-02-26 #i25029#
794     mbInvalidatePrevPrtArea( false ),
795     mbBordersJoinedWithPrev( false )
796 {
797     // OD 08.01.2004 #i11859#
798     if ( pCntntFrm->IsTxtFrm() )
799     {
800         SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
801         if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
802         {
803             const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
804             const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
805             if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
806             {
807                 mbChkHeightOfLastLine = true;
808                 mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
809             }
810         }
811     }
812 }
813 
814 /*************************************************************************/
815 
816 SwCntntNotify::~SwCntntNotify()
817 {
818     // --> OD 2005-07-29 #i49383#
819     if ( mbFrmDeleted )
820     {
821         return;
822     }
823     // <--
824 
825     SwCntntFrm *pCnt = GetCnt();
826     if ( bSetCompletePaintOnInvalidate )
827         pCnt->SetCompletePaint();
828 
829     SWRECTFN( pCnt )
830     if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
831                              pCnt->Frm().SSize() != aFrm.SSize()))
832     {
833         SwLayoutFrm* pCell = pCnt->GetUpper();
834         while( !pCell->IsCellFrm() && pCell->GetUpper() )
835             pCell = pCell->GetUpper();
836         ASSERT( pCell->IsCellFrm(), "Where's my cell?" );
837         if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
838             pCell->InvalidatePrt(); //fuer vertikale Ausrichtung.
839     }
840 
841     // OD 2004-02-26 #i25029#
842     if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
843          pCnt->IsTxtFrm() &&
844          !pCnt->IsFollow() && !pCnt->GetIndPrev() )
845     {
846         // determine previous frame
847         SwFrm* pPrevFrm = pCnt->FindPrev();
848         // skip empty section frames and hidden text frames
849         {
850             while ( pPrevFrm &&
851                     ( ( pPrevFrm->IsSctFrm() &&
852                         !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
853                       ( pPrevFrm->IsTxtFrm() &&
854                         static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
855             {
856                 pPrevFrm = pPrevFrm->FindPrev();
857             }
858         }
859 
860         // Invalidate printing area of found previous frame
861         if ( pPrevFrm )
862         {
863             if ( pPrevFrm->IsSctFrm() )
864             {
865                 if ( pCnt->IsInSct() )
866                 {
867                     // Note: found previous frame is a section frame and
868                     //       <pCnt> is also inside a section.
869                     //       Thus due to <mbBordersJoinedWithPrev>,
870                     //       <pCnt> had joined its borders/shadow with the
871                     //       last content of the found section.
872                     // Invalidate printing area of last content in found section.
873                     SwFrm* pLstCntntOfSctFrm =
874                             static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
875                     if ( pLstCntntOfSctFrm )
876                     {
877                         pLstCntntOfSctFrm->InvalidatePrt();
878                     }
879                 }
880             }
881             else
882             {
883                 pPrevFrm->InvalidatePrt();
884             }
885         }
886     }
887 
888     const bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
889 
890     if ( pCnt->IsNoTxtFrm() )
891     {
892         //Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
893         //mitbekommen, damit sie Ihr Window entsprechend verschieben.
894         ViewShell *pSh  = pCnt->getRootFrm()->GetCurrShell();
895         if ( pSh )
896         {
897             SwOLENode *pNd;
898             if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
899                  (pNd->GetOLEObj().IsOleRef() ||
900                   pNd->IsOLESizeInvalid()) )
901             {
902                 // --> OD #i117189#
903                 const bool bNoTxtFrmPrtAreaChanged =
904                         ( aPrt.SSize().Width() != 0 &&
905                           aPrt.SSize().Height() != 0 ) &&
906                         aPrt.SSize() != pCnt->Prt().SSize();
907                 // <--
908                 ASSERT( pCnt->IsInFly(), "OLE not in FlyFrm" );
909                 SwFlyFrm *pFly = pCnt->FindFlyFrm();
910                 svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
911                 SwFEShell *pFESh = 0;
912                 ViewShell *pTmp = pSh;
913                 do
914                 {   if ( pTmp->ISA( SwCrsrShell ) )
915                     {
916                         pFESh = (SwFEShell*)pTmp;
917                         // #108369#: Here used to be the condition if (!bFirst).
918                         // I think this should mean "do not call CalcAndSetScale"
919                         // if the frame is formatted for the first time.
920                         // Unfortunately this is not valid anymore since the
921                         // SwNoTxtFrm already gets a width during CalcLowerPreps.
922                         // Nevertheless, the indention of !bFirst seemed to be
923                         // to assure that the OLE objects have already been notified
924                         // if necessary before calling CalcAndSetScale.
925                         // So I replaced !bFirst by !IsOLESizeInvalid. There is
926                         // one additional problem specific to the word import:
927                         // The layout is calculated _before_ calling PrtOLENotify,
928                         // and the OLE objects are not invalidated during import.
929                         // Therefore I added the condition !IsUpdateExpFld,
930                         // have a look at the occurrence of CalcLayout in
931                         // uiview/view.cxx.
932                         if ( !pNd->IsOLESizeInvalid() &&
933                              !pSh->GetDoc()->IsUpdateExpFld() )
934                             pFESh->CalcAndSetScale( xObj,
935                                                     &pFly->Prt(), &pFly->Frm(),
936                                                     bNoTxtFrmPrtAreaChanged );
937                     }
938                     pTmp = (ViewShell*)pTmp->GetNext();
939                 } while ( pTmp != pSh );
940 
941                 if ( pFESh && pNd->IsOLESizeInvalid() )
942                 {
943                     pNd->SetOLESizeInvalid( sal_False );
944                     //TODO/LATER: needs OnDocumentPrinterChanged
945                     //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
946                     pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
947                 }
948             }
949             //dito Animierte Grafiken
950             if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
951             {
952                 ((SwNoTxtFrm*)pCnt)->StopAnimation();
953                 pSh->InvalidateWindows( Frm() );
954             }
955         }
956     }
957 
958     if ( bFirst )
959     {
960         pCnt->SetRetouche();    //fix(13870)
961 
962         SwDoc *pDoc = pCnt->GetNode()->GetDoc();
963         if ( pDoc->GetSpzFrmFmts()->Count() &&
964              pDoc->DoesContainAtPageObjWithContentAnchor() && !pDoc->IsNewDoc() )
965         {
966             // If certain import filters for foreign file format import
967             // AT_PAGE anchored objects, the corresponding page number is
968             // typically not known. In this case the content position is
969             // stored at which the anchored object is found in the
970             // imported document.
971             // When this content is formatted it is the time at which
972             // the page is known. Thus, this data can be corrected now.
973 
974             const SwPageFrm* pPage = 0;
975             SwNodeIndex *pIdx  = 0;
976             SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
977             for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
978             {
979                 SwFrmFmt *pFmt = (*pTbl)[i];
980                 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
981                 if ( FLY_AT_PAGE != rAnch.GetAnchorId() ||
982                      rAnch.GetCntntAnchor() == 0 )
983                 {
984                     continue;
985                 }
986 
987                 if ( !pIdx )
988                 {
989                     pIdx = new SwNodeIndex( *pCnt->GetNode() );
990                 }
991                 if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
992                 {
993                     ASSERT( false, "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
994                     if ( !pPage )
995                     {
996                         pPage = pCnt->FindPageFrm();
997                     }
998                     SwFmtAnchor aAnch( rAnch );
999                     aAnch.SetAnchor( 0 );
1000                     aAnch.SetPageNum( pPage->GetPhyPageNum() );
1001                     pFmt->SetFmtAttr( aAnch );
1002                     if ( RES_DRAWFRMFMT != pFmt->Which() )
1003                     {
1004                         pFmt->MakeFrms();
1005                     }
1006                 }
1007             }
1008             delete pIdx;
1009         }
1010     }
1011 
1012     // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
1013     //  if height of last line has changed.
1014     if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
1015     {
1016         if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
1017         {
1018             pCnt->InvalidateNextPrtArea();
1019         }
1020     }
1021 
1022     // --> OD 2005-03-07 #i44049#
1023     if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
1024     {
1025         pCnt->InvalidateObjs( true );
1026     }
1027     // <--
1028 
1029     // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
1030     // anchored objects due to a change of its anchor character from
1031     // method <SwTxtFrm::Format(..)>.
1032     if ( pCnt->IsTxtFrm() )
1033     {
1034         SwTxtFrm* pMasterFrm = pCnt->IsFollow()
1035                                ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
1036                                : static_cast<SwTxtFrm*>(pCnt);
1037         if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
1038              pMasterFrm->GetDrawObjs() )
1039         {
1040             SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
1041             for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
1042             {
1043                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1044                 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
1045                         == FLY_AT_CHAR )
1046                 {
1047                     pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
1048                 }
1049             }
1050         }
1051     }
1052     // <--
1053 }
1054 
1055 /*************************************************************************/
1056 
1057 void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
1058                         SwFrm *pFrm, SwPageFrm *pPage )
1059 {
1060     for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
1061     {
1062         SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
1063         const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1064         if ( rAnch.GetCntntAnchor() &&
1065              (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
1066         {
1067             const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
1068             //Wird ein Rahmen oder ein SdrObject beschrieben?
1069             const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
1070             // OD 23.06.2003 #108784# - append also drawing objects anchored
1071             // as character.
1072             const bool bDrawObjInCntnt = bSdrObj &&
1073                                          (rAnch.GetAnchorId() == FLY_AS_CHAR);
1074 
1075             if( bFlyAtFly ||
1076                 (rAnch.GetAnchorId() == FLY_AT_PARA) ||
1077                 (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
1078                 bDrawObjInCntnt )
1079             {
1080                 SdrObject* pSdrObj = 0;
1081                 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
1082                 {
1083                     ASSERT( !bSdrObj, "DrawObject not found." );
1084                     pFmt->GetDoc()->DelFrmFmt( pFmt );
1085                     --i;
1086                     continue;
1087                 }
1088                 if ( pSdrObj )
1089                 {
1090                     if ( !pSdrObj->GetPage() )
1091                     {
1092                         pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1093                                 InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
1094                     }
1095 
1096                     SwDrawContact* pNew =
1097                         static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
1098                     if ( !pNew->GetAnchorFrm() )
1099                     {
1100                         pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
1101                     }
1102                     // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1103                     // if necessary. But control objects have to be excluded.
1104                     else if ( !::CheckControlLayer( pSdrObj ) &&
1105                               pNew->GetAnchorFrm() != pFrm &&
1106                               !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
1107                     {
1108                         SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
1109                         pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
1110 
1111                         // for repaint, use new ActionChanged()
1112                         // pDrawVirtObj->SendRepaintBroadcast();
1113                         pDrawVirtObj->ActionChanged();
1114                     }
1115 
1116                 }
1117                 else
1118                 {
1119                     SwFlyFrm *pFly;
1120                     if( bFlyAtFly )
1121                         pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1122                     else
1123                         pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1124                     pFly->Lock();
1125                     pFrm->AppendFly( pFly );
1126                     pFly->Unlock();
1127                     if ( pPage )
1128                         ::RegistFlys( pPage, pFly );
1129                 }
1130             }
1131         }
1132     }
1133 }
1134 
1135 bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
1136 {
1137     SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
1138     if ( RES_FLYFRMFMT == pFmt->Which() )
1139     {
1140         const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
1141         const SwFlyFrm* pTmpFrm;
1142         for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
1143         {
1144             if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
1145                 return true;
1146         }
1147     }
1148     else
1149     {
1150         SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
1151         if ( pContact )
1152             return pContact->GetAnchorFrm() != 0;
1153     }
1154     return false;
1155 }
1156 
1157 /** helper method to determine, if a <SwFrmFmt>, which has an object connected,
1158     is located in header or footer.
1159 
1160     OD 23.06.2003 #108784#
1161 
1162     @author OD
1163 */
1164 bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
1165 {
1166     bool bRetVal = false;
1167 
1168     const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
1169 
1170     if (rAnch.GetAnchorId() != FLY_AT_PAGE)
1171     {
1172         bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
1173     }
1174 
1175     return bRetVal;
1176 }
1177 
1178 void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib )
1179 {
1180     //Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
1181     //Layout.
1182     //Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate
1183     //uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch
1184     //Objecte die in zeichengebundenen verankert sind.
1185 
1186     SwSpzFrmFmts aCpy( 255, 255 );
1187     aCpy.Insert( pTbl, 0 );
1188 
1189     sal_uInt16 nOldCnt = USHRT_MAX;
1190 
1191     while ( aCpy.Count() && aCpy.Count() != nOldCnt )
1192     {
1193         nOldCnt = aCpy.Count();
1194         for ( int i = 0; i < int(aCpy.Count()); ++i )
1195         {
1196             SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
1197             const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1198             sal_Bool bRemove = sal_False;
1199             if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
1200                 (rAnch.GetAnchorId() == FLY_AS_CHAR))
1201             {
1202                 //Seitengebunde sind bereits verankert, zeichengebundene
1203                 //will ich hier nicht.
1204                 bRemove = sal_True;
1205             }
1206             else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
1207                       ::lcl_InHeaderOrFooter( *pFmt ) )
1208             {
1209             // OD 23.06.2003 #108784# - correction: for objects in header
1210             // or footer create frames, in spite of the fact that an connected
1211             // objects already exists.
1212                 //Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
1213                 //keine abhaengigen Existieren, andernfalls, oder wenn das
1214                 //MakeFrms keine abhaengigen erzeugt, entfernen.
1215                 pFmt->MakeFrms();
1216                 bRemove = ::lcl_ObjConnected( pFmt, pSib );
1217             }
1218             if ( bRemove )
1219             {
1220                 aCpy.Remove( sal_uInt16(i) );
1221                 --i;
1222             }
1223         }
1224     }
1225     aCpy.Remove( 0, aCpy.Count() );
1226 }
1227 
1228 /** local method to set 'working' position for newly inserted frames
1229 
1230     OD 12.08.2003 #i17969#
1231 
1232     @author OD
1233 */
1234 void lcl_SetPos( SwFrm&             _rNewFrm,
1235                  const SwLayoutFrm& _rLayFrm )
1236 {
1237     SWRECTFN( (&_rLayFrm) )
1238     (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
1239     // move position by one SwTwip in text flow direction in order to get
1240     // notifications for a new calculated position after its formatting.
1241     if ( bVert )
1242         _rNewFrm.Frm().Pos().X() -= 1;
1243     else
1244         _rNewFrm.Frm().Pos().Y() += 1;
1245 }
1246 
1247 void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
1248                              sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
1249                              SwFrm *pPrv )
1250 {
1251     pDoc->BlockIdling();
1252     SwRootFrm* pLayout = pLay->getRootFrm();
1253     const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
1254     if( bOldCallbackActionEnabled )
1255         pLayout->SetCallbackActionEnabled( sal_False );
1256 
1257     //Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann
1258     //werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
1259     //und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
1260     //angelegt.
1261     //Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
1262     //Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
1263     //lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
1264     //ertraegliches mass reduziert hat.
1265     //Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
1266     //Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach
1267     //Node noch etwas drauf.
1268     //Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist
1269     //(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
1270     //ausgegengen.
1271     const sal_Bool bStartPercent = bPages && !nEndIndex;
1272 
1273     SwPageFrm *pPage = pLay->FindPageFrm();
1274     const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1275     SwFrm       *pFrm = 0;
1276     sal_Bool   bBreakAfter   = sal_False;
1277 
1278     SwActualSection *pActualSection = 0;
1279     SwLayHelper *pPageMaker;
1280 
1281     //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress
1282     //an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
1283     //passiert erst am Ende der Funktion.
1284     if ( bPages )
1285     {
1286         // Attention: the SwLayHelper class uses references to the content-,
1287         // page-, layout-frame etc. and may change them!
1288         pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
1289                 pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
1290         if( bStartPercent )
1291         {
1292             const sal_uLong nPageCount = pPageMaker->CalcPageCount();
1293             if( nPageCount )
1294                 bObjsDirect = sal_False;
1295         }
1296     }
1297     else
1298         pPageMaker = NULL;
1299 
1300     if( pLay->IsInSct() &&
1301         ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
1302             // abgefangen, deren Flags noch nicht ermittelt werden koennen,
1303             // so z.B. beim Einfuegen einer Tabelle
1304     {
1305         SwSectionFrm* pSct = pLay->FindSctFrm();
1306         // Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
1307         // Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
1308         // Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
1309         // Kandidat fuer pActualSection.
1310         // Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
1311         // eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
1312         // aufgebrochen werden.
1313         if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
1314             ( !pLay->IsInTab() || pSct->IsInTab() ) )
1315         {
1316             pActualSection = new SwActualSection( 0, pSct, 0 );
1317             ASSERT( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
1318                 "_InsertCnt: Wrong Call" );
1319         }
1320     }
1321 
1322     //If a section is "open", the pActualSection points to an SwActualSection.
1323     //If the page breaks, for "open" sections a follow will created.
1324     //For nested sections (which have, however, not a nested layout),
1325     //the SwActualSection class has a member, which points to an upper(section).
1326     //When the "inner" section finishs, the upper will used instead.
1327 
1328     while( sal_True )
1329     {
1330         SwNode *pNd = pDoc->GetNodes()[nIndex];
1331         if ( pNd->IsCntntNode() )
1332         {
1333             SwCntntNode* pNode = (SwCntntNode*)pNd;
1334             pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) :
1335                                         pNode->MakeFrm( pLay );
1336             if( pPageMaker )
1337                 pPageMaker->CheckInsert( nIndex );
1338 
1339             pFrm->InsertBehind( pLay, pPrv );
1340             // --> OD 2005-12-01 #i27138#
1341             // notify accessibility paragraphs objects about changed
1342             // CONTENT_FLOWS_FROM/_TO relation.
1343             // Relation CONTENT_FLOWS_FROM for next paragraph will change
1344             // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1345             if ( pFrm->IsTxtFrm() )
1346             {
1347                 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1348                 // no notification, if <ViewShell> is in construction
1349                 if ( pViewShell && !pViewShell->IsInConstructor() &&
1350                      pViewShell->GetLayout() &&
1351                      pViewShell->GetLayout()->IsAnyShellAccessible() )
1352                 {
1353                     pViewShell->InvalidateAccessibleParaFlowRelation(
1354                         dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1355                         dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1356                     // --> OD 2006-08-28 #i68958#
1357                     // The information flags of the text frame are validated
1358                     // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1359                     // The information flags have to be invalidated, because
1360                     // it is possible, that the one of its upper frames
1361                     // isn't inserted into the layout.
1362                     pFrm->InvalidateInfFlags();
1363                     // <--
1364                 }
1365             }
1366             // <--
1367             // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1368             // for setting position at newly inserted frame
1369             lcl_SetPos( *pFrm, *pLay );
1370             pPrv = pFrm;
1371 
1372             if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1373                 AppendObjs( pTbl, nIndex, pFrm, pPage );
1374         }
1375         else if ( pNd->IsTableNode() )
1376         {   //Sollten wir auf eine Tabelle gestossen sein?
1377             SwTableNode *pTblNode = (SwTableNode*)pNd;
1378 
1379             // #108116# loading may produce table structures that GCLines
1380             // needs to clean up. To keep table formulas correct, change
1381             // all table formulas to internal (BOXPTR) representation.
1382             SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
1383             aMsgHnt.eFlags = TBL_BOXPTR;
1384             pDoc->UpdateTblFlds( &aMsgHnt );
1385             pTblNode->GetTable().GCLines();
1386 
1387             pFrm = pTblNode->MakeFrm( pLay );
1388 
1389             if( pPageMaker )
1390                 pPageMaker->CheckInsert( nIndex );
1391 
1392             pFrm->InsertBehind( pLay, pPrv );
1393             // --> OD 2005-12-01 #i27138#
1394             // notify accessibility paragraphs objects about changed
1395             // CONTENT_FLOWS_FROM/_TO relation.
1396             // Relation CONTENT_FLOWS_FROM for next paragraph will change
1397             // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1398             {
1399                 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1400                 // no notification, if <ViewShell> is in construction
1401                 if ( pViewShell && !pViewShell->IsInConstructor() &&
1402                      pViewShell->GetLayout() &&
1403                      pViewShell->GetLayout()->IsAnyShellAccessible() )
1404                 {
1405                     pViewShell->InvalidateAccessibleParaFlowRelation(
1406                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1407                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1408                 }
1409             }
1410             // <--
1411             if ( bObjsDirect && pTbl->Count() )
1412                 ((SwTabFrm*)pFrm)->RegistFlys();
1413             // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1414             // for setting position at newly inserted frame
1415             lcl_SetPos( *pFrm, *pLay );
1416 
1417             pPrv = pFrm;
1418             //Index auf den Endnode der Tabellensection setzen.
1419             nIndex = pTblNode->EndOfSectionIndex();
1420 
1421             SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
1422             while ( pTmpFrm )
1423             {
1424                 pTmpFrm->CheckDirChange();
1425                 pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
1426             }
1427 
1428         }
1429         else if ( pNd->IsSectionNode() )
1430         {
1431             SwSectionNode *pNode = (SwSectionNode*)pNd;
1432             if( pNode->GetSection().CalcHiddenFlag() )
1433                 // ist versteckt, ueberspringe den Bereich
1434                 nIndex = pNode->EndOfSectionIndex();
1435             else
1436             {
1437                 pFrm = pNode->MakeFrm( pLay );
1438                 pActualSection = new SwActualSection( pActualSection,
1439                                                 (SwSectionFrm*)pFrm, pNode );
1440                 if ( pActualSection->GetUpper() )
1441                 {
1442                     //Hinter den Upper einsetzen, beim EndNode wird der "Follow"
1443                     //des Uppers erzeugt.
1444                     SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
1445                     pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
1446                     // OD 25.03.2003 #108339# - direct initialization of section
1447                     // after insertion in the layout
1448                     static_cast<SwSectionFrm*>(pFrm)->Init();
1449                 }
1450                 else
1451                 {
1452                     pFrm->InsertBehind( pLay, pPrv );
1453                     // OD 25.03.2003 #108339# - direct initialization of section
1454                     // after insertion in the layout
1455                     static_cast<SwSectionFrm*>(pFrm)->Init();
1456 
1457                     // --> FME 2004-09-08 #i33963#
1458                     // Do not trust the IsInFtn flag. If we are currently
1459                     // building up a table, the upper of pPrv may be a cell
1460                     // frame, but the cell frame does not have an upper yet.
1461                     if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
1462                     // <--
1463                     {
1464                         if( pPrv->IsSctFrm() )
1465                             pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
1466                         if( pPrv && pPrv->IsTxtFrm() )
1467                             ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False );
1468                     }
1469                 }
1470                 // --> OD 2005-12-01 #i27138#
1471                 // notify accessibility paragraphs objects about changed
1472                 // CONTENT_FLOWS_FROM/_TO relation.
1473                 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1474                 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1475                 {
1476                     ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1477                     // no notification, if <ViewShell> is in construction
1478                     if ( pViewShell && !pViewShell->IsInConstructor() &&
1479                          pViewShell->GetLayout() &&
1480                          pViewShell->GetLayout()->IsAnyShellAccessible() )
1481                     {
1482                         pViewShell->InvalidateAccessibleParaFlowRelation(
1483                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1484                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1485                     }
1486                 }
1487                 // <--
1488                 pFrm->CheckDirChange();
1489 
1490                 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1491                 // for setting position at newly inserted frame
1492                 lcl_SetPos( *pFrm, *pLay );
1493 
1494                 // OD 20.11.2002 #105405# - no page, no invalidate.
1495                 if ( pPage )
1496                 {
1497                     // OD 18.09.2002 #100522#
1498                     // invalidate page in order to force format and paint of
1499                     // inserted section frame
1500                     pFrm->InvalidatePage( pPage );
1501 
1502                     // FME 10.11.2003 #112243#
1503                     // Invalidate fly content flag:
1504                     if ( pFrm->IsInFly() )
1505                         pPage->InvalidateFlyCntnt();
1506 
1507                     // OD 14.11.2002 #104684# - invalidate page content in order to
1508                     // force format and paint of section content.
1509                     pPage->InvalidateCntnt();
1510                 }
1511 
1512                 pLay = (SwLayoutFrm*)pFrm;
1513                 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1514                     pLay = pLay->GetNextLayoutLeaf();
1515                 pPrv = 0;
1516             }
1517         }
1518         else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
1519         {
1520             ASSERT( pActualSection, "Sectionende ohne Anfang?" );
1521             ASSERT( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
1522                             "Sectionende mit falschen Start Node?" );
1523 
1524             //Section schliessen, ggf. die umgebende Section wieder
1525             //aktivieren.
1526             SwActualSection *pTmp = pActualSection->GetUpper();
1527             delete pActualSection;
1528             pLay = pLay->FindSctFrm();
1529             if ( 0 != (pActualSection = pTmp) )
1530             {
1531                 //Koennte noch sein, das der letzte SectionFrm leer geblieben
1532                 //ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
1533                 if ( !pLay->ContainsCntnt() )
1534                 {
1535                     SwFrm *pTmpFrm = pLay;
1536                     pLay = pTmpFrm->GetUpper();
1537                     pPrv = pTmpFrm->GetPrev();
1538                     pTmpFrm->Remove();
1539                     delete pTmpFrm;
1540                 }
1541                 else
1542                 {
1543                     pPrv = pLay;
1544                     pLay = pLay->GetUpper();
1545                 }
1546 
1547                 // new section frame
1548                 pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
1549                 pFrm->InsertBehind( pLay, pPrv );
1550                 static_cast<SwSectionFrm*>(pFrm)->Init();
1551 
1552                 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1553                 // for setting position at newly inserted frame
1554                 lcl_SetPos( *pFrm, *pLay );
1555 
1556                 SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
1557 
1558                 // a follow has to be appended to the new section frame
1559                 SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
1560                 if ( pFollow )
1561                 {
1562                     pOuterSectionFrm->SetFollow( NULL );
1563                     pOuterSectionFrm->InvalidateSize();
1564                     ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
1565                 }
1566 
1567                 // Wir wollen keine leeren Teile zuruecklassen
1568                 if( ! pOuterSectionFrm->IsColLocked() &&
1569                     ! pOuterSectionFrm->ContainsCntnt() )
1570                 {
1571                     pOuterSectionFrm->DelEmpty( sal_True );
1572                     delete pOuterSectionFrm;
1573                 }
1574                 pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
1575 
1576                 pLay = (SwLayoutFrm*)pFrm;
1577                 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1578                     pLay = pLay->GetNextLayoutLeaf();
1579                 pPrv = 0;
1580             }
1581             else
1582             {
1583                 //Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
1584                 //weiter.
1585                 pPrv = pLay;
1586                 pLay = pLay->GetUpper();
1587             }
1588         }
1589         else if( pNd->IsStartNode() &&
1590                  SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() )
1591         {
1592             if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1593             {
1594                 SwFlyFrm* pFly = pLay->FindFlyFrm();
1595                 if( pFly )
1596                     AppendObjs( pTbl, nIndex, pFly, pPage );
1597             }
1598         }
1599         else
1600             // Weder Cntnt noch Tabelle noch Section,
1601             // also muessen wir fertig sein.
1602             break;
1603 
1604         ++nIndex;
1605         // Der Endnode wird nicht mehr mitgenommen, es muss vom
1606         // Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
1607         // des Bereichs vor dem EndIndex liegt!
1608         if ( nEndIndex && nIndex >= nEndIndex )
1609             break;
1610     }
1611 
1612     if ( pActualSection )
1613     {
1614         //Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
1615         if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
1616         {
1617             pLay->Remove();
1618             delete pLay;
1619         }
1620         delete pActualSection;
1621     }
1622 
1623     if ( bPages )       //Jetzt noch die Flys verbinden lassen.
1624     {
1625         if ( !bDontCreateObjects )
1626             AppendAllObjs( pTbl, pLayout );
1627         bObjsDirect = sal_True;
1628     }
1629 
1630     if( pPageMaker )
1631     {
1632         pPageMaker->CheckFlyCache( pPage );
1633         delete pPageMaker;
1634         if( pDoc->GetLayoutCache() )
1635         {
1636 #ifdef DBG_UTIL
1637 #if OSL_DEBUG_LEVEL > 1
1638             pDoc->GetLayoutCache()->CompareLayout( *pDoc );
1639 #endif
1640 #endif
1641             pDoc->GetLayoutCache()->ClearImpl();
1642         }
1643     }
1644 
1645     pDoc->UnblockIdling();
1646     if( bOldCallbackActionEnabled )
1647         pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
1648 }
1649 
1650 
1651 void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
1652                const SwNodeIndex &rEndIdx )
1653 {
1654     bObjsDirect = sal_False;
1655 
1656     SwNodeIndex aTmp( rSttIdx );
1657     sal_uLong nEndIdx = rEndIdx.GetIndex();
1658     SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
1659                                             pDoc->GetNodes()[ nEndIdx-1 ]);
1660     if ( pNd )
1661     {
1662         sal_Bool bApres = aTmp < rSttIdx;
1663         SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
1664         SwFrm* pFrm;
1665         while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1666         {
1667             SwLayoutFrm *pUpper = pFrm->GetUpper();
1668             SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
1669             sal_Bool bOldLock, bOldFtn;
1670             if( pFtnFrm )
1671             {
1672                 bOldFtn = pFtnFrm->IsColLocked();
1673                 pFtnFrm->ColLock();
1674             }
1675             else
1676                 bOldFtn = sal_True;
1677             SwSectionFrm* pSct = pUpper->FindSctFrm();
1678             // Es sind innerhalb von Fussnoten nur die Bereiche interessant,
1679             // die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
1680             // in denen die Fussnoten(Container) liegen.
1681             // #109767# Table frame is in section, insert section in cell frame.
1682             if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
1683                 pSct = NULL;
1684             if( pSct )
1685             {   // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
1686                 bOldLock = pSct->IsColLocked();
1687                 pSct->ColLock();
1688             }
1689             else
1690                 bOldLock = sal_True;
1691 
1692             // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
1693             // auf die naechste Seite schieben. Innerhalb eines Rahmens auch
1694             // nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
1695             // Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
1696             sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
1697             sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
1698                  (!pFrm->IsInTab() || pFrm->IsTabFrm() );
1699             if ( bMoveNext && bAllowMove )
1700             {
1701                 SwFrm *pMove = pFrm;
1702                 SwFrm *pPrev = pFrm->GetPrev();
1703                 SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
1704                 ASSERT( pTmp, "Missing FlowFrm" );
1705 
1706                 if ( bApres )
1707                 {
1708                     // Wir wollen, dass der Rest der Seite leer ist, d.h.
1709                     // der naechste muss auf die naechste Seite wandern.
1710                     // Dieser kann auch in der naechsten Spalte stehen!
1711                     ASSERT( !pTmp->HasFollow(), "Follows forbidden" );
1712                     pPrev = pFrm;
1713                     // Wenn unser umgebender SectionFrm einen Next besitzt,
1714                     // so soll dieser ebenfalls gemoved werden!
1715                     pMove = pFrm->GetIndNext();
1716                     SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
1717                     if( pCol )
1718                         pCol = (SwColumnFrm*)pCol->GetNext();
1719                     do
1720                     {
1721                         if( pCol && !pMove )
1722                         {   // Bisher haben wir keinen Nachfolger gefunden
1723                             // jetzt gucken wir in die naechste Spalte
1724                             pMove = pCol->ContainsAny();
1725                             if( pCol->GetNext() )
1726                                 pCol = (SwColumnFrm*)pCol->GetNext();
1727                             else if( pCol->IsInSct() )
1728                             {   // Wenn es keine naechste Spalte gibt, wir aber
1729                                 // innerhalb eines spaltigen Bereichs sind,
1730                                 // koennte es noch ausserhalb des Bereich
1731                                 // (Seiten-)Spalten geben
1732                                 pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
1733                                 if( pCol )
1734                                     pCol = (SwColumnFrm*)pCol->GetNext();
1735                             }
1736                             else
1737                                 pCol = NULL;
1738                         }
1739                         // Falls hier verschrottete SectionFrms herumgammeln,
1740                         // muessen diese uebersprungen werden.
1741                         while( pMove && pMove->IsSctFrm() &&
1742                                !((SwSectionFrm*)pMove)->GetSection() )
1743                             pMove = pMove->GetNext();
1744                     } while( !pMove && pCol );
1745 
1746                     if( pMove )
1747                     {
1748                         if ( pMove->IsCntntFrm() )
1749                             pTmp = (SwCntntFrm*)pMove;
1750                         else if ( pMove->IsTabFrm() )
1751                             pTmp = (SwTabFrm*)pMove;
1752                         else if ( pMove->IsSctFrm() )
1753                         {
1754                             pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1755                             if( pMove )
1756                                 pTmp = SwFlowFrm::CastFlowFrm( pMove );
1757                             else
1758                                 pTmp = NULL;
1759                         }
1760                     }
1761                     else
1762                         pTmp = 0;
1763                 }
1764                 else
1765                 {
1766                     ASSERT( !pTmp->IsFollow(), "Follows really forbidden" );
1767                     // Bei Bereichen muss natuerlich der Inhalt auf die Reise
1768                     // geschickt werden.
1769                     if( pMove->IsSctFrm() )
1770                     {
1771                         while( pMove && pMove->IsSctFrm() &&
1772                                !((SwSectionFrm*)pMove)->GetSection() )
1773                             pMove = pMove->GetNext();
1774                         if( pMove && pMove->IsSctFrm() )
1775                             pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1776                         if( pMove )
1777                             pTmp = SwFlowFrm::CastFlowFrm( pMove );
1778                         else
1779                             pTmp = NULL;
1780                     }
1781                 }
1782 
1783                 if( pTmp )
1784                 {
1785                     SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
1786                     // MoveFwd==sal_True bedeutet, dass wir auf der gleichen
1787                     // Seite geblieben sind, wir wollen aber die Seite wechseln,
1788                     // sofern dies moeglich ist
1789                     sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
1790                     pTmp->LockJoin();
1791                     while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
1792                     {
1793                         if( pOldUp == pTmp->GetFrm()->GetUpper() )
1794                             break;
1795                         pOldUp = pTmp->GetFrm()->GetUpper();
1796                     }
1797                     if( !bTmpOldLock )
1798                         pTmp->UnlockJoin();
1799                 }
1800                 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
1801                               pFrm->IsInDocBody(), nEndIdx, pPrev );
1802             }
1803             else
1804             {
1805                 sal_Bool bSplit;
1806                 SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
1807                 // Wenn in einen SectionFrm ein anderer eingefuegt wird,
1808                 // muss dieser aufgebrochen werden
1809                 if( pSct && rSttIdx.GetNode().IsSectionNode() )
1810                 {
1811                     bSplit = pSct->SplitSect( pFrm, bApres );
1812                     // Wenn pSct nicht aufgespalten werden konnte
1813                     if( !bSplit && !bApres )
1814                     {
1815                         pUpper = pSct->GetUpper();
1816                         pPrv = pSct->GetPrev();
1817                     }
1818                 }
1819                 else
1820                     bSplit = sal_False;
1821                 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
1822                               nEndIdx, pPrv );
1823                 // OD 23.06.2003 #108784# - correction: append objects doesn't
1824                 // depend on value of <bAllowMove>
1825                 if( !bDontCreateObjects )
1826                 {
1827                     const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1828                     if( pTbl->Count() )
1829                         AppendAllObjs( pTbl, pUpper );
1830                 }
1831 
1832                 // Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
1833                 // muss das Splitten rueckgaengig gemacht werden
1834                 if( bSplit && pSct && pSct->GetNext()
1835                     && pSct->GetNext()->IsSctFrm() )
1836                     pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
1837                 if( pFrm->IsInFly() )
1838                     pFrm->FindFlyFrm()->_Invalidate();
1839                 if( pFrm->IsInTab() )
1840                     pFrm->InvalidateSize();
1841             }
1842 
1843             SwPageFrm *pPage = pUpper->FindPageFrm();
1844             SwFrm::CheckPageDescs( pPage, sal_False );
1845             if( !bOldFtn )
1846                 pFtnFrm->ColUnlock();
1847             if( !bOldLock )
1848             {
1849                 pSct->ColUnlock();
1850                 // Zum Beispiel beim Einfuegen von gelinkten Bereichen,
1851                 // die wiederum Bereiche enthalten, kann pSct jetzt leer sein
1852                 // und damit ruhig zerstoert werden.
1853                 if( !pSct->ContainsCntnt() )
1854                 {
1855                     pSct->DelEmpty( sal_True );
1856                     pUpper->getRootFrm()->RemoveFromList( pSct );
1857                     delete pSct;
1858                 }
1859             }
1860         }
1861     }
1862 
1863     bObjsDirect = sal_True;
1864 }
1865 
1866 
1867 /*************************************************************************/
1868 
1869 SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
1870     SwCacheObj( pMod ),
1871     rAttrSet( pConstructor->IsCntntFrm()
1872                     ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
1873                     : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
1874     rUL     ( rAttrSet.GetULSpace() ),
1875     // --> OD 2008-12-04 #i96772#
1876     // LRSpaceItem is copied due to the possibility that it is adjusted - see below
1877     rLR     ( rAttrSet.GetLRSpace() ),
1878     // <--
1879     rBox    ( rAttrSet.GetBox()     ),
1880     rShadow ( rAttrSet.GetShadow()  ),
1881     aFrmSize( rAttrSet.GetFrmSize().GetSize() )
1882 {
1883     // --> OD 2008-12-02 #i96772#
1884     const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
1885     if ( pTxtFrm )
1886     {
1887         pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
1888     }
1889 
1890     //Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
1891     //nicht initialisiert!
1892 
1893     //Muessen alle einmal berechnet werden:
1894     bTopLine = bBottomLine = bLeftLine = bRightLine =
1895     bTop     = bBottom     = bLine   = sal_True;
1896 
1897     bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
1898     // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
1899     // and <bJoinedWithNext>, which aren't initialized by default.
1900     bCachedJoinedWithPrev = sal_False;
1901     bCachedJoinedWithNext = sal_False;
1902 
1903     bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
1904 }
1905 
1906 SwBorderAttrs::~SwBorderAttrs()
1907 {
1908     ((SwModify*)pOwner)->SetInCache( sal_False );
1909 }
1910 
1911 /*************************************************************************
1912 |*
1913 |*  SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
1914 |*
1915 |*  Beschreibung        Die Calc-Methoden errechnen zusaetzlich zu den
1916 |*      von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
1917 |*      der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
1918 |*      Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
1919 |*      groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
1920 |*
1921 |*************************************************************************/
1922 
1923 void SwBorderAttrs::_CalcTop()
1924 {
1925     nTop = CalcTopLine() + rUL.GetUpper();
1926     bTop = sal_False;
1927 }
1928 
1929 void SwBorderAttrs::_CalcBottom()
1930 {
1931     nBottom = CalcBottomLine() + rUL.GetLower();
1932     bBottom = sal_False;
1933 }
1934 
1935 long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
1936 {
1937     long nRight;
1938 
1939     // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1940     // and right border are painted on the right respectively left.
1941     if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1942         nRight = CalcLeftLine();
1943     else
1944         nRight = CalcRightLine();
1945 
1946     // for paragraphs, "left" is "before text" and "right" is "after text"
1947     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1948         nRight += rLR.GetLeft();
1949     else
1950         nRight += rLR.GetRight();
1951 
1952     // --> OD 2008-01-21 #newlistlevelattrs#
1953     // correction: retrieve left margin for numbering in R2L-layout
1954     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1955     {
1956         nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1957     }
1958     // <--
1959 
1960     return nRight;
1961 }
1962 
1963 long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
1964 {
1965     long nLeft;
1966 
1967     // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1968     // and right border are painted on the right respectively left.
1969     if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1970         nLeft = CalcRightLine();
1971     else
1972         nLeft = CalcLeftLine();
1973 
1974     // for paragraphs, "left" is "before text" and "right" is "after text"
1975     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1976         nLeft += rLR.GetRight();
1977     else
1978         nLeft += rLR.GetLeft();
1979 
1980     // --> OD 2008-01-21 #newlistlevelattrs#
1981     // correction: do not retrieve left margin for numbering in R2L-layout
1982 //    if ( pCaller->IsTxtFrm() )
1983     if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
1984     // <--
1985     {
1986         nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1987     }
1988 
1989     return nLeft;
1990 }
1991 
1992 /*************************************************************************
1993 |*
1994 |*  SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
1995 |*                 CalcLeftLine(), CalcRightLine()
1996 |*
1997 |*  Beschreibung        Berechnung der Groessen fuer Umrandung und Schatten.
1998 |*                      Es kann auch ohne Linien ein Abstand erwuenscht sein,
1999 |*                      dieser wird  dann nicht vom Attribut sondern hier
2000 |*                      beruecksichtigt (bBorderDist, z.B. fuer Zellen).
2001 |*
2002 |*************************************************************************/
2003 
2004 void SwBorderAttrs::_CalcTopLine()
2005 {
2006     nTopLine = (bBorderDist && !rBox.GetTop())
2007                             ? rBox.GetDistance  (BOX_LINE_TOP)
2008                             : rBox.CalcLineSpace(BOX_LINE_TOP);
2009     nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
2010     bTopLine = sal_False;
2011 }
2012 
2013 void SwBorderAttrs::_CalcBottomLine()
2014 {
2015     nBottomLine = (bBorderDist && !rBox.GetBottom())
2016                             ? rBox.GetDistance  (BOX_LINE_BOTTOM)
2017                             : rBox.CalcLineSpace(BOX_LINE_BOTTOM);
2018     nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
2019     bBottomLine = sal_False;
2020 }
2021 
2022 void SwBorderAttrs::_CalcLeftLine()
2023 {
2024     nLeftLine = (bBorderDist && !rBox.GetLeft())
2025                             ? rBox.GetDistance  (BOX_LINE_LEFT)
2026                             : rBox.CalcLineSpace(BOX_LINE_LEFT);
2027     nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
2028     bLeftLine = sal_False;
2029 }
2030 
2031 void SwBorderAttrs::_CalcRightLine()
2032 {
2033     nRightLine = (bBorderDist && !rBox.GetRight())
2034                             ? rBox.GetDistance  (BOX_LINE_RIGHT)
2035                             : rBox.CalcLineSpace(BOX_LINE_RIGHT);
2036     nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
2037     bRightLine = sal_False;
2038 }
2039 
2040 /*************************************************************************/
2041 
2042 void SwBorderAttrs::_IsLine()
2043 {
2044     bIsLine = rBox.GetTop() || rBox.GetBottom() ||
2045               rBox.GetLeft()|| rBox.GetRight();
2046     bLine = sal_False;
2047 }
2048 
2049 /*************************************************************************
2050 |*
2051 |*  SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
2052 |*
2053 |*      Die Umrandungen benachbarter Absaetze werden nach folgendem
2054 |*      Algorithmus zusammengefasst:
2055 |*
2056 |*      1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
2057 |*         Umrandung oben aufweist und 3. Zutrifft.
2058 |*         Zusaetzlich muss der Absatz mindestens rechts oder links oder
2059 |*         unten eine Umrandung haben.
2060 |*      2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
2061 |*         Umrandung untern aufweist und 3. Zustrifft.
2062 |*         Zusaetzlich muss der Absatz mindestens rechts oder links oder
2063 |*         oben eine Umrandung haben.
2064 |*      3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
2065 |*         sind identisch.
2066 |*
2067 |*************************************************************************/
2068 inline int CmpLines( const SvxBorderLine *pL1, const SvxBorderLine *pL2 )
2069 {
2070     return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
2071 }
2072 
2073 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2074 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2075 //          instead of only the right LR-spacing, because R2L-layout has to be
2076 //          considered.
2077 sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
2078                                   const SwFrm *pCaller,
2079                                   const SwFrm *pCmp ) const
2080 {
2081     return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft()  ) &&
2082              CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
2083              CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
2084              // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2085              CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
2086 }
2087 
2088 sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
2089                                   const SwFrm& _rCmpFrm ) const
2090 {
2091     sal_Bool bReturnVal = sal_False;
2092 
2093     SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
2094     const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
2095     if ( rShadow == rCmpAttrs.GetShadow() &&
2096          CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
2097          CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
2098          CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
2099        )
2100     {
2101         bReturnVal = sal_True;
2102     }
2103 
2104     return bReturnVal;
2105 }
2106 
2107 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2108 // previous frame. Calculated value saved in cached value <bJoinedWithPrev>
2109 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
2110 void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
2111                                          const SwFrm* _pPrevFrm )
2112 {
2113     // set default
2114     bJoinedWithPrev = sal_False;
2115 
2116     if ( _rFrm.IsTxtFrm() )
2117     {
2118         // text frame can potentially join with previous text frame, if
2119         // corresponding attribute set is set at previous text frame.
2120         // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
2121         // one as previous frame.
2122         const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
2123         // OD 2004-02-13 #i25029# - skip hidden text frames.
2124         while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2125                 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
2126         {
2127             pPrevFrm = pPrevFrm->GetPrev();
2128         }
2129         if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2130              pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
2131            )
2132         {
2133             bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
2134         }
2135     }
2136 
2137     // valid cache status, if demanded
2138     // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
2139     // is set.
2140     bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
2141 }
2142 
2143 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2144 // next frame. Calculated value saved in cached value <bJoinedWithNext>
2145 void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
2146 {
2147     // set default
2148     bJoinedWithNext = sal_False;
2149 
2150     if ( _rFrm.IsTxtFrm() )
2151     {
2152         // text frame can potentially join with next text frame, if
2153         // corresponding attribute set is set at current text frame.
2154         // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2155         const SwFrm* pNextFrm = _rFrm.GetNext();
2156         while ( pNextFrm && pNextFrm->IsTxtFrm() &&
2157                 static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
2158         {
2159             pNextFrm = pNextFrm->GetNext();
2160         }
2161         if ( pNextFrm && pNextFrm->IsTxtFrm() &&
2162              _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
2163            )
2164         {
2165             bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
2166         }
2167     }
2168 
2169     // valid cache status, if demanded
2170     bCachedJoinedWithNext = bCacheGetLine;
2171 }
2172 
2173 // OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
2174 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
2175 // method <_CalcJoindWithPrev(..)>.
2176 sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
2177                                     const SwFrm* _pPrevFrm ) const
2178 {
2179     if ( !bCachedJoinedWithPrev || _pPrevFrm )
2180     {
2181         // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
2182         const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
2183     }
2184 
2185     return bJoinedWithPrev;
2186 }
2187 
2188 sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
2189 {
2190     if ( !bCachedJoinedWithNext )
2191     {
2192         const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
2193     }
2194 
2195     return bJoinedWithNext;
2196 }
2197 
2198 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
2199 // method <JoinedWithPrev>
2200 void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
2201                                  const SwFrm* _pPrevFrm )
2202 {
2203     sal_uInt16 nRet = CalcTopLine();
2204 
2205     // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2206     // OD 2004-02-26 #i25029# - add 2nd parameter
2207     if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
2208     {
2209         nRet = 0;
2210     }
2211 
2212     bCachedGetTopLine = bCacheGetLine;
2213 
2214     nGetTopLine = nRet;
2215 }
2216 
2217 void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
2218 {
2219     sal_uInt16 nRet = CalcBottomLine();
2220 
2221     // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2222     if ( JoinedWithNext( _rFrm ) )
2223     {
2224         nRet = 0;
2225     }
2226 
2227     bCachedGetBottomLine = bCacheGetLine;
2228 
2229     nGetBottomLine = nRet;
2230 }
2231 
2232 /*************************************************************************/
2233 
2234 SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
2235     SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
2236                                 (void*)((SwCntntFrm*)pFrm)->GetNode() :
2237                                 (void*)((SwLayoutFrm*)pFrm)->GetFmt()),
2238                            (sal_Bool)(pFrm->IsCntntFrm() ?
2239                 ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
2240                 ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
2241     pConstructor( pFrm )
2242 {
2243 }
2244 
2245 /*************************************************************************/
2246 
2247 SwCacheObj *SwBorderAttrAccess::NewObj()
2248 {
2249     ((SwModify*)pOwner)->SetInCache( sal_True );
2250     return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
2251 }
2252 
2253 SwBorderAttrs *SwBorderAttrAccess::Get()
2254 {
2255     return (SwBorderAttrs*)SwCacheAccess::Get();
2256 }
2257 
2258 /*************************************************************************/
2259 
2260 SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
2261     pPage( pPg ),
2262     pCurrent( 0 ),
2263     bFlysOnly( bFlys )
2264 {
2265 }
2266 
2267 /*************************************************************************/
2268 
2269 const SdrObject *SwOrderIter::Top()
2270 {
2271     pCurrent = 0;
2272     if ( pPage->GetSortedObjs() )
2273     {
2274         sal_uInt32 nTopOrd = 0;
2275         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2276         if ( pObjs->Count() )
2277         {
2278             (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
2279             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2280             {
2281                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2282                 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2283                     continue;
2284                 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2285                 if ( nTmp >= nTopOrd )
2286                 {
2287                     nTopOrd = nTmp;
2288                     pCurrent = pObj;
2289                 }
2290             }
2291         }
2292     }
2293     return pCurrent;
2294 }
2295 
2296 /*************************************************************************/
2297 
2298 const SdrObject *SwOrderIter::Bottom()
2299 {
2300     pCurrent = 0;
2301     if ( pPage->GetSortedObjs() )
2302     {
2303         sal_uInt32 nBotOrd = USHRT_MAX;
2304         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2305         if ( pObjs->Count() )
2306         {
2307             (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
2308             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2309             {
2310                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2311                 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2312                     continue;
2313                 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2314                 if ( nTmp < nBotOrd )
2315                 {
2316                     nBotOrd = nTmp;
2317                     pCurrent = pObj;
2318                 }
2319             }
2320         }
2321     }
2322     return pCurrent;
2323 }
2324 
2325 /*************************************************************************/
2326 
2327 const SdrObject *SwOrderIter::Next()
2328 {
2329     const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2330     pCurrent = 0;
2331     if ( pPage->GetSortedObjs() )
2332     {
2333         sal_uInt32 nOrd = USHRT_MAX;
2334         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2335         if ( pObjs->Count() )
2336         {
2337             (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
2338             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2339             {
2340                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2341                 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2342                     continue;
2343                 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2344                 if ( nTmp > nCurOrd && nTmp < nOrd )
2345                 {
2346                     nOrd = nTmp;
2347                     pCurrent = pObj;
2348                 }
2349             }
2350         }
2351     }
2352     return pCurrent;
2353 }
2354 
2355 /*************************************************************************/
2356 
2357 const SdrObject *SwOrderIter::Prev()
2358 {
2359     const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2360     pCurrent = 0;
2361     if ( pPage->GetSortedObjs() )
2362     {
2363         sal_uInt32 nOrd = 0;
2364         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2365         if ( pObjs->Count() )
2366         {
2367             (*pObjs)[0]->GetDrawObj()->GetOrdNum();  //Aktualisieren erzwingen!
2368             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2369             {
2370                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2371                 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2372                     continue;
2373                 sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2374                 if ( nTmp < nCurOrd && nTmp >= nOrd )
2375                 {
2376                     nOrd = nTmp;
2377                     pCurrent = pObj;
2378                 }
2379             }
2380         }
2381     }
2382     return pCurrent;
2383 }
2384 
2385 /*************************************************************************/
2386 
2387 //Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
2388 //restaurieren.
2389 //Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
2390 //die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
2391 //Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
2392 //Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
2393 //angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
2394 //die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
2395 //auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
2396 //Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
2397 //verboten.
2398 //Unterwegs werden die Flys bei der Seite abgemeldet.
2399 
2400 // --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
2401 // at-fly anchored objects from page
2402 void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
2403 {
2404     ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
2405     SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2406     for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2407     {
2408         SwAnchoredObject* pObj = rObjs[i];
2409         // --> OD 2004-11-29 #115759# - reset member, at which the anchored
2410         // object orients its vertical position
2411         pObj->ClearVertPosOrientFrm();
2412         // <--
2413         // --> OD 2005-03-03 #i43913#
2414         pObj->ResetLayoutProcessBools();
2415         // <--
2416         // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
2417         // anchored Writer fly frames from page
2418         if ( pObj->ISA(SwFlyFrm) )
2419         {
2420             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2421 
2422             // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
2423             // fly frame from page
2424             if ( pFlyFrm->GetDrawObjs() )
2425             {
2426                 ::lcl_RemoveObjsFromPage( pFlyFrm );
2427             }
2428             // <--
2429 
2430             SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
2431             while ( pCnt )
2432             {
2433                 if ( pCnt->GetDrawObjs() )
2434                     ::lcl_RemoveObjsFromPage( pCnt );
2435                 pCnt = pCnt->GetNextCntntFrm();
2436             }
2437             if ( pFlyFrm->IsFlyFreeFrm() )
2438             {
2439                 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2440                 pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
2441             }
2442         }
2443         // <--
2444         // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2445         else if ( pObj->ISA(SwAnchoredDrawObject) )
2446         {
2447             if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2448             {
2449                 pObj->GetPageFrm()->RemoveDrawObjFromPage(
2450                                 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2451             }
2452         }
2453         // <--
2454     }
2455 }
2456 
2457 SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
2458 {
2459     if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
2460         lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );
2461 
2462     SwFrm *pSav;
2463     if ( 0 == (pSav = pLay->ContainsAny()) )
2464         return 0;
2465 
2466     if( pSav->IsInFtn() && !pLay->IsInFtn() )
2467     {
2468         do
2469             pSav = pSav->FindNext();
2470         while( pSav && pSav->IsInFtn() );
2471         if( !pSav || !pLay->IsAnLower( pSav ) )
2472             return NULL;
2473     }
2474 
2475     // Tables should be saved as a whole, expection:
2476     // The contents of a section or a cell inside a table should be saved
2477     if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
2478         while ( !pSav->IsTabFrm() )
2479             pSav = pSav->GetUpper();
2480 
2481     if( pSav->IsInSct() )
2482     { // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
2483         SwFrm* pSect = pLay->FindSctFrm();
2484         SwFrm *pTmp = pSav;
2485         do
2486         {
2487             pSav = pTmp;
2488             pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
2489         } while ( pTmp != pSect );
2490     }
2491 
2492     SwFrm *pFloat = pSav;
2493     if( !pStart )
2494         pStart = pSav;
2495     sal_Bool bGo = pStart == pSav;
2496     do
2497     {
2498         if( bGo )
2499             pFloat->GetUpper()->pLower = 0;     //Die Teilkette ausklinken.
2500 
2501         //Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
2502         do
2503         {
2504             if( bGo )
2505             {
2506                 if ( pFloat->IsCntntFrm() )
2507                 {
2508                     if ( pFloat->GetDrawObjs() )
2509                         ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
2510                 }
2511                 else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
2512                 {
2513                     SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
2514                     if( pCnt )
2515                     {
2516                         do
2517                         {   if ( pCnt->GetDrawObjs() )
2518                                 ::lcl_RemoveObjsFromPage( pCnt );
2519                             pCnt = pCnt->GetNextCntntFrm();
2520                         } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
2521                     }
2522                 }
2523                 else {
2524                     ASSERT( !pFloat, "Neuer Float-Frame?" );
2525                 }
2526             }
2527             if ( pFloat->GetNext()  )
2528             {
2529                 if( bGo )
2530                     pFloat->pUpper = NULL;
2531                 pFloat = pFloat->GetNext();
2532                 if( !bGo && pFloat == pStart )
2533                 {
2534                     bGo = sal_True;
2535                     pFloat->pPrev->pNext = NULL;
2536                     pFloat->pPrev = NULL;
2537                 }
2538             }
2539             else
2540                 break;
2541 
2542         } while ( pFloat );
2543 
2544         //Die naechste Teilkette suchen und die Ketten miteinander verbinden.
2545         SwFrm *pTmp = pFloat->FindNext();
2546         if( bGo )
2547             pFloat->pUpper = NULL;
2548 
2549         if( !pLay->IsInFtn() )
2550             while( pTmp && pTmp->IsInFtn() )
2551                 pTmp = pTmp->FindNext();
2552 
2553         if ( !pLay->IsAnLower( pTmp ) )
2554             pTmp = 0;
2555 
2556         if ( pTmp && bGo )
2557         {
2558             pFloat->pNext = pTmp;           //Die beiden Ketten verbinden.
2559             pFloat->pNext->pPrev = pFloat;
2560         }
2561         pFloat = pTmp;
2562         bGo = bGo || ( pStart == pFloat );
2563     }  while ( pFloat );
2564 
2565     return bGo ? pStart : NULL;
2566 }
2567 
2568 // --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
2569 // anchored objects to page
2570 void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
2571 {
2572     ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
2573     SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2574     for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2575     {
2576         SwAnchoredObject* pObj = rObjs[i];
2577 
2578         // --> OD 2004-11-29 #115759# - unlock position of anchored object
2579         // in order to get the object's position calculated.
2580         pObj->UnlockPosition();
2581         // <--
2582         // --> OD 2004-11-29 #115759# - add also lower objects of as-character
2583         // anchored Writer fly frames from page
2584         if ( pObj->ISA(SwFlyFrm) )
2585         {
2586             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2587             if ( pObj->ISA(SwFlyFreeFrm) )
2588             {
2589                 _pPage->AppendFlyToPage( pFlyFrm );
2590             }
2591             pFlyFrm->_InvalidatePos();
2592             pFlyFrm->_InvalidateSize();
2593             pFlyFrm->InvalidatePage( _pPage );
2594 
2595             // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
2596             // to page
2597             if ( pFlyFrm->GetDrawObjs() )
2598             {
2599                 ::lcl_AddObjsToPage( pFlyFrm, _pPage );
2600             }
2601             // <--
2602 
2603             SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
2604             while ( pCnt )
2605             {
2606                 if ( pCnt->GetDrawObjs() )
2607                     ::lcl_AddObjsToPage( pCnt, _pPage );
2608                 pCnt = pCnt->GetNextCntntFrm();
2609             }
2610         }
2611         // <--
2612         // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2613         else if ( pObj->ISA(SwAnchoredDrawObject) )
2614         {
2615             if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2616             {
2617                 pObj->InvalidateObjPos();
2618                 _pPage->AppendDrawObjToPage(
2619                                 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2620             }
2621         }
2622         // <--
2623     }
2624 }
2625 
2626 void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
2627 {
2628     ASSERT( pSav && pParent, "Kein Save oder Parent fuer Restore." );
2629     SWRECTFN( pParent )
2630 
2631     //Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
2632     //Kette, beginnend mit pSav,  hinter dem letzten angehaengt.
2633     //Die Teile werden kurzerhand insertet und geeignet invalidiert.
2634     //Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.
2635 
2636     SwPageFrm *pPage = pParent->FindPageFrm();
2637 
2638     if ( pPage )
2639         pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.
2640 
2641     //Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren.
2642     pSav->pPrev = pSibling;
2643     SwFrm* pNxt;
2644     if ( pSibling )
2645     {
2646         pNxt = pSibling->pNext;
2647         pSibling->pNext = pSav;
2648         pSibling->_InvalidatePrt();
2649         ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
2650         if ( ((SwCntntFrm*)pSibling)->GetFollow() )
2651             pSibling->Prepare( PREP_CLEAR, 0, sal_False );
2652     }
2653     else
2654     {   pNxt = pParent->pLower;
2655         pParent->pLower = pSav;
2656         pSav->pUpper = pParent;     //Schon mal setzen, sonst ist fuer das
2657                                     //invalidate der Parent (z.B. ein Fly) nicht klar.
2658         //Invaliden Cntnt anmelden.
2659         if ( pSav->IsCntntFrm() )
2660             ((SwCntntFrm*)pSav)->InvalidatePage( pPage );
2661         else
2662         {   // pSav koennte auch ein leerer SectFrm sein
2663             SwCntntFrm* pCnt = pParent->ContainsCntnt();
2664             if( pCnt )
2665                 pCnt->InvalidatePage( pPage );
2666         }
2667     }
2668 
2669     //Der Parent muss entsprechend gegrow'ed werden.
2670     SwTwips nGrowVal = 0;
2671     SwFrm* pLast;
2672     do
2673     {   pSav->pUpper = pParent;
2674         nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
2675         pSav->_InvalidateAll();
2676 
2677         //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
2678         if ( pSav->IsCntntFrm() )
2679         {
2680             if ( pSav->IsTxtFrm() &&
2681                  ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
2682                 ((SwTxtFrm*)pSav)->Init();  //Ich bin sein Freund.
2683 
2684             if ( pPage && pSav->GetDrawObjs() )
2685                 ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
2686         }
2687         else
2688         {   SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
2689             if( pBlub )
2690             {
2691                 do
2692                 {   if ( pPage && pBlub->GetDrawObjs() )
2693                         ::lcl_AddObjsToPage( pBlub, pPage );
2694                     if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
2695                         ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
2696                         ((SwTxtFrm*)pBlub)->Init(); //Ich bin sein Freund.
2697                     pBlub = pBlub->GetNextCntntFrm();
2698                 } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
2699             }
2700         }
2701         pLast = pSav;
2702         pSav = pSav->GetNext();
2703 
2704     } while ( pSav );
2705 
2706     if( pNxt )
2707     {
2708         pLast->pNext = pNxt;
2709         pNxt->pPrev = pLast;
2710     }
2711 
2712     if ( bGrow )
2713         pParent->Grow( nGrowVal );
2714 }
2715 
2716 /*************************************************************************
2717 |*
2718 |*  SqRt()              Berechnung der Quadratwurzel, damit die math.lib
2719 |*      nicht auch noch dazugelinkt werden muss.
2720 |*
2721 |*************************************************************************/
2722 
2723 sal_uLong MA_FASTCALL SqRt( BigInt nX )
2724 {
2725     BigInt nErg = 1;
2726 
2727     if ( !nX.IsNeg() )
2728     {
2729         BigInt nOldErg = 1;
2730         for ( int i = 0; i <= 5; i++ )
2731         {
2732             nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
2733             nOldErg = nErg;
2734         }
2735     }
2736     return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg;
2737 }
2738 
2739 /*************************************************************************/
2740 
2741 SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
2742                           sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
2743                           SwFrm *pSibling )
2744 {
2745     SwPageFrm *pRet;
2746     SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
2747     SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
2748     //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
2749     //eine Leerseite einfuegen.
2750     if ( !pFmt )
2751     {
2752         pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
2753         ASSERT( pFmt, "Descriptor without any format?!" );
2754         bInsertEmpty = !bInsertEmpty;
2755     }
2756     if( bInsertEmpty )
2757     {
2758         SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
2759                 ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
2760         pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
2761         pRet->Paste( pUpper, pSibling );
2762         pRet->PreparePage( bFtn );
2763     }
2764     pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
2765     pRet->Paste( pUpper, pSibling );
2766     pRet->PreparePage( bFtn );
2767     if ( pRet->GetNext() )
2768         ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
2769     return pRet;
2770 }
2771 
2772 
2773 /*************************************************************************
2774 |*
2775 |*  RegistFlys(), Regist()  Die beiden folgenden Methoden durchsuchen rekursiv
2776 |*      eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
2777 |*      innerhalb der Struktur als Anker haben bei der Seite an.
2778 |*
2779 |*************************************************************************/
2780 
2781 void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
2782 {
2783     SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
2784     for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2785     {
2786         SwAnchoredObject* pObj = (*pObjs)[i];
2787         if ( pObj->ISA(SwFlyFrm) )
2788         {
2789             SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2790             //Ggf. ummelden, nicht anmelden wenn bereits bekannt.
2791             // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2792             SwPageFrm *pPg = pFly->IsFlyFreeFrm()
2793                              ? pFly->GetPageFrm() : pFly->FindPageFrm();
2794             if ( pPg != pPage )
2795             {
2796                 if ( pPg )
2797                     pPg->RemoveFlyFromPage( pFly );
2798                 pPage->AppendFlyToPage( pFly );
2799             }
2800             ::RegistFlys( pPage, pFly );
2801         }
2802         else
2803         {
2804             // --> OD 2008-04-22 #i87493#
2805             if ( pPage != pObj->GetPageFrm() )
2806             {
2807                 // --> OD 2004-07-02 #i28701#
2808                 if ( pObj->GetPageFrm() )
2809                     pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
2810                 pPage->AppendDrawObjToPage( *pObj );
2811                 // <--
2812             }
2813             // <--
2814         }
2815 
2816         const SwFlyFrm* pFly = pAnch->FindFlyFrm();
2817         if ( pFly &&
2818              pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
2819              pObj->GetDrawObj()->GetPage() )
2820         {
2821             //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
2822             pObj->DrawObj()->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(),
2823                                                          pObj->GetDrawObj()->GetOrdNumDirect() );
2824         }
2825     }
2826 }
2827 
2828 void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
2829 {
2830     if ( pLay->GetDrawObjs() )
2831         ::lcl_Regist( pPage, pLay );
2832     const SwFrm *pFrm = pLay->Lower();
2833     while ( pFrm )
2834     {
2835         if ( pFrm->IsLayoutFrm() )
2836             ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
2837         else if ( pFrm->GetDrawObjs() )
2838             ::lcl_Regist( pPage, pFrm );
2839         pFrm = pFrm->GetNext();
2840     }
2841 }
2842 
2843 /*************************************************************************
2844 |*
2845 |*  void Notify()
2846 |*
2847 |*  Beschreibung        Benachrichtigt den Hintergrund je nach der
2848 |*      Veraenderung zwischen altem und neuem Rechteckt.
2849 |*
2850 |*************************************************************************/
2851 
2852 void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
2853              const SwRect* pOldPrt )
2854 {
2855     const SwRect aFrm( pFly->GetObjRectWithSpaces() );
2856     if ( rOld.Pos() != aFrm.Pos() )
2857     {   //Positionsaenderung, alten und neuen Bereich invalidieren
2858         if ( rOld.HasArea() &&
2859              rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
2860         {
2861             pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
2862         }
2863         pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2864     }
2865     else if ( rOld.SSize() != aFrm.SSize() )
2866     {   //Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
2867         //ueberdeckt wird invalidieren.
2868         //Der Einfachheit halber wird hier bewusst jeweils ein Twip
2869         //unnoetig invalidiert.
2870 
2871         ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
2872         if( pSh && rOld.HasArea() )
2873             pSh->InvalidateWindows( rOld );
2874 
2875         // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
2876         // registered at the old page <pOld>
2877         SwPageFrm* pPageFrm = pFly->FindPageFrm();
2878         if ( pOld != pPageFrm )
2879         {
2880             pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
2881         }
2882         // <--
2883 
2884         if ( rOld.Left() != aFrm.Left() )
2885         {
2886             SwRect aTmp( rOld );
2887             aTmp.Union( aFrm );
2888             aTmp.Left(  Min(aFrm.Left(), rOld.Left()) );
2889             aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
2890             pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2891         }
2892         SwTwips nOld = rOld.Right();
2893         SwTwips nNew = aFrm.Right();
2894         if ( nOld != nNew )
2895         {
2896             SwRect aTmp( rOld );
2897             aTmp.Union( aFrm );
2898             aTmp.Left(  Min(nNew, nOld) );
2899             aTmp.Right( Max(nNew, nOld) );
2900             pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2901         }
2902         if ( rOld.Top() != aFrm.Top() )
2903         {
2904             SwRect aTmp( rOld );
2905             aTmp.Union( aFrm );
2906             aTmp.Top(    Min(aFrm.Top(), rOld.Top()) );
2907             aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
2908             pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2909         }
2910         nOld = rOld.Bottom();
2911         nNew = aFrm.Bottom();
2912         if ( nOld != nNew )
2913         {
2914             SwRect aTmp( rOld );
2915             aTmp.Union( aFrm );
2916             aTmp.Top(    Min(nNew, nOld) );
2917             aTmp.Bottom( Max(nNew, nOld) );
2918             pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2919         }
2920     }
2921     else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
2922               pFly->GetFmt()->GetSurround().IsContour() )
2923     {
2924         // #i24097#
2925         pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2926     }
2927 }
2928 
2929 /*************************************************************************/
2930 
2931 void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
2932 {
2933     SwTwips nBottom = rRect.Bottom();
2934     while( pFrm )
2935     {
2936         if( pFrm->IsLayoutFrm() )
2937         {
2938             if( rRect.IsOver( pFrm->Frm() ) )
2939                 lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
2940         }
2941         else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
2942         {
2943             if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
2944                 pFrm->InvalidateSize();
2945             else
2946                 pFrm->InvalidateNextPos();
2947         }
2948         pFrm = pFrm->GetNext();
2949     }
2950 }
2951 
2952 void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
2953     const SwRect &rRect, const PrepareHint eHint )
2954 {
2955     if ( pCnt->IsTxtFrm() )
2956     {
2957         SwRect aCntPrt( pCnt->Prt() );
2958         aCntPrt.Pos() += pCnt->Frm().Pos();
2959         if ( eHint == PREP_FLY_ATTR_CHG )
2960         {
2961             // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
2962             // of current bound rectangle
2963             if ( aCntPrt.IsOver( rRect ) )
2964             // <--
2965                 pCnt->Prepare( PREP_FLY_ATTR_CHG );
2966         }
2967         // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
2968         // printing area overlaps with the given rectangle.
2969         else if ( aCntPrt.IsOver( rRect ) )
2970         // <--
2971             pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
2972         if ( pCnt->GetDrawObjs() )
2973         {
2974             const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2975             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2976             {
2977                 SwAnchoredObject* pObj = rObjs[i];
2978                 if ( pObj->ISA(SwFlyFrm) )
2979                 {
2980                     SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2981                     if ( pFly->IsFlyInCntFrm() )
2982                     {
2983                         SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2984                         while ( pCntnt )
2985                         {
2986                             ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
2987                             pCntnt = pCntnt->GetNextCntntFrm();
2988                         }
2989                     }
2990                 }
2991             }
2992         }
2993     }
2994 }
2995 
2996 void Notify_Background( const SdrObject* pObj,
2997                         SwPageFrm* pPage,
2998                         const SwRect& rRect,
2999                         const PrepareHint eHint,
3000                         const sal_Bool bInva )
3001 {
3002 
3003     //Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
3004     //alte Bereich nicht benachrichtigt werden.
3005     if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
3006          return;
3007 
3008     SwLayoutFrm* pArea;
3009     SwFlyFrm *pFlyFrm = 0;
3010     SwFrm* pAnchor;
3011     if( pObj->ISA(SwVirtFlyDrawObj) )
3012     {
3013         pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
3014         pAnchor = pFlyFrm->AnchorFrm();
3015     }
3016     else
3017     {
3018         pFlyFrm = NULL;
3019         pAnchor = const_cast<SwFrm*>(
3020                     GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
3021     }
3022     if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
3023         pArea = pAnchor->FindFlyFrm();
3024     else
3025         pArea = pPage;
3026     SwCntntFrm *pCnt = 0;
3027     if ( pArea )
3028     {
3029         if( PREP_FLY_ARRIVE != eHint )
3030             lcl_CheckFlowBack( pArea, rRect );
3031 
3032         //Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
3033         //brauchen diese nicht abgeklappert werden.
3034         //Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
3035         //"oben" kommen.
3036         // Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
3037         // die gesamte Seite abgearbeitet werden. (47722)
3038         // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3039         // on the object positioning, the complete area has to be processed,
3040         // because content frames before the anchor frame also have to consider
3041         // the object for the text wrapping.
3042         // --> OD 2004-08-25 #i3317# - The complete area has always been
3043         // processed.
3044         {
3045             pCnt = pArea->ContainsCntnt();
3046         }
3047         // <--
3048     }
3049     SwFrm *pLastTab = 0;
3050 
3051     while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
3052     {
3053         ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3054         if ( pCnt->IsInTab() )
3055         {
3056             SwLayoutFrm* pCell = pCnt->GetUpper();
3057             // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3058             // instead of <GetCurrentBoundRect()>, because a recalculation
3059             // of the bounding rectangle isn't intended here.
3060             if ( pCell->IsCellFrm() &&
3061                  ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3062                    pCell->Frm().IsOver( rRect ) ) )
3063             // <--
3064             {
3065                 const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
3066                 if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
3067                     pCell->InvalidatePrt();
3068             }
3069             SwTabFrm *pTab = pCnt->FindTabFrm();
3070             if ( pTab != pLastTab )
3071             {
3072                 pLastTab = pTab;
3073                 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3074                 // instead of <GetCurrentBoundRect()>, because a recalculation
3075                 // of the bounding rectangle isn't intended here.
3076                 if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3077                      pTab->Frm().IsOver( rRect ) )
3078                 // <--
3079                 {
3080                     if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
3081                         pTab->InvalidatePrt();
3082                 }
3083             }
3084         }
3085         pCnt = pCnt->GetNextCntntFrm();
3086     }
3087 // #108745# Sorry, but this causes nothing but trouble. I remove these lines
3088 // taking the risk that the footer frame will have a wrong height
3089 //  if( pPage->Lower() )
3090 //  {
3091 //      SwFrm* pFrm = pPage->Lower();
3092 //      while( pFrm->GetNext() )
3093 //          pFrm = pFrm->GetNext();
3094 //      if( pFrm->IsFooterFrm() &&
3095 //          ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
3096 //              pFrm->Frm().IsOver( rRect ) ) ) )
3097 //           pFrm->InvalidateSize();
3098 //  }
3099     // --> OD 2007-07-24 #128702# - make code robust
3100     if ( pPage && pPage->GetSortedObjs() )
3101     // <--
3102     {
3103         pObj->GetOrdNum();
3104         const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3105         for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
3106         {
3107             SwAnchoredObject* pAnchoredObj = rObjs[i];
3108             if ( pAnchoredObj->ISA(SwFlyFrm) )
3109             {
3110                 if( pAnchoredObj->GetDrawObj() == pObj )
3111                     continue;
3112                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3113                 if ( pFly->Frm().Top() == WEIT_WECH )
3114                     continue;
3115 
3116                 if ( !pFlyFrm ||
3117                         (!pFly->IsLowerOf( pFlyFrm ) &&
3118                         pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
3119                 {
3120                     pCnt = pFly->ContainsCntnt();
3121                     while ( pCnt )
3122                     {
3123                         ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3124                         pCnt = pCnt->GetNextCntntFrm();
3125                     }
3126                 }
3127                 if( pFly->IsFlyLayFrm() )
3128                 {
3129                     if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
3130                         pFly->Frm().Bottom() >= rRect.Top() &&
3131                         pFly->Frm().Top() <= rRect.Bottom() &&
3132                         pFly->Frm().Right() >= rRect.Left() &&
3133                         pFly->Frm().Left() <= rRect.Right() )
3134                      {
3135                         pFly->InvalidateSize();
3136                      }
3137                 }
3138                 //Flys, die ueber mir liegen muessen/mussten evtl.
3139                 //ausweichen, wenn sie eine automatische Ausrichtung haben.
3140                 //das ist unabhaengig von meinem Attribut, weil dies sich
3141                 //gerade geaendert haben kann und eben deshalb
3142                 //umformatiert wurde.
3143                 else if ( pFly->IsFlyAtCntFrm() &&
3144                         pObj->GetOrdNumDirect() <
3145                         pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
3146                         pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
3147                 {
3148                     const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
3149                     if ( text::HoriOrientation::NONE != rH.GetHoriOrient()  &&
3150                             text::HoriOrientation::CENTER != rH.GetHoriOrient()  &&
3151                             ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
3152                             (pFly->Frm().Bottom() >= rRect.Top() &&
3153                             pFly->Frm().Top() <= rRect.Bottom()) )
3154                         pFly->InvalidatePos();
3155                 }
3156             }
3157         }
3158     }
3159     if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
3160         pAnchor->GetUpper()->InvalidateSize();
3161 
3162     // --> OD 2008-01-30 #i82258# - make code robust
3163     ViewShell* pSh = 0;
3164     if ( bInva && pPage &&
3165         0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
3166     {
3167         pSh->InvalidateWindows( rRect );
3168     }
3169     // <--
3170 }
3171 
3172 /*************************************************************************
3173 |*
3174 |*  GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
3175 |*  des Ankers. Falls es sich dabei um verkettete Rahmen oder
3176 |*  Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
3177 |*
3178 |*************************************************************************/
3179 
3180 const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
3181 {
3182     if( pFrm->IsTxtFrm() )
3183     {
3184         pFrm = pFrm->GetUpper();
3185         if( !pFrm->Frm().IsInside( rPos ) )
3186         {
3187             if( pFrm->IsFtnFrm() )
3188             {
3189                 const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
3190                 while( pTmp )
3191                 {
3192                     if( pTmp->Frm().IsInside( rPos ) )
3193                         return pTmp;
3194                     pTmp = pTmp->GetFollow();
3195                 }
3196             }
3197             else
3198             {
3199                 SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
3200                 while( pTmp )
3201                 {
3202                     if( pTmp->Frm().IsInside( rPos ) )
3203                         return pTmp;
3204                     pTmp = pTmp->GetNextLink();
3205                 }
3206             }
3207         }
3208     }
3209     return pFrm;
3210 }
3211 
3212 /*************************************************************************/
3213 
3214 sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
3215 {
3216     Point aPos;
3217     const SwFrm* pFrm;
3218     if( pObj->ISA(SwVirtFlyDrawObj) )
3219     {
3220         const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
3221         pFrm = pFly->GetAnchorFrm();
3222         aPos = pFly->Frm().Pos();
3223     }
3224     else
3225     {
3226         pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
3227         aPos = pObj->GetCurrentBoundRect().TopLeft();
3228     }
3229     ASSERT( pFrm, "8-( Fly is lost in Space." );
3230     pFrm = GetVirtualUpper( pFrm, aPos );
3231     do
3232     {   if ( pFrm == pCurrFrm )
3233             return sal_True;
3234         if( pFrm->IsFlyFrm() )
3235         {
3236             aPos = pFrm->Frm().Pos();
3237             pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3238         }
3239         else
3240             pFrm = pFrm->GetUpper();
3241     } while ( pFrm );
3242     return sal_False;
3243 }
3244 
3245 const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
3246 {
3247     //Liefert die Umgebung des Frm in die kein Fly aus einer anderen
3248     //Umgebung hineinragen kann.
3249     const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
3250                         FRM_FTN  | FRM_FLY      |
3251                         FRM_TAB  | FRM_ROW      | FRM_CELL |
3252                         nAdditionalKontextTyp;
3253     do
3254     {   if ( pFrm->GetType() & nTyp )
3255             break;
3256         pFrm = pFrm->GetUpper();
3257     } while( pFrm );
3258     return pFrm;
3259 }
3260 
3261 sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
3262 {
3263     const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
3264 
3265     const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
3266                         FRM_FTN  | FRM_FLY      |
3267                         FRM_TAB  | FRM_ROW      | FRM_CELL;
3268     do
3269     {   if ( pFrm->GetType() & nTyp )
3270         {
3271             if( pFrm == pKontext )
3272                 return sal_True;
3273             if( pFrm->IsCellFrm() )
3274                 return sal_False;
3275         }
3276         if( pFrm->IsFlyFrm() )
3277         {
3278             Point aPos( pFrm->Frm().Pos() );
3279             pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3280         }
3281         else
3282             pFrm = pFrm->GetUpper();
3283     } while( pFrm );
3284 
3285     return sal_False;
3286 }
3287 
3288 
3289 //---------------------------------
3290 
3291 SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
3292 {
3293     if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
3294     {
3295         SwFrm *pLow = pCell->Lower();
3296         long nHeight = 0, nFlyAdd = 0;
3297         do
3298         {
3299             long nLow = pLow->Frm().Height();
3300             if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
3301                 nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
3302             else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
3303                 nLow += ((SwSectionFrm*)pLow)->Undersize();
3304             nFlyAdd = Max( 0L, nFlyAdd - nLow );
3305             nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
3306             nHeight += nLow;
3307             pLow = pLow->GetNext();
3308         } while ( pLow );
3309         if ( nFlyAdd )
3310             nHeight += nFlyAdd;
3311 
3312         //Der Border will natuerlich auch mitspielen, er kann leider nicht
3313         //aus PrtArea und Frm errechnet werden, da diese in beliebiger
3314         //Kombination ungueltig sein koennen.
3315         SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
3316         const SwBorderAttrs &rAttrs = *aAccess.Get();
3317         nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
3318 
3319         return pCell->Frm().Height() - nHeight;
3320     }
3321     else
3322     {
3323         long nRstHeight = 0;
3324         SwFrm *pLow = pCell->Lower();
3325         do
3326         {   nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
3327             pLow = pLow->GetNext();
3328 
3329         } while ( pLow );
3330 
3331         return nRstHeight;
3332     }
3333 }
3334 
3335 SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
3336 {
3337     SwTwips nRstHeight = LONG_MAX;
3338     SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
3339     while ( pLow )
3340     {
3341         nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
3342         pLow = (SwLayoutFrm*)pLow->GetNext();
3343     }
3344     return nRstHeight;
3345 }
3346 
3347 const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
3348 {
3349     if ( !rRect.IsOver( pPage->Frm() ) )
3350     {
3351         const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
3352         const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
3353         if ( pTmpPage )
3354             pPage = pTmpPage;
3355     }
3356 
3357     return pPage;
3358 }
3359 
3360 #include <svl/smplhint.hxx>
3361 class SwFrmHolder : private SfxListener
3362 {
3363     SwFrm* pFrm;
3364     bool bSet;
3365     virtual void Notify(  SfxBroadcaster& rBC, const SfxHint& rHint );
3366 public:
3367     SwFrmHolder() : pFrm(0), bSet(false) {}
3368     void SetFrm( SwFrm* pHold );
3369     SwFrm* GetFrm() { return pFrm; }
3370     void Reset();
3371     bool IsSet() { return bSet; }
3372 };
3373 
3374 void SwFrmHolder::SetFrm( SwFrm* pHold )
3375 {
3376     bSet = true;
3377     pFrm = pHold;
3378     StartListening(*pHold);
3379 }
3380 
3381 void SwFrmHolder::Reset()
3382 {
3383     if (pFrm)
3384         EndListening(*pFrm);
3385     bSet = false;
3386     pFrm = 0;
3387 }
3388 
3389 void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
3390 {
3391     if ( rHint.IsA(TYPE(SfxSimpleHint)) )
3392     {
3393         if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
3394             pFrm = 0;
3395     }
3396 }
3397 
3398 SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
3399         const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
3400 {
3401     SwFrm *pMinFrm = 0, *pTmpFrm;
3402     SwFrmHolder aHolder;
3403     SwRect aCalcRect;
3404     bool bClientIterChanged = false;
3405 
3406     SwIterator<SwFrm,SwModify> aIter( rMod );
3407     do {
3408         pMinFrm = 0;
3409         aHolder.Reset();
3410         sal_uInt64 nMinDist = 0;
3411         bClientIterChanged = false;
3412 
3413         for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
3414         {
3415             if( pTmpFrm->GetType() & nFrmType &&
3416                 ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
3417                 (!pTmpFrm->IsFlowFrm() ||
3418                  !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
3419             {
3420                 if( pPoint )
3421                 {
3422                     // watch for Frm being deleted
3423                     if ( pMinFrm )
3424                         aHolder.SetFrm( pMinFrm );
3425                     else
3426                         aHolder.Reset();
3427 
3428                     if( bCalcFrm )
3429                     {
3430                         // --> OD 2005-03-04 #b6234250# - format parent Writer
3431                         // fly frame, if it isn't been formatted yet.
3432                         // Note: The Writer fly frame could be the frame itself.
3433                         SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
3434                         if ( pFlyFrm &&
3435                              pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
3436                              pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
3437                         {
3438                             SwObjectFormatter::FormatObj( *pFlyFrm );
3439                         }
3440                         // <--
3441                         pTmpFrm->Calc();
3442                     }
3443 
3444                     // #127369#
3445                     // aIter.IsChanged checks if the current pTmpFrm has been deleted while
3446                     // it is the current iterator
3447                     // FrmHolder watches for deletion of the current pMinFrm
3448                     if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
3449                     {
3450                         // restart iteration
3451                         bClientIterChanged = true;
3452                         break;
3453                     }
3454 
3455                     // bei Flys ggfs. ueber den Parent gehen wenn sie selbst
3456                     // nocht nicht "formatiert" sind
3457                     if( !bCalcFrm && nFrmType & FRM_FLY &&
3458                         ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
3459                         WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
3460                         WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
3461                         aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
3462                     else
3463                         aCalcRect = pTmpFrm->Frm();
3464 
3465                     if ( aCalcRect.IsInside( *pPoint ) )
3466                     {
3467                         pMinFrm = pTmpFrm;
3468                         break;
3469                     }
3470 
3471                     // Point not in rectangle. Compare distances:
3472                     const Point aCalcRectCenter = aCalcRect.Center();
3473                     const Point aDiff = aCalcRectCenter - *pPoint;
3474                     const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
3475                     if ( !pMinFrm || nCurrentDist < nMinDist )
3476                     {
3477                         pMinFrm = pTmpFrm;
3478                         nMinDist = nCurrentDist;
3479                     }
3480                 }
3481                 else
3482                 {
3483                     // Wenn kein pPoint angegeben ist, dann reichen
3484                     // wir irgendeinen raus: den ersten!
3485                     pMinFrm = pTmpFrm;
3486                     break;
3487                 }
3488             }
3489         }
3490     } while( bClientIterChanged );
3491 
3492     if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
3493         return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
3494 
3495     return pMinFrm;
3496 }
3497 
3498 sal_Bool IsExtraData( const SwDoc *pDoc )
3499 {
3500     const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
3501     return rInf.IsPaintLineNumbers() ||
3502            rInf.IsCountInFlys() ||
3503            ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
3504             pDoc->GetRedlineTbl().Count());
3505 }
3506 
3507 // OD 22.09.2003 #110978#
3508 const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
3509 {
3510     SwRect aPrtWithoutHeaderFooter( Prt() );
3511     aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
3512 
3513     const SwFrm* pLowerFrm = Lower();
3514     while ( pLowerFrm )
3515     {
3516         // Note: independent on text direction page header and page footer are
3517         //       always at top respectively at bottom of the page frame.
3518         if ( pLowerFrm->IsHeaderFrm() )
3519         {
3520             aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
3521                                          pLowerFrm->Frm().Height() );
3522         }
3523         if ( pLowerFrm->IsFooterFrm() )
3524         {
3525             aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
3526                                             pLowerFrm->Frm().Height() );
3527         }
3528 
3529         pLowerFrm = pLowerFrm->GetNext();
3530     }
3531 
3532     return aPrtWithoutHeaderFooter;
3533 }
3534 
3535 /** method to determine the spacing values of a frame
3536 
3537     OD 2004-03-10 #i28701#
3538     OD 2009-08-28 #i102458#
3539     Add output parameter <obIsLineSpacingProportional>
3540 
3541     @author OD
3542 */
3543 void GetSpacingValuesOfFrm( const SwFrm& rFrm,
3544                             SwTwips& onLowerSpacing,
3545                             SwTwips& onLineSpacing,
3546                             bool& obIsLineSpacingProportional )
3547 {
3548     if ( !rFrm.IsFlowFrm() )
3549     {
3550         onLowerSpacing = 0;
3551         onLineSpacing = 0;
3552     }
3553     else
3554     {
3555         const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
3556         onLowerSpacing = rULSpace.GetLower();
3557 
3558         onLineSpacing = 0;
3559         obIsLineSpacingProportional = false;
3560         if ( rFrm.IsTxtFrm() )
3561         {
3562             onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
3563             obIsLineSpacingProportional =
3564                 onLineSpacing != 0 &&
3565                 static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
3566         }
3567 
3568         ASSERT( onLowerSpacing >= 0 && onLineSpacing >= 0,
3569                 "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
3570     }
3571 }
3572 
3573 /** method to get the content of the table cell, skipping content from nested tables
3574 */
3575 const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
3576 {
3577     const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
3578     const SwTabFrm* pTab = rCell.FindTabFrm();
3579 
3580     while ( pCntnt && rCell.IsAnLower( pCntnt ) )
3581     {
3582         const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
3583         if ( pTmpTab != pTab )
3584         {
3585             pCntnt = pTmpTab->FindLastCntnt();
3586             if ( pCntnt )
3587 
3588                 pCntnt = pCntnt->FindNextCnt();
3589 
3590         }
3591         else
3592             break;
3593     }
3594     return pCntnt;
3595 }
3596 
3597 /** Can be used to check if a frame has been deleted
3598  */
3599 bool SwDeletionChecker::HasBeenDeleted()
3600 {
3601     if ( !mpFrm || !mpRegIn )
3602         return false;
3603 
3604     SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
3605     SwFrm* pLast = aIter.First();
3606     while ( pLast )
3607     {
3608         if ( pLast == mpFrm )
3609             return false;
3610         pLast = aIter.Next();
3611     }
3612 
3613     return true;
3614 }
3615 
3616 
3617