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 <txtftn.hxx> 29 #include <fmtftn.hxx> 30 #include <ftnidx.hxx> 31 #include <pagefrm.hxx> 32 #include <colfrm.hxx> 33 #include <rootfrm.hxx> 34 #include <cntfrm.hxx> 35 #include <doc.hxx> 36 #include <ndtxt.hxx> 37 #include <frmtool.hxx> 38 #include <swtable.hxx> 39 #include <ftnfrm.hxx> 40 #include <txtfrm.hxx> 41 #include <tabfrm.hxx> 42 #include <pagedesc.hxx> 43 #include <ftninfo.hxx> 44 #include <ndindex.hxx> 45 #include <sectfrm.hxx> 46 #include <pam.hxx> 47 #include <objectformatter.hxx> 48 #include "viewopt.hxx" 49 #include "viewsh.hxx" 50 #include <switerator.hxx> 51 52 /************************************************************************* 53 |* 54 |* lcl_FindFtnPos() Sucht die Position des Attributes im FtnArray am 55 |* Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem 56 |* Index sortiert. 57 |* 58 |*************************************************************************/ 59 60 #define ENDNOTE 0x80000000 61 62 sal_uLong MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr ) 63 { 64 const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs(); 65 66 #ifdef MA_DEBUG 67 //Wenn das Array nicht stimmt haben wir ein Problem, denn viele 68 //Ftn-Functions bauen auf dem Array auf. 69 for ( sal_uInt16 k = 0; k+1 < rFtnIdxs.Count(); ++k ) 70 { 71 SwIndex aIdx1(&pDoc->GetNodes()); 72 SwIndex aIdx2(&pDoc->GetNodes()); 73 rFtnIdxs[k]->pFtn-> GetTxtNode().GetIndex(aIdx1); 74 rFtnIdxs[k+1]->pFtn->GetTxtNode().GetIndex(aIdx2); 75 if ( aIdx1.GetIndex() > aIdx2.GetIndex() ) 76 { 77 ASSERT( !rFtnIdxs.Count(), "FtnIdxs not up to date" ); 78 } 79 else if ( aIdx1.GetIndex() == aIdx2.GetIndex() ) 80 { 81 SwTxtFtn *p1 = rFtnIdxs[k]; 82 SwTxtFtn *p2 = rFtnIdxs[k+1]; 83 ASSERT( *p1->GetStart() < *p2->GetStart(), 84 "FtnIdxs not up to date" ); 85 } 86 } 87 #endif 88 89 sal_uInt16 nRet; 90 SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr; 91 if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) ) 92 { 93 if( pAttr->GetFtn().IsEndNote() ) 94 return sal_uLong(nRet) + ENDNOTE; 95 return nRet; 96 } 97 ASSERT( !pDoc, "FtnPos not found." ); 98 return 0; 99 } 100 101 sal_Bool SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const 102 { 103 const SwDoc* pDoc = GetFmt()->GetDoc(); 104 ASSERT( pDoc, "SwFtnFrm: Missing doc!" ); 105 return lcl_FindFtnPos( pDoc, GetAttr() ) < 106 lcl_FindFtnPos( pDoc, pTxtFtn ); 107 } 108 109 /************************************************************************* 110 |* 111 |* sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage) 112 |* setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte 113 |* oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird 114 |* enthaelt pPage die neue Seite und die Funktion liefert sal_True. 115 |* 116 |*************************************************************************/ 117 118 sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage, 119 sal_Bool bDontLeave ) 120 { 121 if( rpBoss->IsColumnFrm() ) 122 { 123 if( rpBoss->GetNext() ) 124 { 125 rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte 126 return sal_False; 127 } 128 if( rpBoss->IsInSct() ) 129 { 130 SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow(); 131 if( pSct ) 132 { 133 ASSERT( pSct->Lower() && pSct->Lower()->IsColumnFrm(), 134 "Where's the column?" ); 135 rpBoss = (SwColumnFrm*)pSct->Lower(); 136 SwPageFrm* pOld = rpPage; 137 rpPage = pSct->FindPageFrm(); 138 return pOld != rpPage; 139 } 140 else if( bDontLeave ) 141 { 142 rpPage = NULL; 143 rpBoss = NULL; 144 return sal_False; 145 } 146 } 147 } 148 rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite 149 rpBoss = rpPage; 150 if( rpPage ) 151 { 152 SwLayoutFrm* pBody = rpPage->FindBodyCont(); 153 if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 154 rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte 155 } 156 return sal_True; 157 } 158 159 /************************************************************************* 160 |* 161 |* sal_uInt16 lcl_ColumnNum( SwFrm* pBoss ) 162 |* liefert die Spaltennummer, wenn pBoss eine Spalte ist, 163 |* sonst eine Null (bei Seiten). 164 |* 165 |*************************************************************************/ 166 167 sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss ) 168 { 169 sal_uInt16 nRet = 0; 170 if( !pBoss->IsColumnFrm() ) 171 return 0; 172 const SwFrm* pCol; 173 if( pBoss->IsInSct() ) 174 { 175 pCol = pBoss->GetUpper()->FindColFrm(); 176 if( pBoss->GetNext() || pBoss->GetPrev() ) 177 { 178 while( pBoss ) 179 { 180 ++nRet; // Section columns 181 pBoss = pBoss->GetPrev(); 182 } 183 } 184 } 185 else 186 pCol = pBoss; 187 while( pCol ) 188 { 189 nRet += 256; // Page columns 190 pCol = pCol->GetPrev(); 191 } 192 return nRet; 193 } 194 195 /************************************************************************* 196 |* 197 |* SwFtnContFrm::SwFtnContFrm() 198 |* 199 |*************************************************************************/ 200 201 202 SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ): 203 SwLayoutFrm( pFmt, pSib ) 204 { 205 nType = FRMC_FTNCONT; 206 } 207 208 209 // lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab 210 // und liefert die Summe aller TxtFrm-Vergroesserungswuensche 211 212 long lcl_Undersize( const SwFrm* pFrm ) 213 { 214 long nRet = 0; 215 SWRECTFN( pFrm ) 216 if( pFrm->IsTxtFrm() ) 217 { 218 if( ((SwTxtFrm*)pFrm)->IsUndersized() ) 219 { 220 // Dieser TxtFrm waere gern ein bisschen groesser 221 nRet = ((SwTxtFrm*)pFrm)->GetParHeight() - 222 (pFrm->Prt().*fnRect->fnGetHeight)(); 223 if( nRet < 0 ) 224 nRet = 0; 225 } 226 } 227 else if( pFrm->IsLayoutFrm() ) 228 { 229 const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower(); 230 while( pNxt ) 231 { 232 nRet += lcl_Undersize( pNxt ); 233 pNxt = pNxt->GetNext(); 234 } 235 } 236 return nRet; 237 } 238 239 /************************************************************************* 240 |* 241 |* SwFtnContFrm::Format() 242 |* 243 |* Beschreibung: "Formatiert" den Frame; 244 |* Die Fixsize wird hier nicht eingestellt. 245 |* 246 |*************************************************************************/ 247 248 249 void SwFtnContFrm::Format( const SwBorderAttrs * ) 250 { 251 //GesamtBorder ermitteln, es gibt nur einen Abstand nach oben. 252 const SwPageFrm* pPage = FindPageFrm(); 253 const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo(); 254 const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() + 255 rInf.GetLineWidth(); 256 SWRECTFN( this ) 257 if ( !bValidPrtArea ) 258 { 259 bValidPrtArea = sal_True; 260 (Prt().*fnRect->fnSetTop)( nBorder ); 261 (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() ); 262 (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder ); 263 if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() ) 264 bValidSize = sal_False; 265 } 266 267 if ( !bValidSize ) 268 { 269 bool bGrow = pPage->IsFtnPage(); 270 if( bGrow ) 271 { 272 const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 273 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 274 bGrow = false; 275 } 276 if( bGrow ) 277 Grow( LONG_MAX, sal_False ); 278 else 279 { 280 //Die Groesse in der VarSize wird durch den Inhalt plus den 281 //Raendern bestimmt. 282 SwTwips nRemaining = 0; 283 SwFrm *pFrm = pLower; 284 while ( pFrm ) 285 { // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne 286 // groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen, 287 // wenn diese noch nicht ihre maximale Groesse haben. 288 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)() 289 + lcl_Undersize( pFrm ); 290 pFrm = pFrm->GetNext(); 291 } 292 //Jetzt noch den Rand addieren 293 nRemaining += nBorder; 294 295 SwTwips nDiff; 296 if( IsInSct() ) 297 { 298 nDiff = -(Frm().*fnRect->fnBottomDist)( 299 (GetUpper()->*fnRect->fnGetPrtBottom)() ); 300 if( nDiff > 0 ) 301 { 302 if( nDiff > (Frm().*fnRect->fnGetHeight)() ) 303 nDiff = (Frm().*fnRect->fnGetHeight)(); 304 (Frm().*fnRect->fnAddBottom)( -nDiff ); 305 (Prt().*fnRect->fnAddHeight)( -nDiff ); 306 } 307 } 308 nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining; 309 if ( nDiff > 0 ) 310 Shrink( nDiff ); 311 else if ( nDiff < 0 ) 312 { 313 Grow( -nDiff ); 314 //Es kann passieren, dass weniger Platz zur Verfuegung steht, 315 //als der bereits der Border benoetigt - die Groesse der 316 //PrtArea wird dann negativ. 317 SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)(); 318 if( nPrtHeight < 0 ) 319 { 320 const SwTwips nTmpDiff = Max( (Prt().*fnRect->fnGetTop)(), 321 -nPrtHeight ); 322 (Prt().*fnRect->fnSubTop)( nTmpDiff ); 323 } 324 } 325 } 326 bValidSize = sal_True; 327 } 328 } 329 /************************************************************************* 330 |* 331 |* SwFtnContFrm::GrowFrm(), ShrinkFrm() 332 |* 333 |*************************************************************************/ 334 335 SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool ) 336 { 337 //Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis 338 //zur Maximalhoehe variabel. 339 //Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben 340 //moeglich. 341 //Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch 342 //soviel Platz wie eben moeglich. 343 #ifdef DBG_UTIL 344 if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() ) 345 { ASSERT( !this, "Keine FtnBoss." ); 346 return 0; 347 } 348 #endif 349 350 SWRECTFN( this ) 351 if( (Frm().*fnRect->fnGetHeight)() > 0 && 352 nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) ) 353 nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)(); 354 355 SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper(); 356 if( IsInSct() ) 357 { 358 SwSectionFrm* pSect = FindSctFrm(); 359 ASSERT( pSect, "GrowFrm: Missing SectFrm" ); 360 // In a section, which has to maximize, a footnotecontainer is allowed 361 // to grow, when the section can't grow anymore. 362 if( !bTst && !pSect->IsColLocked() && 363 pSect->ToMaximize( sal_False ) && pSect->Growable() ) 364 { 365 pSect->InvalidateSize(); 366 return 0; 367 } 368 } 369 const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 370 const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode(); 371 SwPageFrm *pPage = pBoss->FindPageFrm(); 372 if ( bBrowseMode || !pPage->IsFtnPage() ) 373 { 374 if ( pBoss->GetMaxFtnHeight() != LONG_MAX ) 375 { 376 nDist = Min( nDist, pBoss->GetMaxFtnHeight() 377 - (Frm().*fnRect->fnGetHeight)() ); 378 if ( nDist <= 0 ) 379 return 0L; 380 } 381 //Der FtnBoss will bezueglich des MaxWerts auch noch mitreden. 382 if( !IsInSct() ) 383 { 384 const SwTwips nMax = pBoss->GetVarSpace(); 385 if ( nDist > nMax ) 386 nDist = nMax; 387 if ( nDist <= 0 ) 388 return 0L; 389 } 390 } 391 else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() ) 392 //aber mehr als der Body kann koennen und wollen wir nun auch wieder 393 //nicht herausruecken. 394 nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)(); 395 396 long nAvail = 0; 397 if ( bBrowseMode ) 398 { 399 nAvail = GetUpper()->Prt().Height(); 400 const SwFrm *pAvail = GetUpper()->Lower(); 401 do 402 { nAvail -= pAvail->Frm().Height(); 403 pAvail = pAvail->GetNext(); 404 } while ( pAvail ); 405 if ( nAvail > nDist ) 406 nAvail = nDist; 407 } 408 409 if ( !bTst ) 410 { 411 (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist ); 412 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 413 if( IsVertical() && !IsVertLR() && !IsReverse() ) 414 Frm().Pos().X() -= nDist; 415 } 416 long nGrow = nDist - nAvail, 417 nReal = 0; 418 if ( nGrow > 0 ) 419 { 420 sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this ); 421 if( NA_ONLY_ADJUST == nAdjust ) 422 nReal = AdjustNeighbourhood( nGrow, bTst ); 423 else 424 { 425 if( NA_GROW_ADJUST == nAdjust ) 426 { 427 SwFrm* pFtn = Lower(); 428 if( pFtn ) 429 { 430 while( pFtn->GetNext() ) 431 pFtn = pFtn->GetNext(); 432 if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() ) 433 { 434 nReal = AdjustNeighbourhood( nGrow, bTst ); 435 nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood 436 } 437 } 438 } 439 nReal += pBoss->Grow( nGrow - nReal, bTst ); 440 if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust ) 441 && nReal < nGrow ) 442 nReal += AdjustNeighbourhood( nGrow - nReal, bTst ); 443 } 444 } 445 446 nReal += nAvail; 447 448 if ( !bTst ) 449 { 450 if ( nReal != nDist ) 451 { 452 nDist -= nReal; 453 //Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen. 454 Frm().SSize().Height() -= nDist; 455 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 456 if( IsVertical() && !IsVertLR() && !IsReverse() ) 457 Frm().Pos().X() += nDist; 458 } 459 460 //Nachfolger braucht nicht invalidiert werden, denn wir wachsen 461 //immer nach oben. 462 if( nReal ) 463 { 464 _InvalidateSize(); 465 _InvalidatePos(); 466 InvalidatePage( pPage ); 467 } 468 } 469 return nReal; 470 } 471 472 473 SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, sal_Bool bTst, sal_Bool bInfo ) 474 { 475 SwPageFrm *pPage = FindPageFrm(); 476 bool bShrink = false; 477 if ( pPage ) 478 { 479 if( !pPage->IsFtnPage() ) 480 bShrink = true; 481 else 482 { 483 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 484 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 485 bShrink = true; 486 } 487 } 488 if( bShrink ) 489 { 490 SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo ); 491 if( IsInSct() && !bTst ) 492 FindSctFrm()->InvalidateNextPos(); 493 if ( !bTst && nRet ) 494 { 495 _InvalidatePos(); 496 InvalidatePage( pPage ); 497 } 498 return nRet; 499 } 500 return 0; 501 } 502 503 504 /************************************************************************* 505 |* 506 |* SwFtnFrm::SwFtnFrm() 507 |* 508 |*************************************************************************/ 509 510 511 SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ): 512 SwLayoutFrm( pFmt, pSib ), 513 pFollow( 0 ), 514 pMaster( 0 ), 515 pRef( pCnt ), 516 pAttr( pAt ), 517 bBackMoveLocked( sal_False ), 518 // --> OD 2005-08-11 #i49383# 519 mbUnlockPosOfLowerObjs( true ) 520 // <-- 521 { 522 nType = FRMC_FTN; 523 } 524 525 /************************************************************************* 526 |* 527 |* SwFtnFrm::InvalidateNxtFtnCnts() 528 |* 529 |*************************************************************************/ 530 531 532 void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage ) 533 { 534 if ( GetNext() ) 535 { 536 SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny(); 537 if( pCnt ) 538 { 539 pCnt->InvalidatePage( pPage ); 540 pCnt->_InvalidatePrt(); 541 do 542 { pCnt->_InvalidatePos(); 543 if( pCnt->IsSctFrm() ) 544 { 545 SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); 546 if( pTmp ) 547 pTmp->_InvalidatePos(); 548 } 549 pCnt->GetUpper()->_InvalidateSize(); 550 pCnt = pCnt->FindNext(); 551 } while ( pCnt && GetUpper()->IsAnLower( pCnt ) ); 552 } 553 } 554 } 555 556 #ifdef DBG_UTIL 557 558 SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 559 { 560 #if OSL_DEBUG_LEVEL > 1 561 static sal_uInt16 nNum = USHRT_MAX; 562 SwTxtFtn* pTxtFtn = GetAttr(); 563 if ( pTxtFtn->GetFtn().GetNumber() == nNum ) 564 { 565 int bla = 5; 566 (void)bla; 567 568 } 569 #endif 570 return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo ); 571 } 572 573 574 SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo ) 575 { 576 #if OSL_DEBUG_LEVEL > 1 577 static sal_uInt16 nNum = USHRT_MAX; 578 if( nNum != USHRT_MAX ) 579 { 580 SwTxtFtn* pTxtFtn = GetAttr(); 581 if( &pTxtFtn->GetAttr() && pTxtFtn->GetFtn().GetNumber() == nNum ) 582 { 583 int bla = 5; 584 (void)bla; 585 } 586 } 587 #endif 588 return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo ); 589 } 590 #endif 591 592 /************************************************************************* 593 |* 594 |* SwFtnFrm::Cut() 595 |* 596 |*************************************************************************/ 597 598 599 void SwFtnFrm::Cut() 600 { 601 if ( GetNext() ) 602 GetNext()->InvalidatePos(); 603 else if ( GetPrev() ) 604 GetPrev()->SetRetouche(); 605 606 //Erst removen, dann Upper Shrinken. 607 SwLayoutFrm *pUp = GetUpper(); 608 609 //Verkettung korrigieren. 610 SwFtnFrm *pFtn = (SwFtnFrm*)this; 611 if ( pFtn->GetFollow() ) 612 pFtn->GetFollow()->SetMaster( pFtn->GetMaster() ); 613 if ( pFtn->GetMaster() ) 614 pFtn->GetMaster()->SetFollow( pFtn->GetFollow() ); 615 pFtn->SetFollow( 0 ); 616 pFtn->SetMaster( 0 ); 617 618 // Alle Verbindungen kappen. 619 Remove(); 620 621 if ( pUp ) 622 { 623 //Die letzte Fussnote nimmt ihren Container mit. 624 if ( !pUp->Lower() ) 625 { 626 SwPageFrm *pPage = pUp->FindPageFrm(); 627 if ( pPage ) 628 { 629 SwLayoutFrm *pBody = pPage->FindBodyCont(); 630 if( pBody && !pBody->ContainsCntnt() ) 631 pPage->getRootFrm()->SetSuperfluous(); 632 } 633 SwSectionFrm* pSect = pUp->FindSctFrm(); 634 pUp->Cut(); 635 delete pUp; 636 // Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet, 637 // so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen. 638 if( pSect && !pSect->ToMaximize( sal_False ) && !pSect->IsColLocked() ) 639 pSect->_InvalidateSize(); 640 } 641 else 642 { if ( Frm().Height() ) 643 pUp->Shrink( Frm().Height() ); 644 pUp->SetCompletePaint(); 645 pUp->InvalidatePage(); 646 } 647 } 648 } 649 650 /************************************************************************* 651 |* 652 |* SwFtnFrm::Paste() 653 |* 654 |*************************************************************************/ 655 656 657 void SwFtnFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) 658 { 659 ASSERT( pParent, "Kein Parent fuer Paste." ); 660 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." ); 661 ASSERT( pParent != this, "Bin selbst der Parent." ); 662 ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); 663 ASSERT( !GetPrev() && !GetNext() && !GetUpper(), 664 "Bin noch irgendwo angemeldet." ); 665 666 //In den Baum einhaengen. 667 InsertBefore( (SwLayoutFrm*)pParent, pSibling ); 668 669 SWRECTFN( this ) 670 if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() ) 671 _InvalidateSize(); 672 _InvalidatePos(); 673 SwPageFrm *pPage = FindPageFrm(); 674 InvalidatePage( pPage ); 675 if ( GetNext() ) 676 GetNext()->_InvalidatePos(); 677 if( (Frm().*fnRect->fnGetHeight)() ) 678 pParent->Grow( (Frm().*fnRect->fnGetHeight)() ); 679 680 //Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein 681 //Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten. 682 if ( GetPrev() && GetPrev() == GetMaster() ) 683 { ASSERT( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ), 684 "Fussnote ohne Inhalt?" ); 685 (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))-> 686 MoveSubTree( this, GetLower() ); 687 SwFrm *pDel = GetPrev(); 688 pDel->Cut(); 689 delete pDel; 690 } 691 if ( GetNext() && GetNext() == GetFollow() ) 692 { ASSERT( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ), 693 "Fussnote ohne Inhalt?" ); 694 (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this ); 695 SwFrm *pDel = GetNext(); 696 pDel->Cut(); 697 delete pDel; 698 } 699 #ifdef DBG_UTIL 700 SwDoc *pDoc = GetFmt()->GetDoc(); 701 if ( GetPrev() ) 702 { 703 ASSERT( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <= 704 lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" ); 705 } 706 if ( GetNext() ) 707 { 708 ASSERT( lcl_FindFtnPos( pDoc, GetAttr() ) <= 709 lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ), 710 "Next is not FtnNext" ); 711 } 712 #endif 713 InvalidateNxtFtnCnts( pPage ); 714 } 715 716 /************************************************************************* 717 |* 718 |* SwFrm::GetNextFtnLeaf() 719 |* 720 |* Beschreibung Liefert das naechste LayoutBlatt in den das 721 |* Frame gemoved werden kann. 722 |* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist. 723 |* 724 |*************************************************************************/ 725 726 727 SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage ) 728 { 729 SwFtnBossFrm *pOldBoss = FindFtnBossFrm(); 730 SwPageFrm* pOldPage = pOldBoss->FindPageFrm(); 731 SwPageFrm* pPage; 732 SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ? 733 (SwFtnBossFrm*)pOldBoss->GetNext() : 0; // naechste Spalte, wenn vorhanden 734 if( pBoss ) 735 pPage = NULL; 736 else 737 { 738 if( pOldBoss->GetUpper()->IsSctFrm() ) 739 { // Das kann nur in einem spaltigen Bereich sein 740 SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage ); 741 if( pNxt ) 742 { 743 ASSERT( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" ); 744 pBoss = (SwFtnBossFrm*)pNxt->GetUpper(); 745 pPage = pBoss->FindPageFrm(); 746 } 747 else 748 return 0; 749 } 750 else 751 { 752 // naechste Seite 753 pPage = (SwPageFrm*)pOldPage->GetNext(); 754 // Leerseiten ueberspringen 755 if( pPage && pPage->IsEmptyPage() ) 756 pPage = (SwPageFrm*)pPage->GetNext(); 757 pBoss = pPage; 758 } 759 } 760 // Was haben wir jetzt? 761 // pBoss != NULL, pPage==NULL => pBoss ist die auf der gleichen Seite folgende Spalte 762 // pBoss != NULL, pPage!=NULL => pBoss und pPage sind die folgende Seite (Empty uebersprungen) 763 // pBoss == NULL => pPage == NULL, es gibt keine folgende Seite 764 765 //Wenn die Fussnote bereits einen Follow hat brauchen wir nicht zu suchen. 766 //Wenn allerdings zwischen Ftn und Follow unerwuenschte Leerseiten/spalten 767 //herumlungern, so legen wir auf der naechstbesten Seite/Spalte einen weiteren 768 //Follow an, der Rest wird sich schon finden. 769 SwFtnFrm *pFtn = FindFtnFrm(); 770 if ( pFtn && pFtn->GetFollow() ) 771 { 772 SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm(); 773 // Folgende Faelle werden hier erkannt und akzeptiert 774 // 1. Die FtnBosse sind benachbarte Seiten oder benachbarte Spalten 775 // 2. Der neue ist die erste Spalte der benachbarten Seite 776 // 3. Der neue ist die erste Spalte in einem Bereich in der naechsten Spalte/Seite 777 while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() ) 778 pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm(); 779 if( pTmpBoss == pBoss ) 780 return pFtn->GetFollow(); 781 } 782 783 // Wenn wir keinen pBoss gefunden haben oder es sich um eine "falsche" Seite handelt, 784 // muss eine neue Seite her 785 if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) ) 786 { 787 if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) 788 { 789 pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() ); 790 ((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() ); 791 } 792 else 793 return 0; 794 } 795 if( pBoss->IsPageFrm() ) 796 { // Wenn wir auf einer spaltigen Seite gelandet sind, 797 // gehen wir in die erste Spalte 798 SwLayoutFrm* pLay = pBoss->FindBodyCont(); 799 if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() ) 800 pBoss = (SwFtnBossFrm*)pLay->Lower(); 801 } 802 //Seite/Spalte gefunden, da schummeln wir uns doch gleich mal 'rein 803 SwFtnContFrm *pCont = pBoss->FindFtnCont(); 804 if ( !pCont && pBoss->GetMaxFtnHeight() && 805 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) ) 806 pCont = pBoss->MakeFtnCont(); 807 return pCont; 808 } 809 810 /************************************************************************* 811 |* 812 |* SwFrm::GetPrevFtnLeaf() 813 |* 814 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der 815 |* Frame gemoved werden kann. 816 |* 817 |*************************************************************************/ 818 819 820 SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn ) 821 { 822 //Der Vorgaenger fuer eine Fussnote ist falls moeglich der Master 823 //in der Fussnoteneigenen Verkettung. 824 SwLayoutFrm *pRet = 0; 825 SwFtnFrm *pFtn = FindFtnFrm(); 826 pRet = pFtn->GetMaster(); 827 828 SwFtnBossFrm* pOldBoss = FindFtnBossFrm(); 829 SwPageFrm *pOldPage = pOldBoss->FindPageFrm(); 830 831 if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() ) 832 return pRet; // es gibt weder eine Spalte noch eine Seite vor uns 833 834 if ( !pRet ) 835 { 836 bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote(); 837 SwFrm* pTmpRef = NULL; 838 if( bEndn && pFtn->IsInSct() ) 839 { 840 SwSectionFrm* pSect = pFtn->FindSctFrm(); 841 if( pSect->IsEndnAtEnd() ) 842 pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT ); 843 } 844 if( !pTmpRef ) 845 pTmpRef = pFtn->GetRef(); 846 SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn ); 847 848 const sal_uInt16 nNum = pStop->GetPhyPageNum(); 849 850 //Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir 851 //die Entsprechenden Seiten nicht. 852 //Selbiges gilt analog fuer die Endnotenseiten. 853 const sal_Bool bEndNote = pOldPage->IsEndNotePage(); 854 const sal_Bool bFtnEndDoc = pOldPage->IsFtnPage(); 855 SwFtnBossFrm* pNxtBoss = pOldBoss; 856 SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ? 857 (SwSectionFrm*)pNxtBoss->GetUpper() : 0; 858 859 do 860 { 861 if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() ) 862 pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev(); // eine Spalte zurueck 863 else // oder eine Seite zurueck 864 { 865 SwLayoutFrm* pBody = 0; 866 if( pSect ) 867 { 868 if( pSect->IsFtnLock() ) 869 { 870 if( pNxtBoss == pOldBoss ) 871 return 0; 872 pStop = pNxtBoss; 873 } 874 else 875 { 876 pSect = (SwSectionFrm*)pSect->FindMaster(); 877 if( !pSect || !pSect->Lower() ) 878 return 0; 879 ASSERT( pSect->Lower()->IsColumnFrm(), 880 "GetPrevFtnLeaf: Where's the column?" ); 881 pNxtBoss = (SwFtnBossFrm*)pSect->Lower(); 882 pBody = pSect; 883 } 884 } 885 else 886 { 887 SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev(); 888 if( !pPage || pPage->GetPhyPageNum() < nNum || 889 bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() ) 890 return NULL; // Keine in Frage kommende Seite mehr gefunden 891 pNxtBoss = pPage; 892 pBody = pPage->FindBodyCont(); 893 } 894 // Die vorherige Seite haben wir nun, ggf. sollten wir in die letzte Spalte 895 // der Seite wechseln 896 if( pBody ) 897 { 898 if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 899 { 900 pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower()); 901 } 902 } 903 } 904 SwFtnContFrm *pCont = pNxtBoss->FindFtnCont(); 905 if ( pCont ) 906 { 907 pRet = pCont; 908 break; 909 } 910 if ( pStop == pNxtBoss ) 911 { //Die Seite/Spalte auf der sich auch die Referenz tummelt, ist erreicht. 912 //Wir koennen jetzt probehalber mal einen Container erzeugen und 913 //uns hineinpasten. 914 if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() ) 915 pRet = pNxtBoss->MakeFtnCont(); 916 break; 917 } 918 } while( !pRet ); 919 } 920 if ( pRet ) 921 { 922 const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm(); 923 sal_Bool bJump = sal_False; 924 if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // es gibt eine vorherige Spalte 925 bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss; // sind wir darin gelandet? 926 else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() ) 927 bJump = sal_True; // es gibt hinter dem neuen Boss noch eine Spalte, die aber nicht 928 // der alte Boss sein kann, das haben wir ja bereits geprueft. 929 else // hier landen wir nur, wenn neuer und alter Boss entweder Seiten oder letzte (neu) 930 { // bzw. erste (alt) Spalten einer Seite sind. In diesem Fall muss noch geprueft 931 // werden, ob Seiten ueberspringen wurden. 932 sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum(); 933 if ( nDiff > 2 || 934 (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) ) 935 bJump = sal_True; 936 } 937 if( bJump ) 938 SwFlowFrm::SetMoveBwdJump( sal_True ); 939 } 940 return pRet; 941 } 942 943 /************************************************************************* 944 |* 945 |* SwFrm::IsFtnAllowed() 946 |* 947 |*************************************************************************/ 948 949 950 sal_Bool SwFrm::IsFtnAllowed() const 951 { 952 if ( !IsInDocBody() ) 953 return sal_False; 954 955 if ( IsInTab() ) 956 { 957 //Keine Ftns in wiederholten Headlines. 958 const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm(); 959 if ( pTab->IsFollow() ) 960 return !pTab->IsInHeadline( *this ); 961 } 962 return sal_True; 963 } 964 965 /************************************************************************* 966 |* 967 |* SwRootFrm::UpdateFtnNums() 968 |* 969 |*************************************************************************/ 970 971 972 void SwRootFrm::UpdateFtnNums() 973 { 974 //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist. 975 if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE ) 976 { 977 SwPageFrm *pPage = (SwPageFrm*)Lower(); 978 while ( pPage && !pPage->IsFtnPage() ) 979 { 980 pPage->UpdateFtnNum(); 981 pPage = (SwPageFrm*)pPage->GetNext(); 982 } 983 } 984 } 985 986 /************************************************************************* 987 |* 988 |* RemoveFtns() Entfernen aller Fussnoten (nicht etwa die Referenzen) 989 |* und Entfernen aller Fussnotenseiten. 990 |* 991 |*************************************************************************/ 992 993 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes ) 994 { 995 do 996 { 997 SwFtnContFrm *pCont = pBoss->FindFtnCont(); 998 if ( pCont ) 999 { 1000 SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower(); 1001 ASSERT( pFtn, "FtnCont ohne Ftn." ); 1002 if ( bPageOnly ) 1003 while ( pFtn->GetMaster() ) 1004 pFtn = pFtn->GetMaster(); 1005 do 1006 { 1007 SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext(); 1008 if ( !pFtn->GetAttr()->GetFtn().IsEndNote() || 1009 bEndNotes ) 1010 { 1011 pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() ); 1012 if ( bPageOnly && !pNxt ) 1013 pNxt = pFtn->GetFollow(); 1014 pFtn->Cut(); 1015 delete pFtn; 1016 } 1017 pFtn = pNxt; 1018 1019 } while ( pFtn ); 1020 } 1021 if( !pBoss->IsInSct() ) 1022 { 1023 // A sectionframe with the Ftn/EndnAtEnd-flags may contain 1024 // foot/endnotes. If the last lower frame of the bodyframe is 1025 // a multicolumned sectionframe, it may contain footnotes, too. 1026 SwLayoutFrm* pBody = pBoss->FindBodyCont(); 1027 if( pBody && pBody->Lower() ) 1028 { 1029 SwFrm* pLow = pBody->Lower(); 1030 while( pLow->GetNext() ) 1031 { 1032 if( pLow->IsSctFrm() && ( !pLow->GetNext() || 1033 ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) && 1034 ((SwSectionFrm*)pLow)->Lower() && 1035 ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() ) 1036 lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(), 1037 bPageOnly, bEndNotes ); 1038 pLow = pLow->GetNext(); 1039 } 1040 } 1041 } 1042 // noch 'ne Spalte? 1043 pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL; 1044 } while( pBoss ); 1045 } 1046 1047 void SwRootFrm::RemoveFtns( SwPageFrm *pPage, sal_Bool bPageOnly, sal_Bool bEndNotes ) 1048 { 1049 if ( !pPage ) 1050 pPage = (SwPageFrm*)Lower(); 1051 1052 do 1053 { // Bei spaltigen Seiten muessen wir in allen Spalten aufraeumen 1054 SwFtnBossFrm* pBoss; 1055 SwLayoutFrm* pBody = pPage->FindBodyCont(); 1056 if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 1057 pBoss = (SwFtnBossFrm*)pBody->Lower(); // die erste Spalte 1058 else 1059 pBoss = pPage; // keine Spalten 1060 lcl_RemoveFtns( pBoss, bPageOnly, bEndNotes ); 1061 if ( !bPageOnly ) 1062 { 1063 if ( pPage->IsFtnPage() && 1064 (!pPage->IsEndNotePage() || bEndNotes) ) 1065 { 1066 SwFrm *pDel = pPage; 1067 pPage = (SwPageFrm*)pPage->GetNext(); 1068 pDel->Cut(); 1069 delete pDel; 1070 } 1071 else 1072 pPage = (SwPageFrm*)pPage->GetNext(); 1073 } 1074 else 1075 break; 1076 1077 } while ( pPage ); 1078 } 1079 1080 /************************************************************************* 1081 |* 1082 |* SetFtnPageDescs() Seitenvorlagen der Fussnotenseiten aendern 1083 |* 1084 |*************************************************************************/ 1085 1086 void SwRootFrm::CheckFtnPageDescs( sal_Bool bEndNote ) 1087 { 1088 SwPageFrm *pPage = (SwPageFrm*)Lower(); 1089 while ( pPage && !pPage->IsFtnPage() ) 1090 pPage = (SwPageFrm*)pPage->GetNext(); 1091 while ( pPage && pPage->IsEndNotePage() != bEndNote ) 1092 pPage = (SwPageFrm*)pPage->GetNext(); 1093 if ( pPage ) 1094 SwFrm::CheckPageDescs( pPage, sal_False ); 1095 } 1096 1097 1098 /************************************************************************* 1099 |* 1100 |* SwFtnBossFrm::MakeFtnCont() 1101 |* 1102 |*************************************************************************/ 1103 1104 1105 SwFtnContFrm *SwFtnBossFrm::MakeFtnCont() 1106 { 1107 //Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt 1108 //immer direkt hinter dem Bodytext. 1109 //Sein FrmFmt ist immer das DefaultFrmFmt. 1110 1111 #ifdef DBG_UTIL 1112 if ( FindFtnCont() ) 1113 { ASSERT( !this, "Fussnotencontainer bereits vorhanden." ); 1114 return 0; 1115 } 1116 #endif 1117 1118 SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt(), this ); 1119 SwLayoutFrm *pLay = FindBodyCont(); 1120 pNew->Paste( this, pLay->GetNext() ); 1121 return pNew; 1122 } 1123 1124 /************************************************************************* 1125 |* 1126 |* SwFtnBossFrm::FindFtnCont() 1127 |* 1128 |*************************************************************************/ 1129 1130 1131 SwFtnContFrm *SwFtnBossFrm::FindFtnCont() 1132 { 1133 SwFrm *pFrm = Lower(); 1134 while( pFrm && !pFrm->IsFtnContFrm() ) 1135 pFrm = pFrm->GetNext(); 1136 1137 #ifdef DBG_UTIL 1138 if ( pFrm ) 1139 { 1140 SwFrm *pFtn = pFrm->GetLower(); 1141 ASSERT( pFtn, "Cont ohne Fussnote." ); 1142 while ( pFtn ) 1143 { 1144 ASSERT( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." ); 1145 pFtn = pFtn->GetNext(); 1146 } 1147 } 1148 #endif 1149 1150 return (SwFtnContFrm*)pFrm; 1151 } 1152 1153 /************************************************************************* 1154 |* 1155 |* SwFtnBossFrm::FindNearestFtnCont() Sucht den naechst greifbaren Fussnotencontainer. 1156 |* 1157 |*************************************************************************/ 1158 1159 SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( sal_Bool bDontLeave ) 1160 { 1161 SwFtnContFrm *pCont = 0; 1162 if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() ) 1163 { 1164 pCont = FindFtnCont(); 1165 if ( !pCont ) 1166 { 1167 SwPageFrm *pPage = FindPageFrm(); 1168 SwFtnBossFrm* pBoss = this; 1169 sal_Bool bEndNote = pPage->IsEndNotePage(); 1170 do 1171 { 1172 sal_Bool bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave ); 1173 // Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss 1174 // zudem noch das EndNotenFlag uebereinstimmen 1175 if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) ) 1176 pCont = pBoss->FindFtnCont(); 1177 } while ( !pCont && pPage ); 1178 } 1179 } 1180 return pCont; 1181 } 1182 1183 1184 /************************************************************************* 1185 |* 1186 |* SwFtnBossFrm::FindFirstFtn() 1187 |* 1188 |* Beschreibung Erste Fussnote des Fussnotenbosses suchen. 1189 |* 1190 |*************************************************************************/ 1191 1192 1193 SwFtnFrm *SwFtnBossFrm::FindFirstFtn() 1194 { 1195 //Erstmal den naechsten FussnotenContainer suchen. 1196 SwFtnContFrm *pCont = FindNearestFtnCont(); 1197 if ( !pCont ) 1198 return 0; 1199 1200 //Ab der ersten Fussnote im Container die erste suchen, die 1201 //von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird. 1202 1203 SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower(); 1204 const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum(); 1205 const sal_uInt16 nRefCol = lcl_ColumnNum( this ); 1206 sal_uInt16 nPgNum, nColNum; //Seitennummer, Spaltennummer 1207 SwFtnBossFrm* pBoss; 1208 SwPageFrm* pPage; 1209 if( pRet ) 1210 { 1211 pBoss = pRet->GetRef()->FindFtnBossFrm(); 1212 ASSERT( pBoss, "FindFirstFtn: No boss found" ); 1213 if( !pBoss ) 1214 return NULL; // ?There must be a bug, but no GPF 1215 pPage = pBoss->FindPageFrm(); 1216 nPgNum = pPage->GetPhyPageNum(); 1217 if ( nPgNum == nRefNum ) 1218 { 1219 nColNum = lcl_ColumnNum( pBoss ); 1220 if( nColNum == nRefCol ) 1221 return pRet; //hat ihn. 1222 else if( nColNum > nRefCol ) 1223 return NULL; //mind. eine Spalte zu weit. 1224 } 1225 else if ( nPgNum > nRefNum ) 1226 return NULL; //mind. eine Seite zu weit. 1227 } 1228 else 1229 return NULL; 1230 // Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer 1231 // spaeteren Spalte liegt 1232 1233 do 1234 { 1235 while ( pRet->GetFollow() ) 1236 pRet = pRet->GetFollow(); 1237 1238 SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext(); 1239 if ( !pNxt ) 1240 { 1241 pBoss = pRet->FindFtnBossFrm(); 1242 pPage = pBoss->FindPageFrm(); 1243 lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss 1244 pCont = pBoss ? pBoss->FindNearestFtnCont() : 0; 1245 if ( pCont ) 1246 pNxt = (SwFtnFrm*)pCont->Lower(); 1247 } 1248 if ( pNxt ) 1249 { 1250 pRet = pNxt; 1251 pBoss = pRet->GetRef()->FindFtnBossFrm(); 1252 pPage = pBoss->FindPageFrm(); 1253 nPgNum = pPage->GetPhyPageNum(); 1254 if ( nPgNum == nRefNum ) 1255 { 1256 nColNum = lcl_ColumnNum( pBoss ); 1257 if( nColNum == nRefCol ) 1258 break; //hat ihn. 1259 else if( nColNum > nRefCol ) 1260 pRet = 0; //mind. eine Spalte zu weit. 1261 } 1262 else if ( nPgNum > nRefNum ) 1263 pRet = 0; //mind. eine Seite zu weit. 1264 } 1265 else 1266 pRet = 0; //Gibt eben keinen. 1267 } while( pRet ); 1268 return pRet; 1269 } 1270 1271 /************************************************************************* 1272 |* 1273 |* SwFtnBossFrm::FindFirstFtn() 1274 |* 1275 |* Beschreibunt Erste Fussnote zum Cnt suchen. 1276 |* 1277 |*************************************************************************/ 1278 1279 1280 const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const 1281 { 1282 const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn(); 1283 if ( pRet ) 1284 { 1285 const sal_uInt16 nColNum = lcl_ColumnNum( this ); //Spaltennummer 1286 const sal_uInt16 nPageNum = GetPhyPageNum(); 1287 while ( pRet && (pRet->GetRef() != pCnt) ) 1288 { 1289 while ( pRet->GetFollow() ) 1290 pRet = pRet->GetFollow(); 1291 1292 if ( pRet->GetNext() ) 1293 pRet = (const SwFtnFrm*)pRet->GetNext(); 1294 else 1295 { SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm(); 1296 SwPageFrm *pPage = pBoss->FindPageFrm(); 1297 lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss 1298 SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0; 1299 pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0; 1300 } 1301 if ( pRet ) 1302 { 1303 const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm(); 1304 if( pBoss->GetPhyPageNum() != nPageNum || 1305 nColNum != lcl_ColumnNum( pBoss ) ) 1306 pRet = 0; 1307 } 1308 } 1309 } 1310 return pRet; 1311 } 1312 1313 /************************************************************************* 1314 |* 1315 |* SwFtnBossFrm::ResetFtn() 1316 |* 1317 |*************************************************************************/ 1318 1319 1320 void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck ) 1321 { 1322 //Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht 1323 //zu pAssumed gehoeren. 1324 ASSERT( !pCheck->GetMaster(), "Master not an Master." ); 1325 1326 SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 ); 1327 SwCntntNode *pNd = aIdx.GetNode().GetCntntNode(); 1328 if ( !pNd ) 1329 pNd = pCheck->GetFmt()->GetDoc()-> 1330 GetNodes().GoNextSection( &aIdx, sal_True, sal_False ); 1331 SwIterator<SwFrm,SwCntntNode> aIter( *pNd ); 1332 SwFrm* pFrm = aIter.First(); 1333 while( pFrm ) 1334 { 1335 if( pFrm->getRootFrm() == pCheck->getRootFrm() ) 1336 { 1337 SwFrm *pTmp = pFrm->GetUpper(); 1338 while ( pTmp && !pTmp->IsFtnFrm() ) 1339 pTmp = pTmp->GetUpper(); 1340 1341 SwFtnFrm *pFtn = (SwFtnFrm*)pTmp; 1342 while ( pFtn && pFtn->GetMaster() ) 1343 pFtn = pFtn->GetMaster(); 1344 if ( pFtn != pCheck ) 1345 { 1346 while ( pFtn ) 1347 { 1348 SwFtnFrm *pNxt = pFtn->GetFollow(); 1349 pFtn->Cut(); 1350 delete pFtn; 1351 pFtn = pNxt; 1352 } 1353 } 1354 } 1355 1356 pFrm = aIter.Next(); 1357 } 1358 } 1359 1360 /************************************************************************* 1361 |* 1362 |* SwFtnBossFrm::InsertFtn() 1363 |* 1364 |*************************************************************************/ 1365 1366 1367 void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew ) 1368 { 1369 #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL) 1370 static sal_uInt16 nStop = 0; 1371 if ( nStop == pNew->GetFrmId() ) 1372 { 1373 int bla = 5; 1374 (void)bla; 1375 } 1376 #endif 1377 //Die Fussnote haben wir, sie muss jetzt nur noch irgendwo 1378 //hin und zwar vor die Fussnote, deren Attribut vor das 1379 //der neuen zeigt (Position wird ueber das Doc ermittelt) 1380 //Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein 1381 //Container erzeugt werden. 1382 //Gibt es bereits einen Container aber noch keine Fussnote zu diesem 1383 //Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten 1384 //Vorseite/spalte. 1385 1386 ResetFtn( pNew ); 1387 SwFtnFrm *pSibling = FindFirstFtn(); 1388 sal_Bool bDontLeave = sal_False; 1389 1390 // Ok, a sibling has been found, but is the sibling in an acceptable 1391 // environment? 1392 if( IsInSct() ) 1393 { 1394 SwSectionFrm* pMySect = ImplFindSctFrm(); 1395 bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote(); 1396 if( bEndnt ) 1397 { 1398 const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt(); 1399 bDontLeave = 0 != pEndFmt; 1400 if( pSibling ) 1401 { 1402 if( pEndFmt ) 1403 { 1404 if( !pSibling->IsInSct() || 1405 !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) ) 1406 pSibling = NULL; 1407 } 1408 else if( pSibling->IsInSct() ) 1409 pSibling = NULL; 1410 } 1411 } 1412 else 1413 { 1414 bDontLeave = pMySect->IsFtnAtEnd(); 1415 if( pSibling ) 1416 { 1417 if( pMySect->IsFtnAtEnd() ) 1418 { 1419 if( !pSibling->IsInSct() || 1420 !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) ) 1421 pSibling = NULL; 1422 } 1423 else if( pSibling->IsInSct() ) 1424 pSibling = NULL; 1425 } 1426 } 1427 } 1428 1429 if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() != 1430 FindPageFrm()->IsEndNotePage() ) 1431 pSibling = NULL; 1432 1433 //Damit die Position herausgefunden werden kann. 1434 SwDoc *pDoc = GetFmt()->GetDoc(); 1435 const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() ); 1436 1437 sal_uLong nCmpPos = 0; 1438 sal_uLong nLastPos = 0; 1439 SwFtnContFrm *pParent = 0; 1440 if( pSibling ) 1441 { 1442 nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); 1443 if( nCmpPos > nStPos ) 1444 pSibling = NULL; 1445 } 1446 1447 if ( !pSibling ) 1448 { pParent = FindFtnCont(); 1449 if ( !pParent ) 1450 { 1451 //Es gibt noch keinen FussnotenContainer, also machen wir einen. 1452 //HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann 1453 //sein, dass irgendeine naechste Fussnote existiert die vor der 1454 //einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig 1455 //Seiten aufgespalten ist usw. 1456 pParent = FindNearestFtnCont( bDontLeave ); 1457 if ( pParent ) 1458 { 1459 SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower(); 1460 if ( pFtn ) 1461 { 1462 1463 nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() ); 1464 if ( nCmpPos > nStPos ) 1465 pParent = 0; 1466 } 1467 else 1468 pParent = 0; 1469 } 1470 } 1471 if ( !pParent ) 1472 //Jetzt kann aber ein Fussnotencontainer gebaut werden. 1473 pParent = MakeFtnCont(); 1474 else 1475 { 1476 //Ausgehend von der ersten Fussnote unterhalb des Parents wird die 1477 //erste Fussnote gesucht deren Index hinter dem Index der 1478 //einzufuegenden liegt; vor dieser kann der neue dann gepastet 1479 //werden. 1480 pSibling = (SwFtnFrm*)pParent->Lower(); 1481 if ( !pSibling ) 1482 { ASSERT( !this, "Keinen Platz fuer Fussnote gefunden."); 1483 return; 1484 } 1485 nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); 1486 1487 SwFtnBossFrm *pNxtB = this; //Immer den letzten merken, damit wir nicht 1488 SwFtnFrm *pLastSib = 0; //ueber das Ziel hinausschiessen. 1489 1490 while ( pSibling && nCmpPos <= nStPos ) 1491 { 1492 pLastSib = pSibling; // der kommt schon mal in Frage 1493 nLastPos = nCmpPos; 1494 1495 while ( pSibling->GetFollow() ) 1496 pSibling = pSibling->GetFollow(); 1497 1498 if ( pSibling->GetNext() ) 1499 { 1500 pSibling = (SwFtnFrm*)pSibling->GetNext(); 1501 ASSERT( !pSibling->GetMaster() || ( ENDNOTE > nStPos && 1502 pSibling->GetAttr()->GetFtn().IsEndNote() ), 1503 "InsertFtn: Master expected I" ); 1504 } 1505 else 1506 { 1507 pNxtB = pSibling->FindFtnBossFrm(); 1508 SwPageFrm *pSibPage = pNxtB->FindPageFrm(); 1509 sal_Bool bEndNote = pSibPage->IsEndNotePage(); 1510 sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave ); 1511 // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden. 1512 SwFtnContFrm *pCont = pNxtB && ( !bChgPage || 1513 pSibPage->IsEndNotePage() == bEndNote ) 1514 ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0; 1515 if( pCont ) 1516 pSibling = (SwFtnFrm*)pCont->Lower(); 1517 else // kein weiterer FtnContainer, dann werden wir uns wohl hinter 1518 break; // pSibling haengen 1519 } 1520 if ( pSibling ) 1521 { 1522 nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); 1523 ASSERT( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" ); 1524 } 1525 } 1526 // pLastSib ist jetzt die letzte Fussnote vor uns, 1527 // pSibling leer oder die erste nach uns. 1528 if ( pSibling && pLastSib && (pSibling != pLastSib) ) 1529 { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen? 1530 if ( nCmpPos > nStPos ) 1531 pSibling = pLastSib; 1532 } 1533 else if ( !pSibling ) 1534 { //Eine Chance haben wir noch: wir nehmen einfach die letzte 1535 //Fussnote im Parent. Ein Sonderfall, der z.B. beim 1536 //zurueckfliessen von Absaetzen mit mehreren Fussnoten 1537 //vorkommt. 1538 //Damit wir nicht die Reihenfolge verwuerfeln muessen wir den 1539 //Parent der letzten Fussnote, die wir an der Hand hatten benutzen. 1540 pSibling = pLastSib; 1541 while( pSibling->GetFollow() ) 1542 pSibling = pSibling->GetFollow(); 1543 ASSERT( !pSibling->GetNext(), "InsertFtn: Who's that guy?" ); 1544 } 1545 } 1546 } 1547 else 1548 { //Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend 1549 //von dieser die erste zur selben Spalte/Seite suchen deren Index hinter 1550 //den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist 1551 //dann der Vorgaenger. 1552 SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm( 1553 !pNew->GetAttr()->GetFtn().IsEndNote() ); 1554 sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // Die Seiten- und 1555 sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // Spaltennummer der neuen Fussnote 1556 sal_Bool bEnd = sal_False; 1557 SwFtnFrm *pLastSib = 0; 1558 while ( pSibling && !bEnd && (nCmpPos <= nStPos) ) 1559 { 1560 pLastSib = pSibling; 1561 nLastPos = nCmpPos; 1562 1563 while ( pSibling->GetFollow() ) 1564 pSibling = pSibling->GetFollow(); 1565 1566 SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext(); 1567 if ( pFoll ) 1568 { 1569 pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling-> 1570 GetAttr()->GetFtn().IsEndNote() ); 1571 sal_uInt16 nTmpRef; 1572 if( nStPos >= ENDNOTE || 1573 (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum || 1574 ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol )) 1575 pSibling = pFoll; 1576 else 1577 bEnd = sal_True; 1578 } 1579 else 1580 { 1581 SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm(); 1582 SwPageFrm *pSibPage = pNxtB->FindPageFrm(); 1583 sal_Bool bEndNote = pSibPage->IsEndNotePage(); 1584 sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave ); 1585 // Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden. 1586 SwFtnContFrm *pCont = pNxtB && ( !bChgPage || 1587 pSibPage->IsEndNotePage() == bEndNote ) 1588 ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0; 1589 if ( pCont ) 1590 pSibling = (SwFtnFrm*)pCont->Lower(); 1591 else 1592 bEnd = sal_True; 1593 } 1594 if ( !bEnd && pSibling ) 1595 nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); 1596 if ( pSibling && pLastSib && (pSibling != pLastSib) ) 1597 { //Sind wir vielleicht bereits ueber das Ziel hinausgeschossen? 1598 if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) ) 1599 { 1600 pSibling = pLastSib; 1601 bEnd = sal_True; 1602 } 1603 } 1604 } 1605 } 1606 if ( pSibling ) 1607 { 1608 nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() ); 1609 if ( nCmpPos < nStPos ) 1610 { 1611 while ( pSibling->GetFollow() ) 1612 pSibling = pSibling->GetFollow(); 1613 pParent = (SwFtnContFrm*)pSibling->GetUpper(); 1614 pSibling = (SwFtnFrm*)pSibling->GetNext(); 1615 } 1616 else 1617 { 1618 if( pSibling->GetMaster() ) 1619 { 1620 if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE ) 1621 { 1622 ASSERT( sal_False, "InsertFtn: Master expected II" ); 1623 do 1624 pSibling = pSibling->GetMaster(); 1625 while ( pSibling->GetMaster() ); 1626 } 1627 } 1628 pParent = (SwFtnContFrm*)pSibling->GetUpper(); 1629 } 1630 } 1631 ASSERT( pParent, "paste in space?" ); 1632 pNew->Paste( pParent, pSibling ); 1633 } 1634 1635 /************************************************************************* 1636 |* 1637 |* SwFtnBossFrm::AppendFtn() 1638 |* 1639 |*************************************************************************/ 1640 1641 1642 void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr ) 1643 { 1644 //Wenn es die Fussnote schon gibt tun wir nix. 1645 if ( FindFtn( pRef, pAttr ) ) 1646 return; 1647 1648 //Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst 1649 //ab der entsprechenden Seite zu suchen. 1650 //Wenn es noch keine gibt, muss eben eine erzeugt werden. 1651 //Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht 1652 //bzw. erzeugt werden. 1653 SwDoc *pDoc = GetFmt()->GetDoc(); 1654 SwFtnBossFrm *pBoss = this; 1655 SwPageFrm *pPage = FindPageFrm(); 1656 SwPageFrm *pMyPage = pPage; 1657 sal_Bool bChgPage = sal_False; 1658 sal_Bool bEnd = sal_False; 1659 if ( pAttr->GetFtn().IsEndNote() ) 1660 { 1661 bEnd = sal_True; 1662 if( GetUpper()->IsSctFrm() && 1663 ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() ) 1664 { 1665 SwFrm* pLast = 1666 ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE ); 1667 if( pLast ) 1668 { 1669 pBoss = pLast->FindFtnBossFrm(); 1670 pPage = pBoss->FindPageFrm(); 1671 } 1672 } 1673 else 1674 { 1675 while ( pPage->GetNext() && !pPage->IsEndNotePage() ) 1676 { 1677 pPage = (SwPageFrm*)pPage->GetNext(); 1678 bChgPage = sal_True; 1679 } 1680 if ( !pPage->IsEndNotePage() ) 1681 { 1682 SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc ); 1683 pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), 1684 !pPage->OnRightPage(), sal_False, sal_True, 0 ); 1685 pPage->SetEndNotePage( sal_True ); 1686 bChgPage = sal_True; 1687 } 1688 else 1689 { 1690 //Wir koennen wenigstens schon mal ungefaehr die richtige Seite 1691 //suchen. Damit stellen wir sicher das wir auch bei hunderten 1692 //Fussnoten noch in endlicher Zeit fertig werden. 1693 SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext(); 1694 const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr ); 1695 while ( pNxt && pNxt->IsEndNotePage() ) 1696 { 1697 SwFtnContFrm *pCont = pNxt->FindFtnCont(); 1698 if ( pCont && pCont->Lower() ) 1699 { 1700 ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" ); 1701 if ( nStPos > ::lcl_FindFtnPos( pDoc, 1702 ((SwFtnFrm*)pCont->Lower())->GetAttr())) 1703 { 1704 pPage = pNxt; 1705 pNxt = (SwPageFrm*)pPage->GetNext(); 1706 continue; 1707 } 1708 } 1709 break; 1710 } 1711 } 1712 } 1713 } 1714 else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()-> 1715 IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) ) 1716 { 1717 while ( pPage->GetNext() && !pPage->IsFtnPage() && 1718 !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() ) 1719 { 1720 pPage = (SwPageFrm*)pPage->GetNext(); 1721 bChgPage = sal_True; 1722 } 1723 1724 if ( !pPage->IsFtnPage() ) 1725 { 1726 SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc ); 1727 pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(), 1728 !pPage->OnRightPage(), sal_False, sal_True, pPage->GetNext() ); 1729 bChgPage = sal_True; 1730 } 1731 else 1732 { 1733 //Wir koennen wenigstens schon mal ungefaehr die richtige Seite 1734 //suchen. Damit stellen wir sicher das wir auch bei hunderten 1735 //Fussnoten noch in endlicher Zeit fertig werden. 1736 SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext(); 1737 const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr ); 1738 while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() ) 1739 { 1740 SwFtnContFrm *pCont = pNxt->FindFtnCont(); 1741 if ( pCont && pCont->Lower() ) 1742 { 1743 ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" ); 1744 if ( nStPos > ::lcl_FindFtnPos( pDoc, 1745 ((SwFtnFrm*)pCont->Lower())->GetAttr())) 1746 { 1747 pPage = pNxt; 1748 pNxt = (SwPageFrm*)pPage->GetNext(); 1749 continue; 1750 } 1751 } 1752 break; 1753 } 1754 } 1755 } 1756 1757 //Erstmal eine Fussnote und die benoetigten CntntFrms anlegen. 1758 if ( !pAttr->GetStartNode() ) 1759 { ASSERT( !this, "Kein Fussnoteninhalt." ); 1760 return; 1761 } 1762 1763 // Wenn es auf der Seite/Spalte bereits einen FtnCont gibt, 1764 // kann in einen spaltigen Bereich keiner erzeugt werden. 1765 if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() ) 1766 { 1767 SwSectionFrm* pSct = pBoss->FindSctFrm(); 1768 if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() ) 1769 { 1770 SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont(); 1771 if( pFtnCont ) 1772 { 1773 SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower(); 1774 if( bEnd ) 1775 while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() ) 1776 pTmp = (SwFtnFrm*)pTmp->GetNext(); 1777 if( pTmp && *pTmp < pAttr ) 1778 return; 1779 } 1780 } 1781 } 1782 1783 SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), this, pRef, pAttr ); 1784 { 1785 SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); 1786 ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() ); 1787 } 1788 // Wenn die Seite gewechselt (oder gar neu angelegt) wurde, 1789 // muessen wir uns dort in die erste Spalte setzen 1790 if( bChgPage ) 1791 { 1792 SwLayoutFrm* pBody = pPage->FindBodyCont(); 1793 ASSERT( pBody, "AppendFtn: NoPageBody?" ); 1794 if( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 1795 pBoss = (SwFtnBossFrm*)pBody->Lower(); 1796 else 1797 pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst 1798 } 1799 pBoss->InsertFtn( pNew ); 1800 if ( pNew->GetUpper() ) //Eingesetzt oder nicht? 1801 { 1802 ::RegistFlys( pNew->FindPageFrm(), pNew ); 1803 SwSectionFrm* pSect = FindSctFrm(); 1804 // Der Inhalt des FtnContainers in einem (spaltigen) Bereich 1805 // braucht nur kalkuliert zu werden, 1806 // wenn der Bereich bereits bis zur Unterkante seines Uppers geht. 1807 if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() : 1808 !pSect->IsFtnAtEnd() ) && pSect->Growable() ) 1809 pSect->InvalidateSize(); 1810 else 1811 { 1812 // --> OD 2005-05-18 #i49383# - disable unlock of position of 1813 // lower objects during format of footnote content. 1814 const bool bOldFtnFrmLocked( pNew->IsColLocked() ); 1815 pNew->ColLock(); 1816 pNew->KeepLockPosOfLowerObjs(); 1817 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 1818 // no extra notify for footnote frame 1819 // SwLayNotify* pFtnFrmNotitfy = new SwLayNotify( pNew ); 1820 // <-- 1821 SwCntntFrm *pCnt = pNew->ContainsCntnt(); 1822 while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) 1823 { 1824 pCnt->Calc(); 1825 // --> OD 2005-05-17 #i49383# - format anchored objects 1826 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 1827 { 1828 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 1829 *(pCnt->FindPageFrm()) ) ) 1830 { 1831 // restart format with first content 1832 pCnt = pNew->ContainsCntnt(); 1833 continue; 1834 } 1835 } 1836 // <-- 1837 pCnt = (SwCntntFrm*)pCnt->FindNextCnt(); 1838 } 1839 // --> OD 2005-05-18 #i49383# 1840 if ( !bOldFtnFrmLocked ) 1841 { 1842 pNew->ColUnlock(); 1843 } 1844 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 1845 // enable lock of lower object position before format of footnote frame. 1846 pNew->UnlockPosOfLowerObjs(); 1847 // <-- 1848 pNew->Calc(); 1849 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 1850 // no extra notify for footnote frame 1851 // pNew->UnlockPosOfLowerObjs(); 1852 // delete pFtnFrmNotitfy; 1853 // <-- 1854 if ( !bOldFtnFrmLocked && !pNew->GetLower() && 1855 !pNew->IsColLocked() && !pNew->IsBackMoveLocked() ) 1856 { 1857 pNew->Cut(); 1858 delete pNew; 1859 } 1860 // <-- 1861 } 1862 pMyPage->UpdateFtnNum(); 1863 } 1864 else 1865 delete pNew; 1866 } 1867 /************************************************************************* 1868 |* 1869 |* SwFtnBossFrm::FindFtn() 1870 |* 1871 |*************************************************************************/ 1872 1873 1874 SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr ) 1875 { 1876 //Der einfachste und sicherste Weg geht ueber das Attribut. 1877 ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." ); 1878 SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 ); 1879 SwCntntNode *pNd = aIdx.GetNode().GetCntntNode(); 1880 if ( !pNd ) 1881 pNd = pRef->GetAttrSet()->GetDoc()-> 1882 GetNodes().GoNextSection( &aIdx, sal_True, sal_False ); 1883 if ( !pNd ) 1884 return 0; 1885 SwIterator<SwFrm,SwCntntNode> aIter( *pNd ); 1886 SwFrm* pFrm = aIter.First(); 1887 if( pFrm ) 1888 do 1889 { 1890 pFrm = pFrm->GetUpper(); 1891 // #i28500#, #i27243# Due to the endnode collector, there are 1892 // SwFtnFrms, which are not in the layout. Therefore the 1893 // bInfFtn flags are not set correctly, and a cell of FindFtnFrm 1894 // would return 0. Therefore we better call ImplFindFtnFrm(). 1895 SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm(); 1896 if ( pFtn && pFtn->GetRef() == pRef ) 1897 { 1898 // The following condition becomes true, if the whole 1899 // footnotecontent is a section. While no frames exist, 1900 // the HiddenFlag of the section is set, this causes 1901 // the GoNextSection-function leaves the footnote. 1902 if( pFtn->GetAttr() != pAttr ) 1903 return 0; 1904 while ( pFtn && pFtn->GetMaster() ) 1905 pFtn = pFtn->GetMaster(); 1906 return pFtn; 1907 } 1908 1909 } while ( 0 != (pFrm = aIter.Next()) ); 1910 1911 return 0; 1912 } 1913 /************************************************************************* 1914 |* 1915 |* SwFtnBossFrm::RemoveFtn() 1916 |* 1917 |*************************************************************************/ 1918 1919 1920 void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr, 1921 sal_Bool bPrep ) 1922 { 1923 SwFtnFrm *pFtn = FindFtn( pRef, pAttr ); 1924 if( pFtn ) 1925 { 1926 do 1927 { 1928 SwFtnFrm *pFoll = pFtn->GetFollow(); 1929 pFtn->Cut(); 1930 delete pFtn; 1931 pFtn = pFoll; 1932 } while ( pFtn ); 1933 if( bPrep && pRef->IsFollow() ) 1934 { 1935 ASSERT( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" ); 1936 SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster(); 1937 if( !pMaster->IsLocked() ) 1938 pMaster->Prepare( PREP_FTN_GONE ); 1939 } 1940 } 1941 FindPageFrm()->UpdateFtnNum(); 1942 } 1943 1944 /************************************************************************* 1945 |* 1946 |* SwFtnBossFrm::ChangeFtnRef() 1947 |* 1948 |*************************************************************************/ 1949 1950 1951 void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr, 1952 SwCntntFrm *pNew ) 1953 { 1954 SwFtnFrm *pFtn = FindFtn( pOld, pAttr ); 1955 while ( pFtn ) 1956 { 1957 pFtn->SetRef( pNew ); 1958 pFtn = pFtn->GetFollow(); 1959 } 1960 } 1961 1962 /************************************************************************* 1963 |* 1964 |* SwFtnBossFrm::CollectFtns() 1965 |* 1966 |*************************************************************************/ 1967 1968 1969 /// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in 1970 /// order to control, if only footnotes, which are positioned before the 1971 /// footnote boss frame <this> have to be collected. 1972 void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef, 1973 SwFtnBossFrm* _pOld, 1974 SvPtrarr& _rFtnArr, 1975 const sal_Bool _bCollectOnlyPreviousFtns ) 1976 { 1977 SwFtnFrm *pFtn = _pOld->FindFirstFtn(); 1978 while( !pFtn ) 1979 { 1980 if( _pOld->IsColumnFrm() ) 1981 { // Spalten abklappern 1982 while ( !pFtn && _pOld->GetPrev() ) 1983 { 1984 //Wenn wir keine Fussnote gefunden haben, ist noch nicht alles zu 1985 //spaet. Die Schleife wird beim Aufnehmen von Follow-Zeilen durch 1986 //Tabellen benoetigt. Fuer alle anderen Faelle ist sie in der Lage 1987 //'krumme' Verhaeltnisse zu korrigieren. 1988 _pOld = (SwFtnBossFrm*)_pOld->GetPrev(); 1989 pFtn = _pOld->FindFirstFtn(); 1990 } 1991 } 1992 if( !pFtn ) 1993 { 1994 // vorherige Seite 1995 SwPageFrm* pPg; 1996 for ( SwFrm* pTmp = _pOld; 1997 0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev()) 1998 && pPg->IsEmptyPage() ; 1999 ) 2000 { 2001 pTmp = pPg; 2002 } 2003 if( !pPg ) 2004 return; 2005 2006 SwLayoutFrm* pBody = pPg->FindBodyCont(); 2007 if( pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 2008 { 2009 // mehrspaltige Seite => letzte Spalte suchen 2010 _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower()); 2011 } 2012 else 2013 _pOld = pPg; // einspaltige Seite 2014 pFtn = _pOld->FindFirstFtn(); 2015 } 2016 } 2017 // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns> 2018 SwFtnBossFrm* pRefBossFrm = NULL; 2019 if ( _bCollectOnlyPreviousFtns ) 2020 { 2021 pRefBossFrm = this; 2022 } 2023 _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm ); 2024 } 2025 2026 2027 /************************************************************************* 2028 |* 2029 |* SwFtnBossFrm::_CollectFtns() 2030 |* 2031 |*************************************************************************/ 2032 inline void FtnInArr( SvPtrarr& rFtnArr, SwFtnFrm* pFtn ) 2033 { 2034 if ( USHRT_MAX == rFtnArr.GetPos( (VoidPtr)pFtn ) ) 2035 rFtnArr.Insert( (VoidPtr)pFtn, rFtnArr.Count() ); 2036 } 2037 2038 /// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and 2039 /// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned 2040 /// before the given reference footnote boss frame have to be collected. 2041 /// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter 2042 /// <_pRefFtnBossFrm> have to be referenced to an object. 2043 /// Adjust parameter names. 2044 void SwFtnBossFrm::_CollectFtns( const SwCntntFrm* _pRef, 2045 SwFtnFrm* _pFtn, 2046 SvPtrarr& _rFtnArr, 2047 sal_Bool _bCollectOnlyPreviousFtns, 2048 const SwFtnBossFrm* _pRefFtnBossFrm) 2049 { 2050 // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame 2051 // is set, in spite of the order, that only previous footnotes has to be 2052 // collected. 2053 ASSERT( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm, 2054 "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" ); 2055 2056 //Alle Fussnoten die von pRef referenziert werden nacheinander 2057 //einsammeln (Attribut fuer Attribut), zusammengefuegen 2058 //(der Inhalt zu einem Attribut kann ueber mehrere Seiten verteilt sein) 2059 //und ausschneiden. 2060 2061 SvPtrarr aNotFtnArr( 20, 20 ); //Zur Robustheit werden hier die nicht 2062 //dazugehoerigen Fussnoten eingetragen. 2063 //Wenn eine Fussnote zweimal angefasst wird 2064 //ists vorbei! So kommt die Funktion auch 2065 //noch mit einem kaputten Layout 2066 //einigermassen (ohne Schleife und Absturz) 2067 //"klar". 2068 2069 //Hier sollte keiner mit einer Follow-Ftn ankommen, es sei denn er hat 2070 //ernste Absichten (:-)); spricht er kommt mit einer Ftn an die vor der 2071 //ersten der Referenz liegt. 2072 ASSERT( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "FollowFtn moven?" ); 2073 while ( _pFtn->GetMaster() ) 2074 _pFtn = _pFtn->GetMaster(); 2075 2076 sal_Bool bFound = sal_False; 2077 2078 while ( _pFtn ) 2079 { 2080 //Erstmal die naechste Fussnote der Spalte/Seite suchen, damit wir nicht 2081 //nach dem Cut jeder Fussnote von vorn anfangen muessen. 2082 SwFtnFrm *pNxtFtn = _pFtn; 2083 while ( pNxtFtn->GetFollow() ) 2084 pNxtFtn = pNxtFtn->GetFollow(); 2085 pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext(); 2086 2087 if ( !pNxtFtn ) 2088 { 2089 SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm(); 2090 SwPageFrm* pPage = pBoss->FindPageFrm(); 2091 do 2092 { 2093 lcl_NextFtnBoss( pBoss, pPage, sal_False ); 2094 if( pBoss ) 2095 { 2096 SwLayoutFrm* pCont = pBoss->FindFtnCont(); 2097 if( pCont ) 2098 { 2099 pNxtFtn = (SwFtnFrm*)pCont->Lower(); 2100 if( pNxtFtn ) 2101 { 2102 while( pNxtFtn->GetMaster() ) 2103 pNxtFtn = pNxtFtn->GetMaster(); 2104 if( pNxtFtn == _pFtn ) 2105 pNxtFtn = NULL; 2106 } 2107 } 2108 } 2109 } while( !pNxtFtn && pBoss ); 2110 } 2111 else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() ) 2112 { ASSERT( !pNxtFtn->GetMaster(), "_CollectFtn: Master exspected" ); 2113 while ( pNxtFtn->GetMaster() ) 2114 pNxtFtn = pNxtFtn->GetMaster(); 2115 } 2116 if ( pNxtFtn == _pFtn ) 2117 { 2118 ASSERT( sal_False, "_CollectFtn: Devil's circle" ); 2119 pNxtFtn = 0; 2120 } 2121 2122 // OD 03.04.2003 #108446# - determine, if found footnote has to be collected. 2123 sal_Bool bCollectFoundFtn = sal_False; 2124 if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() ) 2125 { 2126 if ( _bCollectOnlyPreviousFtns ) 2127 { 2128 SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( sal_True ); 2129 ASSERT( pBossOfFoundFtn, 2130 "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" ); 2131 if ( !pBossOfFoundFtn || // don't crash, if no footnote boss is found. 2132 pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm ) 2133 ) 2134 { 2135 bCollectFoundFtn = sal_True; 2136 } 2137 } 2138 else 2139 { 2140 bCollectFoundFtn = sal_True; 2141 } 2142 } 2143 2144 if ( bCollectFoundFtn ) 2145 { 2146 ASSERT( !_pFtn->GetMaster(), "FollowFtn moven?" ); 2147 SwFtnFrm *pNxt = _pFtn->GetFollow(); 2148 while ( pNxt ) 2149 { 2150 SwFrm *pCnt = pNxt->ContainsAny(); 2151 if ( pCnt ) 2152 { //Unterwegs wird der Follow zerstoert weil er leer wird! 2153 do 2154 { SwFrm *pNxtCnt = pCnt->GetNext(); 2155 pCnt->Cut(); 2156 pCnt->Paste( _pFtn ); 2157 pCnt = pNxtCnt; 2158 } while ( pCnt ); 2159 } 2160 else 2161 { ASSERT( !pNxt, "Fussnote ohne Inhalt?" ); 2162 pNxt->Cut(); 2163 delete pNxt; 2164 } 2165 pNxt = _pFtn->GetFollow(); 2166 } 2167 _pFtn->Cut(); 2168 FtnInArr( _rFtnArr, _pFtn ); 2169 bFound = sal_True; 2170 } 2171 else 2172 { 2173 FtnInArr( aNotFtnArr, _pFtn ); 2174 if( bFound ) 2175 break; 2176 } 2177 if ( pNxtFtn && 2178 USHRT_MAX == _rFtnArr.GetPos( (VoidPtr)pNxtFtn ) && 2179 USHRT_MAX == aNotFtnArr.GetPos( (VoidPtr)pNxtFtn ) ) 2180 _pFtn = pNxtFtn; 2181 else 2182 break; 2183 } 2184 } 2185 2186 /************************************************************************* 2187 |* 2188 |* SwFtnBossFrm::_MoveFtns() 2189 |* 2190 |*************************************************************************/ 2191 2192 2193 void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, sal_Bool bCalc ) 2194 { 2195 //Alle Fussnoten die von pRef referenziert werden muessen von der 2196 //aktuellen Position, die sich durch die alte Spalte/Seite ergab, auf eine 2197 //neue Position, bestimmt durch die neue Spalte/Seite, gemoved werden. 2198 const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum(); 2199 const sal_uInt16 nMyCol = lcl_ColumnNum( this ); 2200 SWRECTFN( this ) 2201 2202 // --> OD 2004-06-11 #i21478# - keep last inserted footnote in order to 2203 // format the content of the following one. 2204 SwFtnFrm* pLastInsertedFtn = 0L; 2205 for ( sal_uInt16 i = 0; i < rFtnArr.Count(); ++i ) 2206 { 2207 SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i]; 2208 2209 SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( sal_True ); 2210 if( pRefBoss != this ) 2211 { 2212 const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum(); 2213 const sal_uInt16 nRefCol = lcl_ColumnNum( this ); 2214 if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) ) 2215 pRefBoss = this; 2216 } 2217 pRefBoss->InsertFtn( pFtn ); 2218 2219 if ( pFtn->GetUpper() ) //Robust, z.B. bei doppelten 2220 { 2221 // Damit FtnFrms, die nicht auf die Seite passen, nicht fuer zuviel 2222 // Unruhe sorgen (Loop 66312), wird ihr Inhalt zunaechst zusammengestaucht. 2223 // Damit wird der FtnCont erst gegrowt, wenn der Inhalt formatiert wird 2224 // und feststellt, dass er auf die Seite passt. 2225 SwFrm *pCnt = pFtn->ContainsAny(); 2226 while( pCnt ) 2227 { 2228 if( pCnt->IsLayoutFrm() ) 2229 { 2230 SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny(); 2231 while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) ) 2232 { 2233 pTmp->Prepare( PREP_MOVEFTN ); 2234 (pTmp->Frm().*fnRect->fnSetHeight)(0); 2235 (pTmp->Prt().*fnRect->fnSetHeight)(0); 2236 pTmp = pTmp->FindNext(); 2237 } 2238 } 2239 else 2240 pCnt->Prepare( PREP_MOVEFTN ); 2241 (pCnt->Frm().*fnRect->fnSetHeight)(0); 2242 (pCnt->Prt().*fnRect->fnSetHeight)(0); 2243 pCnt = pCnt->GetNext(); 2244 } 2245 (pFtn->Frm().*fnRect->fnSetHeight)(0); 2246 (pFtn->Prt().*fnRect->fnSetHeight)(0); 2247 pFtn->Calc(); 2248 pFtn->GetUpper()->Calc(); 2249 2250 if( bCalc ) 2251 { 2252 SwTxtFtn *pAttr = pFtn->GetAttr(); 2253 pCnt = pFtn->ContainsAny(); 2254 sal_Bool bUnlock = !pFtn->IsBackMoveLocked(); 2255 pFtn->LockBackMove(); 2256 2257 // --> OD 2005-05-18 #i49383# - disable unlock of position of 2258 // lower objects during format of footnote content. 2259 pFtn->KeepLockPosOfLowerObjs(); 2260 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2261 // no extra notify for footnote frame 2262 // SwLayNotify aFtnFrmNotitfy( pFtn ); 2263 // <-- 2264 2265 while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) 2266 { 2267 pCnt->_InvalidatePos(); 2268 pCnt->Calc(); 2269 // --> OD 2005-05-17 #i49383# - format anchored objects 2270 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 2271 { 2272 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 2273 *(pCnt->FindPageFrm()) ) ) 2274 { 2275 // restart format with first content 2276 pCnt = pFtn->ContainsAny(); 2277 continue; 2278 } 2279 } 2280 // <-- 2281 if( pCnt->IsSctFrm() ) 2282 { // Wenn es sich um einen nichtleeren Bereich handelt, 2283 // iterieren wir auch ueber seinen Inhalt 2284 SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); 2285 if( pTmp ) 2286 pCnt = pTmp; 2287 else 2288 pCnt = pCnt->FindNext(); 2289 } 2290 else 2291 pCnt = pCnt->FindNext(); 2292 } 2293 if( bUnlock ) 2294 { 2295 pFtn->UnlockBackMove(); 2296 if( !pFtn->ContainsAny() && !pFtn->IsColLocked() ) 2297 { 2298 pFtn->Cut(); 2299 delete pFtn; 2300 // --> OD 2004-06-10 #i21478# 2301 pFtn = 0L; 2302 } 2303 } 2304 // --> OD 2005-05-18 #i49383# 2305 if ( pFtn ) 2306 { 2307 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2308 // enable lock of lower object position before format of footnote frame. 2309 pFtn->UnlockPosOfLowerObjs(); 2310 pFtn->Calc(); 2311 // pFtn->UnlockPosOfLowerObjs(); 2312 // <-- 2313 } 2314 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2315 // no extra notify for footnote frame 2316 // else 2317 // { 2318 // aFtnFrmNotitfy.FrmDeleted(); 2319 // } 2320 // <-- 2321 } 2322 } 2323 else 2324 { ASSERT( !pFtn->GetMaster() && !pFtn->GetFollow(), 2325 "DelFtn und Master/Follow?" ); 2326 delete pFtn; 2327 // --> OD 2004-06-10 #i21478# 2328 pFtn = 0L; 2329 } 2330 2331 // --> OD 2004-06-10 #i21478# 2332 if ( pFtn ) 2333 { 2334 pLastInsertedFtn = pFtn; 2335 } 2336 } 2337 2338 // --> OD 2004-06-10 #i21478# - format content of footnote following 2339 // the new inserted ones. 2340 if ( bCalc && pLastInsertedFtn ) 2341 { 2342 if ( pLastInsertedFtn->GetNext() ) 2343 { 2344 SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext()); 2345 SwTxtFtn* pAttr = pNextFtn->GetAttr(); 2346 SwFrm* pCnt = pNextFtn->ContainsAny(); 2347 2348 sal_Bool bUnlock = !pNextFtn->IsBackMoveLocked(); 2349 pNextFtn->LockBackMove(); 2350 // --> OD 2005-05-18 #i49383# - disable unlock of position of 2351 // lower objects during format of footnote content. 2352 pNextFtn->KeepLockPosOfLowerObjs(); 2353 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2354 // no extra notify for footnote frame 2355 // SwLayNotify aFtnFrmNotitfy( pNextFtn ); 2356 // <-- 2357 2358 while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr ) 2359 { 2360 pCnt->_InvalidatePos(); 2361 pCnt->Calc(); 2362 // --> OD 2005-05-17 #i49383# - format anchored objects 2363 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 2364 { 2365 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 2366 *(pCnt->FindPageFrm()) ) ) 2367 { 2368 // restart format with first content 2369 pCnt = pNextFtn->ContainsAny(); 2370 continue; 2371 } 2372 } 2373 // <-- 2374 if( pCnt->IsSctFrm() ) 2375 { // Wenn es sich um einen nichtleeren Bereich handelt, 2376 // iterieren wir auch ueber seinen Inhalt 2377 SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); 2378 if( pTmp ) 2379 pCnt = pTmp; 2380 else 2381 pCnt = pCnt->FindNext(); 2382 } 2383 else 2384 pCnt = pCnt->FindNext(); 2385 } 2386 if( bUnlock ) 2387 { 2388 pNextFtn->UnlockBackMove(); 2389 } 2390 // --> OD 2005-05-18 #i49383# 2391 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2392 // enable lock of lower object position before format of footnote frame. 2393 pNextFtn->UnlockPosOfLowerObjs(); 2394 pNextFtn->Calc(); 2395 // pNextFtn->UnlockPosOfLowerObjs(); 2396 // <-- 2397 } 2398 } 2399 } 2400 2401 /************************************************************************* 2402 |* 2403 |* SwFtnBossFrm::MoveFtns() 2404 |* 2405 |*************************************************************************/ 2406 2407 2408 void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest, 2409 SwTxtFtn *pAttr ) 2410 { 2411 if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER && 2412 (!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd())) 2413 || pAttr->GetFtn().IsEndNote() ) 2414 return; 2415 2416 ASSERT( this == pSrc->FindFtnBossFrm( sal_True ), 2417 "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" ); 2418 2419 SwFtnFrm *pFtn = FindFirstFtn(); 2420 if( pFtn ) 2421 { 2422 ChangeFtnRef( pSrc, pAttr, pDest ); 2423 SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( sal_True ); 2424 ASSERT( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" ); 2425 if( pDestBoss ) // robust 2426 { 2427 SvPtrarr aFtnArr( 5, 5 ); 2428 pDestBoss->_CollectFtns( pDest, pFtn, aFtnArr ); 2429 if ( aFtnArr.Count() ) 2430 { 2431 pDestBoss->_MoveFtns( aFtnArr, sal_True ); 2432 SwPageFrm* pSrcPage = FindPageFrm(); 2433 SwPageFrm* pDestPage = pDestBoss->FindPageFrm(); 2434 // Nur beim Seitenwechsel FtnNum Updaten 2435 if( pSrcPage != pDestPage ) 2436 { 2437 if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() ) 2438 pSrcPage->UpdateFtnNum(); 2439 pDestPage->UpdateFtnNum(); 2440 } 2441 } 2442 } 2443 } 2444 } 2445 2446 /************************************************************************* 2447 |* 2448 |* SwFtnBossFrm::RearrangeFtns() 2449 |* 2450 |*************************************************************************/ 2451 2452 2453 void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const sal_Bool bLock, 2454 const SwTxtFtn *pAttr ) 2455 { 2456 //Alle Fussnoten der Spalte/Seite dergestalt anformatieren, 2457 //dass sie ggf. die Spalte/Seite wechseln. 2458 2459 SwSaveFtnHeight aSave( this, nDeadLine ); 2460 SwFtnFrm *pFtn = FindFirstFtn(); 2461 if( pFtn && pFtn->GetPrev() && bLock ) 2462 { 2463 SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower(); 2464 SwFrm* pCntnt = pFirst->ContainsAny(); 2465 if( pCntnt ) 2466 { 2467 sal_Bool bUnlock = !pFirst->IsBackMoveLocked(); 2468 pFirst->LockBackMove(); 2469 pFirst->Calc(); 2470 pCntnt->Calc(); 2471 // --> OD 2005-05-17 #i49383# - format anchored objects 2472 if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() ) 2473 { 2474 SwObjectFormatter::FormatObjsAtFrm( *pCntnt, 2475 *(pCntnt->FindPageFrm()) ); 2476 } 2477 // <-- 2478 if( bUnlock ) 2479 pFirst->UnlockBackMove(); 2480 } 2481 pFtn = FindFirstFtn(); 2482 } 2483 SwDoc *pDoc = GetFmt()->GetDoc(); 2484 const sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0; 2485 SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0; 2486 if ( pCnt ) 2487 { 2488 sal_Bool bMore = sal_True; 2489 sal_Bool bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten 2490 // --> OD 2005-05-18 #i49383# - disable unlock of position of 2491 // lower objects during format of footnote and footnote content. 2492 SwFtnFrm* pLastFtnFrm( 0L ); 2493 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2494 // no extra notify for footnote frame 2495 // SwLayNotify* pFtnFrmNotify( 0L ); 2496 // footnote frame needs to be locked, if <bLock> isn't set. 2497 bool bUnlockLastFtnFrm( false ); 2498 // <-- 2499 do 2500 { 2501 if( !bStart ) 2502 bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() ) 2503 == nFtnPos; 2504 if( bStart ) 2505 { 2506 pCnt->_InvalidatePos(); 2507 pCnt->_InvalidateSize(); 2508 pCnt->Prepare( PREP_ADJUST_FRM ); 2509 SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm(); 2510 // --> OD 2005-05-18 #i49383# 2511 if ( pFtnFrm != pLastFtnFrm ) 2512 { 2513 if ( pLastFtnFrm ) 2514 { 2515 if ( !bLock && bUnlockLastFtnFrm ) 2516 { 2517 pLastFtnFrm->ColUnlock(); 2518 } 2519 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2520 // enable lock of lower object position before format of footnote frame. 2521 pLastFtnFrm->UnlockPosOfLowerObjs(); 2522 pLastFtnFrm->Calc(); 2523 // pLastFtnFrm->UnlockPosOfLowerObjs(); 2524 // no extra notify for footnote frame 2525 // delete pFtnFrmNotify; 2526 // <-- 2527 if ( !bLock && bUnlockLastFtnFrm && 2528 !pLastFtnFrm->GetLower() && 2529 !pLastFtnFrm->IsColLocked() && 2530 !pLastFtnFrm->IsBackMoveLocked() ) 2531 { 2532 pLastFtnFrm->Cut(); 2533 delete pLastFtnFrm; 2534 pLastFtnFrm = 0L; 2535 } 2536 } 2537 if ( !bLock ) 2538 { 2539 bUnlockLastFtnFrm = !pFtnFrm->IsColLocked(); 2540 pFtnFrm->ColLock(); 2541 } 2542 pFtnFrm->KeepLockPosOfLowerObjs(); 2543 pLastFtnFrm = pFtnFrm; 2544 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2545 // no extra notify for footnote frame 2546 // pFtnFrmNotify = new SwLayNotify( pLastFtnFrm ); 2547 // <-- 2548 } 2549 // <-- 2550 // OD 30.10.2002 #97265# - invalidate position of footnote 2551 // frame, if it's below its footnote container, in order to 2552 // assure its correct position, probably calculating its previous 2553 // footnote frames. 2554 { 2555 SWRECTFN( this ); 2556 SwFrm* aFtnContFrm = pFtnFrm->GetUpper(); 2557 if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 ) 2558 { 2559 pFtnFrm->_InvalidatePos(); 2560 } 2561 } 2562 if ( bLock ) 2563 { 2564 sal_Bool bUnlock = !pFtnFrm->IsBackMoveLocked(); 2565 pFtnFrm->LockBackMove(); 2566 pFtnFrm->Calc(); 2567 pCnt->Calc(); 2568 // --> OD 2005-05-17 #i49383# - format anchored objects 2569 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 2570 { 2571 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 2572 *(pCnt->FindPageFrm()) ) ) 2573 { 2574 // restart format with first content 2575 pCnt = pFtn->ContainsAny(); 2576 continue; 2577 } 2578 } 2579 // <-- 2580 if( bUnlock ) 2581 { 2582 pFtnFrm->UnlockBackMove(); 2583 if( !pFtnFrm->Lower() && 2584 !pFtnFrm->IsColLocked() ) 2585 { 2586 // --> OD 2005-08-10 #i49383# 2587 ASSERT( pLastFtnFrm == pFtnFrm, 2588 "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" ); 2589 pLastFtnFrm = 0L; 2590 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2591 // no extra notify for footnote frame 2592 // pFtnFrmNotify->FrmDeleted(); 2593 // delete pFtnFrmNotify; 2594 // <-- 2595 pFtnFrm->Cut(); 2596 delete pFtnFrm; 2597 } 2598 } 2599 } 2600 else 2601 { 2602 pFtnFrm->Calc(); 2603 pCnt->Calc(); 2604 // --> OD 2005-05-17 #i49383# - format anchored objects 2605 if ( pCnt->IsTxtFrm() && pCnt->IsValid() ) 2606 { 2607 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt, 2608 *(pCnt->FindPageFrm()) ) ) 2609 { 2610 // restart format with first content 2611 pCnt = pFtn->ContainsAny(); 2612 continue; 2613 } 2614 } 2615 // <-- 2616 } 2617 } 2618 SwSectionFrm *pDel = NULL; 2619 if( pCnt->IsSctFrm() ) 2620 { 2621 SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny(); 2622 if( pTmp ) 2623 { 2624 pCnt = pTmp; 2625 continue; 2626 } 2627 pDel = (SwSectionFrm*)pCnt; 2628 } 2629 if ( pCnt->GetNext() ) 2630 pCnt = pCnt->GetNext(); 2631 else 2632 { 2633 pCnt = pCnt->FindNext(); 2634 if ( pCnt ) 2635 { 2636 SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm(); 2637 if( pFtnFrm->GetRef()->FindFtnBossFrm( 2638 pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this ) 2639 bMore = sal_False; 2640 } 2641 else 2642 bMore = sal_False; 2643 } 2644 if( pDel ) 2645 { 2646 pDel->Cut(); 2647 delete pDel; 2648 } 2649 if ( bMore ) 2650 { 2651 //Nicht weiter als bis zur angegebenen Fussnote, falls eine 2652 //angegeben wurde. 2653 if ( pAttr && 2654 (::lcl_FindFtnPos( pDoc, 2655 pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) ) 2656 bMore = sal_False; 2657 } 2658 } while ( bMore ); 2659 // --> OD 2005-05-18 #i49383# 2660 if ( pLastFtnFrm ) 2661 { 2662 if ( !bLock && bUnlockLastFtnFrm ) 2663 { 2664 pLastFtnFrm->ColUnlock(); 2665 } 2666 // --> OD 2006-02-02 #i57914# - adjust fix #i49383# 2667 // enable lock of lower object position before format of footnote frame. 2668 pLastFtnFrm->UnlockPosOfLowerObjs(); 2669 pLastFtnFrm->Calc(); 2670 // pLastFtnFrm->UnlockPosOfLowerObjs(); 2671 // no extra notify for footnote frame 2672 // delete pFtnFrmNotify; 2673 // <-- 2674 if ( !bLock && bUnlockLastFtnFrm && 2675 !pLastFtnFrm->GetLower() && 2676 !pLastFtnFrm->IsColLocked() && 2677 !pLastFtnFrm->IsBackMoveLocked() ) 2678 { 2679 pLastFtnFrm->Cut(); 2680 delete pLastFtnFrm; 2681 } 2682 } 2683 // <-- 2684 } 2685 } 2686 2687 /************************************************************************* 2688 |* 2689 |* SwPageFrm::UpdateFtnNum() 2690 |* 2691 |*************************************************************************/ 2692 2693 void SwPageFrm::UpdateFtnNum() 2694 { 2695 //Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist. 2696 if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE ) 2697 return; 2698 2699 SwLayoutFrm* pBody = FindBodyCont(); 2700 if( !pBody || !pBody->Lower() ) 2701 return; 2702 2703 SwCntntFrm* pCntnt = pBody->ContainsCntnt(); 2704 sal_uInt16 nNum = 0; 2705 2706 while( pCntnt && pCntnt->FindPageFrm() == this ) 2707 { 2708 if( ((SwTxtFrm*)pCntnt)->HasFtn() ) 2709 { 2710 SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( sal_True ); 2711 if( pBoss->GetUpper()->IsSctFrm() && 2712 ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() ) 2713 pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt(); 2714 else 2715 { 2716 SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt ); 2717 while( pFtn ) 2718 { 2719 SwTxtFtn* pTxtFtn = pFtn->GetAttr(); 2720 if( !pTxtFtn->GetFtn().IsEndNote() && 2721 !pTxtFtn->GetFtn().GetNumStr().Len() && 2722 !pFtn->GetMaster() && 2723 (pTxtFtn->GetFtn().GetNumber() != ++nNum) ) 2724 pTxtFtn->SetNumber( nNum ); 2725 if ( pFtn->GetNext() ) 2726 pFtn = (SwFtnFrm*)pFtn->GetNext(); 2727 else 2728 { 2729 SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( sal_True ); 2730 SwPageFrm* pPage = pTmpBoss->FindPageFrm(); 2731 pFtn = NULL; 2732 lcl_NextFtnBoss( pTmpBoss, pPage, sal_False ); 2733 if( pTmpBoss ) 2734 { 2735 SwFtnContFrm *pCont = pTmpBoss->FindNearestFtnCont(); 2736 if ( pCont ) 2737 pFtn = (SwFtnFrm*)pCont->Lower(); 2738 } 2739 } 2740 if( pFtn && pFtn->GetRef() != pCntnt ) 2741 pFtn = NULL; 2742 } 2743 } 2744 } 2745 pCntnt = pCntnt->FindNextCnt(); 2746 } 2747 } 2748 2749 /************************************************************************* 2750 |* 2751 |* SwFtnBossFrm::SetFtnDeadLine() 2752 |* 2753 |*************************************************************************/ 2754 2755 void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine ) 2756 { 2757 SwFrm *pBody = FindBodyCont(); 2758 pBody->Calc(); 2759 2760 SwFrm *pCont = FindFtnCont(); 2761 const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten. 2762 SWRECTFN( this ) 2763 if ( pCont ) 2764 { 2765 pCont->Calc(); 2766 nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine ); 2767 } 2768 else 2769 nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine ); 2770 2771 const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 2772 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 2773 nMaxFtnHeight += pBody->Grow( LONG_MAX, sal_True ); 2774 if ( IsInSct() ) 2775 nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, sal_True ); 2776 2777 if ( nMaxFtnHeight < 0 ) 2778 nMaxFtnHeight = 0; 2779 if ( nMax != LONG_MAX && nMaxFtnHeight > nMax ) 2780 nMaxFtnHeight = nMax; 2781 } 2782 2783 /************************************************************************* 2784 |* 2785 |* SwFtnBossFrm::GetVarSpace() 2786 |* 2787 |*************************************************************************/ 2788 SwTwips SwFtnBossFrm::GetVarSpace() const 2789 { 2790 //Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten 2791 //werden (->AMA: was macht MS da?) 2792 //->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)? 2793 //AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus 2794 // die ganze Seite/Spalte ein. 2795 2796 const SwPageFrm* pPg = FindPageFrm(); 2797 ASSERT( pPg || IsInSct(), "Footnote lost page" ); 2798 2799 const SwFrm *pBody = FindBodyCont(); 2800 SwTwips nRet; 2801 if( pBody ) 2802 { 2803 SWRECTFN( this ) 2804 if( IsInSct() ) 2805 { 2806 nRet = 0; 2807 SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(), 2808 (Frm().*fnRect->fnGetTop)() ); 2809 const SwSectionFrm* pSect = FindSctFrm(); 2810 // Endnotes in a ftncontainer causes a deadline: 2811 // the bottom of the last contentfrm 2812 if( pSect->IsEndnAtEnd() ) // endnotes allowed? 2813 { 2814 ASSERT( !Lower() || !Lower()->GetNext() || Lower()->GetNext()-> 2815 IsFtnContFrm(), "FtnContainer exspected" ); 2816 const SwFtnContFrm* pCont = Lower() ? 2817 (SwFtnContFrm*)Lower()->GetNext() : 0; 2818 if( pCont ) 2819 { 2820 SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower(); 2821 while( pFtn) 2822 { 2823 if( pFtn->GetAttr()->GetFtn().IsEndNote() ) 2824 { // endnote found 2825 SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower(); 2826 if( pFrm ) 2827 { 2828 while( pFrm->GetNext() ) 2829 pFrm = pFrm->GetNext(); // last cntntfrm 2830 nTmp += (*fnRect->fnYDiff)( 2831 (Frm().*fnRect->fnGetTop)(), 2832 (pFrm->Frm().*fnRect->fnGetBottom)() ); 2833 } 2834 break; 2835 } 2836 pFtn = (SwFtnFrm*)pFtn->GetNext(); 2837 } 2838 } 2839 } 2840 if( nTmp < nRet ) 2841 nRet = nTmp; 2842 } 2843 else 2844 nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5; 2845 nRet += (pBody->Frm().*fnRect->fnGetHeight)(); 2846 if( nRet < 0 ) 2847 nRet = 0; 2848 } 2849 else 2850 nRet = 0; 2851 if ( IsPageFrm() ) 2852 { 2853 const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0; 2854 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 2855 nRet += BROWSE_HEIGHT - Frm().Height(); 2856 } 2857 return nRet; 2858 } 2859 2860 /************************************************************************* 2861 |* 2862 |* SwFtnBossFrm::NeighbourhoodAdjustment(SwFrm*) 2863 |* 2864 |* gibt Auskunft, ob die Groessenveraenderung von pFrm von AdjustNeighbourhood(...) 2865 |* oder von Grow/Shrink(..) verarbeitet werden sollte. 2866 |* Bei einem PageFrm oder in Spalten direkt unterhalb der Seite muss AdjustNei.. 2867 |* gerufen werden, in Rahmenspalten Grow/Shrink. 2868 |* Spannend sind die spaltigen Bereiche: Wenn es in der Spalte einen Fussnotencontainer 2869 |* gibt und die Fussnoten nicht vom Bereich eingesammelt werden, ist ein Adjust.., 2870 |* ansonsten ein Grow/Shrink notwendig. 2871 |* 2872 |*************************************************************************/ 2873 2874 sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const 2875 { 2876 sal_uInt8 nRet = NA_ONLY_ADJUST; 2877 if( GetUpper() && !GetUpper()->IsPageBodyFrm() ) 2878 { 2879 // Spaltige Rahmen erfordern Grow/Shrink 2880 if( GetUpper()->IsFlyFrm() ) 2881 nRet = NA_GROW_SHRINK; 2882 else 2883 { 2884 ASSERT( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" ); 2885 if( !GetNext() && !GetPrev() ) 2886 nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd) 2887 else 2888 { 2889 const SwFrm* pTmp = Lower(); 2890 ASSERT( pTmp, "NeighbourhoodAdjustment: Missing Lower()" ); 2891 if( !pTmp->GetNext() ) 2892 nRet = NA_GROW_SHRINK; 2893 else if( !GetUpper()->IsColLocked() ) 2894 nRet = NA_ADJUST_GROW; 2895 ASSERT( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(), 2896 "NeighbourhoodAdjustment: Who's that guy?" ); 2897 } 2898 } 2899 } 2900 return nRet; 2901 } 2902 2903 /************************************************************************* 2904 |* 2905 |* SwPageFrm::SetColMaxFtnHeight() 2906 |* 2907 |*************************************************************************/ 2908 void SwPageFrm::SetColMaxFtnHeight() 2909 { 2910 SwLayoutFrm *pBody = FindBodyCont(); 2911 if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() ) 2912 { 2913 SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower(); 2914 do 2915 { 2916 pCol->SetMaxFtnHeight( GetMaxFtnHeight() ); 2917 pCol = (SwColumnFrm*)pCol->GetNext(); 2918 } while ( pCol ); 2919 } 2920 } 2921 2922 /************************************************************************* 2923 |* 2924 |* SwLayoutFrm::MoveLowerFtns 2925 |* 2926 |*************************************************************************/ 2927 2928 2929 sal_Bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss, 2930 SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums ) 2931 { 2932 SwDoc *pDoc = GetFmt()->GetDoc(); 2933 if ( !pDoc->GetFtnIdxs().Count() ) 2934 return sal_False; 2935 if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER && 2936 ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) ) 2937 return sal_True; 2938 2939 if ( !pNewBoss ) 2940 pNewBoss = FindFtnBossFrm( sal_True ); 2941 if ( pNewBoss == pOldBoss ) 2942 return sal_False; 2943 2944 sal_Bool bMoved = sal_False; 2945 if( !pStart ) 2946 pStart = ContainsCntnt(); 2947 2948 SvPtrarr aFtnArr( 5, 5 ); 2949 2950 while ( IsAnLower( pStart ) ) 2951 { 2952 if ( ((SwTxtFrm*)pStart)->HasFtn() ) 2953 { 2954 // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes 2955 // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of 2956 // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only 2957 // footnotes have to be collected, that are positioned before the 2958 // new dedicated footnote boss frame. 2959 pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, sal_True ); 2960 } 2961 pStart = pStart->GetNextCntntFrm(); 2962 } 2963 2964 ASSERT( pOldBoss->IsInSct() == pNewBoss->IsInSct(), 2965 "MoveLowerFtns: Section confusion" ); 2966 SvPtrarr *pFtnArr; 2967 SwLayoutFrm* pNewChief = 0; 2968 SwLayoutFrm* pOldChief = 0; 2969 if( pStart && pOldBoss->IsInSct() && ( pOldChief = pOldBoss->FindSctFrm() ) 2970 != ( pNewChief = pNewBoss->FindSctFrm() ) ) 2971 { 2972 pFtnArr = new SvPtrarr( 5, 5 ); 2973 pOldChief = pOldBoss->FindFtnBossFrm( sal_True ); 2974 pNewChief = pNewBoss->FindFtnBossFrm( sal_True ); 2975 while( pOldChief->IsAnLower( pStart ) ) 2976 { 2977 if ( ((SwTxtFrm*)pStart)->HasFtn() ) 2978 ((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart, 2979 (SwFtnBossFrm*)pOldBoss, *pFtnArr ); 2980 pStart = pStart->GetNextCntntFrm(); 2981 } 2982 if( !pFtnArr->Count() ) 2983 { 2984 delete pFtnArr; 2985 pFtnArr = NULL; 2986 } 2987 } 2988 else 2989 pFtnArr = NULL; 2990 2991 if ( aFtnArr.Count() || pFtnArr ) 2992 { 2993 if( aFtnArr.Count() ) 2994 pNewBoss->_MoveFtns( aFtnArr, sal_True ); 2995 if( pFtnArr ) 2996 { 2997 ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, sal_True ); 2998 delete pFtnArr; 2999 } 3000 bMoved = sal_True; 3001 3002 // Nur bei einem Seitenwechsel muss die FtnNum neu berechnet werden 3003 if ( bFtnNums ) 3004 { 3005 SwPageFrm* pOldPage = pOldBoss->FindPageFrm(); 3006 SwPageFrm* pNewPage =pNewBoss->FindPageFrm(); 3007 if( pOldPage != pNewPage ) 3008 { 3009 pOldPage->UpdateFtnNum(); 3010 pNewPage->UpdateFtnNum(); 3011 } 3012 } 3013 } 3014 return bMoved; 3015 } 3016 3017 /************************************************************************* 3018 |* 3019 |* SwLayoutFrm::MoveFtnCntFwd() 3020 |* 3021 |*************************************************************************/ 3022 3023 3024 sal_Bool SwCntntFrm::MoveFtnCntFwd( sal_Bool bMakePage, SwFtnBossFrm *pOldBoss ) 3025 { 3026 ASSERT( IsInFtn(), "Keine Ftn." ); 3027 SwLayoutFrm *pFtn = FindFtnFrm(); 3028 3029 // The first paragraph in the first footnote in the first column in the 3030 // sectionfrm at the top of the page has not to move forward, if the 3031 // columnbody is empty. 3032 if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() && 3033 !pFtn->GetPrev() ) 3034 { 3035 SwLayoutFrm* pBody = pOldBoss->FindBodyCont(); 3036 if( !pBody || !pBody->Lower() ) 3037 return sal_True; 3038 } 3039 3040 //fix(9538): Wenn die Ftn noch Nachbarn hinter sich hat, so muessen 3041 //diese ersteinmal verschwinden. 3042 SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext(); 3043 SwLayoutFrm *pLst = 0; 3044 while ( pNxt ) 3045 { 3046 while ( pNxt->GetNext() ) 3047 pNxt = (SwLayoutFrm*)pNxt->GetNext(); 3048 if ( pNxt == pLst ) 3049 pNxt = 0; 3050 else 3051 { pLst = pNxt; 3052 SwCntntFrm *pCnt = pNxt->ContainsCntnt(); 3053 if( pCnt ) 3054 pCnt->MoveFtnCntFwd( sal_True, pOldBoss ); 3055 pNxt = (SwLayoutFrm*)pFtn->GetNext(); 3056 } 3057 } 3058 3059 sal_Bool bSamePage = sal_True; 3060 SwLayoutFrm *pNewUpper = 3061 GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True ); 3062 3063 if ( pNewUpper ) 3064 { 3065 sal_Bool bSameBoss = sal_True; 3066 SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm(); 3067 //Wechseln wir die Spalte/Seite? 3068 if ( sal_False == ( bSameBoss = pNewBoss == pOldBoss ) ) 3069 { 3070 bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // Seitenwechsel? 3071 pNewUpper->Calc(); 3072 } 3073 3074 //Das Layoutblatt, dass wir fuer Fussnoten bekommen ist entweder 3075 //ein Fussnotencontainer oder eine Fussnote 3076 //Wenn es eine Fussnote ist, und sie die gleiche Fussnotenreferez 3077 //wie der alte Upper hat, so moven wir uns direkt hinein. 3078 //Ist die Referenz einen andere oder ist es ein Container, so wird 3079 //eine neue Fussnote erzeugt und in den Container gestellt. 3080 // Wenn wir in einem Bereich innerhalb der Fussnote sind, muss 3081 // SectionFrame noch angelegt werden. 3082 SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0; 3083 if( !pTmpFtn ) 3084 { 3085 ASSERT( pNewUpper->IsFtnContFrm(), "Neuer Upper kein FtnCont."); 3086 SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper; 3087 3088 //Fussnote erzeugen. 3089 SwFtnFrm *pOld = FindFtnFrm(); 3090 pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(), 3091 pOld, pOld->GetRef(), pOld->GetAttr() ); 3092 //Verkettung der Fussnoten. 3093 if ( pOld->GetFollow() ) 3094 { 3095 pTmpFtn->SetFollow( pOld->GetFollow() ); 3096 pOld->GetFollow()->SetMaster( pTmpFtn ); 3097 } 3098 pOld->SetFollow( pTmpFtn ); 3099 pTmpFtn->SetMaster( pOld ); 3100 SwFrm* pNx = pCont->Lower(); 3101 if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() ) 3102 while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote()) 3103 pNx = pNx->GetNext(); 3104 pTmpFtn->Paste( pCont, pNx ); 3105 pTmpFtn->Calc(); 3106 } 3107 ASSERT( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" ); 3108 // Bereiche in Fussnoten beduerfen besonderer Behandlung 3109 SwLayoutFrm *pNewUp = pTmpFtn; 3110 if( IsInSct() ) 3111 { 3112 SwSectionFrm* pSect = FindSctFrm(); 3113 // Bereich in Fussnote (oder nur Fussnote in Bereich)? 3114 if( pSect->IsInFtn() ) 3115 { 3116 if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() && 3117 pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() ) 3118 pNewUp = (SwSectionFrm*)pTmpFtn->Lower(); 3119 else 3120 { 3121 pNewUp = new SwSectionFrm( *pSect, sal_False ); 3122 pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() ); 3123 static_cast<SwSectionFrm*>(pNewUp)->Init(); 3124 pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos(); 3125 pNewUp->Frm().Pos().Y() += 1; //wg. Benachrichtigungen. 3126 3127 // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser 3128 // umgehaengt werden hinter den neuen Follow der Bereichsframes. 3129 SwFrm* pTmp = pSect->GetNext(); 3130 if( pTmp ) 3131 { 3132 SwFlowFrm* pTmpNxt; 3133 if( pTmp->IsCntntFrm() ) 3134 pTmpNxt = (SwCntntFrm*)pTmp; 3135 else if( pTmp->IsSctFrm() ) 3136 pTmpNxt = (SwSectionFrm*)pTmp; 3137 else 3138 { 3139 ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" ); 3140 pTmpNxt = (SwTabFrm*)pTmp; 3141 } 3142 pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() ); 3143 } 3144 } 3145 } 3146 } 3147 3148 MoveSubTree( pNewUp, pNewUp->Lower() ); 3149 3150 if( !bSameBoss ) 3151 Prepare( PREP_BOSS_CHGD ); 3152 } 3153 return bSamePage; 3154 } 3155 3156 /************************************************************************* 3157 |* 3158 |* class SwSaveFtnHeight 3159 |* 3160 |*************************************************************************/ 3161 3162 3163 SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) : 3164 pBoss( pBs ), 3165 nOldHeight( pBs->GetMaxFtnHeight() ) 3166 { 3167 pBoss->SetFtnDeadLine( nDeadLine ); 3168 nNewHeight = pBoss->GetMaxFtnHeight(); 3169 } 3170 3171 3172 3173 SwSaveFtnHeight::~SwSaveFtnHeight() 3174 { 3175 //Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir 3176 //ihm seinen Spass! 3177 if ( nNewHeight == pBoss->GetMaxFtnHeight() ) 3178 pBoss->nMaxFtnHeight = nOldHeight; 3179 } 3180 3181 3182 #ifdef DBG_UTIL 3183 //JP 15.10.2001: in a non pro version test if the attribute has the same 3184 // meaning which his reference is 3185 3186 // Normally, the pRef member and the GetRefFromAttr() result has to be 3187 // identically. Sometimes footnote will be moved from a master to its follow, 3188 // but the GetRef() is called first, so we have to ignore a master/follow 3189 // mismatch. 3190 3191 const SwCntntFrm* SwFtnFrm::GetRef() const 3192 { 3193 const SwCntntFrm* pRefAttr = GetRefFromAttr(); 3194 ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr ) 3195 || pRefAttr->IsAnFollow( pRef ), 3196 "access to deleted Frame? pRef != pAttr->GetRef()" ); 3197 return pRef; 3198 } 3199 3200 SwCntntFrm* SwFtnFrm::GetRef() 3201 { 3202 const SwCntntFrm* pRefAttr = GetRefFromAttr(); 3203 ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr ) 3204 || pRefAttr->IsAnFollow( pRef ), 3205 "access to deleted Frame? pRef != pAttr->GetRef()" ); 3206 return pRef; 3207 } 3208 3209 #endif 3210 3211 const SwCntntFrm* SwFtnFrm::GetRefFromAttr() const 3212 { 3213 SwFtnFrm* pThis = (SwFtnFrm*)this; 3214 return pThis->GetRefFromAttr(); 3215 } 3216 3217 SwCntntFrm* SwFtnFrm::GetRefFromAttr() 3218 { 3219 ASSERT( pAttr, "invalid Attribute" ); 3220 SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode(); 3221 SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() )); 3222 SwCntntFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, sal_False ); 3223 return pCFrm; 3224 } 3225 3226 /** search for last content in the current footnote frame 3227 3228 OD 2005-12-02 #i27138# 3229 3230 @author OD 3231 */ 3232 SwCntntFrm* SwFtnFrm::FindLastCntnt() 3233 { 3234 SwCntntFrm* pLastCntntFrm( 0L ); 3235 3236 // find last lower, which is a content frame or contains content. 3237 // hidden text frames, empty sections and empty tables have to be skipped. 3238 SwFrm* pLastLowerOfFtn( GetLower() ); 3239 SwFrm* pTmpLastLower( pLastLowerOfFtn ); 3240 while ( pTmpLastLower && pTmpLastLower->GetNext() ) 3241 { 3242 pTmpLastLower = pTmpLastLower->GetNext(); 3243 if ( ( pTmpLastLower->IsTxtFrm() && 3244 !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) || 3245 ( pTmpLastLower->IsSctFrm() && 3246 static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() && 3247 static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) || 3248 ( pTmpLastLower->IsTabFrm() && 3249 static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) ) 3250 { 3251 pLastLowerOfFtn = pTmpLastLower; 3252 } 3253 } 3254 3255 // determine last content frame depending on type of found last lower. 3256 if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() ) 3257 { 3258 pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt(); 3259 } 3260 else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() ) 3261 { 3262 pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt(); 3263 } 3264 else 3265 { 3266 pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn); 3267 } 3268 3269 return pLastCntntFrm; 3270 } 3271 3272