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