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 32 #include "pagefrm.hxx" 33 #include "rootfrm.hxx" 34 #include "cntfrm.hxx" 35 #include "node.hxx" 36 #include "doc.hxx" 37 #include "frmtool.hxx" 38 #include "flyfrm.hxx" 39 #include <frmfmt.hxx> 40 #include <cellfrm.hxx> 41 #include <rowfrm.hxx> 42 #include <swtable.hxx> 43 44 #include "tabfrm.hxx" 45 #include "sectfrm.hxx" 46 #include "flyfrms.hxx" 47 #include "ftnfrm.hxx" 48 #include "txtftn.hxx" 49 #include "fmtftn.hxx" 50 #include <txtfrm.hxx> // SwTxtFrm 51 #include <switerator.hxx> 52 53 /************************************************************************* 54 |* 55 |* FindBodyCont, FindLastBodyCntnt() 56 |* 57 |* Beschreibung Sucht den ersten/letzten CntntFrm im BodyText unterhalb 58 |* der Seite. 59 |* Ersterstellung MA 15. Feb. 93 60 |* Letzte Aenderung MA 18. Apr. 94 61 |* 62 |*************************************************************************/ 63 SwLayoutFrm *SwFtnBossFrm::FindBodyCont() 64 { 65 SwFrm *pLay = Lower(); 66 while ( pLay && !pLay->IsBodyFrm() ) 67 pLay = pLay->GetNext(); 68 return (SwLayoutFrm*)pLay; 69 } 70 71 SwCntntFrm *SwPageFrm::FindLastBodyCntnt() 72 { 73 SwCntntFrm *pRet = FindFirstBodyCntnt(); 74 SwCntntFrm *pNxt = pRet; 75 while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) ) 76 { pRet = pNxt; 77 pNxt = pNxt->FindNextCnt(); 78 } 79 return pRet; 80 } 81 82 /************************************************************************* 83 |* 84 |* SwLayoutFrm::ContainsCntnt 85 |* 86 |* Beschreibung Prueft, ob der Frame irgendwo in seiner 87 |* untergeordneten Struktur einen oder mehrere CntntFrm's enthaelt; 88 |* Falls ja wird der erste gefundene CntntFrm zurueckgegeben. 89 |* 90 |* Ersterstellung MA 13. May. 92 91 |* Letzte Aenderung MA 20. Apr. 94 92 |* 93 |*************************************************************************/ 94 95 const SwCntntFrm *SwLayoutFrm::ContainsCntnt() const 96 { 97 //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat 98 //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der 99 //this verlassen wird. 100 //Sections: Cntnt neben Sections wuerde so nicht gefunden (leere Section 101 //direct neben CntntFrm), deshalb muss fuer diese Aufwendiger rekursiv gesucht 102 //werden. 103 104 const SwLayoutFrm *pLayLeaf = this; 105 do 106 { 107 while ( (!pLayLeaf->IsSctFrm() || pLayLeaf == this ) && 108 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() ) 109 pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower(); 110 111 if( pLayLeaf->IsSctFrm() && pLayLeaf != this ) 112 { 113 const SwCntntFrm *pCnt = pLayLeaf->ContainsCntnt(); 114 if( pCnt ) 115 return pCnt; 116 if( pLayLeaf->GetNext() ) 117 { 118 if( pLayLeaf->GetNext()->IsLayoutFrm() ) 119 { 120 pLayLeaf = (SwLayoutFrm*)pLayLeaf->GetNext(); 121 continue; 122 } 123 else 124 return (SwCntntFrm*)pLayLeaf->GetNext(); 125 } 126 } 127 else if ( pLayLeaf->Lower() ) 128 return (SwCntntFrm*)pLayLeaf->Lower(); 129 130 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 131 if( !IsAnLower( pLayLeaf) ) 132 return 0; 133 } while( pLayLeaf ); 134 return 0; 135 } 136 137 /************************************************************************* 138 |* 139 |* SwLayoutFrm::FirstCell 140 |* 141 |* Beschreibung ruft zunaechst ContainsAny auf, um in die innerste Zelle 142 |* hineinzukommen. Dort hangelt es sich wieder hoch zum 143 |* ersten SwCellFrm, seit es SectionFrms gibt, reicht kein 144 |* ContainsCntnt()->GetUpper() mehr... 145 |* Ersterstellung AMA 17. Mar. 99 146 |* Letzte Aenderung AMA 17. Mar. 99 147 |* 148 |*************************************************************************/ 149 150 const SwCellFrm *SwLayoutFrm::FirstCell() const 151 { 152 const SwFrm* pCnt = ContainsAny(); 153 while( pCnt && !pCnt->IsCellFrm() ) 154 pCnt = pCnt->GetUpper(); 155 return (const SwCellFrm*)pCnt; 156 } 157 158 /************************************************************************* 159 |* 160 |* SwLayoutFrm::ContainsAny 161 |* 162 |* Beschreibung wie ContainsCntnt, nur dass nicht nur CntntFrms, sondern auch 163 |* Bereiche und Tabellen zurueckgegeben werden. 164 |* Ersterstellung AMA 10. Mar. 99 165 |* Letzte Aenderung AMA 10. Mar. 99 166 |* 167 |*************************************************************************/ 168 169 // --> OD 2006-02-01 #130797# 170 // New parameter <_bInvestigateFtnForSections> controls investigation of 171 // content of footnotes for sections. 172 const SwFrm *SwLayoutFrm::ContainsAny( const bool _bInvestigateFtnForSections ) const 173 { 174 //LayoutBlatt nach unten hin suchen und wenn dieses keinen Inhalt hat 175 //solange die weiteren Blatter abklappern bis Inhalt gefunden oder der 176 //this verlassen wird. 177 // Oder bis wir einen SectionFrm oder TabFrm gefunden haben 178 179 const SwLayoutFrm *pLayLeaf = this; 180 // --> OD 2006-02-01 #130797# 181 const bool bNoFtn = IsSctFrm() && !_bInvestigateFtnForSections; 182 // <-- 183 do 184 { 185 while ( ( (!pLayLeaf->IsSctFrm() && !pLayLeaf->IsTabFrm()) 186 || pLayLeaf == this ) && 187 pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrm() ) 188 pLayLeaf = (SwLayoutFrm*)pLayLeaf->Lower(); 189 190 if( ( pLayLeaf->IsTabFrm() || pLayLeaf->IsSctFrm() ) 191 && pLayLeaf != this ) 192 { 193 // Wir liefern jetzt auch "geloeschte" SectionFrms zurueck, 194 // damit diese beim SaveCntnt und RestoreCntnt mitgepflegt werden. 195 return pLayLeaf; 196 } 197 else if ( pLayLeaf->Lower() ) 198 return (SwCntntFrm*)pLayLeaf->Lower(); 199 200 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 201 if( bNoFtn && pLayLeaf && pLayLeaf->IsInFtn() ) 202 { 203 do 204 { 205 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 206 } while( pLayLeaf && pLayLeaf->IsInFtn() ); 207 } 208 if( !IsAnLower( pLayLeaf) ) 209 return 0; 210 } while( pLayLeaf ); 211 return 0; 212 } 213 214 215 /************************************************************************* 216 |* 217 |* SwFrm::GetLower() 218 |* 219 |* Ersterstellung MA 27. Jul. 92 220 |* Letzte Aenderung MA 09. Oct. 97 221 |* 222 |*************************************************************************/ 223 const SwFrm* SwFrm::GetLower() const 224 { 225 return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0; 226 } 227 228 SwFrm* SwFrm::GetLower() 229 { 230 return IsLayoutFrm() ? ((SwLayoutFrm*)this)->Lower() : 0; 231 } 232 233 /************************************************************************* 234 |* 235 |* SwLayoutFrm::IsAnLower() 236 |* 237 |* Ersterstellung MA 18. Mar. 93 238 |* Letzte Aenderung MA 18. Mar. 93 239 |* 240 |*************************************************************************/ 241 sal_Bool SwLayoutFrm::IsAnLower( const SwFrm *pAssumed ) const 242 { 243 const SwFrm *pUp = pAssumed; 244 while ( pUp ) 245 { 246 if ( pUp == this ) 247 return sal_True; 248 if ( pUp->IsFlyFrm() ) 249 pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm(); 250 else 251 pUp = pUp->GetUpper(); 252 } 253 return sal_False; 254 } 255 256 /** method to check relative position of layout frame to 257 a given layout frame. 258 259 OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in 260 <txtftn.cxx> for #104840#. 261 262 @param _aCheckRefLayFrm 263 constant reference of an instance of class <SwLayoutFrm> which 264 is used as the reference for the relative position check. 265 266 @author OD 267 268 @return true, if <this> is positioned before the layout frame <p> 269 */ 270 bool SwLayoutFrm::IsBefore( const SwLayoutFrm* _pCheckRefLayFrm ) const 271 { 272 ASSERT( !IsRootFrm() , "<IsBefore> called at a <SwRootFrm>."); 273 ASSERT( !_pCheckRefLayFrm->IsRootFrm() , "<IsBefore> called with a <SwRootFrm>."); 274 275 bool bReturn; 276 277 // check, if on different pages 278 const SwPageFrm *pMyPage = FindPageFrm(); 279 const SwPageFrm *pCheckRefPage = _pCheckRefLayFrm->FindPageFrm(); 280 if( pMyPage != pCheckRefPage ) 281 { 282 // being on different page as check reference 283 bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum(); 284 } 285 else 286 { 287 // being on same page as check reference 288 // --> search my supreme parent <pUp>, which doesn't contain check reference. 289 const SwLayoutFrm* pUp = this; 290 while ( pUp->GetUpper() && 291 !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrm ) 292 ) 293 pUp = pUp->GetUpper(); 294 if( !pUp->GetUpper() ) 295 { 296 // can occur, if <this> is a fly frm 297 bReturn = false; 298 } 299 else 300 { 301 // travel through the next's of <pUp> and check if one of these 302 // contain the check reference. 303 SwLayoutFrm* pUpNext = (SwLayoutFrm*)pUp->GetNext(); 304 while ( pUpNext && 305 !pUpNext->IsAnLower( _pCheckRefLayFrm ) ) 306 { 307 pUpNext = (SwLayoutFrm*)pUpNext->GetNext(); 308 } 309 bReturn = pUpNext != 0; 310 } 311 } 312 313 return bReturn; 314 } 315 316 // 317 // Local helper functions for GetNextLayoutLeaf 318 // 319 320 const SwFrm* lcl_FindLayoutFrame( const SwFrm* pFrm, bool bNext ) 321 { 322 const SwFrm* pRet = 0; 323 if ( pFrm->IsFlyFrm() ) 324 pRet = bNext ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink(); 325 else 326 pRet = bNext ? pFrm->GetNext() : pFrm->GetPrev(); 327 328 return pRet; 329 } 330 331 const SwFrm* lcl_GetLower( const SwFrm* pFrm, bool bFwd ) 332 { 333 if ( !pFrm->IsLayoutFrm() ) 334 return 0; 335 336 return bFwd ? 337 static_cast<const SwLayoutFrm*>(pFrm)->Lower() : 338 static_cast<const SwLayoutFrm*>(pFrm)->GetLastLower(); 339 } 340 341 /************************************************************************* 342 |* 343 |* SwFrm::ImplGetNextLayoutLeaf 344 |* 345 |* Finds the next layout leaf. This is a layout frame, which does not 346 * have a lower which is a LayoutFrame. That means, pLower can be 0 or a 347 * content frame. 348 * 349 * However, pLower may be a TabFrm 350 * 351 |*************************************************************************/ 352 353 const SwLayoutFrm *SwFrm::ImplGetNextLayoutLeaf( bool bFwd ) const 354 { 355 const SwFrm *pFrm = this; 356 const SwLayoutFrm *pLayoutFrm = 0; 357 const SwFrm *p = 0; 358 bool bGoingUp = !bFwd; // false for forward, true for backward 359 do { 360 361 bool bGoingFwdOrBwd = false, bGoingDown = false; 362 363 bGoingDown = ( !bGoingUp && ( 0 != (p = lcl_GetLower( pFrm, bFwd ) ) ) ); 364 if ( !bGoingDown ) 365 { 366 // I cannot go down, because either I'm currently going up or 367 // because the is no lower. 368 // I'll try to go forward: 369 bGoingFwdOrBwd = (0 != (p = lcl_FindLayoutFrame( pFrm, bFwd ) ) ); 370 if ( !bGoingFwdOrBwd ) 371 { 372 // I cannot go forward, because there is no next frame. 373 // I'll try to go up: 374 bGoingUp = (0 != (p = pFrm->GetUpper() ) ); 375 if ( !bGoingUp ) 376 { 377 // I cannot go up, because there is no upper frame. 378 return 0; 379 } 380 } 381 } 382 383 // If I could not go down or forward, I'll have to go up 384 bGoingUp = !bGoingFwdOrBwd && !bGoingDown; 385 386 pFrm = p; 387 p = lcl_GetLower( pFrm, true ); 388 389 } while( ( p && !p->IsFlowFrm() ) || 390 pFrm == this || 391 0 == ( pLayoutFrm = pFrm->IsLayoutFrm() ? (SwLayoutFrm*)pFrm : 0 ) || 392 pLayoutFrm->IsAnLower( this ) ); 393 394 return pLayoutFrm; 395 } 396 397 398 399 /************************************************************************* 400 |* 401 |* SwFrm::ImplGetNextCntntFrm( bool ) 402 |* 403 |* Rueckwaertswandern im Baum: Den untergeordneten Frm greifen, 404 |* wenn es einen gibt und nicht gerade zuvor um eine Ebene 405 |* aufgestiegen wurde (das wuerde zu einem endlosen Auf und Ab 406 |* fuehren!). Damit wird sichergestellt, dass beim 407 |* Rueckwaertswandern alle Unterbaeume durchsucht werden. Wenn 408 |* abgestiegen wurde, wird zuerst an das Ende der Kette gegangen, 409 |* weil im weiteren ja vom letzten Frm innerhalb eines anderen 410 |* Frms rueckwaerts gegangen wird. 411 |* Vorwaetzwander funktioniert analog. 412 |* 413 |* Ersterstellung ?? 414 |* Letzte Aenderung MA 30. Oct. 97 415 |* 416 |*************************************************************************/ 417 418 // Achtung: Fixes in ImplGetNextCntntFrm() muessen moeglicherweise auch in 419 // die weiter oben stehende Methode lcl_NextFrm(..) eingepflegt werden 420 const SwCntntFrm* SwCntntFrm::ImplGetNextCntntFrm( bool bFwd ) const 421 { 422 const SwFrm *pFrm = this; 423 // #100926# 424 SwCntntFrm *pCntntFrm = 0; 425 sal_Bool bGoingUp = sal_False; 426 do { 427 const SwFrm *p = 0; 428 sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False; 429 430 bGoingDown = ( !bGoingUp && ( 0 != ( p = lcl_GetLower( pFrm, true ) ) ) ); 431 if ( !bGoingDown ) 432 { 433 bGoingFwdOrBwd = ( 0 != ( p = lcl_FindLayoutFrame( pFrm, bFwd ) ) ); 434 if ( !bGoingFwdOrBwd ) 435 { 436 bGoingUp = ( 0 != ( p = pFrm->GetUpper() ) ); 437 if ( !bGoingUp ) 438 { 439 return 0; 440 } 441 } 442 } 443 444 bGoingUp = !(bGoingFwdOrBwd || bGoingDown); 445 446 if ( !bFwd ) 447 { 448 if( bGoingDown && p ) 449 while ( p->GetNext() ) 450 p = p->GetNext(); 451 } 452 453 pFrm = p; 454 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) )); 455 456 return pCntntFrm; 457 } 458 459 460 461 462 /************************************************************************* 463 |* 464 |* SwFrm::FindRootFrm(), FindTabFrm(), FindFtnFrm(), FindFlyFrm(), 465 |* FindPageFrm(), FindColFrm() 466 |* 467 |* Ersterstellung ?? 468 |* Letzte Aenderung MA 05. Sep. 93 469 |* 470 |*************************************************************************/ 471 SwPageFrm* SwFrm::FindPageFrm() 472 { 473 SwFrm *pRet = this; 474 while ( pRet && !pRet->IsPageFrm() ) 475 { 476 if ( pRet->GetUpper() ) 477 pRet = pRet->GetUpper(); 478 else if ( pRet->IsFlyFrm() ) 479 { 480 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 481 if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() ) 482 pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm(); 483 else 484 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm(); 485 } 486 else 487 return 0; 488 } 489 return (SwPageFrm*)pRet; 490 } 491 492 SwFtnBossFrm* SwFrm::FindFtnBossFrm( sal_Bool bFootnotes ) 493 { 494 SwFrm *pRet = this; 495 // Innerhalb einer Tabelle gibt es keine Fussnotenbosse, auch spaltige 496 // Bereiche enthalten dort keine Fussnotentexte 497 if( pRet->IsInTab() ) 498 pRet = pRet->FindTabFrm(); 499 while ( pRet && !pRet->IsFtnBossFrm() ) 500 { 501 if ( pRet->GetUpper() ) 502 pRet = pRet->GetUpper(); 503 else if ( pRet->IsFlyFrm() ) 504 { 505 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 506 if ( static_cast<SwFlyFrm*>(pRet)->GetPageFrm() ) 507 pRet = static_cast<SwFlyFrm*>(pRet)->GetPageFrm(); 508 else 509 pRet = static_cast<SwFlyFrm*>(pRet)->AnchorFrm(); 510 } 511 else 512 return 0; 513 } 514 if( bFootnotes && pRet && pRet->IsColumnFrm() && 515 !pRet->GetNext() && !pRet->GetPrev() ) 516 { 517 SwSectionFrm* pSct = pRet->FindSctFrm(); 518 ASSERT( pSct, "FindFtnBossFrm: Single column outside section?" ); 519 if( !pSct->IsFtnAtEnd() ) 520 return pSct->FindFtnBossFrm( sal_True ); 521 } 522 return (SwFtnBossFrm*)pRet; 523 } 524 525 SwTabFrm* SwFrm::ImplFindTabFrm() 526 { 527 SwFrm *pRet = this; 528 while ( !pRet->IsTabFrm() ) 529 { 530 pRet = pRet->GetUpper(); 531 if ( !pRet ) 532 return 0; 533 } 534 return (SwTabFrm*)pRet; 535 } 536 537 SwSectionFrm* SwFrm::ImplFindSctFrm() 538 { 539 SwFrm *pRet = this; 540 while ( !pRet->IsSctFrm() ) 541 { 542 pRet = pRet->GetUpper(); 543 if ( !pRet ) 544 return 0; 545 } 546 return (SwSectionFrm*)pRet; 547 } 548 549 SwFtnFrm *SwFrm::ImplFindFtnFrm() 550 { 551 SwFrm *pRet = this; 552 while ( !pRet->IsFtnFrm() ) 553 { 554 pRet = pRet->GetUpper(); 555 if ( !pRet ) 556 return 0; 557 } 558 return (SwFtnFrm*)pRet; 559 } 560 561 SwFlyFrm *SwFrm::ImplFindFlyFrm() 562 { 563 const SwFrm *pRet = this; 564 do 565 { 566 if ( pRet->IsFlyFrm() ) 567 return (SwFlyFrm*)pRet; 568 else 569 pRet = pRet->GetUpper(); 570 } while ( pRet ); 571 return 0; 572 } 573 574 SwFrm *SwFrm::FindColFrm() 575 { 576 SwFrm *pFrm = this; 577 do 578 { pFrm = pFrm->GetUpper(); 579 } while ( pFrm && !pFrm->IsColumnFrm() ); 580 return pFrm; 581 } 582 583 SwFrm* SwFrm::FindFooterOrHeader() 584 { 585 SwFrm* pRet = this; 586 do 587 { if ( pRet->GetType() & 0x0018 ) //Header und Footer 588 return pRet; 589 else if ( pRet->GetUpper() ) 590 pRet = pRet->GetUpper(); 591 else if ( pRet->IsFlyFrm() ) 592 pRet = ((SwFlyFrm*)pRet)->AnchorFrm(); 593 else 594 return 0; 595 } while ( pRet ); 596 return pRet; 597 } 598 599 const SwFtnFrm* SwFtnContFrm::FindFootNote() const 600 { 601 const SwFtnFrm* pRet = (SwFtnFrm*)Lower(); 602 if( pRet && !pRet->GetAttr()->GetFtn().IsEndNote() ) 603 return pRet; 604 return NULL; 605 } 606 607 const SwPageFrm* SwRootFrm::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const 608 { 609 const SwPageFrm* pRet = 0; 610 611 SwRect aRect; 612 if ( pSize ) 613 { 614 aRect.Pos() = rPt; 615 aRect.SSize() = *pSize; 616 } 617 618 const SwFrm* pPage = Lower(); 619 620 if ( !bExtend ) 621 { 622 if( !Frm().IsInside( rPt ) ) 623 return 0; 624 625 // skip pages above point: 626 while( pPage && rPt.Y() > pPage->Frm().Bottom() ) 627 pPage = pPage->GetNext(); 628 } 629 630 ASSERT( GetPageNum() <= maPageRects.size(), "number of pages differes from page rect array size" ) 631 sal_uInt16 nPageIdx = 0; 632 633 while ( pPage && !pRet ) 634 { 635 const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->Frm(); 636 637 if ( (!pSize && rBoundRect.IsInside(rPt)) || 638 (pSize && rBoundRect.IsOver(aRect)) ) 639 { 640 pRet = static_cast<const SwPageFrm*>(pPage); 641 } 642 643 pPage = pPage->GetNext(); 644 } 645 646 return pRet; 647 } 648 649 /************************************************************************* 650 |* 651 |* SwFrmFrm::GetAttrSet() 652 |* 653 |* Ersterstellung MA 02. Aug. 93 654 |* Letzte Aenderung MA 02. Aug. 93 655 |* 656 |*************************************************************************/ 657 const SwAttrSet* SwFrm::GetAttrSet() const 658 { 659 if ( IsCntntFrm() ) 660 return &((const SwCntntFrm*)this)->GetNode()->GetSwAttrSet(); 661 else 662 return &((const SwLayoutFrm*)this)->GetFmt()->GetAttrSet(); 663 } 664 665 /************************************************************************* 666 |* 667 |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos() 668 |* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert 669 |* nur SwCntntFrms. 670 |* 671 |* Beschreibung Invalidiert die Position des Naechsten Frames. 672 |* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste 673 |* CntntFrm der im gleichen Fluss liegt wie ich: 674 |* - Body, 675 |* - Fussnoten, 676 |* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des 677 |* Bereiches weiterzuleiten. 678 |* - dito fuer Flys. 679 |* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle 680 |* auf. 681 |* - Tabellen verhalten sich prinzipiell analog zu den Cntnts 682 |* - Bereiche ebenfalls 683 |* Ersterstellung AK 14-Feb-1991 684 |* Letzte Aenderung AMA 10. Mar. 99 685 |* 686 |*************************************************************************/ 687 688 // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode, 689 // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms. 690 SwFrm* lcl_NextFrm( SwFrm* pFrm ) 691 { 692 SwFrm *pRet = 0; 693 sal_Bool bGoingUp = sal_False; 694 do { 695 SwFrm *p = 0; 696 697 sal_Bool bGoingFwd = sal_False; 698 sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0))); 699 700 if( !bGoingDown ) 701 { 702 bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext()))); 703 if ( !bGoingFwd ) 704 { 705 bGoingUp = (0 != (p = pFrm->GetUpper())); 706 if ( !bGoingUp ) 707 { 708 return 0; 709 } 710 } 711 } 712 bGoingUp = !(bGoingFwd || bGoingDown); 713 pFrm = p; 714 } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp && 715 ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) ); 716 return pRet; 717 } 718 719 SwFrm *SwFrm::_FindNext() 720 { 721 sal_Bool bIgnoreTab = sal_False; 722 SwFrm *pThis = this; 723 724 if ( IsTabFrm() ) 725 { 726 //Der letzte Cntnt der Tabelle wird 727 //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh. 728 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. 729 if ( ((SwTabFrm*)this)->GetFollow() ) 730 return ((SwTabFrm*)this)->GetFollow(); 731 732 pThis = ((SwTabFrm*)this)->FindLastCntnt(); 733 if ( !pThis ) 734 pThis = this; 735 bIgnoreTab = sal_True; 736 } 737 else if ( IsSctFrm() ) 738 { 739 //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger 740 // geliefert. 741 if ( ((SwSectionFrm*)this)->GetFollow() ) 742 return ((SwSectionFrm*)this)->GetFollow(); 743 744 pThis = ((SwSectionFrm*)this)->FindLastCntnt(); 745 if ( !pThis ) 746 pThis = this; 747 } 748 else if ( IsCntntFrm() ) 749 { 750 if( ((SwCntntFrm*)this)->GetFollow() ) 751 return ((SwCntntFrm*)this)->GetFollow(); 752 } 753 else if ( IsRowFrm() ) 754 { 755 SwFrm* pMyUpper = GetUpper(); 756 if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() ) 757 return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower(); 758 else return NULL; 759 } 760 else 761 return NULL; 762 763 SwFrm* pRet = NULL; 764 const sal_Bool bFtn = pThis->IsInFtn(); 765 if ( !bIgnoreTab && pThis->IsInTab() ) 766 { 767 SwLayoutFrm *pUp = pThis->GetUpper(); 768 while ( !pUp->IsCellFrm() ) 769 pUp = pUp->GetUpper(); 770 ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); 771 SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell(); 772 if ( pNxt ) 773 pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt(); 774 if ( !pNxt ) 775 { 776 pNxt = lcl_NextFrm( pThis ); 777 if ( pUp->IsAnLower( pNxt ) ) 778 pRet = pNxt; 779 } 780 else 781 pRet = pNxt; 782 } 783 else 784 { 785 const sal_Bool bBody = pThis->IsInDocBody(); 786 SwFrm *pNxtCnt = lcl_NextFrm( pThis ); 787 if ( pNxtCnt ) 788 { 789 if ( bBody || bFtn ) 790 { 791 while ( pNxtCnt ) 792 { 793 // OD 02.04.2003 #108446# - check for endnote, only if found 794 // next content isn't contained in a section, that collect its 795 // endnotes at its end. 796 bool bEndn = IsInSct() && !IsSctFrm() && 797 ( !pNxtCnt->IsInSct() || 798 !pNxtCnt->FindSctFrm()->IsEndnAtEnd() 799 ); 800 if ( ( bBody && pNxtCnt->IsInDocBody() ) || 801 ( pNxtCnt->IsInFtn() && 802 ( bFtn || 803 ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() ) 804 ) 805 ) 806 ) 807 { 808 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 809 : (SwFrm*)pNxtCnt; 810 break; 811 } 812 pNxtCnt = lcl_NextFrm( pNxtCnt ); 813 } 814 } 815 else if ( pThis->IsInFly() ) 816 { 817 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 818 : (SwFrm*)pNxtCnt; 819 } 820 else //Fuss-/oder Kopfbereich 821 { 822 const SwFrm *pUp = pThis->GetUpper(); 823 const SwFrm *pCntUp = pNxtCnt->GetUpper(); 824 while ( pUp && pUp->GetUpper() && 825 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 826 pUp = pUp->GetUpper(); 827 while ( pCntUp && pCntUp->GetUpper() && 828 !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) 829 pCntUp = pCntUp->GetUpper(); 830 if ( pCntUp == pUp ) 831 { 832 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 833 : (SwFrm*)pNxtCnt; 834 } 835 } 836 } 837 } 838 if( pRet && pRet->IsInSct() ) 839 { 840 SwSectionFrm* pSct = pRet->FindSctFrm(); 841 //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich 842 //liefern, der die Fussnoten umfasst 843 if( !pSct->IsAnLower( this ) && 844 (!bFtn || pSct->IsInFtn() ) ) 845 return pSct; 846 } 847 return pRet; 848 } 849 850 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn> 851 SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn ) 852 { 853 SwFrm *pThis = this; 854 855 if ( IsTabFrm() ) 856 { 857 if ( ((SwTabFrm*)this)->GetFollow() ) 858 { 859 pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt(); 860 if( pThis ) 861 return (SwCntntFrm*)pThis; 862 } 863 pThis = ((SwTabFrm*)this)->FindLastCntnt(); 864 if ( !pThis ) 865 return 0; 866 } 867 else if ( IsSctFrm() ) 868 { 869 if ( ((SwSectionFrm*)this)->GetFollow() ) 870 { 871 pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt(); 872 if( pThis ) 873 return (SwCntntFrm*)pThis; 874 } 875 pThis = ((SwSectionFrm*)this)->FindLastCntnt(); 876 if ( !pThis ) 877 return 0; 878 } 879 else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() ) 880 return ((SwCntntFrm*)this)->GetFollow(); 881 882 if ( pThis->IsCntntFrm() ) 883 { 884 const sal_Bool bBody = pThis->IsInDocBody(); 885 const sal_Bool bFtn = pThis->IsInFtn(); 886 SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm(); 887 if ( pNxtCnt ) 888 { 889 // --> OD 2005-12-01 #i27138# 890 if ( bBody || ( bFtn && !_bInSameFtn ) ) 891 // <-- 892 { 893 // handling for environments 'footnotes' and 'document body frames': 894 while ( pNxtCnt ) 895 { 896 if ( (bBody && pNxtCnt->IsInDocBody()) || 897 (bFtn && pNxtCnt->IsInFtn()) ) 898 return pNxtCnt; 899 pNxtCnt = pNxtCnt->GetNextCntntFrm(); 900 } 901 } 902 // --> OD 2005-12-01 #i27138# 903 else if ( bFtn && _bInSameFtn ) 904 { 905 // handling for environments 'each footnote': 906 // Assure that found next content frame belongs to the same footnotes 907 const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() ); 908 const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() ); 909 ASSERT( pFtnFrmOfCurr, 910 "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." ); 911 if ( pFtnFrmOfNext == pFtnFrmOfCurr ) 912 { 913 return pNxtCnt; 914 } 915 else if ( pFtnFrmOfCurr->GetFollow() ) 916 { 917 // next content frame has to be the first content frame 918 // in the follow footnote, which contains a content frame. 919 SwFtnFrm* pFollowFtnFrmOfCurr( 920 const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); 921 pNxtCnt = 0L; 922 do { 923 pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow(); 924 pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt(); 925 } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() ); 926 return pNxtCnt; 927 } 928 else 929 { 930 // current content frame is the last content frame in the 931 // footnote - no next content frame exists. 932 return 0L; 933 } 934 } 935 // <-- 936 else if ( pThis->IsInFly() ) 937 // handling for environments 'unlinked fly frame' and 938 // 'group of linked fly frames': 939 return pNxtCnt; 940 else 941 { 942 // handling for environments 'page header' and 'page footer': 943 const SwFrm *pUp = pThis->GetUpper(); 944 const SwFrm *pCntUp = pNxtCnt->GetUpper(); 945 while ( pUp && pUp->GetUpper() && 946 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 947 pUp = pUp->GetUpper(); 948 while ( pCntUp && pCntUp->GetUpper() && 949 !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) 950 pCntUp = pCntUp->GetUpper(); 951 if ( pCntUp == pUp ) 952 return pNxtCnt; 953 } 954 } 955 } 956 return 0; 957 } 958 959 /** method to determine previous content frame in the same environment 960 for a flow frame (content frame, table frame, section frame) 961 962 OD 2005-11-30 #i27138# 963 964 @author OD 965 */ 966 SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn ) 967 { 968 if ( !IsFlowFrm() ) 969 { 970 // nothing to do, if current frame isn't a flow frame. 971 return 0L; 972 } 973 974 SwCntntFrm* pPrevCntntFrm( 0L ); 975 976 // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel 977 // through the layout, a content frame, at which the travel starts, is needed. 978 SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this); 979 980 // perform shortcut, if current frame is a follow, and 981 // determine <pCurrCntntFrm>, if current frame is a table or section frame 982 if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() ) 983 { 984 // previous content frame is its master content frame 985 pPrevCntntFrm = pCurrCntntFrm->FindMaster(); 986 } 987 else if ( IsTabFrm() ) 988 { 989 SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) ); 990 if ( pTabFrm->IsFollow() ) 991 { 992 // previous content frame is the last content of its master table frame 993 pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt(); 994 } 995 else 996 { 997 // start content frame for the search is the first content frame of 998 // the table frame. 999 pCurrCntntFrm = pTabFrm->ContainsCntnt(); 1000 } 1001 } 1002 else if ( IsSctFrm() ) 1003 { 1004 SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) ); 1005 if ( pSectFrm->IsFollow() ) 1006 { 1007 // previous content frame is the last content of its master section frame 1008 pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt(); 1009 } 1010 else 1011 { 1012 // start content frame for the search is the first content frame of 1013 // the section frame. 1014 pCurrCntntFrm = pSectFrm->ContainsCntnt(); 1015 } 1016 } 1017 1018 // search for next content frame, depending on the environment, in which 1019 // the current frame is in. 1020 if ( !pPrevCntntFrm && pCurrCntntFrm ) 1021 { 1022 pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm(); 1023 if ( pPrevCntntFrm ) 1024 { 1025 if ( pCurrCntntFrm->IsInFly() ) 1026 { 1027 // handling for environments 'unlinked fly frame' and 1028 // 'group of linked fly frames': 1029 // Nothing to do, <pPrevCntntFrm> is the one 1030 } 1031 else 1032 { 1033 const bool bInDocBody = pCurrCntntFrm->IsInDocBody(); 1034 const bool bInFtn = pCurrCntntFrm->IsInFtn(); 1035 if ( bInDocBody || ( bInFtn && !_bInSameFtn ) ) 1036 { 1037 // handling for environments 'footnotes' and 'document body frames': 1038 // Assure that found previous frame is also in one of these 1039 // environments. Otherwise, travel further 1040 while ( pPrevCntntFrm ) 1041 { 1042 if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) || 1043 ( bInFtn && pPrevCntntFrm->IsInFtn() ) ) 1044 { 1045 break; 1046 } 1047 pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm(); 1048 } 1049 } 1050 else if ( bInFtn && _bInSameFtn ) 1051 { 1052 // handling for environments 'each footnote': 1053 // Assure that found next content frame belongs to the same footnotes 1054 const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() ); 1055 const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() ); 1056 if ( pFtnFrmOfPrev != pFtnFrmOfCurr ) 1057 { 1058 if ( pFtnFrmOfCurr->GetMaster() ) 1059 { 1060 SwFtnFrm* pMasterFtnFrmOfCurr( 1061 const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); 1062 pPrevCntntFrm = 0L; 1063 // --> OD 2007-07-05 #146872# 1064 // correct wrong loop-condition 1065 do { 1066 pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster(); 1067 pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt(); 1068 } while ( !pPrevCntntFrm && 1069 pMasterFtnFrmOfCurr->GetMaster() ); 1070 // <-- 1071 } 1072 else 1073 { 1074 // current content frame is the first content in the 1075 // footnote - no previous content exists. 1076 pPrevCntntFrm = 0L;; 1077 } 1078 } 1079 } 1080 else 1081 { 1082 // handling for environments 'page header' and 'page footer': 1083 // Assure that found previous frame is also in the same 1084 // page header respectively page footer as <pCurrCntntFrm> 1085 // Note: At this point its clear, that <pCurrCntntFrm> has 1086 // to be inside a page header or page footer and that 1087 // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are 1088 // inside a fly frame. 1089 // Thus, method <FindFooterOrHeader()> can be used. 1090 ASSERT( pCurrCntntFrm->FindFooterOrHeader(), 1091 "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" ); 1092 ASSERT( !pPrevCntntFrm->IsInFly(), 1093 "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." ); 1094 if ( pPrevCntntFrm->FindFooterOrHeader() != 1095 pCurrCntntFrm->FindFooterOrHeader() ) 1096 { 1097 pPrevCntntFrm = 0L; 1098 } 1099 } 1100 } 1101 } 1102 } 1103 1104 return pPrevCntntFrm; 1105 } 1106 1107 SwFrm *SwFrm::_FindPrev() 1108 { 1109 sal_Bool bIgnoreTab = sal_False; 1110 SwFrm *pThis = this; 1111 1112 if ( IsTabFrm() ) 1113 { 1114 //Der erste Cntnt der Tabelle wird 1115 //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh. 1116 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. 1117 if ( ((SwTabFrm*)this)->IsFollow() ) 1118 return ((SwTabFrm*)this)->FindMaster(); 1119 else 1120 pThis = ((SwTabFrm*)this)->ContainsCntnt(); 1121 bIgnoreTab = sal_True; 1122 } 1123 1124 if ( pThis && pThis->IsCntntFrm() ) 1125 { 1126 SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm(); 1127 if( !pPrvCnt ) 1128 return 0; 1129 if ( !bIgnoreTab && pThis->IsInTab() ) 1130 { 1131 SwLayoutFrm *pUp = pThis->GetUpper(); 1132 while ( !pUp->IsCellFrm() ) 1133 pUp = pUp->GetUpper(); 1134 ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); 1135 if ( pUp->IsAnLower( pPrvCnt ) ) 1136 return pPrvCnt; 1137 } 1138 else 1139 { 1140 SwFrm* pRet; 1141 const sal_Bool bBody = pThis->IsInDocBody(); 1142 const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn(); 1143 if ( bBody || bFtn ) 1144 { 1145 while ( pPrvCnt ) 1146 { 1147 if ( (bBody && pPrvCnt->IsInDocBody()) || 1148 (bFtn && pPrvCnt->IsInFtn()) ) 1149 { 1150 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1151 : (SwFrm*)pPrvCnt; 1152 return pRet; 1153 } 1154 pPrvCnt = pPrvCnt->GetPrevCntntFrm(); 1155 } 1156 } 1157 else if ( pThis->IsInFly() ) 1158 { 1159 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1160 : (SwFrm*)pPrvCnt; 1161 return pRet; 1162 } 1163 else //Fuss-/oder Kopfbereich oder Fly 1164 { 1165 const SwFrm *pUp = pThis->GetUpper(); 1166 const SwFrm *pCntUp = pPrvCnt->GetUpper(); 1167 while ( pUp && pUp->GetUpper() && 1168 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 1169 pUp = pUp->GetUpper(); 1170 while ( pCntUp && pCntUp->GetUpper() ) 1171 pCntUp = pCntUp->GetUpper(); 1172 if ( pCntUp == pUp ) 1173 { 1174 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1175 : (SwFrm*)pPrvCnt; 1176 return pRet; 1177 } 1178 } 1179 } 1180 } 1181 return 0; 1182 } 1183 1184 void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn ) 1185 { 1186 SwFrm *pFrm; 1187 if ( 0 != (pFrm = _FindNext()) ) 1188 { 1189 if( pFrm->IsSctFrm() ) 1190 { 1191 while( pFrm && pFrm->IsSctFrm() ) 1192 { 1193 if( ((SwSectionFrm*)pFrm)->GetSection() ) 1194 { 1195 SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); 1196 if( pTmp ) 1197 pTmp->InvalidatePos(); 1198 else if( !bNoFtn ) 1199 ((SwSectionFrm*)pFrm)->InvalidateFtnPos(); 1200 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) 1201 pFrm->InvalidatePos(); 1202 return; 1203 } 1204 pFrm = pFrm->FindNext(); 1205 } 1206 if( pFrm ) 1207 { 1208 if ( pFrm->IsSctFrm()) 1209 { // Damit der Inhalt eines Bereichs die Chance erhaelt, 1210 // die Seite zu wechseln, muss er ebenfalls invalidiert werden. 1211 SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); 1212 if( pTmp ) 1213 pTmp->InvalidatePos(); 1214 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) 1215 pFrm->InvalidatePos(); 1216 } 1217 else 1218 pFrm->InvalidatePos(); 1219 } 1220 } 1221 else 1222 pFrm->InvalidatePos(); 1223 } 1224 } 1225 1226 /** method to invalidate printing area of next frame 1227 1228 OD 09.01.2004 #i11859# 1229 1230 @author OD 1231 1232 FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm 1233 */ 1234 void SwFrm::InvalidateNextPrtArea() 1235 { 1236 // determine next frame 1237 SwFrm* pNextFrm = FindNext(); 1238 // skip empty section frames and hidden text frames 1239 { 1240 while ( pNextFrm && 1241 ( ( pNextFrm->IsSctFrm() && 1242 !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) || 1243 ( pNextFrm->IsTxtFrm() && 1244 static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) ) 1245 { 1246 pNextFrm = pNextFrm->FindNext(); 1247 } 1248 } 1249 1250 // Invalidate printing area of found next frame 1251 if ( pNextFrm ) 1252 { 1253 if ( pNextFrm->IsSctFrm() ) 1254 { 1255 // Invalidate printing area of found section frame, if 1256 // (1) this text frame isn't in a section OR 1257 // (2) found section frame isn't a follow of the section frame this 1258 // text frame is in. 1259 if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm ) 1260 { 1261 pNextFrm->InvalidatePrt(); 1262 } 1263 1264 // Invalidate printing area of first content in found section. 1265 SwFrm* pFstCntntOfSctFrm = 1266 static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny(); 1267 if ( pFstCntntOfSctFrm ) 1268 { 1269 pFstCntntOfSctFrm->InvalidatePrt(); 1270 } 1271 } 1272 else 1273 { 1274 pNextFrm->InvalidatePrt(); 1275 } 1276 } 1277 } 1278 1279 /************************************************************************* 1280 |* 1281 |* lcl_IsInColSect() 1282 |* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht, 1283 |* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist. 1284 |* 1285 |*************************************************************************/ 1286 1287 sal_Bool lcl_IsInColSct( const SwFrm *pUp ) 1288 { 1289 sal_Bool bRet = sal_False; 1290 while( pUp ) 1291 { 1292 if( pUp->IsColumnFrm() ) 1293 bRet = sal_True; 1294 else if( pUp->IsSctFrm() ) 1295 return bRet; 1296 else if( pUp->IsTabFrm() ) 1297 return sal_False; 1298 pUp = pUp->GetUpper(); 1299 } 1300 return sal_False; 1301 } 1302 1303 /************************************************************************* 1304 |* 1305 |* SwFrm::IsMoveable(); 1306 |* 1307 |* Ersterstellung MA 09. Mar. 93 1308 |* Letzte Aenderung MA 05. May. 95 1309 |* 1310 |*************************************************************************/ 1311 /** determine, if frame is moveable in given environment 1312 1313 OD 08.08.2003 #110978# 1314 method replaced 'old' method <sal_Bool IsMoveable() const>. 1315 Determines, if frame is moveable in given environment. if no environment 1316 is given (parameter _pLayoutFrm == 0L), the movability in the actual 1317 environment (<this->GetUpper()) is checked. 1318 1319 @author OD 1320 */ 1321 1322 bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const 1323 { 1324 bool bRetVal = false; 1325 1326 if ( !_pLayoutFrm ) 1327 { 1328 _pLayoutFrm = GetUpper(); 1329 } 1330 1331 if ( _pLayoutFrm && IsFlowFrm() ) 1332 { 1333 if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) ) 1334 { 1335 bRetVal = true; 1336 } 1337 else if ( _pLayoutFrm->IsInFly() || 1338 _pLayoutFrm->IsInDocBody() || 1339 _pLayoutFrm->IsInFtn() ) 1340 { 1341 if ( _pLayoutFrm->IsInTab() && !IsTabFrm() && 1342 ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) ) 1343 { 1344 bRetVal = false; 1345 } 1346 else 1347 { 1348 if ( _pLayoutFrm->IsInFly() ) 1349 { 1350 // if fly frame has a follow (next linked fly frame), 1351 // frame is moveable. 1352 if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() ) 1353 { 1354 bRetVal = true; 1355 } 1356 else 1357 { 1358 // if environment is columned, frame is moveable, if 1359 // it isn't in last column. 1360 // search for column frame 1361 const SwFrm* pCol = _pLayoutFrm; 1362 while ( pCol && !pCol->IsColumnFrm() ) 1363 { 1364 pCol = pCol->GetUpper(); 1365 } 1366 // frame is moveable, if found column frame isn't last one. 1367 if ( pCol && pCol->GetNext() ) 1368 { 1369 bRetVal = true; 1370 } 1371 } 1372 } 1373 else 1374 { 1375 bRetVal = true; 1376 } 1377 } 1378 } 1379 } 1380 1381 return bRetVal; 1382 } 1383 1384 /************************************************************************* 1385 |* 1386 |* SwFrm::SetInfFlags(); 1387 |* 1388 |* Ersterstellung MA 05. Apr. 94 1389 |* Letzte Aenderung MA 05. Apr. 94 1390 |* 1391 |*************************************************************************/ 1392 void SwFrm::SetInfFlags() 1393 { 1394 if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen 1395 return; //lieferbar 1396 1397 bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False; 1398 1399 SwFrm *pFrm = this; 1400 if( IsFtnContFrm() ) 1401 bInfFtn = sal_True; 1402 do 1403 { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt 1404 if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper() 1405 && pFrm->GetUpper()->IsPageFrm() ) 1406 bInfBody = sal_True; 1407 else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() ) 1408 { 1409 bInfTab = sal_True; 1410 } 1411 else if ( pFrm->IsFlyFrm() ) 1412 bInfFly = sal_True; 1413 else if ( pFrm->IsSctFrm() ) 1414 bInfSct = sal_True; 1415 else if ( pFrm->IsFtnFrm() ) 1416 bInfFtn = sal_True; 1417 1418 pFrm = pFrm->GetUpper(); 1419 1420 } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix 1421 } 1422 1423 /*-----------------22.8.2001 14:30------------------ 1424 * SwFrm::SetDirFlags( sal_Bool ) 1425 * actualizes the vertical or the righttoleft-flags. 1426 * If the property is derived, it's from the upper or (for fly frames) from 1427 * the anchor. Otherwise we've to call a virtual method to check the property. 1428 * --------------------------------------------------*/ 1429 1430 void SwFrm::SetDirFlags( sal_Bool bVert ) 1431 { 1432 if( bVert ) 1433 { 1434 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if 1435 // vertical flag of upper/anchor is valid. 1436 if( bDerivedVert ) 1437 { 1438 const SwFrm* pAsk = IsFlyFrm() ? 1439 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); 1440 1441 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) 1442 1443 if( pAsk ) 1444 { 1445 bVertical = pAsk->IsVertical() ? 1 : 0; 1446 bReverse = pAsk->IsReverse() ? 1 : 0; 1447 1448 bVertLR = pAsk->IsVertLR() ? 1 : 0; 1449 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1450 if ( !pAsk->bInvalidVert ) 1451 bInvalidVert = sal_False; 1452 } 1453 } 1454 else 1455 CheckDirection( bVert ); 1456 } 1457 else 1458 { 1459 sal_Bool bInv = 0; 1460 if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L! 1461 CheckDirection( bVert ); 1462 if( bDerivedR2L ) 1463 { 1464 const SwFrm* pAsk = IsFlyFrm() ? 1465 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); 1466 1467 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) 1468 1469 if( pAsk ) 1470 bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0; 1471 if( !pAsk || pAsk->bInvalidR2L ) 1472 bInv = bInvalidR2L; 1473 } 1474 bInvalidR2L = bInv; 1475 } 1476 } 1477 1478 SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType ) 1479 { 1480 SwFrm* pTmpFrm = this; 1481 while ( !pTmpFrm->IsCellFrm() ) 1482 pTmpFrm = pTmpFrm->GetUpper(); 1483 1484 ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" ) 1485 return ((SwCellFrm*)pTmpFrm)->GetFollowCell(); 1486 } 1487 1488 SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType ) 1489 { 1490 SwFrm* pTmpFrm = this; 1491 while ( !pTmpFrm->IsCellFrm() ) 1492 pTmpFrm = pTmpFrm->GetUpper(); 1493 1494 ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" ) 1495 return ((SwCellFrm*)pTmpFrm)->GetPreviousCell(); 1496 } 1497 1498 SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow, 1499 const SwCellFrm& rOrigCell, 1500 const SwRowFrm& rCorrRow, 1501 bool bInFollow ) 1502 { 1503 SwCellFrm* pRet = NULL; 1504 SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower(); 1505 SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower(); 1506 1507 while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) ) 1508 { 1509 pCell = (SwCellFrm*)pCell->GetNext(); 1510 pCorrCell = (SwCellFrm*)pCorrCell->GetNext(); 1511 } 1512 1513 ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" ) 1514 1515 if ( pCell != &rOrigCell ) 1516 { 1517 // rOrigCell must be a lower of pCell. We need to recurse into the rows: 1518 ASSERT( pCell->Lower() && pCell->Lower()->IsRowFrm(), 1519 "lcl_FindCorrespondingCellFrm does not work" ) 1520 1521 SwRowFrm* pRow = (SwRowFrm*)pCell->Lower(); 1522 while ( !pRow->IsAnLower( &rOrigCell ) ) 1523 pRow = (SwRowFrm*)pRow->GetNext(); 1524 1525 SwRowFrm* pCorrRow = 0; 1526 if ( bInFollow ) 1527 pCorrRow = pRow->GetFollowRow(); 1528 else 1529 { 1530 SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower()); 1531 1532 if ( pTmpRow && pTmpRow->GetFollowRow() == pRow ) 1533 pCorrRow = pTmpRow; 1534 } 1535 1536 if ( pCorrRow ) 1537 pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow ); 1538 } 1539 else 1540 pRet = pCorrCell; 1541 1542 return pRet; 1543 } 1544 1545 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line: 1546 SwCellFrm* SwCellFrm::GetFollowCell() const 1547 { 1548 SwCellFrm* pRet = NULL; 1549 1550 // NEW TABLES 1551 // Covered cells do not have follow cells! 1552 const long nRowSpan = GetLayoutRowSpan(); 1553 if ( nRowSpan < 1 ) 1554 return NULL; 1555 1556 // find most upper row frame 1557 const SwFrm* pRow = GetUpper(); 1558 while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) 1559 pRow = pRow->GetUpper(); 1560 1561 if ( !pRow ) 1562 return NULL; 1563 1564 const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() ); 1565 if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() ) 1566 return NULL; 1567 1568 const SwCellFrm* pThisCell = this; 1569 1570 // Get last cell of the current table frame that belongs to the rowspan: 1571 if ( nRowSpan > 1 ) 1572 { 1573 // optimization: Will end of row span be in last row or exceed row? 1574 long nMax = 0; 1575 while ( pRow->GetNext() && ++nMax < nRowSpan ) 1576 pRow = pRow->GetNext(); 1577 1578 if ( !pRow->GetNext() ) 1579 { 1580 pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true ); 1581 pRow = pThisCell->GetUpper(); 1582 } 1583 } 1584 1585 const SwRowFrm* pFollowRow = NULL; 1586 if ( !pRow->GetNext() && 1587 NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) && 1588 ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) ) 1589 pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true ); 1590 1591 return pRet; 1592 } 1593 1594 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL 1595 SwCellFrm* SwCellFrm::GetPreviousCell() const 1596 { 1597 SwCellFrm* pRet = NULL; 1598 1599 // NEW TABLES 1600 // Covered cells do not have previous cells! 1601 if ( GetLayoutRowSpan() < 1 ) 1602 return NULL; 1603 1604 // find most upper row frame 1605 const SwFrm* pRow = GetUpper(); 1606 while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) 1607 pRow = pRow->GetUpper(); 1608 1609 ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" ); 1610 1611 SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1612 1613 if ( pTab->IsFollow() ) 1614 { 1615 const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); 1616 const bool bIsInFirstLine = ( pTmp == pRow ); 1617 1618 if ( bIsInFirstLine ) 1619 { 1620 SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster(); 1621 if ( pMaster && pMaster->HasFollowFlowLine() ) 1622 { 1623 SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower()); 1624 if ( pMasterRow ) 1625 pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false ); 1626 if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 ) 1627 pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true )); 1628 } 1629 } 1630 } 1631 1632 return pRet; 1633 } 1634 1635 // --> NEW TABLES 1636 const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const 1637 { 1638 const SwCellFrm* pRet = 0; 1639 1640 const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper()); 1641 1642 if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) ) 1643 return *this; 1644 1645 ASSERT( pTableFrm && 1646 ( bStart && GetTabBox()->getRowSpan() < 1 || 1647 !bStart && GetLayoutRowSpan() > 1 ), 1648 "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" ) 1649 1650 if ( pTableFrm ) 1651 { 1652 const SwTable* pTable = pTableFrm->GetTable(); 1653 1654 sal_uInt16 nMax = USHRT_MAX; 1655 if ( bCurrentTableOnly ) 1656 { 1657 const SwFrm* pCurrentRow = GetUpper(); 1658 const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() && 1659 !pTableFrm->IsInHeadline( *pCurrentRow ); 1660 1661 // check how many rows we are allowed to go up or down until we reach the end of 1662 // the current table frame: 1663 nMax = 0; 1664 while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() ) 1665 { 1666 if ( bStart ) 1667 { 1668 // do not enter a repeated headline: 1669 if ( bDoNotEnterHeadline && pTableFrm->IsFollow() && 1670 pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) ) 1671 break; 1672 1673 pCurrentRow = pCurrentRow->GetPrev(); 1674 } 1675 else 1676 pCurrentRow = pCurrentRow->GetNext(); 1677 1678 ++nMax; 1679 } 1680 } 1681 1682 // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly 1683 // is set) we assure that we find a rMasterBox that has a SwCellFrm in 1684 // the current table frame: 1685 const SwTableBox& rMasterBox = bStart ? 1686 GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) : 1687 GetTabBox()->FindEndOfRowSpan( *pTable, nMax ); 1688 1689 SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() ); 1690 1691 for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() ) 1692 { 1693 if ( pMasterCell->GetTabBox() == &rMasterBox ) 1694 { 1695 const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper()); 1696 1697 if ( bCurrentTableOnly ) 1698 { 1699 if ( pMasterTable == pTableFrm ) 1700 { 1701 pRet = pMasterCell; 1702 break; 1703 } 1704 } 1705 else 1706 { 1707 if ( pMasterTable == pTableFrm || 1708 ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) || 1709 (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) ) 1710 { 1711 pRet = pMasterCell; 1712 break; 1713 } 1714 } 1715 } 1716 } 1717 } 1718 1719 ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" ) 1720 1721 return *pRet; 1722 } 1723 // <-- NEW TABLES 1724 1725 const SwRowFrm* SwFrm::IsInSplitTableRow() const 1726 { 1727 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) 1728 1729 const SwFrm* pRow = this; 1730 1731 // find most upper row frame 1732 while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) 1733 pRow = pRow->GetUpper(); 1734 1735 if ( !pRow ) return NULL; 1736 1737 ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) 1738 1739 const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1740 // --> OD 2006-06-28 #b6443897# 1741 // If most upper row frame is a headline row, the current frame 1742 // can't be in a splitted table row. Thus, add corresponding condition. 1743 if ( pRow->GetNext() || 1744 pTab->GetTable()->IsHeadline( 1745 *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) || 1746 !pTab->HasFollowFlowLine() || 1747 !pTab->GetFollow() ) 1748 return NULL; 1749 // <-- 1750 1751 // skip headline 1752 const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow(); 1753 1754 ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" ) 1755 1756 return pFollowRow; 1757 } 1758 1759 const SwRowFrm* SwFrm::IsInFollowFlowRow() const 1760 { 1761 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) 1762 1763 // find most upper row frame 1764 const SwFrm* pRow = this; 1765 while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) 1766 pRow = pRow->GetUpper(); 1767 1768 if ( !pRow ) return NULL; 1769 1770 ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) 1771 1772 const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1773 1774 const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0; 1775 1776 if ( !pMaster || !pMaster->HasFollowFlowLine() ) 1777 return NULL; 1778 1779 const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); 1780 const bool bIsInFirstLine = ( pTmp == pRow ); 1781 1782 if ( !bIsInFirstLine ) 1783 return NULL; 1784 1785 const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower()); 1786 return pMasterRow; 1787 } 1788 1789 bool SwFrm::IsInBalancedSection() const 1790 { 1791 bool bRet = false; 1792 1793 if ( IsInSct() ) 1794 { 1795 const SwSectionFrm* pSectionFrm = FindSctFrm(); 1796 if ( pSectionFrm ) 1797 bRet = pSectionFrm->IsBalancedSection(); 1798 } 1799 return bRet; 1800 } 1801 1802 /* 1803 * SwLayoutFrm::GetLastLower() 1804 */ 1805 const SwFrm* SwLayoutFrm::GetLastLower() const 1806 { 1807 const SwFrm* pRet = Lower(); 1808 if ( !pRet ) 1809 return 0; 1810 while ( pRet->GetNext() ) 1811 pRet = pRet->GetNext(); 1812 return pRet; 1813 } 1814