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