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