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