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