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