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