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