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 |*************************************************************************/
SwBodyFrm(SwFrmFmt * pFmt,SwFrm * pSib)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 |*************************************************************************/
Format(const SwBorderAttrs *)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 |*************************************************************************/
SwPageFrm(SwFrmFmt * pFmt,SwFrm * pSib,SwPageDesc * pPgDsc)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
~SwPageFrm()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
CheckGrid(sal_Bool bInvalidate)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
CheckDirection(sal_Bool bVert)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 |*************************************************************************/
lcl_FormatLay(SwLayoutFrm * pLay)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
lcl_MakeObjs(const SwSpzFrmFmts & rTbl,SwPageFrm * pPage)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
PreparePage(sal_Bool bFtn)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 |*************************************************************************/
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)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
_UpdateAttr(const SfxPoolItem * pOld,const SfxPoolItem * pNew,sal_uInt8 & rInvFlags,SwAttrSetChg * pOldSet,SwAttrSetChg * pNewSet)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
GetInfo(SfxPoolItem & rInfo) const742 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 |*************************************************************************/
SetPageDesc(SwPageDesc * pNew,SwFrmFmt * pFmt)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 |*************************************************************************/
FindPageDesc()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.
AdjustSizeChgNotify(SwRootFrm * pRoot)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
SetLastPage(SwPageFrm * pPage)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 |*************************************************************************/
Cut()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 |*************************************************************************/
Paste(SwFrm * pParent,SwFrm * pSibling)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 |*************************************************************************/
lcl_PrepFlyInCntRegister(SwCntntFrm * pFrm)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
PrepareRegisterChg()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 |*************************************************************************/
CheckPageDescs(SwPageFrm * pStart,sal_Bool bNotifyFields)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 |*************************************************************************/
InsertPage(SwPageFrm * pPrevPage,sal_Bool bFtn)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
SidebarPosition() const1406 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
GrowFrm(SwTwips nDist,sal_Bool bTst,sal_Bool)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 |*************************************************************************/
ShrinkFrm(SwTwips nDist,sal_Bool bTst,sal_Bool)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 |*************************************************************************/
RemoveSuperfluous()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 |*************************************************************************/
AssertFlyPages()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 |*************************************************************************/
AssertPageFlys(SwPageFrm * pPage)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 |*************************************************************************/
ChgSize(const Size & aNewSize)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 |*************************************************************************/
MakeAll()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 |*************************************************************************/
ImplInvalidateBrowseWidth()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 |*************************************************************************/
ImplCalcBrowseWidth()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
StartAllAction()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
EndAllAction(sal_Bool bVirDev)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
UnoRemoveAllActions()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
UnoRestoreAllActions()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
lcl_MoveAllLowerObjs(SwFrm * pFrm,const Point & rOffset)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
lcl_MoveAllLowers(SwFrm * pFrm,const Point & rOffset)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
CheckViewLayout(const SwViewOption * pViewOpt,const SwRect * pVisArea)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
IsLeftToRightViewLayout() const2465 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
GetFormatPage() const2488 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