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 #include <com/sun/star/embed/EmbedStates.hpp> 32 #include <ndole.hxx> 33 #include <docary.hxx> 34 #include <svl/itemiter.hxx> 35 #include <fmtfsize.hxx> 36 #include <fmthdft.hxx> 37 #include <fmtclds.hxx> 38 #include <fmtanchr.hxx> 39 #include <fmtpdsc.hxx> 40 #include <fmtfordr.hxx> 41 #include <fmtfld.hxx> 42 #include <fmtornt.hxx> 43 #include <ftninfo.hxx> 44 #include <tgrditem.hxx> 45 #include <viewopt.hxx> 46 #include <docsh.hxx> 47 48 #include "viewimp.hxx" 49 #include "viewopt.hxx" 50 #include "pagefrm.hxx" 51 #include "rootfrm.hxx" 52 #include "cntfrm.hxx" 53 #include "flyfrm.hxx" 54 #include "doc.hxx" 55 #include "fesh.hxx" 56 #include "dview.hxx" 57 #include "dflyobj.hxx" 58 #include "dcontact.hxx" 59 #include "frmtool.hxx" 60 #include "fldbas.hxx" 61 #include "hints.hxx" 62 #include "errhdl.hxx" 63 #include "swtable.hxx" 64 65 #include "ftnidx.hxx" 66 #include "bodyfrm.hxx" 67 #include "ftnfrm.hxx" 68 #include "tabfrm.hxx" 69 #include "txtfrm.hxx" 70 #include "layact.hxx" 71 #include "flyfrms.hxx" 72 #include "htmltbl.hxx" 73 #include "pagedesc.hxx" 74 #include "poolfmt.hxx" 75 #include <editeng/frmdiritem.hxx> 76 #include <swfntcch.hxx> // SwFontAccess 77 #include <sortedobjs.hxx> 78 #include <switerator.hxx> 79 #include <vcl/svapp.hxx> 80 81 using namespace ::com::sun::star; 82 83 84 /************************************************************************* 85 |* 86 |* SwBodyFrm::SwBodyFrm() 87 |* 88 |* Ersterstellung MA ?? 89 |* Letzte Aenderung MA 01. Aug. 93 90 |* 91 |*************************************************************************/ 92 SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ): 93 SwLayoutFrm( pFmt, pSib ) 94 { 95 nType = FRMC_BODY; 96 } 97 98 /************************************************************************* 99 |* 100 |* SwBodyFrm::Format() 101 |* 102 |* Ersterstellung MA 30. May. 94 103 |* Letzte Aenderung MA 20. Jan. 99 104 |* 105 |*************************************************************************/ 106 void SwBodyFrm::Format( const SwBorderAttrs * ) 107 { 108 //Formatieren des Body ist zu einfach, deshalb bekommt er ein eigenes 109 //Format; Umrandungen und dergl. sind hier nicht zu beruecksichtigen. 110 //Breite ist die der PrtArea des Uppers, Hoehe ist die Hoehe der PrtArea 111 //des Uppers abzueglich der Nachbarn (Wird eigentlich eingestellt aber 112 //Vorsicht ist die Mutter der Robustheit). 113 //Die PrtArea ist stets so gross wie der Frm itself. 114 115 if ( !bValidSize ) 116 { 117 SwTwips nHeight = GetUpper()->Prt().Height(); 118 SwTwips nWidth = GetUpper()->Prt().Width(); 119 const SwFrm *pFrm = GetUpper()->Lower(); 120 do 121 { 122 if ( pFrm != this ) 123 { 124 if( pFrm->IsVertical() ) 125 nWidth -= pFrm->Frm().Width(); 126 else 127 nHeight -= pFrm->Frm().Height(); 128 } 129 pFrm = pFrm->GetNext(); 130 } while ( pFrm ); 131 if ( nHeight < 0 ) 132 nHeight = 0; 133 Frm().Height( nHeight ); 134 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 135 if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() ) 136 Frm().Pos().X() += Frm().Width() - nWidth; 137 Frm().Width( nWidth ); 138 } 139 140 sal_Bool bNoGrid = sal_True; 141 if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() ) 142 { 143 GETGRID( ((SwPageFrm*)GetUpper()) ) 144 if( pGrid ) 145 { 146 bNoGrid = sal_False; 147 long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight(); 148 SWRECTFN( this ) 149 long nSize = (Frm().*fnRect->fnGetWidth)(); 150 long nBorder = 0; 151 if( GRID_LINES_CHARS == pGrid->GetGridType() ) 152 { 153 //for textgrid refactor 154 SwDoc *pDoc = GetFmt()->GetDoc(); 155 nBorder = nSize % (GETGRIDWIDTH(pGrid, pDoc)); 156 nSize -= nBorder; 157 nBorder /= 2; 158 } 159 (Prt().*fnRect->fnSetPosX)( nBorder ); 160 (Prt().*fnRect->fnSetWidth)( nSize ); 161 162 // Height of body frame: 163 nBorder = (Frm().*fnRect->fnGetHeight)(); 164 165 // Number of possible lines in area of body frame: 166 long nNumberOfLines = nBorder / nSum; 167 if( nNumberOfLines > pGrid->GetLines() ) 168 nNumberOfLines = pGrid->GetLines(); 169 170 // Space required for nNumberOfLines lines: 171 nSize = nNumberOfLines * nSum; 172 nBorder -= nSize; 173 nBorder /= 2; 174 175 // #i21774# Footnotes and centering the grid does not work together: 176 const bool bAdjust = 0 == ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()-> 177 GetFtnIdxs().Count(); 178 179 (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 ); 180 (Prt().*fnRect->fnSetHeight)( nSize ); 181 } 182 } 183 if( bNoGrid ) 184 { 185 Prt().Pos().X() = Prt().Pos().Y() = 0; 186 Prt().Height( Frm().Height() ); 187 Prt().Width( Frm().Width() ); 188 } 189 bValidSize = bValidPrtArea = sal_True; 190 } 191 192 /************************************************************************* 193 |* 194 |* SwPageFrm::SwPageFrm(), ~SwPageFrm() 195 |* 196 |* Ersterstellung MA 20. Oct. 92 197 |* Letzte Aenderung MA 08. Dec. 97 198 |* 199 |*************************************************************************/ 200 SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwPageDesc *pPgDsc ) : 201 SwFtnBossFrm( pFmt, pSib ), 202 pSortedObjs( 0 ), 203 pDesc( pPgDsc ), 204 nPhyPageNum( 0 ), 205 // OD 2004-05-17 #i28701# 206 mbLayoutInProgress( false ) 207 { 208 SetDerivedVert( sal_False ); 209 SetDerivedR2L( sal_False ); 210 if( pDesc ) 211 { 212 bHasGrid = sal_True; 213 GETGRID( this ) 214 if( !pGrid ) 215 bHasGrid = sal_False; 216 } 217 else 218 bHasGrid = sal_False; 219 SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ? 220 pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ), 221 nType = FRMC_PAGE; 222 bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True; 223 bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False; 224 225 ViewShell *pSh = getRootFrm()->GetCurrShell(); 226 const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode(); 227 if ( bBrowseMode ) 228 { 229 Frm().Height( 0 ); 230 long nWidth = pSh->VisArea().Width(); 231 if ( !nWidth ) 232 nWidth = 5000L; //aendert sich sowieso 233 Frm().Width ( nWidth ); 234 } 235 else 236 Frm().SSize( pFmt->GetFrmSize().GetSize() ); 237 238 //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade 239 //eine Leerseite bin. 240 SwDoc *pDoc = pFmt->GetDoc(); 241 if ( sal_False == (bEmptyPage = pFmt == pDoc->GetEmptyPageFmt()) ) 242 { 243 bEmptyPage = sal_False; 244 Calc(); //Damit die PrtArea stimmt. 245 SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this ); 246 pBodyFrm->ChgSize( Prt().SSize() ); 247 pBodyFrm->Paste( this ); 248 pBodyFrm->Calc(); //Damit die Spalten korrekt 249 //eingesetzt werden koennen. 250 pBodyFrm->InvalidatePos(); 251 252 if ( bBrowseMode ) 253 _InvalidateSize(); //Alles nur gelogen 254 255 //Header/Footer einsetzen, nur rufen wenn aktiv. 256 if ( pFmt->GetHeader().IsActive() ) 257 PrepareHeader(); 258 if ( pFmt->GetFooter().IsActive() ) 259 PrepareFooter(); 260 261 const SwFmtCol &rCol = pFmt->GetCol(); 262 if ( rCol.GetNumCols() > 1 ) 263 { 264 const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein 265 //Old-Wert hereingereicht wird. 266 pBodyFrm->ChgColumns( aOld, rCol ); 267 } 268 } 269 } 270 271 SwPageFrm::~SwPageFrm() 272 { 273 //FlyContainer entleeren, delete der Flys uebernimmt der Anchor 274 //(Basisklasse SwFrm) 275 if ( pSortedObjs ) 276 { 277 //Objekte koennen (warum auch immer) auch an Seiten verankert sein, 278 //die vor Ihren Ankern stehen. Dann wuerde auf bereits freigegebenen 279 //Speicher zugegriffen. 280 for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i ) 281 { 282 SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i]; 283 pAnchoredObj->SetPageFrm( 0L ); 284 } 285 delete pSortedObjs; 286 pSortedObjs = 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys! 287 } 288 289 //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann. 290 if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein. 291 { 292 SwDoc *pDoc = GetFmt()->GetDoc(); 293 if( pDoc && !pDoc->IsInDtor() ) 294 { 295 ViewShell *pSh = getRootFrm()->GetCurrShell(); 296 if ( pSh ) 297 { 298 SwViewImp *pImp = pSh->Imp(); 299 pImp->SetFirstVisPageInvalid(); 300 if ( pImp->IsAction() ) 301 pImp->GetLayAction().SetAgain(); 302 // OD 12.02.2003 #i9719#, #105645# - retouche area of page 303 // including border and shadow area. 304 const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT); 305 SwRect aRetoucheRect; 306 SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, bRightSidebar ); 307 pSh->AddPaintRect( aRetoucheRect ); 308 } 309 } 310 } 311 } 312 313 314 void SwPageFrm::CheckGrid( sal_Bool bInvalidate ) 315 { 316 sal_Bool bOld = bHasGrid; 317 bHasGrid = sal_True; 318 GETGRID( this ) 319 bHasGrid = 0 != pGrid; 320 if( bInvalidate || bOld != bHasGrid ) 321 { 322 SwLayoutFrm* pBody = FindBodyCont(); 323 if( pBody ) 324 { 325 pBody->InvalidatePrt(); 326 SwCntntFrm* pFrm = pBody->ContainsCntnt(); 327 while( pBody->IsAnLower( pFrm ) ) 328 { 329 ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR ); 330 pFrm = pFrm->GetNextCntntFrm(); 331 } 332 } 333 SetCompletePaint(); 334 } 335 } 336 337 338 void SwPageFrm::CheckDirection( sal_Bool bVert ) 339 { 340 sal_uInt16 nDir = 341 ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue(); 342 if( bVert ) 343 { 344 if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir ) 345 { 346 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 347 bVertLR = 0; 348 bVertical = 0; 349 } 350 else 351 { 352 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 353 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 354 { 355 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 356 bVertLR = 0; 357 bVertical = 0; 358 } 359 else 360 { 361 bVertical = 1; 362 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 363 if(FRMDIR_VERT_TOP_RIGHT == nDir) 364 bVertLR = 0; 365 else if(FRMDIR_VERT_TOP_LEFT==nDir) 366 bVertLR = 1; 367 } 368 } 369 370 bReverse = 0; 371 bInvalidVert = 0; 372 } 373 else 374 { 375 if( FRMDIR_HORI_RIGHT_TOP == nDir ) 376 bRightToLeft = 1; 377 else 378 bRightToLeft = 0; 379 bInvalidR2L = 0; 380 } 381 } 382 383 /************************************************************************* 384 |* 385 |* SwPageFrm::PreparePage() 386 |* 387 |* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert 388 |* generischen Cntnt 389 |* Ersterstellung MA 20. Oct. 92 390 |* Letzte Aenderung MA 09. Nov. 95 391 |* 392 |*************************************************************************/ 393 void MA_FASTCALL lcl_FormatLay( SwLayoutFrm *pLay ) 394 { 395 //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren. 396 397 SwFrm *pTmp = pLay->Lower(); 398 //Erst die untergeordneten 399 while ( pTmp ) 400 { 401 if ( pTmp->GetType() & 0x00FF ) 402 ::lcl_FormatLay( (SwLayoutFrm*)pTmp ); 403 pTmp = pTmp->GetNext(); 404 } 405 pLay->Calc(); 406 } 407 408 void MA_FASTCALL lcl_MakeObjs( const SwSpzFrmFmts &rTbl, SwPageFrm *pPage ) 409 { 410 //Anlegen bzw. registrieren von Flys und Drawobjekten. 411 //Die Formate stehen in der SpzTbl (vom Dokument). 412 //Flys werden angelegt, DrawObjekte werden bei der Seite angemeldet. 413 414 for ( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 415 { 416 SdrObject *pSdrObj; 417 SwFrmFmt *pFmt = rTbl[i]; 418 const SwFmtAnchor &rAnch = pFmt->GetAnchor(); 419 if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() ) 420 { 421 if( rAnch.GetCntntAnchor() ) 422 { 423 if (FLY_AT_PAGE == rAnch.GetAnchorId()) 424 { 425 SwFmtAnchor aAnch( rAnch ); 426 aAnch.SetAnchor( 0 ); 427 pFmt->SetFmtAttr( aAnch ); 428 } 429 else 430 continue; 431 } 432 433 //Wird ein Rahmen oder ein SdrObject beschrieben? 434 sal_Bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which(); 435 pSdrObj = 0; 436 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) ) 437 { 438 ASSERT( sal_False, "DrawObject not found." ); 439 pFmt->GetDoc()->DelFrmFmt( pFmt ); 440 --i; 441 continue; 442 } 443 //Das Objekt kann noch an einer anderen Seite verankert sein. 444 //Z.B. beim Einfuegen einer neuen Seite aufgrund eines 445 //Pagedescriptor-Wechsels. Das Objekt muss dann umgehaengt 446 //werden. 447 //Fuer bestimmte Faelle ist das Objekt bereits an der richtigen 448 //Seite verankert. Das wird hier automatisch erledigt und braucht 449 //- wenngleich performater machbar - nicht extra codiert werden. 450 SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage; 451 if ( bSdrObj ) 452 { 453 // OD 23.06.2003 #108784# - consider 'virtual' drawing objects 454 SwDrawContact *pContact = 455 static_cast<SwDrawContact*>(::GetUserCall(pSdrObj)); 456 if ( pSdrObj->ISA(SwDrawVirtObj) ) 457 { 458 SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj); 459 if ( pContact ) 460 { 461 pDrawVirtObj->RemoveFromWriterLayout(); 462 pDrawVirtObj->RemoveFromDrawingPage(); 463 pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) ); 464 } 465 } 466 else 467 { 468 if ( pContact->GetAnchorFrm() ) 469 pContact->DisconnectFromLayout( false ); 470 pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) ); 471 } 472 } 473 else 474 { 475 SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt ); 476 SwFlyFrm *pFly = aIter.First(); 477 if ( pFly) 478 { 479 if( pFly->GetAnchorFrm() ) 480 pFly->AnchorFrm()->RemoveFly( pFly ); 481 } 482 else 483 pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg, pPg ); 484 pPg->AppendFly( pFly ); 485 ::RegistFlys( pPg, pFly ); 486 } 487 } 488 } 489 } 490 491 void SwPageFrm::PreparePage( sal_Bool bFtn ) 492 { 493 SetFtnPage( bFtn ); 494 495 // --> OD 2008-01-30 #i82258# 496 // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has 497 // the side effect, that the content of page header and footer are formatted. 498 // For this formatting it is needed that the anchored objects are registered 499 // at the <SwPageFrm> instance. 500 // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)> 501 ::RegistFlys( this, this ); 502 503 if ( Lower() ) 504 { 505 ::lcl_FormatLay( this ); 506 } 507 // <-- 508 509 //Flys und DrawObjekte die noch am Dokument bereitstehen. 510 //Fussnotenseiten tragen keine Seitengebundenen Flys! 511 //Es kann Flys und Objekte geben, die auf Leerseiten (Seitennummernmaessig) 512 //stehen wollen, diese werden jedoch von den Leerseiten ignoriert; 513 //sie werden von den Folgeseiten aufgenommen. 514 if ( !bFtn && !IsEmptyPage() ) 515 { 516 SwDoc *pDoc = GetFmt()->GetDoc(); 517 518 if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() ) 519 lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() ); 520 lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this ); 521 522 //Kopf-/Fusszeilen) formatieren. 523 SwLayoutFrm *pLow = (SwLayoutFrm*)Lower(); 524 while ( pLow ) 525 { 526 if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) ) 527 { 528 SwCntntFrm *pCntnt = pLow->ContainsCntnt(); 529 while ( pCntnt && pLow->IsAnLower( pCntnt ) ) 530 { 531 pCntnt->OptCalc(); //Nicht die Vorgaenger 532 pCntnt = pCntnt->GetNextCntntFrm(); 533 } 534 } 535 pLow = (SwLayoutFrm*)pLow->GetNext(); 536 } 537 } 538 } 539 540 /************************************************************************* 541 |* 542 |* SwPageFrm::Modify() 543 |* 544 |* Ersterstellung MA 20. Oct. 92 545 |* Letzte Aenderung MA 03. Mar. 96 546 |* 547 |*************************************************************************/ 548 void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 549 { 550 ViewShell *pSh = getRootFrm()->GetCurrShell(); 551 if ( pSh ) 552 pSh->SetFirstVisPageInvalid(); 553 sal_uInt8 nInvFlags = 0; 554 555 if( pNew && RES_ATTRSET_CHG == pNew->Which() ) 556 { 557 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() ); 558 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() ); 559 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld ); 560 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew ); 561 while( sal_True ) 562 { 563 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(), 564 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags, 565 &aOldSet, &aNewSet ); 566 if( aNIter.IsAtEnd() ) 567 break; 568 aNIter.NextItem(); 569 aOIter.NextItem(); 570 } 571 if ( aOldSet.Count() || aNewSet.Count() ) 572 SwLayoutFrm::Modify( &aOldSet, &aNewSet ); 573 } 574 else 575 _UpdateAttr( pOld, pNew, nInvFlags ); 576 577 if ( nInvFlags != 0 ) 578 { 579 InvalidatePage( this ); 580 if ( nInvFlags & 0x01 ) 581 _InvalidatePrt(); 582 if ( nInvFlags & 0x02 ) 583 SetCompletePaint(); 584 if ( nInvFlags & 0x04 && GetNext() ) 585 GetNext()->InvalidatePos(); 586 if ( nInvFlags & 0x08 ) 587 PrepareHeader(); 588 if ( nInvFlags & 0x10 ) 589 PrepareFooter(); 590 if ( nInvFlags & 0x20 ) 591 CheckGrid( nInvFlags & 0x40 ); 592 } 593 } 594 595 void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew, 596 sal_uInt8 &rInvFlags, 597 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet ) 598 { 599 sal_Bool bClear = sal_True; 600 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 601 switch( nWhich ) 602 { 603 case RES_FMT_CHG: 604 { 605 //Wenn sich das FrmFmt aendert kann hier einiges passieren. 606 //Abgesehen von den Grossenverhaeltnissen sind noch andere 607 //Dinge betroffen. 608 //1. Spaltigkeit. 609 ASSERT( pOld && pNew, "FMT_CHG Missing Format." ); 610 const SwFmt* pOldFmt = ((SwFmtChg*)pOld)->pChangedFmt; 611 const SwFmt* pNewFmt = ((SwFmtChg*)pNew)->pChangedFmt; 612 ASSERT( pOldFmt && pNewFmt, "FMT_CHG Missing Format." ); 613 614 const SwFmtCol &rOldCol = pOldFmt->GetCol(); 615 const SwFmtCol &rNewCol = pNewFmt->GetCol(); 616 if( rOldCol != rNewCol ) 617 { 618 SwLayoutFrm *pB = FindBodyCont(); 619 ASSERT( pB, "Seite ohne Body." ); 620 pB->ChgColumns( rOldCol, rNewCol ); 621 rInvFlags |= 0x20; 622 } 623 624 //2. Kopf- und Fusszeilen. 625 const SwFmtHeader &rOldH = pOldFmt->GetHeader(); 626 const SwFmtHeader &rNewH = pNewFmt->GetHeader(); 627 if( rOldH != rNewH ) 628 rInvFlags |= 0x08; 629 630 const SwFmtFooter &rOldF = pOldFmt->GetFooter(); 631 const SwFmtFooter &rNewF = pNewFmt->GetFooter(); 632 if( rOldF != rNewF ) 633 rInvFlags |= 0x10; 634 CheckDirChange(); 635 } 636 /* kein break hier */ 637 case RES_FRM_SIZE: 638 { 639 const SwRect aOldPageFrmRect( Frm() ); 640 ViewShell *pSh = getRootFrm()->GetCurrShell(); 641 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 642 { 643 bValidSize = sal_False; 644 // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()> 645 // Calculation of the page is not necessary, because its size is 646 // is invalidated here and further invalidation is done in the 647 // calling method <SwPageFrm::Modify(..)> and probably by calling 648 // <SwLayoutFrm::Modify(..)> at the end. 649 // It can also causes inconsistences, because the lowers are 650 // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of 651 // a next page is called. This is performed on the switch to the 652 // online layout. 653 //MakeAll(); 654 } 655 else 656 { 657 const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ? 658 ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() : 659 (const SwFmtFrmSize&)*pNew; 660 661 Frm().Height( Max( rSz.GetHeight(), long(MINLAY) ) ); 662 Frm().Width ( Max( rSz.GetWidth(), long(MINLAY) ) ); 663 664 // PAGES01 665 if ( GetUpper() ) 666 static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 ); 667 } 668 //Window aufraeumen. 669 if( pSh && pSh->GetWin() && aOldPageFrmRect.HasArea() ) 670 { 671 // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of 672 // page frame for determine 'old' rectangle - it's used for invalidating. 673 const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT); 674 SwRect aOldRectWithBorderAndShadow; 675 SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow, bRightSidebar ); 676 pSh->InvalidateWindows( aOldRectWithBorderAndShadow ); 677 } 678 rInvFlags |= 0x03; 679 if ( aOldPageFrmRect.Height() != Frm().Height() ) 680 rInvFlags |= 0x04; 681 } 682 break; 683 684 case RES_COL: 685 { 686 SwLayoutFrm *pB = FindBodyCont(); 687 ASSERT( pB, "Seite ohne Body." ); 688 pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew ); 689 rInvFlags |= 0x22; 690 } 691 break; 692 693 case RES_HEADER: 694 rInvFlags |= 0x08; 695 break; 696 697 case RES_FOOTER: 698 rInvFlags |= 0x10; 699 break; 700 case RES_TEXTGRID: 701 rInvFlags |= 0x60; 702 break; 703 704 case RES_PAGEDESC_FTNINFO: 705 //Die derzeit einzig sichere Methode: 706 ((SwRootFrm*)GetUpper())->SetSuperfluous(); 707 SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() ); 708 if ( !GetMaxFtnHeight() ) 709 SetMaxFtnHeight( LONG_MAX ); 710 SetColMaxFtnHeight(); 711 //Hier wird die Seite ggf. zerstoert! 712 ((SwRootFrm*)GetUpper())->RemoveFtns( 0, sal_False, sal_True ); 713 break; 714 case RES_FRAMEDIR : 715 CheckDirChange(); 716 break; 717 718 default: 719 bClear = sal_False; 720 } 721 if ( bClear ) 722 { 723 if ( pOldSet || pNewSet ) 724 { 725 if ( pOldSet ) 726 pOldSet->ClearItem( nWhich ); 727 if ( pNewSet ) 728 pNewSet->ClearItem( nWhich ); 729 } 730 else 731 SwLayoutFrm::Modify( pOld, pNew ); 732 } 733 } 734 735 /************************************************************************* 736 |* 737 |* SwPageFrm::GetInfo() 738 |* 739 |* Beschreibung erfragt Informationen 740 |* Ersterstellung JP 31.03.94 741 |* Letzte Aenderung JP 31.03.94 742 |* 743 *************************************************************************/ 744 // erfrage vom Modify Informationen 745 sal_Bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const 746 { 747 if( RES_AUTOFMT_DOCNODE == rInfo.Which() ) 748 { 749 // es gibt einen PageFrm also wird er benutzt 750 return sal_False; 751 } 752 return sal_True; // weiter suchen 753 } 754 755 /************************************************************************* 756 |* 757 |* SwPageFrm::SetPageDesc() 758 |* 759 |* Ersterstellung MA 02. Nov. 94 760 |* Letzte Aenderung MA 02. Nov. 94 761 |* 762 |*************************************************************************/ 763 void SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt ) 764 { 765 pDesc = pNew; 766 if ( pFmt ) 767 SetFrmFmt( pFmt ); 768 } 769 770 /************************************************************************* 771 |* 772 |* SwPageFrm::FindPageDesc() 773 |* 774 |* Beschreibung Der richtige PageDesc wird bestimmt: 775 |* 0. Vom Dokument bei Fussnotenseiten und Endnotenseiten 776 |* 1. vom ersten BodyCntnt unterhalb der Seite. 777 |* 2. vom PageDesc der vorstehenden Seite. 778 |* 3. bei Leerseiten vom PageDesc der vorigen Seite. 779 |* 3.1 vom PageDesc der folgenden Seite wenn es keinen Vorgaenger gibt. 780 |* 4. es ist der Default-PageDesc sonst. 781 |* 5. Im BrowseMode ist der Pagedesc immer der vom ersten Absatz im 782 |* Dokument oder Standard (der 0-te) wenn der erste Absatz keinen 783 |* wuenscht. 784 |* (6. Im HTML-Mode ist der Pagedesc immer die HTML-Seitenvorlage.) 785 |* Ersterstellung MA 15. Feb. 93 786 |* Letzte Aenderung MA 17. Jun. 99 787 |* 788 |*************************************************************************/ 789 SwPageDesc *SwPageFrm::FindPageDesc() 790 { 791 //0. 792 if ( IsFtnPage() ) 793 { 794 SwDoc *pDoc = GetFmt()->GetDoc(); 795 if ( IsEndNotePage() ) 796 return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc ); 797 else 798 return pDoc->GetFtnInfo().GetPageDesc( *pDoc ); 799 } 800 801 //6. 802 //if ( GetFmt()->GetDoc()->IsHTMLMode() ) 803 // return GetFmt()->GetDoc()->GetPageDescFromPool( RES_POOLPAGE_HTML ); 804 805 SwPageDesc *pRet = 0; 806 807 //5. 808 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 809 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 810 { 811 SwCntntFrm *pFrm = GetUpper()->ContainsCntnt(); 812 while ( !pFrm->IsInDocBody() ) 813 pFrm = pFrm->GetNextCntntFrm(); 814 SwFrm *pFlow = pFrm; 815 if ( pFlow->IsInTab() ) 816 pFlow = pFlow->FindTabFrm(); 817 pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc(); 818 if ( !pRet ) 819 pRet = &GetFmt()->GetDoc()->_GetPageDesc( 0 ); 820 return pRet; 821 } 822 823 SwFrm *pFlow = FindFirstBodyCntnt(); 824 if ( pFlow && pFlow->IsInTab() ) 825 pFlow = pFlow->FindTabFrm(); 826 827 //1. 828 if ( pFlow ) 829 { 830 SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow ); 831 if ( !pTmp->IsFollow() ) 832 pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc(); 833 } 834 835 //3. und 3.1 836 if ( !pRet && IsEmptyPage() ) 837 // FME 2008-03-03 #i81544# lijian/fme: an empty page should have 838 // the same page description as its prev, just like after construction 839 // of the empty page. 840 pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() : 841 GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0; 842 843 //2. 844 if ( !pRet ) 845 pRet = GetPrev() ? 846 ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0; 847 848 //4. 849 if ( !pRet ) 850 pRet = (SwPageDesc*)&(const_cast<const SwDoc *>(GetFmt()->GetDoc()) 851 ->GetPageDesc( 0 )); 852 853 854 ASSERT( pRet, "Kein Descriptor gefunden." ); 855 return pRet; 856 } 857 858 //Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden. 859 void AdjustSizeChgNotify( SwRootFrm *pRoot ) 860 { 861 const sal_Bool bOld = pRoot->IsSuperfluous(); 862 pRoot->bCheckSuperfluous = sal_False; 863 ViewShell *pSh = pRoot->GetCurrShell(); 864 if ( pSh ) 865 { 866 do 867 { 868 if( pRoot == pSh->GetLayout() ) 869 { 870 pSh->SizeChgNotify(); 871 pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() ); 872 } 873 pSh = (ViewShell*)pSh->GetNext(); 874 } while ( pSh != pRoot->GetCurrShell() ); 875 } 876 pRoot->bCheckSuperfluous = bOld; 877 } 878 879 880 inline void SetLastPage( SwPageFrm *pPage ) 881 { 882 ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage; 883 } 884 885 /************************************************************************* 886 |* 887 |* SwPageFrm::Cut() 888 |* 889 |* Ersterstellung MA 23. Feb. 94 890 |* Letzte Aenderung MA 22. Jun. 95 891 |* 892 |*************************************************************************/ 893 void SwPageFrm::Cut() 894 { 895 // PAGES01 896 //AdjustRootSize( CHG_CUTPAGE, 0 ); 897 898 ViewShell *pSh = getRootFrm()->GetCurrShell(); 899 if ( !IsEmptyPage() ) 900 { 901 if ( GetNext() ) 902 GetNext()->InvalidatePos(); 903 904 //Flys deren Anker auf anderen Seiten stehen umhaengen. 905 //DrawObjecte spielen hier keine Rolle. 906 if ( GetSortedObjs() ) 907 { 908 for ( int i = 0; GetSortedObjs() && 909 (sal_uInt16)i < GetSortedObjs()->Count(); ++i ) 910 { 911 // --> OD 2004-06-29 #i28701# 912 SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i]; 913 914 if ( pAnchoredObj->ISA(SwFlyAtCntFrm) ) 915 { 916 SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj); 917 SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ? 918 pFly->AnchorFrm()->FindPageFrm() : 0; 919 if ( pAnchPage && (pAnchPage != this) ) 920 { 921 MoveFly( pFly, pAnchPage ); 922 --i; 923 pFly->InvalidateSize(); 924 pFly->_InvalidatePos(); 925 } 926 } 927 // <-- 928 } 929 } 930 //Window aufraeumen 931 if ( pSh && pSh->GetWin() ) 932 pSh->InvalidateWindows( Frm() ); 933 } 934 935 // die Seitennummer der Root runterzaehlen. 936 ((SwRootFrm*)GetUpper())->DecrPhyPageNums(); 937 SwPageFrm *pPg = (SwPageFrm*)GetNext(); 938 if ( pPg ) 939 { 940 while ( pPg ) 941 { 942 pPg->DecrPhyPageNum(); //inline --nPhyPageNum 943 pPg = (SwPageFrm*)pPg->GetNext(); 944 } 945 } 946 else 947 ::SetLastPage( (SwPageFrm*)GetPrev() ); 948 949 SwFrm* pRootFrm = GetUpper(); 950 951 // Alle Verbindungen kappen. 952 Remove(); 953 954 // PAGES01 955 if ( pRootFrm ) 956 static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 ); 957 } 958 959 /************************************************************************* 960 |* 961 |* SwPageFrm::Paste() 962 |* 963 |* Ersterstellung MA 23. Feb. 94 964 |* Letzte Aenderung MA 07. Dec. 94 965 |* 966 |*************************************************************************/ 967 void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) 968 { 969 ASSERT( pParent->IsRootFrm(), "Parent ist keine Root." ); 970 ASSERT( pParent, "Kein Parent fuer Paste." ); 971 ASSERT( pParent != this, "Bin selbst der Parent." ); 972 ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); 973 ASSERT( !GetPrev() && !GetNext() && !GetUpper(), 974 "Bin noch irgendwo angemeldet." ); 975 976 //In den Baum einhaengen. 977 InsertBefore( (SwLayoutFrm*)pParent, pSibling ); 978 979 // die Seitennummer am Root hochzaehlen. 980 ((SwRootFrm*)GetUpper())->IncrPhyPageNums(); 981 if( GetPrev() ) 982 SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 ); 983 else 984 SetPhyPageNum( 1 ); 985 SwPageFrm *pPg = (SwPageFrm*)GetNext(); 986 if ( pPg ) 987 { 988 while ( pPg ) 989 { 990 pPg->IncrPhyPageNum(); //inline ++nPhyPageNum 991 pPg->_InvalidatePos(); 992 pPg->InvalidateLayout(); 993 pPg = (SwPageFrm*)pPg->GetNext(); 994 } 995 } 996 else 997 ::SetLastPage( this ); 998 999 if( Frm().Width() != pParent->Prt().Width() ) 1000 _InvalidateSize(); 1001 1002 InvalidatePos(); 1003 1004 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1005 if ( pSh ) 1006 pSh->SetFirstVisPageInvalid(); 1007 // PAGES01 1008 getRootFrm()->CheckViewLayout( 0, 0 ); 1009 } 1010 1011 /************************************************************************* 1012 |* 1013 |* SwPageFrm::PrepareRegisterChg() 1014 |* 1015 |* Ersterstellung AMA 22. Jul. 96 1016 |* Letzte Aenderung AMA 22. Jul. 96 1017 |* 1018 |*************************************************************************/ 1019 void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm ) 1020 { 1021 pFrm->Prepare( PREP_REGISTER ); 1022 if( pFrm->GetDrawObjs() ) 1023 { 1024 for( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i ) 1025 { 1026 // --> OD 2004-06-29 #i28701# 1027 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i]; 1028 if ( pAnchoredObj->ISA(SwFlyInCntFrm) ) 1029 { 1030 SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj); 1031 SwCntntFrm *pCnt = pFly->ContainsCntnt(); 1032 while ( pCnt ) 1033 { 1034 lcl_PrepFlyInCntRegister( pCnt ); 1035 pCnt = pCnt->GetNextCntntFrm(); 1036 } 1037 } 1038 // <-- 1039 } 1040 } 1041 } 1042 1043 void SwPageFrm::PrepareRegisterChg() 1044 { 1045 SwCntntFrm *pFrm = FindFirstBodyCntnt(); 1046 while( pFrm ) 1047 { 1048 lcl_PrepFlyInCntRegister( pFrm ); 1049 pFrm = pFrm->GetNextCntntFrm(); 1050 if( !IsAnLower( pFrm ) ) 1051 break; 1052 } 1053 if( GetSortedObjs() ) 1054 { 1055 for( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i ) 1056 { 1057 // --> OD 2004-06-29 #i28701# 1058 SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i]; 1059 if ( pAnchoredObj->ISA(SwFlyFrm) ) 1060 { 1061 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 1062 pFrm = pFly->ContainsCntnt(); 1063 while ( pFrm ) 1064 { 1065 ::lcl_PrepFlyInCntRegister( pFrm ); 1066 pFrm = pFrm->GetNextCntntFrm(); 1067 } 1068 } 1069 } 1070 } 1071 } 1072 1073 /************************************************************************* 1074 |* 1075 |* SwFrm::CheckPageDescs() 1076 |* 1077 |* Beschreibung Prueft alle Seiten ab der uebergebenen, daraufhin, 1078 |* ob sie das richtige FrmFmt verwenden. Wenn 'falsche' Seiten 1079 |* aufgespuehrt werden, so wird versucht die Situation moeglichst 1080 |* einfache zu bereinigen. 1081 |* 1082 |* Ersterstellung MA 10. Feb. 93 1083 |* Letzte Aenderung MA 18. Apr. 96 1084 |* 1085 |*************************************************************************/ 1086 void SwFrm::CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields ) 1087 { 1088 ASSERT( pStart, "Keine Startpage." ); 1089 1090 ViewShell *pSh = pStart->getRootFrm()->GetCurrShell(); 1091 SwViewImp *pImp = pSh ? pSh->Imp() : 0; 1092 1093 if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() ) 1094 { 1095 pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() ); 1096 return; 1097 } 1098 1099 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos 1100 //die Seitenposition an, _ab_ der invalidiert werden soll. 1101 SwTwips nDocPos = LONG_MAX; 1102 1103 SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper(); 1104 SwDoc* pDoc = pStart->GetFmt()->GetDoc(); 1105 const sal_Bool bFtns = 0 != pDoc->GetFtnIdxs().Count(); 1106 1107 SwPageFrm *pPage = pStart; 1108 if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() ) 1109 pPage = (SwPageFrm*)pPage->GetPrev(); 1110 while ( pPage ) 1111 { 1112 //gewuenschten PageDesc und FrmFmt festellen. 1113 SwPageDesc *pDesc = pPage->FindPageDesc(); 1114 sal_Bool bCheckEmpty = pPage->IsEmptyPage(); 1115 sal_Bool bActOdd = pPage->OnRightPage(); 1116 sal_Bool bOdd = pPage->WannaRightPage(); 1117 SwFrmFmt *pFmtWish = bOdd ? pDesc->GetRightFmt() 1118 : pDesc->GetLeftFmt(); 1119 1120 if ( bActOdd != bOdd || 1121 pDesc != pPage->GetPageDesc() || //falscher Desc 1122 ( pFmtWish != pPage->GetFmt() && //falsches Format und 1123 ( !pPage->IsEmptyPage() || pFmtWish ) //nicht Leerseite 1124 ) 1125 ) 1126 { 1127 //Wenn wir schon ein Seite veraendern muessen kann das eine 1128 //Weile dauern, deshalb hier den WaitCrsr pruefen. 1129 if( pImp ) 1130 pImp->CheckWaitCrsr(); 1131 1132 //Ab hier muessen die Felder invalidiert werden! 1133 if ( nDocPos == LONG_MAX ) 1134 nDocPos = pPage->GetPrev() ? 1135 pPage->GetPrev()->Frm().Top() : pPage->Frm().Top(); 1136 1137 //Faelle: 1138 //1. Wir haben eine EmptyPage und wollen eine "Normalseite". 1139 // ->EmptyPage wegwerfen und weiter mit der naechsten. 1140 //2. Wir haben eine EmptyPage und wollen eine EmptyPage mit 1141 // anderem Descriptor. 1142 // ->Descriptor austauschen. 1143 //3. Wir haben eine "Normalseite" und wollen eine EmptyPage. 1144 // ->Emptypage einfuegen, nicht aber wenn die Vorseite 1145 // bereits eine EmptyPage ist -> 6. 1146 //4. Wir haben eine "Normalseite" und wollen eine "Normalseite" 1147 // mit anderem Descriptor 1148 // ->Descriptor und Format austauschen 1149 //5. Wir haben eine "Normalseite" und wollen eine "Normalseite" 1150 // mit anderem Format 1151 // ->Format austauschen. 1152 //6. Wir haben kein Wunschformat erhalten, also nehmen wir das 1153 // 'andere' Format (rechts/links) des PageDesc. 1154 1155 if ( pPage->IsEmptyPage() && ( pFmtWish || //1. 1156 ( !bOdd && !pPage->GetPrev() ) ) ) 1157 { 1158 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext(); 1159 pPage->Cut(); 1160 delete pPage; 1161 if ( pStart == pPage ) 1162 pStart = pTmp; 1163 pPage = pTmp; 1164 continue; 1165 } 1166 else if ( pPage->IsEmptyPage() && !pFmtWish && //2. 1167 pDesc != pPage->GetPageDesc() ) 1168 { 1169 pPage->SetPageDesc( pDesc, 0 ); 1170 } 1171 else if ( !pPage->IsEmptyPage() && //3. 1172 bActOdd != bOdd && 1173 ( ( !pPage->GetPrev() && !bOdd ) || 1174 ( pPage->GetPrev() && 1175 !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() ) 1176 ) 1177 ) 1178 { 1179 if ( pPage->GetPrev() ) 1180 pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc(); 1181 SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pRoot,pDesc); 1182 pTmp->Paste( pRoot, pPage ); 1183 pTmp->PreparePage( sal_False ); 1184 pPage = pTmp; 1185 } 1186 else if ( pPage->GetPageDesc() != pDesc ) //4. 1187 { 1188 SwPageDesc *pOld = pPage->GetPageDesc(); 1189 pPage->SetPageDesc( pDesc, pFmtWish ); 1190 if ( bFtns ) 1191 { 1192 //Wenn sich bestimmte Werte der FtnInfo veraendert haben 1193 //muss etwas passieren. Wir versuchen den Schaden zu 1194 //begrenzen. 1195 //Wenn die Seiten keinen FtnCont hat, ist zwar theoretisches 1196 //ein Problem denkbar, aber das ignorieren wir mit aller Kraft. 1197 //Bei Aenderungen hoffen wir mal, dass eine Invalidierung 1198 //ausreicht, denn alles andere wuerde viel Kraft kosten. 1199 SwFtnContFrm *pCont = pPage->FindFtnCont(); 1200 if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) ) 1201 pCont->_InvalidateAll(); 1202 } 1203 } 1204 else if ( pFmtWish && pPage->GetFmt() != pFmtWish ) //5. 1205 { 1206 pPage->SetFrmFmt( pFmtWish ); 1207 } 1208 else if ( !pFmtWish ) //6. 1209 { 1210 //Format mit verdrehter Logic besorgen. 1211 pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt(); 1212 if ( pPage->GetFmt() != pFmtWish ) 1213 pPage->SetFrmFmt( pFmtWish ); 1214 } 1215 #ifdef DBG_UTIL 1216 else 1217 { 1218 ASSERT( sal_False, "CheckPageDescs, missing solution" ); 1219 } 1220 #endif 1221 } 1222 if ( bCheckEmpty ) 1223 { 1224 //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist. 1225 //Obiger Algorithmus kann dies leider nicht feststellen. 1226 //Eigentlich muesste die Leerseite einfach praeventiv entfernt 1227 //werden; sie wuerde ja ggf. wieder eingefuegt. 1228 //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite 1229 //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse 1230 //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle 1231 //Seitennummer manuell. 1232 SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext(); 1233 if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() ) 1234 { 1235 //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen 1236 //Nachfolger, also ist die Leerseite ueberfluessig. 1237 SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext(); 1238 pPage->Cut(); 1239 delete pPage; 1240 if ( pStart == pPage ) 1241 pStart = pTmp; 1242 pPage = pTmp; 1243 continue; 1244 } 1245 } 1246 pPage = (SwPageFrm*)pPage->GetNext(); 1247 } 1248 1249 pRoot->SetAssertFlyPages(); 1250 pRoot->AssertPageFlys( pStart ); 1251 1252 if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) ) 1253 { 1254 SwDocPosUpdate aMsgHnt( nDocPos ); 1255 pDoc->UpdatePageFlds( &aMsgHnt ); 1256 } 1257 1258 #ifdef DBG_UTIL 1259 //Ein paar Pruefungen muessen schon erlaubt sein. 1260 1261 //1. Keine zwei EmptyPages hintereinander. 1262 //2. Alle PageDescs richtig? 1263 sal_Bool bEmpty = sal_False; 1264 SwPageFrm *pPg = pStart; 1265 while ( pPg ) 1266 { 1267 if ( pPg->IsEmptyPage() ) 1268 { 1269 if ( bEmpty ) 1270 { 1271 ASSERT( sal_False, "Doppelte Leerseiten." ); 1272 break; //Einmal reicht. 1273 } 1274 bEmpty = sal_True; 1275 } 1276 else 1277 bEmpty = sal_False; 1278 1279 //MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus 1280 //moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden, 1281 //rechte als folge der ersten, linke als folge der rechten, rechte als 1282 //folge der linken. 1283 // ASSERT( pPg->GetPageDesc() == pPg->FindPageDesc(), 1284 // "Seite mit falschem Descriptor." ); 1285 1286 pPg = (SwPageFrm*)pPg->GetNext(); 1287 } 1288 #endif 1289 } 1290 1291 /************************************************************************* 1292 |* 1293 |* SwFrm::InsertPage() 1294 |* 1295 |* Beschreibung 1296 |* Ersterstellung MA 10. Feb. 93 1297 |* Letzte Aenderung MA 27. Jul. 93 1298 |* 1299 |*************************************************************************/ 1300 SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn ) 1301 { 1302 SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper(); 1303 SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower(); 1304 SwPageDesc *pDesc = pSibling->GetPageDesc(); 1305 1306 pSibling = (SwPageFrm*)pPrevPage->GetNext(); 1307 //Rechte (ungerade) oder linke (gerade) Seite einfuegen? 1308 sal_Bool bNextOdd = !pPrevPage->OnRightPage(); 1309 sal_Bool bWishedOdd = bNextOdd; 1310 1311 //Welcher PageDesc gilt? 1312 //Bei CntntFrm der aus dem Format wenn einer angegeben ist, 1313 //der Follow vom bereits in der PrevPage gueltigen sonst. 1314 pDesc = 0; 1315 if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() ) 1316 { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc(); 1317 pDesc = rDesc.GetPageDesc(); 1318 if ( rDesc.GetNumOffset() ) 1319 { 1320 bWishedOdd = rDesc.GetNumOffset() % 2 ? sal_True : sal_False; 1321 //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen. 1322 pRoot->SetVirtPageNum( sal_True ); 1323 } 1324 } 1325 if ( !pDesc ) 1326 pDesc = pPrevPage->GetPageDesc()->GetFollow(); 1327 1328 ASSERT( pDesc, "Missing PageDesc" ); 1329 if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ) 1330 bWishedOdd = !bWishedOdd; 1331 1332 SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc(); 1333 SwFrmFmt *pFmt; 1334 sal_Bool bCheckPages = sal_False; 1335 //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine 1336 //Leerseite einfuegen. 1337 if( bWishedOdd != bNextOdd ) 1338 { pFmt = pDoc->GetEmptyPageFmt(); 1339 SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc(); 1340 SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pTmpDesc ); 1341 pPage->Paste( pRoot, pSibling ); 1342 pPage->PreparePage( bFtn ); 1343 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten 1344 //Es sei denn, es ist eine Fussnotenseite 1345 if ( pSibling && !pSibling->IsFtnPage() && 1346 !pSibling->FindFirstBodyCntnt() ) 1347 { 1348 SwPageFrm *pDel = pSibling; 1349 pSibling = (SwPageFrm*)pSibling->GetNext(); 1350 if ( pDoc->GetFtnIdxs().Count() ) 1351 pRoot->RemoveFtns( pDel, sal_True ); 1352 pDel->Cut(); 1353 delete pDel; 1354 } 1355 else 1356 bCheckPages = sal_True; 1357 } 1358 pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt(); 1359 ASSERT( pFmt, "Descriptor without format." ); 1360 SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc ); 1361 pPage->Paste( pRoot, pSibling ); 1362 pPage->PreparePage( bFtn ); 1363 //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten 1364 //Es sei denn es ist eine Fussnotenseite. 1365 if ( pSibling && !pSibling->IsFtnPage() && 1366 !pSibling->FindFirstBodyCntnt() ) 1367 { 1368 SwPageFrm *pDel = pSibling; 1369 pSibling = (SwPageFrm*)pSibling->GetNext(); 1370 if ( pDoc->GetFtnIdxs().Count() ) 1371 pRoot->RemoveFtns( pDel, sal_True ); 1372 pDel->Cut(); 1373 delete pDel; 1374 } 1375 else 1376 bCheckPages = sal_True; 1377 1378 if ( pSibling ) 1379 { 1380 if ( bCheckPages ) 1381 { 1382 CheckPageDescs( pSibling, sal_False ); 1383 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1384 SwViewImp *pImp = pSh ? pSh->Imp() : 0; 1385 if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() ) 1386 { 1387 const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum(); 1388 if ( nNum == pPrevPage->GetPhyPageNum() + 1 ) 1389 pImp->GetLayAction().SetCheckPageNumDirect( 1390 pSibling->GetPhyPageNum() ); 1391 return pPage; 1392 } 1393 } 1394 else 1395 pRoot->AssertPageFlys( pSibling ); 1396 } 1397 1398 //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos 1399 //die Seitenposition an, _ab_ der invalidiert werden soll. 1400 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1401 if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() ) 1402 { 1403 SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() ); 1404 pDoc->UpdatePageFlds( &aMsgHnt ); 1405 } 1406 return pPage; 1407 } 1408 1409 sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const 1410 { 1411 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1412 if( !pSh || pSh->GetViewOptions()->getBrowseMode() ) 1413 { 1414 return sw::sidebarwindows::SIDEBAR_RIGHT; 1415 } 1416 else 1417 { 1418 const bool bLTR = getRootFrm()->IsLeftToRightViewLayout(); 1419 const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode(); 1420 const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage()); 1421 1422 return bRightSidebar 1423 ? sw::sidebarwindows::SIDEBAR_RIGHT 1424 : sw::sidebarwindows::SIDEBAR_LEFT; 1425 } 1426 } 1427 1428 /************************************************************************* 1429 |* 1430 |* SwRootFrm::GrowFrm() 1431 |* 1432 |* Ersterstellung MA 30. Jul. 92 1433 |* Letzte Aenderung MA 05. May. 94 1434 |* 1435 |*************************************************************************/ 1436 1437 SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool ) 1438 { 1439 if ( !bTst ) 1440 Frm().SSize().Height() += nDist; 1441 return nDist; 1442 } 1443 /************************************************************************* 1444 |* 1445 |* SwRootFrm::ShrinkFrm() 1446 |* 1447 |* Ersterstellung MA 30. Jul. 92 1448 |* Letzte Aenderung MA 05. May. 94 1449 |* 1450 |*************************************************************************/ 1451 SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool ) 1452 { 1453 ASSERT( nDist >= 0, "nDist < 0." ); 1454 ASSERT( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." ); 1455 1456 if ( !bTst ) 1457 Frm().SSize().Height() -= nDist; 1458 return nDist; 1459 } 1460 1461 /************************************************************************* 1462 |* 1463 |* SwRootFrm::RemoveSuperfluous() 1464 |* 1465 |* Beschreibung: Entfernung von ueberfluessigen Seiten. 1466 |* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist. 1467 |* Definition: Eine Seite ist genau dann leer, wenn der 1468 |* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch 1469 |* mindestens ein Fly an der Seite klebt. 1470 |* Die Seite ist auch dann nicht leer, wenn sie noch eine 1471 |* Fussnote enthaelt. 1472 |* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren: 1473 |* - einmal fuer die Endnotenseiten. 1474 |* - und einmal fuer die Seiten des Bodytextes. 1475 |* 1476 |* Ersterstellung MA 20. May. 92 1477 |* Letzte Aenderung MA 10. Jan. 95 1478 |* 1479 |*************************************************************************/ 1480 void SwRootFrm::RemoveSuperfluous() 1481 { 1482 if ( !IsSuperfluous() ) 1483 return; 1484 bCheckSuperfluous = sal_False; 1485 1486 SwPageFrm *pPage = GetLastPage(); 1487 long nDocPos = LONG_MAX; 1488 1489 //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist 1490 //bei der ersten nicht leeren Seite wird die Schleife beendet. 1491 do 1492 { 1493 bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() ); 1494 if ( bExistEssentialObjs ) 1495 { 1496 //Nur weil die Seite Flys hat sind wir noch lange nicht fertig, 1497 //denn wenn alle Flys an generischem Inhalt haengen, so ist sie 1498 //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen). 1499 // OD 19.06.2003 #108784# - consider that drawing objects in 1500 // header/footer are supported now. 1501 bool bOnlySuperfluosObjs = true; 1502 SwSortedObjs &rObjs = *pPage->GetSortedObjs(); 1503 for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i ) 1504 { 1505 // --> OD 2004-06-29 #i28701# 1506 SwAnchoredObject* pAnchoredObj = rObjs[i]; 1507 // OD 2004-01-19 #110582# - do not consider hidden objects 1508 if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId( 1509 pAnchoredObj->GetDrawObj()->GetLayer() ) && 1510 !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() ) 1511 { 1512 bOnlySuperfluosObjs = false; 1513 } 1514 // <-- 1515 } 1516 bExistEssentialObjs = !bOnlySuperfluosObjs; 1517 } 1518 1519 // OD 19.06.2003 #108784# - optimization: check first, if essential objects 1520 // exists. 1521 const SwLayoutFrm* pBody = 0; 1522 if ( bExistEssentialObjs || 1523 pPage->FindFtnCont() || 1524 ( 0 != ( pBody = pPage->FindBodyCont() ) && 1525 ( pBody->ContainsCntnt() || 1526 // --> FME 2005-05-18 #i47580# 1527 // Do not delete page if there's an empty tabframe 1528 // left. I think it might be correct to use ContainsAny() 1529 // instead of ContainsCntnt() to cover the empty-table-case, 1530 // but I'm not fully sure, since ContainsAny() also returns 1531 // SectionFrames. Therefore I prefer to do it the safe way: 1532 ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) ) 1533 // <-- 1534 { 1535 if ( pPage->IsFtnPage() ) 1536 { 1537 while ( pPage->IsFtnPage() ) 1538 { 1539 pPage = (SwPageFrm*)pPage->GetPrev(); 1540 ASSERT( pPage, "Nur noch Endnotenseiten uebrig." ); 1541 } 1542 continue; 1543 } 1544 else 1545 pPage = 0; 1546 } 1547 1548 if ( pPage ) 1549 { 1550 SwPageFrm *pEmpty = pPage; 1551 pPage = (SwPageFrm*)pPage->GetPrev(); 1552 if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() ) 1553 RemoveFtns( pEmpty, sal_True ); 1554 pEmpty->Cut(); 1555 delete pEmpty; 1556 nDocPos = pPage ? pPage->Frm().Top() : 0; 1557 } 1558 } while ( pPage ); 1559 1560 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1561 if ( nDocPos != LONG_MAX && 1562 (!pSh || !pSh->Imp()->IsUpdateExpFlds()) ) 1563 { 1564 SwDocPosUpdate aMsgHnt( nDocPos ); 1565 GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt ); 1566 } 1567 } 1568 1569 /************************************************************************* 1570 |* 1571 |* SwRootFrm::AssertFlyPages() 1572 |* 1573 |* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden 1574 |* sind, damit alle Seitengebundenen Rahmen und DrawObject 1575 |* untergebracht sind. 1576 |* 1577 |* Ersterstellung MA 27. Jul. 93 1578 |* Letzte Aenderung MA 24. Apr. 97 1579 |* 1580 |*************************************************************************/ 1581 void SwRootFrm::AssertFlyPages() 1582 { 1583 if ( !IsAssertFlyPages() ) 1584 return; 1585 bAssertFlyPages = sal_False; 1586 1587 SwDoc *pDoc = GetFmt()->GetDoc(); 1588 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts(); 1589 1590 //Auf welche Seite will der 'letzte' Fly? 1591 sal_uInt16 nMaxPg = 0; 1592 sal_uInt16 i; 1593 1594 for ( i = 0; i < pTbl->Count(); ++i ) 1595 { 1596 const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor(); 1597 if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() ) 1598 nMaxPg = rAnch.GetPageNum(); 1599 } 1600 //Wieviele Seiten haben wir derzeit? 1601 SwPageFrm *pPage = (SwPageFrm*)Lower(); 1602 while ( pPage && pPage->GetNext() && 1603 !((SwPageFrm*)pPage->GetNext())->IsFtnPage() ) 1604 { 1605 pPage = (SwPageFrm*)pPage->GetNext(); 1606 } 1607 1608 if ( nMaxPg > pPage->GetPhyPageNum() ) 1609 { 1610 //Die Seiten werden ausgehend von der letzten Seite konsequent 1611 //nach den Regeln der PageDescs weitergefuehrt. 1612 sal_Bool bOdd = pPage->GetPhyPageNum() % 2 ? sal_True : sal_False; 1613 SwPageDesc *pDesc = pPage->GetPageDesc(); 1614 SwFrm *pSibling = pPage->GetNext(); 1615 for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i ) 1616 { 1617 if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ) 1618 { 1619 //Leerseite einfuegen, die Flys werden aber erst von 1620 //der naechsten Seite aufgenommen! 1621 pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc ); 1622 pPage->Paste( this, pSibling ); 1623 pPage->PreparePage( sal_False ); 1624 bOdd = bOdd ? sal_False : sal_True; 1625 ++i; 1626 } 1627 pPage = new 1628 SwPageFrm( (bOdd ? pDesc->GetRightFmt() : 1629 pDesc->GetLeftFmt()), this, pDesc ); 1630 pPage->Paste( this, pSibling ); 1631 pPage->PreparePage( sal_False ); 1632 bOdd = bOdd ? sal_False : sal_True; 1633 pDesc = pDesc->GetFollow(); 1634 } 1635 //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein; 1636 //in diesem Fall werden sie vernichtet. 1637 if ( pDoc->GetFtnIdxs().Count() ) 1638 { 1639 pPage = (SwPageFrm*)Lower(); 1640 while ( pPage && !pPage->IsFtnPage() ) 1641 pPage = (SwPageFrm*)pPage->GetNext(); 1642 1643 if ( pPage ) 1644 { 1645 SwPageDesc *pTmpDesc = pPage->FindPageDesc(); 1646 bOdd = pPage->OnRightPage(); 1647 if ( pPage->GetFmt() != 1648 (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) ) 1649 RemoveFtns( pPage, sal_False, sal_True ); 1650 } 1651 } 1652 } 1653 } 1654 1655 /************************************************************************* 1656 |* 1657 |* SwRootFrm::AssertPageFlys() 1658 |* 1659 |* Beschreibung Stellt sicher, dass ab der uebergebenen Seite 1660 |* auf allen Seiten die Seitengebunden Objecte auf der richtigen 1661 |* Seite (Seitennummer stehen). 1662 |* 1663 |* Ersterstellung MA 02. Nov. 94 1664 |* Letzte Aenderung MA 10. Aug. 95 1665 |* 1666 |*************************************************************************/ 1667 void SwRootFrm::AssertPageFlys( SwPageFrm *pPage ) 1668 { 1669 while ( pPage ) 1670 { 1671 if ( pPage->GetSortedObjs() ) 1672 { 1673 pPage->GetSortedObjs(); 1674 for ( int i = 0; 1675 pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count(); 1676 ++i) 1677 { 1678 // --> OD 2004-06-29 #i28701# 1679 SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt(); 1680 const SwFmtAnchor &rAnch = rFmt.GetAnchor(); 1681 const sal_uInt16 nPg = rAnch.GetPageNum(); 1682 if ((rAnch.GetAnchorId() == FLY_AT_PAGE) && 1683 nPg != pPage->GetPhyPageNum() ) 1684 { 1685 //Das er auf der falschen Seite steht muss noch nichts 1686 //heissen, wenn er eigentlich auf der Vorseite 1687 //stehen will und diese eine EmptyPage ist. 1688 if( nPg && !(pPage->GetPhyPageNum()-1 == nPg && 1689 ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) ) 1690 { 1691 //Umhaengen kann er sich selbst, indem wir ihm 1692 //einfach ein Modify mit seinem AnkerAttr schicken. 1693 #ifndef DBG_UTIL 1694 rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch ); 1695 #else 1696 const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count(); 1697 rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch ); 1698 ASSERT( !pPage->GetSortedObjs() || 1699 nCnt != pPage->GetSortedObjs()->Count(), 1700 "Object couldn't be reattached!" ); 1701 #endif 1702 --i; 1703 } 1704 } 1705 } 1706 } 1707 pPage = (SwPageFrm*)pPage->GetNext(); 1708 } 1709 } 1710 1711 /************************************************************************* 1712 |* 1713 |* SwRootFrm::ChgSize() 1714 |* 1715 |* Ersterstellung MA 24. Jul. 92 1716 |* Letzte Aenderung MA 13. Aug. 93 1717 |* 1718 |*************************************************************************/ 1719 Size SwRootFrm::ChgSize( const Size& aNewSize ) 1720 { 1721 Frm().SSize() = aNewSize; 1722 _InvalidatePrt(); 1723 bFixSize = sal_False; 1724 return Frm().SSize(); 1725 } 1726 1727 /************************************************************************* 1728 |* 1729 |* SwRootFrm::MakeAll() 1730 |* 1731 |* Ersterstellung MA 17. Nov. 92 1732 |* Letzte Aenderung MA 19. Apr. 93 1733 |* 1734 |*************************************************************************/ 1735 void SwRootFrm::MakeAll() 1736 { 1737 if ( !bValidPos ) 1738 { bValidPos = sal_True; 1739 aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER; 1740 } 1741 if ( !bValidPrtArea ) 1742 { bValidPrtArea = sal_True; 1743 aPrt.Pos().X() = aPrt.Pos().Y() = 0; 1744 aPrt.SSize( aFrm.SSize() ); 1745 } 1746 if ( !bValidSize ) 1747 //SSize wird von den Seiten (Cut/Paste) eingestellt. 1748 bValidSize = sal_True; 1749 } 1750 1751 /************************************************************************* 1752 |* 1753 |* SwRootFrm::ImplInvalidateBrowseWidth() 1754 |* 1755 |* Ersterstellung MA 08. Jun. 96 1756 |* Letzte Aenderung MA 08. Jun. 96 1757 |* 1758 |*************************************************************************/ 1759 void SwRootFrm::ImplInvalidateBrowseWidth() 1760 { 1761 bBrowseWidthValid = sal_False; 1762 SwFrm *pPg = Lower(); 1763 while ( pPg ) 1764 { 1765 pPg->InvalidateSize(); 1766 pPg = pPg->GetNext(); 1767 } 1768 } 1769 1770 /************************************************************************* 1771 |* 1772 |* SwRootFrm::ImplCalcBrowseWidth() 1773 |* 1774 |* Ersterstellung MA 07. Jun. 96 1775 |* Letzte Aenderung MA 13. Jun. 96 1776 |* 1777 |*************************************************************************/ 1778 void SwRootFrm::ImplCalcBrowseWidth() 1779 { 1780 ASSERT( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(), 1781 "CalcBrowseWidth and not in BrowseView" ) 1782 1783 //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten 1784 //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt, 1785 //sondern anhand der Attribute. Es interessiert also nicht wie breit sie 1786 //sind, sondern wie breit sie sein wollen. 1787 //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen) 1788 //Zaehlen nicht. 1789 //Seitenraender und Spalten werden hier nicht beruecksichtigt. 1790 1791 SwFrm *pFrm = ContainsCntnt(); 1792 while ( pFrm && !pFrm->IsInDocBody() ) 1793 pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm(); 1794 if ( !pFrm ) 1795 return; 1796 1797 bBrowseWidthValid = sal_True; 1798 ViewShell *pSh = getRootFrm()->GetCurrShell(); 1799 nBrowseWidth = pSh 1800 ? MINLAY + 2 * pSh->GetOut()-> 1801 PixelToLogic( pSh->GetBrowseBorder() ).Width() 1802 : 5000; 1803 do 1804 { 1805 if ( pFrm->IsInTab() ) 1806 pFrm = pFrm->FindTabFrm(); 1807 1808 if ( pFrm->IsTabFrm() && 1809 !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() ) 1810 { 1811 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm ); 1812 const SwBorderAttrs &rAttrs = *aAccess.Get(); 1813 const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient(); 1814 long nWidth = rAttrs.GetSize().Width(); 1815 if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per 1816 //Zuppeln das USHRT_MAX verlorengeht! 1817 text::HoriOrientation::FULL != rHori.GetHoriOrient() ) 1818 { 1819 const SwHTMLTableLayout *pLayoutInfo = 1820 ((const SwTabFrm *)pFrm)->GetTable() 1821 ->GetHTMLTableLayout(); 1822 if ( pLayoutInfo ) 1823 nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() ); 1824 1825 switch ( rHori.GetHoriOrient() ) 1826 { 1827 case text::HoriOrientation::NONE: 1828 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)> 1829 nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ); 1830 break; 1831 case text::HoriOrientation::LEFT_AND_WIDTH: 1832 nWidth += rAttrs.CalcLeft( pFrm ); 1833 break; 1834 default: 1835 break; 1836 1837 } 1838 nBrowseWidth = Max( nBrowseWidth, nWidth ); 1839 } 1840 } 1841 else if ( pFrm->GetDrawObjs() ) 1842 { 1843 for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i ) 1844 { 1845 // --> OD 2004-06-29 #i28701# 1846 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i]; 1847 const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt(); 1848 const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm); 1849 if ((bFly && (WEIT_WECH == pAnchoredObj->GetObjRect().Width())) 1850 || rFmt.GetFrmSize().GetWidthPercent()) 1851 { 1852 continue; 1853 } 1854 1855 long nWidth = 0; 1856 switch ( rFmt.GetAnchor().GetAnchorId() ) 1857 { 1858 case FLY_AS_CHAR: 1859 nWidth = bFly ? rFmt.GetFrmSize().GetWidth() : 1860 pAnchoredObj->GetObjRect().Width(); 1861 break; 1862 case FLY_AT_PARA: 1863 { 1864 // --> FME 2004-09-13 #i33170# 1865 // Reactivated old code because 1866 // nWidth = pAnchoredObj->GetObjRect().Right() 1867 // gives wrong results for objects that are still 1868 // at position WEIT_WECH. 1869 if ( bFly ) 1870 { 1871 nWidth = rFmt.GetFrmSize().GetWidth(); 1872 const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient(); 1873 switch ( rHori.GetHoriOrient() ) 1874 { 1875 case text::HoriOrientation::NONE: 1876 nWidth += rHori.GetPos(); 1877 break; 1878 case text::HoriOrientation::INSIDE: 1879 case text::HoriOrientation::LEFT: 1880 if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ) 1881 nWidth += pFrm->Prt().Left(); 1882 break; 1883 default: 1884 break; 1885 } 1886 } 1887 else 1888 //Fuer Zeichenobjekte ist die Auswahl sehr klein, 1889 //weil sie keine Attribute haben, also durch ihre 1890 //aktuelle Groesse bestimmt werden. 1891 nWidth = pAnchoredObj->GetObjRect().Right() - 1892 pAnchoredObj->GetDrawObj()->GetAnchorPos().X(); 1893 // <-- 1894 } 1895 break; 1896 default: /* do nothing */; 1897 } 1898 nBrowseWidth = Max( nBrowseWidth, nWidth ); 1899 } 1900 } 1901 pFrm = pFrm->FindNextCnt(); 1902 } while ( pFrm ); 1903 } 1904 1905 /************************************************************************* 1906 |* 1907 |* SwRootFrm::StartAllAction() 1908 |* 1909 |* Ersterstellung MA 08. Mar. 98 1910 |* Letzte Aenderung MA 08. Mar. 98 1911 |* 1912 |*************************************************************************/ 1913 1914 void SwRootFrm::StartAllAction() 1915 { 1916 ViewShell *pSh = GetCurrShell(); 1917 if ( pSh ) 1918 do 1919 { if ( pSh->ISA( SwCrsrShell ) ) 1920 ((SwCrsrShell*)pSh)->StartAction(); 1921 else 1922 pSh->StartAction(); 1923 pSh = (ViewShell*)pSh->GetNext(); 1924 1925 } while ( pSh != GetCurrShell() ); 1926 } 1927 1928 void SwRootFrm::EndAllAction( sal_Bool bVirDev ) 1929 { 1930 ViewShell *pSh = GetCurrShell(); 1931 if ( pSh ) 1932 do 1933 { 1934 const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev(); 1935 pSh->SetEndActionByVirDev( bVirDev ); 1936 if ( pSh->ISA( SwCrsrShell ) ) 1937 { 1938 ((SwCrsrShell*)pSh)->EndAction(); 1939 ((SwCrsrShell*)pSh)->CallChgLnk(); 1940 if ( pSh->ISA( SwFEShell ) ) 1941 ((SwFEShell*)pSh)->SetChainMarker(); 1942 } 1943 else 1944 pSh->EndAction(); 1945 pSh->SetEndActionByVirDev( bOldEndActionByVirDev ); 1946 pSh = (ViewShell*)pSh->GetNext(); 1947 1948 } while ( pSh != GetCurrShell() ); 1949 } 1950 1951 void SwRootFrm::UnoRemoveAllActions() 1952 { 1953 ViewShell *pSh = GetCurrShell(); 1954 if ( pSh ) 1955 do 1956 { 1957 // --> OD 2008-05-16 #i84729# 1958 // No end action, if <ViewShell> instance is currently in its end action. 1959 // Recursives calls to <::EndAction()> are not allowed. 1960 if ( !pSh->IsInEndAction() ) 1961 { 1962 DBG_ASSERT(!pSh->GetRestoreActions(), "Restore action count is already set!"); 1963 sal_Bool bCrsr = pSh->ISA( SwCrsrShell ); 1964 sal_Bool bFE = pSh->ISA( SwFEShell ); 1965 sal_uInt16 nRestore = 0; 1966 while( pSh->ActionCount() ) 1967 { 1968 if( bCrsr ) 1969 { 1970 ((SwCrsrShell*)pSh)->EndAction(); 1971 ((SwCrsrShell*)pSh)->CallChgLnk(); 1972 if ( bFE ) 1973 ((SwFEShell*)pSh)->SetChainMarker(); 1974 } 1975 else 1976 pSh->EndAction(); 1977 nRestore++; 1978 } 1979 pSh->SetRestoreActions(nRestore); 1980 } 1981 // <-- 1982 pSh->LockView(sal_True); 1983 pSh = (ViewShell*)pSh->GetNext(); 1984 1985 } while ( pSh != GetCurrShell() ); 1986 } 1987 1988 void SwRootFrm::UnoRestoreAllActions() 1989 { 1990 ViewShell *pSh = GetCurrShell(); 1991 if ( pSh ) 1992 do 1993 { 1994 sal_uInt16 nActions = pSh->GetRestoreActions(); 1995 while( nActions-- ) 1996 { 1997 if ( pSh->ISA( SwCrsrShell ) ) 1998 ((SwCrsrShell*)pSh)->StartAction(); 1999 else 2000 pSh->StartAction(); 2001 } 2002 pSh->SetRestoreActions(0); 2003 pSh->LockView(sal_False); 2004 pSh = (ViewShell*)pSh->GetNext(); 2005 2006 } while ( pSh != GetCurrShell() ); 2007 } 2008 2009 // PAGES01: Helper functions for SwRootFrm::CheckViewLayout 2010 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset ); 2011 2012 void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset ) 2013 { 2014 SwSortedObjs* pSortedObj = 0; 2015 const bool bPage = pFrm->IsPageFrm(); 2016 2017 if ( bPage ) 2018 pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs(); 2019 else 2020 pSortedObj = pFrm->GetDrawObjs(); 2021 2022 for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i) 2023 { 2024 SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i]; 2025 2026 const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt(); 2027 const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor(); 2028 2029 // all except from the as character anchored objects are moved 2030 // when processing the page frame: 2031 const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR); 2032 if ( !bPage && !bAsChar ) 2033 continue; 2034 2035 SwObjPositioningInProgress aPosInProgress( *pAnchoredObj ); 2036 2037 if ( pAnchoredObj->ISA(SwFlyFrm) ) 2038 { 2039 SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) ); 2040 lcl_MoveAllLowers( pFlyFrm, rOffset ); 2041 pFlyFrm->NotifyDrawObj(); 2042 // --> let the active embedded object be moved 2043 if ( pFlyFrm->Lower() ) 2044 { 2045 if ( pFlyFrm->Lower()->IsNoTxtFrm() ) 2046 { 2047 SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower()); 2048 SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm(); 2049 ViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0; 2050 if ( pSh ) 2051 { 2052 SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode(); 2053 if ( pNode ) 2054 { 2055 svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject(); 2056 if ( xObj.is() ) 2057 { 2058 ViewShell* pTmp = pSh; 2059 do 2060 { 2061 SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp ); 2062 if ( pFEShell ) 2063 pFEShell->MoveObjectIfActive( xObj, rOffset ); 2064 pTmp = static_cast<ViewShell*>( pTmp->GetNext() ); 2065 } while( pTmp != pSh ); 2066 } 2067 } 2068 } 2069 } 2070 } 2071 // <-- 2072 } 2073 else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) ) 2074 { 2075 SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) ); 2076 2077 // don't touch objects that are not yet positioned: 2078 const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned(); 2079 if ( bNotYetPositioned ) 2080 continue; 2081 2082 const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos(); 2083 const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) ); 2084 pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos ); 2085 pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() ); 2086 } 2087 // --> OD 2009-08-20 #i92511# 2088 // cache for object rectangle inclusive spaces has to be invalidated. 2089 pAnchoredObj->InvalidateObjRectWithSpaces(); 2090 // <-- 2091 } 2092 } 2093 2094 void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset ) 2095 { 2096 const SwRect aFrm( pFrm->Frm() ); 2097 2098 // first move the current frame 2099 pFrm->Frm().Pos() += rOffset; 2100 2101 // Don't forget accessibility: 2102 if( pFrm->IsAccessibleFrm() ) 2103 { 2104 SwRootFrm *pRootFrm = pFrm->getRootFrm(); 2105 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 2106 pRootFrm->GetCurrShell() ) 2107 { 2108 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm ); 2109 } 2110 } 2111 2112 // the move any objects 2113 lcl_MoveAllLowerObjs( pFrm, rOffset ); 2114 2115 // finally, for layout frames we have to call this function recursively: 2116 if ( pFrm->ISA(SwLayoutFrm) ) 2117 { 2118 SwFrm* pLowerFrm = pFrm->GetLower(); 2119 while ( pLowerFrm ) 2120 { 2121 lcl_MoveAllLowers( pLowerFrm, rOffset ); 2122 pLowerFrm = pLowerFrm->GetNext(); 2123 } 2124 } 2125 } 2126 2127 // PAGES01: Calculate how the pages have to be positioned 2128 void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea ) 2129 { 2130 // --> OD 2008-07-07 #i91432# 2131 // No calculation of page positions, if only an empty page is present. 2132 // This situation occurs when <SwRootFrm> instance is in construction 2133 // and the document contains only left pages. 2134 if ( Lower()->GetNext() == 0 && 2135 static_cast<SwPageFrm*>(Lower())->IsEmptyPage() ) 2136 { 2137 return; 2138 } 2139 // <-- 2140 2141 if ( !pVisArea ) 2142 { 2143 // no early return for bNewPage 2144 if ( mnViewWidth < 0 ) 2145 mnViewWidth = 0; 2146 } 2147 else 2148 { 2149 ASSERT( pViewOpt, "CheckViewLayout required ViewOptions" ) 2150 2151 const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns(); 2152 const bool bBookMode = pViewOpt->IsViewLayoutBookMode(); 2153 2154 if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged ) 2155 return; 2156 2157 mnColumns = nColumns; 2158 mbBookMode = bBookMode; 2159 mnViewWidth = pVisArea->Width(); 2160 mbSidebarChanged = false; 2161 } 2162 2163 if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) ) 2164 { 2165 mnColumns = 1; 2166 mbBookMode = false; 2167 } 2168 2169 Calc(); 2170 2171 const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled(); 2172 SetCallbackActionEnabled( sal_False ); 2173 2174 maPageRects.clear(); 2175 2176 const long nBorder = Frm().Pos().X(); 2177 const long nVisWidth = mnViewWidth - 2 * nBorder; 2178 const long nGapBetweenPages = GAPBETWEENPAGES; 2179 2180 // check how many pages fit into the first page layout row: 2181 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower()); 2182 2183 // will contain the number of pages per row. 0 means that 2184 // the page does not fit. 2185 long nWidthRemain = nVisWidth; 2186 2187 // after one row has been processed, these variables contain 2188 // the width of the row and the maxium of the page heights 2189 long nCurrentRowHeight = 0; 2190 long nCurrentRowWidth = 0; 2191 2192 // these variables are used to finally set the size of the 2193 // root frame 2194 long nSumRowHeight = 0; 2195 SwTwips nMinPageLeft = TWIPS_MAX; 2196 SwTwips nMaxPageRight = 0; 2197 SwPageFrm* pStartOfRow = pPageFrm; 2198 sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page 2199 bool bFirstRow = true; 2200 2201 bool bPageChanged = false; 2202 const bool bRTL = !IsLeftToRightViewLayout(); 2203 const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() ); 2204 2205 while ( pPageFrm ) 2206 { 2207 // we consider the current page to be "start of row" if 2208 // 1. it is the first page in the current row or 2209 // 2. it is the second page in the row and the first page is an empty page in non-book view: 2210 const bool bStartOfRow = pPageFrm == pStartOfRow || 2211 ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode ); 2212 2213 const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode; 2214 2215 // no half doc border space for first page in each row and 2216 long nPageWidth = 0; 2217 long nPageHeight = 0; 2218 2219 if ( mbBookMode ) 2220 { 2221 const SwFrm& rFormatPage = pPageFrm->GetFormatPage(); 2222 2223 nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages); 2224 nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages; 2225 } 2226 else 2227 { 2228 SwRect aPageFrm; 2229 if ( !pPageFrm->IsEmptyPage() ) 2230 { 2231 nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages); 2232 nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages; 2233 } 2234 } 2235 2236 if ( !bEmptyPage ) 2237 ++nNumberOfPagesInRow; 2238 2239 // finish current row if 2240 // 1. in dynamic mode the current page does not fit anymore or 2241 // 2. the current page exceeds the maximum number of columns 2242 bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) || 2243 (0 != mnColumns && mnColumns < nNumberOfPagesInRow); 2244 2245 // make sure that at least one page goes to the current row: 2246 if ( !bRowFinished || bStartOfRow ) 2247 { 2248 // current page is allowed to be in current row 2249 nWidthRemain = nWidthRemain - nPageWidth; 2250 2251 nCurrentRowWidth = nCurrentRowWidth + nPageWidth; 2252 nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight ); 2253 2254 pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext()); 2255 2256 if ( !pPageFrm ) 2257 bRowFinished = true; 2258 } 2259 2260 if ( bRowFinished ) 2261 { 2262 // pPageFrm now points to the first page in the new row or null 2263 // pStartOfRow points to the first page in the current row 2264 2265 // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering: 2266 if ( !pPageFrm && nWidthRemain > 0 ) 2267 { 2268 // find last page in current row: 2269 const SwPageFrm* pLastPageInCurrentRow = pStartOfRow; 2270 while( pLastPageInCurrentRow->GetNext() ) 2271 pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext()); 2272 2273 if ( pLastPageInCurrentRow->IsEmptyPage() ) 2274 pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev()); 2275 2276 // check how many times the last page would still fit into the remaining space: 2277 sal_uInt16 nNumberOfVirtualPages = 0; 2278 const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX; 2279 SwTwips nRemain = nWidthRemain; 2280 SwTwips nVirtualPagesWidth = 0; 2281 SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth; 2282 2283 while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages ) 2284 { 2285 SwTwips nLastPageWidthWithGap = nLastPageWidth; 2286 if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) ) 2287 nLastPageWidthWithGap += nGapBetweenPages; 2288 2289 if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain ) 2290 { 2291 ++nNumberOfVirtualPages; 2292 nVirtualPagesWidth += nLastPageWidthWithGap; 2293 } 2294 nRemain = nRemain - nLastPageWidthWithGap; 2295 } 2296 2297 nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth; 2298 } 2299 2300 // first page in book mode is always special: 2301 if ( bFirstRow && mbBookMode ) 2302 { 2303 // --> OD 2008-04-08 #i88036# 2304 // nCurrentRowWidth += pStartOfRow->Frm().Width() + nSidebarWidth; 2305 nCurrentRowWidth += 2306 pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth; 2307 // <-- 2308 } 2309 2310 // center page if possible 2311 const long nSizeDiff = nVisWidth > nCurrentRowWidth ? 2312 ( nVisWidth - nCurrentRowWidth ) / 2 : 2313 0; 2314 2315 // adjust positions of pages in current row 2316 long nX = nSizeDiff; 2317 2318 const long nRowStart = nBorder + nSizeDiff; 2319 const long nRowEnd = nRowStart + nCurrentRowWidth; 2320 2321 if ( bFirstRow && mbBookMode ) 2322 { 2323 // --> OD 2008-04-08 #i88036# 2324 // nX += pStartOfRow->Frm().Width() + nSidebarWidth; 2325 nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth; 2326 // <-- 2327 } 2328 2329 SwPageFrm* pEndOfRow = pPageFrm; 2330 SwPageFrm* pPageToAdjust = pStartOfRow; 2331 2332 do 2333 { 2334 const SwPageFrm* pFormatPage = pPageToAdjust; 2335 if ( mbBookMode ) 2336 pFormatPage = &pPageToAdjust->GetFormatPage(); 2337 2338 const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth); 2339 const Point aOldPagePos = pPageToAdjust->Frm().Pos(); 2340 const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT; 2341 const SwTwips nLeftPageAddOffset = bLeftSidebar ? 2342 nSidebarWidth : 2343 0; 2344 2345 Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight ); 2346 Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight ); 2347 2348 // RTL view layout: Calculate mirrored page position 2349 if ( bRTL ) 2350 { 2351 const long nXOffsetInRow = aNewPagePos.X() - nRowStart; 2352 aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth; 2353 aNewPagePosWithLeftOffset = aNewPagePos; 2354 aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset; 2355 } 2356 2357 if ( aNewPagePosWithLeftOffset != aOldPagePos ) 2358 { 2359 lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos ); 2360 pPageToAdjust->SetCompletePaint(); 2361 bPageChanged = true; 2362 } 2363 2364 // calculate area covered by the current page and store to 2365 // maPageRects. This is used e.g., for cursor setting 2366 const bool bFirstColumn = pPageToAdjust == pStartOfRow; 2367 const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow; 2368 const bool bLastRow = !pEndOfRow; 2369 2370 nMinPageLeft = Min( nMinPageLeft, aNewPagePos.X() ); 2371 nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth); 2372 2373 // border of nGapBetweenPages around the current page: 2374 SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages, 2375 aNewPagePos.Y(), 2376 pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth, 2377 nCurrentRowHeight ); 2378 2379 static const long nOuterClickDiff = 1000000; 2380 2381 // adjust borders for these special cases: 2382 if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) ) 2383 aPageRectWithBorders.SubLeft( nOuterClickDiff ); 2384 if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) ) 2385 aPageRectWithBorders.AddRight( nOuterClickDiff ); 2386 if ( bFirstRow ) 2387 aPageRectWithBorders.SubTop( nOuterClickDiff ); 2388 if ( bLastRow ) 2389 aPageRectWithBorders.AddBottom( nOuterClickDiff ); 2390 2391 maPageRects.push_back( aPageRectWithBorders ); 2392 2393 nX = nX + nCurrentPageWidth; 2394 pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext()); 2395 2396 // distance to next page 2397 if ( pPageToAdjust && pPageToAdjust != pEndOfRow ) 2398 { 2399 // in book view, we add the x gap before left (even) pages: 2400 if ( mbBookMode ) 2401 { 2402 if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) ) 2403 nX = nX + nGapBetweenPages; 2404 } 2405 else 2406 { 2407 // in non-book view, dont add x gap before 2408 // 1. the last empty page in a row 2409 // 2. after an empty page 2410 const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) || 2411 ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() ); 2412 2413 if ( !bDontAddGap ) 2414 nX = nX + nGapBetweenPages; 2415 } 2416 } 2417 } 2418 while ( pPageToAdjust != pEndOfRow ); 2419 2420 // adjust values for root frame size 2421 nSumRowHeight = nSumRowHeight + nCurrentRowHeight; 2422 2423 // start new row: 2424 nCurrentRowHeight = 0; 2425 nCurrentRowWidth = 0; 2426 pStartOfRow = pEndOfRow; 2427 nWidthRemain = nVisWidth; 2428 nNumberOfPagesInRow = 0; 2429 bFirstRow = false; 2430 } // end row finished 2431 } // end while 2432 2433 // set size of root frame: 2434 const Size aOldSize( Frm().SSize() ); 2435 const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages ); 2436 2437 if ( bPageChanged || aNewSize != aOldSize ) 2438 { 2439 ChgSize( aNewSize ); 2440 ::AdjustSizeChgNotify( this ); 2441 Calc(); 2442 2443 ViewShell* pSh = GetCurrShell(); 2444 2445 if ( pSh && pSh->GetDoc()->GetDocShell() ) 2446 { 2447 pSh->SetFirstVisPageInvalid(); 2448 if (bOldCallbackActionEnabled) 2449 { 2450 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) ); 2451 pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED)); 2452 } 2453 } 2454 } 2455 2456 maPagesArea.Pos( Frm().Pos() ); 2457 maPagesArea.SSize( aNewSize ); 2458 if ( TWIPS_MAX != nMinPageLeft ) 2459 maPagesArea._Left( nMinPageLeft ); 2460 2461 SetCallbackActionEnabled( bOldCallbackActionEnabled ); 2462 } 2463 2464 bool SwRootFrm::IsLeftToRightViewLayout() const 2465 { 2466 // Layout direction determined by layout direction of the first page. 2467 // --> OD 2008-04-08 #i88036# 2468 // Only ask a non-empty page frame for its layout direction 2469 // const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower()); 2470 // return !pPage->IsRightToLeft() && !pPage->IsVertical(); 2471 const SwPageFrm& rPage = 2472 dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage(); 2473 return !rPage.IsRightToLeft() && !rPage.IsVertical(); 2474 // <-- 2475 } 2476 2477 /*const SwRect SwRootFrm::GetExtendedPageArea( sal_uInt16 nPageNumber ) const 2478 { 2479 SwRect aRet; 2480 ASSERT( nPageNumber < maPageRects.size(), "No extended page area available" ) 2481 if ( nPageNumber < maPageRects.size() ) 2482 aRet = maPageRects[ nPageNumber ]; 2483 return aRet; 2484 }*/ 2485 2486 2487 const SwPageFrm& SwPageFrm::GetFormatPage() const 2488 { 2489 const SwPageFrm* pRet = this; 2490 if ( IsEmptyPage() ) 2491 { 2492 pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() ); 2493 // --> OD 2008-04-08 #i88035# 2494 // Typically a right empty page frame has a next non-empty page frame and 2495 // a left empty page frame has a previous non-empty page frame. 2496 // But under certain cirsumstances this assumption is not true - 2497 // e.g. during insertion of a left page at the end of the document right 2498 // after a left page in an intermediate state a right empty page does not 2499 // have a next page frame. 2500 if ( pRet == 0 ) 2501 { 2502 if ( OnRightPage() ) 2503 { 2504 pRet = static_cast<const SwPageFrm*>( GetPrev() ); 2505 } 2506 else 2507 { 2508 pRet = static_cast<const SwPageFrm*>( GetNext() ); 2509 } 2510 } 2511 ASSERT( pRet, 2512 "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." ); 2513 // <-- 2514 } 2515 return *pRet; 2516 } 2517 2518