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 /************************************************************************* 662 |* 663 |* SwFrm::_FindNext(), _FindPrev(), InvalidateNextPos() 664 |* _FindNextCnt() geht in Tabellen und Bereiche hineinund liefert 665 |* nur SwCntntFrms. 666 |* 667 |* Beschreibung Invalidiert die Position des Naechsten Frames. 668 |* Dies ist der direkte Nachfolger, oder bei CntntFrm's der naechste 669 |* CntntFrm der im gleichen Fluss liegt wie ich: 670 |* - Body, 671 |* - Fussnoten, 672 |* - Bei Kopf-/Fussbereichen ist die Benachrichtigung nur innerhalb des 673 |* Bereiches weiterzuleiten. 674 |* - dito fuer Flys. 675 |* - Cntnts in Tabs halten sich ausschliesslich innerhalb ihrer Zelle 676 |* auf. 677 |* - Tabellen verhalten sich prinzipiell analog zu den Cntnts 678 |* - Bereiche ebenfalls 679 |* Ersterstellung AK 14-Feb-1991 680 |* Letzte Aenderung AMA 10. Mar. 99 681 |* 682 |*************************************************************************/ 683 684 // Diese Hilfsfunktion ist ein Aequivalent zur ImplGetNextCntntFrm()-Methode, 685 // sie liefert allerdings neben ContentFrames auch TabFrms und SectionFrms. 686 SwFrm* lcl_NextFrm( SwFrm* pFrm ) 687 { 688 SwFrm *pRet = 0; 689 sal_Bool bGoingUp = sal_False; 690 do { 691 SwFrm *p = 0; 692 693 sal_Bool bGoingFwd = sal_False; 694 sal_Bool bGoingDown = (!bGoingUp && ( 0 != (p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0))); 695 696 if( !bGoingDown ) 697 { 698 bGoingFwd = (0 != (p = ( pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->GetNextLink() : pFrm->GetNext()))); 699 if ( !bGoingFwd ) 700 { 701 bGoingUp = (0 != (p = pFrm->GetUpper())); 702 if ( !bGoingUp ) 703 { 704 return 0; 705 } 706 } 707 } 708 bGoingUp = !(bGoingFwd || bGoingDown); 709 pFrm = p; 710 } while ( 0 == (pRet = ( ( pFrm->IsCntntFrm() || ( !bGoingUp && 711 ( pFrm->IsTabFrm() || pFrm->IsSctFrm() ) ) )? pFrm : 0 ) ) ); 712 return pRet; 713 } 714 715 SwFrm *SwFrm::_FindNext() 716 { 717 sal_Bool bIgnoreTab = sal_False; 718 SwFrm *pThis = this; 719 720 if ( IsTabFrm() ) 721 { 722 //Der letzte Cntnt der Tabelle wird 723 //gegriffen und dessen Nachfolger geliefert. Um die Spezialbeh. 724 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. 725 if ( ((SwTabFrm*)this)->GetFollow() ) 726 return ((SwTabFrm*)this)->GetFollow(); 727 728 pThis = ((SwTabFrm*)this)->FindLastCntnt(); 729 if ( !pThis ) 730 pThis = this; 731 bIgnoreTab = sal_True; 732 } 733 else if ( IsSctFrm() ) 734 { 735 //Der letzte Cntnt des Bereichs wird gegriffen und dessen Nachfolger 736 // geliefert. 737 if ( ((SwSectionFrm*)this)->GetFollow() ) 738 return ((SwSectionFrm*)this)->GetFollow(); 739 740 pThis = ((SwSectionFrm*)this)->FindLastCntnt(); 741 if ( !pThis ) 742 pThis = this; 743 } 744 else if ( IsCntntFrm() ) 745 { 746 if( ((SwCntntFrm*)this)->GetFollow() ) 747 return ((SwCntntFrm*)this)->GetFollow(); 748 } 749 else if ( IsRowFrm() ) 750 { 751 SwFrm* pMyUpper = GetUpper(); 752 if ( pMyUpper->IsTabFrm() && ((SwTabFrm*)pMyUpper)->GetFollow() ) 753 return ((SwTabFrm*)pMyUpper)->GetFollow()->GetLower(); 754 else return NULL; 755 } 756 else 757 return NULL; 758 759 SwFrm* pRet = NULL; 760 const sal_Bool bFtn = pThis->IsInFtn(); 761 if ( !bIgnoreTab && pThis->IsInTab() ) 762 { 763 SwLayoutFrm *pUp = pThis->GetUpper(); 764 while ( !pUp->IsCellFrm() ) 765 pUp = pUp->GetUpper(); 766 ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); 767 SwFrm* pNxt = ((SwCellFrm*)pUp)->GetFollowCell(); 768 if ( pNxt ) 769 pNxt = ((SwCellFrm*)pNxt)->ContainsCntnt(); 770 if ( !pNxt ) 771 { 772 pNxt = lcl_NextFrm( pThis ); 773 if ( pUp->IsAnLower( pNxt ) ) 774 pRet = pNxt; 775 } 776 else 777 pRet = pNxt; 778 } 779 else 780 { 781 const sal_Bool bBody = pThis->IsInDocBody(); 782 SwFrm *pNxtCnt = lcl_NextFrm( pThis ); 783 if ( pNxtCnt ) 784 { 785 if ( bBody || bFtn ) 786 { 787 while ( pNxtCnt ) 788 { 789 // OD 02.04.2003 #108446# - check for endnote, only if found 790 // next content isn't contained in a section, that collect its 791 // endnotes at its end. 792 bool bEndn = IsInSct() && !IsSctFrm() && 793 ( !pNxtCnt->IsInSct() || 794 !pNxtCnt->FindSctFrm()->IsEndnAtEnd() 795 ); 796 if ( ( bBody && pNxtCnt->IsInDocBody() ) || 797 ( pNxtCnt->IsInFtn() && 798 ( bFtn || 799 ( bEndn && pNxtCnt->FindFtnFrm()->GetAttr()->GetFtn().IsEndNote() ) 800 ) 801 ) 802 ) 803 { 804 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 805 : (SwFrm*)pNxtCnt; 806 break; 807 } 808 pNxtCnt = lcl_NextFrm( pNxtCnt ); 809 } 810 } 811 else if ( pThis->IsInFly() ) 812 { 813 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 814 : (SwFrm*)pNxtCnt; 815 } 816 else //Fuss-/oder Kopfbereich 817 { 818 const SwFrm *pUp = pThis->GetUpper(); 819 const SwFrm *pCntUp = pNxtCnt->GetUpper(); 820 while ( pUp && pUp->GetUpper() && 821 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 822 pUp = pUp->GetUpper(); 823 while ( pCntUp && pCntUp->GetUpper() && 824 !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) 825 pCntUp = pCntUp->GetUpper(); 826 if ( pCntUp == pUp ) 827 { 828 pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrm() 829 : (SwFrm*)pNxtCnt; 830 } 831 } 832 } 833 } 834 if( pRet && pRet->IsInSct() ) 835 { 836 SwSectionFrm* pSct = pRet->FindSctFrm(); 837 //Fussnoten in spaltigen Rahmen duerfen nicht den Bereich 838 //liefern, der die Fussnoten umfasst 839 if( !pSct->IsAnLower( this ) && 840 (!bFtn || pSct->IsInFtn() ) ) 841 return pSct; 842 } 843 return pRet; 844 } 845 846 // --> OD 2005-12-01 #i27138# - add parameter <_bInSameFtn> 847 SwCntntFrm *SwFrm::_FindNextCnt( const bool _bInSameFtn ) 848 { 849 SwFrm *pThis = this; 850 851 if ( IsTabFrm() ) 852 { 853 if ( ((SwTabFrm*)this)->GetFollow() ) 854 { 855 pThis = ((SwTabFrm*)this)->GetFollow()->ContainsCntnt(); 856 if( pThis ) 857 return (SwCntntFrm*)pThis; 858 } 859 pThis = ((SwTabFrm*)this)->FindLastCntnt(); 860 if ( !pThis ) 861 return 0; 862 } 863 else if ( IsSctFrm() ) 864 { 865 if ( ((SwSectionFrm*)this)->GetFollow() ) 866 { 867 pThis = ((SwSectionFrm*)this)->GetFollow()->ContainsCntnt(); 868 if( pThis ) 869 return (SwCntntFrm*)pThis; 870 } 871 pThis = ((SwSectionFrm*)this)->FindLastCntnt(); 872 if ( !pThis ) 873 return 0; 874 } 875 else if ( IsCntntFrm() && ((SwCntntFrm*)this)->GetFollow() ) 876 return ((SwCntntFrm*)this)->GetFollow(); 877 878 if ( pThis->IsCntntFrm() ) 879 { 880 const sal_Bool bBody = pThis->IsInDocBody(); 881 const sal_Bool bFtn = pThis->IsInFtn(); 882 SwCntntFrm *pNxtCnt = ((SwCntntFrm*)pThis)->GetNextCntntFrm(); 883 if ( pNxtCnt ) 884 { 885 // --> OD 2005-12-01 #i27138# 886 if ( bBody || ( bFtn && !_bInSameFtn ) ) 887 // <-- 888 { 889 // handling for environments 'footnotes' and 'document body frames': 890 while ( pNxtCnt ) 891 { 892 if ( (bBody && pNxtCnt->IsInDocBody()) || 893 (bFtn && pNxtCnt->IsInFtn()) ) 894 return pNxtCnt; 895 pNxtCnt = pNxtCnt->GetNextCntntFrm(); 896 } 897 } 898 // --> OD 2005-12-01 #i27138# 899 else if ( bFtn && _bInSameFtn ) 900 { 901 // handling for environments 'each footnote': 902 // Assure that found next content frame belongs to the same footnotes 903 const SwFtnFrm* pFtnFrmOfNext( pNxtCnt->FindFtnFrm() ); 904 const SwFtnFrm* pFtnFrmOfCurr( pThis->FindFtnFrm() ); 905 ASSERT( pFtnFrmOfCurr, 906 "<SwFrm::_FindNextCnt() - unknown layout situation: current frame has to have an upper footnote frame." ); 907 if ( pFtnFrmOfNext == pFtnFrmOfCurr ) 908 { 909 return pNxtCnt; 910 } 911 else if ( pFtnFrmOfCurr->GetFollow() ) 912 { 913 // next content frame has to be the first content frame 914 // in the follow footnote, which contains a content frame. 915 SwFtnFrm* pFollowFtnFrmOfCurr( 916 const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); 917 pNxtCnt = 0L; 918 do { 919 pFollowFtnFrmOfCurr = pFollowFtnFrmOfCurr->GetFollow(); 920 pNxtCnt = pFollowFtnFrmOfCurr->ContainsCntnt(); 921 } while ( !pNxtCnt && pFollowFtnFrmOfCurr->GetFollow() ); 922 return pNxtCnt; 923 } 924 else 925 { 926 // current content frame is the last content frame in the 927 // footnote - no next content frame exists. 928 return 0L; 929 } 930 } 931 // <-- 932 else if ( pThis->IsInFly() ) 933 // handling for environments 'unlinked fly frame' and 934 // 'group of linked fly frames': 935 return pNxtCnt; 936 else 937 { 938 // handling for environments 'page header' and 'page footer': 939 const SwFrm *pUp = pThis->GetUpper(); 940 const SwFrm *pCntUp = pNxtCnt->GetUpper(); 941 while ( pUp && pUp->GetUpper() && 942 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 943 pUp = pUp->GetUpper(); 944 while ( pCntUp && pCntUp->GetUpper() && 945 !pCntUp->IsHeaderFrm() && !pCntUp->IsFooterFrm() ) 946 pCntUp = pCntUp->GetUpper(); 947 if ( pCntUp == pUp ) 948 return pNxtCnt; 949 } 950 } 951 } 952 return 0; 953 } 954 955 /** method to determine previous content frame in the same environment 956 for a flow frame (content frame, table frame, section frame) 957 958 OD 2005-11-30 #i27138# 959 960 @author OD 961 */ 962 SwCntntFrm* SwFrm::_FindPrevCnt( const bool _bInSameFtn ) 963 { 964 if ( !IsFlowFrm() ) 965 { 966 // nothing to do, if current frame isn't a flow frame. 967 return 0L; 968 } 969 970 SwCntntFrm* pPrevCntntFrm( 0L ); 971 972 // Because method <SwCntntFrm::GetPrevCntntFrm()> is used to travel 973 // through the layout, a content frame, at which the travel starts, is needed. 974 SwCntntFrm* pCurrCntntFrm = dynamic_cast<SwCntntFrm*>(this); 975 976 // perform shortcut, if current frame is a follow, and 977 // determine <pCurrCntntFrm>, if current frame is a table or section frame 978 if ( pCurrCntntFrm && pCurrCntntFrm->IsFollow() ) 979 { 980 // previous content frame is its master content frame 981 pPrevCntntFrm = pCurrCntntFrm->FindMaster(); 982 } 983 else if ( IsTabFrm() ) 984 { 985 SwTabFrm* pTabFrm( static_cast<SwTabFrm*>(this) ); 986 if ( pTabFrm->IsFollow() ) 987 { 988 // previous content frame is the last content of its master table frame 989 pPrevCntntFrm = pTabFrm->FindMaster()->FindLastCntnt(); 990 } 991 else 992 { 993 // start content frame for the search is the first content frame of 994 // the table frame. 995 pCurrCntntFrm = pTabFrm->ContainsCntnt(); 996 } 997 } 998 else if ( IsSctFrm() ) 999 { 1000 SwSectionFrm* pSectFrm( static_cast<SwSectionFrm*>(this) ); 1001 if ( pSectFrm->IsFollow() ) 1002 { 1003 // previous content frame is the last content of its master section frame 1004 pPrevCntntFrm = pSectFrm->FindMaster()->FindLastCntnt(); 1005 } 1006 else 1007 { 1008 // start content frame for the search is the first content frame of 1009 // the section frame. 1010 pCurrCntntFrm = pSectFrm->ContainsCntnt(); 1011 } 1012 } 1013 1014 // search for next content frame, depending on the environment, in which 1015 // the current frame is in. 1016 if ( !pPrevCntntFrm && pCurrCntntFrm ) 1017 { 1018 pPrevCntntFrm = pCurrCntntFrm->GetPrevCntntFrm(); 1019 if ( pPrevCntntFrm ) 1020 { 1021 if ( pCurrCntntFrm->IsInFly() ) 1022 { 1023 // handling for environments 'unlinked fly frame' and 1024 // 'group of linked fly frames': 1025 // Nothing to do, <pPrevCntntFrm> is the one 1026 } 1027 else 1028 { 1029 const bool bInDocBody = pCurrCntntFrm->IsInDocBody(); 1030 const bool bInFtn = pCurrCntntFrm->IsInFtn(); 1031 if ( bInDocBody || ( bInFtn && !_bInSameFtn ) ) 1032 { 1033 // handling for environments 'footnotes' and 'document body frames': 1034 // Assure that found previous frame is also in one of these 1035 // environments. Otherwise, travel further 1036 while ( pPrevCntntFrm ) 1037 { 1038 if ( ( bInDocBody && pPrevCntntFrm->IsInDocBody() ) || 1039 ( bInFtn && pPrevCntntFrm->IsInFtn() ) ) 1040 { 1041 break; 1042 } 1043 pPrevCntntFrm = pPrevCntntFrm->GetPrevCntntFrm(); 1044 } 1045 } 1046 else if ( bInFtn && _bInSameFtn ) 1047 { 1048 // handling for environments 'each footnote': 1049 // Assure that found next content frame belongs to the same footnotes 1050 const SwFtnFrm* pFtnFrmOfPrev( pPrevCntntFrm->FindFtnFrm() ); 1051 const SwFtnFrm* pFtnFrmOfCurr( pCurrCntntFrm->FindFtnFrm() ); 1052 if ( pFtnFrmOfPrev != pFtnFrmOfCurr ) 1053 { 1054 if ( pFtnFrmOfCurr->GetMaster() ) 1055 { 1056 SwFtnFrm* pMasterFtnFrmOfCurr( 1057 const_cast<SwFtnFrm*>(pFtnFrmOfCurr) ); 1058 pPrevCntntFrm = 0L; 1059 // --> OD 2007-07-05 #146872# 1060 // correct wrong loop-condition 1061 do { 1062 pMasterFtnFrmOfCurr = pMasterFtnFrmOfCurr->GetMaster(); 1063 pPrevCntntFrm = pMasterFtnFrmOfCurr->FindLastCntnt(); 1064 } while ( !pPrevCntntFrm && 1065 pMasterFtnFrmOfCurr->GetMaster() ); 1066 // <-- 1067 } 1068 else 1069 { 1070 // current content frame is the first content in the 1071 // footnote - no previous content exists. 1072 pPrevCntntFrm = 0L;; 1073 } 1074 } 1075 } 1076 else 1077 { 1078 // handling for environments 'page header' and 'page footer': 1079 // Assure that found previous frame is also in the same 1080 // page header respectively page footer as <pCurrCntntFrm> 1081 // Note: At this point its clear, that <pCurrCntntFrm> has 1082 // to be inside a page header or page footer and that 1083 // neither <pCurrCntntFrm> nor <pPrevCntntFrm> are 1084 // inside a fly frame. 1085 // Thus, method <FindFooterOrHeader()> can be used. 1086 ASSERT( pCurrCntntFrm->FindFooterOrHeader(), 1087 "<SwFrm::_FindPrevCnt()> - unknown layout situation: current frame should be in page header or page footer" ); 1088 ASSERT( !pPrevCntntFrm->IsInFly(), 1089 "<SwFrm::_FindPrevCnt()> - unknown layout situation: found previous frame should *not* be inside a fly frame." ); 1090 if ( pPrevCntntFrm->FindFooterOrHeader() != 1091 pCurrCntntFrm->FindFooterOrHeader() ) 1092 { 1093 pPrevCntntFrm = 0L; 1094 } 1095 } 1096 } 1097 } 1098 } 1099 1100 return pPrevCntntFrm; 1101 } 1102 1103 SwFrm *SwFrm::_FindPrev() 1104 { 1105 sal_Bool bIgnoreTab = sal_False; 1106 SwFrm *pThis = this; 1107 1108 if ( IsTabFrm() ) 1109 { 1110 //Der erste Cntnt der Tabelle wird 1111 //gegriffen und dessen Vorgaenger geliefert. Um die Spezialbeh. 1112 //Fuer Tabellen (s.u.) auszuschalten wird bIgnoreTab gesetzt. 1113 if ( ((SwTabFrm*)this)->IsFollow() ) 1114 return ((SwTabFrm*)this)->FindMaster(); 1115 else 1116 pThis = ((SwTabFrm*)this)->ContainsCntnt(); 1117 bIgnoreTab = sal_True; 1118 } 1119 1120 if ( pThis && pThis->IsCntntFrm() ) 1121 { 1122 SwCntntFrm *pPrvCnt = ((SwCntntFrm*)pThis)->GetPrevCntntFrm(); 1123 if( !pPrvCnt ) 1124 return 0; 1125 if ( !bIgnoreTab && pThis->IsInTab() ) 1126 { 1127 SwLayoutFrm *pUp = pThis->GetUpper(); 1128 while ( !pUp->IsCellFrm() ) 1129 pUp = pUp->GetUpper(); 1130 ASSERT( pUp, "Cntnt in Tabelle aber nicht in Zelle." ); 1131 if ( pUp->IsAnLower( pPrvCnt ) ) 1132 return pPrvCnt; 1133 } 1134 else 1135 { 1136 SwFrm* pRet; 1137 const sal_Bool bBody = pThis->IsInDocBody(); 1138 const sal_Bool bFtn = bBody ? sal_False : pThis->IsInFtn(); 1139 if ( bBody || bFtn ) 1140 { 1141 while ( pPrvCnt ) 1142 { 1143 if ( (bBody && pPrvCnt->IsInDocBody()) || 1144 (bFtn && pPrvCnt->IsInFtn()) ) 1145 { 1146 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1147 : (SwFrm*)pPrvCnt; 1148 return pRet; 1149 } 1150 pPrvCnt = pPrvCnt->GetPrevCntntFrm(); 1151 } 1152 } 1153 else if ( pThis->IsInFly() ) 1154 { 1155 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1156 : (SwFrm*)pPrvCnt; 1157 return pRet; 1158 } 1159 else //Fuss-/oder Kopfbereich oder Fly 1160 { 1161 const SwFrm *pUp = pThis->GetUpper(); 1162 const SwFrm *pCntUp = pPrvCnt->GetUpper(); 1163 while ( pUp && pUp->GetUpper() && 1164 !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() ) 1165 pUp = pUp->GetUpper(); 1166 while ( pCntUp && pCntUp->GetUpper() ) 1167 pCntUp = pCntUp->GetUpper(); 1168 if ( pCntUp == pUp ) 1169 { 1170 pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrm() 1171 : (SwFrm*)pPrvCnt; 1172 return pRet; 1173 } 1174 } 1175 } 1176 } 1177 return 0; 1178 } 1179 1180 void SwFrm::ImplInvalidateNextPos( sal_Bool bNoFtn ) 1181 { 1182 SwFrm *pFrm; 1183 if ( 0 != (pFrm = _FindNext()) ) 1184 { 1185 if( pFrm->IsSctFrm() ) 1186 { 1187 while( pFrm && pFrm->IsSctFrm() ) 1188 { 1189 if( ((SwSectionFrm*)pFrm)->GetSection() ) 1190 { 1191 SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); 1192 if( pTmp ) 1193 pTmp->InvalidatePos(); 1194 else if( !bNoFtn ) 1195 ((SwSectionFrm*)pFrm)->InvalidateFtnPos(); 1196 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) 1197 pFrm->InvalidatePos(); 1198 return; 1199 } 1200 pFrm = pFrm->FindNext(); 1201 } 1202 if( pFrm ) 1203 { 1204 if ( pFrm->IsSctFrm()) 1205 { // Damit der Inhalt eines Bereichs die Chance erhaelt, 1206 // die Seite zu wechseln, muss er ebenfalls invalidiert werden. 1207 SwFrm* pTmp = ((SwSectionFrm*)pFrm)->ContainsAny(); 1208 if( pTmp ) 1209 pTmp->InvalidatePos(); 1210 if( !IsInSct() || FindSctFrm()->GetFollow() != pFrm ) 1211 pFrm->InvalidatePos(); 1212 } 1213 else 1214 pFrm->InvalidatePos(); 1215 } 1216 } 1217 else 1218 pFrm->InvalidatePos(); 1219 } 1220 } 1221 1222 /** method to invalidate printing area of next frame 1223 1224 OD 09.01.2004 #i11859# 1225 1226 @author OD 1227 1228 FME 2004-04-19 #i27145# Moved function from SwTxtFrm to SwFrm 1229 */ 1230 void SwFrm::InvalidateNextPrtArea() 1231 { 1232 // determine next frame 1233 SwFrm* pNextFrm = FindNext(); 1234 // skip empty section frames and hidden text frames 1235 { 1236 while ( pNextFrm && 1237 ( ( pNextFrm->IsSctFrm() && 1238 !static_cast<SwSectionFrm*>(pNextFrm)->GetSection() ) || 1239 ( pNextFrm->IsTxtFrm() && 1240 static_cast<SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) ) ) 1241 { 1242 pNextFrm = pNextFrm->FindNext(); 1243 } 1244 } 1245 1246 // Invalidate printing area of found next frame 1247 if ( pNextFrm ) 1248 { 1249 if ( pNextFrm->IsSctFrm() ) 1250 { 1251 // Invalidate printing area of found section frame, if 1252 // (1) this text frame isn't in a section OR 1253 // (2) found section frame isn't a follow of the section frame this 1254 // text frame is in. 1255 if ( !IsInSct() || FindSctFrm()->GetFollow() != pNextFrm ) 1256 { 1257 pNextFrm->InvalidatePrt(); 1258 } 1259 1260 // Invalidate printing area of first content in found section. 1261 SwFrm* pFstCntntOfSctFrm = 1262 static_cast<SwSectionFrm*>(pNextFrm)->ContainsAny(); 1263 if ( pFstCntntOfSctFrm ) 1264 { 1265 pFstCntntOfSctFrm->InvalidatePrt(); 1266 } 1267 } 1268 else 1269 { 1270 pNextFrm->InvalidatePrt(); 1271 } 1272 } 1273 } 1274 1275 /************************************************************************* 1276 |* 1277 |* lcl_IsInColSect() 1278 |* liefert nur sal_True, wenn der Frame _direkt_ in einem spaltigen Bereich steht, 1279 |* nicht etwa, wenn er in einer Tabelle steht, die in einem spaltigen Bereich ist. 1280 |* 1281 |*************************************************************************/ 1282 1283 sal_Bool lcl_IsInColSct( const SwFrm *pUp ) 1284 { 1285 sal_Bool bRet = sal_False; 1286 while( pUp ) 1287 { 1288 if( pUp->IsColumnFrm() ) 1289 bRet = sal_True; 1290 else if( pUp->IsSctFrm() ) 1291 return bRet; 1292 else if( pUp->IsTabFrm() ) 1293 return sal_False; 1294 pUp = pUp->GetUpper(); 1295 } 1296 return sal_False; 1297 } 1298 1299 /************************************************************************* 1300 |* 1301 |* SwFrm::IsMoveable(); 1302 |* 1303 |* Ersterstellung MA 09. Mar. 93 1304 |* Letzte Aenderung MA 05. May. 95 1305 |* 1306 |*************************************************************************/ 1307 /** determine, if frame is moveable in given environment 1308 1309 OD 08.08.2003 #110978# 1310 method replaced 'old' method <sal_Bool IsMoveable() const>. 1311 Determines, if frame is moveable in given environment. if no environment 1312 is given (parameter _pLayoutFrm == 0L), the movability in the actual 1313 environment (<this->GetUpper()) is checked. 1314 1315 @author OD 1316 */ 1317 1318 bool SwFrm::IsMoveable( const SwLayoutFrm* _pLayoutFrm ) const 1319 { 1320 bool bRetVal = false; 1321 1322 if ( !_pLayoutFrm ) 1323 { 1324 _pLayoutFrm = GetUpper(); 1325 } 1326 1327 if ( _pLayoutFrm && IsFlowFrm() ) 1328 { 1329 if ( _pLayoutFrm->IsInSct() && lcl_IsInColSct( _pLayoutFrm ) ) 1330 { 1331 bRetVal = true; 1332 } 1333 else if ( _pLayoutFrm->IsInFly() || 1334 _pLayoutFrm->IsInDocBody() || 1335 _pLayoutFrm->IsInFtn() ) 1336 { 1337 if ( _pLayoutFrm->IsInTab() && !IsTabFrm() && 1338 ( !IsCntntFrm() || !const_cast<SwFrm*>(this)->GetNextCellLeaf( MAKEPAGE_NONE ) ) ) 1339 { 1340 bRetVal = false; 1341 } 1342 else 1343 { 1344 if ( _pLayoutFrm->IsInFly() ) 1345 { 1346 // if fly frame has a follow (next linked fly frame), 1347 // frame is moveable. 1348 if ( const_cast<SwLayoutFrm*>(_pLayoutFrm)->FindFlyFrm()->GetNextLink() ) 1349 { 1350 bRetVal = true; 1351 } 1352 else 1353 { 1354 // if environment is columned, frame is moveable, if 1355 // it isn't in last column. 1356 // search for column frame 1357 const SwFrm* pCol = _pLayoutFrm; 1358 while ( pCol && !pCol->IsColumnFrm() ) 1359 { 1360 pCol = pCol->GetUpper(); 1361 } 1362 // frame is moveable, if found column frame isn't last one. 1363 if ( pCol && pCol->GetNext() ) 1364 { 1365 bRetVal = true; 1366 } 1367 } 1368 } 1369 else 1370 { 1371 bRetVal = true; 1372 } 1373 } 1374 } 1375 } 1376 1377 return bRetVal; 1378 } 1379 1380 /************************************************************************* 1381 |* 1382 |* SwFrm::SetInfFlags(); 1383 |* 1384 |* Ersterstellung MA 05. Apr. 94 1385 |* Letzte Aenderung MA 05. Apr. 94 1386 |* 1387 |*************************************************************************/ 1388 void SwFrm::SetInfFlags() 1389 { 1390 if ( !IsFlyFrm() && !GetUpper() ) //noch nicht gepastet, keine Informationen 1391 return; //lieferbar 1392 1393 bInfInvalid = bInfBody = bInfTab = bInfFly = bInfFtn = bInfSct = sal_False; 1394 1395 SwFrm *pFrm = this; 1396 if( IsFtnContFrm() ) 1397 bInfFtn = sal_True; 1398 do 1399 { // bInfBody wird nur am Seitenbody, nicht im ColumnBody gesetzt 1400 if ( pFrm->IsBodyFrm() && !bInfFtn && pFrm->GetUpper() 1401 && pFrm->GetUpper()->IsPageFrm() ) 1402 bInfBody = sal_True; 1403 else if ( pFrm->IsTabFrm() || pFrm->IsCellFrm() ) 1404 { 1405 bInfTab = sal_True; 1406 } 1407 else if ( pFrm->IsFlyFrm() ) 1408 bInfFly = sal_True; 1409 else if ( pFrm->IsSctFrm() ) 1410 bInfSct = sal_True; 1411 else if ( pFrm->IsFtnFrm() ) 1412 bInfFtn = sal_True; 1413 1414 pFrm = pFrm->GetUpper(); 1415 1416 } while ( pFrm && !pFrm->IsPageFrm() ); //Oberhalb der Seite kommt nix 1417 } 1418 1419 /*-----------------22.8.2001 14:30------------------ 1420 * SwFrm::SetDirFlags( sal_Bool ) 1421 * actualizes the vertical or the righttoleft-flags. 1422 * If the property is derived, it's from the upper or (for fly frames) from 1423 * the anchor. Otherwise we've to call a virtual method to check the property. 1424 * --------------------------------------------------*/ 1425 1426 void SwFrm::SetDirFlags( sal_Bool bVert ) 1427 { 1428 if( bVert ) 1429 { 1430 // OD 2004-01-21 #114969# - if derived, valid vertical flag only if 1431 // vertical flag of upper/anchor is valid. 1432 if( bDerivedVert ) 1433 { 1434 const SwFrm* pAsk = IsFlyFrm() ? 1435 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); 1436 1437 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) 1438 1439 if( pAsk ) 1440 { 1441 bVertical = pAsk->IsVertical() ? 1 : 0; 1442 bReverse = pAsk->IsReverse() ? 1 : 0; 1443 1444 bVertLR = pAsk->IsVertLR() ? 1 : 0; 1445 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1446 if ( !pAsk->bInvalidVert ) 1447 bInvalidVert = sal_False; 1448 } 1449 } 1450 else 1451 CheckDirection( bVert ); 1452 } 1453 else 1454 { 1455 sal_Bool bInv = 0; 1456 if( !bDerivedR2L ) // CheckDirection is able to set bDerivedR2L! 1457 CheckDirection( bVert ); 1458 if( bDerivedR2L ) 1459 { 1460 const SwFrm* pAsk = IsFlyFrm() ? 1461 ((SwFlyFrm*)this)->GetAnchorFrm() : GetUpper(); 1462 1463 ASSERT( pAsk != this, "Autsch! Stack overflow is about to happen" ) 1464 1465 if( pAsk ) 1466 bRightToLeft = pAsk->IsRightToLeft() ? 1 : 0; 1467 if( !pAsk || pAsk->bInvalidR2L ) 1468 bInv = bInvalidR2L; 1469 } 1470 bInvalidR2L = bInv; 1471 } 1472 } 1473 1474 SwLayoutFrm* SwFrm::GetNextCellLeaf( MakePageType ) 1475 { 1476 SwFrm* pTmpFrm = this; 1477 while ( !pTmpFrm->IsCellFrm() ) 1478 pTmpFrm = pTmpFrm->GetUpper(); 1479 1480 ASSERT( pTmpFrm, "SwFrm::GetNextCellLeaf() without cell" ) 1481 return ((SwCellFrm*)pTmpFrm)->GetFollowCell(); 1482 } 1483 1484 SwLayoutFrm* SwFrm::GetPrevCellLeaf( MakePageType ) 1485 { 1486 SwFrm* pTmpFrm = this; 1487 while ( !pTmpFrm->IsCellFrm() ) 1488 pTmpFrm = pTmpFrm->GetUpper(); 1489 1490 ASSERT( pTmpFrm, "SwFrm::GetNextPreviousLeaf() without cell" ) 1491 return ((SwCellFrm*)pTmpFrm)->GetPreviousCell(); 1492 } 1493 1494 SwCellFrm* lcl_FindCorrespondingCellFrm( const SwRowFrm& rOrigRow, 1495 const SwCellFrm& rOrigCell, 1496 const SwRowFrm& rCorrRow, 1497 bool bInFollow ) 1498 { 1499 SwCellFrm* pRet = NULL; 1500 SwCellFrm* pCell = (SwCellFrm*)rOrigRow.Lower(); 1501 SwCellFrm* pCorrCell = (SwCellFrm*)rCorrRow.Lower(); 1502 1503 while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) ) 1504 { 1505 pCell = (SwCellFrm*)pCell->GetNext(); 1506 pCorrCell = (SwCellFrm*)pCorrCell->GetNext(); 1507 } 1508 1509 ASSERT( pCell && pCorrCell, "lcl_FindCorrespondingCellFrm does not work" ) 1510 1511 if ( pCell != &rOrigCell ) 1512 { 1513 // rOrigCell must be a lower of pCell. We need to recurse into the rows: 1514 ASSERT( pCell->Lower() && pCell->Lower()->IsRowFrm(), 1515 "lcl_FindCorrespondingCellFrm does not work" ) 1516 1517 SwRowFrm* pRow = (SwRowFrm*)pCell->Lower(); 1518 while ( !pRow->IsAnLower( &rOrigCell ) ) 1519 pRow = (SwRowFrm*)pRow->GetNext(); 1520 1521 SwRowFrm* pCorrRow = 0; 1522 if ( bInFollow ) 1523 pCorrRow = pRow->GetFollowRow(); 1524 else 1525 { 1526 SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pCorrCell->GetLastLower()); 1527 1528 if ( pTmpRow && pTmpRow->GetFollowRow() == pRow ) 1529 pCorrRow = pTmpRow; 1530 } 1531 1532 if ( pCorrRow ) 1533 pRet = lcl_FindCorrespondingCellFrm( *pRow, rOrigCell, *pCorrRow, bInFollow ); 1534 } 1535 else 1536 pRet = pCorrCell; 1537 1538 return pRet; 1539 } 1540 1541 // VERSION OF GetFollowCell() that assumes that we always have a follow flow line: 1542 SwCellFrm* SwCellFrm::GetFollowCell() const 1543 { 1544 SwCellFrm* pRet = NULL; 1545 1546 // NEW TABLES 1547 // Covered cells do not have follow cells! 1548 const long nRowSpan = GetLayoutRowSpan(); 1549 if ( nRowSpan < 1 ) 1550 return NULL; 1551 1552 // find most upper row frame 1553 const SwFrm* pRow = GetUpper(); 1554 while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) 1555 pRow = pRow->GetUpper(); 1556 1557 if ( !pRow ) 1558 return NULL; 1559 1560 const SwTabFrm* pTabFrm = static_cast<const SwTabFrm*>( pRow->GetUpper() ); 1561 if ( !pRow || !pTabFrm->GetFollow() || !pTabFrm->HasFollowFlowLine() ) 1562 return NULL; 1563 1564 const SwCellFrm* pThisCell = this; 1565 1566 // Get last cell of the current table frame that belongs to the rowspan: 1567 if ( nRowSpan > 1 ) 1568 { 1569 // optimization: Will end of row span be in last row or exceed row? 1570 long nMax = 0; 1571 while ( pRow->GetNext() && ++nMax < nRowSpan ) 1572 pRow = pRow->GetNext(); 1573 1574 if ( !pRow->GetNext() ) 1575 { 1576 pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false, true ); 1577 pRow = pThisCell->GetUpper(); 1578 } 1579 } 1580 1581 const SwRowFrm* pFollowRow = NULL; 1582 if ( !pRow->GetNext() && 1583 NULL != ( pFollowRow = pRow->IsInSplitTableRow() ) && 1584 ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) ) 1585 pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *pThisCell, *pFollowRow, true ); 1586 1587 return pRet; 1588 } 1589 1590 // VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL 1591 SwCellFrm* SwCellFrm::GetPreviousCell() const 1592 { 1593 SwCellFrm* pRet = NULL; 1594 1595 // NEW TABLES 1596 // Covered cells do not have previous cells! 1597 if ( GetLayoutRowSpan() < 1 ) 1598 return NULL; 1599 1600 // find most upper row frame 1601 const SwFrm* pRow = GetUpper(); 1602 while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) 1603 pRow = pRow->GetUpper(); 1604 1605 ASSERT( pRow->GetUpper() && pRow->GetUpper()->IsTabFrm(), "GetPreviousCell without Table" ); 1606 1607 SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1608 1609 if ( pTab->IsFollow() ) 1610 { 1611 const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); 1612 const bool bIsInFirstLine = ( pTmp == pRow ); 1613 1614 if ( bIsInFirstLine ) 1615 { 1616 SwTabFrm *pMaster = (SwTabFrm*)pTab->FindMaster(); 1617 if ( pMaster && pMaster->HasFollowFlowLine() ) 1618 { 1619 SwRowFrm* pMasterRow = static_cast<SwRowFrm*>(pMaster->GetLastLower()); 1620 if ( pMasterRow ) 1621 pRet = lcl_FindCorrespondingCellFrm( *((SwRowFrm*)pRow), *this, *pMasterRow, false ); 1622 if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 ) 1623 pRet = &const_cast<SwCellFrm&>(pRet->FindStartEndOfRowSpanCell( true, true )); 1624 } 1625 } 1626 } 1627 1628 return pRet; 1629 } 1630 1631 // --> NEW TABLES 1632 const SwCellFrm& SwCellFrm::FindStartEndOfRowSpanCell( bool bStart, bool bCurrentTableOnly ) const 1633 { 1634 const SwCellFrm* pRet = 0; 1635 1636 const SwTabFrm* pTableFrm = dynamic_cast<const SwTabFrm*>(GetUpper()->GetUpper()); 1637 1638 if ( !bStart && pTableFrm->IsFollow() && pTableFrm->IsInHeadline( *this ) ) 1639 return *this; 1640 1641 ASSERT( pTableFrm && 1642 ( bStart && GetTabBox()->getRowSpan() < 1 || 1643 !bStart && GetLayoutRowSpan() > 1 ), 1644 "SwCellFrm::FindStartRowSpanCell: No rowspan, no table, no cookies" ) 1645 1646 if ( pTableFrm ) 1647 { 1648 const SwTable* pTable = pTableFrm->GetTable(); 1649 1650 sal_uInt16 nMax = USHRT_MAX; 1651 if ( bCurrentTableOnly ) 1652 { 1653 const SwFrm* pCurrentRow = GetUpper(); 1654 const bool bDoNotEnterHeadline = bStart && pTableFrm->IsFollow() && 1655 !pTableFrm->IsInHeadline( *pCurrentRow ); 1656 1657 // check how many rows we are allowed to go up or down until we reach the end of 1658 // the current table frame: 1659 nMax = 0; 1660 while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() ) 1661 { 1662 if ( bStart ) 1663 { 1664 // do not enter a repeated headline: 1665 if ( bDoNotEnterHeadline && pTableFrm->IsFollow() && 1666 pTableFrm->IsInHeadline( *pCurrentRow->GetPrev() ) ) 1667 break; 1668 1669 pCurrentRow = pCurrentRow->GetPrev(); 1670 } 1671 else 1672 pCurrentRow = pCurrentRow->GetNext(); 1673 1674 ++nMax; 1675 } 1676 } 1677 1678 // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly 1679 // is set) we assure that we find a rMasterBox that has a SwCellFrm in 1680 // the current table frame: 1681 const SwTableBox& rMasterBox = bStart ? 1682 GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) : 1683 GetTabBox()->FindEndOfRowSpan( *pTable, nMax ); 1684 1685 SwIterator<SwCellFrm,SwFmt> aIter( *rMasterBox.GetFrmFmt() ); 1686 1687 for ( SwCellFrm* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() ) 1688 { 1689 if ( pMasterCell->GetTabBox() == &rMasterBox ) 1690 { 1691 const SwTabFrm* pMasterTable = static_cast<const SwTabFrm*>(pMasterCell->GetUpper()->GetUpper()); 1692 1693 if ( bCurrentTableOnly ) 1694 { 1695 if ( pMasterTable == pTableFrm ) 1696 { 1697 pRet = pMasterCell; 1698 break; 1699 } 1700 } 1701 else 1702 { 1703 if ( pMasterTable == pTableFrm || 1704 ( (bStart && pMasterTable->IsAnFollow(pTableFrm)) || 1705 (!bStart && pTableFrm->IsAnFollow(pMasterTable)) ) ) 1706 { 1707 pRet = pMasterCell; 1708 break; 1709 } 1710 } 1711 } 1712 } 1713 } 1714 1715 ASSERT( pRet, "SwCellFrm::FindStartRowSpanCell: No result" ) 1716 1717 return *pRet; 1718 } 1719 // <-- NEW TABLES 1720 1721 const SwRowFrm* SwFrm::IsInSplitTableRow() const 1722 { 1723 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) 1724 1725 const SwFrm* pRow = this; 1726 1727 // find most upper row frame 1728 while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) 1729 pRow = pRow->GetUpper(); 1730 1731 if ( !pRow ) return NULL; 1732 1733 ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) 1734 1735 const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1736 // --> OD 2006-06-28 #b6443897# 1737 // If most upper row frame is a headline row, the current frame 1738 // can't be in a splitted table row. Thus, add corresponding condition. 1739 if ( pRow->GetNext() || 1740 pTab->GetTable()->IsHeadline( 1741 *(static_cast<const SwRowFrm*>(pRow)->GetTabLine()) ) || 1742 !pTab->HasFollowFlowLine() || 1743 !pTab->GetFollow() ) 1744 return NULL; 1745 // <-- 1746 1747 // skip headline 1748 const SwRowFrm* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow(); 1749 1750 ASSERT( pFollowRow, "SwFrm::IsInSplitTableRow() does not work" ) 1751 1752 return pFollowRow; 1753 } 1754 1755 const SwRowFrm* SwFrm::IsInFollowFlowRow() const 1756 { 1757 ASSERT( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" ) 1758 1759 // find most upper row frame 1760 const SwFrm* pRow = this; 1761 while( pRow && ( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() ) ) 1762 pRow = pRow->GetUpper(); 1763 1764 if ( !pRow ) return NULL; 1765 1766 ASSERT( pRow->GetUpper()->IsTabFrm(), "Confusion in table layout" ) 1767 1768 const SwTabFrm* pTab = (SwTabFrm*)pRow->GetUpper(); 1769 1770 const SwTabFrm* pMaster = pTab->IsFollow() ? pTab->FindMaster() : 0; 1771 1772 if ( !pMaster || !pMaster->HasFollowFlowLine() ) 1773 return NULL; 1774 1775 const SwFrm* pTmp = pTab->GetFirstNonHeadlineRow(); 1776 const bool bIsInFirstLine = ( pTmp == pRow ); 1777 1778 if ( !bIsInFirstLine ) 1779 return NULL; 1780 1781 const SwRowFrm* pMasterRow = static_cast<const SwRowFrm*>(pMaster->GetLastLower()); 1782 return pMasterRow; 1783 } 1784 1785 bool SwFrm::IsInBalancedSection() const 1786 { 1787 bool bRet = false; 1788 1789 if ( IsInSct() ) 1790 { 1791 const SwSectionFrm* pSectionFrm = FindSctFrm(); 1792 if ( pSectionFrm ) 1793 bRet = pSectionFrm->IsBalancedSection(); 1794 } 1795 return bRet; 1796 } 1797 1798 /* 1799 * SwLayoutFrm::GetLastLower() 1800 */ 1801 const SwFrm* SwLayoutFrm::GetLastLower() const 1802 { 1803 const SwFrm* pRet = Lower(); 1804 if ( !pRet ) 1805 return 0; 1806 while ( pRet->GetNext() ) 1807 pRet = pRet->GetNext(); 1808 return pRet; 1809 } 1810