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