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