Update ooo320-m1
[ooovba.git] / sw / source / core / layout / wsfrm.cxx
blobd00d3e3459710bd8a722731a3327429e7c7b6682
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wsfrm.cxx,v $
10 * $Revision: 1.86.124.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <hints.hxx>
37 #include <tools/pstm.hxx>
38 #ifndef _OUTDEV_HXX
39 #include <vcl/outdev.hxx>
40 #endif
41 #include <svtools/itemiter.hxx>
42 #include <svx/brshitem.hxx>
43 #include <svx/keepitem.hxx>
44 #include <svx/brkitem.hxx>
45 #include <fmtornt.hxx>
46 #include <pagefrm.hxx>
47 #include <section.hxx>
48 #include <rootfrm.hxx>
49 #include <cntfrm.hxx>
50 #include <dcontact.hxx>
51 #include <viewsh.hxx>
52 #include <viewimp.hxx>
53 #include <doc.hxx>
54 #include <fesh.hxx>
55 #ifndef _DOCSH_HXX
56 #include <docsh.hxx>
57 #endif
58 #include <flyfrm.hxx>
59 #include <frmtool.hxx>
60 #include <ftninfo.hxx>
61 #include <dflyobj.hxx>
62 #include <fmtclbl.hxx>
63 #include <fmtfordr.hxx>
64 #include <fmtfsize.hxx>
65 #include <fmtpdsc.hxx>
66 #include <txtftn.hxx>
67 #include <fmtftn.hxx>
68 #include <fmtsrnd.hxx>
69 #include <ftnfrm.hxx>
70 #include <tabfrm.hxx>
71 #include <htmltbl.hxx>
72 #include <flyfrms.hxx>
73 #include <sectfrm.hxx>
74 #include <fmtclds.hxx>
75 #include <txtfrm.hxx>
76 #include <ndtxt.hxx>
77 #include <bodyfrm.hxx>
78 #include <cellfrm.hxx>
79 #include <dbg_lay.hxx>
80 #include <svx/frmdiritem.hxx>
81 // OD 2004-05-24 #i28701#
82 #include <sortedobjs.hxx>
84 using namespace ::com::sun::star;
86 /*************************************************************************
88 |* SwFrm::SwFrm()
90 |* Ersterstellung AK 12-Feb-1991
91 |* Letzte Aenderung MA 05. Apr. 94
93 |*************************************************************************/
95 SwFrm::SwFrm( SwModify *pMod ) :
96 SwClient( pMod ),
97 // --> OD 2006-05-10 #i65250#
98 mnFrmId( SwFrm::mnLastFrmId++ ),
99 // <--
100 pUpper( 0 ),
101 pNext( 0 ),
102 pPrev( 0 ),
103 pDrawObjs( 0 )
105 #ifndef PRODUCT
106 bFlag01 = bFlag02 = bFlag03 = bFlag04 = bFlag05 = 0;
107 #endif
109 ASSERT( pMod, "Kein Frameformat uebergeben." );
110 bInvalidR2L = bInvalidVert = 1;
111 bDerivedR2L = bDerivedVert = bRightToLeft = bVertical = bReverse = 0;
112 bValidPos = bValidPrtArea = bValidSize = bValidLineNum = bRetouche =
113 bFixSize = bColLocked = FALSE;
114 bCompletePaint = bInfInvalid = TRUE;
118 ViewShell * SwFrm::GetShell() const
120 const SwRootFrm *pRoot;
121 if ( 0 != (pRoot = FindRootFrm()) )
122 return pRoot->GetCurrShell();
123 return 0;
127 void SwFrm::CheckDir( UINT16 nDir, BOOL bVert, BOOL bOnlyBiDi, BOOL bBrowse )
129 if( FRMDIR_ENVIRONMENT == nDir || ( bVert && bOnlyBiDi ) )
131 bDerivedVert = 1;
132 if( FRMDIR_ENVIRONMENT == nDir )
133 bDerivedR2L = 1;
134 SetDirFlags( bVert );
136 else if( bVert )
138 bInvalidVert = 0;
139 if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir
140 || bBrowse )
141 bVertical = 0;
142 else
143 bVertical = 1;
145 else
147 bInvalidR2L = 0;
148 if( FRMDIR_HORI_RIGHT_TOP == nDir )
149 bRightToLeft = 1;
150 else
151 bRightToLeft = 0;
155 void SwFrm::CheckDirection( BOOL bVert )
157 if( bVert )
159 if( !IsHeaderFrm() && !IsFooterFrm() )
161 bDerivedVert = 1;
162 SetDirFlags( bVert );
165 else
167 bDerivedR2L = 1;
168 SetDirFlags( bVert );
172 void SwSectionFrm::CheckDirection( BOOL bVert )
174 const SwFrmFmt* pFmt = GetFmt();
175 if( pFmt )
176 CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
177 bVert, sal_True,
178 pFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) );
179 else
180 SwFrm::CheckDirection( bVert );
183 void SwFlyFrm::CheckDirection( BOOL bVert )
185 const SwFrmFmt* pFmt = GetFmt();
186 if( pFmt )
187 CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
188 bVert, sal_False,
189 pFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) );
190 else
191 SwFrm::CheckDirection( bVert );
194 void SwTabFrm::CheckDirection( BOOL bVert )
196 const SwFrmFmt* pFmt = GetFmt();
197 if( pFmt )
198 CheckDir(((SvxFrameDirectionItem&)pFmt->GetFmtAttr(RES_FRAMEDIR)).GetValue(),
199 bVert, sal_True,
200 pFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) );
201 else
202 SwFrm::CheckDirection( bVert );
205 void SwCellFrm::CheckDirection( BOOL bVert )
207 const SwFrmFmt* pFmt = GetFmt();
208 const SfxPoolItem* pItem;
209 // --> FME 2006-03-30 #b6402837# Check if the item is set, before actually
210 // using it. Otherwise the dynamic pool default is used, which may be set
211 // to LTR in case of OOo 1.0 documents.
212 // <--
213 if( pFmt && SFX_ITEM_SET == pFmt->GetItemState( RES_FRAMEDIR, TRUE, &pItem ) )
215 const SvxFrameDirectionItem* pFrmDirItem = static_cast<const SvxFrameDirectionItem*>(pItem);
216 CheckDir( pFrmDirItem->GetValue(), bVert, sal_False,
217 pFmt->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) );
219 else
220 SwFrm::CheckDirection( bVert );
223 void SwTxtFrm::CheckDirection( BOOL bVert )
225 CheckDir( GetTxtNode()->GetSwAttrSet().GetFrmDir().GetValue(), bVert,
226 sal_True,
227 GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) );
230 /*************************************************************************
232 |* SwFrm::Modify()
234 |* Ersterstellung AK 01-Mar-1991
235 |* Letzte Aenderung MA 20. Jun. 96
237 |*************************************************************************/
238 void SwFrm::Modify( SfxPoolItem * pOld, SfxPoolItem * pNew )
240 BYTE nInvFlags = 0;
242 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
244 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
245 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
246 while( TRUE )
248 _UpdateAttrFrm( (SfxPoolItem*)aOIter.GetCurItem(),
249 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags );
250 if( aNIter.IsAtEnd() )
251 break;
252 aNIter.NextItem();
253 aOIter.NextItem();
256 else
257 _UpdateAttrFrm( pOld, pNew, nInvFlags );
259 if ( nInvFlags != 0 )
261 SwPageFrm *pPage = FindPageFrm();
262 InvalidatePage( pPage );
263 if ( nInvFlags & 0x01 )
265 _InvalidatePrt();
266 if( !GetPrev() && IsTabFrm() && IsInSct() )
267 FindSctFrm()->_InvalidatePrt();
269 if ( nInvFlags & 0x02 )
270 _InvalidateSize();
271 if ( nInvFlags & 0x04 )
272 _InvalidatePos();
273 if ( nInvFlags & 0x08 )
274 SetCompletePaint();
275 SwFrm *pNxt;
276 if ( nInvFlags & 0x30 && 0 != (pNxt = GetNext()) )
278 pNxt->InvalidatePage( pPage );
279 if ( nInvFlags & 0x10 )
280 pNxt->_InvalidatePos();
281 if ( nInvFlags & 0x20 )
282 pNxt->SetCompletePaint();
287 void SwFrm::_UpdateAttrFrm( SfxPoolItem *pOld, SfxPoolItem *pNew,
288 BYTE &rInvFlags )
290 USHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
291 switch( nWhich )
293 case RES_BOX:
294 case RES_SHADOW:
295 Prepare( PREP_FIXSIZE_CHG );
296 // hier kein break !
297 case RES_LR_SPACE:
298 case RES_UL_SPACE:
299 rInvFlags |= 0x0B;
300 break;
302 case RES_HEADER_FOOTER_EAT_SPACING:
303 rInvFlags |= 0x03;
304 break;
306 case RES_BACKGROUND:
307 rInvFlags |= 0x28;
308 break;
310 case RES_KEEP:
311 rInvFlags |= 0x04;
312 break;
314 case RES_FRM_SIZE:
315 ReinitializeFrmSizeAttrFlags();
316 rInvFlags |= 0x13;
317 break;
319 case RES_FMT_CHG:
320 rInvFlags |= 0x0F;
321 break;
323 case RES_ROW_SPLIT:
325 if ( IsRowFrm() )
327 BOOL bInFollowFlowRow = 0 != IsInFollowFlowRow();
328 if ( bInFollowFlowRow || 0 != IsInSplitTableRow() )
330 SwTabFrm* pTab = FindTabFrm();
331 if ( bInFollowFlowRow )
332 pTab = pTab->FindMaster();
333 pTab->SetRemoveFollowFlowLinePending( TRUE );
336 break;
338 case RES_COL:
339 ASSERT( FALSE, "Spalten fuer neuen FrmTyp?" );
340 break;
342 default:
343 /* do Nothing */;
347 /*************************************************************************
349 |* SwFrm::Prepare()
350 |* Ersterstellung MA 13. Apr. 93
351 |* Letzte Aenderung MA 26. Jun. 96
353 |*************************************************************************/
354 void SwFrm::Prepare( const PrepareHint, const void *, BOOL )
356 /* Do nothing */
359 /*************************************************************************
361 |* SwFrm::InvalidatePage()
362 |* Beschreibung: Invalidiert die Seite, in der der Frm gerade steht.
363 |* Je nachdem ob es ein Layout, Cntnt oder FlyFrm ist wird die Seite
364 |* entsprechend Invalidiert.
365 |* Ersterstellung MA 22. Jul. 92
366 |* Letzte Aenderung MA 14. Oct. 94
368 |*************************************************************************/
369 void SwFrm::InvalidatePage( const SwPageFrm *pPage ) const
371 if ( !pPage )
373 pPage = FindPageFrm();
374 // --> OD 2004-07-02 #i28701# - for at-character and as-character
375 // anchored Writer fly frames additionally invalidate also page frame
376 // its 'anchor character' is on.
377 if ( pPage && pPage->GetUpper() && IsFlyFrm() )
379 const SwFlyFrm* pFlyFrm = static_cast<const SwFlyFrm*>(this);
380 if ( pFlyFrm->IsAutoPos() || pFlyFrm->IsFlyInCntFrm() )
382 // --> OD 2004-09-23 #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
383 // is replaced by method <FindPageFrmOfAnchor()>. It's return value
384 // have to be checked.
385 SwPageFrm* pPageFrmOfAnchor =
386 const_cast<SwFlyFrm*>(pFlyFrm)->FindPageFrmOfAnchor();
387 if ( pPageFrmOfAnchor && pPageFrmOfAnchor != pPage )
388 // <--
390 InvalidatePage( pPageFrmOfAnchor );
394 // <--
397 if ( pPage && pPage->GetUpper() )
399 if ( pPage->GetFmt()->GetDoc()->IsInDtor() )
400 return;
402 SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
403 const SwFlyFrm *pFly = FindFlyFrm();
404 if ( IsCntntFrm() )
406 if ( pRoot->IsTurboAllowed() )
408 // JP 21.09.95: wenn sich der ContentFrame 2 mal eintragen
409 // will, kann es doch eine TurboAction bleiben.
410 // ODER????
411 if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
412 pRoot->SetTurbo( (const SwCntntFrm*)this );
413 else
415 pRoot->DisallowTurbo();
416 //Die Seite des Turbo koennte eine andere als die meinige
417 //sein, deshalb muss sie invalidiert werden.
418 const SwFrm *pTmp = pRoot->GetTurbo();
419 pRoot->ResetTurbo();
420 pTmp->InvalidatePage();
423 if ( !pRoot->GetTurbo() )
425 if ( pFly )
426 { if( !pFly->IsLocked() )
428 if ( pFly->IsFlyInCntFrm() )
429 { pPage->InvalidateFlyInCnt();
430 ((SwFlyInCntFrm*)pFly)->InvalidateCntnt();
431 pFly->GetAnchorFrm()->InvalidatePage();
433 else
434 pPage->InvalidateFlyCntnt();
437 else
438 pPage->InvalidateCntnt();
441 else
443 pRoot->DisallowTurbo();
444 if ( pFly )
446 if ( !pFly->IsLocked() )
448 if ( pFly->IsFlyInCntFrm() )
450 pPage->InvalidateFlyInCnt();
451 ((SwFlyInCntFrm*)pFly)->InvalidateLayout();
452 pFly->GetAnchorFrm()->InvalidatePage();
454 else
455 pPage->InvalidateFlyLayout();
458 else
459 pPage->InvalidateLayout();
461 if ( pRoot->GetTurbo() )
462 { const SwFrm *pTmp = pRoot->GetTurbo();
463 pRoot->ResetTurbo();
464 pTmp->InvalidatePage();
467 pRoot->SetIdleFlags();
469 const SwTxtFrm *pTxtFrm = dynamic_cast< const SwTxtFrm * >(this);
470 if (pTxtFrm)
472 const SwTxtNode *pTxtNode = pTxtFrm->GetTxtNode();
473 if (pTxtNode && pTxtNode->IsGrammarCheckDirty())
474 pRoot->SetNeedGrammarCheck( TRUE );
479 /*************************************************************************
481 |* SwFrm::ChgSize()
483 |* Ersterstellung AK 15-Feb-1991
484 |* Letzte Aenderung MA 18. Nov. 98
486 |*************************************************************************/
487 Size SwFrm::ChgSize( const Size& aNewSize )
489 bFixSize = TRUE;
490 const Size aOldSize( Frm().SSize() );
491 if ( aNewSize == aOldSize )
492 return aOldSize;
494 if ( GetUpper() )
496 SWRECTFN2( this )
497 SwRect aNew( Point(0,0), aNewSize );
498 (aFrm.*fnRect->fnSetWidth)( (aNew.*fnRect->fnGetWidth)() );
499 long nNew = (aNew.*fnRect->fnGetHeight)();
500 long nDiff = nNew - (aFrm.*fnRect->fnGetHeight)();
501 if( nDiff )
503 if ( GetUpper()->IsFtnBossFrm() && HasFixSize() &&
504 NA_GROW_SHRINK !=
505 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this ) )
507 (aFrm.*fnRect->fnSetHeight)( nNew );
508 SwTwips nReal = ((SwLayoutFrm*)this)->AdjustNeighbourhood(nDiff);
509 if ( nReal != nDiff )
510 (aFrm.*fnRect->fnSetHeight)( nNew - nDiff + nReal );
512 else
514 // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
515 // NOTE: neighbour frames are cell and column frames.
516 if ( !bNeighb )
518 if ( nDiff > 0 )
519 Grow( nDiff );
520 else
521 Shrink( -nDiff );
523 if ( GetUpper() && (aFrm.*fnRect->fnGetHeight)() != nNew )
524 GetUpper()->_InvalidateSize();
527 // Auch wenn das Grow/Shrink noch nicht die gewuenschte Breite eingestellt hat,
528 // wie z.B. beim Aufruf durch ChgColumns, um die Spaltenbreiten einzustellen,
529 // wird die Breite jetzt gesetzt.
530 (aFrm.*fnRect->fnSetHeight)( nNew );
534 else
535 aFrm.SSize( aNewSize );
537 if ( Frm().SSize() != aOldSize )
539 SwPageFrm *pPage = FindPageFrm();
540 if ( GetNext() )
542 GetNext()->_InvalidatePos();
543 GetNext()->InvalidatePage( pPage );
545 if( IsLayoutFrm() )
547 if( IsRightToLeft() )
548 _InvalidatePos();
549 if( ((SwLayoutFrm*)this)->Lower() )
550 ((SwLayoutFrm*)this)->Lower()->_InvalidateSize();
552 _InvalidatePrt();
553 _InvalidateSize();
554 InvalidatePage( pPage );
557 return aFrm.SSize();
560 /*************************************************************************
562 |* SwFrm::InsertBefore()
564 |* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
565 |* Eingefuegt wird unterhalb des Parent und entweder
566 |* vor pBehind oder am Ende der Kette wenn pBehind
567 |* leer ist.
568 |* Letzte Aenderung MA 06. Aug. 99
570 |*************************************************************************/
571 void SwFrm::InsertBefore( SwLayoutFrm* pParent, SwFrm* pBehind )
573 ASSERT( pParent, "Kein Parent fuer Insert." );
574 ASSERT( (!pBehind || (pBehind && pParent == pBehind->GetUpper())),
575 "Framebaum inkonsistent." );
577 pUpper = pParent;
578 pNext = pBehind;
579 if( pBehind )
580 { //Einfuegen vor pBehind.
581 if( 0 != (pPrev = pBehind->pPrev) )
582 pPrev->pNext = this;
583 else
584 pUpper->pLower = this;
585 pBehind->pPrev = this;
587 else
588 { //Einfuegen am Ende, oder als ersten Node im Unterbaum
589 pPrev = pUpper->Lower();
590 if ( pPrev )
592 while( pPrev->pNext )
593 pPrev = pPrev->pNext;
594 pPrev->pNext = this;
596 else
597 pUpper->pLower = this;
601 /*************************************************************************
603 |* SwFrm::InsertBehind()
605 |* Beschreibung SwFrm wird in eine bestehende Struktur eingefuegt
606 |* Eingefuegt wird unterhalb des Parent und entweder
607 |* hinter pBefore oder am Anfang der Kette wenn pBefore
608 |* leer ist.
609 |* Letzte Aenderung MA 06. Aug. 99
611 |*************************************************************************/
612 void SwFrm::InsertBehind( SwLayoutFrm *pParent, SwFrm *pBefore )
614 ASSERT( pParent, "Kein Parent fuer Insert." );
615 ASSERT( (!pBefore || (pBefore && pParent == pBefore->GetUpper())),
616 "Framebaum inkonsistent." );
618 pUpper = pParent;
619 pPrev = pBefore;
620 if ( pBefore )
622 //Einfuegen hinter pBefore
623 if ( 0 != (pNext = pBefore->pNext) )
624 pNext->pPrev = this;
625 pBefore->pNext = this;
627 else
629 //Einfuegen am Anfang der Kette
630 pNext = pParent->Lower();
631 if ( pParent->Lower() )
632 pParent->Lower()->pPrev = this;
633 pParent->pLower = this;
637 /*************************************************************************
639 |* SwFrm::InsertGroup()
641 |* Beschreibung Eine Kette von SwFrms wird in eine bestehende Struktur
642 |* eingefuegt
643 |* Letzte Aenderung AMA 9. Dec. 97
645 |* Bisher wird dies genutzt, um einen SectionFrame, der ggf. schon Geschwister
646 |* mit sich bringt, in eine bestehende Struktur einzufuegen.
648 |* Wenn man den dritten Parameter als NULL uebergibt, entspricht
649 |* diese Methode dem SwFrm::InsertBefore(..), nur eben mit Geschwistern.
651 |* Wenn man einen dritten Parameter uebergibt, passiert folgendes:
652 |* this wird pNext von pParent,
653 |* pSct wird pNext vom Letzten der this-Kette,
654 |* pBehind wird vom pParent an den pSct umgehaengt.
655 |* Dies dient dazu: ein SectionFrm (this) wird nicht als
656 |* Kind an einen anderen SectionFrm (pParent) gehaengt, sondern pParent
657 |* wird in zwei Geschwister aufgespalten (pParent+pSct) und this dazwischen
658 |* eingebaut.
660 |*************************************************************************/
661 void SwFrm::InsertGroupBefore( SwFrm* pParent, SwFrm* pBehind, SwFrm* pSct )
663 ASSERT( pParent, "Kein Parent fuer Insert." );
664 ASSERT( (!pBehind || (pBehind && ( pParent == pBehind->GetUpper())
665 || ( pParent->IsSctFrm() && pBehind->GetUpper()->IsColBodyFrm() ) ) ),
666 "Framebaum inkonsistent." );
667 if( pSct )
669 pUpper = pParent->GetUpper();
670 SwFrm *pLast = this;
671 while( pLast->GetNext() )
673 pLast = pLast->GetNext();
674 pLast->pUpper = GetUpper();
676 if( pBehind )
678 pLast->pNext = pSct;
679 pSct->pPrev = pLast;
680 pSct->pNext = pParent->GetNext();
682 else
684 pLast->pNext = pParent->GetNext();
685 if( pLast->GetNext() )
686 pLast->GetNext()->pPrev = pLast;
688 pParent->pNext = this;
689 pPrev = pParent;
690 if( pSct->GetNext() )
691 pSct->GetNext()->pPrev = pSct;
692 while( pLast->GetNext() )
694 pLast = pLast->GetNext();
695 pLast->pUpper = GetUpper();
697 if( pBehind )
698 { //Einfuegen vor pBehind.
699 if( pBehind->GetPrev() )
700 pBehind->GetPrev()->pNext = NULL;
701 else
702 pBehind->GetUpper()->pLower = NULL;
703 pBehind->pPrev = NULL;
704 SwLayoutFrm* pTmp = (SwLayoutFrm*)pSct;
705 if( pTmp->Lower() )
707 ASSERT( pTmp->Lower()->IsColumnFrm(), "InsertGrp: Used SectionFrm" );
708 pTmp = (SwLayoutFrm*)((SwLayoutFrm*)pTmp->Lower())->Lower();
709 ASSERT( pTmp, "InsertGrp: Missing ColBody" );
711 pBehind->pUpper = pTmp;
712 pBehind->GetUpper()->pLower = pBehind;
713 pLast = pBehind->GetNext();
714 while ( pLast )
716 pLast->pUpper = pBehind->GetUpper();
717 pLast = pLast->GetNext();
720 else
722 ASSERT( pSct->IsSctFrm(), "InsertGroup: For SectionFrms only" );
723 delete ((SwSectionFrm*)pSct);
726 else
728 pUpper = (SwLayoutFrm*)pParent;
729 SwFrm *pLast = this;
730 while( pLast->GetNext() )
732 pLast = pLast->GetNext();
733 pLast->pUpper = GetUpper();
735 pLast->pNext = pBehind;
736 if( pBehind )
737 { //Einfuegen vor pBehind.
738 if( 0 != (pPrev = pBehind->pPrev) )
739 pPrev->pNext = this;
740 else
741 pUpper->pLower = this;
742 pBehind->pPrev = pLast;
744 else
745 { //Einfuegen am Ende, oder des ersten Nodes im Unterbaum
746 pPrev = pUpper->Lower();
747 if ( pPrev )
749 while( pPrev->pNext )
750 pPrev = pPrev->pNext;
751 pPrev->pNext = this;
753 else
754 pUpper->pLower = this;
759 /*************************************************************************
761 |* SwFrm::Remove()
763 |* Ersterstellung AK 01-Mar-1991
764 |* Letzte Aenderung MA 07. Dec. 95
766 |*************************************************************************/
767 void SwFrm::Remove()
769 ASSERT( pUpper, "Removen ohne Upper?" );
771 // --> OD 2004-09-27 #114344# - inform accessibility API - dispose table the
772 // frame is in - before frame is 'removed from the layout' and
773 // only for cell frames and row frames.
774 if ( IsInTab() && ( IsRowFrm() || IsCellFrm() ) )
776 SwTabFrm* pTableFrm = FindTabFrm();
777 if( pTableFrm != NULL &&
778 pTableFrm->IsAccessibleFrm() &&
779 pTableFrm->GetFmt() != NULL )
781 SwRootFrm *pRootFrm = pTableFrm->FindRootFrm();
782 if( pRootFrm != NULL &&
783 pRootFrm->IsAnyShellAccessible() )
785 ViewShell* pShell = pRootFrm->GetCurrShell();
786 if( pShell != NULL )
787 pShell->Imp()->DisposeAccessibleFrm( pTableFrm, sal_True );
791 // <--
793 if( pPrev )
794 // einer aus der Mitte wird removed
795 pPrev->pNext = pNext;
796 else
797 { // der erste in einer Folge wird removed
798 ASSERT( pUpper->pLower == this, "Layout inkonsistent." );
799 pUpper->pLower = pNext;
801 if( pNext )
802 pNext->pPrev = pPrev;
804 // Verbindung kappen.
805 pNext = pPrev = 0;
806 pUpper = 0;
808 /*************************************************************************
810 |* SwCntntFrm::Paste()
812 |* Ersterstellung MA 23. Feb. 94
813 |* Letzte Aenderung MA 09. Sep. 98
815 |*************************************************************************/
816 void SwCntntFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
818 ASSERT( pParent, "Kein Parent fuer Paste." );
819 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
820 ASSERT( pParent != this, "Bin selbst der Parent." );
821 ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
822 ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
823 "Bin noch irgendwo angemeldet." );
824 ASSERT( !pSibling || pSibling->IsFlowFrm(),
825 "<SwCntntFrm::Paste(..)> - sibling not of expected type." )
827 //In den Baum einhaengen.
828 InsertBefore( (SwLayoutFrm*)pParent, pSibling );
830 SwPageFrm *pPage = FindPageFrm();
831 _InvalidateAll();
832 InvalidatePage( pPage );
834 if( pPage )
836 pPage->InvalidateSpelling();
837 pPage->InvalidateSmartTags(); // SMARTTAGS
838 pPage->InvalidateAutoCompleteWords();
839 pPage->InvalidateWordCount();
842 if ( GetNext() )
844 SwFrm* pNxt = GetNext();
845 pNxt->_InvalidatePrt();
846 pNxt->_InvalidatePos();
847 pNxt->InvalidatePage( pPage );
848 if( pNxt->IsSctFrm() )
849 pNxt = ((SwSectionFrm*)pNxt)->ContainsCntnt();
850 if( pNxt && pNxt->IsTxtFrm() && pNxt->IsInFtn() )
851 pNxt->Prepare( PREP_FTN, 0, FALSE );
854 if ( Frm().Height() )
855 pParent->Grow( Frm().Height() );
857 if ( Frm().Width() != pParent->Prt().Width() )
858 Prepare( PREP_FIXSIZE_CHG );
860 if ( GetPrev() )
862 if ( IsFollow() )
863 //Ich bin jetzt direkter Nachfolger meines Masters geworden
864 ((SwCntntFrm*)GetPrev())->Prepare( PREP_FOLLOW_FOLLOWS );
865 else
867 if ( GetPrev()->Frm().Height() !=
868 GetPrev()->Prt().Height() + GetPrev()->Prt().Top() )
869 //Umrandung zu beruecksichtigen?
870 GetPrev()->_InvalidatePrt();
871 // OD 18.02.2003 #104989# - force complete paint of previous frame,
872 // if frame is inserted at the end of a section frame, in order to
873 // get subsidiary lines repainted for the section.
874 if ( pParent->IsSctFrm() && !GetNext() )
876 // force complete paint of previous frame, if new inserted frame
877 // in the section is the last one.
878 GetPrev()->SetCompletePaint();
880 GetPrev()->InvalidatePage( pPage );
883 if ( IsInFtn() )
885 SwFrm* pFrm = GetIndPrev();
886 if( pFrm && pFrm->IsSctFrm() )
887 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
888 if( pFrm )
889 pFrm->Prepare( PREP_QUOVADIS, 0, FALSE );
890 if( !GetNext() )
892 pFrm = FindFtnFrm()->GetNext();
893 if( pFrm && 0 != (pFrm=((SwLayoutFrm*)pFrm)->ContainsAny()) )
894 pFrm->_InvalidatePrt();
898 _InvalidateLineNum();
899 SwFrm *pNxt = FindNextCnt();
900 if ( pNxt )
902 while ( pNxt && pNxt->IsInTab() )
904 if( 0 != (pNxt = pNxt->FindTabFrm()) )
905 pNxt = pNxt->FindNextCnt();
907 if ( pNxt )
909 pNxt->_InvalidateLineNum();
910 if ( pNxt != GetNext() )
911 pNxt->InvalidatePage();
916 /*************************************************************************
918 |* SwCntntFrm::Cut()
920 |* Ersterstellung AK 14-Feb-1991
921 |* Letzte Aenderung MA 09. Sep. 98
923 |*************************************************************************/
924 void SwCntntFrm::Cut()
926 ASSERT( GetUpper(), "Cut ohne Upper()." );
928 SwPageFrm *pPage = FindPageFrm();
929 InvalidatePage( pPage );
930 SwFrm *pFrm = GetIndPrev();
931 if( pFrm )
933 if( pFrm->IsSctFrm() )
934 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
935 if ( pFrm && pFrm->IsCntntFrm() )
937 pFrm->_InvalidatePrt();
938 if( IsInFtn() )
939 pFrm->Prepare( PREP_QUOVADIS, 0, FALSE );
941 // --> OD 2004-07-15 #i26250# - invalidate printing area of previous
942 // table frame.
943 else if ( pFrm && pFrm->IsTabFrm() )
945 pFrm->InvalidatePrt();
947 // <--
950 SwFrm *pNxt = FindNextCnt();
951 if ( pNxt )
953 while ( pNxt && pNxt->IsInTab() )
955 if( 0 != (pNxt = pNxt->FindTabFrm()) )
956 pNxt = pNxt->FindNextCnt();
958 if ( pNxt )
960 pNxt->_InvalidateLineNum();
961 if ( pNxt != GetNext() )
962 pNxt->InvalidatePage();
966 if( 0 != (pFrm = GetIndNext()) )
967 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
968 //berechnet, der ist jetzt, wo er der erste wird obsolet bzw. anders.
969 pFrm->_InvalidatePrt();
970 pFrm->_InvalidatePos();
971 pFrm->InvalidatePage( pPage );
972 if( pFrm->IsSctFrm() )
974 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
975 if( pFrm )
977 pFrm->_InvalidatePrt();
978 pFrm->_InvalidatePos();
979 pFrm->InvalidatePage( pPage );
982 if( pFrm && IsInFtn() )
983 pFrm->Prepare( PREP_ERGOSUM, 0, FALSE );
984 if( IsInSct() && !GetPrev() )
986 SwSectionFrm* pSct = FindSctFrm();
987 if( !pSct->IsFollow() )
989 pSct->_InvalidatePrt();
990 pSct->InvalidatePage( pPage );
994 else
996 InvalidateNextPos();
997 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
998 if ( 0 != (pFrm = GetPrev()) )
999 { pFrm->SetRetouche();
1000 pFrm->Prepare( PREP_WIDOWS_ORPHANS );
1001 pFrm->_InvalidatePos();
1002 pFrm->InvalidatePage( pPage );
1004 //Wenn ich der einzige CntntFrm in meinem Upper bin (war), so muss
1005 //er die Retouche uebernehmen.
1006 //Ausserdem kann eine Leerseite entstanden sein.
1007 else
1008 { SwRootFrm *pRoot = FindRootFrm();
1009 if ( pRoot )
1011 pRoot->SetSuperfluous();
1012 GetUpper()->SetCompletePaint();
1013 GetUpper()->InvalidatePage( pPage );
1015 if( IsInSct() )
1017 SwSectionFrm* pSct = FindSctFrm();
1018 if( !pSct->IsFollow() )
1020 pSct->_InvalidatePrt();
1021 pSct->InvalidatePage( pPage );
1024 // --> FME 2005-08-03 #i52253# The master table should take care
1025 // of removing the follow flow line.
1026 if ( IsInTab() )
1028 SwTabFrm* pThisTab = FindTabFrm();
1029 SwTabFrm* pMasterTab = pThisTab && pThisTab->IsFollow() ? pThisTab->FindMaster() : 0;
1030 if ( pMasterTab )
1032 pMasterTab->_InvalidatePos();
1033 pMasterTab->SetRemoveFollowFlowLinePending( TRUE );
1036 // <--
1039 //Erst removen, dann Upper Shrinken.
1040 SwLayoutFrm *pUp = GetUpper();
1041 Remove();
1042 if ( pUp )
1044 SwSectionFrm *pSct = 0;
1045 if ( !pUp->Lower() &&
1046 ( ( pUp->IsFtnFrm() && !pUp->IsColLocked() ) ||
1047 ( pUp->IsInSct() &&
1048 // --> FME 2004-06-03 #i29438#
1049 // We have to consider the case that the section may be "empty"
1050 // except from a temporary empty table frame.
1051 // This can happen due to the new cell split feature.
1052 !pUp->IsCellFrm() &&
1053 // <--
1054 // --> OD 2006-01-04 #126020# - adjust check for empty section
1055 // --> OD 2006-02-01 #130797# - correct fix #126020#
1056 !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
1057 !pSct->ContainsAny( true ) ) ) )
1058 // <--
1060 if ( pUp->GetUpper() )
1062 // --> OD 2006-09-25 #b6448963#
1063 // prevent delete of <ColLocked> footnote frame
1064 // if( pUp->IsFtnFrm() )
1065 if ( pUp->IsFtnFrm() && !pUp->IsColLocked())
1066 // <--
1068 if( pUp->GetNext() && !pUp->GetPrev() )
1070 SwFrm* pTmp = ((SwLayoutFrm*)pUp->GetNext())->ContainsAny();
1071 if( pTmp )
1072 pTmp->_InvalidatePrt();
1074 pUp->Cut();
1075 delete pUp;
1077 else
1079 // --> OD 2006-09-25 #b6448963#
1080 // if ( pSct->IsColLocked() || !pSct->IsInFtn() )
1081 if ( pSct->IsColLocked() || !pSct->IsInFtn() ||
1082 ( pUp->IsFtnFrm() && pUp->IsColLocked() ) )
1083 // <--
1085 pSct->DelEmpty( FALSE );
1086 // Wenn ein gelockter Bereich nicht geloescht werden darf,
1087 // so ist zumindest seine Groesse durch das Entfernen seines
1088 // letzten Contents ungueltig geworden.
1089 pSct->_InvalidateSize();
1091 else
1093 pSct->DelEmpty( TRUE );
1094 delete pSct;
1099 else
1101 SWRECTFN( this )
1102 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1103 if( nFrmHeight )
1104 pUp->Shrink( nFrmHeight );
1109 /*************************************************************************
1111 |* SwLayoutFrm::Paste()
1113 |* Ersterstellung MA 23. Feb. 94
1114 |* Letzte Aenderung MA 23. Feb. 94
1116 |*************************************************************************/
1117 void SwLayoutFrm::Paste( SwFrm* pParent, SwFrm* pSibling)
1119 ASSERT( pParent, "Kein Parent fuer Paste." );
1120 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
1121 ASSERT( pParent != this, "Bin selbst der Parent." );
1122 ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
1123 ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
1124 "Bin noch irgendwo angemeldet." );
1126 //In den Baum einhaengen.
1127 InsertBefore( (SwLayoutFrm*)pParent, pSibling );
1129 // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
1130 // <fnRect> is used for the following:
1131 // (1) To invalidate the frame's size, if its size, which has to be the
1132 // same as its upper/parent, differs from its upper's/parent's.
1133 // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
1134 // size, which is not determined by its upper/parent.
1135 // Which size is which depends on the frame type and the layout direction
1136 // (vertical or horizontal).
1137 // There are the following cases:
1138 // (A) Header and footer frames both in vertical and in horizontal layout
1139 // have to size the width to the upper/parent. A dimension in the height
1140 // has to cause a adjustment/grow of the upper/parent.
1141 // --> <fnRect> = fnRectHori
1142 // (B) Cell and column frames in vertical layout, the width has to be the
1143 // same as upper/parent and a dimension in height causes adjustment/grow
1144 // of the upper/parent.
1145 // --> <fnRect> = fnRectHori
1146 // in horizontal layout the other way around
1147 // --> <fnRect> = fnRectVert
1148 // (C) Other frames in vertical layout, the height has to be the
1149 // same as upper/parent and a dimension in width causes adjustment/grow
1150 // of the upper/parent.
1151 // --> <fnRect> = fnRectVert
1152 // in horizontal layout the other way around
1153 // --> <fnRect> = fnRectHori
1154 //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
1155 SwRectFn fnRect;
1156 if ( IsHeaderFrm() || IsFooterFrm() )
1157 fnRect = fnRectHori;
1158 else if ( IsCellFrm() || IsColumnFrm() )
1159 fnRect = GetUpper()->IsVertical() ? fnRectHori : fnRectVert;
1160 else
1161 fnRect = GetUpper()->IsVertical() ? fnRectVert : fnRectHori;
1163 if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)())
1164 _InvalidateSize();
1165 _InvalidatePos();
1166 const SwPageFrm *pPage = FindPageFrm();
1167 InvalidatePage( pPage );
1168 SwFrm *pFrm;
1169 if( !IsColumnFrm() )
1171 if( 0 != ( pFrm = GetIndNext() ) )
1173 pFrm->_InvalidatePos();
1174 if( IsInFtn() )
1176 if( pFrm->IsSctFrm() )
1177 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
1178 if( pFrm )
1179 pFrm->Prepare( PREP_ERGOSUM, 0, FALSE );
1182 if ( IsInFtn() && 0 != ( pFrm = GetIndPrev() ) )
1184 if( pFrm->IsSctFrm() )
1185 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny();
1186 if( pFrm )
1187 pFrm->Prepare( PREP_QUOVADIS, 0, FALSE );
1191 if( (Frm().*fnRect->fnGetHeight)() )
1193 // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
1194 // die sich nicht in Rahmen befinden
1195 BYTE nAdjust = GetUpper()->IsFtnBossFrm() ?
1196 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
1197 : NA_GROW_SHRINK;
1198 SwTwips nGrow = (Frm().*fnRect->fnGetHeight)();
1199 if( NA_ONLY_ADJUST == nAdjust )
1200 AdjustNeighbourhood( nGrow );
1201 else
1203 SwTwips nReal = 0;
1204 if( NA_ADJUST_GROW == nAdjust )
1205 nReal = AdjustNeighbourhood( nGrow );
1206 if( nReal < nGrow )
1207 nReal += pParent->Grow( nGrow - nReal );
1208 if( NA_GROW_ADJUST == nAdjust && nReal < nGrow )
1209 AdjustNeighbourhood( nGrow - nReal );
1214 /*************************************************************************
1216 |* SwLayoutFrm::Cut()
1218 |* Ersterstellung MA 23. Feb. 94
1219 |* Letzte Aenderung MA 23. Feb. 94
1221 |*************************************************************************/
1222 void SwLayoutFrm::Cut()
1224 if ( GetNext() )
1225 GetNext()->_InvalidatePos();
1227 SWRECTFN( this )
1228 SwTwips nShrink = (Frm().*fnRect->fnGetHeight)();
1230 //Erst removen, dann Upper Shrinken.
1231 SwLayoutFrm *pUp = GetUpper();
1233 // AdjustNeighbourhood wird jetzt auch in Spalten aufgerufen,
1234 // die sich nicht in Rahmen befinden
1236 // Remove must not be called before a AdjustNeighbourhood, but it has to
1237 // be called before the upper-shrink-call, if the upper-shrink takes care
1238 // of his content
1239 if ( pUp && nShrink )
1241 if( pUp->IsFtnBossFrm() )
1243 BYTE nAdjust= ((SwFtnBossFrm*)pUp)->NeighbourhoodAdjustment( this );
1244 if( NA_ONLY_ADJUST == nAdjust )
1245 AdjustNeighbourhood( -nShrink );
1246 else
1248 SwTwips nReal = 0;
1249 if( NA_ADJUST_GROW == nAdjust )
1250 nReal = -AdjustNeighbourhood( -nShrink );
1251 if( nReal < nShrink )
1253 SwTwips nOldHeight = (Frm().*fnRect->fnGetHeight)();
1254 (Frm().*fnRect->fnSetHeight)( 0 );
1255 nReal += pUp->Shrink( nShrink - nReal );
1256 (Frm().*fnRect->fnSetHeight)( nOldHeight );
1258 if( NA_GROW_ADJUST == nAdjust && nReal < nShrink )
1259 AdjustNeighbourhood( nReal - nShrink );
1261 Remove();
1263 else
1265 Remove();
1266 pUp->Shrink( nShrink );
1269 else
1270 Remove();
1272 if( pUp && !pUp->Lower() )
1274 pUp->SetCompletePaint();
1275 pUp->InvalidatePage();
1279 /*************************************************************************
1281 |* SwFrm::Grow()
1283 |* Ersterstellung AK 19-Feb-1991
1284 |* Letzte Aenderung MA 05. May. 94
1286 |*************************************************************************/
1287 SwTwips SwFrm::Grow( SwTwips nDist, BOOL bTst, BOOL bInfo )
1289 ASSERT( nDist >= 0, "Negatives Wachstum?" );
1291 PROTOCOL_ENTER( this, bTst ? PROT_GROW_TST : PROT_GROW, 0, &nDist )
1293 if ( nDist )
1295 SWRECTFN( this )
1297 SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1298 if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
1299 nDist = LONG_MAX - nPrtHeight;
1301 if ( IsFlyFrm() )
1302 return ((SwFlyFrm*)this)->_Grow( nDist, bTst );
1303 else if( IsSctFrm() )
1304 return ((SwSectionFrm*)this)->_Grow( nDist, bTst );
1305 else
1307 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
1308 if ( pThisCell )
1310 const SwTabFrm* pTab = FindTabFrm();
1312 // NEW TABLES
1313 if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
1314 pThisCell->GetLayoutRowSpan() < 1 )
1315 return 0;
1318 const SwTwips nReal = GrowFrm( nDist, bTst, bInfo );
1319 if( !bTst )
1321 nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1322 (Prt().*fnRect->fnSetHeight)( nPrtHeight +
1323 ( IsCntntFrm() ? nDist : nReal ) );
1325 return nReal;
1328 return 0L;
1331 /*************************************************************************
1333 |* SwFrm::Shrink()
1335 |* Ersterstellung AK 14-Feb-1991
1336 |* Letzte Aenderung MA 05. May. 94
1338 |*************************************************************************/
1339 SwTwips SwFrm::Shrink( SwTwips nDist, BOOL bTst, BOOL bInfo )
1341 ASSERT( nDist >= 0, "Negative Verkleinerung?" );
1343 PROTOCOL_ENTER( this, bTst ? PROT_SHRINK_TST : PROT_SHRINK, 0, &nDist )
1345 if ( nDist )
1347 if ( IsFlyFrm() )
1348 return ((SwFlyFrm*)this)->_Shrink( nDist, bTst );
1349 else if( IsSctFrm() )
1350 return ((SwSectionFrm*)this)->_Shrink( nDist, bTst );
1351 else
1353 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
1354 if ( pThisCell )
1356 const SwTabFrm* pTab = FindTabFrm();
1358 // NEW TABLES
1359 if ( ( 0 != pTab->IsVertical() ) != ( 0 != IsVertical() ) ||
1360 pThisCell->GetLayoutRowSpan() < 1 )
1361 return 0;
1364 SWRECTFN( this )
1365 SwTwips nReal = (Frm().*fnRect->fnGetHeight)();
1366 ShrinkFrm( nDist, bTst, bInfo );
1367 nReal -= (Frm().*fnRect->fnGetHeight)();
1368 if( !bTst )
1370 const SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
1371 (Prt().*fnRect->fnSetHeight)( nPrtHeight -
1372 ( IsCntntFrm() ? nDist : nReal ) );
1374 return nReal;
1377 return 0L;
1380 /*************************************************************************
1382 |* SwFrm::AdjustNeighbourhood()
1384 |* Beschreibung Wenn sich die Groesse eines Frm's direkt unterhalb
1385 |* eines Fussnotenbosses (Seite/Spalte) veraendert hat, so muss dieser
1386 |* "Normalisiert" werden.
1387 |* Es gibt dort immer einen Frame, der den "maximal moeglichen" Raum
1388 |* einnimmt (der Frame, der den Body.Text enhaelt) und keinen oder
1389 |* mehrere Frames die den Platz einnehmen den sie halt brauchen
1390 |* (Kopf-/Fussbereich, Fussnoten).
1391 |* Hat sich einer der Frames veraendert, so muss der Body-Text-Frame
1392 |* entsprechen wachsen oder schrumpfen; unabhaegig davon, dass er fix ist.
1393 |* !! Ist es moeglich dies allgemeiner zu loesen, also nicht auf die
1394 |* Seite beschraenkt und nicht auf einen Speziellen Frame, der den
1395 |* maximalen Platz einnimmt (gesteuert ueber Attribut FrmSize)? Probleme:
1396 |* Was ist wenn mehrere Frames nebeneinander stehen, die den maximalen
1397 |* Platz einnehmen?
1398 |* Wie wird der Maximale Platz berechnet?
1399 |* Wie klein duerfen diese Frames werden?
1401 |* Es wird auf jeden Fall nur so viel Platz genehmigt, dass ein
1402 |* Minimalwert fuer die Hoehe des Bodys nicht unterschritten wird.
1404 |* Parameter: nDiff ist der Betrag, um den Platz geschaffen werden muss
1406 |* Ersterstellung MA 07. May. 92
1407 |* Letzte Aenderung AMA 02. Nov. 98
1409 |*************************************************************************/
1410 SwTwips SwFrm::AdjustNeighbourhood( SwTwips nDiff, BOOL bTst )
1412 PROTOCOL_ENTER( this, PROT_ADJUSTN, 0, &nDiff );
1414 if ( !nDiff || !GetUpper()->IsFtnBossFrm() ) // nur innerhalb von Seiten/Spalten
1415 return 0L;
1417 BOOL bBrowse = GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
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;
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
1431 ViewShell *pSh = GetShell();
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 ( pSh )
1439 aInva.Pos().X() = pSh->VisArea().Left();
1440 aInva.Width( pSh->VisArea().Width() );
1442 if ( nDiff > 0 )
1444 nChg = BROWSE_HEIGHT - pUp->Frm().Height();
1445 nChg = Min( nDiff, nChg );
1447 if ( !IsBodyFrm() )
1449 SetCompletePaint();
1450 if ( !pSh || pSh->VisArea().Height() >= pUp->Frm().Height() )
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 )
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();
1466 nChg = nTmp <= 0 ? 0 : nTmp;
1470 const long nTmp = nUpPrtBottom + 20;
1471 aInva.Top( aInva.Bottom() - nTmp );
1472 aInva.Height( nChg + nTmp );
1474 else
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 ( pSh && !pUp->GetPrev() &&
1481 pUp->Frm().Height() + nDiff < pSh->VisArea().Height() )
1483 //Das heisst aber wiederum trotzdem, das wir geeignet invalidieren
1484 //muessen.
1485 nChg = pSh->VisArea().Height() - pUp->Frm().Height();
1486 nInvaAdd = -(nDiff - nChg);
1489 //Invalidieren inklusive unterem Rand.
1490 long nBorder = nUpPrtBottom + 20;
1491 nBorder -= nChg;
1492 aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
1493 if ( !IsBodyFrm() )
1495 SetCompletePaint();
1496 if ( !IsHeaderFrm() )
1497 ((SwFtnBossFrm*)pUp)->FindBodyCont()->SetCompletePaint();
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();
1505 if ( !bTst )
1507 //Unabhaengig von nChg
1508 if ( pSh && aInva.HasArea() && pUp->GetUpper() )
1509 pSh->InvalidateWindows( aInva );
1511 if ( !bTst && nChg )
1513 const SwRect aOldRect( pUp->Frm() );
1514 pUp->Frm().SSize().Height() += nChg;
1515 pUp->Prt().SSize().Height() += nChg;
1516 if ( pSh )
1517 pSh->Imp()->SetFirstVisPageInvalid();
1519 if ( GetNext() )
1520 GetNext()->_InvalidatePos();
1522 //Ggf. noch ein Repaint ausloesen.
1523 const SvxGraphicPosition ePos = pUp->GetFmt()->GetBackground().GetGraphicPos();
1524 if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
1525 pSh->InvalidateWindows( pUp->Frm() );
1527 if ( pUp->GetUpper() )
1529 if ( pUp->GetNext() )
1530 pUp->GetNext()->InvalidatePos();
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 BOOL bOldComplete = IsCompletePaint();
1539 if ( IsBodyFrm() )
1540 Prt().SSize().Height() = nOldFrmHeight;
1542 // PAGES01
1543 if ( pUp->GetUpper() )
1544 static_cast<SwRootFrm*>(pUp->GetUpper())->CheckViewLayout( 0, 0 );
1545 //((SwPageFrm*)pUp)->AdjustRootSize( CHG_CHGPAGE, &aOldRect );
1547 Frm().SSize().Height() = nOldFrmHeight;
1548 Prt().SSize().Height() = nOldPrtHeight;
1549 bCompletePaint = bOldComplete;
1551 if ( !IsBodyFrm() )
1552 pUp->_InvalidateSize();
1553 InvalidatePage( (SwPageFrm*)pUp );
1555 nDiff -= nChg;
1556 if ( !nDiff )
1557 return nChg;
1558 else
1559 nBrowseAdd = nChg;
1562 const SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
1564 SwTwips nReal = 0,
1565 nAdd = 0;
1566 SwFrm *pFrm = 0;
1567 SWRECTFN( this )
1569 if( IsBodyFrm() )
1571 if( IsInSct() )
1573 SwSectionFrm *pSect = FindSctFrm();
1574 if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
1575 GetNext()->IsFtnContFrm() )
1577 SwFtnContFrm* pCont = (SwFtnContFrm*)GetNext();
1578 SwTwips nMinH = 0;
1579 SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
1580 BOOL bFtn = FALSE;
1581 while( pFtn )
1583 if( !pFtn->GetAttr()->GetFtn().IsEndNote() )
1585 nMinH += (pFtn->Frm().*fnRect->fnGetHeight)();
1586 bFtn = TRUE;
1588 pFtn = (SwFtnFrm*)pFtn->GetNext();
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;
1600 if( !bTst && !pSect->IsColLocked() )
1601 pSect->InvalidateSize();
1603 if( !pFrm )
1604 return nBrowseAdd;
1606 else
1608 const BOOL bFtnPage = pBoss->IsPageFrm() && ((SwPageFrm*)pBoss)->IsFtnPage();
1609 if ( bFtnPage && !IsFtnContFrm() )
1610 pFrm = (SwFrm*)pBoss->FindFtnCont();
1611 if ( !pFrm )
1612 pFrm = (SwFrm*)pBoss->FindBodyCont();
1614 if ( !pFrm )
1615 return 0;
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 )
1623 //Minimalgrenze beachten!
1624 if( nReal )
1626 const SwTwips nMax = pBoss->GetVarSpace();
1627 if ( nReal > nMax )
1628 nReal = nMax;
1630 if( !IsFtnContFrm() && nDiff > nReal &&
1631 pFrm->GetNext() && pFrm->GetNext()->IsFtnContFrm()
1632 && ( pFrm->GetNext()->IsVertical() == IsVertical() )
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 )
1645 (pFrm->GetNext()->Frm().*fnRect->fnSetHeight)(nAddMax-nAdd);
1646 if( bVert && !bRev )
1647 pFrm->GetNext()->Frm().Pos().X() += nAdd;
1648 pFrm->GetNext()->InvalidatePrt();
1649 if ( pFrm->GetNext()->GetNext() )
1650 pFrm->GetNext()->GetNext()->_InvalidatePos();
1656 if ( !bTst && nReal )
1658 SwTwips nTmp = (pFrm->Frm().*fnRect->fnGetHeight)();
1659 (pFrm->Frm().*fnRect->fnSetHeight)( nTmp - nReal );
1660 if( bVert && !bRev )
1661 pFrm->Frm().Pos().X() += nReal;
1662 pFrm->InvalidatePrt();
1663 if ( pFrm->GetNext() )
1664 pFrm->GetNext()->_InvalidatePos();
1665 if( nReal < 0 && pFrm->IsInSct() )
1667 SwLayoutFrm* pUp = pFrm->GetUpper();
1668 if( pUp && 0 != ( pUp = pUp->GetUpper() ) && pUp->IsSctFrm() &&
1669 !pUp->IsColLocked() )
1670 pUp->InvalidateSize();
1672 if( ( IsHeaderFrm() || IsFooterFrm() ) && pBoss->GetDrawObjs() )
1674 const SwSortedObjs &rObjs = *pBoss->GetDrawObjs();
1675 ASSERT( pBoss->IsPageFrm(), "Header/Footer out of page?" );
1676 for ( USHORT i = 0; i < rObjs.Count(); ++i )
1678 SwAnchoredObject* pAnchoredObj = rObjs[i];
1679 if ( pAnchoredObj->ISA(SwFlyFrm) )
1681 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1682 ASSERT( !pFly->IsFlyInCntFrm(), "FlyInCnt at Page?" );
1683 const SwFmtVertOrient &rVert =
1684 pFly->GetFmt()->GetVertOrient();
1685 // Wann muss invalidiert werden?
1686 // Wenn ein Rahmen am SeitenTextBereich ausgerichtet ist,
1687 // muss bei Aenderung des Headers ein TOP, MIDDLE oder NONE,
1688 // bei Aenderung des Footers ein BOTTOM oder MIDDLE
1689 // ausgerichteter Rahmen seine Position neu berechnen.
1690 if( ( rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ||
1691 rVert.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) &&
1692 ((IsHeaderFrm() && rVert.GetVertOrient()!=text::VertOrientation::BOTTOM) ||
1693 (IsFooterFrm() && rVert.GetVertOrient()!=text::VertOrientation::NONE &&
1694 rVert.GetVertOrient() != text::VertOrientation::TOP)) )
1696 pFly->_InvalidatePos();
1697 pFly->_Invalidate();
1703 return (nBrowseAdd + nReal + nAdd);
1706 /*************************************************************************
1708 |* SwFrm::ImplInvalidateSize(), ImplInvalidatePrt(), ImplInvalidatePos(),
1709 |* ImplInvalidateLineNum()
1711 |* Ersterstellung MA 15. Oct. 92
1712 |* Letzte Aenderung MA 24. Mar. 94
1714 |*************************************************************************/
1715 /** method to perform additional actions on an invalidation
1717 OD 2004-05-19 #i28701#
1719 @author OD
1721 void SwFrm::_ActionOnInvalidation( const InvalidationType )
1723 // default behaviour is to perform no additional action
1726 /** method to determine, if an invalidation is allowed.
1728 OD 2004-05-19 #i28701#
1730 @author OD
1732 bool SwFrm::_InvalidationAllowed( const InvalidationType ) const
1734 // default behaviour is to allow invalidation
1735 return true;
1738 void SwFrm::ImplInvalidateSize()
1740 if ( _InvalidationAllowed( INVALID_SIZE ) )
1742 bValidSize = FALSE;
1743 if ( IsFlyFrm() )
1744 ((SwFlyFrm*)this)->_Invalidate();
1745 else
1746 InvalidatePage();
1748 // OD 2004-05-19 #i28701#
1749 _ActionOnInvalidation( INVALID_SIZE );
1753 void SwFrm::ImplInvalidatePrt()
1755 if ( _InvalidationAllowed( INVALID_PRTAREA ) )
1757 bValidPrtArea = FALSE;
1758 if ( IsFlyFrm() )
1759 ((SwFlyFrm*)this)->_Invalidate();
1760 else
1761 InvalidatePage();
1763 // OD 2004-05-19 #i28701#
1764 _ActionOnInvalidation( INVALID_PRTAREA );
1768 void SwFrm::ImplInvalidatePos()
1770 if ( _InvalidationAllowed( INVALID_POS ) )
1772 bValidPos = FALSE;
1773 if ( IsFlyFrm() )
1775 ((SwFlyFrm*)this)->_Invalidate();
1777 else
1779 InvalidatePage();
1782 // OD 2004-05-19 #i28701#
1783 _ActionOnInvalidation( INVALID_POS );
1787 void SwFrm::ImplInvalidateLineNum()
1789 if ( _InvalidationAllowed( INVALID_LINENUM ) )
1791 bValidLineNum = FALSE;
1792 ASSERT( IsTxtFrm(), "line numbers are implemented for text only" );
1793 InvalidatePage();
1795 // OD 2004-05-19 #i28701#
1796 _ActionOnInvalidation( INVALID_LINENUM );
1800 /*************************************************************************
1802 |* SwFrm::ReinitializeFrmSizeAttrFlags
1804 |* Ersterstellung MA 15. Oct. 96
1805 |* Letzte Aenderung MA 15. Oct. 96
1807 |*************************************************************************/
1808 void SwFrm::ReinitializeFrmSizeAttrFlags()
1810 const SwFmtFrmSize &rFmtSize = GetAttrSet()->GetFrmSize();
1811 if ( ATT_VAR_SIZE == rFmtSize.GetHeightSizeType() ||
1812 ATT_MIN_SIZE == rFmtSize.GetHeightSizeType())
1814 bFixSize = FALSE;
1815 if ( GetType() & (FRM_HEADER | FRM_FOOTER | FRM_ROW) )
1817 SwFrm *pFrm = ((SwLayoutFrm*)this)->Lower();
1818 while ( pFrm )
1819 { pFrm->_InvalidateSize();
1820 pFrm->_InvalidatePrt();
1821 pFrm = pFrm->GetNext();
1823 SwCntntFrm *pCnt = ((SwLayoutFrm*)this)->ContainsCntnt();
1824 // --> OD 2004-12-20 #i36991# - be save.
1825 // E.g., a row can contain *no* content.
1826 if ( pCnt )
1828 pCnt->InvalidatePage();
1831 pCnt->Prepare( PREP_ADJUST_FRM );
1832 pCnt->_InvalidateSize();
1833 pCnt = pCnt->GetNextCntntFrm();
1834 } while ( ((SwLayoutFrm*)this)->IsAnLower( pCnt ) );
1836 // <--
1839 else if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
1841 if( IsVertical() )
1842 ChgSize( Size( rFmtSize.GetWidth(), Frm().Height()));
1843 else
1844 ChgSize( Size( Frm().Width(), rFmtSize.GetHeight()));
1848 /*************************************************************************
1849 |* SwFrm::ValidateThisAndAllLowers()
1851 * FME 2007-08-30 #i81146# new loop control
1852 |*************************************************************************/
1853 void SwFrm::ValidateThisAndAllLowers( const USHORT nStage )
1855 // Stage 0: Only validate frames. Do not process any objects.
1856 // Stage 1: Only validate fly frames and all of their contents.
1857 // Stage 2: Validate all.
1859 const bool bOnlyObject = 1 == nStage;
1860 const bool bIncludeObjects = 1 <= nStage;
1862 if ( !bOnlyObject || ISA(SwFlyFrm) )
1864 bValidSize = TRUE;
1865 bValidPrtArea = TRUE;
1866 bValidPos = TRUE;
1869 if ( bIncludeObjects )
1871 const SwSortedObjs* pObjs = GetDrawObjs();
1872 if ( pObjs )
1874 const sal_uInt32 nCnt = pObjs->Count();
1875 for ( sal_uInt32 i = 0; i < nCnt; ++i )
1877 SwAnchoredObject* pAnchObj = (*pObjs)[i];
1878 if ( pAnchObj->ISA(SwFlyFrm) )
1879 static_cast<SwFlyFrm*>(pAnchObj)->ValidateThisAndAllLowers( 2 );
1880 else if ( pAnchObj->ISA(SwAnchoredDrawObject) )
1881 static_cast<SwAnchoredDrawObject*>(pAnchObj)->ValidateThis();
1886 if ( IsLayoutFrm() )
1888 SwFrm* pLower = static_cast<SwLayoutFrm*>(this)->Lower();
1889 while ( pLower )
1891 pLower->ValidateThisAndAllLowers( nStage );
1892 pLower = pLower->GetNext();
1897 /*************************************************************************
1899 |* SwCntntFrm::GrowFrm()
1901 |* Ersterstellung MA 30. Jul. 92
1902 |* Letzte Aenderung MA 25. Mar. 99
1904 |*************************************************************************/
1905 SwTwips SwCntntFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
1907 SWRECTFN( this )
1909 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
1910 if( nFrmHeight > 0 &&
1911 nDist > (LONG_MAX - nFrmHeight ) )
1912 nDist = LONG_MAX - nFrmHeight;
1914 const BOOL bBrowse = GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
1915 const USHORT nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
1916 if( !(GetUpper()->GetType() & nTmpType) && GetUpper()->HasFixSize() )
1918 if ( !bTst )
1920 (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
1921 if( IsVertical() && !IsReverse() )
1922 Frm().Pos().X() -= nDist;
1923 if ( GetNext() )
1925 GetNext()->InvalidatePos();
1927 // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
1928 // frame on the next page/column can flow backward (e.g. it was moved forward
1929 // due to the positioning of its objects ). Thus, invalivate this next frame,
1930 // if document compatibility option 'Consider wrapping style influence on
1931 // object positioning' is ON.
1932 else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
1934 InvalidateNextPos();
1936 // <--
1938 return 0;
1941 SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
1942 SwFrm *pFrm = GetUpper()->Lower();
1943 while( pFrm && nReal > 0 )
1944 { nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
1945 pFrm = pFrm->GetNext();
1948 if ( !bTst )
1950 //Cntnts werden immer auf den gewuenschten Wert gebracht.
1951 long nOld = (Frm().*fnRect->fnGetHeight)();
1952 (Frm().*fnRect->fnSetHeight)( nOld + nDist );
1953 if( IsVertical() && !IsReverse() )
1954 Frm().Pos().X() -= nDist;
1955 if ( nOld && IsInTab() )
1957 SwTabFrm *pTab = FindTabFrm();
1958 if ( pTab->GetTable()->GetHTMLTableLayout() &&
1959 !pTab->IsJoinLocked() &&
1960 !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
1962 pTab->InvalidatePos();
1963 pTab->SetResizeHTMLTable();
1968 //Upper nur growen wenn notwendig.
1969 if ( nReal < nDist )
1971 if( GetUpper() )
1973 if( bTst || !GetUpper()->IsFooterFrm() )
1974 nReal = GetUpper()->Grow( nDist - (nReal > 0 ? nReal : 0),
1975 bTst, bInfo );
1976 else
1978 nReal = 0;
1979 GetUpper()->InvalidateSize();
1982 else
1983 nReal = 0;
1985 else
1986 nReal = nDist;
1988 // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
1989 // frame on the next page/column can flow backward (e.g. it was moved forward
1990 // due to the positioning of its objects ). Thus, invalivate this next frame,
1991 // if document compatibility option 'Consider wrapping style influence on
1992 // object positioning' is ON.
1993 if ( !bTst )
1995 if ( GetNext() )
1997 GetNext()->InvalidatePos();
1999 else if ( GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
2001 InvalidateNextPos();
2004 // <--
2006 return nReal;
2009 /*************************************************************************
2011 |* SwCntntFrm::ShrinkFrm()
2013 |* Ersterstellung MA 30. Jul. 92
2014 |* Letzte Aenderung MA 05. May. 94
2016 |*************************************************************************/
2017 SwTwips SwCntntFrm::ShrinkFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
2019 SWRECTFN( this )
2020 ASSERT( nDist >= 0, "nDist < 0" );
2021 ASSERT( nDist <= (Frm().*fnRect->fnGetHeight)(),
2022 "nDist > als aktuelle Grosse." );
2024 if ( !bTst )
2026 SwTwips nRstHeight;
2027 if( GetUpper() )
2028 nRstHeight = (Frm().*fnRect->fnBottomDist)
2029 ( (GetUpper()->*fnRect->fnGetPrtBottom)() );
2030 else
2031 nRstHeight = 0;
2032 if( nRstHeight < 0 )
2034 SwTwips nNextHeight = 0;
2035 if( GetUpper()->IsSctFrm() && nDist > LONG_MAX/2 )
2037 SwFrm *pNxt = GetNext();
2038 while( pNxt )
2040 nNextHeight += (pNxt->Frm().*fnRect->fnGetHeight)();
2041 pNxt = pNxt->GetNext();
2044 nRstHeight = nDist + nRstHeight - nNextHeight;
2046 else
2047 nRstHeight = nDist;
2048 (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() - nDist );
2049 if( IsVertical() )
2050 Frm().Pos().X() += nDist;
2051 nDist = nRstHeight;
2052 if ( IsInTab() )
2054 SwTabFrm *pTab = FindTabFrm();
2055 if ( pTab->GetTable()->GetHTMLTableLayout() &&
2056 !pTab->IsJoinLocked() &&
2057 !pTab->GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() )
2059 pTab->InvalidatePos();
2060 pTab->SetResizeHTMLTable();
2065 SwTwips nReal;
2066 if( GetUpper() && nDist > 0 )
2068 if( bTst || !GetUpper()->IsFooterFrm() )
2069 nReal = GetUpper()->Shrink( nDist, bTst, bInfo );
2070 else
2072 nReal = 0;
2074 // #108745# Sorry, dear old footer friend, I'm not gonna invalidate you,
2075 // if there are any objects anchored inside your content, which
2076 // overlap with the shrinking frame.
2077 // This may lead to a footer frame that is too big, but this is better
2078 // than looping.
2079 // #109722# : The fix for #108745# was too strict.
2081 bool bInvalidate = true;
2082 const SwRect aRect( Frm() );
2083 const SwPageFrm* pPage = FindPageFrm();
2084 const SwSortedObjs* pSorted = pPage ? pPage->GetSortedObjs() : 0;
2085 if( pSorted )
2087 for ( USHORT i = 0; i < pSorted->Count(); ++i )
2089 const SwAnchoredObject* pAnchoredObj = (*pSorted)[i];
2090 const SwRect aBound( pAnchoredObj->GetObjRectWithSpaces() );
2092 if( aBound.Left() > aRect.Right() )
2093 continue;
2095 if( aBound.IsOver( aRect ) )
2097 const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
2098 if( SURROUND_THROUGHT != rFmt.GetSurround().GetSurround() )
2100 const SwFrm* pAnchor = pAnchoredObj->GetAnchorFrm();
2101 if ( pAnchor && pAnchor->FindFooterOrHeader() == GetUpper() )
2103 bInvalidate = false;
2104 break;
2111 if ( bInvalidate )
2112 GetUpper()->InvalidateSize();
2115 else
2116 nReal = 0;
2118 if ( !bTst )
2120 //Die Position des naechsten Frm's veraendert sich auf jeden Fall.
2121 InvalidateNextPos();
2123 //Wenn ich keinen Nachfolger habe, so muss ich mich eben selbst um
2124 //die Retusche kuemmern.
2125 if ( !GetNext() )
2126 SetRetouche();
2128 return nReal;
2131 /*************************************************************************
2133 |* SwCntntFrm::Modify()
2135 |* Beschreibung
2136 |* Ersterstellung AK 05-Mar-1991
2137 |* Letzte Aenderung MA 13. Oct. 95
2139 |*************************************************************************/
2140 void SwCntntFrm::Modify( SfxPoolItem * pOld, SfxPoolItem * pNew )
2142 BYTE nInvFlags = 0;
2144 if( pNew && RES_ATTRSET_CHG == pNew->Which() )
2146 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
2147 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
2148 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
2149 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
2150 while( TRUE )
2152 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
2153 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
2154 &aOldSet, &aNewSet );
2155 if( aNIter.IsAtEnd() )
2156 break;
2157 aNIter.NextItem();
2158 aOIter.NextItem();
2160 if ( aOldSet.Count() || aNewSet.Count() )
2161 SwFrm::Modify( &aOldSet, &aNewSet );
2163 else
2164 _UpdateAttr( pOld, pNew, nInvFlags );
2166 if ( nInvFlags != 0 )
2168 SwPageFrm *pPage = FindPageFrm();
2169 InvalidatePage( pPage );
2170 if ( nInvFlags & 0x01 )
2171 SetCompletePaint();
2172 if ( nInvFlags & 0x02 )
2173 _InvalidatePos();
2174 if ( nInvFlags & 0x04 )
2175 _InvalidateSize();
2176 if ( nInvFlags & 0x88 )
2178 if( IsInSct() && !GetPrev() )
2180 SwSectionFrm *pSect = FindSctFrm();
2181 if( pSect->ContainsAny() == this )
2183 pSect->_InvalidatePrt();
2184 pSect->InvalidatePage( pPage );
2187 _InvalidatePrt();
2189 SwFrm* pNextFrm = GetIndNext();
2190 if ( pNextFrm && nInvFlags & 0x10)
2192 pNextFrm->_InvalidatePrt();
2193 pNextFrm->InvalidatePage( pPage );
2195 if ( pNextFrm && nInvFlags & 0x80 )
2197 pNextFrm->SetCompletePaint();
2199 if ( nInvFlags & 0x20 )
2201 SwFrm* pPrevFrm = GetPrev();
2202 if ( pPrevFrm )
2204 pPrevFrm->_InvalidatePrt();
2205 pPrevFrm->InvalidatePage( pPage );
2208 if ( nInvFlags & 0x40 )
2209 InvalidateNextPos();
2213 void SwCntntFrm::_UpdateAttr( SfxPoolItem* pOld, SfxPoolItem* pNew,
2214 BYTE &rInvFlags,
2215 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
2217 BOOL bClear = TRUE;
2218 USHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2219 switch ( nWhich )
2221 case RES_FMT_CHG:
2222 rInvFlags = 0xFF;
2223 /* kein break hier */
2225 case RES_PAGEDESC: //Attributaenderung (an/aus)
2226 if ( IsInDocBody() && !IsInTab() )
2228 rInvFlags |= 0x02;
2229 SwPageFrm *pPage = FindPageFrm();
2230 if ( !GetPrev() )
2231 CheckPageDescs( pPage );
2232 if ( pPage && GetAttrSet()->GetPageDesc().GetNumOffset() )
2233 ((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( TRUE );
2234 SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
2235 pPage->GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
2237 break;
2239 case RES_UL_SPACE:
2241 // OD 2004-02-18 #106629# - correction
2242 // Invalidation of the printing area of next frame, not only
2243 // for footnote content.
2244 if ( !GetIndNext() )
2246 SwFrm* pNxt = FindNext();
2247 if ( pNxt )
2249 SwPageFrm* pPg = pNxt->FindPageFrm();
2250 pNxt->InvalidatePage( pPg );
2251 pNxt->_InvalidatePrt();
2252 if( pNxt->IsSctFrm() )
2254 SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
2255 if( pCnt )
2257 pCnt->_InvalidatePrt();
2258 pCnt->InvalidatePage( pPg );
2261 pNxt->SetCompletePaint();
2264 // OD 2004-03-17 #i11860#
2265 if ( GetIndNext() &&
2266 !GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
2268 // OD 2004-07-01 #i28701# - use new method <InvalidateObjs(..)>
2269 GetIndNext()->InvalidateObjs( true );
2271 Prepare( PREP_UL_SPACE ); //TxtFrm muss Zeilenabst. korrigieren.
2272 rInvFlags |= 0x80;
2273 /* kein Break hier */
2275 case RES_LR_SPACE:
2276 case RES_BOX:
2277 case RES_SHADOW:
2278 Prepare( PREP_FIXSIZE_CHG );
2279 SwFrm::Modify( pOld, pNew );
2280 rInvFlags |= 0x30;
2281 break;
2283 case RES_BREAK:
2285 rInvFlags |= 0x42;
2286 const IDocumentSettingAccess* pIDSA = GetUpper()->GetFmt()->getIDocumentSettingAccess();
2287 if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
2288 pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) )
2290 rInvFlags |= 0x1;
2291 SwFrm* pNxt = FindNext();
2292 if( pNxt )
2294 SwPageFrm* pPg = pNxt->FindPageFrm();
2295 pNxt->InvalidatePage( pPg );
2296 pNxt->_InvalidatePrt();
2297 if( pNxt->IsSctFrm() )
2299 SwFrm* pCnt = ((SwSectionFrm*)pNxt)->ContainsAny();
2300 if( pCnt )
2302 pCnt->_InvalidatePrt();
2303 pCnt->InvalidatePage( pPg );
2306 pNxt->SetCompletePaint();
2310 break;
2312 // OD 2004-02-26 #i25029#
2313 case RES_PARATR_CONNECT_BORDER:
2315 rInvFlags |= 0x01;
2316 if ( IsTxtFrm() )
2318 InvalidateNextPrtArea();
2320 if ( !GetIndNext() && IsInTab() && IsInSplitTableRow() )
2322 FindTabFrm()->InvalidateSize();
2325 break;
2327 case RES_PARATR_TABSTOP:
2328 case RES_CHRATR_PROPORTIONALFONTSIZE:
2329 case RES_CHRATR_SHADOWED:
2330 case RES_CHRATR_AUTOKERN:
2331 case RES_CHRATR_UNDERLINE:
2332 case RES_CHRATR_OVERLINE:
2333 case RES_CHRATR_KERNING:
2334 case RES_CHRATR_FONT:
2335 case RES_CHRATR_FONTSIZE:
2336 case RES_CHRATR_ESCAPEMENT:
2337 case RES_CHRATR_CONTOUR:
2338 case RES_PARATR_NUMRULE:
2339 rInvFlags |= 0x01;
2340 break;
2343 case RES_FRM_SIZE:
2344 rInvFlags |= 0x01;
2345 /* no break here */
2347 default:
2348 bClear = FALSE;
2350 if ( bClear )
2352 if ( pOldSet || pNewSet )
2354 if ( pOldSet )
2355 pOldSet->ClearItem( nWhich );
2356 if ( pNewSet )
2357 pNewSet->ClearItem( nWhich );
2359 else
2360 SwFrm::Modify( pOld, pNew );
2364 /*************************************************************************
2366 |* SwLayoutFrm::SwLayoutFrm()
2368 |* Ersterstellung AK 14-Feb-1991
2369 |* Letzte Aenderung MA 12. May. 95
2371 |*************************************************************************/
2372 SwLayoutFrm::SwLayoutFrm( SwFrmFmt* pFmt ):
2373 SwFrm( pFmt ),
2374 pLower( 0 )
2376 const SwFmtFrmSize &rFmtSize = pFmt->GetFrmSize();
2377 if ( rFmtSize.GetHeightSizeType() == ATT_FIX_SIZE )
2378 bFixSize = TRUE;
2381 // --> OD 2004-06-29 #i28701#
2382 TYPEINIT1(SwLayoutFrm,SwFrm);
2383 // <--
2384 /*-----------------10.06.99 09:42-------------------
2385 * SwLayoutFrm::InnerHeight()
2386 * --------------------------------------------------*/
2388 SwTwips SwLayoutFrm::InnerHeight() const
2390 if( !Lower() )
2391 return 0;
2392 SwTwips nRet = 0;
2393 const SwFrm* pCnt = Lower();
2394 SWRECTFN( this )
2395 if( pCnt->IsColumnFrm() || pCnt->IsCellFrm() )
2399 SwTwips nTmp = ((SwLayoutFrm*)pCnt)->InnerHeight();
2400 if( pCnt->GetValidPrtAreaFlag() )
2401 nTmp += (pCnt->Frm().*fnRect->fnGetHeight)() -
2402 (pCnt->Prt().*fnRect->fnGetHeight)();
2403 if( nRet < nTmp )
2404 nRet = nTmp;
2405 pCnt = pCnt->GetNext();
2406 } while ( pCnt );
2408 else
2412 nRet += (pCnt->Frm().*fnRect->fnGetHeight)();
2413 if( pCnt->IsCntntFrm() && ((SwTxtFrm*)pCnt)->IsUndersized() )
2414 nRet += ((SwTxtFrm*)pCnt)->GetParHeight() -
2415 (pCnt->Prt().*fnRect->fnGetHeight)();
2416 if( pCnt->IsLayoutFrm() && !pCnt->IsTabFrm() )
2417 nRet += ((SwLayoutFrm*)pCnt)->InnerHeight() -
2418 (pCnt->Prt().*fnRect->fnGetHeight)();
2419 pCnt = pCnt->GetNext();
2420 } while( pCnt );
2423 return nRet;
2426 /*************************************************************************
2428 |* SwLayoutFrm::GrowFrm()
2430 |* Ersterstellung MA 30. Jul. 92
2431 |* Letzte Aenderung MA 23. Sep. 96
2433 |*************************************************************************/
2434 SwTwips SwLayoutFrm::GrowFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
2436 const BOOL bBrowse = GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
2437 const USHORT nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
2438 if( !(GetType() & nTmpType) && HasFixSize() )
2439 return 0;
2441 SWRECTFN( this )
2442 const SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2443 const SwTwips nFrmPos = Frm().Pos().X();
2445 if ( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) )
2446 nDist = LONG_MAX - nFrmHeight;
2448 SwTwips nMin = 0;
2449 if ( GetUpper() && !IsCellFrm() )
2451 SwFrm *pFrm = GetUpper()->Lower();
2452 while( pFrm )
2453 { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
2454 pFrm = pFrm->GetNext();
2456 nMin = (GetUpper()->Prt().*fnRect->fnGetHeight)() - nMin;
2457 if ( nMin < 0 )
2458 nMin = 0;
2461 SwRect aOldFrm( Frm() );
2462 sal_Bool bMoveAccFrm = sal_False;
2464 BOOL bChgPos = IsVertical() && !IsReverse();
2465 if ( !bTst )
2467 (Frm().*fnRect->fnSetHeight)( nFrmHeight + nDist );
2468 if( bChgPos )
2469 Frm().Pos().X() -= nDist;
2470 bMoveAccFrm = sal_True;
2473 SwTwips nReal = nDist - nMin;
2474 if ( nReal > 0 )
2476 if ( GetUpper() )
2477 { // AdjustNeighbourhood jetzt auch in Spalten (aber nicht in Rahmen)
2478 BYTE nAdjust = GetUpper()->IsFtnBossFrm() ?
2479 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
2480 : NA_GROW_SHRINK;
2481 if( NA_ONLY_ADJUST == nAdjust )
2482 nReal = AdjustNeighbourhood( nReal, bTst );
2483 else
2485 if( NA_ADJUST_GROW == nAdjust )
2486 nReal += AdjustNeighbourhood( nReal, bTst );
2488 SwTwips nGrow = 0;
2489 if( 0 < nReal )
2491 SwFrm* pToGrow = GetUpper();
2492 // NEW TABLES
2493 // A cell with a row span of > 1 is allowed to grow the
2494 // line containing the end of the row span if it is
2495 // located in the same table frame:
2496 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
2497 if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2499 SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
2500 if ( -1 == rEndCell.GetTabBox()->getRowSpan() )
2501 pToGrow = rEndCell.GetUpper();
2502 else
2503 pToGrow = 0;
2506 nGrow = pToGrow ? pToGrow->Grow( nReal, bTst, bInfo ) : 0;
2509 if( NA_GROW_ADJUST == nAdjust && nGrow < nReal )
2510 nReal += AdjustNeighbourhood( nReal - nGrow, bTst );
2512 if ( IsFtnFrm() && (nGrow != nReal) && GetNext() )
2514 //Fussnoten koennen ihre Nachfolger verdraengen.
2515 SwTwips nSpace = bTst ? 0 : -nDist;
2516 const SwFrm *pFrm = GetUpper()->Lower();
2518 { nSpace += (pFrm->Frm().*fnRect->fnGetHeight)();
2519 pFrm = pFrm->GetNext();
2520 } while ( pFrm != GetNext() );
2521 nSpace = (GetUpper()->Prt().*fnRect->fnGetHeight)() -nSpace;
2522 if ( nSpace < 0 )
2523 nSpace = 0;
2524 nSpace += nGrow;
2525 if ( nReal > nSpace )
2526 nReal = nSpace;
2527 if ( nReal && !bTst )
2528 ((SwFtnFrm*)this)->InvalidateNxtFtnCnts( FindPageFrm() );
2530 else
2531 nReal = nGrow;
2534 else
2535 nReal = 0;
2537 nReal += nMin;
2539 else
2540 nReal = nDist;
2542 if ( !bTst )
2544 if( nReal != nDist &&
2545 // NEW TABLES
2546 ( !IsCellFrm() || static_cast<SwCellFrm*>(this)->GetLayoutRowSpan() > 1 ) )
2548 (Frm().*fnRect->fnSetHeight)( nFrmHeight + nReal );
2549 if( bChgPos )
2550 Frm().Pos().X() = nFrmPos - nReal;
2551 bMoveAccFrm = sal_True;
2554 if ( nReal )
2556 SwPageFrm *pPage = FindPageFrm();
2557 if ( GetNext() )
2559 GetNext()->_InvalidatePos();
2560 if ( GetNext()->IsCntntFrm() )
2561 GetNext()->InvalidatePage( pPage );
2563 if ( !IsPageBodyFrm() )
2565 _InvalidateAll();
2566 InvalidatePage( pPage );
2568 if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
2569 NotifyLowerObjs();
2571 if( IsCellFrm() )
2572 InvaPercentLowers( nReal );
2574 const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
2575 if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2576 SetCompletePaint();
2580 if( bMoveAccFrm && IsAccessibleFrm() )
2582 SwRootFrm *pRootFrm = FindRootFrm();
2583 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2584 pRootFrm->GetCurrShell() )
2586 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
2589 return nReal;
2592 /*************************************************************************
2594 |* SwLayoutFrm::ShrinkFrm()
2596 |* Ersterstellung MA 30. Jul. 92
2597 |* Letzte Aenderung MA 25. Mar. 99
2599 |*************************************************************************/
2600 SwTwips SwLayoutFrm::ShrinkFrm( SwTwips nDist, BOOL bTst, BOOL bInfo )
2602 const BOOL bBrowse = GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
2603 const USHORT nTmpType = bBrowse ? 0x2084: 0x2004; //Row+Cell, Browse mit Body
2604 if( !(GetType() & nTmpType) && HasFixSize() )
2605 return 0;
2607 ASSERT( nDist >= 0, "nDist < 0" );
2608 SWRECTFN( this )
2609 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)();
2610 if ( nDist > nFrmHeight )
2611 nDist = nFrmHeight;
2613 SwTwips nMin = 0;
2614 BOOL bChgPos = IsVertical() && !IsReverse();
2615 if ( Lower() )
2617 if( !Lower()->IsNeighbourFrm() )
2618 { const SwFrm *pFrm = Lower();
2619 const long nTmp = (Prt().*fnRect->fnGetHeight)();
2620 while( pFrm && nMin < nTmp )
2621 { nMin += (pFrm->Frm().*fnRect->fnGetHeight)();
2622 pFrm = pFrm->GetNext();
2626 SwTwips nReal = nDist;
2627 SwTwips nMinDiff = (Prt().*fnRect->fnGetHeight)() - nMin;
2628 if( nReal > nMinDiff )
2629 nReal = nMinDiff;
2630 if( nReal <= 0 )
2631 return nDist;
2633 SwRect aOldFrm( Frm() );
2634 sal_Bool bMoveAccFrm = sal_False;
2636 SwTwips nRealDist = nReal;
2637 if ( !bTst )
2639 (Frm().*fnRect->fnSetHeight)( nFrmHeight - nReal );
2640 if( bChgPos )
2641 Frm().Pos().X() += nReal;
2642 bMoveAccFrm = sal_True;
2645 BYTE nAdjust = GetUpper() && GetUpper()->IsFtnBossFrm() ?
2646 ((SwFtnBossFrm*)GetUpper())->NeighbourhoodAdjustment( this )
2647 : NA_GROW_SHRINK;
2649 // AdjustNeighbourhood auch in Spalten (aber nicht in Rahmen)
2650 if( NA_ONLY_ADJUST == nAdjust )
2652 if ( IsPageBodyFrm() && !bBrowse )
2653 nReal = nDist;
2654 else
2655 { nReal = AdjustNeighbourhood( -nReal, bTst );
2656 nReal *= -1;
2657 if ( !bTst && IsBodyFrm() && nReal < nRealDist )
2659 (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
2660 + nRealDist - nReal );
2661 if( bChgPos )
2662 Frm().Pos().X() += nRealDist - nReal;
2663 ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
2667 else if( IsColumnFrm() || IsColBodyFrm() )
2669 SwTwips nTmp = GetUpper()->Shrink( nReal, bTst, bInfo );
2670 if ( nTmp != nReal )
2672 (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)()
2673 + nReal - nTmp );
2674 if( bChgPos )
2675 Frm().Pos().X() += nTmp - nReal;
2676 ASSERT( !IsAccessibleFrm(), "bMoveAccFrm has to be set!" );
2677 nReal = nTmp;
2680 else
2682 SwTwips nShrink = nReal;
2683 SwFrm* pToShrink = GetUpper();
2684 const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
2685 // NEW TABLES
2686 if ( pThisCell && pThisCell->GetLayoutRowSpan() > 1 )
2688 SwCellFrm& rEndCell = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( false, true ));
2689 pToShrink = rEndCell.GetUpper();
2692 nReal = pToShrink ? pToShrink->Shrink( nShrink, bTst, bInfo ) : 0;
2693 if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
2694 && nReal < nShrink )
2695 AdjustNeighbourhood( nReal - nShrink );
2698 if( bMoveAccFrm && IsAccessibleFrm() )
2700 SwRootFrm *pRootFrm = FindRootFrm();
2701 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2702 pRootFrm->GetCurrShell() )
2704 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
2707 if ( !bTst && (IsCellFrm() || IsColumnFrm() ? nReal : nRealDist) )
2709 SwPageFrm *pPage = FindPageFrm();
2710 if ( GetNext() )
2712 GetNext()->_InvalidatePos();
2713 if ( GetNext()->IsCntntFrm() )
2714 GetNext()->InvalidatePage( pPage );
2715 if ( IsTabFrm() )
2716 ((SwTabFrm*)this)->SetComplete();
2718 else
2719 { if ( IsRetoucheFrm() )
2720 SetRetouche();
2721 if ( IsTabFrm() )
2723 if( IsTabFrm() )
2724 ((SwTabFrm*)this)->SetComplete();
2725 if ( Lower() ) //Kann auch im Join stehen und leer sein!
2726 InvalidateNextPos();
2729 if ( !IsBodyFrm() )
2731 _InvalidateAll();
2732 InvalidatePage( pPage );
2733 const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
2734 if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
2735 SetCompletePaint();
2738 if ( !(GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
2739 NotifyLowerObjs();
2741 if( IsCellFrm() )
2742 InvaPercentLowers( nReal );
2744 SwCntntFrm *pCnt;
2745 if( IsFtnFrm() && !((SwFtnFrm*)this)->GetAttr()->GetFtn().IsEndNote() &&
2746 ( GetFmt()->GetDoc()->GetFtnInfo().ePos != FTNPOS_CHAPTER ||
2747 ( IsInSct() && FindSctFrm()->IsFtnAtEnd() ) ) &&
2748 0 != (pCnt = ((SwFtnFrm*)this)->GetRefFromAttr() ) )
2750 if ( pCnt->IsFollow() )
2751 { // Wenn wir sowieso schon in einer anderen Spalte/Seite sitzen
2752 // als der Frame mit der Referenz, dann brauchen wir nicht
2753 // auch noch seinen Master zu invalidieren.
2754 SwFrm *pTmp = pCnt->FindFtnBossFrm(TRUE) == FindFtnBossFrm(TRUE)
2755 ? pCnt->FindMaster()->GetFrm() : pCnt;
2756 pTmp->Prepare( PREP_ADJUST_FRM );
2757 pTmp->InvalidateSize();
2759 else
2760 pCnt->InvalidatePos();
2763 return nReal;
2765 /*************************************************************************
2767 |* SwLayoutFrm::ChgLowersProp()
2769 |* Beschreibung Aendert die Grosse der direkt untergeordneten Frm's
2770 |* die eine Fixe Groesse haben, proportional zur Groessenaenderung der
2771 |* PrtArea des Frm's.
2772 |* Die Variablen Frm's werden auch proportional angepasst; sie werden
2773 |* sich schon wieder zurechtwachsen/-schrumpfen.
2774 |* Ersterstellung MA 11.03.92
2775 |* Letzte Aenderung AMA 2. Nov. 98
2777 |*************************************************************************/
2778 void SwLayoutFrm::ChgLowersProp( const Size& rOldSize )
2780 // no change of lower properties for root frame or if no lower exists.
2781 if ( IsRootFrm() || !Lower() )
2782 return;
2784 // declare and init <SwFrm* pLowerFrm> with first lower
2785 SwFrm *pLowerFrm = Lower();
2787 // declare and init const booleans <bHeightChgd> and <bWidthChg>
2788 const bool bHeightChgd = rOldSize.Height() != Prt().Height();
2789 const bool bWidthChgd = rOldSize.Width() != Prt().Width();
2791 // declare and init variables <bVert>, <bRev> and <fnRect>
2792 SWRECTFN( this )
2794 // This shortcut basically tries to handle only lower frames that
2795 // are affected by the size change. Otherwise much more lower frames
2796 // are invalidated.
2797 if ( !( bVert ? bHeightChgd : bWidthChgd ) &&
2798 ! Lower()->IsColumnFrm() &&
2799 ( ( IsBodyFrm() && IsInDocBody() && ( !IsInSct() || !FindSctFrm()->IsColLocked() ) ) ||
2800 // --> FME 2004-07-21 #i10826# Section frames without columns should not
2801 // invalidate all lowers!
2802 IsSctFrm() ) )
2803 // <--
2805 // Determine page frame the body frame resp. the section frame belongs to.
2806 SwPageFrm *pPage = FindPageFrm();
2807 // Determine last lower by traveling through them using <GetNext()>.
2808 // During travel check each section frame, if it will be sized to
2809 // maximum. If Yes, invalidate size of section frame and set
2810 // corresponding flags at the page.
2813 if( pLowerFrm->IsSctFrm() &&((SwSectionFrm*)pLowerFrm)->_ToMaximize() )
2815 pLowerFrm->_InvalidateSize();
2816 pLowerFrm->InvalidatePage( pPage );
2818 if( pLowerFrm->GetNext() )
2819 pLowerFrm = pLowerFrm->GetNext();
2820 else
2821 break;
2822 } while( TRUE );
2823 // If found last lower is a section frame containing no section
2824 // (section frame isn't valid and will be deleted in the future),
2825 // travel backwards.
2826 while( pLowerFrm->IsSctFrm() && !((SwSectionFrm*)pLowerFrm)->GetSection() &&
2827 pLowerFrm->GetPrev() )
2828 pLowerFrm = pLowerFrm->GetPrev();
2829 // If found last lower is a section frame, set <pLowerFrm> to its last
2830 // content, if the section frame is valid and is not sized to maximum.
2831 // Otherwise set <pLowerFrm> to NULL - In this case body frame only
2832 // contains invalid section frames.
2833 if( pLowerFrm->IsSctFrm() )
2834 pLowerFrm = ((SwSectionFrm*)pLowerFrm)->GetSection() &&
2835 !((SwSectionFrm*)pLowerFrm)->ToMaximize( FALSE ) ?
2836 ((SwSectionFrm*)pLowerFrm)->FindLastCntnt() : NULL;
2838 // continue with found last lower, probably the last content of a section
2839 if ( pLowerFrm )
2841 // If <pLowerFrm> is in a table frame, set <pLowerFrm> to this table
2842 // frame and continue.
2843 if ( pLowerFrm->IsInTab() )
2845 // OD 28.10.2002 #97265# - safeguard for setting <pLowerFrm> to
2846 // its table frame - check, if the table frame is also a lower
2847 // of the body frame, in order to assure that <pLowerFrm> is not
2848 // set to a frame, which is an *upper* of the body frame.
2849 SwFrm* pTableFrm = pLowerFrm->FindTabFrm();
2850 if ( IsAnLower( pTableFrm ) )
2852 pLowerFrm = pTableFrm;
2855 // Check, if variable size of body frame resp. section frame has grown
2856 // OD 28.10.2002 #97265# - correct check, if variable size has grown.
2857 SwTwips nOldHeight = bVert ? rOldSize.Width() : rOldSize.Height();
2858 if( nOldHeight < (Prt().*fnRect->fnGetHeight)() )
2860 // If variable size of body|section frame has grown, only found
2861 // last lower and the position of the its next have to be invalidated.
2862 pLowerFrm->_InvalidateAll();
2863 pLowerFrm->InvalidatePage( pPage );
2864 if( !pLowerFrm->IsFlowFrm() ||
2865 !SwFlowFrm::CastFlowFrm( pLowerFrm )->HasFollow() )
2866 pLowerFrm->InvalidateNextPos( TRUE );
2867 if ( pLowerFrm->IsTxtFrm() )
2868 ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2870 else
2872 // variable size of body|section frame has shrinked. Thus,
2873 // invalidate all lowers not matching the new body|section size
2874 // and the dedicated new last lower.
2875 if( bVert )
2877 SwTwips nBot = Frm().Left() + Prt().Left();
2878 while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Left() < nBot )
2880 pLowerFrm->_InvalidateAll();
2881 pLowerFrm->InvalidatePage( pPage );
2882 pLowerFrm = pLowerFrm->GetPrev();
2885 else
2887 SwTwips nBot = Frm().Top() + Prt().Bottom();
2888 while ( pLowerFrm->GetPrev() && pLowerFrm->Frm().Top() > nBot )
2890 pLowerFrm->_InvalidateAll();
2891 pLowerFrm->InvalidatePage( pPage );
2892 pLowerFrm = pLowerFrm->GetPrev();
2895 if ( pLowerFrm )
2897 pLowerFrm->_InvalidateSize();
2898 pLowerFrm->InvalidatePage( pPage );
2899 if ( pLowerFrm->IsTxtFrm() )
2900 ((SwCntntFrm*)pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2903 // --> OD 2005-01-31 #i41694# - improvement by removing duplicates
2904 if ( pLowerFrm )
2906 if ( pLowerFrm->IsInSct() )
2908 // --> OD 2005-01-31 #i41694# - follow-up of issue #i10826#:
2909 // No invalidation of section frame, if it's the this.
2910 SwFrm* pSectFrm = pLowerFrm->FindSctFrm();
2911 if( pSectFrm != this && IsAnLower( pSectFrm ) )
2913 pSectFrm->_InvalidateSize();
2914 pSectFrm->InvalidatePage( pPage );
2916 // <--
2919 // <--
2921 return;
2922 } // end of { special case }
2925 // Invalidate page for content only once.
2926 bool bInvaPageForCntnt = true;
2928 // Declare booleans <bFixChgd> and <bVarChgd>, indicating for text frame
2929 // adjustment, if fixed/variable size has changed.
2930 bool bFixChgd, bVarChgd;
2931 if( bVert == pLowerFrm->IsNeighbourFrm() )
2933 bFixChgd = bWidthChgd;
2934 bVarChgd = bHeightChgd;
2936 else
2938 bFixChgd = bHeightChgd;
2939 bVarChgd = bWidthChgd;
2942 // Declare const unsigned short <nFixWidth> and init it this frame types
2943 // which has fixed width in vertical respectively horizontal layout.
2944 // In vertical layout these are neighbour frames (cell and column frames),
2945 // header frames and footer frames.
2946 // In horizontal layout these are all frames, which aren't neighbour frames.
2947 const USHORT nFixWidth = bVert ? (FRM_NEIGHBOUR | FRM_HEADFOOT)
2948 : ~FRM_NEIGHBOUR;
2950 // Declare const unsigned short <nFixHeight> and init it this frame types
2951 // which has fixed height in vertical respectively horizontal layout.
2952 // In vertical layout these are all frames, which aren't neighbour frames,
2953 // header frames, footer frames, body frames or foot note container frames.
2954 // In horizontal layout these are neighbour frames.
2955 const USHORT nFixHeight= bVert ? ~(FRM_NEIGHBOUR | FRM_HEADFOOT | FRM_BODYFTNC)
2956 : FRM_NEIGHBOUR;
2958 // Travel through all lowers using <GetNext()>
2959 while ( pLowerFrm )
2961 if ( pLowerFrm->IsTxtFrm() )
2963 // Text frames will only be invalidated - prepare invalidation
2964 if ( bFixChgd )
2965 static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_FIXSIZE_CHG );
2966 if ( bVarChgd )
2967 static_cast<SwCntntFrm*>(pLowerFrm)->Prepare( PREP_ADJUST_FRM );
2969 else
2971 // If lower isn't a table, row, cell or section frame, adjust its
2972 // frame size.
2973 const USHORT nLowerType = pLowerFrm->GetType();
2974 if ( !(nLowerType & (FRM_TAB|FRM_ROW|FRM_CELL|FRM_SECTION)) )
2976 if ( bWidthChgd )
2978 if( nLowerType & nFixWidth )
2980 // Considering previous conditions:
2981 // In vertical layout set width of column, header and
2982 // footer frames to its upper width.
2983 // In horizontal layout set width of header, footer,
2984 // foot note container, foot note, body and no-text
2985 // frames to its upper width.
2986 pLowerFrm->Frm().Width( Prt().Width() );
2988 else if( rOldSize.Width() && !pLowerFrm->IsFtnFrm() )
2990 // Adjust frame width proportional, if lower isn't a
2991 // foot note frame and condition <nLowerType & nFixWidth>
2992 // isn't true.
2993 // Considering previous conditions:
2994 // In vertical layout these are foot note container,
2995 // body and no-text frames.
2996 // In horizontal layout these are column and no-text frames.
2997 // OD 24.10.2002 #97265# - <double> calculation
2998 // Perform <double> calculation of new width, if
2999 // one of the coefficients is greater than 50000
3000 SwTwips nNewWidth;
3001 if ( (pLowerFrm->Frm().Width() > 50000) ||
3002 (Prt().Width() > 50000) )
3004 double nNewWidthTmp =
3005 ( double(pLowerFrm->Frm().Width())
3006 * double(Prt().Width()) )
3007 / double(rOldSize.Width());
3008 nNewWidth = SwTwips(nNewWidthTmp);
3010 else
3012 nNewWidth =
3013 (pLowerFrm->Frm().Width() * Prt().Width()) / rOldSize.Width();
3015 pLowerFrm->Frm().Width( nNewWidth );
3018 if ( bHeightChgd )
3020 if( nLowerType & nFixHeight )
3022 // Considering previous conditions:
3023 // In vertical layout set height of foot note and
3024 // no-text frames to its upper height.
3025 // In horizontal layout set height of column frames
3026 // to its upper height.
3027 pLowerFrm->Frm().Height( Prt().Height() );
3029 // OD 01.10.2002 #102211#
3030 // add conditions <!pLowerFrm->IsHeaderFrm()> and
3031 // <!pLowerFrm->IsFooterFrm()> in order to avoid that
3032 // the <Grow> of header or footer are overwritten.
3033 // NOTE: Height of header/footer frame is determined by contents.
3034 else if ( rOldSize.Height() &&
3035 !pLowerFrm->IsFtnFrm() &&
3036 !pLowerFrm->IsHeaderFrm() &&
3037 !pLowerFrm->IsFooterFrm()
3040 // Adjust frame height proportional, if lower isn't a
3041 // foot note, a header or a footer frame and
3042 // condition <nLowerType & nFixHeight> isn't true.
3043 // Considering previous conditions:
3044 // In vertical layout these are column, foot note container,
3045 // body and no-text frames.
3046 // In horizontal layout these are column, foot note
3047 // container, body and no-text frames.
3049 // OD 29.10.2002 #97265# - special case for page lowers
3050 // The page lowers that have to be adjusted on page height
3051 // change are the body frame and the foot note container
3052 // frame.
3053 // In vertical layout the height of both is directly
3054 // adjusted to the page height change.
3055 // In horizontal layout the height of the body frame is
3056 // directly adjsuted to the page height change and the
3057 // foot note frame height isn't touched, because its
3058 // determined by its content.
3059 // OD 31.03.2003 #108446# - apply special case for page
3060 // lowers - see description above - also for section columns.
3061 if ( IsPageFrm() ||
3062 ( IsColumnFrm() && IsInSct() )
3065 ASSERT( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm(),
3066 "ChgLowersProp - only for body or foot note container" );
3067 if ( pLowerFrm->IsBodyFrm() || pLowerFrm->IsFtnContFrm() )
3069 if ( IsVertical() || pLowerFrm->IsBodyFrm() )
3071 SwTwips nNewHeight =
3072 pLowerFrm->Frm().Height() +
3073 ( Prt().Height() - rOldSize.Height() );
3074 if ( nNewHeight < 0)
3076 // OD 01.04.2003 #108446# - adjust assertion condition and text
3077 ASSERT( !( IsPageFrm() &&
3078 (pLowerFrm->Frm().Height()>0) &&
3079 (pLowerFrm->IsValid()) ),
3080 "ChgLowersProg - negative height for lower.");
3081 nNewHeight = 0;
3083 pLowerFrm->Frm().Height( nNewHeight );
3087 else
3089 SwTwips nNewHeight;
3090 // OD 24.10.2002 #97265# - <double> calculation
3091 // Perform <double> calculation of new height, if
3092 // one of the coefficients is greater than 50000
3093 if ( (pLowerFrm->Frm().Height() > 50000) ||
3094 (Prt().Height() > 50000) )
3096 double nNewHeightTmp =
3097 ( double(pLowerFrm->Frm().Height())
3098 * double(Prt().Height()) )
3099 / double(rOldSize.Height());
3100 nNewHeight = SwTwips(nNewHeightTmp);
3102 else
3104 nNewHeight = ( pLowerFrm->Frm().Height()
3105 * Prt().Height() ) / rOldSize.Height();
3107 if( !pLowerFrm->GetNext() )
3109 SwTwips nSum = Prt().Height();
3110 SwFrm* pTmp = Lower();
3111 while( pTmp->GetNext() )
3113 if( !pTmp->IsFtnContFrm() || !pTmp->IsVertical() )
3114 nSum -= pTmp->Frm().Height();
3115 pTmp = pTmp->GetNext();
3117 if( nSum - nNewHeight == 1 &&
3118 nSum == pLowerFrm->Frm().Height() )
3119 nNewHeight = nSum;
3121 pLowerFrm->Frm().Height( nNewHeight );
3126 } // end of else { NOT text frame }
3128 pLowerFrm->_InvalidateAll();
3129 if ( bInvaPageForCntnt && pLowerFrm->IsCntntFrm() )
3131 pLowerFrm->InvalidatePage();
3132 bInvaPageForCntnt = false;
3135 if ( !pLowerFrm->GetNext() && pLowerFrm->IsRetoucheFrm() )
3137 //Wenn ein Wachstum stattgefunden hat, und die untergeordneten
3138 //zur Retouche faehig sind (derzeit Tab, Section und Cntnt), so
3139 //trigger ich sie an.
3140 if ( rOldSize.Height() < Prt().SSize().Height() ||
3141 rOldSize.Width() < Prt().SSize().Width() )
3142 pLowerFrm->SetRetouche();
3144 pLowerFrm = pLowerFrm->GetNext();
3147 // Finally adjust the columns if width is set to auto
3148 // Possible optimisation: execute this code earlier in this function and
3149 // return???
3150 if ( ( bVert && bHeightChgd || ! bVert && bWidthChgd ) &&
3151 Lower()->IsColumnFrm() )
3153 // get column attribute
3154 const SwFmtCol* pColAttr = NULL;
3155 if ( IsPageBodyFrm() )
3157 ASSERT( GetUpper()->IsPageFrm(), "Upper is not page frame" )
3158 pColAttr = &GetUpper()->GetFmt()->GetCol();
3160 else
3162 ASSERT( IsFlyFrm() || IsSctFrm(), "Columns not in fly or section" )
3163 pColAttr = &GetFmt()->GetCol();
3166 if ( pColAttr->IsOrtho() && pColAttr->GetNumCols() > 1 )
3167 AdjustColumns( pColAttr, sal_False );
3171 /*************************************************************************
3173 |* SwLayoutFrm::Format()
3175 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea.
3176 |* Die Fixsize wird hier nicht eingestellt.
3177 |* Ersterstellung MA 28. Jul. 92
3178 |* Letzte Aenderung MA 21. Mar. 95
3180 |*************************************************************************/
3181 void SwLayoutFrm::Format( const SwBorderAttrs *pAttrs )
3183 ASSERT( pAttrs, "LayoutFrm::Format, pAttrs ist 0." );
3185 if ( bValidPrtArea && bValidSize )
3186 return;
3188 const USHORT nLeft = (USHORT)pAttrs->CalcLeft( this );
3189 const USHORT nUpper = pAttrs->CalcTop();
3191 const USHORT nRight = (USHORT)((SwBorderAttrs*)pAttrs)->CalcRight( this );
3192 const USHORT nLower = pAttrs->CalcBottom();
3193 BOOL bVert = IsVertical() && !IsPageFrm();
3194 SwRectFn fnRect = bVert ? fnRectVert : fnRectHori;
3195 if ( !bValidPrtArea )
3197 bValidPrtArea = TRUE;
3198 (this->*fnRect->fnSetXMargins)( nLeft, nRight );
3199 (this->*fnRect->fnSetYMargins)( nUpper, nLower );
3202 if ( !bValidSize )
3204 if ( !HasFixSize() )
3206 const SwTwips nBorder = nUpper + nLower;
3207 const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
3208 SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ? rSz.GetHeight() : 0;
3210 { bValidSize = TRUE;
3212 //Die Groesse in der VarSize wird durch den Inhalt plus den
3213 //Raendern bestimmt.
3214 SwTwips nRemaining = 0;
3215 SwFrm *pFrm = Lower();
3216 while ( pFrm )
3217 { nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
3218 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() )
3219 // Dieser TxtFrm waere gern ein bisschen groesser
3220 nRemaining += ((SwTxtFrm*)pFrm)->GetParHeight()
3221 - (pFrm->Prt().*fnRect->fnGetHeight)();
3222 else if( pFrm->IsSctFrm() && ((SwSectionFrm*)pFrm)->IsUndersized() )
3223 nRemaining += ((SwSectionFrm*)pFrm)->Undersize();
3224 pFrm = pFrm->GetNext();
3226 nRemaining += nBorder;
3227 nRemaining = Max( nRemaining, nMinHeight );
3228 const SwTwips nDiff = nRemaining-(Frm().*fnRect->fnGetHeight)();
3229 const long nOldLeft = (Frm().*fnRect->fnGetLeft)();
3230 const long nOldTop = (Frm().*fnRect->fnGetTop)();
3231 if ( nDiff )
3233 if ( nDiff > 0 )
3234 Grow( nDiff );
3235 else
3236 Shrink( -nDiff );
3237 //Schnell auf dem kurzen Dienstweg die Position updaten.
3238 MakePos();
3240 //Unterkante des Uppers nicht ueberschreiten.
3241 if ( GetUpper() && (Frm().*fnRect->fnGetHeight)() )
3243 const SwTwips nLimit = (GetUpper()->*fnRect->fnGetPrtBottom)();
3244 if( (this->*fnRect->fnSetLimit)( nLimit ) &&
3245 nOldLeft == (Frm().*fnRect->fnGetLeft)() &&
3246 nOldTop == (Frm().*fnRect->fnGetTop)() )
3247 bValidSize = bValidPrtArea = TRUE;
3249 } while ( !bValidSize );
3251 else if ( GetType() & 0x0018 )
3254 { if ( Frm().Height() != pAttrs->GetSize().Height() )
3255 ChgSize( Size( Frm().Width(), pAttrs->GetSize().Height()));
3256 bValidSize = TRUE;
3257 MakePos();
3258 } while ( !bValidSize );
3260 else
3261 bValidSize = TRUE;
3265 /*************************************************************************
3267 |* SwLayoutFrm::InvalidatePercentLowers()
3269 |* Ersterstellung MA 13. Jun. 96
3270 |* Letzte Aenderung MA 13. Jun. 96
3272 |*************************************************************************/
3273 static void InvaPercentFlys( SwFrm *pFrm, SwTwips nDiff )
3275 ASSERT( pFrm->GetDrawObjs(), "Can't find any Objects" );
3276 for ( USHORT i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
3278 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
3279 if ( pAnchoredObj->ISA(SwFlyFrm) )
3281 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3282 const SwFmtFrmSize &rSz = pFly->GetFmt()->GetFrmSize();
3283 if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3285 BOOL bNotify = TRUE;
3286 // If we've a fly with more than 90% relative height...
3287 if( rSz.GetHeightPercent() > 90 && pFly->GetAnchorFrm() &&
3288 rSz.GetHeightPercent() != 0xFF && nDiff )
3290 const SwFrm *pRel = pFly->IsFlyLayFrm() ? pFly->GetAnchorFrm():
3291 pFly->GetAnchorFrm()->GetUpper();
3292 // ... and we have already more than 90% height and we
3293 // not allow the text to go through...
3294 // then a notifycation could cause an endless loop, e.g.
3295 // 100% height and no text wrap inside a cell of a table.
3296 if( pFly->Frm().Height()*10 >
3297 ( nDiff + pRel->Prt().Height() )*9 &&
3298 pFly->GetFmt()->GetSurround().GetSurround() !=
3299 SURROUND_THROUGHT )
3300 bNotify = FALSE;
3302 if( bNotify )
3303 pFly->InvalidateSize();
3309 void SwLayoutFrm::InvaPercentLowers( SwTwips nDiff )
3311 if ( GetDrawObjs() )
3312 ::InvaPercentFlys( this, nDiff );
3314 SwFrm *pFrm = ContainsCntnt();
3315 if ( pFrm )
3318 if ( pFrm->IsInTab() && !IsTabFrm() )
3320 SwFrm *pTmp = pFrm->FindTabFrm();
3321 ASSERT( pTmp, "Where's my TabFrm?" );
3322 if( IsAnLower( pTmp ) )
3323 pFrm = pTmp;
3326 if ( pFrm->IsTabFrm() )
3328 const SwFmtFrmSize &rSz = ((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize();
3329 if ( rSz.GetWidthPercent() || rSz.GetHeightPercent() )
3330 pFrm->InvalidatePrt();
3332 else if ( pFrm->GetDrawObjs() )
3333 ::InvaPercentFlys( pFrm, nDiff );
3334 pFrm = pFrm->FindNextCnt();
3335 } while ( pFrm && IsAnLower( pFrm ) ) ;
3338 /*************************************************************************
3340 |* SwLayoutFrm::CalcRel()
3342 |* Ersterstellung MA 13. Jun. 96
3343 |* Letzte Aenderung MA 10. Oct. 96
3345 |*************************************************************************/
3346 long SwLayoutFrm::CalcRel( const SwFmtFrmSize &rSz, BOOL ) const
3348 long nRet = rSz.GetWidth(),
3349 nPercent = rSz.GetWidthPercent();
3351 if ( nPercent )
3353 const SwFrm *pRel = GetUpper();
3354 long nRel = LONG_MAX;
3355 const ViewShell *pSh = GetShell();
3356 if ( pRel->IsPageBodyFrm() &&
3357 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
3358 pSh && pSh->VisArea().Width())
3360 nRel = pSh->GetBrowseWidth();
3361 long nDiff = nRel - pRel->Prt().Width();
3362 if ( nDiff > 0 )
3363 nRel -= nDiff;
3365 nRel = Min( nRel, pRel->Prt().Width() );
3366 nRet = nRel * nPercent / 100;
3368 return nRet;
3371 /*************************************************************************
3372 |* Local helpers for SwLayoutFrm::FormatWidthCols()
3373 |*************************************************************************/
3374 long MA_FASTCALL lcl_CalcMinColDiff( SwLayoutFrm *pLayFrm )
3376 long nDiff = 0, nFirstDiff = 0;
3377 SwLayoutFrm *pCol = (SwLayoutFrm*)pLayFrm->Lower();
3378 ASSERT( pCol, "Where's the columnframe?" );
3379 SwFrm *pFrm = pCol->Lower();
3382 if( pFrm && pFrm->IsBodyFrm() )
3383 pFrm = ((SwBodyFrm*)pFrm)->Lower();
3384 if ( pFrm && pFrm->IsTxtFrm() )
3386 const long nTmp = ((SwTxtFrm*)pFrm)->FirstLineHeight();
3387 if ( nTmp != USHRT_MAX )
3389 if ( pCol == pLayFrm->Lower() )
3390 nFirstDiff = nTmp;
3391 else
3392 nDiff = nDiff ? Min( nDiff, nTmp ) : nTmp;
3395 //Leere Spalten ueberspringen!
3396 pCol = (SwLayoutFrm*)pCol->GetNext();
3397 while ( pCol && 0 == (pFrm = pCol->Lower()) )
3398 pCol = (SwLayoutFrm*)pCol->GetNext();
3400 } while ( pFrm && pCol );
3402 return nDiff ? nDiff : nFirstDiff ? nFirstDiff : 240;
3405 BOOL lcl_IsFlyHeightClipped( SwLayoutFrm *pLay )
3407 SwFrm *pFrm = pLay->ContainsCntnt();
3408 while ( pFrm )
3410 if ( pFrm->IsInTab() )
3411 pFrm = pFrm->FindTabFrm();
3413 if ( pFrm->GetDrawObjs() )
3415 sal_uInt32 nCnt = pFrm->GetDrawObjs()->Count();
3416 for ( USHORT i = 0; i < nCnt; ++i )
3418 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
3419 if ( pAnchoredObj->ISA(SwFlyFrm) )
3421 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3422 if ( pFly->IsHeightClipped() &&
3423 ( !pFly->IsFlyFreeFrm() || pFly->GetPageFrm() ) )
3424 return TRUE;
3428 pFrm = pFrm->FindNextCnt();
3430 return FALSE;
3433 /*************************************************************************
3434 |* SwLayoutFrm::FormatWidthCols()
3435 |*************************************************************************/
3436 void SwLayoutFrm::FormatWidthCols( const SwBorderAttrs &rAttrs,
3437 const SwTwips nBorder, const SwTwips nMinHeight )
3439 //Wenn Spalten im Spiel sind, so wird die Groesse an der
3440 //letzten Spalte ausgerichtet.
3441 //1. Inhalt formatieren.
3442 //2. Hoehe der letzten Spalte ermitteln, wenn diese zu
3443 // zu gross ist muss der Fly wachsen.
3444 // Der Betrag um den der Fly waechst ist aber nicht etwa
3445 // der Betrag des Ueberhangs, denn wir muessen davon
3446 // ausgehen, dass etwas Masse zurueckfliesst und so
3447 // zusaetzlicher Platz geschaffen wird.
3448 // Im Ersten Ansatz ist der Betrag um den gewachsen wird
3449 // der Ueberhang geteilt durch die Spaltenanzahl oder
3450 // der Ueberhang selbst wenn er kleiner als die Spalten-
3451 // anzahl ist.
3452 //3. Weiter mit 1. bis zur Stabilitaet.
3454 const SwFmtCol &rCol = rAttrs.GetAttrSet().GetCol();
3455 const USHORT nNumCols = rCol.GetNumCols();
3457 BOOL bEnd = FALSE;
3458 BOOL bBackLock = FALSE;
3459 SwViewImp *pImp = GetShell() ? GetShell()->Imp() : 0;
3461 // Zugrunde liegender Algorithmus
3462 // Es wird versucht, eine optimale Hoehe fuer die Spalten zu finden.
3463 // nMinimum beginnt mit der uebergebenen Mindesthoehe und wird dann als
3464 // Maximum der Hoehen gepflegt, bei denen noch Spalteninhalt aus einer
3465 // Spalte herausragt.
3466 // nMaximum beginnt bei LONG_MAX und wird als Minimum der Hoehen gepflegt,
3467 // bei denen der Inhalt gepasst hat.
3468 // Bei spaltigen Bereichen beginnt nMaximum bei dem maximalen Wert, den
3469 // die Umgebung vorgibt, dies kann natuerlich ein Wert sein, bei dem noch
3470 // Inhalt heraushaengt.
3471 // Es werden die Spalten formatiert, wenn Inhalt heraushaengt, wird nMinimum
3472 // ggf. angepasst, dann wird gewachsen, mindestens um nMinDiff, aber nicht ueber
3473 // ein groesseres nMaximum hinaus. Wenn kein Inhalt heraushaengt, sondern
3474 // noch Luft in einer Spalte ist, schrumpfen wir entsprechend, mindestens um
3475 // nMinDiff, aber nicht unter das nMinimum.
3476 // Abgebrochen wird, wenn kein Inhalt mehr heraushaengt und das Minimum sich auf
3477 // weniger als ein MinDiff dem Maximum angenaehert hat oder das von der
3478 // Umgebung vorgegebene Maximum erreicht ist und trotzdem Inhalt heraus-
3479 // haengt.
3481 // Kritik an der Implementation
3482 // 1. Es kann theoretisch Situationen geben, in denen der Inhalt in einer geringeren
3483 // Hoehe passt und in einer groesseren Hoehe nicht passt. Damit der Code robust
3484 // gegen solche Verhaeltnisse ist, sind ein paar Abfragen bezgl. Minimum und Maximum
3485 // drin, die wahrscheinlich niemals zuschlagen koennen.
3486 // 2. Es wird fuer das Schrumpfen das gleiche nMinDiff benutzt wie fuer das Wachstum,
3487 // das nMinDiff ist allerdings mehr oder weniger die kleinste erste Zeilenhoehe und
3488 // als Mindestwert fuer das Schrumpfen nicht unbedingt optimal.
3490 long nMinimum = nMinHeight;
3491 long nMaximum;
3492 BOOL bNoBalance = FALSE;
3493 SWRECTFN( this )
3494 if( IsSctFrm() )
3496 nMaximum = (Frm().*fnRect->fnGetHeight)() - nBorder +
3497 (Frm().*fnRect->fnBottomDist)(
3498 (GetUpper()->*fnRect->fnGetPrtBottom)() );
3499 nMaximum += GetUpper()->Grow( LONG_MAX, TRUE );
3500 if( nMaximum < nMinimum )
3502 if( nMaximum < 0 )
3503 nMinimum = nMaximum = 0;
3504 else
3505 nMinimum = nMaximum;
3507 if( nMaximum > BROWSE_HEIGHT )
3508 nMaximum = BROWSE_HEIGHT;
3510 bNoBalance = ((SwSectionFrm*)this)->GetSection()->GetFmt()->
3511 GetBalancedColumns().GetValue();
3512 SwFrm* pAny = ContainsAny();
3513 if( bNoBalance ||
3514 ( !(Frm().*fnRect->fnGetHeight)() && pAny ) )
3516 long nTop = (this->*fnRect->fnGetTopMargin)();
3517 // --> OD 2004-11-01 #i23129# - correction: enlarge section
3518 // to the calculated maximum height.
3519 (Frm().*fnRect->fnAddBottom)( nMaximum -
3520 (Frm().*fnRect->fnGetHeight)() );
3521 // <--
3522 if( nTop > nMaximum )
3523 nTop = nMaximum;
3524 (this->*fnRect->fnSetYMargins)( nTop, 0 );
3526 if( !pAny && !((SwSectionFrm*)this)->IsFtnLock() )
3528 SwFtnContFrm* pFtnCont = ((SwSectionFrm*)this)->ContainsFtnCont();
3529 if( pFtnCont )
3531 SwFrm* pFtnAny = pFtnCont->ContainsAny();
3532 if( pFtnAny && pFtnAny->IsValid() )
3534 bBackLock = TRUE;
3535 ((SwSectionFrm*)this)->SetFtnLock( TRUE );
3540 else
3541 nMaximum = LONG_MAX;
3543 // --> OD 2004-08-25 #i3317# - reset temporarly consideration
3544 // of wrapping style influence
3545 SwPageFrm* pPageFrm = FindPageFrm();
3546 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L;
3547 if ( pObjs )
3549 sal_uInt32 i = 0;
3550 for ( i = 0; i < pObjs->Count(); ++i )
3552 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
3554 if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
3556 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3560 // <--
3563 //Kann eine Weile dauern, deshalb hier auf Waitcrsr pruefen.
3564 if ( pImp )
3565 pImp->CheckWaitCrsr();
3567 bValidSize = TRUE;
3568 //Erstmal die Spalten formatieren, das entlastet den
3569 //Stack ein wenig.
3570 //Bei der Gelegenheit stellen wir auch gleich mal die
3571 //Breiten und Hoehen der Spalten ein (so sie denn falsch sind).
3572 SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
3574 // --> FME 2004-07-19 #i27399#
3575 // Simply setting the column width based on the values returned by
3576 // CalcColWidth does not work for automatic column width.
3577 AdjustColumns( &rCol, sal_False );
3578 // <--
3580 for ( USHORT i = 0; i < nNumCols; ++i )
3582 pCol->Calc();
3583 // ColumnFrms besitzen jetzt einen BodyFrm, der auch kalkuliert werden will
3584 pCol->Lower()->Calc();
3585 if( pCol->Lower()->GetNext() )
3586 pCol->Lower()->GetNext()->Calc(); // SwFtnCont
3587 pCol = (SwLayoutFrm*)pCol->GetNext();
3590 ::CalcCntnt( this );
3592 pCol = (SwLayoutFrm*)Lower();
3593 ASSERT( pCol && pCol->GetNext(), ":-( Spalten auf Urlaub?");
3594 // bMinDiff wird gesetzt, wenn es keine leere Spalte gibt
3595 BOOL bMinDiff = TRUE;
3596 // OD 28.03.2003 #108446# - check for all column content and all columns
3597 while ( bMinDiff && pCol )
3599 bMinDiff = 0 != pCol->ContainsCntnt();
3600 pCol = (SwLayoutFrm*)pCol->GetNext();
3602 pCol = (SwLayoutFrm*)Lower();
3603 // OD 28.03.2003 #108446# - initialize local variable
3604 SwFrm *pLow = NULL;
3605 SwTwips nDiff = 0;
3606 SwTwips nMaxFree = 0;
3607 SwTwips nAllFree = LONG_MAX;
3608 // bFoundLower wird gesetzt, wenn es mind. eine nichtleere Spalte gibt
3609 BOOL bFoundLower = FALSE;
3610 while( pCol )
3612 SwLayoutFrm* pLay = (SwLayoutFrm*)pCol->Lower();
3613 SwTwips nInnerHeight = (pLay->Frm().*fnRect->fnGetHeight)() -
3614 (pLay->Prt().*fnRect->fnGetHeight)();
3615 if( pLay->Lower() )
3617 bFoundLower = TRUE;
3618 nInnerHeight += pLay->InnerHeight();
3620 else if( nInnerHeight < 0 )
3621 nInnerHeight = 0;
3623 if( pLay->GetNext() )
3625 bFoundLower = TRUE;
3626 pLay = (SwLayoutFrm*)pLay->GetNext();
3627 ASSERT( pLay->IsFtnContFrm(),"FtnContainer exspected" );
3628 nInnerHeight += pLay->InnerHeight();
3629 nInnerHeight += (pLay->Frm().*fnRect->fnGetHeight)() -
3630 (pLay->Prt().*fnRect->fnGetHeight)();
3632 nInnerHeight -= (pCol->Prt().*fnRect->fnGetHeight)();
3633 if( nInnerHeight > nDiff )
3635 nDiff = nInnerHeight;
3636 nAllFree = 0;
3638 else
3640 if( nMaxFree < -nInnerHeight )
3641 nMaxFree = -nInnerHeight;
3642 if( nAllFree > -nInnerHeight )
3643 nAllFree = -nInnerHeight;
3645 pCol = (SwLayoutFrm*)pCol->GetNext();
3648 if ( bFoundLower || ( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() ) )
3650 SwTwips nMinDiff = ::lcl_CalcMinColDiff( this );
3651 // Hier wird entschieden, ob wir wachsen muessen, naemlich wenn
3652 // ein Spalteninhalt (nDiff) oder ein Fly herausragt.
3653 // Bei spaltigen Bereichen wird beruecksichtigt, dass mit dem
3654 // Besitz eines nichtleeren Follows die Groesse festgelegt ist.
3655 if ( nDiff || ::lcl_IsFlyHeightClipped( this ) ||
3656 ( IsSctFrm() && ((SwSectionFrm*)this)->CalcMinDiff( nMinDiff ) ) )
3658 long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
3659 // Das Minimum darf nicht kleiner sein als unsere PrtHeight,
3660 // solange noch etwas herausragt.
3661 if( nMinimum < nPrtHeight )
3662 nMinimum = nPrtHeight;
3663 // Es muss sichergestellt sein, dass das Maximum nicht kleiner
3664 // als die PrtHeight ist, wenn noch etwas herausragt
3665 if( nMaximum < nPrtHeight )
3666 nMaximum = nPrtHeight; // Robust, aber kann das ueberhaupt eintreten?
3667 if( !nDiff ) // wenn nur Flys herausragen, wachsen wir um nMinDiff
3668 nDiff = nMinDiff;
3669 // Wenn wir um mehr als nMinDiff wachsen wollen, wird dies auf die
3670 // Spalten verteilt
3671 if ( Abs(nDiff - nMinDiff) > nNumCols && nDiff > (long)nNumCols )
3672 nDiff /= nNumCols;
3674 if ( bMinDiff )
3675 { // Wenn es keinen leeren Spalten gibt, wollen wir mind. um nMinDiff
3676 // wachsen. Sonderfall: Wenn wir kleiner als die minimale Frmhoehe
3677 // sind und die PrtHeight kleiner als nMinDiff ist, wachsen wir so,
3678 // dass die PrtHeight hinterher genau nMinDiff ist.
3679 long nFrmHeight = (Frm().*fnRect->fnGetHeight)();
3680 if ( nFrmHeight > nMinHeight || nPrtHeight >= nMinDiff )
3681 nDiff = Max( nDiff, nMinDiff );
3682 else if( nDiff < nMinDiff )
3683 nDiff = nMinDiff - nPrtHeight + 1;
3685 // nMaximum ist eine Groesse, in der der Inhalt gepasst hat,
3686 // oder der von der Umgebung vorgegebene Wert, deshalb
3687 // brauchen wir nicht ueber diesen Wrt hinauswachsen.
3688 if( nDiff + nPrtHeight > nMaximum )
3689 nDiff = nMaximum - nPrtHeight;
3691 else if( nMaximum > nMinimum ) // Wir passen, haben wir auch noch Spielraum?
3693 long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
3694 if ( nMaximum < nPrtHeight )
3695 nDiff = nMaximum - nPrtHeight; // wir sind ueber eine funktionierende
3696 // Hoehe hinausgewachsen und schrumpfen wieder auf diese zurueck,
3697 // aber kann das ueberhaupt eintreten?
3698 else
3699 { // Wir haben ein neues Maximum, eine Groesse, fuer die der Inhalt passt.
3700 nMaximum = nPrtHeight;
3701 // Wenn der Freiraum in den Spalten groesser ist als nMinDiff und wir
3702 // nicht dadurch wieder unter das Minimum rutschen, wollen wir ein wenig
3703 // Luft herauslassen.
3704 if ( !bNoBalance &&
3705 // --> OD 2004-11-04 #i23129# - <nMinDiff> can be
3706 // big, because of an object at the beginning of
3707 // a column. Thus, decrease optimization here.
3708 //nMaxFree >= nMinDiff &&
3709 nMaxFree > 0 &&
3710 // <--
3711 ( !nAllFree ||
3712 nMinimum < nPrtHeight - nMinDiff ) )
3714 nMaxFree /= nNumCols; // auf die Spalten verteilen
3715 nDiff = nMaxFree < nMinDiff ? -nMinDiff : -nMaxFree; // mind. nMinDiff
3716 if( nPrtHeight + nDiff <= nMinimum ) // Unter das Minimum?
3717 nDiff = ( nMinimum - nMaximum ) / 2; // dann lieber die Mitte
3719 else if( nAllFree )
3721 nDiff = -nAllFree;
3722 if( nPrtHeight + nDiff <= nMinimum ) // Less than minimum?
3723 nDiff = ( nMinimum - nMaximum ) / 2; // Take the center
3727 if( nDiff ) // jetzt wird geschrumpft oder gewachsen..
3729 Size aOldSz( Prt().SSize() );
3730 long nTop = (this->*fnRect->fnGetTopMargin)();
3731 nDiff = (Prt().*fnRect->fnGetHeight)() + nDiff + nBorder -
3732 (Frm().*fnRect->fnGetHeight)();
3733 (Frm().*fnRect->fnAddBottom)( nDiff );
3734 // --> OD 2006-08-16 #i68520#
3735 if ( dynamic_cast<SwFlyFrm*>(this) )
3737 dynamic_cast<SwFlyFrm*>(this)->InvalidateObjRectWithSpaces();
3739 // <--
3740 (this->*fnRect->fnSetYMargins)( nTop, nBorder - nTop );
3741 ChgLowersProp( aOldSz );
3742 NotifyLowerObjs();
3744 // --> OD 2004-08-25 #i3317# - reset temporarly consideration
3745 // of wrapping style influence
3746 SwPageFrm* pTmpPageFrm = FindPageFrm();
3747 SwSortedObjs* pTmpObjs = pTmpPageFrm ? pTmpPageFrm->GetSortedObjs() : 0L;
3748 if ( pTmpObjs )
3750 sal_uInt32 i = 0;
3751 for ( i = 0; i < pTmpObjs->Count(); ++i )
3753 SwAnchoredObject* pAnchoredObj = (*pTmpObjs)[i];
3755 if ( IsAnLower( pAnchoredObj->GetAnchorFrm() ) )
3757 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
3761 // <--
3762 //Es muss geeignet invalidiert werden, damit
3763 //sich die Frms huebsch ausbalancieren
3764 //- Der jeweils erste ab der zweiten Spalte bekommt
3765 // ein InvalidatePos();
3766 pCol = (SwLayoutFrm*)Lower()->GetNext();
3767 while ( pCol )
3769 pLow = pCol->Lower();
3770 if ( pLow )
3771 pLow->_InvalidatePos();
3772 pCol = (SwLayoutFrm*)pCol->GetNext();
3774 if( IsSctFrm() && ((SwSectionFrm*)this)->HasFollow() )
3776 // Wenn wir einen Follow erzeugt haben, muessen wir
3777 // seinem Inhalt die Chance geben, im CalcCntnt
3778 // zurueckzufliessen
3779 SwCntntFrm* pTmpCntnt =
3780 ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt();
3781 if( pTmpCntnt )
3782 pTmpCntnt->_InvalidatePos();
3785 else
3786 bEnd = TRUE;
3788 else
3789 bEnd = TRUE;
3791 } while ( !bEnd || !bValidSize );
3793 // OD 01.04.2003 #108446# - Don't collect endnotes for sections. Thus, set
3794 // 2nd parameter to <true>.
3795 ::CalcCntnt( this, true );
3796 if( IsSctFrm() )
3798 // OD 14.03.2003 #i11760# - adjust 2nd parameter - TRUE --> true
3799 ::CalcCntnt( this, true );
3800 if( bBackLock )
3801 ((SwSectionFrm*)this)->SetFtnLock( FALSE );
3806 /*************************************************************************
3808 |* SwRootFrm::InvalidateAllCntnt()
3810 |* Ersterstellung MA 13. Feb. 98
3811 |* Letzte Aenderung MA 12. Aug. 00
3813 |*************************************************************************/
3815 SwCntntFrm* lcl_InvalidateSection( SwFrm *pCnt, BYTE nInv )
3817 SwSectionFrm* pSect = pCnt->FindSctFrm();
3818 // Wenn unser CntntFrm in einer Tabelle oder Fussnote steht, sind nur
3819 // Bereiche gemeint, die ebenfalls innerhalb liegen.
3820 // Ausnahme: Wenn direkt eine Tabelle uebergeben wird.
3821 if( ( ( pCnt->IsInTab() && !pSect->IsInTab() ) ||
3822 ( pCnt->IsInFtn() && !pSect->IsInFtn() ) ) && !pCnt->IsTabFrm() )
3823 return NULL;
3824 if( nInv & INV_SIZE )
3825 pSect->_InvalidateSize();
3826 if( nInv & INV_POS )
3827 pSect->_InvalidatePos();
3828 if( nInv & INV_PRTAREA )
3829 pSect->_InvalidatePrt();
3830 SwFlowFrm *pFoll = pSect->GetFollow();
3831 // Temporary separation from follow
3832 pSect->SetFollow( NULL );
3833 SwCntntFrm* pRet = pSect->FindLastCntnt();
3834 pSect->SetFollow( pFoll );
3835 return pRet;
3838 SwCntntFrm* lcl_InvalidateTable( SwTabFrm *pTable, BYTE nInv )
3840 if( ( nInv & INV_SECTION ) && pTable->IsInSct() )
3841 lcl_InvalidateSection( pTable, nInv );
3842 if( nInv & INV_SIZE )
3843 pTable->_InvalidateSize();
3844 if( nInv & INV_POS )
3845 pTable->_InvalidatePos();
3846 if( nInv & INV_PRTAREA )
3847 pTable->_InvalidatePrt();
3848 return pTable->FindLastCntnt();
3851 void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, BYTE nInv );
3853 void lcl_InvalidateCntnt( SwCntntFrm *pCnt, BYTE nInv )
3855 SwCntntFrm *pLastTabCnt = NULL;
3856 SwCntntFrm *pLastSctCnt = NULL;
3857 while ( pCnt )
3859 if( nInv & INV_SECTION )
3861 if( pCnt->IsInSct() )
3863 // Siehe oben bei Tabellen
3864 if( !pLastSctCnt )
3865 pLastSctCnt = lcl_InvalidateSection( pCnt, nInv );
3866 if( pLastSctCnt == pCnt )
3867 pLastSctCnt = NULL;
3869 #ifndef PRODUCT
3870 else
3871 ASSERT( !pLastSctCnt, "Where's the last SctCntnt?" );
3872 #endif
3874 if( nInv & INV_TABLE )
3876 if( pCnt->IsInTab() )
3878 // Um nicht fuer jeden CntntFrm einer Tabelle das FindTabFrm() zu rufen
3879 // und wieder die gleiche Tabelle zu invalidieren, merken wir uns den letzten
3880 // CntntFrm der Tabelle und reagieren erst wieder auf IsInTab(), wenn wir
3881 // an diesem vorbei sind.
3882 // Beim Eintritt in die Tabelle wird der LastSctCnt auf Null gesetzt,
3883 // damit Bereiche im Innern der Tabelle richtig invalidiert werden.
3884 // Sollte die Tabelle selbst in einem Bereich stehen, so wird an
3885 // diesem die Invalidierung bis zu dreimal durchgefuehrt, das ist vertretbar.
3886 if( !pLastTabCnt )
3888 pLastTabCnt = lcl_InvalidateTable( pCnt->FindTabFrm(), nInv );
3889 pLastSctCnt = NULL;
3891 if( pLastTabCnt == pCnt )
3893 pLastTabCnt = NULL;
3894 pLastSctCnt = NULL;
3897 #ifndef PRODUCT
3898 else
3899 ASSERT( !pLastTabCnt, "Where's the last TabCntnt?" );
3900 #endif
3903 if( nInv & INV_SIZE )
3904 pCnt->Prepare( PREP_CLEAR, 0, FALSE );
3905 if( nInv & INV_POS )
3906 pCnt->_InvalidatePos();
3907 if( nInv & INV_PRTAREA )
3908 pCnt->_InvalidatePrt();
3909 if ( nInv & INV_LINENUM )
3910 pCnt->InvalidateLineNum();
3911 if ( pCnt->GetDrawObjs() )
3912 lcl_InvalidateAllCntnt( pCnt, nInv );
3913 pCnt = pCnt->GetNextCntntFrm();
3917 void lcl_InvalidateAllCntnt( SwCntntFrm *pCnt, BYTE nInv )
3919 SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
3920 for ( USHORT i = 0; i < rObjs.Count(); ++i )
3922 SwAnchoredObject* pAnchoredObj = rObjs[i];
3923 if ( pAnchoredObj->ISA(SwFlyFrm) )
3925 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3926 if ( pFly->IsFlyInCntFrm() )
3928 ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
3929 if( nInv & INV_DIRECTION )
3930 pFly->CheckDirChange();
3936 void SwRootFrm::InvalidateAllCntnt( BYTE nInv )
3938 // Erst werden alle Seitengebundenen FlyFrms abgearbeitet.
3939 SwPageFrm *pPage = (SwPageFrm*)Lower();
3940 while( pPage )
3942 pPage->InvalidateFlyLayout();
3943 pPage->InvalidateFlyCntnt();
3944 pPage->InvalidateFlyInCnt();
3945 pPage->InvalidateLayout();
3946 pPage->InvalidateCntnt();
3947 pPage->InvalidatePage( pPage ); //Damit ggf. auch der Turbo verschwindet
3949 if ( pPage->GetSortedObjs() )
3951 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3952 for ( USHORT i = 0; i < rObjs.Count(); ++i )
3954 SwAnchoredObject* pAnchoredObj = rObjs[i];
3955 if ( pAnchoredObj->ISA(SwFlyFrm) )
3957 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3958 ::lcl_InvalidateCntnt( pFly->ContainsCntnt(), nInv );
3959 if ( nInv & INV_DIRECTION )
3960 pFly->CheckDirChange();
3964 if( nInv & INV_DIRECTION )
3965 pPage->CheckDirChange();
3966 pPage = (SwPageFrm*)(pPage->GetNext());
3969 //Hier den gesamten Dokumentinhalt und die zeichengebundenen Flys.
3970 ::lcl_InvalidateCntnt( ContainsCntnt(), nInv );
3972 if( nInv & INV_PRTAREA )
3974 ViewShell *pSh = GetShell();
3975 if( pSh )
3976 pSh->InvalidateWindows( Frm() );
3980 /** method to invalidate/re-calculate the position of all floating
3981 screen objects (Writer fly frames and drawing objects), which are
3982 anchored to paragraph or to character.
3984 OD 2004-03-16 #i11860#
3986 @author OD
3988 void SwRootFrm::InvalidateAllObjPos()
3990 const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>(Lower());
3991 while( pPageFrm )
3993 pPageFrm->InvalidateFlyLayout();
3995 if ( pPageFrm->GetSortedObjs() )
3997 const SwSortedObjs& rObjs = *(pPageFrm->GetSortedObjs());
3998 for ( sal_uInt8 i = 0; i < rObjs.Count(); ++i )
4000 SwAnchoredObject* pAnchoredObj = rObjs[i];
4001 const SwFmtAnchor& rAnch = pAnchoredObj->GetFrmFmt().GetAnchor();
4002 if ( rAnch.GetAnchorId() != FLY_AT_CNTNT &&
4003 rAnch.GetAnchorId() != FLY_AUTO_CNTNT )
4005 // only to paragraph and to character anchored objects are considered.
4006 continue;
4008 // --> OD 2004-07-07 #i28701# - special invalidation for anchored
4009 // objects, whose wrapping style influence has to be considered.
4010 if ( pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos() )
4011 pAnchoredObj->InvalidateObjPosForConsiderWrapInfluence( true );
4012 else
4013 pAnchoredObj->InvalidateObjPos();
4014 // <--
4018 pPageFrm = static_cast<const SwPageFrm*>(pPageFrm->GetNext());