xref: /AOO41X/main/sw/source/core/layout/wsfrm.cxx (revision 4d7c9de063a797b8b4f3d45e3561e82ad1f8ef1f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 #include <hints.hxx>
30 #include <tools/pstm.hxx>
31 #include <vcl/outdev.hxx>
32 #include <svl/itemiter.hxx>
33 #include <editeng/brshitem.hxx>
34 #include <editeng/keepitem.hxx>
35 #include <editeng/brkitem.hxx>
36 #include <fmtornt.hxx>
37 #include <pagefrm.hxx>
38 #include <section.hxx>
39 #include <rootfrm.hxx>
40 #include <cntfrm.hxx>
41 #include <dcontact.hxx>
42 #include <anchoreddrawobject.hxx>
43 #include <fmtanchr.hxx>
44 #include <viewsh.hxx>
45 #include <viewimp.hxx>
46 #include "viewopt.hxx"
47 #include <doc.hxx>
48 #include <fesh.hxx>
49 #include <docsh.hxx>
50 #include <flyfrm.hxx>
51 #include <frmtool.hxx>
52 #include <ftninfo.hxx>
53 #include <dflyobj.hxx>
54 #include <fmtclbl.hxx>
55 #include <fmtfordr.hxx>
56 #include <fmtfsize.hxx>
57 #include <fmtpdsc.hxx>
58 #include <txtftn.hxx>
59 #include <fmtftn.hxx>
60 #include <fmtsrnd.hxx>
61 #include <ftnfrm.hxx>
62 #include <tabfrm.hxx>
63 #include <htmltbl.hxx>
64 #include <flyfrms.hxx>
65 #include <sectfrm.hxx>
66 #include <fmtclds.hxx>
67 #include <txtfrm.hxx>
68 #include <ndtxt.hxx>
69 #include <bodyfrm.hxx>
70 #include <cellfrm.hxx>
71 #include <dbg_lay.hxx>
72 #include <editeng/frmdiritem.hxx>
73 // OD 2004-05-24 #i28701#
74 #include <sortedobjs.hxx>
75 
76 
77 using namespace ::com::sun::star;
78 
79 
80 /*************************************************************************
81 |*
82 |*  SwFrm::SwFrm()
83 |*
84 |*  Ersterstellung      AK 12-Feb-1991
85 |*  Letzte Aenderung    MA 05. Apr. 94
86 |*
87 |*************************************************************************/
88 
SwFrm(SwModify * pMod,SwFrm * pSib)89 SwFrm::SwFrm( SwModify *pMod, SwFrm* pSib ) :
90     SwClient( pMod ),
91     //Solution:Add a member to identify if the acc table should dispose
92     bIfAccTableShouldDisposing( sal_False ),
93     // --> OD 2006-05-10 #i65250#
94     mnFrmId( SwFrm::mnLastFrmId++ ),
95     // <--
96     mpRoot( pSib ? pSib->getRootFrm() : 0 ),
97     pUpper( 0 ),
98     pNext( 0 ),
99     pPrev( 0 ),
100     pDrawObjs( 0 )
101     , bInfBody( sal_False )
102     , bInfTab ( sal_False )
103     , bInfFly ( sal_False )
104     , bInfFtn ( sal_False )
105     , bInfSct ( sal_False )
106 {
107 #ifdef DBG_UTIL
108     bFlag01 = bFlag02 = bFlag03 = bFlag04 = bFlag05 = 0;
109 #endif
110 
111     ASSERT( pMod, "Kein Frameformat uebergeben." );
112     bInvalidR2L = bInvalidVert = 1;
113     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
114     bDerivedR2L = bDerivedVert = bRightToLeft = bVertical = bReverse = bVertLR = 0;
115 
116     bValidPos = bValidPrtArea = bValidSize = bValidLineNum = bRetouche =
117     bFixSize = bColLocked = sal_False;
118     bCompletePaint = bInfInvalid = sal_True;
119 }
120 
KnowsFormat(const SwFmt & rFmt) const121 bool SwFrm::KnowsFormat( const SwFmt& rFmt ) const
122 {
123     return GetRegisteredIn() == &rFmt;
124 }
125 
RegisterToFormat(SwFmt & rFmt)126 void SwFrm::RegisterToFormat( SwFmt& rFmt )
127 {
128     rFmt.Add( this );
129 }
130 
CheckDir(sal_uInt16 nDir,sal_Bool bVert,sal_Bool bOnlyBiDi,sal_Bool bBrowse)131 void SwFrm::CheckDir( sal_uInt16 nDir, sal_Bool bVert, sal_Bool bOnlyBiDi, sal_Bool bBrowse )
132 {
133     if( FRMDIR_ENVIRONMENT == nDir || ( bVert && bOnlyBiDi ) )
134     {
135         bDerivedVert = 1;
136         if( FRMDIR_ENVIRONMENT == nDir )
137             bDerivedR2L = 1;
138         SetDirFlags( bVert );
139     }
140     else if( bVert )
141     {
142         bInvalidVert = 0;
143         if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir
144             || bBrowse )
145         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
146         {
147             bVertical = 0;
148             bVertLR = 0;
149         }
150         else
151         {
152             bVertical = 1;
153             if(FRMDIR_VERT_TOP_RIGHT == nDir)
154                 bVertLR = 0;
155             else if(FRMDIR_VERT_TOP_LEFT==nDir)
156                     bVertLR = 1;
157         }
158     }
159     else
160     {
161         bInvalidR2L = 0;
162         if( FRMDIR_HORI_RIGHT_TOP == nDir )
163             bRightToLeft = 1;
164         else
165             bRightToLeft = 0;
166     }
167 }
168 
CheckDirection(sal_Bool bVert)169 void SwFrm::CheckDirection( sal_Bool bVert )
170 {
171     if( bVert )
172     {
173         if( !IsHeaderFrm() && !IsFooterFrm() )
174         {
175             bDerivedVert = 1;
176             SetDirFlags( bVert );
177         }
178     }
179     else
180     {
181         bDerivedR2L = 1;
182         SetDirFlags( bVert );
183     }
184 }
185 
CheckDirection(sal_Bool bVert)186 void SwSectionFrm::CheckDirection( sal_Bool bVert )
187 {
188     const SwFrmFmt* pFmt = GetFmt();
189     if( pFmt )
190     {
191         const ViewShell *pSh = getRootFrm()->GetCurrShell();
192         const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
193         CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
194                     bVert, sal_True, bBrowseMode );
195     }
196     else
197         SwFrm::CheckDirection( bVert );
198 }
199 
CheckDirection(sal_Bool bVert)200 void SwFlyFrm::CheckDirection( sal_Bool bVert )
201 {
202     const SwFrmFmt* pFmt = GetFmt();
203     if( pFmt )
204     {
205         const ViewShell *pSh = getRootFrm()->GetCurrShell();
206         const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
207         CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
208                     bVert, sal_False, bBrowseMode );
209     }
210     else
211         SwFrm::CheckDirection( bVert );
212 }
213 
CheckDirection(sal_Bool bVert)214 void SwTabFrm::CheckDirection( sal_Bool bVert )
215 {
216     const SwFrmFmt* pFmt = GetFmt();
217     if( pFmt )
218     {
219         const ViewShell *pSh = getRootFrm()->GetCurrShell();
220         const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
221         CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
222                     bVert, sal_True, bBrowseMode );
223     }
224     else
225         SwFrm::CheckDirection( bVert );
226 }
227 
CheckDirection(sal_Bool bVert)228 void SwCellFrm::CheckDirection( sal_Bool bVert )
229 {
230     const SwFrmFmt* pFmt = GetFmt();
231     const SfxPoolItem* pItem;
232     // --> FME 2006-03-30 #b6402837# Check if the item is set, before actually
233     // using it. Otherwise the dynamic pool default is used, which may be set
234     // to LTR in case of OOo 1.0 documents.
235     // <--
236     if( pFmt && SFX_ITEM_SET == pFmt->GetItemState( RES_FRAMEDIR, sal_True, &pItem ) )
237     {
238         const SvxFrameDirectionItem* pFrmDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
239         const ViewShell *pSh = getRootFrm()->GetCurrShell();
240         const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
241         CheckDir( pFrmDirItem->GetValue(), bVert, sal_False, bBrowseMode );
242     }
243     else
244         SwFrm::CheckDirection( bVert );
245 }
246 
CheckDirection(sal_Bool bVert)247 void SwTxtFrm::CheckDirection( sal_Bool bVert )
248 {
249     const ViewShell *pSh = getRootFrm()->GetCurrShell();
250     const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
251     CheckDir( GetTxtNode()->GetSwAttrSet().GetFrmDir().GetValue(), bVert,
252               sal_True, bBrowseMode );
253 }
254 
255 /*************************************************************************/
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)256 void SwFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
257 {
258     sal_uInt8 nInvFlags = 0;
259 
260     if( pNew && RES_ATTRSET_CHG == pNew->Which() )
261     {
262         SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
263         SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
264         while( sal_True )
265         {
266             _UpdateAttrFrm( (SfxPoolItem*)aOIter.GetCurItem(),
267                          (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags );
268             if( aNIter.IsAtEnd() )
269                 break;
270             aNIter.NextItem();
271             aOIter.NextItem();
272         }
273     }
274     else
275         _UpdateAttrFrm( pOld, pNew, nInvFlags );
276 
277     if ( nInvFlags != 0 )
278     {
279         SwPageFrm *pPage = FindPageFrm();
280         InvalidatePage( pPage );
281         if ( nInvFlags & 0x01 )
282         {
283             _InvalidatePrt();
284             if( !GetPrev() && IsTabFrm() && IsInSct() )
285                 FindSctFrm()->_InvalidatePrt();
286         }
287         if ( nInvFlags & 0x02 )
288             _InvalidateSize();
289         if ( nInvFlags & 0x04 )
290             _InvalidatePos();
291         if ( nInvFlags & 0x08 )
292             SetCompletePaint();
293         SwFrm *pNxt;
294         if ( nInvFlags & 0x30 && 0 != (pNxt = GetNext()) )
295         {
296             pNxt->InvalidatePage( pPage );
297             if ( nInvFlags & 0x10 )
298                 pNxt->_InvalidatePos();
299             if ( nInvFlags & 0x20 )
300                 pNxt->SetCompletePaint();
301         }
302     }
303 }
304 
_UpdateAttrFrm(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags)305 void SwFrm::_UpdateAttrFrm( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
306                          sal_uInt8 &rInvFlags )
307 {
308     sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
309     switch( nWhich )
310     {
311         case RES_BOX:
312         case RES_SHADOW:
313             Prepare( PREP_FIXSIZE_CHG );
314             // hier kein break !
315         case RES_LR_SPACE:
316         case RES_UL_SPACE:
317             rInvFlags |= 0x0B;
318             break;
319 
320         case RES_HEADER_FOOTER_EAT_SPACING:
321             rInvFlags |= 0x03;
322             break;
323 
324         case RES_BACKGROUND:
325             rInvFlags |= 0x28;
326             break;
327 
328         case RES_KEEP:
329             rInvFlags |= 0x04;
330             break;
331 
332         case RES_FRM_SIZE:
333             ReinitializeFrmSizeAttrFlags();
334             rInvFlags |= 0x13;
335             break;
336 
337         case RES_FMT_CHG:
338             rInvFlags |= 0x0F;
339             break;
340 
341         case RES_ROW_SPLIT:
342         {
343             if ( IsRowFrm() )
344             {
345                 sal_Bool bInFollowFlowRow = 0 != IsInFollowFlowRow();
346                 if ( bInFollowFlowRow || 0 != IsInSplitTableRow() )
347                 {
348                     SwTabFrm* pTab = FindTabFrm();
349                     if ( bInFollowFlowRow )
350                         pTab = pTab->FindMaster();
351                     pTab->SetRemoveFollowFlowLinePending( sal_True );
352                 }
353             }
354             break;
355         }
356         case RES_COL:
357             ASSERT( sal_False, "Spalten fuer neuen FrmTyp?" );
358             break;
359 
360         default:
361             /* do Nothing */;
362     }
363 }
364 
365 /*************************************************************************
366 |*
367 |*    SwFrm::Prepare()
368 |*    Ersterstellung    MA 13. Apr. 93
369 |*    Letzte Aenderung  MA 26. Jun. 96
370 |*
371 |*************************************************************************/
Prepare(const PrepareHint,const void *,sal_Bool)372 void SwFrm::Prepare( const PrepareHint, const void *, sal_Bool )
373 {
374     /* Do nothing */
375 }
376 
377 /*************************************************************************
378 |*
379 |*    SwFrm::InvalidatePage()
380 |*    Beschreibung:     Invalidiert die Seite, in der der Frm gerade steht.
381 |*      Je nachdem ob es ein Layout, Cntnt oder FlyFrm ist wird die Seite
382 |*      entsprechend Invalidiert.
383 |*    Ersterstellung    MA 22. Jul. 92
384 |*    Letzte Aenderung  MA 14. Oct. 94
385 |*
386 |*************************************************************************/
InvalidatePage(const SwPageFrm * pPage) const387 void SwFrm::InvalidatePage( const SwPageFrm *pPage ) const
388 {
389     if ( !pPage )
390     {
391         pPage = FindPageFrm();
392         // --> OD 2004-07-02 #i28701# - for at-character and as-character
393         // anchored Writer fly frames additionally invalidate also page frame
394         // its 'anchor character' is on.
395         if ( pPage && pPage->GetUpper() && IsFlyFrm() )
396         {
397             const SwFlyFrm* pFlyFrm = static_cast<const SwFlyFrm*>(this);
398             if ( pFlyFrm->IsAutoPos() || pFlyFrm->IsFlyInCntFrm() )
399             {
400                 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
401                 // is replaced by method <FindPageFrmOfAnchor()>. It's return value
402                 // have to be checked.
403                 SwPageFrm* pPageFrmOfAnchor =
404                         const_cast<SwFlyFrm*>(pFlyFrm)->FindPageFrmOfAnchor();
405                 if ( pPageFrmOfAnchor && pPageFrmOfAnchor != pPage )
406                 // <--
407                 {
408                     InvalidatePage( pPageFrmOfAnchor );
409                 }
410             }
411         }
412         // <--
413     }
414 
415     if ( pPage && pPage->GetUpper() )
416     {
417         if ( pPage->GetFmt()->GetDoc()->IsInDtor() )
418             return;
419 
420         SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
421         const SwFlyFrm *pFly = FindFlyFrm();
422         if ( IsCntntFrm() )
423         {
424             if ( pRoot->IsTurboAllowed() )
425             {
426                 // JP 21.09.95: wenn sich der ContentFrame 2 mal eintragen
427                 //              will, kann es doch eine TurboAction bleiben.
428                 //  ODER????
429                 if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
430                     pRoot->SetTurbo( (const SwCntntFrm*)this );
431                 else
432                 {
433                     pRoot->DisallowTurbo();
434                     //Die Seite des Turbo koennte eine andere als die meinige
435                     //sein, deshalb muss sie invalidiert werden.
436                     const SwFrm *pTmp = pRoot->GetTurbo();
437                     pRoot->ResetTurbo();
438                     pTmp->InvalidatePage();
439                 }
440             }
441             if ( !pRoot->GetTurbo() )
442             {
443                 if ( pFly )
444                 {   if( !pFly->IsLocked() )
445                     {
446                         if ( pFly->IsFlyInCntFrm() )
447                         {   pPage->InvalidateFlyInCnt();
448                             ((SwFlyInCntFrm*)pFly)->InvalidateCntnt();
449                             pFly->GetAnchorFrm()->InvalidatePage();
450                         }
451                         else
452                             pPage->InvalidateFlyCntnt();
453                     }
454                 }
455                 else
456                     pPage->InvalidateCntnt();
457             }
458         }
459         else
460         {
461             pRoot->DisallowTurbo();
462             if ( pFly )
463             {
464                 if ( !pFly->IsLocked() )
465                 {
466                     if ( pFly->IsFlyInCntFrm() )
467                     {
468                         pPage->InvalidateFlyInCnt();
469                         ((SwFlyInCntFrm*)pFly)->InvalidateLayout();
470                         pFly->GetAnchorFrm()->InvalidatePage();
471                     }
472                     else
473                         pPage->InvalidateFlyLayout();
474                 }
475             }
476             else
477                 pPage->InvalidateLayout();
478 
479             if ( pRoot->GetTurbo() )
480             {   const SwFrm *pTmp = pRoot->GetTurbo();
481                 pRoot->ResetTurbo();
482                 pTmp->InvalidatePage();
483             }
484         }
485         pRoot->SetIdleFlags();
486 
487         const SwTxtFrm *pTxtFrm = dynamic_cast< const SwTxtFrm * >(this);
488         if (pTxtFrm)
489         {
490             const SwTxtNode *pTxtNode = pTxtFrm->GetTxtNode();
491             if (pTxtNode && pTxtNode->IsGrammarCheckDirty())
492                 pRoot->SetNeedGrammarCheck( sal_True );
493         }
494     }
495 }
496 
497 /*************************************************************************
498 |*
499 |*  SwFrm::ChgSize()
500 |*
501 |*  Ersterstellung      AK 15-Feb-1991
502 |*  Letzte Aenderung    MA 18. Nov. 98
503 |*
504 |*************************************************************************/
ChgSize(const Size & aNewSize)505 Size SwFrm::ChgSize( const Size& aNewSize )
506 {
507     bFixSize = sal_True;
508     const Size aOldSize( Frm().SSize() );
509     if ( aNewSize == aOldSize )
510         return aOldSize;
511 
512     if ( GetUpper() )
513     {
514         SWRECTFN2( this )
515         SwRect aNew( Point(0,0), aNewSize );
516         (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
517         long nNew = (aNew.*fnRect->fnGetHeight)();
518         long nDiff = nNew - (aFrm.*fnRect->fnGetHeight)();
519         if( nDiff )
520         {
521             if ( GetUpper()->IsFtnBossFrm() && HasFixSize() &&
522                  NA_GROW_SHRINK !=
523                  ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this ) )
524             {
525                 (aFrm.*fnRect->fnSetHeight)( nNew );
526                 SwTwips nReal = ((SwLayoutFrm*)this)->AdjustNeighbourhood(nDiff);
527                 if ( nReal != nDiff )
528                     (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
529             }
530             else
531             {
532                 // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
533                 // NOTE: neighbour frames are cell and column frames.
534                 if ( !bNeighb )
535                 {
536                     if ( nDiff > 0 )
537                         Grow( nDiff );
538                     else
539                         Shrink( -nDiff );
540 
541                     if ( GetUpper() && (aFrm.*fnRect->fnGetHeight)() != nNew )
542                         GetUpper()->_InvalidateSize();
543                 }
544 
545                 // Auch wenn das Grow/Shrink noch nicht die gewuenschte Breite eingestellt hat,
546                 // wie z.B. beim Aufruf durch ChgColumns, um die Spaltenbreiten einzustellen,
547                 // wird die Breite jetzt gesetzt.
548                 (aFrm.*fnRect->fnSetHeight)( nNew );
549             }
550         }
551     }
552     else
553         aFrm.SSize( aNewSize );
554 
555     if ( Frm().SSize() != aOldSize )
556     {
557         SwPageFrm *pPage = FindPageFrm();
558         if ( GetNext() )
559         {
560             GetNext()->_InvalidatePos();
561             GetNext()->InvalidatePage( pPage );
562         }
563         if( IsLayoutFrm() )
564         {
565             if( IsRightToLeft() )
566                 _InvalidatePos();
567             if( ((SwLayoutFrm*)this)->Lower() )
568                 ((SwLayoutFrm*)this)->Lower()->_InvalidateSize();
569         }
570         _InvalidatePrt();
571         _InvalidateSize();
572         InvalidatePage( pPage );
573     }
574 
575     return aFrm.SSize();
576 }
577 
578 /*************************************************************************
579 |*
580 |*  SwFrm::InsertBefore()
581 |*
582 |*  Beschreibung        SwFrm wird in eine bestehende Struktur eingefuegt
583 |*                      Eingefuegt wird unterhalb des Parent und entweder
584 |*                      vor pBehind oder am Ende der Kette wenn pBehind
585 |*                      leer ist.
586 |*  Letzte Aenderung    MA 06. Aug. 99
587 |*
588 |*************************************************************************/
InsertBefore(SwLayoutFrm * pParent,SwFrm * pBehind)589 void SwFrm::InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind )
590 {
591     ASSERT( pParent, "Kein Parent fuer Insert." );
592     ASSERT( (!pBehind || (pBehind && pParent == pBehind->GetUpper())),
593             "Framebaum inkonsistent." );
594 
595     pUpper = pParent;
596     pNext = pBehind;
597     if( pBehind )
598     {   //Einfuegen vor pBehind.
599         if( 0 != (pPrev = pBehind->pPrev) )
600             pPrev->pNext = this;
601         else
602             pUpper->pLower = this;
603         pBehind->pPrev = this;
604     }
605     else
606     {   //Einfuegen am Ende, oder als ersten Node im Unterbaum
607         pPrev = pUpper->Lower();
608         if ( pPrev )
609         {
610             while( pPrev->pNext )
611                 pPrev = pPrev->pNext;
612             pPrev->pNext = this;
613         }
614         else
615             pUpper->pLower = this;
616     }
617 }
618 
619 /*************************************************************************
620 |*
621 |*  SwFrm::InsertBehind()
622 |*
623 |*  Beschreibung        SwFrm wird in eine bestehende Struktur eingefuegt
624 |*                      Eingefuegt wird unterhalb des Parent und entweder
625 |*                      hinter pBefore oder am Anfang der Kette wenn pBefore
626 |*                      leer ist.
627 |*  Letzte Aenderung    MA 06. Aug. 99
628 |*
629 |*************************************************************************/
InsertBehind(SwLayoutFrm * pParent,SwFrm * pBefore)630 void SwFrm::InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore )
631 {
632     ASSERT( pParent, "Kein Parent fuer Insert." );
633     ASSERT( (!pBefore || (pBefore && pParent == pBefore->GetUpper())),
634             "Framebaum inkonsistent." );
635 
636     pUpper = pParent;
637     pPrev = pBefore;
638     if ( pBefore )
639     {
640         //Einfuegen hinter pBefore
641         if ( 0 != (pNext = pBefore->pNext) )
642             pNext->pPrev = this;
643         pBefore->pNext = this;
644     }
645     else
646     {
647         //Einfuegen am Anfang der Kette
648         pNext = pParent->Lower();
649         if ( pParent->Lower() )
650             pParent->Lower()->pPrev = this;
651         pParent->pLower = this;
652     }
653 }
654 
655 /*************************************************************************
656 |*
657 |*  SwFrm::InsertGroup()
658 |*
659 |*  Beschreibung        Eine Kette von SwFrms wird in eine bestehende Struktur
660 |*                      eingefuegt
661 |*  Letzte Aenderung    AMA 9. Dec. 97
662 |*
663 |*  Bisher wird dies genutzt, um einen SectionFrame, der ggf. schon Geschwister
664 |*  mit sich bringt, in eine bestehende Struktur einzufuegen.
665 |*
666 |*  Wenn man den dritten Parameter als NULL uebergibt, entspricht
667 |*  diese Methode dem SwFrm::InsertBefore(..), nur eben mit Geschwistern.
668 |*
669 |*  Wenn man einen dritten Parameter uebergibt, passiert folgendes:
670 |*  this wird pNext von pParent,
671 |*  pSct wird pNext vom Letzten der this-Kette,
672 |*  pBehind wird vom pParent an den pSct umgehaengt.
673 |*  Dies dient dazu: ein SectionFrm (this) wird nicht als
674 |*  Kind an einen anderen SectionFrm (pParent) gehaengt, sondern pParent
675 |*  wird in zwei Geschwister aufgespalten (pParent+pSct) und this dazwischen
676 |*  eingebaut.
677 |*
678 |*************************************************************************/
InsertGroupBefore(SwFrm * pParent,SwFrm * pBehind,SwFrm * pSct)679 void SwFrm::InsertGroupBefore( SwFrm* pParent, SwFrm* pBehind, SwFrm* pSct )
680 {
681     ASSERT( pParent, "Kein Parent fuer Insert." );
682     ASSERT( (!pBehind || (pBehind && ( pParent == pBehind->GetUpper())
683             || ( pParent->IsSctFrm() && pBehind->GetUpper()->IsColBodyFrm() ) ) ),
684             "Framebaum inkonsistent." );
685     if( pSct )
686     {
687         pUpper = pParent->GetUpper();
688         SwFrm *pLast = this;
689         while( pLast->GetNext() )
690         {
691             pLast = pLast->GetNext();
692             pLast->pUpper = GetUpper();
693         }
694         if( pBehind )
695         {
696             pLast->pNext = pSct;
697             pSct->pPrev = pLast;
698             pSct->pNext = pParent->GetNext();
699         }
700         else
701         {
702             pLast->pNext = pParent->GetNext();
703             if( pLast->GetNext() )
704                 pLast->GetNext()->pPrev = pLast;
705         }
706         pParent->pNext = this;
707         pPrev = pParent;
708         if( pSct->GetNext() )
709             pSct->GetNext()->pPrev = pSct;
710         while( pLast->GetNext() )
711         {
712             pLast = pLast->GetNext();
713             pLast->pUpper = GetUpper();
714         }
715         if( pBehind )
716         {   //Einfuegen vor pBehind.
717             if( pBehind->GetPrev() )
718                 pBehind->GetPrev()->pNext = NULL;
719             else
720                 pBehind->GetUpper()->pLower = NULL;
721             pBehind->pPrev = NULL;
722             SwLayoutFrm* pTmp = (SwLayoutFrm*)pSct;
723             if( pTmp->Lower() )
724             {
725                 ASSERT( pTmp->Lower()->IsColumnFrm(), "InsertGrp: Used SectionFrm" );
726                 pTmp = (SwLayoutFrm*)((SwLayoutFrm*)pTmp->Lower())->Lower();
727                 ASSERT( pTmp, "InsertGrp: Missing ColBody" );
728             }
729             pBehind->pUpper = pTmp;
730             pBehind->GetUpper()->pLower = pBehind;
731             pLast = pBehind->GetNext();
732             while ( pLast )
733             {
734                 pLast->pUpper = pBehind->GetUpper();
735                 pLast = pLast->GetNext();
736             };
737         }
738         else
739         {
740             ASSERT( pSct->IsSctFrm(), "InsertGroup: For SectionFrms only" );
741             delete ((SwSectionFrm*)pSct);
742         }
743     }
744     else
745     {
746         pUpper = (SwLayoutFrm*)pParent;
747         SwFrm *pLast = this;
748         while( pLast->GetNext() )
749         {
750             pLast = pLast->GetNext();
751             pLast->pUpper = GetUpper();
752         }
753         pLast->pNext = pBehind;
754         if( pBehind )
755         {   //Einfuegen vor pBehind.
756             if( 0 != (pPrev = pBehind->pPrev) )
757                 pPrev->pNext = this;
758             else
759                 pUpper->pLower = this;
760             pBehind->pPrev = pLast;
761         }
762         else
763         {   //Einfuegen am Ende, oder des ersten Nodes im Unterbaum
764             pPrev = pUpper->Lower();
765             if ( pPrev )
766             {
767                 while( pPrev->pNext )
768                     pPrev = pPrev->pNext;
769                 pPrev->pNext = this;
770             }
771             else
772                 pUpper->pLower = this;
773         }
774     }
775 }
776 
777 /*************************************************************************
778 |*
779 |*  SwFrm::Remove()
780 |*
781 |*  Ersterstellung      AK 01-Mar-1991
782 |*  Letzte Aenderung    MA 07. Dec. 95
783 |*
784 |*************************************************************************/
Remove()785 void SwFrm::Remove()
786 {
787     ASSERT( pUpper, "Removen ohne Upper?" );
788 
789     if( pPrev )
790         // einer aus der Mitte wird removed
791         pPrev->pNext = pNext;
792     else
793     {   // der erste in einer Folge wird removed
794         ASSERT( pUpper->pLower == this, "Layout inkonsistent." );
795         pUpper->pLower = pNext;
796     }
797     if( pNext )
798         pNext->pPrev = pPrev;
799 
800     // Verbindung kappen.
801     pNext  = pPrev  = 0;
802     pUpper = 0;
803 }
804 /*************************************************************************
805 |*
806 |*  SwCntntFrm::Paste()
807 |*
808 |*  Ersterstellung      MA 23. Feb. 94
809 |*  Letzte Aenderung    MA 09. Sep. 98
810 |*
811 |*************************************************************************/
Paste(SwFrm * pParent,SwFrm * pSibling)812 void SwCntntFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
813 {
814     ASSERT( pParent, "Kein Parent fuer Paste." );
815     ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
816     ASSERT( pParent != this, "Bin selbst der Parent." );
817     ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
818     ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
819             "Bin noch irgendwo angemeldet." );
820     ASSERT( !pSibling || pSibling->IsFlowFrm(),
821             "<SwCntntFrm::Paste(..)> - sibling not of expected type." )
822 
823     //In den Baum einhaengen.
824     InsertBefore( (SwLayoutFrm*)pParent, pSibling );
825 
826     SwPageFrm *pPage = FindPageFrm();
827     _InvalidateAll();
828     InvalidatePage( pPage );
829 
830     if( pPage )
831     {
832         pPage->InvalidateSpelling();
833         pPage->InvalidateSmartTags();   // SMARTTAGS
834         pPage->InvalidateAutoCompleteWords();
835         pPage->InvalidateWordCount();
836     }
837 
838     if ( GetNext() )
839     {
840         SwFrm* pNxt = GetNext();
841         pNxt->_InvalidatePrt();
842         pNxt->_InvalidatePos();
843         pNxt->InvalidatePage( pPage );
844         if( pNxt->IsSctFrm() )
845             pNxt = ((SwSectionFrm*)pNxt)->ContainsCntnt();
846         if( pNxt && pNxt->IsTxtFrm() && pNxt->IsInFtn() )
847             pNxt->Prepare( PREP_FTN, 0, sal_False );
848     }
849 
850     if ( Frm().Height() )
851         pParent->Grow( Frm().Height() );
852 
853     if ( Frm().Width() != pParent->Prt().Width() )
854         Prepare( PREP_FIXSIZE_CHG );
855 
856     if ( GetPrev() )
857     {
858         if ( IsFollow() )
859             //Ich bin jetzt direkter Nachfolger meines Masters geworden
860             ((SwCntntFrm*)GetPrev())->Prepare( PREP_FOLLOW_FOLLOWS );
861         else
862         {
863             if ( GetPrev()->Frm().Height() !=
864                  GetPrev()->Prt().Height() + GetPrev()->Prt().Top() )
865                 //Umrandung zu beruecksichtigen?
866                 GetPrev()->_InvalidatePrt();
867             // OD 18.02.2003 #104989# - force complete paint of previous frame,
868             // if frame is inserted at the end of a section frame, in order to
869             // get subsidiary lines repainted for the section.
870             if ( pParent->IsSctFrm() && !GetNext() )
871             {
872                 // force complete paint of previous frame, if new inserted frame
873                 // in the section is the last one.
874                 GetPrev()->SetCompletePaint();
875             }
876             GetPrev()->InvalidatePage( pPage );
877         }
878     }
879     if ( IsInFtn() )
880     {
881         SwFrm* pFrm = GetIndPrev();
882         if( pFrm && pFrm->IsSctFrm() )
883             pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
884         if( pFrm )
885             pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
886         if( !GetNext() )
887         {
888             pFrm = FindFtnFrm()->GetNext();
889             if( pFrm && 0 != (pFrm=((SwLayoutFrm*)pFrm)->ContainsAny()) )
890                 pFrm->_InvalidatePrt();
891         }
892     }
893 
894     _InvalidateLineNum();
895     SwFrm *pNxt = FindNextCnt();
896     if ( pNxt  )
897     {
898         while ( pNxt && pNxt->IsInTab() )
899         {
900             if( 0 != (pNxt = pNxt->FindTabFrm()) )
901                 pNxt = pNxt->FindNextCnt();
902         }
903         if ( pNxt )
904         {
905             pNxt->_InvalidateLineNum();
906             if ( pNxt != GetNext() )
907                 pNxt->InvalidatePage();
908         }
909     }
910 }
911 
912 /*************************************************************************
913 |*
914 |*  SwCntntFrm::Cut()
915 |*
916 |*  Ersterstellung      AK 14-Feb-1991
917 |*  Letzte Aenderung    MA 09. Sep. 98
918 |*
919 |*************************************************************************/
Cut()920 void SwCntntFrm::Cut()
921 {
922     ASSERT( GetUpper(), "Cut ohne Upper()." );
923 
924     SwPageFrm *pPage = FindPageFrm();
925     InvalidatePage( pPage );
926     SwFrm *pFrm = GetIndPrev();
927     if( pFrm )
928     {
929         if( pFrm->IsSctFrm() )
930             pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
931         if ( pFrm && pFrm->IsCntntFrm() )
932         {
933             pFrm->_InvalidatePrt();
934             if( IsInFtn() )
935                 pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
936         }
937         // --> OD 2004-07-15 #i26250# - invalidate printing area of previous
938         // table frame.
939         else if ( pFrm && pFrm->IsTabFrm() )
940         {
941             pFrm->InvalidatePrt();
942         }
943         // <--
944     }
945 
946     SwFrm *pNxt = FindNextCnt();
947     if ( pNxt )
948     {
949         while ( pNxt && pNxt->IsInTab() )
950         {
951             if( 0 != (pNxt = pNxt->FindTabFrm()) )
952                 pNxt = pNxt->FindNextCnt();
953         }
954         if ( pNxt )
955         {
956             pNxt->_InvalidateLineNum();
957             if ( pNxt != GetNext() )
958                 pNxt->InvalidatePage();
959         }
960     }
961 
962     if( 0 != (pFrm = GetIndNext()) )
963     {   //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
964         //berechnet, der ist jetzt, wo er der erste wird obsolet bzw. anders.
965         pFrm->_InvalidatePrt();
966         pFrm->_InvalidatePos();
967         pFrm->InvalidatePage( pPage );
968         if( pFrm->IsSctFrm() )
969         {
970             pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
971             if( pFrm )
972             {
973                 pFrm->_InvalidatePrt();
974                 pFrm->_InvalidatePos();
975                 pFrm->InvalidatePage( pPage );
976             }
977         }
978         if( pFrm && IsInFtn() )
979             pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
980         if( IsInSct() && !GetPrev() )
981         {
982             SwSectionFrm* pSct = FindSctFrm();
983             if( !pSct->IsFollow() )
984             {
985                 pSct->_InvalidatePrt();
986                 pSct->InvalidatePage( pPage );
987             }
988         }
989     }
990     else
991     {
992         InvalidateNextPos();
993         //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
994         if ( 0 != (pFrm = GetPrev()) )
995         {   pFrm->SetRetouche();
996             pFrm->Prepare( PREP_WIDOWS_ORPHANS );
997             pFrm->_InvalidatePos();
998             pFrm->InvalidatePage( pPage );
999         }
1000         //Wenn ich der einzige CntntFrm in meinem Upper bin (war), so muss
1001         //er die Retouche uebernehmen.
1002         //Ausserdem kann eine Leerseite entstanden sein.
1003         else
1004         {   SwRootFrm *pRoot = getRootFrm();
1005             if ( pRoot )
1006             {
1007                 pRoot->SetSuperfluous();
1008                 GetUpper()->SetCompletePaint();
1009                 GetUpper()->InvalidatePage( pPage );
1010             }
1011             if( IsInSct() )
1012             {
1013                 SwSectionFrm* pSct = FindSctFrm();
1014                 if( !pSct->IsFollow() )
1015                 {
1016                     pSct->_InvalidatePrt();
1017                     pSct->InvalidatePage( pPage );
1018                 }
1019             }
1020             // --> FME 2005-08-03 #i52253# The master table should take care
1021             // of removing the follow flow line.
1022             if ( IsInTab() )
1023             {
1024                 SwTabFrm* pThisTab = FindTabFrm();
1025                 SwTabFrm* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : 0;
1026                 if ( pMasterTab )
1027                 {
1028                     pMasterTab->_InvalidatePos();
1029                     pMasterTab->SetRemoveFollowFlowLinePending( sal_True );
1030                 }
1031             }
1032             // <--
1033         }
1034     }
1035     //Erst removen, dann Upper Shrinken.
1036     SwLayoutFrm *pUp = GetUpper();
1037     Remove();
1038     if ( pUp )
1039     {
1040         SwSectionFrm *pSct = 0;
1041         if ( !pUp->Lower() &&
1042              ( ( pUp->IsFtnFrm() && !pUp->IsColLocked() ) ||
1043                ( pUp->IsInSct() &&
1044                  // -->  FME 2004-06-03 #i29438#
1045                  // We have to consider the case that the section may be "empty"
1046                  // except from a temporary empty table frame.
1047                  // This can happen due to the new cell split feature.
1048                  !pUp->IsCellFrm() &&
1049                  // <--
1050                  // --> OD 2006-01-04 #126020# - adjust check for empty section
1051                  // --> OD 2006-02-01 #130797# - correct fix #126020#
1052                  !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
1053                  !pSct->ContainsAny( true ) ) ) )
1054                  // <--
1055         {
1056             if ( pUp->GetUpper() )
1057             {
1058                 // --> OD 2006-09-25 #b6448963#
1059                 // prevent delete of <ColLocked> footnote frame
1060 //                if( pUp->IsFtnFrm() )
1061                 if ( pUp->IsFtnFrm() && !pUp->IsColLocked())
1062                 // <--
1063                 {
1064                     if( pUp->GetNext() && !pUp->GetPrev() )
1065                     {
1066                         SwFrm* pTmp = ((SwLayoutFrm*)pUp->GetNext())->ContainsAny();
1067                         if( pTmp )
1068                             pTmp->_InvalidatePrt();
1069                     }
1070                     pUp->Cut();
1071                     delete pUp;
1072                 }
1073                 else
1074                 {
1075                     // --> OD 2006-09-25 #b6448963#
1076 //                    if ( pSct->IsColLocked() || !pSct->IsInFtn() )
1077                     if ( pSct->IsColLocked() || !pSct->IsInFtn() ||
1078                          ( pUp->IsFtnFrm() && pUp->IsColLocked() ) )
1079                     // <--
1080                     {
1081                         pSct->DelEmpty( sal_False );
1082                         // Wenn ein gelockter Bereich nicht geloescht werden darf,
1083                         // so ist zumindest seine Groesse durch das Entfernen seines
1084                         // letzten Contents ungueltig geworden.
1085                         pSct->_InvalidateSize();
1086                     }
1087                     else
1088                     {
1089                         pSct->DelEmpty( sal_True );
1090                         delete pSct;
1091                     }
1092                 }
1093             }
1094         }
1095         else
1096         {
1097             SWRECTFN( this )
1098             long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1099             if( nFrmHeight )
1100                 pUp->Shrink( nFrmHeight );
1101         }
1102     }
1103 }
1104 
1105 /*************************************************************************
1106 |*
1107 |*  SwLayoutFrm::Paste()
1108 |*
1109 |*  Ersterstellung      MA 23. Feb. 94
1110 |*  Letzte Aenderung    MA 23. Feb. 94
1111 |*
1112 |*************************************************************************/
Paste(SwFrm * pParent,SwFrm * pSibling)1113 void SwLayoutFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
1114 {
1115     ASSERT( pParent, "Kein Parent fuer Paste." );
1116     ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
1117     ASSERT( pParent != this, "Bin selbst der Parent." );
1118     ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
1119     ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
1120             "Bin noch irgendwo angemeldet." );
1121 
1122     //In den Baum einhaengen.
1123     InsertBefore( (SwLayoutFrm*)pParent, pSibling );
1124 
1125     // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
1126     // <fnRect> is used for the following:
1127     // (1) To invalidate the frame's size, if its size, which has to be the
1128     //      same as its upper/parent, differs from its upper's/parent's.
1129     // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
1130     //      size, which is not determined by its upper/parent.
1131     // Which size is which depends on the frame type and the layout direction
1132     // (vertical or horizontal).
1133     // There are the following cases:
1134     // (A) Header and footer frames both in vertical and in horizontal layout
1135     //      have to size the width to the upper/parent. A dimension in the height
1136     //      has to cause a adjustment/grow of the upper/parent.
1137     //      --> <fnRect> = fnRectHori
1138     // (B) Cell and column frames in vertical layout, the width has to be the
1139     //          same as upper/parent and a dimension in height causes adjustment/grow
1140     //          of the upper/parent.
1141     //          --> <fnRect> = fnRectHori
1142     //      in horizontal layout the other way around
1143     //          --> <fnRect> = fnRectVert
1144     // (C) Other frames in vertical layout, the height has to be the
1145     //          same as upper/parent and a dimension in width causes adjustment/grow
1146     //          of the upper/parent.
1147     //          --> <fnRect> = fnRectVert
1148     //      in horizontal layout the other way around
1149     //          --> <fnRect> = fnRectHori
1150     //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
1151     SwRectFn fnRect;
1152     if ( IsHeaderFrm() || IsFooterFrm() )
1153         fnRect = fnRectHori;
1154     else if ( IsCellFrm() || IsColumnFrm() )
1155         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1156         fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert );
1157     else
1158         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1159         fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
1160 
1161 
1162     if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)())
1163         _InvalidateSize();
1164     _InvalidatePos();
1165     const SwPageFrm *pPage = FindPageFrm();
1166     InvalidatePage( pPage );
1167     SwFrm *pFrm;
1168     if( !IsColumnFrm() )
1169     {
1170         if( 0 != ( pFrm = GetIndNext() ) )
1171         {
1172             pFrm->_InvalidatePos();
1173             if( IsInFtn() )
1174             {
1175                 if( pFrm->IsSctFrm() )
1176                     pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
1177                 if( pFrm )
1178                     pFrm->Prepare( PREP_ERGOSUM, 0, sal_False );
1179             }
1180         }
1181         if ( IsInFtn() && 0 != ( pFrm = GetIndPrev() ) )
1182         {
1183             if( pFrm->IsSctFrm() )
1184                 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
1185             if( pFrm )
1186                 pFrm->Prepare( PREP_QUOVADIS, 0, sal_False );
1187         }
1188     }
1189 
1190     if( (Frm().*fnRect->fnGetHeight)() )
1191     {
1192         // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
1193         // die sich nicht in Rahmen befinden
1194         sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
1195                 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
1196                 : NA_GROW_SHRINK;
1197         SwTwips nGrow = (Frm().*fnRect->fnGetHeight)();
1198         if( NA_ONLY_ADJUST == nAdjust )
1199             AdjustNeighbourhood( nGrow );
1200         else
1201         {
1202             SwTwips nReal = 0;
1203             if( NA_ADJUST_GROW == nAdjust )
1204                 nReal = AdjustNeighbourhood( nGrow );
1205             if( nReal < nGrow )
1206                 nReal += pParent->Grow( nGrow - nReal );
1207             if( NA_GROW_ADJUST == nAdjust && nReal < nGrow )
1208                 AdjustNeighbourhood( nGrow - nReal );
1209         }
1210     }
1211 }
1212 
1213 /*************************************************************************
1214 |*
1215 |*  SwLayoutFrm::Cut()
1216 |*
1217 |*  Ersterstellung      MA 23. Feb. 94
1218 |*  Letzte Aenderung    MA 23. Feb. 94
1219 |*
1220 |*************************************************************************/
Cut()1221 void SwLayoutFrm::Cut()
1222 {
1223     if ( GetNext() )
1224         GetNext()->_InvalidatePos();
1225 
1226     SWRECTFN( this )
1227     SwTwips nShrink = (Frm().*fnRect->fnGetHeight)();
1228 
1229     //Erst removen, dann Upper Shrinken.
1230     SwLayoutFrm *pUp = GetUpper();
1231 
1232     // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
1233     // die sich nicht in Rahmen befinden
1234 
1235     // Remove must not be called before a AdjustNeighbourhood, but it has to
1236     // be called before the upper-shrink-call, if the upper-shrink takes care
1237     // of his content
1238     if ( pUp && nShrink )
1239     {
1240         if( pUp->IsFtnBossFrm() )
1241         {
1242             sal_uInt8 nAdjust= ((SwFtnBossFrm*)pUp)->NeighbourhoodAdjustment( this );
1243             if( NA_ONLY_ADJUST == nAdjust )
1244                 AdjustNeighbourhood( -nShrink );
1245             else
1246             {
1247                 SwTwips nReal = 0;
1248                 if( NA_ADJUST_GROW == nAdjust )
1249                     nReal = -AdjustNeighbourhood( -nShrink );
1250                 if( nReal < nShrink )
1251                 {
1252                     SwTwips nOldHeight = (Frm().*fnRect->fnGetHeight)();
1253                     (Frm().*fnRect->fnSetHeight)( 0 );
1254                     nReal += pUp->Shrink( nShrink - nReal );
1255                     (Frm().*fnRect->fnSetHeight)( nOldHeight );
1256                 }
1257                 if( NA_GROW_ADJUST == nAdjust && nReal < nShrink )
1258                     AdjustNeighbourhood( nReal - nShrink );
1259             }
1260             Remove();
1261         }
1262         else
1263         {
1264             Remove();
1265             pUp->Shrink( nShrink );
1266         }
1267     }
1268     else
1269         Remove();
1270 
1271     if( pUp && !pUp->Lower() )
1272     {
1273         pUp->SetCompletePaint();
1274         pUp->InvalidatePage();
1275     }
1276 }
1277 
1278 /*************************************************************************
1279 |*
1280 |*  SwFrm::Grow()
1281 |*
1282 |*  Ersterstellung      AK 19-Feb-1991
1283 |*  Letzte Aenderung    MA 05. May. 94
1284 |*
1285 |*************************************************************************/
Grow(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)1286 SwTwips SwFrm::Grow( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
1287 {
1288     ASSERT( nDist >= 0, "Negatives Wachstum?" );
1289 
1290     PROTOCOL_ENTER( this, bTst ? PROT_GROW_TST : PROT_GROW, 0, &nDist )
1291 
1292     if ( nDist )
1293     {
1294         SWRECTFN( this )
1295 
1296         SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1297         if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
1298             nDist = LONG_MAX - nPrtHeight;
1299 
1300         if ( IsFlyFrm() )
1301             return ((SwFlyFrm*)this)->_Grow( nDist, bTst );
1302         else if( IsSctFrm() )
1303             return ((SwSectionFrm*)this)->_Grow( nDist, bTst );
1304         else
1305         {
1306             const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
1307             if ( pThisCell )
1308             {
1309                 const SwTabFrm* pTab = FindTabFrm();
1310 
1311                 // NEW TABLES
1312                 if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
1313                      pThisCell->GetLayoutRowSpan() < 1 )
1314                     return 0;
1315             }
1316 
1317             const SwTwips nReal = GrowFrm( nDist, bTst, bInfo );
1318             if( !bTst )
1319             {
1320                 nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1321                 (Prt().*fnRect->fnSetHeight)( nPrtHeight +
1322                         ( IsCntntFrm() ? nDist : nReal ) );
1323             }
1324             return nReal;
1325         }
1326     }
1327     return 0L;
1328 }
1329 
1330 /*************************************************************************
1331 |*
1332 |*  SwFrm::Shrink()
1333 |*
1334 |*  Ersterstellung      AK 14-Feb-1991
1335 |*  Letzte Aenderung    MA 05. May. 94
1336 |*
1337 |*************************************************************************/
Shrink(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)1338 SwTwips SwFrm::Shrink( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
1339 {
1340     ASSERT( nDist >= 0, "Negative Verkleinerung?" );
1341 
1342     PROTOCOL_ENTER( this, bTst ? PROT_SHRINK_TST : PROT_SHRINK, 0, &nDist )
1343 
1344     if ( nDist )
1345     {
1346         if ( IsFlyFrm() )
1347             return ((SwFlyFrm*)this)->_Shrink( nDist, bTst );
1348         else if( IsSctFrm() )
1349             return ((SwSectionFrm*)this)->_Shrink( nDist, bTst );
1350         else
1351         {
1352             const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
1353             if ( pThisCell )
1354             {
1355                 const SwTabFrm* pTab = FindTabFrm();
1356 
1357                 // NEW TABLES
1358                 if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
1359                      pThisCell->GetLayoutRowSpan() < 1 )
1360                     return 0;
1361             }
1362 
1363             SWRECTFN( this )
1364             SwTwips nReal = (Frm().*fnRect->fnGetHeight)();
1365             ShrinkFrm( nDist, bTst, bInfo );
1366             nReal -= (Frm().*fnRect->fnGetHeight)();
1367             if( !bTst )
1368             {
1369                 const SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1370                 (Prt().*fnRect->fnSetHeight)( nPrtHeight -
1371                         ( IsCntntFrm() ? nDist : nReal ) );
1372             }
1373             return nReal;
1374         }
1375     }
1376     return 0L;
1377 }
1378 
1379 /*************************************************************************
1380 |*
1381 |*  SwFrm::AdjustNeighbourhood()
1382 |*
1383 |*  Beschreibung        Wenn sich die Groesse eines Frm's direkt unterhalb
1384 |*      eines Fussnotenbosses (Seite/Spalte) veraendert hat, so muss dieser
1385 |*      "Normalisiert" werden.
1386 |*      Es gibt dort immer einen Frame, der den "maximal moeglichen" Raum
1387 |*      einnimmt (der Frame, der den Body.Text enhaelt) und keinen oder
1388 |*      mehrere Frames die den Platz einnehmen den sie halt brauchen
1389 |*      (Kopf-/Fussbereich, Fussnoten).
1390 |*      Hat sich einer der Frames veraendert, so muss der Body-Text-Frame
1391 |*      entsprechen wachsen oder schrumpfen; unabhaegig davon, dass er fix ist.
1392 |*      !! Ist es moeglich dies allgemeiner zu loesen, also nicht auf die
1393 |*      Seite beschraenkt und nicht auf einen Speziellen Frame, der den
1394 |*      maximalen Platz einnimmt (gesteuert ueber Attribut FrmSize)? Probleme:
1395 |*      Was ist wenn mehrere Frames nebeneinander stehen, die den maximalen
1396 |*      Platz einnehmen?
1397 |*      Wie wird der Maximale Platz berechnet?
1398 |*      Wie klein duerfen diese Frames werden?
1399 |*
1400 |*      Es wird auf jeden Fall nur so viel Platz genehmigt, dass ein
1401 |*      Minimalwert fuer die Hoehe des Bodys nicht unterschritten wird.
1402 |*
1403 |*  Parameter: nDiff ist der Betrag, um den Platz geschaffen werden muss
1404 |*
1405 |*  Ersterstellung      MA 07. May. 92
1406 |*  Letzte Aenderung    AMA 02. Nov. 98
1407 |*
1408 |*************************************************************************/
AdjustNeighbourhood(SwTwips nDiff,sal_Bool bTst)1409 SwTwips SwFrm::AdjustNeighbourhood( SwTwips nDiff, sal_Bool bTst )
1410 {
1411     PROTOCOL_ENTER( this, PROT_ADJUSTN, 0, &nDiff );
1412 
1413     if ( !nDiff || !GetUpper()->IsFtnBossFrm() ) // nur innerhalb von Seiten/Spalten
1414         return 0L;
1415 
1416     const ViewShell *pSh = getRootFrm()->GetCurrShell();
1417     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1418 
1419     //Der (Page)Body veraendert sich nur im BrowseMode, aber nicht wenn er
1420     //Spalten enthaelt.
1421     if ( IsPageBodyFrm() && (!bBrowse ||
1422           (((SwLayoutFrm*)this)->Lower() &&
1423            ((SwLayoutFrm*)this)->Lower()->IsColumnFrm())) )
1424         return 0L;
1425 
1426     //In der BrowseView kann der PageFrm selbst ersteinmal einiges von den
1427     //Wuenschen abfangen.
1428     long nBrowseAdd = 0;
1429     if ( bBrowse && GetUpper()->IsPageFrm() ) // nur (Page)BodyFrms
1430     {
1431         ViewShell *pViewShell = getRootFrm()->GetCurrShell();
1432         SwLayoutFrm *pUp = GetUpper();
1433         long nChg;
1434         const long nUpPrtBottom = pUp->Frm().Height() -
1435                                   pUp->Prt().Height() - pUp->Prt().Top();
1436         SwRect aInva( pUp->Frm() );
1437         if ( pViewShell )
1438         {
1439             aInva.Pos().X() = pViewShell->VisArea().Left();
1440             aInva.Width( pViewShell->VisArea().Width() );
1441         }
1442         if ( nDiff > 0 )
1443         {
1444             nChg = BROWSE_HEIGHT - pUp->Frm().Height();
1445             nChg = Min( nDiff, nChg );
1446 
1447             if ( !IsBodyFrm() )
1448             {
1449                 SetCompletePaint();
1450                 if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->Frm().Height() )
1451                 {
1452                     //Ersteinmal den Body verkleinern. Der waechst dann schon
1453                     //wieder.
1454                     SwFrm *pBody = ((SwFtnBossFrm*)pUp)->FindBodyCont();
1455                     const long nTmp = nChg - pBody->Prt().Height();
1456                     if ( !bTst )
1457                     {
1458                         pBody->Frm().Height(Max( 0L, pBody->Frm().Height() - nChg ));
1459                         pBody->_InvalidatePrt();
1460                         pBody->_InvalidateSize();
1461                         if ( pBody->GetNext() )
1462                             pBody->GetNext()->_InvalidatePos();
1463                         if ( !IsHeaderFrm() )
1464                             pBody->SetCompletePaint();
1465                     }
1466                     nChg = nTmp <= 0 ? 0 : nTmp;
1467                 }
1468             }
1469 
1470             const long nTmp = nUpPrtBottom + 20;
1471             aInva.Top( aInva.Bottom() - nTmp );
1472             aInva.Height( nChg + nTmp );
1473         }
1474         else
1475         {
1476             //Die Seite kann bis auf 0 schrumpfen. Die erste Seite bleibt
1477             //mindestens so gross wie die VisArea.
1478             nChg = nDiff;
1479             long nInvaAdd = 0;
1480             if ( pViewShell && !pUp->GetPrev() &&
1481                  pUp->Frm().Height() + nDiff < pViewShell->VisArea().Height() )
1482             {
1483                 //Das heisst aber wiederum trotzdem, das wir geeignet invalidieren
1484                 //muessen.
1485                 nChg = pViewShell->VisArea().Height() - pUp->Frm().Height();
1486                 nInvaAdd = -(nDiff - nChg);
1487             }
1488 
1489             //Invalidieren inklusive unterem Rand.
1490             long nBorder = nUpPrtBottom + 20;
1491             nBorder -= nChg;
1492             aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
1493             if ( !IsBodyFrm() )
1494             {
1495                 SetCompletePaint();
1496                 if ( !IsHeaderFrm() )
1497                     ((SwFtnBossFrm*)pUp)->FindBodyCont()->SetCompletePaint();
1498             }
1499             //Wegen der Rahmen die Seite invalidieren. Dadurch wird die Seite
1500             //wieder entsprechend gross wenn ein Rahmen nicht passt. Das
1501             //funktioniert anderfalls nur zufaellig fuer absatzgebundene Rahmen
1502             //(NotifyFlys).
1503             pUp->InvalidateSize();
1504         }
1505         if ( !bTst )
1506         {
1507             //Unabhaengig von nChg
1508             if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
1509                 pViewShell->InvalidateWindows( aInva );
1510         }
1511         if ( !bTst && nChg )
1512         {
1513             const SwRect aOldRect( pUp->Frm() );
1514             pUp->Frm().SSize().Height() += nChg;
1515             pUp->Prt().SSize().Height() += nChg;
1516             if ( pViewShell )
1517                 pViewShell->Imp()->SetFirstVisPageInvalid();
1518 
1519             if ( GetNext() )
1520                 GetNext()->_InvalidatePos();
1521 
1522             //Ggf. noch ein Repaint ausloesen.
1523             const SvxGraphicPosition ePos = pUp->GetFmt()->GetBackground().GetGraphicPos();
1524             if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
1525                 pViewShell->InvalidateWindows( pUp->Frm() );
1526 
1527             if ( pUp->GetUpper() )
1528             {
1529                 if ( pUp->GetNext() )
1530                     pUp->GetNext()->InvalidatePos();
1531 
1532                 //Mies aber wahr: im Notify am ViewImp wird evtl. ein Calc
1533                 //auf die Seite und deren Lower gerufen. Die Werte sollten
1534                 //unverandert bleiben, weil der Aufrufer bereits fuer die
1535                 //Anpassung von Frm und Prt sorgen wird.
1536                 const long nOldFrmHeight = Frm().Height();
1537                 const long nOldPrtHeight = Prt().Height();
1538                 const sal_Bool bOldComplete = IsCompletePaint();
1539                 if ( IsBodyFrm() )
1540                     Prt().SSize().Height() = nOldFrmHeight;
1541 
1542                 // PAGES01
1543                 if ( pUp->GetUpper() )
1544                     static_cast<SwRootFrm*>(pUp->GetUpper())->CheckViewLayout( 0, 0 );
1545                 //((SwPageFrm*)pUp)->AdjustRootSize( CHG_CHGPAGE, &aOldRect );
1546 
1547                 Frm().SSize().Height() = nOldFrmHeight;
1548                 Prt().SSize().Height() = nOldPrtHeight;
1549                 bCompletePaint = bOldComplete;
1550             }
1551             if ( !IsBodyFrm() )
1552                 pUp->_InvalidateSize();
1553             InvalidatePage( (SwPageFrm*)pUp );
1554         }
1555         nDiff -= nChg;
1556         if ( !nDiff )
1557             return nChg;
1558         else
1559             nBrowseAdd = nChg;
1560     }
1561 
1562     const SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
1563 
1564     SwTwips nReal = 0,
1565             nAdd  = 0;
1566     SwFrm *pFrm = 0;
1567     SWRECTFN( this )
1568 
1569     if( IsBodyFrm() )
1570     {
1571         if( IsInSct() )
1572         {
1573             SwSectionFrm *pSect = FindSctFrm();
1574             if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
1575                 GetNext()->IsFtnContFrm() )
1576             {
1577                 SwFtnContFrm* pCont = (SwFtnContFrm*)GetNext();
1578                 SwTwips nMinH = 0;
1579                 SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
1580                 sal_Bool bFtn = sal_False;
1581                 while( pFtn )
1582                 {
1583                     if( !pFtn->GetAttr()->GetFtn().IsEndNote() )
1584                     {
1585                         nMinH += (pFtn->Frm().*fnRect->fnGetHeight)();
1586                         bFtn = sal_True;
1587                     }
1588                     pFtn = (SwFtnFrm*)pFtn->GetNext();
1589                 }
1590                 if( bFtn )
1591                     nMinH += (pCont->Prt().*fnRect->fnGetTop)();
1592                 nReal = (pCont->Frm().*fnRect->fnGetHeight)() - nMinH;
1593                 if( nReal > nDiff )
1594                     nReal = nDiff;
1595                 if( nReal > 0 )
1596                     pFrm = GetNext();
1597                 else
1598                     nReal = 0;
1599             }
1600             if( !bTst && !pSect->IsColLocked() )
1601                 pSect->InvalidateSize();
1602         }
1603         if( !pFrm )
1604             return nBrowseAdd;
1605     }
1606     else
1607     {
1608         const sal_Bool bFtnPage = pBoss->IsPageFrm() && ((SwPageFrm*)pBoss)->IsFtnPage();
1609         if ( bFtnPage && !IsFtnContFrm() )
1610             pFrm = (SwFrm*)pBoss->FindFtnCont();
1611         if ( !pFrm )
1612             pFrm = (SwFrm*)pBoss->FindBodyCont();
1613 
1614         if ( !pFrm )
1615             return 0;
1616 
1617         //Wenn ich keinen finde eruebrigt sich alles weitere.
1618         nReal = (pFrm->Frm().*fnRect->fnGetHeight)();
1619         if( nReal > nDiff )
1620             nReal = nDiff;
1621         if( !bFtnPage )
1622         {
1623             //Minimalgrenze beachten!
1624             if( nReal )
1625             {
1626                 const SwTwips nMax = pBoss->GetVarSpace();
1627                 if ( nReal > nMax )
1628                     nReal = nMax;
1629             }
1630             if( !IsFtnContFrm() && nDiff > nReal &&
1631                 pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm()
1632                 && ( pFrm->GetNext()->IsVertical() == IsVertical() )
1633                 )
1634             {
1635                 //Wenn der Body nicht genuegend her gibt, kann ich noch mal
1636                 //schauen ob es eine Fussnote gibt, falls ja kann dieser
1637                 //entsprechend viel gemopst werden.
1638                 const SwTwips nAddMax = (pFrm->GetNext()->Frm().*fnRect->
1639                                         fnGetHeight)();
1640                 nAdd = nDiff - nReal;
1641                 if ( nAdd > nAddMax )
1642                     nAdd = nAddMax;
1643                 if ( !bTst )
1644                 {
1645                     (pFrm->GetNext()->Frm().*fnRect->fnSetHeight)(nAddMax-nAdd);
1646                     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1647                     if( bVert && !bVertL2R && !bRev )
1648                         pFrm->GetNext()->Frm().Pos().X() += nAdd;
1649                     pFrm->GetNext()->InvalidatePrt();
1650                     if ( pFrm->GetNext()->GetNext() )
1651                         pFrm->GetNext()->GetNext()->_InvalidatePos();
1652                 }
1653             }
1654         }
1655     }
1656 
1657     if ( !bTst && nReal )
1658     {
1659         SwTwips nTmp = (pFrm->Frm().*fnRect->fnGetHeight)();
1660         (pFrm->Frm().*fnRect->fnSetHeight)( nTmp - nReal );
1661         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1662         if( bVert && !bVertL2R && !bRev )
1663             pFrm->Frm().Pos().X() += nReal;
1664         pFrm->InvalidatePrt();
1665         if ( pFrm->GetNext() )
1666             pFrm->GetNext()->_InvalidatePos();
1667         if( nReal < 0 && pFrm->IsInSct() )
1668         {
1669             SwLayoutFrm* pUp = pFrm->GetUpper();
1670             if( pUp && 0 != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrm() &&
1671                 !pUp->IsColLocked() )
1672                 pUp->InvalidateSize();
1673         }
1674         if( ( IsHeaderFrm() || IsFooterFrm() ) && pBoss->GetDrawObjs() )
1675         {
1676             const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
1677             ASSERT( pBoss->IsPageFrm(), "Header/Footer out of page?" );
1678             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1679             {
1680                 SwAnchoredObject* pAnchoredObj = rObjs[i];
1681                 if ( pAnchoredObj->ISA(SwFlyFrm) )
1682                 {
1683                     SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1684                     ASSERT( !pFly->IsFlyInCntFrm(), "FlyInCnt at Page?" );
1685                     const SwFmtVertOrient &rVert =
1686                                         pFly->GetFmt()->GetVertOrient();
1687                    // Wann muss invalidiert werden?
1688                    // Wenn ein Rahmen am SeitenTextBereich ausgerichtet ist,
1689                    // muss bei Aenderung des Headers ein TOP, MIDDLE oder NONE,
1690                    // bei Aenderung des Footers ein BOTTOM oder MIDDLE
1691                    // ausgerichteter Rahmen seine Position neu berechnen.
1692                     if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
1693                           rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA )    &&
1694                         ((IsHeaderFrm() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
1695                          (IsFooterFrm() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
1696                           rVert.GetVertOrient() != text::VertOrientation::TOP)) )
1697                     {
1698                         pFly->_InvalidatePos();
1699                         pFly->_Invalidate();
1700                     }
1701                 }
1702             }
1703         }
1704     }
1705     return (nBrowseAdd + nReal + nAdd);
1706 }
1707 
1708 /*************************************************************************
1709 |*
1710 |*  SwFrm::ImplInvalidateSize(), ImplInvalidatePrt(), ImplInvalidatePos(),
1711 |*         ImplInvalidateLineNum()
1712 |*
1713 |*  Ersterstellung      MA 15. Oct. 92
1714 |*  Letzte Aenderung    MA 24. Mar. 94
1715 |*
1716 |*************************************************************************/
1717 /** method to perform additional actions on an invalidation
1718 
1719     OD 2004-05-19 #i28701#
1720 
1721     @author OD
1722 */
_ActionOnInvalidation(const InvalidationType)1723 void SwFrm::_ActionOnInvalidation( const InvalidationType )
1724 {
1725     // default behaviour is to perform no additional action
1726 }
1727 
1728 /** method to determine, if an invalidation is allowed.
1729 
1730     OD 2004-05-19 #i28701#
1731 
1732     @author OD
1733 */
_InvalidationAllowed(const InvalidationType) const1734 bool SwFrm::_InvalidationAllowed( const InvalidationType ) const
1735 {
1736     // default behaviour is to allow invalidation
1737     return true;
1738 }
1739 
ImplInvalidateSize()1740 void SwFrm::ImplInvalidateSize()
1741 {
1742     if ( _InvalidationAllowed( INVALID_SIZE ) )
1743     {
1744         bValidSize = sal_False;
1745         if ( IsFlyFrm() )
1746             ((SwFlyFrm*)this)->_Invalidate();
1747         else
1748             InvalidatePage();
1749 
1750         // OD 2004-05-19 #i28701#
1751         _ActionOnInvalidation( INVALID_SIZE );
1752     }
1753 }
1754 
ImplInvalidatePrt()1755 void SwFrm::ImplInvalidatePrt()
1756 {
1757     if ( _InvalidationAllowed( INVALID_PRTAREA ) )
1758     {
1759         bValidPrtArea = sal_False;
1760         if ( IsFlyFrm() )
1761             ((SwFlyFrm*)this)->_Invalidate();
1762         else
1763             InvalidatePage();
1764 
1765         // OD 2004-05-19 #i28701#
1766         _ActionOnInvalidation( INVALID_PRTAREA );
1767     }
1768 }
1769 
ImplInvalidatePos()1770 void SwFrm::ImplInvalidatePos()
1771 {
1772     if ( _InvalidationAllowed( INVALID_POS ) )
1773     {
1774         bValidPos = sal_False;
1775         if ( IsFlyFrm() )
1776         {
1777             ((SwFlyFrm*)this)->_Invalidate();
1778         }
1779         else
1780         {
1781             InvalidatePage();
1782         }
1783 
1784         // OD 2004-05-19 #i28701#
1785         _ActionOnInvalidation( INVALID_POS );
1786     }
1787 }
1788 
ImplInvalidateLineNum()1789 void SwFrm::ImplInvalidateLineNum()
1790 {
1791     if ( _InvalidationAllowed( INVALID_LINENUM ) )
1792     {
1793         bValidLineNum = sal_False;
1794         ASSERT( IsTxtFrm(), "line numbers are implemented for text only" );
1795         InvalidatePage();
1796 
1797         // OD 2004-05-19 #i28701#
1798         _ActionOnInvalidation( INVALID_LINENUM );
1799     }
1800 }
1801 
1802 /*************************************************************************
1803 |*
1804 |*  SwFrm::ReinitializeFrmSizeAttrFlags
1805 |*
1806 |*  Ersterstellung      MA 15. Oct. 96
1807 |*  Letzte Aenderung    MA 15. Oct. 96
1808 |*
1809 |*************************************************************************/
ReinitializeFrmSizeAttrFlags()1810 void SwFrm::ReinitializeFrmSizeAttrFlags()
1811 {
1812     const SwFmtFrmSize &rFmtSize = GetAttrSet()->GetFrmSize();
1813     if ( ATT_VAR_SIZE == rFmtSize.GetHeightSizeType() ||
1814          ATT_MIN_SIZE == rFmtSize.GetHeightSizeType())
1815     {
1816         bFixSize = sal_False;
1817         if ( GetType() & (FRM_HEADER | FRM_FOOTER | FRM_ROW) )
1818         {
1819             SwFrm *pFrm = ((SwLayoutFrm*)this)->Lower();
1820             while ( pFrm )
1821             {   pFrm->_InvalidateSize();
1822                 pFrm->_InvalidatePrt();
1823                 pFrm = pFrm->GetNext();
1824             }
1825             SwCntntFrm *pCnt = ((SwLayoutFrm*)this)->ContainsCntnt();
1826             // --> OD 2004-12-20 #i36991# - be save.
1827             // E.g., a row can contain *no* content.
1828             if ( pCnt )
1829             {
1830                 pCnt->InvalidatePage();
1831                 do
1832                 {
1833                     pCnt->Prepare( PREP_ADJUST_FRM );
1834                     pCnt->_InvalidateSize();
1835                     pCnt = pCnt->GetNextCntntFrm();
1836                 } while ( ((SwLayoutFrm*)this)->IsAnLower( pCnt ) );
1837             }
1838             // <--
1839         }
1840     }
1841     else if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
1842     {
1843         if( IsVertical() )
1844             ChgSize( Size( rFmtSize.GetWidth(), Frm().Height()));
1845         else
1846             ChgSize( Size( Frm().Width(), rFmtSize.GetHeight()));
1847     }
1848 }
1849 
1850 /*************************************************************************
1851 |*  SwFrm::ValidateThisAndAllLowers()
1852  *
1853  * FME 2007-08-30 #i81146# new loop control
1854 |*************************************************************************/
ValidateThisAndAllLowers(const sal_uInt16 nStage)1855 void SwFrm::ValidateThisAndAllLowers( const sal_uInt16 nStage )
1856 {
1857     // Stage 0: Only validate frames. Do not process any objects.
1858     // Stage 1: Only validate fly frames and all of their contents.
1859     // Stage 2: Validate all.
1860 
1861     const bool bOnlyObject = 1 == nStage;
1862     const bool bIncludeObjects = 1 <= nStage;
1863 
1864     if ( !bOnlyObject || ISA(SwFlyFrm) )
1865     {
1866         bValidSize = sal_True;
1867         bValidPrtArea = sal_True;
1868         bValidPos = sal_True;
1869     }
1870 
1871     if ( bIncludeObjects )
1872     {
1873         const SwSortedObjs* pObjs = GetDrawObjs();
1874         if ( pObjs )
1875         {
1876             const sal_uInt32 nCnt = pObjs->Count();
1877             for ( sal_uInt32 i = 0; i < nCnt; ++i )
1878             {
1879                 SwAnchoredObject* pAnchObj = (*pObjs)[i];
1880                 if ( pAnchObj->ISA(SwFlyFrm) )
1881                     static_cast<SwFlyFrm*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
1882                 else if ( pAnchObj->ISA(SwAnchoredDrawObject) )
1883                     static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
1884             }
1885         }
1886     }
1887 
1888     if ( IsLayoutFrm() )
1889     {
1890         SwFrm* pLower = static_cast<SwLayoutFrm*>(this)->Lower();
1891         while ( pLower )
1892         {
1893             pLower->ValidateThisAndAllLowers( nStage );
1894             pLower = pLower->GetNext();
1895         }
1896     }
1897 }
1898 
1899 /*************************************************************************
1900 |*
1901 |*  SwCntntFrm::GrowFrm()
1902 |*
1903 |*  Ersterstellung      MA 30. Jul. 92
1904 |*  Letzte Aenderung    MA 25. Mar. 99
1905 |*
1906 |*************************************************************************/
GrowFrm(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)1907 SwTwips SwCntntFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
1908 {
1909     SWRECTFN( this )
1910 
1911     SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1912     if( nFrmHeight > 0 &&
1913          nDist > (LONG_MAX - nFrmHeight ) )
1914         nDist = LONG_MAX - nFrmHeight;
1915 
1916     const ViewShell *pSh = getRootFrm()->GetCurrShell();
1917     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1918     const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
1919     if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
1920     {
1921         if ( !bTst )
1922         {
1923             (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
1924             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1925             if( IsVertical() && !IsVertLR() && !IsReverse() )
1926                 Frm().Pos().X() -= nDist;
1927             if ( GetNext() )
1928             {
1929                 GetNext()->InvalidatePos();
1930             }
1931             // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
1932             // frame on the next page/column can flow backward (e.g. it was moved forward
1933             // due to the positioning of its objects ). Thus, invalivate this next frame,
1934             // if document compatibility option 'Consider wrapping style influence on
1935             // object positioning' is ON.
1936             else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
1937             {
1938                 InvalidateNextPos();
1939             }
1940             // <--
1941         }
1942         return 0;
1943     }
1944 
1945     SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
1946     SwFrm *pFrm = GetUpper()->Lower();
1947     while( pFrm && nReal > 0 )
1948     {   nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
1949         pFrm = pFrm->GetNext();
1950     }
1951 
1952     if ( !bTst )
1953     {
1954         //Cntnts werden immer auf den gewuenschten Wert gebracht.
1955         long nOld = (Frm().*fnRect->fnGetHeight)();
1956         (Frm().*fnRect->fnSetHeight)( nOld + nDist );
1957         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1958         if( IsVertical()&& !IsVertLR() && !IsReverse() )
1959             Frm().Pos().X() -= nDist;
1960         if ( nOld && IsInTab() )
1961         {
1962             SwTabFrm *pTab = FindTabFrm();
1963             if ( pTab->GetTable()->GetHTMLTableLayout() &&
1964                  !pTab->IsJoinLocked() &&
1965                  !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
1966             {
1967                 pTab->InvalidatePos();
1968                 pTab->SetResizeHTMLTable();
1969             }
1970         }
1971     }
1972 
1973     //Upper nur growen wenn notwendig.
1974     if ( nReal < nDist )
1975     {
1976         if( GetUpper() )
1977         {
1978             if( bTst || !GetUpper()->IsFooterFrm() )
1979                 nReal = GetUpper()->Grow( nDist - (nReal > 0 ? nReal : 0),
1980                                           bTst, bInfo );
1981             else
1982             {
1983                 nReal = 0;
1984                 GetUpper()->InvalidateSize();
1985             }
1986         }
1987         else
1988             nReal = 0;
1989     }
1990     else
1991         nReal = nDist;
1992 
1993     // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
1994     // frame on the next page/column can flow backward (e.g. it was moved forward
1995     // due to the positioning of its objects ). Thus, invalivate this next frame,
1996     // if document compatibility option 'Consider wrapping style influence on
1997     // object positioning' is ON.
1998     if ( !bTst )
1999     {
2000         if ( GetNext() )
2001         {
2002             GetNext()->InvalidatePos();
2003         }
2004         else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2005         {
2006             InvalidateNextPos();
2007         }
2008     }
2009     // <--
2010 
2011     return nReal;
2012 }
2013 
2014 /*************************************************************************
2015 |*
2016 |*  SwCntntFrm::ShrinkFrm()
2017 |*
2018 |*  Ersterstellung      MA 30. Jul. 92
2019 |*  Letzte Aenderung    MA 05. May. 94
2020 |*
2021 |*************************************************************************/
ShrinkFrm(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)2022 SwTwips SwCntntFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
2023 {
2024     SWRECTFN( this )
2025     ASSERT( nDist >= 0, "nDist < 0" );
2026     ASSERT( nDist <= (Frm().*fnRect->fnGetHeight)(),
2027             "nDist > als aktuelle Grosse." );
2028 
2029     if ( !bTst )
2030     {
2031         SwTwips nRstHeight;
2032         if( GetUpper() )
2033             nRstHeight = (Frm().*fnRect->fnBottomDist)
2034                          ( (GetUpper()->*fnRect->fnGetPrtBottom)() );
2035         else
2036             nRstHeight = 0;
2037         if( nRstHeight < 0 )
2038         {
2039             SwTwips nNextHeight = 0;
2040             if( GetUpper()->IsSctFrm() && nDist > LONG_MAX/2 )
2041             {
2042                 SwFrm *pNxt = GetNext();
2043                 while( pNxt )
2044                 {
2045                     nNextHeight += (pNxt->Frm().*fnRect->fnGetHeight)();
2046                     pNxt = pNxt->GetNext();
2047                 }
2048             }
2049             nRstHeight = nDist + nRstHeight - nNextHeight;
2050         }
2051         else
2052             nRstHeight = nDist;
2053         (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() - nDist );
2054         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2055         if( IsVertical() && !IsVertLR() )
2056             Frm().Pos().X() += nDist;
2057         nDist = nRstHeight;
2058         if ( IsInTab() )
2059         {
2060             SwTabFrm *pTab = FindTabFrm();
2061             if ( pTab->GetTable()->GetHTMLTableLayout() &&
2062                  !pTab->IsJoinLocked() &&
2063                  !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
2064             {
2065                 pTab->InvalidatePos();
2066                 pTab->SetResizeHTMLTable();
2067             }
2068         }
2069     }
2070 
2071     SwTwips nReal;
2072     if( GetUpper() && nDist > 0 )
2073     {
2074         if( bTst || !GetUpper()->IsFooterFrm() )
2075             nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
2076         else
2077         {
2078             nReal = 0;
2079 
2080             // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
2081             // if there are any objects anchored inside your content, which
2082             // overlap with the shrinking frame.
2083             // This may lead to a footer frame that is too big, but this is better
2084             // than looping.
2085             // #109722# : The fix for #108745# was too strict.
2086 
2087             bool bInvalidate = true;
2088             const SwRect aRect( Frm() );
2089             const SwPageFrm* pPage = FindPageFrm();
2090             const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : 0;
2091             if( pSorted )
2092             {
2093                 for ( sal_uInt16 i = 0; i < pSorted->Count(); ++i )
2094                 {
2095                     const SwAnchoredObject* pAnchoredObj = (*pSorted)[i];
2096                     const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
2097 
2098                     if( aBound.Left() > aRect.Right() )
2099                         continue;
2100 
2101                     if( aBound.IsOver( aRect ) )
2102                     {
2103                         const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
2104                         if( SURROUND_THROUGHT != rFmt.GetSurround().GetSurround() )
2105                         {
2106                             const SwFrm* pAnchor = pAnchoredObj->GetAnchorFrm();
2107                             if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
2108                             {
2109                                 bInvalidate = false;
2110                                 break;
2111                             }
2112                         }
2113                     }
2114                 }
2115             }
2116 
2117             if ( bInvalidate )
2118                 GetUpper()->InvalidateSize();
2119         }
2120     }
2121     else
2122         nReal = 0;
2123 
2124     if ( !bTst )
2125     {
2126         //Die Position des naechsten Frm's veraendert sich auf jeden Fall.
2127         InvalidateNextPos();
2128 
2129         //Wenn ich keinen Nachfolger habe, so muss ich mich eben selbst um
2130         //die Retusche kuemmern.
2131         if ( !GetNext() )
2132             SetRetouche();
2133     }
2134     return nReal;
2135 }
2136 
2137 /*************************************************************************
2138 |*
2139 |*    SwCntntFrm::Modify()
2140 |*
2141 |*    Beschreibung
2142 |*    Ersterstellung    AK 05-Mar-1991
2143 |*    Letzte Aenderung  MA 13. Oct. 95
2144 |*
2145 |*************************************************************************/
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2146 void SwCntntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
2147 {
2148     sal_uInt8 nInvFlags = 0;
2149 
2150     if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2151     {
2152         SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2153         SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2154         SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2155         SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2156         while( sal_True )
2157         {
2158             _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2159                          (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2160                          &aOldSet, &aNewSet );
2161             if( aNIter.IsAtEnd() )
2162                 break;
2163             aNIter.NextItem();
2164             aOIter.NextItem();
2165         }
2166         if ( aOldSet.Count() || aNewSet.Count() )
2167             SwFrm::Modify( &aOldSet, &aNewSet );
2168     }
2169     else
2170         _UpdateAttr( pOld, pNew, nInvFlags );
2171 
2172     if ( nInvFlags != 0 )
2173     {
2174         SwPageFrm *pPage = FindPageFrm();
2175         InvalidatePage( pPage );
2176         if ( nInvFlags & 0x01 )
2177             SetCompletePaint();
2178         if ( nInvFlags & 0x02 )
2179             _InvalidatePos();
2180         if ( nInvFlags & 0x04 )
2181             _InvalidateSize();
2182         if ( nInvFlags & 0x88 )
2183         {
2184             if( IsInSct() && !GetPrev() )
2185             {
2186                 SwSectionFrm *pSect = FindSctFrm();
2187                 if( pSect->ContainsAny() == this )
2188                 {
2189                     pSect->_InvalidatePrt();
2190                     pSect->InvalidatePage( pPage );
2191                 }
2192             }
2193             _InvalidatePrt();
2194         }
2195         SwFrm* pNextFrm = GetIndNext();
2196         if ( pNextFrm && nInvFlags & 0x10)
2197         {
2198             pNextFrm->_InvalidatePrt();
2199             pNextFrm->InvalidatePage( pPage );
2200         }
2201         if ( pNextFrm && nInvFlags & 0x80 )
2202         {
2203             pNextFrm->SetCompletePaint();
2204         }
2205         if ( nInvFlags & 0x20 )
2206         {
2207             SwFrm* pPrevFrm = GetPrev();
2208             if ( pPrevFrm )
2209             {
2210                 pPrevFrm->_InvalidatePrt();
2211                 pPrevFrm->InvalidatePage( pPage );
2212             }
2213         }
2214         if ( nInvFlags & 0x40 )
2215             InvalidateNextPos();
2216     }
2217 }
2218 
_UpdateAttr(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)2219 void SwCntntFrm::_UpdateAttr( const SfxPoolItem* pOld, const SfxPoolItem* pNew,
2220                               sal_uInt8 &rInvFlags,
2221                             SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2222 {
2223     sal_Bool bClear = sal_True;
2224     sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2225     switch ( nWhich )
2226     {
2227         case RES_FMT_CHG:
2228             rInvFlags = 0xFF;
2229             /* kein break hier */
2230 
2231         case RES_PAGEDESC:                      //Attributaenderung (an/aus)
2232             if ( IsInDocBody() && !IsInTab() )
2233             {
2234                 rInvFlags |= 0x02;
2235                 SwPageFrm *pPage = FindPageFrm();
2236                 if ( !GetPrev() )
2237                     CheckPageDescs( pPage );
2238                 if ( pPage && GetAttrSet()->GetPageDesc().GetNumOffset() )
2239                     ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
2240                 SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
2241                 pPage->GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
2242             }
2243             break;
2244 
2245         case RES_UL_SPACE:
2246             {
2247                 // OD 2004-02-18 #106629# - correction
2248                 // Invalidation of the printing area of next frame, not only
2249                 // for footnote content.
2250                 if ( !GetIndNext() )
2251                 {
2252                     SwFrm* pNxt = FindNext();
2253                     if ( pNxt )
2254                     {
2255                         SwPageFrm* pPg = pNxt->FindPageFrm();
2256                         pNxt->InvalidatePage( pPg );
2257                         pNxt->_InvalidatePrt();
2258                         if( pNxt->IsSctFrm() )
2259                         {
2260                             SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
2261                             if( pCnt )
2262                             {
2263                                 pCnt->_InvalidatePrt();
2264                                 pCnt->InvalidatePage( pPg );
2265                             }
2266                         }
2267                         pNxt->SetCompletePaint();
2268                     }
2269                 }
2270                 // OD 2004-03-17 #i11860#
2271                 if ( GetIndNext() &&
2272                      !GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
2273                 {
2274                     // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
2275                     GetIndNext()->InvalidateObjs( true );
2276                 }
2277                 Prepare( PREP_UL_SPACE );   //TxtFrm muss Zeilenabst. korrigieren.
2278                 rInvFlags |= 0x80;
2279                 /* kein Break hier */
2280             }
2281         case RES_LR_SPACE:
2282         case RES_BOX:
2283         case RES_SHADOW:
2284             Prepare( PREP_FIXSIZE_CHG );
2285             SwFrm::Modify( pOld, pNew );
2286             rInvFlags |= 0x30;
2287             break;
2288 
2289         case RES_BREAK:
2290             {
2291                 rInvFlags |= 0x42;
2292                 const IDocumentSettingAccess* pIDSA = GetUpper()->GetFmt()->getIDocumentSettingAccess();
2293                 if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
2294                     pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) )
2295                 {
2296                     rInvFlags |= 0x1;
2297                     SwFrm* pNxt = FindNext();
2298                     if( pNxt )
2299                     {
2300                         SwPageFrm* pPg = pNxt->FindPageFrm();
2301                         pNxt->InvalidatePage( pPg );
2302                         pNxt->_InvalidatePrt();
2303                         if( pNxt->IsSctFrm() )
2304                         {
2305                             SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
2306                             if( pCnt )
2307                             {
2308                                 pCnt->_InvalidatePrt();
2309                                 pCnt->InvalidatePage( pPg );
2310                             }
2311                         }
2312                         pNxt->SetCompletePaint();
2313                     }
2314                 }
2315             }
2316             break;
2317 
2318         // OD 2004-02-26 #i25029#
2319         case RES_PARATR_CONNECT_BORDER:
2320         {
2321             rInvFlags |= 0x01;
2322             if ( IsTxtFrm() )
2323             {
2324                 InvalidateNextPrtArea();
2325             }
2326             if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
2327             {
2328                 FindTabFrm()->InvalidateSize();
2329             }
2330         }
2331         break;
2332 
2333         case RES_PARATR_TABSTOP:
2334         case RES_CHRATR_PROPORTIONALFONTSIZE:
2335         case RES_CHRATR_SHADOWED:
2336         case RES_CHRATR_AUTOKERN:
2337         case RES_CHRATR_UNDERLINE:
2338         case RES_CHRATR_OVERLINE:
2339         case RES_CHRATR_KERNING:
2340         case RES_CHRATR_FONT:
2341         case RES_CHRATR_FONTSIZE:
2342         case RES_CHRATR_ESCAPEMENT:
2343         case RES_CHRATR_CONTOUR:
2344         case RES_PARATR_NUMRULE:
2345             rInvFlags |= 0x01;
2346             break;
2347 
2348 
2349         case RES_FRM_SIZE:
2350             rInvFlags |= 0x01;
2351             /* no break here */
2352 
2353         default:
2354             bClear = sal_False;
2355     }
2356     if ( bClear )
2357     {
2358         if ( pOldSet || pNewSet )
2359         {
2360             if ( pOldSet )
2361                 pOldSet->ClearItem( nWhich );
2362             if ( pNewSet )
2363                 pNewSet->ClearItem( nWhich );
2364         }
2365         else
2366             SwFrm::Modify( pOld, pNew );
2367     }
2368 }
2369 
2370 /*************************************************************************
2371 |*
2372 |*  SwLayoutFrm::SwLayoutFrm()
2373 |*
2374 |*  Ersterstellung      AK 14-Feb-1991
2375 |*  Letzte Aenderung    MA 12. May. 95
2376 |*
2377 |*************************************************************************/
SwLayoutFrm(SwFrmFmt * pFmt,SwFrm * pSib)2378 SwLayoutFrm::SwLayoutFrm( SwFrmFmt* pFmt, SwFrm* pSib ):
2379     SwFrm( pFmt, pSib ),
2380     pLower( 0 )
2381 {
2382     const SwFmtFrmSize &rFmtSize = pFmt->GetFrmSize();
2383     if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
2384         bFixSize = sal_True;
2385 }
2386 
2387 // --> OD 2004-06-29 #i28701#
2388 TYPEINIT1(SwLayoutFrm,SwFrm);
2389 // <--
2390 /*-----------------10.06.99 09:42-------------------
2391  * SwLayoutFrm::InnerHeight()
2392  * --------------------------------------------------*/
2393 
InnerHeight() const2394 SwTwips SwLayoutFrm::InnerHeight() const
2395 {
2396     if( !Lower() )
2397         return 0;
2398     SwTwips nRet = 0;
2399     const SwFrm* pCnt = Lower();
2400     SWRECTFN( this )
2401     if( pCnt->IsColumnFrm() || pCnt->IsCellFrm() )
2402     {
2403         do
2404         {
2405             SwTwips nTmp = ((SwLayoutFrm*)pCnt)->InnerHeight();
2406             if( pCnt->GetValidPrtAreaFlag() )
2407                 nTmp += (pCnt->Frm().*fnRect->fnGetHeight)() -
2408                         (pCnt->Prt().*fnRect->fnGetHeight)();
2409             if( nRet < nTmp )
2410                 nRet = nTmp;
2411             pCnt = pCnt->GetNext();
2412         } while ( pCnt );
2413     }
2414     else
2415     {
2416         do
2417         {
2418             nRet += (pCnt->Frm().*fnRect->fnGetHeight)();
2419             if( pCnt->IsCntntFrm() && ((SwTxtFrm*)pCnt)->IsUndersized() )
2420                 nRet += ((SwTxtFrm*)pCnt)->GetParHeight() -
2421                         (pCnt->Prt().*fnRect->fnGetHeight)();
2422             if( pCnt->IsLayoutFrm() && !pCnt->IsTabFrm() )
2423                 nRet += ((SwLayoutFrm*)pCnt)->InnerHeight() -
2424                         (pCnt->Prt().*fnRect->fnGetHeight)();
2425             pCnt = pCnt->GetNext();
2426         } while( pCnt );
2427 
2428     }
2429     return nRet;
2430 }
2431 
2432 /*************************************************************************
2433 |*
2434 |*  SwLayoutFrm::GrowFrm()
2435 |*
2436 |*  Ersterstellung      MA 30. Jul. 92
2437 |*  Letzte Aenderung    MA 23. Sep. 96
2438 |*
2439 |*************************************************************************/
GrowFrm(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)2440 SwTwips SwLayoutFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
2441 {
2442     const ViewShell *pSh = getRootFrm()->GetCurrShell();
2443     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
2444     const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
2445     if( !(GetType() & nTmpType) && HasFixSize() )
2446         return 0;
2447 
2448     SWRECTFN( this )
2449     const SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2450     const SwTwips nFrmPos = Frm().Pos().X();
2451 
2452     if ( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2453         nDist = LONG_MAX - nFrmHeight;
2454 
2455     SwTwips nMin = 0;
2456     if ( GetUpper() && !IsCellFrm() )
2457     {
2458         SwFrm *pFrm = GetUpper()->Lower();
2459         while( pFrm )
2460         {   nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
2461             pFrm = pFrm->GetNext();
2462         }
2463         nMin = (GetUpper()->Prt().*fnRect->fnGetHeight)() - nMin;
2464         if ( nMin < 0 )
2465             nMin = 0;
2466     }
2467 
2468     SwRect aOldFrm( Frm() );
2469     sal_Bool bMoveAccFrm = sal_False;
2470 
2471     sal_Bool bChgPos = IsVertical() && !IsReverse();
2472     if ( !bTst )
2473     {
2474         (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
2475         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2476         if( bChgPos && !IsVertLR() )
2477             Frm().Pos().X() -= nDist;
2478         bMoveAccFrm = sal_True;
2479     }
2480 
2481     SwTwips nReal = nDist - nMin;
2482     if ( nReal > 0 )
2483     {
2484         if ( GetUpper() )
2485         {   // AdjustNeighbourhood jetzt auch in Spalten (aber nicht in Rahmen)
2486             sal_uInt8 nAdjust = GetUpper()->IsFtnBossFrm() ?
2487                 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
2488                 : NA_GROW_SHRINK;
2489             if( NA_ONLY_ADJUST == nAdjust )
2490                 nReal = AdjustNeighbourhood( nReal, bTst );
2491             else
2492             {
2493                 if( NA_ADJUST_GROW == nAdjust )
2494                     nReal += AdjustNeighbourhood( nReal, bTst );
2495 
2496                 SwTwips nGrow = 0;
2497                 if( 0 < nReal )
2498                 {
2499                     SwFrm* pToGrow = GetUpper();
2500                     // NEW TABLES
2501                     // A cell with a row span of > 1 is allowed to grow the
2502                     // line containing the end of the row span if it is
2503                     // located in the same table frame:
2504                     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
2505                     if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2506                     {
2507                         SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
2508                         if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
2509                             pToGrow = rEndCell.GetUpper();
2510                         else
2511                             pToGrow = 0;
2512                     }
2513 
2514                     nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
2515                 }
2516 
2517                 if( NA_GROW_ADJUST == nAdjust && nGrow < nReal )
2518                     nReal += AdjustNeighbourhood( nReal - nGrow, bTst );
2519 
2520                 if ( IsFtnFrm() && (nGrow != nReal) && GetNext() )
2521                 {
2522                     //Fussnoten koennen ihre Nachfolger verdraengen.
2523                     SwTwips nSpace = bTst ? 0 : -nDist;
2524                     const SwFrm *pFrm = GetUpper()->Lower();
2525                     do
2526                     {   nSpace += (pFrm->Frm().*fnRect->fnGetHeight)();
2527                         pFrm = pFrm->GetNext();
2528                     } while ( pFrm != GetNext() );
2529                     nSpace = (GetUpper()->Prt().*fnRect->fnGetHeight)() -nSpace;
2530                     if ( nSpace < 0 )
2531                         nSpace = 0;
2532                     nSpace += nGrow;
2533                     if ( nReal > nSpace )
2534                         nReal = nSpace;
2535                     if ( nReal && !bTst )
2536                         ((SwFtnFrm*)this)->InvalidateNxtFtnCnts( FindPageFrm() );
2537                 }
2538                 else
2539                     nReal = nGrow;
2540             }
2541         }
2542         else
2543             nReal = 0;
2544 
2545         nReal += nMin;
2546     }
2547     else
2548         nReal = nDist;
2549 
2550     if ( !bTst )
2551     {
2552         if( nReal != nDist &&
2553             // NEW TABLES
2554             ( !IsCellFrm() || static_cast<SwCellFrm*>(this)->GetLayoutRowSpan() > 1 ) )
2555         {
2556             (Frm().*fnRect->fnSetHeight)( nFrmHeight + nReal );
2557             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2558             if( bChgPos && !IsVertLR() )
2559                 Frm().Pos().X() = nFrmPos - nReal;
2560             bMoveAccFrm = sal_True;
2561         }
2562 
2563         if ( nReal )
2564         {
2565             SwPageFrm *pPage = FindPageFrm();
2566             if ( GetNext() )
2567             {
2568                 GetNext()->_InvalidatePos();
2569                 if ( GetNext()->IsCntntFrm() )
2570                     GetNext()->InvalidatePage( pPage );
2571             }
2572             if ( !IsPageBodyFrm() )
2573             {
2574                 _InvalidateAll();
2575                 InvalidatePage( pPage );
2576             }
2577             if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
2578                 NotifyLowerObjs();
2579 
2580             if( IsCellFrm() )
2581                 InvaPercentLowers( nReal );
2582 
2583             const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
2584             if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2585                 SetCompletePaint();
2586         }
2587     }
2588 
2589     if( bMoveAccFrm && IsAccessibleFrm() )
2590     {
2591         SwRootFrm *pRootFrm = getRootFrm();
2592         if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2593             pRootFrm->GetCurrShell() )
2594         {
2595             pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
2596         }
2597     }
2598     return nReal;
2599 }
2600 
2601 /*************************************************************************
2602 |*
2603 |*  SwLayoutFrm::ShrinkFrm()
2604 |*
2605 |*  Ersterstellung      MA 30. Jul. 92
2606 |*  Letzte Aenderung    MA 25. Mar. 99
2607 |*
2608 |*************************************************************************/
ShrinkFrm(SwTwips nDist,sal_Bool bTst,sal_Bool bInfo)2609 SwTwips SwLayoutFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
2610 {
2611     const ViewShell *pSh = getRootFrm()->GetCurrShell();
2612     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
2613     const sal_uInt16 nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
2614     if( !(GetType() & nTmpType) && HasFixSize() )
2615         return 0;
2616 
2617     ASSERT( nDist >= 0, "nDist < 0" );
2618     SWRECTFN( this )
2619     SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2620     if ( nDist > nFrmHeight )
2621         nDist = nFrmHeight;
2622 
2623     SwTwips nMin = 0;
2624     sal_Bool bChgPos = IsVertical() && !IsReverse();
2625     if ( Lower() )
2626     {
2627         if( !Lower()->IsNeighbourFrm() )
2628         {   const SwFrm *pFrm = Lower();
2629             const long nTmp = (Prt().*fnRect->fnGetHeight)();
2630             while( pFrm && nMin < nTmp )
2631             {   nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
2632                 pFrm = pFrm->GetNext();
2633             }
2634         }
2635     }
2636     SwTwips nReal = nDist;
2637     SwTwips nMinDiff = (Prt().*fnRect->fnGetHeight)() - nMin;
2638     if( nReal > nMinDiff )
2639         nReal = nMinDiff;
2640     if( nReal <= 0 )
2641         return nDist;
2642 
2643     SwRect aOldFrm( Frm() );
2644     sal_Bool bMoveAccFrm = sal_False;
2645 
2646     SwTwips nRealDist = nReal;
2647     if ( !bTst )
2648     {
2649         (Frm().*fnRect->fnSetHeight)( nFrmHeight - nReal );
2650         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2651         if( bChgPos && !IsVertLR() )
2652             Frm().Pos().X() += nReal;
2653         bMoveAccFrm = sal_True;
2654     }
2655 
2656     sal_uInt8 nAdjust = GetUpper() && GetUpper()->IsFtnBossFrm() ?
2657                    ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
2658                    : NA_GROW_SHRINK;
2659 
2660     // AdjustNeighbourhood auch in Spalten (aber nicht in Rahmen)
2661     if( NA_ONLY_ADJUST == nAdjust )
2662     {
2663         if ( IsPageBodyFrm() && !bBrowse )
2664             nReal = nDist;
2665         else
2666         {   nReal = AdjustNeighbourhood( -nReal, bTst );
2667             nReal *= -1;
2668             if ( !bTst && IsBodyFrm() && nReal < nRealDist )
2669             {
2670                 (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
2671                                             + nRealDist - nReal );
2672                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2673                 if( bChgPos && !IsVertLR() )
2674                     Frm().Pos().X() += nRealDist - nReal;
2675                 ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
2676             }
2677         }
2678     }
2679     else if( IsColumnFrm() || IsColBodyFrm() )
2680     {
2681         SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
2682         if ( nTmp != nReal )
2683         {
2684             (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
2685                                           + nReal - nTmp );
2686             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2687             if( bChgPos && !IsVertLR() )
2688                 Frm().Pos().X() += nTmp - nReal;
2689             ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
2690             nReal = nTmp;
2691         }
2692     }
2693     else
2694     {
2695         SwTwips nShrink = nReal;
2696         SwFrm* pToShrink = GetUpper();
2697         const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
2698         // NEW TABLES
2699         if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2700         {
2701             SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
2702             pToShrink = rEndCell.GetUpper();
2703         }
2704 
2705         nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
2706         if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
2707             && nReal < nShrink )
2708             AdjustNeighbourhood( nReal - nShrink );
2709     }
2710 
2711     if( bMoveAccFrm && IsAccessibleFrm() )
2712     {
2713         SwRootFrm *pRootFrm = getRootFrm();
2714         if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2715             pRootFrm->GetCurrShell() )
2716         {
2717             pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
2718         }
2719     }
2720     if ( !bTst && (IsCellFrm() || IsColumnFrm() ? nReal : nRealDist) )
2721     {
2722         SwPageFrm *pPage = FindPageFrm();
2723         if ( GetNext() )
2724         {
2725             GetNext()->_InvalidatePos();
2726             if ( GetNext()->IsCntntFrm() )
2727                 GetNext()->InvalidatePage( pPage );
2728             if ( IsTabFrm() )
2729                 ((SwTabFrm*)this)->SetComplete();
2730         }
2731         else
2732         {   if ( IsRetoucheFrm() )
2733                 SetRetouche();
2734             if ( IsTabFrm() )
2735             {
2736                 if( IsTabFrm() )
2737                     ((SwTabFrm*)this)->SetComplete();
2738                 if ( Lower() )  //Kann auch im Join stehen und leer sein!
2739                     InvalidateNextPos();
2740             }
2741         }
2742         if ( !IsBodyFrm() )
2743         {
2744             _InvalidateAll();
2745             InvalidatePage( pPage );
2746             const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
2747             if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2748                 SetCompletePaint();
2749         }
2750 
2751         if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
2752             NotifyLowerObjs();
2753 
2754         if( IsCellFrm() )
2755             InvaPercentLowers( nReal );
2756 
2757         SwCntntFrm *pCnt;
2758         if( IsFtnFrm() && !((SwFtnFrm*)this)->GetAttr()->GetFtn().IsEndNote() &&
2759             ( GetFmt()->GetDoc()->GetFtnInfo().ePos != FTNPOS_CHAPTER ||
2760               ( IsInSct() && FindSctFrm()->IsFtnAtEnd() ) ) &&
2761               0 != (pCnt = ((SwFtnFrm*)this)->GetRefFromAttr() ) )
2762         {
2763             if ( pCnt->IsFollow() )
2764             {   // Wenn wir sowieso schon in einer anderen Spalte/Seite sitzen
2765                 // als der Frame mit der Referenz, dann brauchen wir nicht
2766                 // auch noch seinen Master zu invalidieren.
2767                 SwFrm *pTmp = pCnt->FindFtnBossFrm(sal_True) == FindFtnBossFrm(sal_True)
2768                               ?  pCnt->FindMaster()->GetFrm() : pCnt;
2769                 pTmp->Prepare( PREP_ADJUST_FRM );
2770                 pTmp->InvalidateSize();
2771             }
2772             else
2773                 pCnt->InvalidatePos();
2774         }
2775     }
2776     return nReal;
2777 }
2778 /*************************************************************************
2779 |*
2780 |*  SwLayoutFrm::ChgLowersProp()
2781 |*
2782 |*  Beschreibung        Aendert die Grosse der direkt untergeordneten Frm's
2783 |*      die eine Fixe Groesse haben, proportional zur Groessenaenderung der
2784 |*      PrtArea des Frm's.
2785 |*      Die Variablen Frm's werden auch proportional angepasst; sie werden
2786 |*      sich schon wieder zurechtwachsen/-schrumpfen.
2787 |*  Ersterstellung      MA 11.03.92
2788 |*  Letzte Aenderung    AMA 2. Nov. 98
2789 |*
2790 |*************************************************************************/
ChgLowersProp(const Size & rOldSize)2791 void SwLayoutFrm::ChgLowersProp( const Size& rOldSize )
2792 {
2793     // no change of lower properties for root frame or if no lower exists.
2794     if ( IsRootFrm() || !Lower() )
2795         return;
2796 
2797     // declare and init <SwFrm* pLowerFrm> with first lower
2798     SwFrm *pLowerFrm = Lower();
2799 
2800     // declare and init const booleans <bHeightChgd> and <bWidthChg>
2801     const bool bHeightChgd = rOldSize.Height() != Prt().Height();
2802     const bool bWidthChgd  = rOldSize.Width()  != Prt().Width();
2803 
2804     // declare and init variables <bVert>, <bRev> and <fnRect>
2805     SWRECTFN( this )
2806 
2807     // This shortcut basically tries to handle only lower frames that
2808     // are affected by the size change. Otherwise much more lower frames
2809     // are invalidated.
2810     if ( !( bVert ? bHeightChgd : bWidthChgd ) &&
2811          ! Lower()->IsColumnFrm() &&
2812            ( ( IsBodyFrm() && IsInDocBody() && ( !IsInSct() || !FindSctFrm()->IsColLocked() ) ) ||
2813                 // --> FME 2004-07-21 #i10826# Section frames without columns should not
2814                 // invalidate all lowers!
2815                IsSctFrm() ) )
2816                // <--
2817     {
2818         // Determine page frame the body frame resp. the section frame belongs to.
2819         SwPageFrm *pPage = FindPageFrm();
2820         // Determine last lower by traveling through them using <GetNext()>.
2821         // During travel check each section frame, if it will be sized to
2822         // maximum. If Yes, invalidate size of section frame and set
2823         // corresponding flags at the page.
2824         do
2825         {
2826             if( pLowerFrm->IsSctFrm() &&((SwSectionFrm*)pLowerFrm)->_ToMaximize() )
2827             {
2828                 pLowerFrm->_InvalidateSize();
2829                 pLowerFrm->InvalidatePage( pPage );
2830             }
2831             if( pLowerFrm->GetNext() )
2832                 pLowerFrm = pLowerFrm->GetNext();
2833             else
2834                 break;
2835         } while( sal_True );
2836         // If found last lower is a section frame containing no section
2837         // (section frame isn't valid and will be deleted in the future),
2838         // travel backwards.
2839         while( pLowerFrm->IsSctFrm() && !((SwSectionFrm*)pLowerFrm)->GetSection() &&
2840                pLowerFrm->GetPrev() )
2841             pLowerFrm = pLowerFrm->GetPrev();
2842         // If found last lower is a section frame, set <pLowerFrm> to its last
2843         // content, if the section frame is valid and is not sized to maximum.
2844         // Otherwise set <pLowerFrm> to NULL - In this case body frame only
2845         //      contains invalid section frames.
2846         if( pLowerFrm->IsSctFrm() )
2847             pLowerFrm = ((SwSectionFrm*)pLowerFrm)->GetSection() &&
2848                    !((SwSectionFrm*)pLowerFrm)->ToMaximize( sal_False ) ?
2849                    ((SwSectionFrm*)pLowerFrm)->FindLastCntnt() : NULL;
2850 
2851         // continue with found last lower, probably the last content of a section
2852         if ( pLowerFrm )
2853         {
2854             // If <pLowerFrm> is in a table frame, set <pLowerFrm> to this table
2855             // frame and continue.
2856             if ( pLowerFrm->IsInTab() )
2857             {
2858                 // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrm> to
2859                 // its table frame - check, if the table frame is also a lower
2860                 // of the body frame, in order to assure that <pLowerFrm> is not
2861                 // set to a frame, which is an *upper* of the body frame.
2862                 SwFrm* pTableFrm = pLowerFrm->FindTabFrm();
2863                 if ( IsAnLower( pTableFrm ) )
2864                 {
2865                     pLowerFrm = pTableFrm;
2866                 }
2867             }
2868             // Check, if variable size of body frame resp. section frame has grown
2869             // OD 28.10.2002 #97265# - correct check, if variable size has grown.
2870             SwTwips nOldHeight = bVert ? rOldSize.Width() : rOldSize.Height();
2871             if( nOldHeight < (Prt().*fnRect->fnGetHeight)() )
2872             {
2873                 // If variable size of body|section frame has grown, only found
2874                 // last lower and the position of the its next have to be invalidated.
2875                 pLowerFrm->_InvalidateAll();
2876                 pLowerFrm->InvalidatePage( pPage );
2877                 if( !pLowerFrm->IsFlowFrm() ||
2878                     !SwFlowFrm::CastFlowFrm( pLowerFrm )->HasFollow() )
2879                     pLowerFrm->InvalidateNextPos( sal_True );
2880                 if ( pLowerFrm->IsTxtFrm() )
2881                     ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2882             }
2883             else
2884             {
2885                 // variable size of body|section frame has shrinked. Thus,
2886                 // invalidate all lowers not matching the new body|section size
2887                 // and the dedicated new last lower.
2888                 if( bVert )
2889                 {
2890                     SwTwips nBot = Frm().Left() + Prt().Left();
2891                     while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Left() < nBot )
2892                     {
2893                         pLowerFrm->_InvalidateAll();
2894                         pLowerFrm->InvalidatePage( pPage );
2895                         pLowerFrm = pLowerFrm->GetPrev();
2896                     }
2897                 }
2898                 else
2899                 {
2900                     SwTwips nBot = Frm().Top() + Prt().Bottom();
2901                     while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Top() > nBot )
2902                     {
2903                         pLowerFrm->_InvalidateAll();
2904                         pLowerFrm->InvalidatePage( pPage );
2905                         pLowerFrm = pLowerFrm->GetPrev();
2906                     }
2907                 }
2908                 if ( pLowerFrm )
2909                 {
2910                     pLowerFrm->_InvalidateSize();
2911                     pLowerFrm->InvalidatePage( pPage );
2912                     if ( pLowerFrm->IsTxtFrm() )
2913                         ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2914                 }
2915             }
2916             // --> OD 2005-01-31 #i41694# - improvement by removing duplicates
2917             if ( pLowerFrm )
2918             {
2919                 if ( pLowerFrm->IsInSct() )
2920                 {
2921                     // --> OD 2005-01-31 #i41694# - follow-up of issue #i10826#:
2922                     // No invalidation of section frame, if it's the this.
2923                     SwFrm* pSectFrm = pLowerFrm->FindSctFrm();
2924                     if( pSectFrm != this && IsAnLower( pSectFrm ) )
2925                     {
2926                         pSectFrm->_InvalidateSize();
2927                         pSectFrm->InvalidatePage( pPage );
2928                     }
2929                     // <--
2930                 }
2931             }
2932             // <--
2933         }
2934         return;
2935     } // end of { special case }
2936 
2937 
2938     // Invalidate page for content only once.
2939     bool bInvaPageForCntnt = true;
2940 
2941     // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
2942     // adjustment, if fixed/variable size has changed.
2943     bool bFixChgd, bVarChgd;
2944     if( bVert == pLowerFrm->IsNeighbourFrm() )
2945     {
2946         bFixChgd = bWidthChgd;
2947         bVarChgd = bHeightChgd;
2948     }
2949     else
2950     {
2951         bFixChgd = bHeightChgd;
2952         bVarChgd = bWidthChgd;
2953     }
2954 
2955     // Declare const unsigned short <nFixWidth> and init it this frame types
2956     // which has fixed width in vertical respectively horizontal layout.
2957     // In vertical layout these are neighbour frames (cell and column frames),
2958     //      header frames and footer frames.
2959     // In horizontal layout these are all frames, which aren't neighbour frames.
2960     const sal_uInt16 nFixWidth = bVert ? (FRM_NEIGHBOUR | FRM_HEADFOOT)
2961                                    : ~FRM_NEIGHBOUR;
2962 
2963     // Declare const unsigned short <nFixHeight> and init it this frame types
2964     // which has fixed height in vertical respectively horizontal layout.
2965     // In vertical layout these are all frames, which aren't neighbour frames,
2966     //      header frames, footer frames, body frames or foot note container frames.
2967     // In horizontal layout these are neighbour frames.
2968     const sal_uInt16 nFixHeight= bVert ? ~(FRM_NEIGHBOUR | FRM_HEADFOOT | FRM_BODYFTNC)
2969                                    : FRM_NEIGHBOUR;
2970 
2971     // Travel through all lowers using <GetNext()>
2972     while ( pLowerFrm )
2973     {
2974         if ( pLowerFrm->IsTxtFrm() )
2975         {
2976             // Text frames will only be invalidated - prepare invalidation
2977             if ( bFixChgd )
2978                 static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_FIXSIZE_CHG );
2979             if ( bVarChgd )
2980                 static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2981         }
2982         else
2983         {
2984             // If lower isn't a table, row, cell or section frame, adjust its
2985             // frame size.
2986             const sal_uInt16 nLowerType = pLowerFrm->GetType();
2987             if ( !(nLowerType & (FRM_TAB|FRM_ROW|FRM_CELL|FRM_SECTION)) )
2988             {
2989                 if ( bWidthChgd )
2990                 {
2991                     if( nLowerType & nFixWidth )
2992                     {
2993                         // Considering previous conditions:
2994                         // In vertical layout set width of column, header and
2995                         // footer frames to its upper width.
2996                         // In horizontal layout set width of header, footer,
2997                         // foot note container, foot note, body and no-text
2998                         // frames to its upper width.
2999                         pLowerFrm->Frm().Width( Prt().Width() );
3000                     }
3001                     else if( rOldSize.Width() && !pLowerFrm->IsFtnFrm() )
3002                     {
3003                         // Adjust frame width proportional, if lower isn't a
3004                         // foot note frame and condition <nLowerType & nFixWidth>
3005                         // isn't true.
3006                         // Considering previous conditions:
3007                         // In vertical layout these are foot note container,
3008                         // body and no-text frames.
3009                         // In horizontal layout these are column and no-text frames.
3010                         // OD 24.10.2002 #97265# - <double> calculation
3011                         // Perform <double> calculation of new width, if
3012                         // one of the coefficients is greater than 50000
3013                         SwTwips nNewWidth;
3014                         if ( (pLowerFrm->Frm().Width() > 50000) ||
3015                              (Prt().Width() > 50000) )
3016                         {
3017                             double nNewWidthTmp =
3018                                 ( double(pLowerFrm->Frm().Width())
3019                                   * double(Prt().Width()) )
3020                                 / double(rOldSize.Width());
3021                             nNewWidth = SwTwips(nNewWidthTmp);
3022                         }
3023                         else
3024                         {
3025                             nNewWidth =
3026                                 (pLowerFrm->Frm().Width() * Prt().Width()) / rOldSize.Width();
3027                         }
3028                         pLowerFrm->Frm().Width( nNewWidth );
3029                     }
3030                 }
3031                 if ( bHeightChgd )
3032                 {
3033                     if( nLowerType & nFixHeight )
3034                     {
3035                         // Considering previous conditions:
3036                         // In vertical layout set height of foot note and
3037                         // no-text frames to its upper height.
3038                         // In horizontal layout set height of column frames
3039                         // to its upper height.
3040                         pLowerFrm->Frm().Height( Prt().Height() );
3041                     }
3042                     // OD 01.10.2002 #102211#
3043                     // add conditions <!pLowerFrm->IsHeaderFrm()> and
3044                     // <!pLowerFrm->IsFooterFrm()> in order to avoid that
3045                     // the <Grow> of header or footer are overwritten.
3046                     // NOTE: Height of header/footer frame is determined by contents.
3047                     else if ( rOldSize.Height() &&
3048                               !pLowerFrm->IsFtnFrm() &&
3049                               !pLowerFrm->IsHeaderFrm() &&
3050                               !pLowerFrm->IsFooterFrm()
3051                             )
3052                     {
3053                         // Adjust frame height proportional, if lower isn't a
3054                         // foot note, a header or a footer frame and
3055                         // condition <nLowerType & nFixHeight> isn't true.
3056                         // Considering previous conditions:
3057                         // In vertical layout these are column, foot note container,
3058                         // body and no-text frames.
3059                         // In horizontal layout these are column, foot note
3060                         // container, body and no-text frames.
3061 
3062                         // OD 29.10.2002 #97265# - special case for page lowers
3063                         // The page lowers that have to be adjusted on page height
3064                         // change are the body frame and the foot note container
3065                         // frame.
3066                         // In vertical layout the height of both is directly
3067                         // adjusted to the page height change.
3068                         // In horizontal layout the height of the body frame is
3069                         // directly adjsuted to the page height change and the
3070                         // foot note frame height isn't touched, because its
3071                         // determined by its content.
3072                         // OD 31.03.2003 #108446# - apply special case for page
3073                         // lowers - see description above - also for section columns.
3074                         if ( IsPageFrm() ||
3075                              ( IsColumnFrm() && IsInSct() )
3076                            )
3077                         {
3078                             ASSERT( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm(),
3079                                     "ChgLowersProp - only for body or foot note container" );
3080                             if ( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm() )
3081                             {
3082                                 if ( IsVertical() || pLowerFrm->IsBodyFrm() )
3083                                 {
3084                                     SwTwips nNewHeight =
3085                                             pLowerFrm->Frm().Height() +
3086                                             ( Prt().Height() - rOldSize.Height() );
3087                                     if ( nNewHeight < 0)
3088                                     {
3089                                         // OD 01.04.2003 #108446# - adjust assertion condition and text
3090                                         ASSERT( !( IsPageFrm() &&
3091                                                    (pLowerFrm->Frm().Height()>0) &&
3092                                                    (pLowerFrm->IsValid()) ),
3093                                                     "ChgLowersProg - negative height for lower.");
3094                                         nNewHeight = 0;
3095                                     }
3096                                     pLowerFrm->Frm().Height( nNewHeight );
3097                                 }
3098                             }
3099                         }
3100                         else
3101                         {
3102                             SwTwips nNewHeight;
3103                             // OD 24.10.2002 #97265# - <double> calculation
3104                             // Perform <double> calculation of new height, if
3105                             // one of the coefficients is greater than 50000
3106                             if ( (pLowerFrm->Frm().Height() > 50000) ||
3107                                  (Prt().Height() > 50000) )
3108                             {
3109                                 double nNewHeightTmp =
3110                                     ( double(pLowerFrm->Frm().Height())
3111                                       * double(Prt().Height()) )
3112                                     / double(rOldSize.Height());
3113                                 nNewHeight = SwTwips(nNewHeightTmp);
3114                             }
3115                             else
3116                             {
3117                                 nNewHeight = ( pLowerFrm->Frm().Height()
3118                                              * Prt().Height() ) / rOldSize.Height();
3119                             }
3120                             if( !pLowerFrm->GetNext() )
3121                             {
3122                                 SwTwips nSum = Prt().Height();
3123                                 SwFrm* pTmp = Lower();
3124                                 while( pTmp->GetNext() )
3125                                 {
3126                                     if( !pTmp->IsFtnContFrm() || !pTmp->IsVertical() )
3127                                         nSum -= pTmp->Frm().Height();
3128                                     pTmp = pTmp->GetNext();
3129                                 }
3130                                 if( nSum - nNewHeight == 1 &&
3131                                     nSum == pLowerFrm->Frm().Height() )
3132                                     nNewHeight = nSum;
3133                             }
3134                             pLowerFrm->Frm().Height( nNewHeight );
3135                         }
3136                     }
3137                 }
3138             }
3139         } // end of else { NOT text frame }
3140 
3141         pLowerFrm->_InvalidateAll();
3142         if ( bInvaPageForCntnt && pLowerFrm->IsCntntFrm() )
3143         {
3144             pLowerFrm->InvalidatePage();
3145             bInvaPageForCntnt = false;
3146         }
3147 
3148         if ( !pLowerFrm->GetNext() && pLowerFrm->IsRetoucheFrm() )
3149         {
3150             //Wenn ein Wachstum stattgefunden hat, und die untergeordneten
3151             //zur Retouche faehig sind (derzeit Tab, Section und Cntnt), so
3152             //trigger ich sie an.
3153             if ( rOldSize.Height() < Prt().SSize().Height() ||
3154                  rOldSize.Width() < Prt().SSize().Width() )
3155                 pLowerFrm->SetRetouche();
3156         }
3157         pLowerFrm = pLowerFrm->GetNext();
3158     }
3159 
3160     // Finally adjust the columns if width is set to auto
3161     // Possible optimisation: execute this code earlier in this function and
3162     // return???
3163     if ( ( (bVert && bHeightChgd) || (! bVert && bWidthChgd) ) &&
3164            Lower()->IsColumnFrm() )
3165     {
3166         // get column attribute
3167         const SwFmtCol* pColAttr = NULL;
3168         if ( IsPageBodyFrm() )
3169         {
3170             ASSERT( GetUpper()->IsPageFrm(), "Upper is not page frame" )
3171             pColAttr = &GetUpper()->GetFmt()->GetCol();
3172         }
3173         else
3174         {
3175             ASSERT( IsFlyFrm() || IsSctFrm(), "Columns not in fly or section" )
3176             pColAttr = &GetFmt()->GetCol();
3177         }
3178 
3179         if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
3180             AdjustColumns( pColAttr, sal_False );
3181     }
3182 }
3183 
3184 /*************************************************************************
3185 |*
3186 |*  SwLayoutFrm::Format()
3187 |*
3188 |*  Beschreibung:       "Formatiert" den Frame; Frm und PrtArea.
3189 |*                      Die Fixsize wird hier nicht eingestellt.
3190 |*  Ersterstellung      MA 28. Jul. 92
3191 |*  Letzte Aenderung    MA 21. Mar. 95
3192 |*
3193 |*************************************************************************/
Format(const SwBorderAttrs * pAttrs)3194 void SwLayoutFrm::Format( const SwBorderAttrs *pAttrs )
3195 {
3196     ASSERT( pAttrs, "LayoutFrm::Format, pAttrs ist 0." );
3197 
3198     if ( bValidPrtArea && bValidSize )
3199         return;
3200 
3201     const sal_uInt16 nLeft = (sal_uInt16)pAttrs->CalcLeft( this );
3202     const sal_uInt16 nUpper = pAttrs->CalcTop();
3203 
3204     const sal_uInt16 nRight = (sal_uInt16)((SwBorderAttrs*)pAttrs)->CalcRight( this );
3205     const sal_uInt16 nLower = pAttrs->CalcBottom();
3206     sal_Bool bVert = IsVertical() && !IsPageFrm();
3207     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
3208     SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
3209     if ( !bValidPrtArea )
3210     {
3211         bValidPrtArea = sal_True;
3212         (this->*fnRect->fnSetXMargins)( nLeft, nRight );
3213         (this->*fnRect->fnSetYMargins)( nUpper, nLower );
3214     }
3215 
3216     if ( !bValidSize )
3217     {
3218         if ( !HasFixSize() )
3219         {
3220             const SwTwips nBorder = nUpper + nLower;
3221             const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
3222             SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? rSz.GetHeight() : 0;
3223             do
3224             {   bValidSize = sal_True;
3225 
3226                 //Die Groesse in der VarSize wird durch den Inhalt plus den
3227                 //Raendern bestimmt.
3228                 SwTwips nRemaining = 0;
3229                 SwFrm *pFrm = Lower();
3230                 while ( pFrm )
3231                 {   nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
3232                     if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
3233                     // Dieser TxtFrm waere gern ein bisschen groesser
3234                         nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
3235                                       - (pFrm->Prt().*fnRect->fnGetHeight)();
3236                     else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
3237                         nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
3238                     pFrm = pFrm->GetNext();
3239                 }
3240                 nRemaining += nBorder;
3241                 nRemaining = Max( nRemaining, nMinHeight );
3242                 const SwTwips nDiff = nRemaining-(Frm().*fnRect->fnGetHeight)();
3243                 const long nOldLeft = (Frm().*fnRect->fnGetLeft)();
3244                 const long nOldTop = (Frm().*fnRect->fnGetTop)();
3245                 if ( nDiff )
3246                 {
3247                     if ( nDiff > 0 )
3248                         Grow( nDiff );
3249                     else
3250                         Shrink( -nDiff );
3251                     //Schnell auf dem kurzen Dienstweg die Position updaten.
3252                     MakePos();
3253                 }
3254                 //Unterkante des Uppers nicht ueberschreiten.
3255                 if ( GetUpper() && (Frm().*fnRect->fnGetHeight)() )
3256                 {
3257                     const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
3258                     if( (this->*fnRect->fnSetLimit)( nLimit ) &&
3259                         nOldLeft == (Frm().*fnRect->fnGetLeft)() &&
3260                         nOldTop  == (Frm().*fnRect->fnGetTop)() )
3261                         bValidSize = bValidPrtArea = sal_True;
3262                 }
3263             } while ( !bValidSize );
3264         }
3265         else if ( GetType() & 0x0018 )
3266         {
3267             do
3268             {   if ( Frm().Height() != pAttrs->GetSize().Height() )
3269                     ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
3270                 bValidSize = sal_True;
3271                 MakePos();
3272             } while ( !bValidSize );
3273         }
3274         else
3275             bValidSize = sal_True;
3276     }
3277 }
3278 
3279 /*************************************************************************
3280 |*
3281 |*  SwLayoutFrm::InvalidatePercentLowers()
3282 |*
3283 |*  Ersterstellung      MA 13. Jun. 96
3284 |*  Letzte Aenderung    MA 13. Jun. 96
3285 |*
3286 |*************************************************************************/
InvaPercentFlys(SwFrm * pFrm,SwTwips nDiff)3287 static void InvaPercentFlys( SwFrm *pFrm, SwTwips nDiff )
3288 {
3289     ASSERT( pFrm->GetDrawObjs(), "Can't find any Objects" );
3290     for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
3291     {
3292         SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
3293         if ( pAnchoredObj->ISA(SwFlyFrm) )
3294         {
3295             SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3296             const SwFmtFrmSize &rSz = pFly->GetFmt()->GetFrmSize();
3297             if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3298             {
3299                 sal_Bool bNotify = sal_True;
3300                 // If we've a fly with more than 90% relative height...
3301                 if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrm() &&
3302                     rSz.GetHeightPercent() != 0xFF && nDiff )
3303                 {
3304                     const SwFrm *pRel = pFly->IsFlyLayFrm() ? pFly->GetAnchorFrm():
3305                                         pFly->GetAnchorFrm()->GetUpper();
3306                     // ... and we have already more than 90% height and we
3307                     // not allow the text to go through...
3308                     // then a notifycation could cause an endless loop, e.g.
3309                     // 100% height and no text wrap inside a cell of a table.
3310                     if( pFly->Frm().Height()*10 >
3311                         ( nDiff + pRel->Prt().Height() )*9 &&
3312                         pFly->GetFmt()->GetSurround().GetSurround() !=
3313                         SURROUND_THROUGHT )
3314                        bNotify = sal_False;
3315                 }
3316                 if( bNotify )
3317                     pFly->InvalidateSize();
3318             }
3319         }
3320     }
3321 }
3322 
InvaPercentLowers(SwTwips nDiff)3323 void SwLayoutFrm::InvaPercentLowers( SwTwips nDiff )
3324 {
3325     if ( GetDrawObjs() )
3326         ::InvaPercentFlys( this, nDiff );
3327 
3328     SwFrm *pFrm = ContainsCntnt();
3329     if ( pFrm )
3330         do
3331         {
3332             if ( pFrm->IsInTab() && !IsTabFrm() )
3333             {
3334                 SwFrm *pTmp = pFrm->FindTabFrm();
3335                 ASSERT( pTmp, "Where's my TabFrm?" );
3336                 if( IsAnLower( pTmp ) )
3337                     pFrm = pTmp;
3338             }
3339 
3340             if ( pFrm->IsTabFrm() )
3341             {
3342                 const SwFmtFrmSize &rSz = ((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize();
3343                 if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3344                     pFrm->InvalidatePrt();
3345             }
3346             else if ( pFrm->GetDrawObjs() )
3347                 ::InvaPercentFlys( pFrm, nDiff );
3348             pFrm = pFrm->FindNextCnt();
3349         } while ( pFrm && IsAnLower( pFrm ) ) ;
3350 }
3351 
3352 /*************************************************************************
3353 |*
3354 |*  SwLayoutFrm::CalcRel()
3355 |*
3356 |*  Ersterstellung      MA 13. Jun. 96
3357 |*  Letzte Aenderung    MA 10. Oct. 96
3358 |*
3359 |*************************************************************************/
CalcRel(const SwFmtFrmSize & rSz,sal_Bool) const3360 long SwLayoutFrm::CalcRel( const SwFmtFrmSize &rSz, sal_Bool ) const
3361 {
3362     long nRet     = rSz.GetWidth(),
3363          nPercent = rSz.GetWidthPercent();
3364 
3365     if ( nPercent )
3366     {
3367         const SwFrm *pRel = GetUpper();
3368         long nRel = LONG_MAX;
3369         const ViewShell *pSh = getRootFrm()->GetCurrShell();
3370         const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
3371         if( pRel->IsPageBodyFrm() && pSh && bBrowseMode && pSh->VisArea().Width() )
3372         {
3373             nRel = pSh->GetBrowseWidth();
3374             long nDiff = nRel - pRel->Prt().Width();
3375             if ( nDiff > 0 )
3376                 nRel -= nDiff;
3377         }
3378         nRel = Min( nRel, pRel->Prt().Width() );
3379         nRet = nRel * nPercent / 100;
3380     }
3381     return nRet;
3382 }
3383 
3384 /*************************************************************************
3385 |*  Local helpers for SwLayoutFrm::FormatWidthCols()
3386 |*************************************************************************/
lcl_CalcMinColDiff(SwLayoutFrm * pLayFrm)3387 long MA_FASTCALL lcl_CalcMinColDiff( SwLayoutFrm *pLayFrm )
3388 {
3389     long nDiff = 0, nFirstDiff = 0;
3390     SwLayoutFrm *pCol = (SwLayoutFrm*)pLayFrm->Lower();
3391     ASSERT( pCol, "Where's the columnframe?" );
3392     SwFrm *pFrm = pCol->Lower();
3393     do
3394     {
3395         if( pFrm && pFrm->IsBodyFrm() )
3396             pFrm = ((SwBodyFrm*)pFrm)->Lower();
3397         if ( pFrm && pFrm->IsTxtFrm() )
3398         {
3399             const long nTmp = ((SwTxtFrm*)pFrm)->FirstLineHeight();
3400             if ( nTmp != USHRT_MAX )
3401             {
3402                 if ( pCol == pLayFrm->Lower() )
3403                     nFirstDiff = nTmp;
3404                 else
3405                     nDiff = nDiff ? Min( nDiff, nTmp ) : nTmp;
3406             }
3407         }
3408         //Leere Spalten ueberspringen!
3409         pCol = (SwLayoutFrm*)pCol->GetNext();
3410         while ( pCol && 0 == (pFrm = pCol->Lower()) )
3411             pCol = (SwLayoutFrm*)pCol->GetNext();
3412 
3413     } while ( pFrm && pCol );
3414 
3415     return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
3416 }
3417 
lcl_IsFlyHeightClipped(SwLayoutFrm * pLay)3418 sal_Bool lcl_IsFlyHeightClipped( SwLayoutFrm *pLay )
3419 {
3420     SwFrm *pFrm = pLay->ContainsCntnt();
3421     while ( pFrm )
3422     {
3423         if ( pFrm->IsInTab() )
3424             pFrm = pFrm->FindTabFrm();
3425 
3426         if ( pFrm->GetDrawObjs() )
3427         {
3428             sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
3429             for ( sal_uInt16 i = 0; i < nCnt; ++i )
3430             {
3431                 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
3432                 if ( pAnchoredObj->ISA(SwFlyFrm) )
3433                 {
3434                     SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3435                     if ( pFly->IsHeightClipped() &&
3436                          ( !pFly->IsFlyFreeFrm() || pFly->GetPageFrm() ) )
3437                         return sal_True;
3438                 }
3439             }
3440         }
3441         pFrm = pFrm->FindNextCnt();
3442     }
3443     return sal_False;
3444 }
3445 
3446 /*************************************************************************
3447 |*  SwLayoutFrm::FormatWidthCols()
3448 |*************************************************************************/
FormatWidthCols(const SwBorderAttrs & rAttrs,const SwTwips nBorder,const SwTwips nMinHeight)3449 void SwLayoutFrm::FormatWidthCols( const SwBorderAttrs &rAttrs,
3450                                    const SwTwips nBorder, const SwTwips nMinHeight )
3451 {
3452     //Wenn Spalten im Spiel sind, so wird die Groesse an der
3453     //letzten Spalte ausgerichtet.
3454     //1. Inhalt formatieren.
3455     //2. Hoehe der letzten Spalte ermitteln, wenn diese zu
3456     //   zu gross ist muss der Fly wachsen.
3457     //   Der Betrag um den der Fly waechst ist aber nicht etwa
3458     //   der Betrag des Ueberhangs, denn wir muessen davon
3459     //   ausgehen, dass etwas Masse zurueckfliesst und so
3460     //   zusaetzlicher Platz geschaffen wird.
3461     //   Im Ersten Ansatz ist der Betrag um den gewachsen wird
3462     //   der Ueberhang geteilt durch die Spaltenanzahl oder
3463     //   der Ueberhang selbst wenn er kleiner als die Spalten-
3464     //   anzahl ist.
3465     //3. Weiter mit 1. bis zur Stabilitaet.
3466 
3467     const SwFmtCol &rCol = rAttrs.GetAttrSet().GetCol();
3468     const sal_uInt16 nNumCols = rCol.GetNumCols();
3469 
3470     sal_Bool bEnd = sal_False;
3471     sal_Bool bBackLock = sal_False;
3472     ViewShell *pSh = getRootFrm()->GetCurrShell();
3473     SwViewImp *pImp = pSh ? pSh->Imp() : 0;
3474     {
3475         // Zugrunde liegender Algorithmus
3476         // Es wird versucht, eine optimale Hoehe fuer die Spalten zu finden.
3477         // nMinimum beginnt mit der uebergebenen Mindesthoehe und wird dann als
3478         // Maximum der Hoehen gepflegt, bei denen noch Spalteninhalt aus einer
3479         // Spalte herausragt.
3480         // nMaximum beginnt bei LONG_MAX und wird als Minimum der Hoehen gepflegt,
3481         // bei denen der Inhalt gepasst hat.
3482         // Bei spaltigen Bereichen beginnt nMaximum bei dem maximalen Wert, den
3483         // die Umgebung vorgibt, dies kann natuerlich ein Wert sein, bei dem noch
3484         // Inhalt heraushaengt.
3485         // Es werden die Spalten formatiert, wenn Inhalt heraushaengt, wird nMinimum
3486         // ggf. angepasst, dann wird gewachsen, mindestens um nMinDiff, aber nicht ueber
3487         // ein groesseres nMaximum hinaus. Wenn kein Inhalt heraushaengt, sondern
3488         // noch Luft in einer Spalte ist, schrumpfen wir entsprechend, mindestens um
3489         // nMinDiff, aber nicht unter das nMinimum.
3490         // Abgebrochen wird, wenn kein Inhalt mehr heraushaengt und das Minimum sich auf
3491         // weniger als ein MinDiff dem Maximum angenaehert hat oder das von der
3492         // Umgebung vorgegebene Maximum erreicht ist und trotzdem Inhalt heraus-
3493         // haengt.
3494 
3495         // Kritik an der Implementation
3496         // 1. Es kann theoretisch Situationen geben, in denen der Inhalt in einer geringeren
3497         // Hoehe passt und in einer groesseren Hoehe nicht passt. Damit der Code robust
3498         // gegen solche Verhaeltnisse ist, sind ein paar Abfragen bezgl. Minimum und Maximum
3499         // drin, die wahrscheinlich niemals zuschlagen koennen.
3500         // 2. Es wird fuer das Schrumpfen das gleiche nMinDiff benutzt wie fuer das Wachstum,
3501         // das nMinDiff ist allerdings mehr oder weniger die kleinste erste Zeilenhoehe und
3502         // als Mindestwert fuer das Schrumpfen nicht unbedingt optimal.
3503 
3504         long nMinimum = nMinHeight;
3505         long nMaximum;
3506         sal_Bool bNoBalance = sal_False;
3507         SWRECTFN( this )
3508         if( IsSctFrm() )
3509         {
3510             nMaximum = (Frm().*fnRect->fnGetHeight)() - nBorder +
3511                        (Frm().*fnRect->fnBottomDist)(
3512                                         (GetUpper()->*fnRect->fnGetPrtBottom)() );
3513             nMaximum += GetUpper()->Grow( LONG_MAX, sal_True );
3514             if( nMaximum < nMinimum )
3515             {
3516                 if( nMaximum < 0 )
3517                     nMinimum = nMaximum = 0;
3518                 else
3519                     nMinimum = nMaximum;
3520             }
3521             if( nMaximum > BROWSE_HEIGHT )
3522                 nMaximum = BROWSE_HEIGHT;
3523 
3524             bNoBalance = ((SwSectionFrm*)this)->GetSection()->GetFmt()->
3525                          GetBalancedColumns().GetValue();
3526             SwFrm* pAny = ContainsAny();
3527             if( bNoBalance ||
3528                 ( !(Frm().*fnRect->fnGetHeight)() && pAny ) )
3529             {
3530                 long nTop = (this->*fnRect->fnGetTopMargin)();
3531                 // --> OD 2004-11-01 #i23129# - correction: enlarge section
3532                 // to the calculated maximum height.
3533                 (Frm().*fnRect->fnAddBottom)( nMaximum -
3534                                               (Frm().*fnRect->fnGetHeight)() );
3535                 // <--
3536                 if( nTop > nMaximum )
3537                     nTop = nMaximum;
3538                 (this->*fnRect->fnSetYMargins)( nTop, 0 );
3539             }
3540             if( !pAny && !((SwSectionFrm*)this)->IsFtnLock() )
3541             {
3542                 SwFtnContFrm* pFtnCont = ((SwSectionFrm*)this)->ContainsFtnCont();
3543                 if( pFtnCont )
3544                 {
3545                     SwFrm* pFtnAny = pFtnCont->ContainsAny();
3546                     if( pFtnAny && pFtnAny->IsValid() )
3547                     {
3548                         bBackLock = sal_True;
3549                         ((SwSectionFrm*)this)->SetFtnLock( sal_True );
3550                     }
3551                 }
3552             }
3553         }
3554         else
3555             nMaximum = LONG_MAX;
3556 
3557         // --> OD 2004-08-25 #i3317# - reset temporarly consideration
3558         // of wrapping style influence
3559         SwPageFrm* pPageFrm = FindPageFrm();
3560         SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
3561         if ( pObjs )
3562         {
3563             sal_uInt32 i = 0;
3564             for ( i = 0; i < pObjs->Count(); ++i )
3565             {
3566                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
3567 
3568                 if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
3569                 {
3570                     pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3571                 }
3572             }
3573         }
3574         // <--
3575         do
3576         {
3577             //Kann eine Weile dauern, deshalb hier auf Waitcrsr pruefen.
3578             if ( pImp )
3579                 pImp->CheckWaitCrsr();
3580 
3581             bValidSize = sal_True;
3582             //Erstmal die Spalten formatieren, das entlastet den
3583             //Stack ein wenig.
3584             //Bei der Gelegenheit stellen wir auch gleich mal die
3585             //Breiten und Hoehen der Spalten ein (so sie denn falsch sind).
3586             SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
3587 
3588             // --> FME 2004-07-19 #i27399#
3589             // Simply setting the column width based on the values returned by
3590             // CalcColWidth does not work for automatic column width.
3591             AdjustColumns( &rCol, sal_False );
3592             // <--
3593 
3594             for ( sal_uInt16 i = 0; i < nNumCols; ++i )
3595             {
3596                 pCol->Calc();
3597                 // ColumnFrms besitzen jetzt einen BodyFrm, der auch kalkuliert werden will
3598                 pCol->Lower()->Calc();
3599                 if( pCol->Lower()->GetNext() )
3600                     pCol->Lower()->GetNext()->Calc();  // SwFtnCont
3601                 pCol = (SwLayoutFrm*)pCol->GetNext();
3602             }
3603 
3604             ::CalcCntnt( this );
3605 
3606             pCol = (SwLayoutFrm*)Lower();
3607             ASSERT( pCol && pCol->GetNext(), ":-( Spalten auf Urlaub?");
3608             // bMinDiff wird gesetzt, wenn es keine leere Spalte gibt
3609             sal_Bool bMinDiff = sal_True;
3610             // OD 28.03.2003 #108446# - check for all column content and all columns
3611             while ( bMinDiff && pCol )
3612             {
3613                 bMinDiff = 0 != pCol->ContainsCntnt();
3614                 pCol = (SwLayoutFrm*)pCol->GetNext();
3615             }
3616             pCol = (SwLayoutFrm*)Lower();
3617             // OD 28.03.2003 #108446# - initialize local variable
3618             SwFrm *pLow = NULL;
3619             SwTwips nDiff = 0;
3620             SwTwips nMaxFree = 0;
3621             SwTwips nAllFree = LONG_MAX;
3622             // bFoundLower wird gesetzt, wenn es mind. eine nichtleere Spalte gibt
3623             sal_Bool bFoundLower = sal_False;
3624             while( pCol )
3625             {
3626                 SwLayoutFrm* pLay = (SwLayoutFrm*)pCol->Lower();
3627                 SwTwips nInnerHeight = (pLay->Frm().*fnRect->fnGetHeight)() -
3628                                        (pLay->Prt().*fnRect->fnGetHeight)();
3629                 if( pLay->Lower() )
3630                 {
3631                     bFoundLower = sal_True;
3632                     nInnerHeight += pLay->InnerHeight();
3633                 }
3634                 else if( nInnerHeight < 0 )
3635                     nInnerHeight = 0;
3636 
3637                 if( pLay->GetNext() )
3638                 {
3639                     bFoundLower = sal_True;
3640                     pLay = (SwLayoutFrm*)pLay->GetNext();
3641                     ASSERT( pLay->IsFtnContFrm(),"FtnContainer exspected" );
3642                     nInnerHeight += pLay->InnerHeight();
3643                     nInnerHeight += (pLay->Frm().*fnRect->fnGetHeight)() -
3644                                     (pLay->Prt().*fnRect->fnGetHeight)();
3645                 }
3646                 nInnerHeight -= (pCol->Prt().*fnRect->fnGetHeight)();
3647                 if( nInnerHeight > nDiff )
3648                 {
3649                     nDiff = nInnerHeight;
3650                     nAllFree = 0;
3651                 }
3652                 else
3653                 {
3654                     if( nMaxFree < -nInnerHeight )
3655                         nMaxFree = -nInnerHeight;
3656                     if( nAllFree > -nInnerHeight )
3657                         nAllFree = -nInnerHeight;
3658                 }
3659                 pCol = (SwLayoutFrm*)pCol->GetNext();
3660             }
3661 
3662             if ( bFoundLower || ( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() ) )
3663             {
3664                 SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
3665                 // Hier wird entschieden, ob wir wachsen muessen, naemlich wenn
3666                 // ein Spalteninhalt (nDiff) oder ein Fly herausragt.
3667                 // Bei spaltigen Bereichen wird beruecksichtigt, dass mit dem
3668                 // Besitz eines nichtleeren Follows die Groesse festgelegt ist.
3669                 if ( nDiff || ::lcl_IsFlyHeightClipped( this ) ||
3670                      ( IsSctFrm() && ((SwSectionFrm*)this)->CalcMinDiff( nMinDiff ) ) )
3671                 {
3672                     long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
3673                     // Das Minimum darf nicht kleiner sein als unsere PrtHeight,
3674                     // solange noch etwas herausragt.
3675                     if( nMinimum < nPrtHeight )
3676                         nMinimum = nPrtHeight;
3677                     // Es muss sichergestellt sein, dass das Maximum nicht kleiner
3678                     // als die PrtHeight ist, wenn noch etwas herausragt
3679                     if( nMaximum < nPrtHeight )
3680                         nMaximum = nPrtHeight;  // Robust, aber kann das ueberhaupt eintreten?
3681                     if( !nDiff ) // wenn nur Flys herausragen, wachsen wir um nMinDiff
3682                         nDiff = nMinDiff;
3683                     // Wenn wir um mehr als nMinDiff wachsen wollen, wird dies auf die
3684                     // Spalten verteilt
3685                     if ( Abs(nDiff - nMinDiff) > nNumCols && nDiff > (long)nNumCols )
3686                         nDiff /= nNumCols;
3687 
3688                     if ( bMinDiff )
3689                     {   // Wenn es keinen leeren Spalten gibt, wollen wir mind. um nMinDiff
3690                         // wachsen. Sonderfall: Wenn wir kleiner als die minimale Frmhoehe
3691                         // sind und die PrtHeight kleiner als nMinDiff ist, wachsen wir so,
3692                         // dass die PrtHeight hinterher genau nMinDiff ist.
3693                         long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
3694                         if ( nFrmHeight > nMinHeight || nPrtHeight >= nMinDiff )
3695                             nDiff = Max( nDiff, nMinDiff );
3696                         else if( nDiff < nMinDiff )
3697                             nDiff = nMinDiff - nPrtHeight + 1;
3698                     }
3699                     // nMaximum ist eine Groesse, in der der Inhalt gepasst hat,
3700                     // oder der von der Umgebung vorgegebene Wert, deshalb
3701                     // brauchen wir nicht ueber diesen Wrt hinauswachsen.
3702                     if( nDiff + nPrtHeight > nMaximum )
3703                         nDiff = nMaximum - nPrtHeight;
3704                 }
3705                 else if( nMaximum > nMinimum ) // Wir passen, haben wir auch noch Spielraum?
3706                 {
3707                     long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
3708                     if ( nMaximum < nPrtHeight )
3709                         nDiff = nMaximum - nPrtHeight; // wir sind ueber eine funktionierende
3710                         // Hoehe hinausgewachsen und schrumpfen wieder auf diese zurueck,
3711                         // aber kann das ueberhaupt eintreten?
3712                     else
3713                     {   // Wir haben ein neues Maximum, eine Groesse, fuer die der Inhalt passt.
3714                         nMaximum = nPrtHeight;
3715                         // Wenn der Freiraum in den Spalten groesser ist als nMinDiff und wir
3716                         // nicht dadurch wieder unter das Minimum rutschen, wollen wir ein wenig
3717                         // Luft herauslassen.
3718                         if ( !bNoBalance &&
3719                              // --> OD 2004-11-04 #i23129# - <nMinDiff> can be
3720                              // big, because of an object at the beginning of
3721                              // a column. Thus, decrease optimization here.
3722                              //nMaxFree >= nMinDiff &&
3723                              nMaxFree > 0 &&
3724                              // <--
3725                              ( !nAllFree ||
3726                                nMinimum < nPrtHeight - nMinDiff ) )
3727                         {
3728                             nMaxFree /= nNumCols; // auf die Spalten verteilen
3729                             nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // mind. nMinDiff
3730                             if( nPrtHeight + nDiff <= nMinimum ) // Unter das Minimum?
3731                                 nDiff = ( nMinimum - nMaximum ) / 2; // dann lieber die Mitte
3732                         }
3733                         else if( nAllFree )
3734                         {
3735                             nDiff = -nAllFree;
3736                             if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
3737                                 nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
3738                         }
3739                     }
3740                 }
3741                 if( nDiff ) // jetzt wird geschrumpft oder gewachsen..
3742                 {
3743                     Size aOldSz( Prt().SSize() );
3744                     long nTop = (this->*fnRect->fnGetTopMargin)();
3745                     nDiff = (Prt().*fnRect->fnGetHeight)() + nDiff + nBorder -
3746                             (Frm().*fnRect->fnGetHeight)();
3747                     (Frm().*fnRect->fnAddBottom)( nDiff );
3748                     // --> OD 2006-08-16 #i68520#
3749                     if ( dynamic_cast<SwFlyFrm*>(this) )
3750                     {
3751                         dynamic_cast<SwFlyFrm*>(this)->InvalidateObjRectWithSpaces();
3752                     }
3753                     // <--
3754                     (this->*fnRect->fnSetYMargins)( nTop, nBorder - nTop );
3755                     ChgLowersProp( aOldSz );
3756                     NotifyLowerObjs();
3757 
3758                     // --> OD 2004-08-25 #i3317# - reset temporarly consideration
3759                     // of wrapping style influence
3760                     SwPageFrm* pTmpPageFrm = FindPageFrm();
3761                     SwSortedObjs* pTmpObjs = pTmpPageFrm ? pTmpPageFrm->GetSortedObjs() : 0L;
3762                     if ( pTmpObjs )
3763                     {
3764                         sal_uInt32 i = 0;
3765                         for ( i = 0; i < pTmpObjs->Count(); ++i )
3766                         {
3767                             SwAnchoredObject* pAnchoredObj = (*pTmpObjs)[i];
3768 
3769                             if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
3770                             {
3771                                 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3772                             }
3773                         }
3774                     }
3775                     // <--
3776                     //Es muss geeignet invalidiert werden, damit
3777                     //sich die Frms huebsch ausbalancieren
3778                     //- Der jeweils erste ab der zweiten Spalte bekommt
3779                     //  ein InvalidatePos();
3780                     pCol = (SwLayoutFrm*)Lower()->GetNext();
3781                     while ( pCol )
3782                     {
3783                         pLow = pCol->Lower();
3784                         if ( pLow )
3785                             pLow->_InvalidatePos();
3786                         pCol = (SwLayoutFrm*)pCol->GetNext();
3787                     }
3788                     if( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() )
3789                     {
3790                         // Wenn wir einen Follow erzeugt haben, muessen wir
3791                         // seinem Inhalt die Chance geben, im CalcCntnt
3792                         // zurueckzufliessen
3793                         SwCntntFrm* pTmpCntnt =
3794                             ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
3795                         if( pTmpCntnt )
3796                             pTmpCntnt->_InvalidatePos();
3797                     }
3798                 }
3799                 else
3800                     bEnd = sal_True;
3801             }
3802             else
3803                 bEnd = sal_True;
3804 
3805         } while ( !bEnd || !bValidSize );
3806     }
3807     // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
3808     // 2nd parameter to <true>.
3809     ::CalcCntnt( this, true );
3810     if( IsSctFrm() )
3811     {
3812         // OD 14.03.2003 #i11760# - adjust 2nd parameter - sal_True --> true
3813         ::CalcCntnt( this, true );
3814         if( bBackLock )
3815             ((SwSectionFrm*)this)->SetFtnLock( sal_False );
3816     }
3817 }
3818 
3819 
3820 /*************************************************************************
3821 |*
3822 |*  SwRootFrm::InvalidateAllCntnt()
3823 |*
3824 |*  Ersterstellung      MA 13. Feb. 98
3825 |*  Letzte Aenderung    MA 12. Aug. 00
3826 |*
3827 |*************************************************************************/
3828 
lcl_InvalidateSection(SwFrm * pCnt,sal_uInt8 nInv)3829 SwCntntFrm* lcl_InvalidateSection( SwFrm *pCnt, sal_uInt8 nInv )
3830 {
3831     SwSectionFrm* pSect = pCnt->FindSctFrm();
3832     // Wenn unser CntntFrm in einer Tabelle oder Fussnote steht, sind nur
3833     // Bereiche gemeint, die ebenfalls innerhalb liegen.
3834     // Ausnahme: Wenn direkt eine Tabelle uebergeben wird.
3835     if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
3836         ( pCnt->IsInFtn() && !pSect->IsInFtn() ) ) && !pCnt->IsTabFrm() )
3837         return NULL;
3838     if( nInv & INV_SIZE )
3839         pSect->_InvalidateSize();
3840     if( nInv & INV_POS )
3841         pSect->_InvalidatePos();
3842     if( nInv & INV_PRTAREA )
3843         pSect->_InvalidatePrt();
3844     SwFlowFrm *pFoll = pSect->GetFollow();
3845     // Temporary separation from follow
3846     pSect->SetFollow( NULL );
3847     SwCntntFrm* pRet = pSect->FindLastCntnt();
3848     pSect->SetFollow( pFoll );
3849     return pRet;
3850 }
3851 
lcl_InvalidateTable(SwTabFrm * pTable,sal_uInt8 nInv)3852 SwCntntFrm* lcl_InvalidateTable( SwTabFrm *pTable, sal_uInt8 nInv )
3853 {
3854     if( ( nInv & INV_SECTION ) && pTable->IsInSct() )
3855         lcl_InvalidateSection( pTable, nInv );
3856     if( nInv & INV_SIZE )
3857         pTable->_InvalidateSize();
3858     if( nInv & INV_POS )
3859         pTable->_InvalidatePos();
3860     if( nInv & INV_PRTAREA )
3861         pTable->_InvalidatePrt();
3862     return pTable->FindLastCntnt();
3863 }
3864 
3865 void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv );
3866 
lcl_InvalidateCntnt(SwCntntFrm * pCnt,sal_uInt8 nInv)3867 void lcl_InvalidateCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
3868 {
3869     SwCntntFrm *pLastTabCnt = NULL;
3870     SwCntntFrm *pLastSctCnt = NULL;
3871     while ( pCnt )
3872     {
3873         if( nInv & INV_SECTION )
3874         {
3875             if( pCnt->IsInSct() )
3876             {
3877                 // Siehe oben bei Tabellen
3878                 if( !pLastSctCnt )
3879                     pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
3880                 if( pLastSctCnt == pCnt )
3881                     pLastSctCnt = NULL;
3882             }
3883 #ifdef DBG_UTIL
3884             else
3885                 ASSERT( !pLastSctCnt, "Where's the last SctCntnt?" );
3886 #endif
3887         }
3888         if( nInv & INV_TABLE )
3889         {
3890             if( pCnt->IsInTab() )
3891             {
3892                 // Um nicht fuer jeden CntntFrm einer Tabelle das FindTabFrm() zu rufen
3893                 // und wieder die gleiche Tabelle zu invalidieren, merken wir uns den letzten
3894                 // CntntFrm der Tabelle und reagieren erst wieder auf IsInTab(), wenn wir
3895                 // an diesem vorbei sind.
3896                 // Beim Eintritt in die Tabelle wird der LastSctCnt auf Null gesetzt,
3897                 // damit Bereiche im Innern der Tabelle richtig invalidiert werden.
3898                 // Sollte die Tabelle selbst in einem Bereich stehen, so wird an
3899                 // diesem die Invalidierung bis zu dreimal durchgefuehrt, das ist vertretbar.
3900                 if( !pLastTabCnt )
3901                 {
3902                     pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrm(), nInv );
3903                     pLastSctCnt = NULL;
3904                 }
3905                 if( pLastTabCnt == pCnt )
3906                 {
3907                     pLastTabCnt = NULL;
3908                     pLastSctCnt = NULL;
3909                 }
3910             }
3911 #ifdef DBG_UTIL
3912             else
3913                 ASSERT( !pLastTabCnt, "Where's the last TabCntnt?" );
3914 #endif
3915         }
3916 
3917         if( nInv & INV_SIZE )
3918             pCnt->Prepare( PREP_CLEAR, 0, sal_False );
3919         if( nInv & INV_POS )
3920             pCnt->_InvalidatePos();
3921         if( nInv & INV_PRTAREA )
3922             pCnt->_InvalidatePrt();
3923         if ( nInv & INV_LINENUM )
3924             pCnt->InvalidateLineNum();
3925         if ( pCnt->GetDrawObjs() )
3926             lcl_InvalidateAllCntnt( pCnt, nInv );
3927         pCnt = pCnt->GetNextCntntFrm();
3928     }
3929 }
3930 
lcl_InvalidateAllCntnt(SwCntntFrm * pCnt,sal_uInt8 nInv)3931 void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, sal_uInt8 nInv )
3932 {
3933     SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
3934     for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
3935     {
3936         SwAnchoredObject* pAnchoredObj = rObjs[i];
3937         if ( pAnchoredObj->ISA(SwFlyFrm) )
3938         {
3939             SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3940             if ( pFly->IsFlyInCntFrm() )
3941             {
3942                 ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
3943                 if( nInv & INV_DIRECTION )
3944                     pFly->CheckDirChange();
3945             }
3946         }
3947     }
3948 }
3949 
InvalidateAllCntnt(sal_uInt8 nInv)3950 void SwRootFrm::InvalidateAllCntnt( sal_uInt8 nInv )
3951 {
3952     // Erst werden alle Seitengebundenen FlyFrms abgearbeitet.
3953     SwPageFrm *pPage = (SwPageFrm*)Lower();
3954     while( pPage )
3955     {
3956         pPage->InvalidateFlyLayout();
3957         pPage->InvalidateFlyCntnt();
3958         pPage->InvalidateFlyInCnt();
3959         pPage->InvalidateLayout();
3960         pPage->InvalidateCntnt();
3961         pPage->InvalidatePage( pPage ); //Damit ggf. auch der Turbo verschwindet
3962 
3963         if ( pPage->GetSortedObjs() )
3964         {
3965             const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3966             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
3967             {
3968                 SwAnchoredObject* pAnchoredObj = rObjs[i];
3969                 if ( pAnchoredObj->ISA(SwFlyFrm) )
3970                 {
3971                     SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3972                     ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
3973                     if ( nInv & INV_DIRECTION )
3974                         pFly->CheckDirChange();
3975                 }
3976             }
3977         }
3978         if( nInv & INV_DIRECTION )
3979             pPage->CheckDirChange();
3980         pPage = (SwPageFrm*)(pPage->GetNext());
3981     }
3982 
3983     //Hier den gesamten Dokumentinhalt und die zeichengebundenen Flys.
3984     ::lcl_InvalidateCntnt( ContainsCntnt(), nInv );
3985 
3986     if( nInv & INV_PRTAREA )
3987     {
3988         ViewShell *pSh  = getRootFrm()->GetCurrShell();
3989         if( pSh )
3990             pSh->InvalidateWindows( Frm() );
3991     }
3992 }
3993 
3994 /** method to invalidate/re-calculate the position of all floating
3995     screen objects (Writer fly frames and drawing objects), which are
3996     anchored to paragraph or to character.
3997 
3998     OD 2004-03-16 #i11860#
3999 
4000     @author OD
4001 */
InvalidateAllObjPos()4002 void SwRootFrm::InvalidateAllObjPos()
4003 {
4004     const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>(Lower());
4005     while( pPageFrm )
4006     {
4007         pPageFrm->InvalidateFlyLayout();
4008 
4009         if ( pPageFrm->GetSortedObjs() )
4010         {
4011             const SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
4012             for ( sal_uInt8 i = 0; i < rObjs.Count(); ++i )
4013             {
4014                 SwAnchoredObject* pAnchoredObj = rObjs[i];
4015                 const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
4016                 if ((rAnch.GetAnchorId() != FLY_AT_PARA) &&
4017                     (rAnch.GetAnchorId() != FLY_AT_CHAR))
4018                 {
4019                     // only to paragraph and to character anchored objects are considered.
4020                     continue;
4021                 }
4022                 // --> OD 2004-07-07 #i28701# - special invalidation for anchored
4023                 // objects, whose wrapping style influence has to be considered.
4024                 if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
4025                     pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
4026                 else
4027                     pAnchoredObj->InvalidateObjPos();
4028                 // <--
4029             }
4030         }
4031 
4032         pPageFrm = static_cast<const SwPageFrm*>(pPageFrm->GetNext());
4033     }
4034 }
4035 
4036 
4037