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