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