xref: /AOO41X/main/sw/source/core/layout/ssfrm.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <ftnfrm.hxx>
32 #include <pagefrm.hxx>
33 #include <rootfrm.hxx>
34 #include <cntfrm.hxx>
35 #include <doc.hxx>
36 #include <node.hxx>
37 #include <dview.hxx>
38 #include <dcontact.hxx>
39 #include <dflyobj.hxx>
40 #include <flyfrm.hxx>
41 #include <txtfrm.hxx>		// ClearPara()
42 #include <cellfrm.hxx>
43 #include <swtable.hxx>
44 #include <fmtfsize.hxx>
45 #include <ftnidx.hxx>
46 #include <txtftn.hxx>
47 #include <ndtxt.hxx>
48 #include <ndindex.hxx>
49 #include <frmtool.hxx>
50 #include <pagedesc.hxx>
51 #include <editeng/boxitem.hxx>
52 #include <editeng/shaditem.hxx>
53 #include <fmtclds.hxx>
54 #include <viewsh.hxx>
55 #include <viewimp.hxx>
56 #include <sortedobjs.hxx>
57 #include <hints.hxx>
58 #include <switerator.hxx>
59 
60     // No inline cause we need the function pointers
61 long SwFrm::GetTopMargin() const
62     { return Prt().Top(); }
63 long SwFrm::GetBottomMargin() const
64     { return Frm().Height() -Prt().Height() -Prt().Top(); }
65 long SwFrm::GetLeftMargin() const
66     { return Prt().Left(); }
67 long SwFrm::GetRightMargin() const
68     { return Frm().Width() - Prt().Width() - Prt().Left(); }
69 long SwFrm::GetPrtLeft() const
70     { return Frm().Left() + Prt().Left(); }
71 long SwFrm::GetPrtBottom() const
72     { return Frm().Top() + Prt().Height() + Prt().Top(); }
73 long SwFrm::GetPrtRight() const
74     { return Frm().Left() + Prt().Width() + Prt().Left(); }
75 long SwFrm::GetPrtTop() const
76     { return Frm().Top() + Prt().Top(); }
77 
78 sal_Bool SwFrm::SetMinLeft( long nDeadline )
79 {
80     SwTwips nDiff = nDeadline - Frm().Left();
81     if( nDiff > 0 )
82     {
83         Frm().Left( nDeadline );
84         Prt().Width( Prt().Width() - nDiff );
85         return sal_True;
86     }
87     return sal_False;
88 }
89 
90 sal_Bool SwFrm::SetMaxBottom( long nDeadline )
91 {
92     SwTwips nDiff = Frm().Top() + Frm().Height() - nDeadline;
93     if( nDiff > 0 )
94     {
95         Frm().Height( Frm().Height() - nDiff );
96         Prt().Height( Prt().Height() - nDiff );
97         return sal_True;
98     }
99     return sal_False;
100 }
101 
102 sal_Bool SwFrm::SetMinTop( long nDeadline )
103 {
104     SwTwips nDiff = nDeadline - Frm().Top();
105     if( nDiff > 0 )
106     {
107         Frm().Top( nDeadline );
108         Prt().Height( Prt().Height() - nDiff );
109         return sal_True;
110     }
111     return sal_False;
112 }
113 
114 sal_Bool SwFrm::SetMaxRight( long nDeadline )
115 {
116     SwTwips nDiff = Frm().Left() + Frm().Width() - nDeadline;
117     if( nDiff > 0 )
118     {
119         Frm().Width( Frm().Width() - nDiff );
120         Prt().Width( Prt().Width() - nDiff );
121         return sal_True;
122     }
123     return sal_False;
124 }
125 
126 void SwFrm::MakeBelowPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
127 {
128     if( pPrv )
129     {
130         aFrm.Pos( pPrv->Frm().Pos() );
131         aFrm.Pos().Y() += pPrv->Frm().Height();
132     }
133     else
134     {
135         aFrm.Pos( pUp->Frm().Pos() );
136         aFrm.Pos() += pUp->Prt().Pos();
137     }
138     if( bNotify )
139         aFrm.Pos().Y() += 1;
140 }
141 
142 void SwFrm::MakeUpperPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
143 {
144     if( pPrv )
145     {
146         aFrm.Pos( pPrv->Frm().Pos() );
147         aFrm.Pos().Y() -= Frm().Height();
148     }
149     else
150     {
151         aFrm.Pos( pUp->Frm().Pos() );
152         aFrm.Pos() += pUp->Prt().Pos();
153         aFrm.Pos().Y() += pUp->Prt().Height() - aFrm.Height();
154     }
155     if( bNotify )
156         aFrm.Pos().Y() -= 1;
157 }
158 
159 void SwFrm::MakeLeftPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
160 {
161     if( pPrv )
162     {
163         aFrm.Pos( pPrv->Frm().Pos() );
164         aFrm.Pos().X() -= Frm().Width();
165     }
166     else
167     {
168         aFrm.Pos( pUp->Frm().Pos() );
169         aFrm.Pos() += pUp->Prt().Pos();
170         aFrm.Pos().X() += pUp->Prt().Width() - aFrm.Width();
171     }
172     if( bNotify )
173         aFrm.Pos().X() -= 1;
174 }
175 
176 void SwFrm::MakeRightPos( const SwFrm* pUp, const SwFrm* pPrv, sal_Bool bNotify )
177 {
178     if( pPrv )
179     {
180         aFrm.Pos( pPrv->Frm().Pos() );
181         aFrm.Pos().X() += pPrv->Frm().Width();
182     }
183     else
184     {
185         aFrm.Pos( pUp->Frm().Pos() );
186         aFrm.Pos() += pUp->Prt().Pos();
187     }
188     if( bNotify )
189         aFrm.Pos().X() += 1;
190 }
191 
192 void SwFrm::SetTopBottomMargins( long nTop, long nBot )
193 {
194     Prt().Top( nTop );
195     Prt().Height( Frm().Height() - nTop - nBot );
196 }
197 
198 void SwFrm::SetBottomTopMargins( long nBot, long nTop )
199 {
200     Prt().Top( nTop );
201     Prt().Height( Frm().Height() - nTop - nBot );
202 }
203 
204 void SwFrm::SetLeftRightMargins( long nLeft, long nRight)
205 {
206     Prt().Left( nLeft );
207     Prt().Width( Frm().Width() - nLeft - nRight );
208 }
209 
210 void SwFrm::SetRightLeftMargins( long nRight, long nLeft)
211 {
212     Prt().Left( nLeft );
213     Prt().Width( Frm().Width() - nLeft - nRight );
214 }
215 
216 const sal_uInt16 nMinVertCellHeight = 1135;
217 
218 /*-----------------------------------
219  * SwFrm::CheckDirChange(..)
220  * checks the layout direction and
221  * invalidates the lower frames rekursivly, if necessary.
222  * --------------------------------------------------*/
223 
224 void SwFrm::CheckDirChange()
225 {
226     sal_Bool bOldVert = GetVerticalFlag();
227     sal_Bool bOldRev = IsReverse();
228     sal_Bool bOldR2L = GetRightToLeftFlag();
229     SetInvalidVert( sal_True );
230     SetInvalidR2L( sal_True );
231     sal_Bool bChg = bOldR2L != IsRightToLeft();
232     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
233     sal_Bool bOldVertL2R = IsVertLR();
234     if( ( IsVertical() != bOldVert ) || bChg || IsReverse() != bOldRev || bOldVertL2R != IsVertLR() )
235     {
236         InvalidateAll();
237         if( IsLayoutFrm() )
238         {
239             // set minimum row height for vertical cells in horizontal table:
240             if ( IsCellFrm() && GetUpper() )
241             {
242                 if ( IsVertical() != GetUpper()->IsVertical() &&
243                      ((SwCellFrm*)this)->GetTabBox()->getRowSpan() == 1 )
244                 {
245                     SwTableLine* pLine = (SwTableLine*)((SwCellFrm*)this)->GetTabBox()->GetUpper();
246                     SwFrmFmt* pFrmFmt = pLine->GetFrmFmt();
247                     SwFmtFrmSize aNew( pFrmFmt->GetFrmSize() );
248                     if ( ATT_FIX_SIZE != aNew.GetHeightSizeType() )
249                         aNew.SetHeightSizeType( ATT_MIN_SIZE );
250                     if ( aNew.GetHeight() < nMinVertCellHeight )
251                         aNew.SetHeight( nMinVertCellHeight );
252                     SwDoc* pDoc = pFrmFmt->GetDoc();
253                     pDoc->SetAttr( aNew, *pLine->ClaimFrmFmt() );
254                 }
255             }
256 
257             SwFrm* pFrm = ((SwLayoutFrm*)this)->Lower();
258             const SwFmtCol* pCol = NULL;
259             SwLayoutFrm* pBody = 0;
260             if( pFrm )
261             {
262                 if( IsPageFrm() )
263                 {
264                     // If we're a page frame and we change our layout direction,
265                     // we have to look for columns and rearrange them.
266                     pBody = ((SwPageFrm*)this)->FindBodyCont();
267                     if(pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm())
268                         pCol = &((SwPageFrm*)this)->GetFmt()->GetCol();
269                 }
270                 else if( pFrm->IsColumnFrm() )
271                 {
272                     pBody = ((SwLayoutFrm*)this);
273                     const SwFrmFmt *pFmt = pBody->GetFmt();
274                     if( pFmt )
275                         pCol = &pFmt->GetCol();
276                 }
277             }
278             while( pFrm )
279             {
280                 pFrm->CheckDirChange();
281                 pFrm = pFrm->GetNext();
282             }
283             if( pCol )
284                 pBody->AdjustColumns( pCol, sal_True );
285         }
286         else if( IsTxtFrm() )
287             ((SwTxtFrm*)this)->Prepare( PREP_CLEAR );
288 
289         // --> OD 2004-07-27 #i31698# - notify anchored objects also for page frames.
290         // Remove code above for special handling of page frames
291         if ( GetDrawObjs() )
292         {
293             const SwSortedObjs *pObjs = GetDrawObjs();
294             sal_uInt32 nCnt = pObjs->Count();
295             for ( sal_uInt32 i = 0; i < nCnt; ++i )
296             {
297                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
298                 if( pAnchoredObj->ISA(SwFlyFrm) )
299                     static_cast<SwFlyFrm*>(pAnchoredObj)->CheckDirChange();
300                 else
301                 {
302                     // OD 2004-04-06 #i26791# - direct object
303                     // positioning no longer needed. Instead
304                     // invalidate
305                     pAnchoredObj->InvalidateObjPos();
306                 }
307                 // --> OD 2004-07-27 #i31698# - update layout direction of
308                 // anchored object
309                 {
310                     ::setContextWritingMode( pAnchoredObj->DrawObj(), pAnchoredObj->GetAnchorFrmContainingAnchPos() );
311                     pAnchoredObj->UpdateLayoutDir();
312                 }
313                 // <--
314             }
315         }
316     }
317 }
318 
319 /*-----------------------------------
320  * SwFrm::GetFrmAnchorPos(..)
321  * returns the position for anchors based on frame direction
322  * --------------------------------------------------*/
323 // OD 2004-03-10 #i11860# - consider lower space and line spacing of
324 // previous frame according to new option 'Use former object positioning'
325 Point SwFrm::GetFrmAnchorPos( sal_Bool bIgnoreFlysAnchoredAtThisFrame ) const
326 {
327     Point aAnchor = Frm().Pos();
328     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
329     if ( ( IsVertical() && !IsVertLR() ) || IsRightToLeft() )
330 		aAnchor.X() += Frm().Width();
331 
332     if ( IsTxtFrm() )
333     {
334         SwTwips nBaseOfstForFly =
335             ((SwTxtFrm*)this)->GetBaseOfstForFly( bIgnoreFlysAnchoredAtThisFrame );
336         if ( IsVertical() )
337             aAnchor.Y() += nBaseOfstForFly;
338         else
339             aAnchor.X() += nBaseOfstForFly;
340 
341         // OD 2004-03-10 #i11860# - if option 'Use former object positioning'
342         // is OFF, consider the lower space and the line spacing of the
343         // previous frame and the spacing considered for the page grid
344         const SwTxtFrm* pThisTxtFrm = static_cast<const SwTxtFrm*>(this);
345         const SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
346                 pThisTxtFrm->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid();
347         if ( IsVertical() )
348         {
349             aAnchor.X() -= nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
350         }
351         else
352         {
353             aAnchor.Y() += nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
354         }
355     }
356 
357     return aAnchor;
358 }
359 
360 
361 /*************************************************************************
362 |*
363 |*	SwFrm::~SwFrm()
364 |*
365 |*************************************************************************/
366 
367 SwFrm::~SwFrm()
368 {
369 	// accessible objects for fly and cell frames have been already disposed
370 	// by the destructors of the derived classes.
371 	if( IsAccessibleFrm() && !(IsFlyFrm() || IsCellFrm()) && GetDep() )
372 	{
373 		SwRootFrm *pRootFrm = getRootFrm();
374 		if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
375 		{
376 			ViewShell *pVSh = pRootFrm->GetCurrShell();
377 			if( pVSh && pVSh->Imp() )
378 			{
379 				ASSERT( !GetLower(), "Lowers should be dispose already!" );
380 				pVSh->Imp()->DisposeAccessibleFrm( this );
381 			}
382 		}
383 	}
384 
385 	if( pDrawObjs )
386 	{
387         for ( sal_uInt32 i = pDrawObjs->Count(); i; )
388 		{
389             SwAnchoredObject* pAnchoredObj = (*pDrawObjs)[--i];
390             if ( pAnchoredObj->ISA(SwFlyFrm) )
391                 delete pAnchoredObj;
392             else
393             {
394                 SdrObject* pSdrObj = pAnchoredObj->DrawObj();
395                 SwDrawContact* pContact =
396                         static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
397                 ASSERT( pContact,
398                         "<SwFrm::~SwFrm> - missing contact for drawing object" );
399                 if ( pContact )
400                 {
401                     pContact->DisconnectObjFromLayout( pSdrObj );
402                 }
403             }
404 		}
405 		if ( pDrawObjs )
406 			delete pDrawObjs;
407 	}
408 
409 #ifdef DBG_UTIL
410 	// JP 15.10.2001: for detection of access to deleted frames
411     pDrawObjs = (SwSortedObjs*)0x33333333;
412 #endif
413 }
414 
415 /*************************************************************************/
416 
417 const SwFrmFmt * SwLayoutFrm::GetFmt() const
418 {
419     return static_cast< const SwFlyFrmFmt * >( GetDep() );
420 }
421 
422 SwFrmFmt * SwLayoutFrm::GetFmt()
423 {
424     return static_cast< SwFlyFrmFmt * >( GetDep() );
425 }
426 
427 
428 /*************************************************************************
429 |*
430 |*	  SwLayoutFrm::SetFrmFmt()
431 |*
432 |*************************************************************************/
433 
434 
435 void SwLayoutFrm::SetFrmFmt( SwFrmFmt *pNew )
436 {
437 	if ( pNew != GetFmt() )
438 	{
439 		SwFmtChg aOldFmt( GetFmt() );
440 		pNew->Add( this );
441 		SwFmtChg aNewFmt( pNew );
442 		ModifyNotification( &aOldFmt, &aNewFmt );
443 	}
444 }
445 
446 /*************************************************************************
447 |*                  SwCntntFrm::SwCntntFrm()
448 |*************************************************************************/
449 SwCntntFrm::SwCntntFrm( SwCntntNode * const pCntnt, SwFrm* pSib ) :
450 	SwFrm( pCntnt, pSib ),
451 	SwFlowFrm( (SwFrm&)*this )
452 {
453 }
454 
455 /*************************************************************************
456 |*                  SwCntntFrm::~SwCntntFrm()
457 |*************************************************************************/
458 SwCntntFrm::~SwCntntFrm()
459 {
460 	SwCntntNode* pCNd;
461 	if( 0 != ( pCNd = PTR_CAST( SwCntntNode, GetRegisteredIn() )) &&
462 		!pCNd->GetDoc()->IsInDtor() )
463 	{
464 		//Bei der Root abmelden wenn ich dort noch im Turbo stehe.
465 		SwRootFrm *pRoot = getRootFrm();
466 		if( pRoot && pRoot->GetTurbo() == this )
467 		{
468 			pRoot->DisallowTurbo();
469 			pRoot->ResetTurbo();
470 		}
471         if( IsTxtFrm() && ((SwTxtFrm*)this)->HasFtn() )
472         {
473             SwTxtNode *pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
474             const SwFtnIdxs &rFtnIdxs = pCNd->GetDoc()->GetFtnIdxs();
475             sal_uInt16 nPos;
476             sal_uLong nIndex = pCNd->GetIndex();
477             rFtnIdxs.SeekEntry( *pTxtNd, &nPos );
478             SwTxtFtn* pTxtFtn;
479             if( nPos < rFtnIdxs.Count() )
480             {
481                 while( nPos && pTxtNd == &(rFtnIdxs[ nPos ]->GetTxtNode()) )
482                     --nPos;
483                 if( nPos || pTxtNd != &(rFtnIdxs[ nPos ]->GetTxtNode()) )
484                     ++nPos;
485             }
486             while( nPos < rFtnIdxs.Count() )
487             {
488                 pTxtFtn = rFtnIdxs[ nPos ];
489                 if( pTxtFtn->GetTxtNode().GetIndex() > nIndex )
490                     break;
491                 pTxtFtn->DelFrms( this );
492                 ++nPos;
493             }
494         }
495 	}
496 }
497 
498 void SwCntntFrm::RegisterToNode( SwCntntNode& rNode )
499 {
500     rNode.Add( this );
501 }
502 
503 void SwCntntFrm::DelFrms( const SwCntntNode& rNode )
504 {
505 	SwIterator<SwCntntFrm,SwCntntNode> aIter( rNode );
506 	for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
507 	{
508         // --> OD 2005-12-01 #i27138#
509         // notify accessibility paragraphs objects about changed
510         // CONTENT_FLOWS_FROM/_TO relation.
511         // Relation CONTENT_FLOWS_FROM for current next paragraph will change
512         // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
513         if ( pFrm->IsTxtFrm() )
514         {
515             ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
516             if ( pViewShell && pViewShell->GetLayout() &&
517                  pViewShell->GetLayout()->IsAnyShellAccessible() )
518             {
519                 pViewShell->InvalidateAccessibleParaFlowRelation(
520                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
521                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
522             }
523         }
524         // <--
525         if( pFrm->HasFollow() )
526             pFrm->GetFollow()->_SetIsFollow( pFrm->IsFollow() );
527         if( pFrm->IsFollow() )
528         {
529             SwCntntFrm* pMaster = (SwTxtFrm*)pFrm->FindMaster();
530             pMaster->SetFollow( pFrm->GetFollow() );
531             pFrm->_SetIsFollow( sal_False );
532         }
533 		pFrm->SetFollow( 0 );//Damit er nicht auf dumme Gedanken kommt.
534 								//Andernfalls kann es sein, dass ein Follow
535 								//vor seinem Master zerstoert wird, der Master
536 								//greift dann ueber den ungueltigen
537 								//Follow-Pointer auf fremdes Memory zu.
538 								//Die Kette darf hier zerknauscht werden, weil
539 								//sowieso alle zerstoert werden.
540 		if( pFrm->GetUpper() && pFrm->IsInFtn() && !pFrm->GetIndNext() &&
541 			!pFrm->GetIndPrev() )
542 		{
543 			SwFtnFrm *pFtn = pFrm->FindFtnFrm();
544 			ASSERT( pFtn, "You promised a FtnFrm?" );
545 			SwCntntFrm* pCFrm;
546 			if( !pFtn->GetFollow() && !pFtn->GetMaster() &&
547 				0 != ( pCFrm = pFtn->GetRefFromAttr()) && pCFrm->IsFollow() )
548 			{
549 				ASSERT( pCFrm->IsTxtFrm(), "NoTxtFrm has Footnote?" );
550 				((SwTxtFrm*)pCFrm->FindMaster())->Prepare( PREP_FTN_GONE );
551 			}
552 		}
553 		pFrm->Cut();
554 		delete pFrm;
555 	}
556 }
557 
558 /*************************************************************************
559 |*
560 |*	SwLayoutFrm::~SwLayoutFrm
561 |*
562 |*************************************************************************/
563 
564 
565 SwLayoutFrm::~SwLayoutFrm()
566 {
567 	SwFrm *pFrm = pLower;
568 
569 	if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() )
570 	{
571         while ( pFrm )
572 		{
573 			//Erst die Objs des Frm vernichten, denn diese koennen sich sonst nach
574 			//dem Remove nicht mehr bei der Seite abmelden.
575 			//Falls sich einer nicht abmeldet wollen wir nicht gleich
576 			//endlos schleifen.
577 
578             sal_uInt32 nCnt;
579 			while ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() )
580 			{
581 				nCnt = pFrm->GetDrawObjs()->Count();
582                 // --> OD 2004-06-30 #i28701#
583                 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[0];
584                 if ( pAnchoredObj->ISA(SwFlyFrm) )
585                     delete pAnchoredObj;
586                 else
587                 {
588                     SdrObject* pSdrObj = pAnchoredObj->DrawObj();
589                     SwDrawContact* pContact =
590                             static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
591                     ASSERT( pContact,
592                             "<SwFrm::~SwFrm> - missing contact for drawing object" );
593                     if ( pContact )
594                     {
595                         pContact->DisconnectObjFromLayout( pSdrObj );
596                     }
597                 }
598 				if ( pFrm->GetDrawObjs() &&
599 					 nCnt == pFrm->GetDrawObjs()->Count() )
600                 {
601                     pFrm->GetDrawObjs()->Remove( *pAnchoredObj );
602                 }
603                 // <--
604 			}
605 			pFrm->Remove();
606 			delete pFrm;
607 			pFrm = pLower;
608 		}
609 		//Fly's vernichten. Der letzte loescht gleich das Array.
610         sal_uInt32 nCnt;
611 		while ( GetDrawObjs() && GetDrawObjs()->Count() )
612 		{
613 			nCnt = GetDrawObjs()->Count();
614 
615             // --> OD 2004-06-30 #i28701#
616             SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[0];
617             if ( pAnchoredObj->ISA(SwFlyFrm) )
618                 delete pAnchoredObj;
619             else
620             {
621                 SdrObject* pSdrObj = pAnchoredObj->DrawObj();
622                 SwDrawContact* pContact =
623                         static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
624                 ASSERT( pContact,
625                         "<SwFrm::~SwFrm> - missing contact for drawing object" );
626                 if ( pContact )
627                 {
628                     pContact->DisconnectObjFromLayout( pSdrObj );
629                 }
630             }
631             if ( GetDrawObjs() && nCnt == GetDrawObjs()->Count() )
632             {
633                 GetDrawObjs()->Remove( *pAnchoredObj );
634             }
635             // <--
636 		}
637 	}
638 	else
639 	{
640 		while( pFrm )
641 		{
642 			SwFrm *pNxt = pFrm->GetNext();
643 			delete pFrm;
644 			pFrm = pNxt;
645 		}
646 	}
647 }
648 
649 /*************************************************************************
650 |*
651 |*	SwFrm::PaintArea()
652 |*
653 |*  The paintarea is the area, in which the content of a frame is allowed
654 |*  to be displayed. This region could be larger than the printarea (Prt())
655 |*  of the upper, it includes e.g. often the margin of the page.
656 |*
657 |*************************************************************************/
658 
659 const SwRect SwFrm::PaintArea() const
660 {
661     // NEW TABLES
662     // Cell frames may not leave their upper:
663     SwRect aRect = IsRowFrm() ? GetUpper()->Frm() : Frm();
664     const sal_Bool bVert = IsVertical();
665     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
666     SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
667     long nRight = (aRect.*fnRect->fnGetRight)();
668     long nLeft  = (aRect.*fnRect->fnGetLeft)();
669 	const SwFrm* pTmp = this;
670 	sal_Bool bLeft = sal_True;
671 	sal_Bool bRight = sal_True;
672     long nRowSpan = 0;
673 	while( pTmp )
674 	{
675         if( pTmp->IsCellFrm() && pTmp->GetUpper() &&
676             pTmp->GetUpper()->IsVertical() != pTmp->IsVertical() )
677             nRowSpan = ((SwCellFrm*)pTmp)->GetTabBox()->getRowSpan();
678         long nTmpRight = (pTmp->Frm().*fnRect->fnGetRight)();
679         long nTmpLeft = (pTmp->Frm().*fnRect->fnGetLeft)();
680         if( pTmp->IsRowFrm() && nRowSpan > 1 )
681         {
682             const SwFrm* pNxt = pTmp;
683             while( --nRowSpan > 0 && pNxt->GetNext() )
684                 pNxt = pNxt->GetNext();
685             if( pTmp->IsVertical() )
686                 nTmpLeft = (pNxt->Frm().*fnRect->fnGetLeft)();
687             else
688                 nTmpRight = (pNxt->Frm().*fnRect->fnGetRight)();
689         }
690 		ASSERT( pTmp, "PaintArea lost in time and space" );
691 		if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() ||
692 			pTmp->IsCellFrm() || pTmp->IsRowFrm() || //nobody leaves a table!
693 			pTmp->IsRootFrm() )
694 		{
695             if( bLeft || nLeft < nTmpLeft )
696                 nLeft = nTmpLeft;
697             if( bRight || nTmpRight < nRight )
698 				nRight = nTmpRight;
699 			if( pTmp->IsPageFrm() || pTmp->IsFlyFrm() || pTmp->IsRootFrm() )
700 				break;
701 			bLeft = sal_False;
702 			bRight = sal_False;
703 		}
704 		else if( pTmp->IsColumnFrm() )  // nobody enters neightbour columns
705 		{
706             sal_Bool bR2L = pTmp->IsRightToLeft();
707             // the first column has _no_ influence to the left range
708             if( bR2L ? pTmp->GetNext() : pTmp->GetPrev() )
709             {
710                 if( bLeft || nLeft < nTmpLeft )
711                     nLeft = nTmpLeft;
712 				bLeft = sal_False;
713 			}
714              // the last column has _no_ influence to the right range
715             if( bR2L ? pTmp->GetPrev() : pTmp->GetNext() )
716             {
717 				if( bRight || nTmpRight < nRight )
718                     nRight = nTmpRight;
719 				bRight = sal_False;
720 			}
721 		}
722         else if( bVert && pTmp->IsBodyFrm() )
723         {
724             // Header and footer frames have always horizontal direction and
725             // limit the body frame.
726             // A previous frame of a body frame must be a header,
727             // the next frame of a body frame may be a footnotecontainer or
728             // a footer. The footnotecontainer has the same direction like
729             // the body frame.
730             if( pTmp->GetPrev() && ( bLeft || nLeft < nTmpLeft ) )
731             {
732                 nLeft = nTmpLeft;
733                 bLeft = sal_False;
734             }
735             if( pTmp->GetNext() &&
736                 ( pTmp->GetNext()->IsFooterFrm() || pTmp->GetNext()->GetNext() )
737                 && ( bRight || nTmpRight < nRight ) )
738             {
739                 nRight = nTmpRight;
740                 bRight = sal_False;
741 			}
742         }
743 		pTmp = pTmp->GetUpper();
744 	}
745     (aRect.*fnRect->fnSetLeft)( nLeft );
746     (aRect.*fnRect->fnSetRight)( nRight );
747 	return aRect;
748 }
749 
750 /*************************************************************************
751 |*
752 |*	SwFrm::UnionFrm()
753 |*
754 |*  The unionframe is the framearea (Frm()) of a frame expanded by the
755 |*  printarea, if there's a negative margin at the left or right side.
756 |*
757 |*************************************************************************/
758 
759 const SwRect SwFrm::UnionFrm( sal_Bool bBorder ) const
760 {
761     sal_Bool bVert = IsVertical();
762     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
763     SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
764     long nLeft = (Frm().*fnRect->fnGetLeft)();
765     long nWidth = (Frm().*fnRect->fnGetWidth)();
766     long nPrtLeft = (Prt().*fnRect->fnGetLeft)();
767     long nPrtWidth = (Prt().*fnRect->fnGetWidth)();
768     if( nPrtLeft + nPrtWidth > nWidth )
769         nWidth = nPrtLeft + nPrtWidth;
770     if( nPrtLeft < 0 )
771     {
772         nLeft += nPrtLeft;
773         nWidth -= nPrtLeft;
774     }
775     SwTwips nRight = nLeft + nWidth;
776     long nAdd = 0;
777 	if( bBorder )
778 	{
779 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), this );
780 		const SwBorderAttrs &rAttrs = *aAccess.Get();
781 		const SvxBoxItem &rBox = rAttrs.GetBox();
782 		if ( rBox.GetLeft() )
783             nLeft -= rBox.CalcLineSpace( BOX_LINE_LEFT );
784 		else if ( rAttrs.IsBorderDist() )
785             nLeft -= rBox.GetDistance( BOX_LINE_LEFT ) + 1;
786 		if ( rBox.GetRight() )
787             nAdd += rBox.CalcLineSpace( BOX_LINE_RIGHT );
788 		else if ( rAttrs.IsBorderDist() )
789             nAdd += rBox.GetDistance( BOX_LINE_RIGHT ) + 1;
790 		if( rAttrs.GetShadow().GetLocation() != SVX_SHADOW_NONE )
791 		{
792 			const SvxShadowItem &rShadow = rAttrs.GetShadow();
793             nLeft -= rShadow.CalcShadowSpace( SHADOW_LEFT );
794             nAdd += rShadow.CalcShadowSpace( SHADOW_RIGHT );
795 		}
796 	}
797     if( IsTxtFrm() && ((SwTxtFrm*)this)->HasPara() )
798     {
799         long nTmp = ((SwTxtFrm*)this)->HangingMargin();
800         if( nTmp > nAdd )
801             nAdd = nTmp;
802     }
803     nWidth = nRight + nAdd - nLeft;
804 	SwRect aRet( Frm() );
805     (aRet.*fnRect->fnSetPosX)( nLeft );
806     (aRet.*fnRect->fnSetWidth)( nWidth );
807 	return aRet;
808 }
809 
810 
811 
812 
813