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