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 : #include <com/sun/star/embed/EmbedStates.hpp>
21 : #include <ndole.hxx>
22 : #include <docary.hxx>
23 : #include <svl/itemiter.hxx>
24 : #include <fmtfsize.hxx>
25 : #include <fmthdft.hxx>
26 : #include <fmtclds.hxx>
27 : #include <fmtanchr.hxx>
28 : #include <fmtpdsc.hxx>
29 : #include <fmtfordr.hxx>
30 : #include <fmtfld.hxx>
31 : #include <fmtornt.hxx>
32 : #include <fmtsrnd.hxx>
33 : #include <ftninfo.hxx>
34 : #include <tgrditem.hxx>
35 : #include <viewopt.hxx>
36 : #include <docsh.hxx>
37 : #include <wrtsh.hxx>
38 : #include <view.hxx>
39 : #include <edtwin.hxx>
40 :
41 : #include "viewimp.hxx"
42 : #include "pagefrm.hxx"
43 : #include "rootfrm.hxx"
44 : #include "cntfrm.hxx"
45 : #include "flyfrm.hxx"
46 : #include "doc.hxx"
47 : #include "fesh.hxx"
48 : #include "dview.hxx"
49 : #include "dflyobj.hxx"
50 : #include "dcontact.hxx"
51 : #include "frmtool.hxx"
52 : #include "fldbas.hxx"
53 : #include "hints.hxx"
54 : #include "swtable.hxx"
55 :
56 : #include "ftnidx.hxx"
57 : #include "bodyfrm.hxx"
58 : #include "ftnfrm.hxx"
59 : #include "tabfrm.hxx"
60 : #include "txtfrm.hxx"
61 : #include "layact.hxx"
62 : #include "flyfrms.hxx"
63 : #include "htmltbl.hxx"
64 : #include "pagedesc.hxx"
65 : #include "poolfmt.hxx"
66 : #include <editeng/frmdiritem.hxx>
67 : #include <swfntcch.hxx>
68 : #include <sortedobjs.hxx>
69 : #include <switerator.hxx>
70 : #include <vcl/svapp.hxx>
71 :
72 : using namespace ::com::sun::star;
73 :
74 0 : SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
75 0 : SwLayoutFrm( pFmt, pSib )
76 : {
77 0 : mnType = FRMC_BODY;
78 0 : }
79 :
80 0 : void SwBodyFrm::Format( const SwBorderAttrs * )
81 : {
82 : // Formatting of the body is too simple, thus, it gets an own format method.
83 : // Borders etc. are not taken into account here.
84 : // With is taken from the PrtArea of the Upper, height is the height of the
85 : // PrtArea of the Upper minus any neighbors (for robustness).
86 : // The PrtArea has always the size of the frame.
87 :
88 0 : if ( !mbValidSize )
89 : {
90 0 : SwTwips nHeight = GetUpper()->Prt().Height();
91 0 : SwTwips nWidth = GetUpper()->Prt().Width();
92 0 : const SwFrm *pFrm = GetUpper()->Lower();
93 0 : do
94 : {
95 0 : if ( pFrm != this )
96 : {
97 0 : if( pFrm->IsVertical() )
98 0 : nWidth -= pFrm->Frm().Width();
99 : else
100 0 : nHeight -= pFrm->Frm().Height();
101 : }
102 0 : pFrm = pFrm->GetNext();
103 : } while ( pFrm );
104 0 : if ( nHeight < 0 )
105 0 : nHeight = 0;
106 0 : Frm().Height( nHeight );
107 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
108 0 : if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() )
109 0 : Frm().Pos().setX(Frm().Pos().getX() + Frm().Width() - nWidth);
110 0 : Frm().Width( nWidth );
111 : }
112 :
113 0 : bool bNoGrid = true;
114 0 : if( GetUpper()->IsPageFrm() && ((SwPageFrm*)GetUpper())->HasGrid() )
115 : {
116 : SwTextGridItem const*const pGrid(
117 0 : GetGridItem(static_cast<SwPageFrm*>(GetUpper())));
118 0 : if( pGrid )
119 : {
120 0 : bNoGrid = false;
121 0 : long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
122 0 : SWRECTFN( this )
123 0 : long nSize = (Frm().*fnRect->fnGetWidth)();
124 0 : long nBorder = 0;
125 0 : if( GRID_LINES_CHARS == pGrid->GetGridType() )
126 : {
127 : //for textgrid refactor
128 0 : SwDoc *pDoc = GetFmt()->GetDoc();
129 0 : nBorder = nSize % (GetGridWidth(*pGrid, *pDoc));
130 0 : nSize -= nBorder;
131 0 : nBorder /= 2;
132 : }
133 0 : (Prt().*fnRect->fnSetPosX)( nBorder );
134 0 : (Prt().*fnRect->fnSetWidth)( nSize );
135 :
136 : // Height of body frame:
137 0 : nBorder = (Frm().*fnRect->fnGetHeight)();
138 :
139 : // Number of possible lines in area of body frame:
140 0 : long nNumberOfLines = nBorder / nSum;
141 0 : if( nNumberOfLines > pGrid->GetLines() )
142 0 : nNumberOfLines = pGrid->GetLines();
143 :
144 : // Space required for nNumberOfLines lines:
145 0 : nSize = nNumberOfLines * nSum;
146 0 : nBorder -= nSize;
147 0 : nBorder /= 2;
148 :
149 : // #i21774# Footnotes and centering the grid does not work together:
150 0 : const bool bAdjust = ((SwPageFrm*)GetUpper())->GetFmt()->GetDoc()->
151 0 : GetFtnIdxs().empty();
152 :
153 0 : (Prt().*fnRect->fnSetPosY)( bAdjust ? nBorder : 0 );
154 0 : (Prt().*fnRect->fnSetHeight)( nSize );
155 : }
156 : }
157 0 : if( bNoGrid )
158 : {
159 0 : Prt().Pos().setX(0);
160 0 : Prt().Pos().setY(0);
161 0 : Prt().Height( Frm().Height() );
162 0 : Prt().Width( Frm().Width() );
163 : }
164 0 : mbValidSize = mbValidPrtArea = sal_True;
165 0 : }
166 :
167 0 : SwPageFrm::SwPageFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwPageDesc *pPgDsc ) :
168 : SwFtnBossFrm( pFmt, pSib ),
169 : pSortedObjs( 0 ),
170 : pDesc( pPgDsc ),
171 0 : nPhyPageNum( 0 )
172 : {
173 0 : SetDerivedVert( sal_False );
174 0 : SetDerivedR2L( sal_False );
175 0 : if( pDesc )
176 : {
177 0 : bHasGrid = sal_True;
178 0 : SwTextGridItem const*const pGrid(GetGridItem(this));
179 0 : if( !pGrid )
180 0 : bHasGrid = sal_False;
181 : }
182 : else
183 0 : bHasGrid = sal_False;
184 0 : SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
185 0 : pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
186 0 : mnType = FRMC_PAGE;
187 0 : bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True;
188 0 : bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False;
189 :
190 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
191 0 : const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
192 0 : if ( bBrowseMode )
193 : {
194 0 : Frm().Height( 0 );
195 0 : long nWidth = pSh->VisArea().Width();
196 0 : if ( !nWidth )
197 0 : nWidth = 5000L; //aendert sich sowieso
198 0 : Frm().Width ( nWidth );
199 : }
200 : else
201 0 : Frm().SSize( pFmt->GetFrmSize().GetSize() );
202 :
203 : // create and insert body area if it is not a blank page
204 0 : SwDoc *pDoc = pFmt->GetDoc();
205 0 : if ( sal_False == (bEmptyPage = (pFmt == pDoc->GetEmptyPageFmt())) )
206 : {
207 0 : bEmptyPage = sal_False;
208 0 : Calc(); // so that the PrtArea is correct
209 0 : SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this );
210 0 : pBodyFrm->ChgSize( Prt().SSize() );
211 0 : pBodyFrm->Paste( this );
212 0 : pBodyFrm->Calc(); // so that the columns can be inserted correctly
213 0 : pBodyFrm->InvalidatePos();
214 :
215 0 : if ( bBrowseMode )
216 0 : _InvalidateSize();
217 :
218 : // insert header/footer,, but only if active.
219 0 : if ( pFmt->GetHeader().IsActive() )
220 0 : PrepareHeader();
221 0 : if ( pFmt->GetFooter().IsActive() )
222 0 : PrepareFooter();
223 :
224 0 : const SwFmtCol &rCol = pFmt->GetCol();
225 0 : if ( rCol.GetNumCols() > 1 )
226 : {
227 0 : const SwFmtCol aOld; //ChgColumns() needs an old value
228 0 : pBodyFrm->ChgColumns( aOld, rCol );
229 : }
230 : }
231 0 : }
232 :
233 0 : SwPageFrm::~SwPageFrm()
234 : {
235 : // Cleanup the header-footer controls in the SwEditWin
236 0 : SwViewShell* pSh = getRootFrm()->GetCurrShell();
237 0 : SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( pSh );
238 0 : if ( pWrtSh )
239 : {
240 0 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
241 0 : rEditWin.GetFrameControlsManager( ).RemoveControls( this );
242 : }
243 :
244 : // empty FlyContainer, deletion of the Flys is done by the anchor (in base class SwFrm)
245 0 : if ( pSortedObjs )
246 : {
247 : // Objects can be anchored at pages that are before their anchors (why ever...).
248 : // In such cases, we would access already freed memory.
249 0 : for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
250 : {
251 0 : SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
252 0 : pAnchoredObj->SetPageFrm( 0L );
253 : }
254 0 : delete pSortedObjs;
255 0 : pSortedObjs = 0; // reset to zero to prevent problems when detaching the Flys
256 : }
257 :
258 0 : if ( !IsEmptyPage() ) //#59184# unnessesary for empty pages
259 : {
260 : // prevent access to destroyed pages
261 0 : SwDoc *pDoc = GetFmt() ? GetFmt()->GetDoc() : NULL;
262 0 : if( pDoc && !pDoc->IsInDtor() )
263 : {
264 0 : if ( pSh )
265 : {
266 0 : SwViewImp *pImp = pSh->Imp();
267 0 : pImp->SetFirstVisPageInvalid();
268 0 : if ( pImp->IsAction() )
269 0 : pImp->GetLayAction().SetAgain();
270 : // OD 12.02.2003 #i9719#, #105645# - retouche area of page
271 : // including border and shadow area.
272 0 : const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
273 0 : SwRect aRetoucheRect;
274 0 : SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
275 0 : pSh->AddPaintRect( aRetoucheRect );
276 : }
277 : }
278 : }
279 0 : }
280 :
281 0 : void SwPageFrm::CheckGrid( sal_Bool bInvalidate )
282 : {
283 0 : sal_Bool bOld = bHasGrid;
284 0 : bHasGrid = sal_True;
285 0 : SwTextGridItem const*const pGrid(GetGridItem(this));
286 0 : bHasGrid = 0 != pGrid;
287 0 : if( bInvalidate || bOld != bHasGrid )
288 : {
289 0 : SwLayoutFrm* pBody = FindBodyCont();
290 0 : if( pBody )
291 : {
292 0 : pBody->InvalidatePrt();
293 0 : SwCntntFrm* pFrm = pBody->ContainsCntnt();
294 0 : while( pBody->IsAnLower( pFrm ) )
295 : {
296 0 : ((SwTxtFrm*)pFrm)->Prepare( PREP_CLEAR );
297 0 : pFrm = pFrm->GetNextCntntFrm();
298 : }
299 : }
300 0 : SetCompletePaint();
301 : }
302 0 : }
303 :
304 0 : void SwPageFrm::CheckDirection( bool bVert )
305 : {
306 : sal_uInt16 nDir =
307 0 : ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
308 0 : if( bVert )
309 : {
310 0 : if( FRMDIR_HORI_LEFT_TOP == nDir || FRMDIR_HORI_RIGHT_TOP == nDir )
311 : {
312 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
313 0 : mbVertLR = 0;
314 0 : mbVertical = 0;
315 : }
316 : else
317 : {
318 0 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
319 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
320 : {
321 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
322 0 : mbVertLR = 0;
323 0 : mbVertical = 0;
324 : }
325 : else
326 : {
327 0 : mbVertical = 1;
328 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
329 0 : if(FRMDIR_VERT_TOP_RIGHT == nDir)
330 0 : mbVertLR = 0;
331 0 : else if(FRMDIR_VERT_TOP_LEFT==nDir)
332 0 : mbVertLR = 1;
333 : }
334 : }
335 :
336 0 : mbReverse = 0;
337 0 : mbInvalidVert = 0;
338 : }
339 : else
340 : {
341 0 : if( FRMDIR_HORI_RIGHT_TOP == nDir )
342 0 : mbRightToLeft = 1;
343 : else
344 0 : mbRightToLeft = 0;
345 0 : mbInvalidR2L = 0;
346 : }
347 0 : }
348 :
349 : /// create specific Flys for this page and format generic content
350 0 : static void lcl_FormatLay( SwLayoutFrm *pLay )
351 : {
352 : // format all LayoutFrms - no tables, Flys etc.
353 :
354 0 : SwFrm *pTmp = pLay->Lower();
355 : // first the low-level ones
356 0 : while ( pTmp )
357 : {
358 0 : if ( pTmp->GetType() & 0x00FF )
359 0 : ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
360 0 : pTmp = pTmp->GetNext();
361 : }
362 0 : pLay->Calc();
363 0 : }
364 :
365 : /// Create Flys or register draw objects
366 0 : static void lcl_MakeObjs( const SwFrmFmts &rTbl, SwPageFrm *pPage )
367 : {
368 : // formats are in the special table of the document
369 :
370 0 : for ( sal_uInt16 i = 0; i < rTbl.size(); ++i )
371 : {
372 : SdrObject *pSdrObj;
373 0 : SwFrmFmt *pFmt = rTbl[i];
374 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
375 0 : if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
376 : {
377 0 : if( rAnch.GetCntntAnchor() )
378 : {
379 0 : if (FLY_AT_PAGE == rAnch.GetAnchorId())
380 : {
381 0 : SwFmtAnchor aAnch( rAnch );
382 0 : aAnch.SetAnchor( 0 );
383 0 : pFmt->SetFmtAttr( aAnch );
384 : }
385 : else
386 0 : continue;
387 : }
388 :
389 : // is it a border or a SdrObject?
390 0 : bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
391 0 : pSdrObj = 0;
392 0 : if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
393 : {
394 : OSL_FAIL( "DrawObject not found." );
395 0 : pFmt->GetDoc()->DelFrmFmt( pFmt );
396 0 : --i;
397 0 : continue;
398 : }
399 : // The object might be anchored to another page, e.g. when inserting
400 : // a new page due to a page descriptor change. In such cases, the
401 : // object needs to be moved.
402 : // In some cases the object is already anchored to the correct page.
403 : // This will be handled here and does not need to be coded extra.
404 0 : SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
405 0 : if ( bSdrObj )
406 : {
407 : // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
408 : SwDrawContact *pContact =
409 0 : static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
410 0 : if ( pSdrObj->ISA(SwDrawVirtObj) )
411 : {
412 0 : SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
413 0 : if ( pContact )
414 : {
415 0 : pDrawVirtObj->RemoveFromWriterLayout();
416 0 : pDrawVirtObj->RemoveFromDrawingPage();
417 0 : pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
418 : }
419 : }
420 : else
421 : {
422 0 : if ( pContact->GetAnchorFrm() )
423 0 : pContact->DisconnectFromLayout( false );
424 0 : pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
425 : }
426 : }
427 : else
428 : {
429 0 : SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
430 0 : SwFlyFrm *pFly = aIter.First();
431 0 : if ( pFly)
432 : {
433 0 : if( pFly->GetAnchorFrm() )
434 0 : pFly->AnchorFrm()->RemoveFly( pFly );
435 : }
436 : else
437 0 : pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pPg, pPg );
438 0 : pPg->AppendFly( pFly );
439 0 : ::RegistFlys( pPg, pFly );
440 : }
441 : }
442 : }
443 0 : }
444 :
445 0 : void SwPageFrm::PreparePage( sal_Bool bFtn )
446 : {
447 0 : SetFtnPage( bFtn );
448 :
449 : // #i82258#
450 : // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
451 : // the side effect, that the content of page header and footer are formatted.
452 : // For this formatting it is needed that the anchored objects are registered
453 : // at the <SwPageFrm> instance.
454 : // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
455 0 : ::RegistFlys( this, this );
456 :
457 0 : if ( Lower() )
458 : {
459 0 : ::lcl_FormatLay( this );
460 : }
461 :
462 : // Flys and draw objects that are still attached to the document.
463 : // Footnote pages do not have page-bound Flys!
464 : // There might be Flys or draw objects that want to be placed on
465 : // empty pages, however, the empty pages ignore that and the following
466 : // pages take care of them.
467 0 : if ( !bFtn && !IsEmptyPage() )
468 : {
469 0 : SwDoc *pDoc = GetFmt()->GetDoc();
470 :
471 0 : if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
472 0 : lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
473 0 : lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
474 :
475 : // format footer/ header
476 0 : SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
477 0 : while ( pLow )
478 : {
479 0 : if ( pLow->GetType() & (FRMTYPE_HEADER|FRMTYPE_FOOTER) )
480 : {
481 0 : SwCntntFrm *pCntnt = pLow->ContainsCntnt();
482 0 : while ( pCntnt && pLow->IsAnLower( pCntnt ) )
483 : {
484 0 : pCntnt->OptCalc(); // not the predecessors
485 0 : pCntnt = pCntnt->GetNextCntntFrm();
486 : }
487 : }
488 0 : pLow = (SwLayoutFrm*)pLow->GetNext();
489 : }
490 : }
491 0 : }
492 :
493 0 : void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
494 : {
495 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
496 0 : if ( pSh )
497 0 : pSh->SetFirstVisPageInvalid();
498 0 : sal_uInt8 nInvFlags = 0;
499 :
500 0 : if( pNew && RES_ATTRSET_CHG == pNew->Which() )
501 : {
502 0 : SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
503 0 : SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
504 0 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
505 0 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
506 : while( true )
507 : {
508 : _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
509 : (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
510 0 : &aOldSet, &aNewSet );
511 0 : if( aNIter.IsAtEnd() )
512 0 : break;
513 0 : aNIter.NextItem();
514 0 : aOIter.NextItem();
515 : }
516 0 : if ( aOldSet.Count() || aNewSet.Count() )
517 0 : SwLayoutFrm::Modify( &aOldSet, &aNewSet );
518 : }
519 : else
520 0 : _UpdateAttr( pOld, pNew, nInvFlags );
521 :
522 0 : if ( nInvFlags != 0 )
523 : {
524 0 : InvalidatePage( this );
525 0 : if ( nInvFlags & 0x01 )
526 0 : _InvalidatePrt();
527 0 : if ( nInvFlags & 0x02 )
528 0 : SetCompletePaint();
529 0 : if ( nInvFlags & 0x04 && GetNext() )
530 0 : GetNext()->InvalidatePos();
531 0 : if ( nInvFlags & 0x08 )
532 0 : PrepareHeader();
533 0 : if ( nInvFlags & 0x10 )
534 0 : PrepareFooter();
535 0 : if ( nInvFlags & 0x20 )
536 0 : CheckGrid( nInvFlags & 0x40 );
537 : }
538 0 : }
539 :
540 0 : void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
541 : sal_uInt8 &rInvFlags,
542 : SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
543 : {
544 0 : bool bClear = true;
545 0 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
546 0 : switch( nWhich )
547 : {
548 : case RES_FMT_CHG:
549 : {
550 : // If the frame format is changed, several things might also change:
551 : // 1. columns:
552 : assert(pOld && pNew); //FMT_CHG Missing Format
553 0 : const SwFmt* pOldFmt = pOld ? ((SwFmtChg*)pOld)->pChangedFmt : NULL;
554 0 : const SwFmt* pNewFmt = pNew ? ((SwFmtChg*)pNew)->pChangedFmt : NULL;
555 : assert(pOldFmt && pNewFmt); //FMT_CHG Missing Format
556 0 : if (pOldFmt && pNewFmt)
557 : {
558 0 : const SwFmtCol &rOldCol = pOldFmt->GetCol();
559 0 : const SwFmtCol &rNewCol = pNewFmt->GetCol();
560 0 : if( rOldCol != rNewCol )
561 : {
562 0 : SwLayoutFrm *pB = FindBodyCont();
563 : OSL_ENSURE( pB, "Seite ohne Body." );
564 0 : pB->ChgColumns( rOldCol, rNewCol );
565 0 : rInvFlags |= 0x20;
566 : }
567 :
568 : // 2. header and footer:
569 0 : const SwFmtHeader &rOldH = pOldFmt->GetHeader();
570 0 : const SwFmtHeader &rNewH = pNewFmt->GetHeader();
571 0 : if( rOldH != rNewH )
572 0 : rInvFlags |= 0x08;
573 :
574 0 : const SwFmtFooter &rOldF = pOldFmt->GetFooter();
575 0 : const SwFmtFooter &rNewF = pNewFmt->GetFooter();
576 0 : if( rOldF != rNewF )
577 0 : rInvFlags |= 0x10;
578 0 : CheckDirChange();
579 : }
580 : }
581 : // no break
582 : case RES_FRM_SIZE:
583 : {
584 0 : const SwRect aOldPageFrmRect( Frm() );
585 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
586 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
587 : {
588 0 : mbValidSize = sal_False;
589 : // OD 28.10.2002 #97265# - Don't call <SwPageFrm::MakeAll()>
590 : // Calculation of the page is not necessary, because its size is
591 : // is invalidated here and further invalidation is done in the
592 : // calling method <SwPageFrm::Modify(..)> and probably by calling
593 : // <SwLayoutFrm::Modify(..)> at the end.
594 : // It can also causes inconsistences, because the lowers are
595 : // adjusted, but not calculated, and a <SwPageFrm::MakeAll()> of
596 : // a next page is called. This is performed on the switch to the
597 : // online layout.
598 : //MakeAll();
599 : }
600 0 : else if (pNew)
601 : {
602 : const SwFmtFrmSize &rSz = nWhich == RES_FMT_CHG ?
603 0 : ((SwFmtChg*)pNew)->pChangedFmt->GetFrmSize() :
604 0 : (const SwFmtFrmSize&)*pNew;
605 :
606 0 : Frm().Height( std::max( rSz.GetHeight(), long(MINLAY) ) );
607 0 : Frm().Width ( std::max( rSz.GetWidth(), long(MINLAY) ) );
608 :
609 0 : if ( GetUpper() )
610 0 : static_cast<SwRootFrm*>(GetUpper())->CheckViewLayout( 0, 0 );
611 : }
612 : // cleanup Window
613 0 : if( pSh && pSh->GetWin() && aOldPageFrmRect.HasArea() )
614 : {
615 : // OD 12.02.2003 #i9719#, #105645# - consider border and shadow of
616 : // page frame for determine 'old' rectangle - it's used for invalidating.
617 0 : const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
618 0 : SwRect aOldRectWithBorderAndShadow;
619 : SwPageFrm::GetBorderAndShadowBoundRect( aOldPageFrmRect, pSh, aOldRectWithBorderAndShadow,
620 0 : IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
621 0 : pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
622 : }
623 0 : rInvFlags |= 0x03;
624 0 : if ( aOldPageFrmRect.Height() != Frm().Height() )
625 0 : rInvFlags |= 0x04;
626 : }
627 0 : break;
628 :
629 : case RES_COL:
630 : assert(pOld && pNew); //COL Missing Format
631 0 : if (pOld && pNew)
632 : {
633 0 : SwLayoutFrm *pB = FindBodyCont();
634 : assert(pB); //page without body
635 0 : pB->ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew );
636 0 : rInvFlags |= 0x22;
637 : }
638 0 : break;
639 :
640 : case RES_HEADER:
641 0 : rInvFlags |= 0x08;
642 0 : break;
643 :
644 : case RES_FOOTER:
645 0 : rInvFlags |= 0x10;
646 0 : break;
647 : case RES_TEXTGRID:
648 0 : rInvFlags |= 0x60;
649 0 : break;
650 :
651 : case RES_PAGEDESC_FTNINFO:
652 : // currently the savest way:
653 0 : ((SwRootFrm*)GetUpper())->SetSuperfluous();
654 0 : SetMaxFtnHeight( pDesc->GetFtnInfo().GetHeight() );
655 0 : if ( !GetMaxFtnHeight() )
656 0 : SetMaxFtnHeight( LONG_MAX );
657 0 : SetColMaxFtnHeight();
658 : // here, the page might be destroyed:
659 0 : ((SwRootFrm*)GetUpper())->RemoveFtns( 0, sal_False, sal_True );
660 0 : break;
661 : case RES_FRAMEDIR :
662 0 : CheckDirChange();
663 0 : break;
664 :
665 : default:
666 0 : bClear = false;
667 : }
668 0 : if ( bClear )
669 : {
670 0 : if ( pOldSet || pNewSet )
671 : {
672 0 : if ( pOldSet )
673 0 : pOldSet->ClearItem( nWhich );
674 0 : if ( pNewSet )
675 0 : pNewSet->ClearItem( nWhich );
676 : }
677 : else
678 0 : SwLayoutFrm::Modify( pOld, pNew );
679 : }
680 0 : }
681 :
682 : /// get information from Modify
683 0 : bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
684 : {
685 0 : if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
686 : {
687 : // a page frame exists, so use this one
688 0 : return false;
689 : }
690 0 : return true; // continue searching
691 : }
692 :
693 0 : void SwPageFrm::SetPageDesc( SwPageDesc *pNew, SwFrmFmt *pFmt )
694 : {
695 0 : pDesc = pNew;
696 0 : if ( pFmt )
697 0 : SetFrmFmt( pFmt );
698 0 : }
699 :
700 : /* determine the right PageDesc:
701 : * 0. from the document for footnote and endnote pages
702 : * 1. from the first BodyCntnt below a page
703 : * 2. from PageDesc of the predecessor page
704 : * 3. from PageDesc of the previous page if blank page
705 : * 3.1 from PageDesc of the next page if no predecessor exists
706 : * 4. default PageDesc
707 : * 5. In BrowseMode use the first paragraph or default PageDesc.
708 : */
709 0 : SwPageDesc *SwPageFrm::FindPageDesc()
710 : {
711 : // 0.
712 0 : if ( IsFtnPage() )
713 : {
714 0 : SwDoc *pDoc = GetFmt()->GetDoc();
715 0 : if ( IsEndNotePage() )
716 0 : return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
717 : else
718 0 : return pDoc->GetFtnInfo().GetPageDesc( *pDoc );
719 : }
720 :
721 0 : SwPageDesc *pRet = 0;
722 :
723 : //5.
724 0 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
725 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
726 : {
727 0 : SwCntntFrm *pFrm = GetUpper()->ContainsCntnt();
728 0 : while ( !pFrm->IsInDocBody() )
729 0 : pFrm = pFrm->GetNextCntntFrm();
730 0 : SwFrm *pFlow = pFrm;
731 0 : if ( pFlow->IsInTab() )
732 0 : pFlow = pFlow->FindTabFrm();
733 0 : pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
734 0 : if ( !pRet )
735 0 : pRet = &GetFmt()->GetDoc()->GetPageDesc( 0 );
736 0 : return pRet;
737 : }
738 :
739 0 : SwFrm *pFlow = FindFirstBodyCntnt();
740 0 : if ( pFlow && pFlow->IsInTab() )
741 0 : pFlow = pFlow->FindTabFrm();
742 :
743 : //1.
744 0 : if ( pFlow )
745 : {
746 0 : SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
747 0 : if ( !pTmp->IsFollow() )
748 0 : pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
749 : }
750 :
751 : //3. und 3.1
752 0 : if ( !pRet && IsEmptyPage() )
753 : // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
754 : // the same page description as its prev, just like after construction
755 : // of the empty page.
756 0 : pRet = GetPrev() ? ((SwPageFrm*)GetPrev())->GetPageDesc() :
757 0 : GetNext() ? ((SwPageFrm*)GetNext())->GetPageDesc() : 0;
758 :
759 : //2.
760 0 : if ( !pRet )
761 0 : pRet = GetPrev() ?
762 0 : ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
763 :
764 : //4.
765 0 : if ( !pRet )
766 0 : pRet = &GetFmt()->GetDoc()->GetPageDesc( 0 );
767 :
768 : OSL_ENSURE( pRet, "could not find page descriptor." );
769 0 : return pRet;
770 : }
771 :
772 : // Notify if the RootFrm changes its size
773 0 : void AdjustSizeChgNotify( SwRootFrm *pRoot )
774 : {
775 0 : const sal_Bool bOld = pRoot->IsSuperfluous();
776 0 : pRoot->bCheckSuperfluous = sal_False;
777 0 : SwViewShell *pSh = pRoot->GetCurrShell();
778 0 : if ( pSh )
779 : {
780 0 : do
781 : {
782 0 : if( pRoot == pSh->GetLayout() )
783 : {
784 0 : pSh->SizeChgNotify();
785 0 : if ( pSh->Imp() )
786 0 : pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );
787 : }
788 0 : pSh = (SwViewShell*)pSh->GetNext();
789 0 : } while ( pSh != pRoot->GetCurrShell() );
790 : }
791 0 : pRoot->bCheckSuperfluous = bOld;
792 0 : }
793 :
794 0 : inline void SetLastPage( SwPageFrm *pPage )
795 : {
796 0 : ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
797 0 : }
798 :
799 0 : void SwPageFrm::Cut()
800 : {
801 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
802 0 : if ( !IsEmptyPage() )
803 : {
804 0 : if ( GetNext() )
805 0 : GetNext()->InvalidatePos();
806 :
807 : // move Flys whose anchor is on a different page (draw objects are not relevant here)
808 0 : if ( GetSortedObjs() )
809 : {
810 0 : for ( int i = 0; GetSortedObjs() &&
811 0 : (sal_uInt16)i < GetSortedObjs()->Count(); ++i )
812 : {
813 : // #i28701#
814 0 : SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
815 :
816 0 : if ( pAnchoredObj->ISA(SwFlyAtCntFrm) )
817 : {
818 0 : SwFlyFrm* pFly = static_cast<SwFlyAtCntFrm*>(pAnchoredObj);
819 0 : SwPageFrm *pAnchPage = pFly->GetAnchorFrm() ?
820 0 : pFly->AnchorFrm()->FindPageFrm() : 0;
821 0 : if ( pAnchPage && (pAnchPage != this) )
822 : {
823 0 : MoveFly( pFly, pAnchPage );
824 0 : --i;
825 0 : pFly->InvalidateSize();
826 0 : pFly->_InvalidatePos();
827 : }
828 : }
829 : }
830 : }
831 : // cleanup Window
832 0 : if ( pSh && pSh->GetWin() )
833 0 : pSh->InvalidateWindows( Frm() );
834 : }
835 :
836 : // decrease the root's page number
837 0 : ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
838 0 : SwPageFrm *pPg = (SwPageFrm*)GetNext();
839 0 : if ( pPg )
840 : {
841 0 : while ( pPg )
842 : {
843 0 : pPg->DecrPhyPageNum(); //inline --nPhyPageNum
844 0 : pPg = (SwPageFrm*)pPg->GetNext();
845 : }
846 : }
847 : else
848 0 : ::SetLastPage( (SwPageFrm*)GetPrev() );
849 :
850 0 : SwFrm* pRootFrm = GetUpper();
851 :
852 : // cut all connections
853 0 : Remove();
854 :
855 0 : if ( pRootFrm )
856 0 : static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
857 0 : }
858 :
859 0 : void SwPageFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
860 : {
861 : OSL_ENSURE( pParent->IsRootFrm(), "Parent is no Root." );
862 : OSL_ENSURE( pParent, "No parent for Paste()." );
863 : OSL_ENSURE( pParent != this, "I'm my own parent." );
864 : OSL_ENSURE( pSibling != this, "I'm my own neighbour." );
865 : OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
866 : "I am still registered somewhere." );
867 :
868 : // insert into tree structure
869 0 : InsertBefore( (SwLayoutFrm*)pParent, pSibling );
870 :
871 : // increase the root's page number
872 0 : ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
873 0 : if( GetPrev() )
874 0 : SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
875 : else
876 0 : SetPhyPageNum( 1 );
877 0 : SwPageFrm *pPg = (SwPageFrm*)GetNext();
878 0 : if ( pPg )
879 : {
880 0 : while ( pPg )
881 : {
882 0 : pPg->IncrPhyPageNum(); //inline ++nPhyPageNum
883 0 : pPg->_InvalidatePos();
884 0 : pPg->InvalidateLayout();
885 0 : pPg = (SwPageFrm*)pPg->GetNext();
886 : }
887 : }
888 : else
889 0 : ::SetLastPage( this );
890 :
891 0 : if( Frm().Width() != pParent->Prt().Width() )
892 0 : _InvalidateSize();
893 :
894 0 : InvalidatePos();
895 :
896 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
897 0 : if ( pSh )
898 0 : pSh->SetFirstVisPageInvalid();
899 :
900 0 : getRootFrm()->CheckViewLayout( 0, 0 );
901 0 : }
902 :
903 0 : static void lcl_PrepFlyInCntRegister( SwCntntFrm *pFrm )
904 : {
905 0 : pFrm->Prepare( PREP_REGISTER );
906 0 : if( pFrm->GetDrawObjs() )
907 : {
908 0 : for( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
909 : {
910 : // #i28701#
911 0 : SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
912 0 : if ( pAnchoredObj->ISA(SwFlyInCntFrm) )
913 : {
914 0 : SwFlyFrm* pFly = static_cast<SwFlyInCntFrm*>(pAnchoredObj);
915 0 : SwCntntFrm *pCnt = pFly->ContainsCntnt();
916 0 : while ( pCnt )
917 : {
918 0 : lcl_PrepFlyInCntRegister( pCnt );
919 0 : pCnt = pCnt->GetNextCntntFrm();
920 : }
921 : }
922 : }
923 : }
924 0 : }
925 :
926 0 : void SwPageFrm::PrepareRegisterChg()
927 : {
928 0 : SwCntntFrm *pFrm = FindFirstBodyCntnt();
929 0 : while( pFrm )
930 : {
931 0 : lcl_PrepFlyInCntRegister( pFrm );
932 0 : pFrm = pFrm->GetNextCntntFrm();
933 0 : if( !IsAnLower( pFrm ) )
934 0 : break;
935 : }
936 0 : if( GetSortedObjs() )
937 : {
938 0 : for( sal_uInt16 i = 0; i < GetSortedObjs()->Count(); ++i )
939 : {
940 : // #i28701#
941 0 : SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];
942 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
943 : {
944 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
945 0 : pFrm = pFly->ContainsCntnt();
946 0 : while ( pFrm )
947 : {
948 0 : ::lcl_PrepFlyInCntRegister( pFrm );
949 0 : pFrm = pFrm->GetNextCntntFrm();
950 : }
951 : }
952 : }
953 : }
954 0 : }
955 :
956 : //FIXME: provide missing documentation
957 : /** Check all pages (starting from the given one) if they use the right frame format.
958 : *
959 : * If "wrong" pages are found, try to fix this as simple as possible.
960 : *
961 : * @param pStart the page from where to start searching
962 : * @param bNotifyFields
963 : * @param ppPrev
964 : */
965 0 : void SwFrm::CheckPageDescs( SwPageFrm *pStart, sal_Bool bNotifyFields, SwPageFrm** ppPrev )
966 : {
967 : OSL_ENSURE( pStart, "no starting page." );
968 :
969 0 : SwViewShell *pSh = pStart->getRootFrm()->GetCurrShell();
970 0 : SwViewImp *pImp = pSh ? pSh->Imp() : 0;
971 :
972 0 : if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
973 : {
974 0 : pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
975 0 : return;
976 : }
977 :
978 : // For the update of page numbering fields, nDocPos provides
979 : // the page position from where invalidation should start.
980 0 : SwTwips nDocPos = LONG_MAX;
981 :
982 0 : SwRootFrm *pRoot = (SwRootFrm*)pStart->GetUpper();
983 0 : SwDoc* pDoc = pStart->GetFmt()->GetDoc();
984 0 : const bool bFtns = !pDoc->GetFtnIdxs().empty();
985 :
986 0 : SwPageFrm *pPage = pStart;
987 0 : if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
988 0 : pPage = (SwPageFrm*)pPage->GetPrev();
989 0 : while ( pPage )
990 : {
991 : // obtain PageDesc and FrmFmt
992 0 : SwPageDesc *pDesc = pPage->FindPageDesc();
993 0 : sal_Bool bCheckEmpty = pPage->IsEmptyPage();
994 0 : sal_Bool bActOdd = pPage->OnRightPage();
995 0 : sal_Bool bOdd = pPage->WannaRightPage();
996 0 : bool bFirst = pPage->OnFirstPage();
997 : SwFrmFmt *pFmtWish = (bOdd)
998 0 : ? pDesc->GetRightFmt(bFirst) : pDesc->GetLeftFmt(bFirst);
999 :
1000 0 : if ( bActOdd != bOdd ||
1001 0 : pDesc != pPage->GetPageDesc() || // wrong Desc
1002 0 : ( pFmtWish != pPage->GetFmt() && // wrong format and
1003 0 : ( !pPage->IsEmptyPage() || pFmtWish ) // not blank /empty
1004 : )
1005 : )
1006 : {
1007 : // Updating a page might take a while, so check the WaitCrsr
1008 0 : if( pImp )
1009 0 : pImp->CheckWaitCrsr();
1010 :
1011 : // invalidate the field, starting from here
1012 0 : if ( nDocPos == LONG_MAX )
1013 0 : nDocPos = pPage->GetPrev() ?
1014 0 : pPage->GetPrev()->Frm().Top() : pPage->Frm().Top();
1015 :
1016 : // Cases:
1017 : // 1. Empty page should be "normal" page -> remove empty page and take next one
1018 : // 2. Empty page should have different descriptor -> change
1019 : // 3. Normal page should be empty -> insert empty page if previous page
1020 : // is not empty, otherwise see (6).
1021 : // 4. Normal page should have different descriptor -> change
1022 : // 5. Normal page should have different format -> change
1023 : // 6. No "wish" format provided -> take the "other" format (left/right) of the PageDesc
1024 :
1025 0 : if ( pPage->IsEmptyPage() && ( pFmtWish || //1.
1026 0 : ( !bOdd && !pPage->GetPrev() ) ) )
1027 : {
1028 0 : SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1029 0 : pPage->Cut();
1030 0 : bool bUpdatePrev = false;
1031 0 : if (ppPrev && *ppPrev == pPage)
1032 0 : bUpdatePrev = true;
1033 0 : delete pPage;
1034 0 : if ( pStart == pPage )
1035 0 : pStart = pTmp;
1036 0 : pPage = pTmp;
1037 0 : if (bUpdatePrev)
1038 0 : *ppPrev = pTmp;
1039 0 : continue;
1040 : }
1041 0 : else if ( pPage->IsEmptyPage() && !pFmtWish && //2.
1042 0 : pDesc != pPage->GetPageDesc() )
1043 : {
1044 0 : pPage->SetPageDesc( pDesc, 0 );
1045 : }
1046 0 : else if ( !pPage->IsEmptyPage() && //3.
1047 0 : bActOdd != bOdd &&
1048 0 : ( ( !pPage->GetPrev() && !bOdd ) ||
1049 0 : ( pPage->GetPrev() &&
1050 0 : !((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1051 : )
1052 : )
1053 : {
1054 0 : if ( pPage->GetPrev() )
1055 0 : pDesc = ((SwPageFrm*)pPage->GetPrev())->GetPageDesc();
1056 0 : SwPageFrm *pTmp = new SwPageFrm( pDoc->GetEmptyPageFmt(),pRoot,pDesc);
1057 0 : pTmp->Paste( pRoot, pPage );
1058 0 : pTmp->PreparePage( sal_False );
1059 0 : pPage = pTmp;
1060 : }
1061 0 : else if ( pPage->GetPageDesc() != pDesc ) //4.
1062 : {
1063 0 : SwPageDesc *pOld = pPage->GetPageDesc();
1064 0 : pPage->SetPageDesc( pDesc, pFmtWish );
1065 0 : if ( bFtns )
1066 : {
1067 : // If specific values of the FtnInfo are changed, something has to happen.
1068 : // We try to limit the damage...
1069 : // If the page has no FtnCont it might be problematic.
1070 : // Let's hope that invalidation is enough.
1071 0 : SwFtnContFrm *pCont = pPage->FindFtnCont();
1072 0 : if ( pCont && !(pOld->GetFtnInfo() == pDesc->GetFtnInfo()) )
1073 0 : pCont->_InvalidateAll();
1074 : }
1075 : }
1076 0 : else if ( pFmtWish && pPage->GetFmt() != pFmtWish ) //5.
1077 : {
1078 0 : pPage->SetFrmFmt( pFmtWish );
1079 : }
1080 0 : else if ( !pFmtWish ) //6.
1081 : {
1082 : // get format with inverted logic
1083 0 : if (!pFmtWish)
1084 0 : pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
1085 0 : if ( pPage->GetFmt() != pFmtWish )
1086 0 : pPage->SetFrmFmt( pFmtWish );
1087 : }
1088 : #if OSL_DEBUG_LEVEL > 0
1089 : else
1090 : {
1091 : OSL_FAIL( "CheckPageDescs, missing solution" );
1092 : }
1093 : #endif
1094 : }
1095 0 : if ( bCheckEmpty )
1096 : {
1097 : // It also might be that an empty page is not needed at all.
1098 : // However, the algorithm above cannot determine that. It is not needed if the following
1099 : // page can live without it. Do obtain that information, we need to dig deeper...
1100 0 : SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
1101 0 : if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
1102 : {
1103 : // The following page can find a FrmFmt or has no successor -> empty page not needed
1104 0 : SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1105 0 : pPage->Cut();
1106 0 : bool bUpdatePrev = false;
1107 0 : if (ppPrev && *ppPrev == pPage)
1108 0 : bUpdatePrev = true;
1109 0 : delete pPage;
1110 0 : if ( pStart == pPage )
1111 0 : pStart = pTmp;
1112 0 : pPage = pTmp;
1113 0 : if (bUpdatePrev)
1114 0 : *ppPrev = pTmp;
1115 0 : continue;
1116 : }
1117 : }
1118 0 : pPage = (SwPageFrm*)pPage->GetNext();
1119 : }
1120 :
1121 0 : pRoot->SetAssertFlyPages();
1122 0 : pRoot->AssertPageFlys( pStart );
1123 :
1124 0 : if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
1125 : {
1126 0 : SwDocPosUpdate aMsgHnt( nDocPos );
1127 0 : pDoc->UpdatePageFlds( &aMsgHnt );
1128 : }
1129 :
1130 : #if OSL_DEBUG_LEVEL > 0
1131 : //1. check if two empty pages are behind one another
1132 : bool bEmpty = false;
1133 : SwPageFrm *pPg = pStart;
1134 : while ( pPg )
1135 : {
1136 : if ( pPg->IsEmptyPage() )
1137 : {
1138 : if ( bEmpty )
1139 : {
1140 : OSL_FAIL( "double empty pages." );
1141 : break; // once is enough
1142 : }
1143 : bEmpty = true;
1144 : }
1145 : else
1146 : bEmpty = false;
1147 :
1148 : pPg = (SwPageFrm*)pPg->GetNext();
1149 : }
1150 : #endif
1151 : }
1152 :
1153 0 : SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn )
1154 : {
1155 0 : SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
1156 0 : SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
1157 0 : SwPageDesc *pDesc = pSibling->GetPageDesc();
1158 :
1159 0 : pSibling = (SwPageFrm*)pPrevPage->GetNext();
1160 : // insert right (odd) or left (even) page?
1161 0 : bool bNextOdd = !pPrevPage->OnRightPage();
1162 0 : bool bWishedOdd = bNextOdd;
1163 :
1164 : // Which PageDesc is relevant?
1165 : // For CntntFrm take the one from format if provided,
1166 : // otherwise from the Follow of the PrevPage
1167 0 : pDesc = 0;
1168 0 : if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
1169 0 : { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
1170 0 : pDesc = rDesc.GetPageDesc();
1171 0 : if ( rDesc.GetNumOffset() )
1172 : {
1173 0 : ::boost::optional<sal_uInt16> oNumOffset = rDesc.GetNumOffset();
1174 0 : bWishedOdd = ((oNumOffset ? oNumOffset.get() : 0) % 2) ? true : false;
1175 : // use the opportunity to set the flag at root
1176 0 : pRoot->SetVirtPageNum( sal_True );
1177 : }
1178 : }
1179 0 : if ( !pDesc )
1180 0 : pDesc = pPrevPage->GetPageDesc()->GetFollow();
1181 :
1182 : OSL_ENSURE( pDesc, "Missing PageDesc" );
1183 0 : if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1184 0 : bWishedOdd = !bWishedOdd;
1185 0 : bool const bWishedFirst = pDesc != pPrevPage->GetPageDesc();
1186 :
1187 0 : SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
1188 0 : bool bCheckPages = false;
1189 : // If there is no FrmFmt for this page, create an empty page.
1190 0 : if( bWishedOdd != bNextOdd )
1191 : {
1192 0 : SwFrmFmt *const pEmptyFmt = pDoc->GetEmptyPageFmt();
1193 0 : SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
1194 0 : SwPageFrm *pPage = new SwPageFrm(pEmptyFmt, pRoot, pTmpDesc);
1195 0 : pPage->Paste( pRoot, pSibling );
1196 0 : pPage->PreparePage( bFtn );
1197 : // If the sibling has no body text, destroy it as long as it is no footnote page.
1198 0 : if ( pSibling && !pSibling->IsFtnPage() &&
1199 0 : !pSibling->FindFirstBodyCntnt() )
1200 : {
1201 0 : SwPageFrm *pDel = pSibling;
1202 0 : pSibling = (SwPageFrm*)pSibling->GetNext();
1203 0 : if ( !pDoc->GetFtnIdxs().empty() )
1204 0 : pRoot->RemoveFtns( pDel, sal_True );
1205 0 : pDel->Cut();
1206 0 : delete pDel;
1207 : }
1208 : else
1209 0 : bCheckPages = true;
1210 : }
1211 : SwFrmFmt *const pFmt( (bWishedOdd)
1212 0 : ? pDesc->GetRightFmt(bWishedFirst)
1213 0 : : pDesc->GetLeftFmt(bWishedFirst) );
1214 : assert(pFmt);
1215 0 : SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc );
1216 0 : pPage->Paste( pRoot, pSibling );
1217 0 : pPage->PreparePage( bFtn );
1218 : // If the sibling has no body text, destroy it as long as it is no footnote page.
1219 0 : if ( pSibling && !pSibling->IsFtnPage() &&
1220 0 : !pSibling->FindFirstBodyCntnt() )
1221 : {
1222 0 : SwPageFrm *pDel = pSibling;
1223 0 : pSibling = (SwPageFrm*)pSibling->GetNext();
1224 0 : if ( !pDoc->GetFtnIdxs().empty() )
1225 0 : pRoot->RemoveFtns( pDel, sal_True );
1226 0 : pDel->Cut();
1227 0 : delete pDel;
1228 : }
1229 : else
1230 0 : bCheckPages = true;
1231 :
1232 0 : if ( pSibling )
1233 : {
1234 0 : if ( bCheckPages )
1235 : {
1236 0 : CheckPageDescs( pSibling, sal_False );
1237 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
1238 0 : SwViewImp *pImp = pSh ? pSh->Imp() : 0;
1239 0 : if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1240 : {
1241 0 : const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
1242 0 : if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
1243 0 : pImp->GetLayAction().SetCheckPageNumDirect(
1244 0 : pSibling->GetPhyPageNum() );
1245 0 : return pPage;
1246 : }
1247 : }
1248 : else
1249 0 : pRoot->AssertPageFlys( pSibling );
1250 : }
1251 :
1252 : // For the update of page numbering fields, nDocPos provides
1253 : // the page position from where invalidation should start.
1254 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
1255 0 : if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
1256 : {
1257 0 : SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
1258 0 : pDoc->UpdatePageFlds( &aMsgHnt );
1259 : }
1260 0 : return pPage;
1261 : }
1262 :
1263 0 : sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const
1264 : {
1265 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
1266 0 : if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
1267 : {
1268 0 : return sw::sidebarwindows::SIDEBAR_RIGHT;
1269 : }
1270 : else
1271 : {
1272 0 : const bool bLTR = getRootFrm()->IsLeftToRightViewLayout();
1273 0 : const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
1274 0 : const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
1275 :
1276 : return bRightSidebar
1277 : ? sw::sidebarwindows::SIDEBAR_RIGHT
1278 0 : : sw::sidebarwindows::SIDEBAR_LEFT;
1279 : }
1280 : }
1281 :
1282 0 : SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1283 : {
1284 0 : if ( !bTst )
1285 0 : Frm().SSize().Height() += nDist;
1286 0 : return nDist;
1287 : }
1288 :
1289 0 : SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1290 : {
1291 : OSL_ENSURE( nDist >= 0, "nDist < 0." );
1292 : OSL_ENSURE( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
1293 :
1294 0 : if ( !bTst )
1295 0 : Frm().SSize().Height() -= nDist;
1296 0 : return nDist;
1297 : }
1298 :
1299 : /// remove pages that are not needed at all
1300 0 : void SwRootFrm::RemoveSuperfluous()
1301 : {
1302 : // A page is empty if the body text area has no CntntFrm, but not if there
1303 : // is at least one Fly or one footnote attached to the page. Two runs are
1304 : // needed: one for endnote pages and one for the pages of the body text.
1305 :
1306 0 : if ( !IsSuperfluous() )
1307 0 : return;
1308 0 : bCheckSuperfluous = sal_False;
1309 :
1310 0 : SwPageFrm *pPage = GetLastPage();
1311 0 : long nDocPos = LONG_MAX;
1312 :
1313 : // Check the corresponding last page if it is empty and stop loop at the last non-empty page.
1314 0 : do
1315 : {
1316 0 : bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
1317 0 : if ( bExistEssentialObjs )
1318 : {
1319 : // Only because the page has Flys does not mean that it is needed. If all Flys are
1320 : // attached to generic content it is also superfluous (checking DocBody should be enough)
1321 : // OD 19.06.2003 #108784# - consider that drawing objects in
1322 : // header/footer are supported now.
1323 0 : bool bOnlySuperfluosObjs = true;
1324 0 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1325 0 : for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
1326 : {
1327 : // #i28701#
1328 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
1329 : // OD 2004-01-19 #110582# - do not consider hidden objects
1330 0 : if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
1331 0 : pAnchoredObj->GetDrawObj()->GetLayer() ) &&
1332 0 : !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
1333 : {
1334 0 : bOnlySuperfluosObjs = false;
1335 : }
1336 : }
1337 0 : bExistEssentialObjs = !bOnlySuperfluosObjs;
1338 : }
1339 :
1340 : // OD 19.06.2003 #108784# - optimization: check first, if essential objects
1341 : // exists.
1342 0 : const SwLayoutFrm* pBody = 0;
1343 0 : if ( bExistEssentialObjs ||
1344 0 : pPage->FindFtnCont() ||
1345 0 : ( 0 != ( pBody = pPage->FindBodyCont() ) &&
1346 0 : ( pBody->ContainsCntnt() ||
1347 : // #i47580#
1348 : // Do not delete page if there's an empty tabframe
1349 : // left. I think it might be correct to use ContainsAny()
1350 : // instead of ContainsCntnt() to cover the empty-table-case,
1351 : // but I'm not fully sure, since ContainsAny() also returns
1352 : // SectionFrames. Therefore I prefer to do it the safe way:
1353 0 : ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
1354 : {
1355 0 : if ( pPage->IsFtnPage() )
1356 : {
1357 0 : while ( pPage->IsFtnPage() )
1358 : {
1359 0 : pPage = (SwPageFrm*)pPage->GetPrev();
1360 : OSL_ENSURE( pPage, "only endnote pages remain." );
1361 : }
1362 0 : continue;
1363 : }
1364 : else
1365 0 : pPage = 0;
1366 : }
1367 :
1368 0 : if ( pPage )
1369 : {
1370 0 : SwPageFrm *pEmpty = pPage;
1371 0 : pPage = (SwPageFrm*)pPage->GetPrev();
1372 0 : if ( !GetFmt()->GetDoc()->GetFtnIdxs().empty() )
1373 0 : RemoveFtns( pEmpty, sal_True );
1374 0 : pEmpty->Cut();
1375 0 : delete pEmpty;
1376 0 : nDocPos = pPage ? pPage->Frm().Top() : 0;
1377 : }
1378 : } while ( pPage );
1379 :
1380 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
1381 0 : if ( nDocPos != LONG_MAX &&
1382 0 : (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
1383 : {
1384 0 : SwDocPosUpdate aMsgHnt( nDocPos );
1385 0 : GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
1386 : }
1387 : }
1388 :
1389 : /// Ensures that enough pages exist, so that all page bound frames and draw objects can be placed
1390 0 : void SwRootFrm::AssertFlyPages()
1391 : {
1392 0 : if ( !IsAssertFlyPages() )
1393 0 : return;
1394 0 : bAssertFlyPages = sal_False;
1395 :
1396 0 : SwDoc *pDoc = GetFmt()->GetDoc();
1397 0 : const SwFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1398 :
1399 : // what page targets the "last" Fly?
1400 0 : sal_uInt16 nMaxPg = 0;
1401 : sal_uInt16 i;
1402 :
1403 0 : for ( i = 0; i < pTbl->size(); ++i )
1404 : {
1405 0 : const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
1406 0 : if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
1407 0 : nMaxPg = rAnch.GetPageNum();
1408 : }
1409 : // How many pages exist at the moment?
1410 0 : SwPageFrm *pPage = (SwPageFrm*)Lower();
1411 0 : while ( pPage && pPage->GetNext() &&
1412 0 : !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
1413 : {
1414 0 : pPage = (SwPageFrm*)pPage->GetNext();
1415 : }
1416 :
1417 0 : if ( nMaxPg > pPage->GetPhyPageNum() )
1418 : {
1419 : // Continue pages based on the rules of the PageDesc after the last page.
1420 0 : sal_Bool bOdd = (pPage->GetPhyPageNum() % 2) ? sal_True : sal_False;
1421 0 : SwPageDesc *pDesc = pPage->GetPageDesc();
1422 0 : SwFrm *pSibling = pPage->GetNext();
1423 0 : for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
1424 : {
1425 0 : if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1426 : {
1427 : // Insert empty page (but Flys will be stored in the next page)
1428 0 : pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc );
1429 0 : pPage->Paste( this, pSibling );
1430 0 : pPage->PreparePage( sal_False );
1431 0 : bOdd = bOdd ? sal_False : sal_True;
1432 0 : ++i;
1433 : }
1434 : pPage = new
1435 : SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
1436 0 : pDesc->GetLeftFmt()), this, pDesc );
1437 0 : pPage->Paste( this, pSibling );
1438 0 : pPage->PreparePage( sal_False );
1439 0 : bOdd = bOdd ? sal_False : sal_True;
1440 0 : pDesc = pDesc->GetFollow();
1441 : }
1442 : // If the endnote pages are now corrupt, destroy them.
1443 0 : if ( !pDoc->GetFtnIdxs().empty() )
1444 : {
1445 0 : pPage = (SwPageFrm*)Lower();
1446 0 : while ( pPage && !pPage->IsFtnPage() )
1447 0 : pPage = (SwPageFrm*)pPage->GetNext();
1448 :
1449 0 : if ( pPage )
1450 : {
1451 0 : SwPageDesc *pTmpDesc = pPage->FindPageDesc();
1452 0 : bOdd = pPage->OnRightPage();
1453 0 : if ( pPage->GetFmt() !=
1454 : (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
1455 0 : RemoveFtns( pPage, sal_False, sal_True );
1456 : }
1457 : }
1458 : }
1459 : }
1460 :
1461 : /// Ensure that after the given page all page-bound objects are located on the correct page
1462 0 : void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
1463 : {
1464 0 : while ( pPage )
1465 : {
1466 0 : if ( pPage->GetSortedObjs() )
1467 : {
1468 0 : pPage->GetSortedObjs();
1469 0 : for ( int i = 0;
1470 0 : pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count();
1471 : ++i)
1472 : {
1473 : // #i28701#
1474 0 : SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
1475 0 : const SwFmtAnchor &rAnch = rFmt.GetAnchor();
1476 0 : const sal_uInt16 nPg = rAnch.GetPageNum();
1477 0 : if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
1478 0 : nPg != pPage->GetPhyPageNum() )
1479 : {
1480 : // If on the wrong page, check if previous page is empty
1481 0 : if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
1482 0 : ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
1483 : {
1484 : // It can move by itself. Just send a modify to its anchor attribute.
1485 : #if OSL_DEBUG_LEVEL > 1
1486 : const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
1487 : rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1488 : OSL_ENSURE( !pPage->GetSortedObjs() ||
1489 : nCnt != pPage->GetSortedObjs()->Count(),
1490 : "Object couldn't be reattached!" );
1491 : #else
1492 0 : rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1493 : #endif
1494 0 : --i;
1495 : }
1496 : }
1497 : }
1498 : }
1499 0 : pPage = (SwPageFrm*)pPage->GetNext();
1500 : }
1501 0 : }
1502 :
1503 0 : Size SwRootFrm::ChgSize( const Size& aNewSize )
1504 : {
1505 0 : Frm().SSize() = aNewSize;
1506 0 : _InvalidatePrt();
1507 0 : mbFixSize = sal_False;
1508 0 : return Frm().SSize();
1509 : }
1510 :
1511 0 : void SwRootFrm::MakeAll()
1512 : {
1513 0 : if ( !mbValidPos )
1514 0 : { mbValidPos = sal_True;
1515 0 : maFrm.Pos().setX(DOCUMENTBORDER);
1516 0 : maFrm.Pos().setY(DOCUMENTBORDER);
1517 : }
1518 0 : if ( !mbValidPrtArea )
1519 0 : { mbValidPrtArea = sal_True;
1520 0 : maPrt.Pos().setX(0);
1521 0 : maPrt.Pos().setY(0);
1522 0 : maPrt.SSize( maFrm.SSize() );
1523 : }
1524 0 : if ( !mbValidSize )
1525 : // SSize is set by the pages (Cut/Paste).
1526 0 : mbValidSize = sal_True;
1527 0 : }
1528 :
1529 0 : void SwRootFrm::ImplInvalidateBrowseWidth()
1530 : {
1531 0 : bBrowseWidthValid = sal_False;
1532 0 : SwFrm *pPg = Lower();
1533 0 : while ( pPg )
1534 : {
1535 0 : pPg->InvalidateSize();
1536 0 : pPg = pPg->GetNext();
1537 : }
1538 0 : }
1539 :
1540 0 : void SwRootFrm::ImplCalcBrowseWidth()
1541 : {
1542 : OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
1543 : "CalcBrowseWidth and not in BrowseView" );
1544 :
1545 : // The (minimal) with is determined from borders, tables and paint objects.
1546 : // It is calculated based on the attributes. Thus, it is not relevant how wide they are
1547 : // currently but only how wide they want to be.
1548 : // Frames and paint objects inside other objects (frames, tables) do not count.
1549 : // Borders and columns are not taken into account.
1550 :
1551 0 : SwFrm *pFrm = ContainsCntnt();
1552 0 : while ( pFrm && !pFrm->IsInDocBody() )
1553 0 : pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
1554 0 : if ( !pFrm )
1555 0 : return;
1556 :
1557 0 : bBrowseWidthValid = sal_True;
1558 0 : SwViewShell *pSh = getRootFrm()->GetCurrShell();
1559 : nBrowseWidth = pSh
1560 0 : ? MINLAY + 2 * pSh->GetOut()->
1561 0 : PixelToLogic( pSh->GetBrowseBorder() ).Width()
1562 0 : : 5000;
1563 0 : do
1564 : {
1565 0 : if ( pFrm->IsInTab() )
1566 0 : pFrm = pFrm->FindTabFrm();
1567 :
1568 0 : if ( pFrm->IsTabFrm() &&
1569 0 : !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
1570 : {
1571 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1572 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1573 0 : const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
1574 0 : long nWidth = rAttrs.GetSize().Width();
1575 0 : if ( nWidth < USHRT_MAX-2000 && //-2k, because USHRT_MAX gets missing while trying to resize!
1576 0 : text::HoriOrientation::FULL != rHori.GetHoriOrient() )
1577 : {
1578 : const SwHTMLTableLayout *pLayoutInfo =
1579 : ((const SwTabFrm *)pFrm)->GetTable()
1580 0 : ->GetHTMLTableLayout();
1581 0 : if ( pLayoutInfo )
1582 0 : nWidth = std::min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
1583 :
1584 0 : switch ( rHori.GetHoriOrient() )
1585 : {
1586 : case text::HoriOrientation::NONE:
1587 : // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1588 0 : nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
1589 0 : break;
1590 : case text::HoriOrientation::LEFT_AND_WIDTH:
1591 0 : nWidth += rAttrs.CalcLeft( pFrm );
1592 0 : break;
1593 : default:
1594 0 : break;
1595 : }
1596 0 : nBrowseWidth = std::max( nBrowseWidth, nWidth );
1597 0 : }
1598 : }
1599 0 : else if ( pFrm->GetDrawObjs() )
1600 : {
1601 0 : for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1602 : {
1603 : // #i28701#
1604 0 : SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1605 0 : const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
1606 0 : const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm);
1607 0 : if ((bFly && (FAR_AWAY == pAnchoredObj->GetObjRect().Width()))
1608 0 : || rFmt.GetFrmSize().GetWidthPercent())
1609 : {
1610 0 : continue;
1611 : }
1612 :
1613 0 : long nWidth = 0;
1614 0 : switch ( rFmt.GetAnchor().GetAnchorId() )
1615 : {
1616 : case FLY_AS_CHAR:
1617 0 : nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
1618 0 : pAnchoredObj->GetObjRect().Width();
1619 0 : break;
1620 : case FLY_AT_PARA:
1621 : {
1622 : // #i33170#
1623 : // Reactivated old code because
1624 : // nWidth = pAnchoredObj->GetObjRect().Right()
1625 : // gives wrong results for objects that are still
1626 : // at position FAR_AWAY.
1627 0 : if ( bFly )
1628 : {
1629 0 : nWidth = rFmt.GetFrmSize().GetWidth();
1630 0 : const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
1631 0 : switch ( rHori.GetHoriOrient() )
1632 : {
1633 : case text::HoriOrientation::NONE:
1634 0 : nWidth += rHori.GetPos();
1635 0 : break;
1636 : case text::HoriOrientation::INSIDE:
1637 : case text::HoriOrientation::LEFT:
1638 0 : if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
1639 0 : nWidth += pFrm->Prt().Left();
1640 0 : break;
1641 : default:
1642 0 : break;
1643 : }
1644 : }
1645 : else
1646 : // Paint objects to not have attributes and
1647 : // are defined by their current size
1648 0 : nWidth = pAnchoredObj->GetObjRect().Right() -
1649 0 : pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
1650 : }
1651 0 : break;
1652 : default: /* do nothing */;
1653 : }
1654 0 : nBrowseWidth = std::max( nBrowseWidth, nWidth );
1655 : }
1656 : }
1657 0 : pFrm = pFrm->FindNextCnt();
1658 : } while ( pFrm );
1659 : }
1660 :
1661 0 : void SwRootFrm::StartAllAction()
1662 : {
1663 0 : SwViewShell *pSh = GetCurrShell();
1664 0 : if ( pSh )
1665 0 : do
1666 0 : { if ( pSh->ISA( SwCrsrShell ) )
1667 0 : ((SwCrsrShell*)pSh)->StartAction();
1668 : else
1669 0 : pSh->StartAction();
1670 0 : pSh = (SwViewShell*)pSh->GetNext();
1671 :
1672 0 : } while ( pSh != GetCurrShell() );
1673 0 : }
1674 :
1675 0 : void SwRootFrm::EndAllAction( sal_Bool bVirDev )
1676 : {
1677 0 : SwViewShell *pSh = GetCurrShell();
1678 0 : if ( pSh )
1679 0 : do
1680 : {
1681 0 : const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
1682 0 : pSh->SetEndActionByVirDev( bVirDev );
1683 0 : if ( pSh->ISA( SwCrsrShell ) )
1684 : {
1685 0 : ((SwCrsrShell*)pSh)->EndAction();
1686 0 : ((SwCrsrShell*)pSh)->CallChgLnk();
1687 0 : if ( pSh->ISA( SwFEShell ) )
1688 0 : ((SwFEShell*)pSh)->SetChainMarker();
1689 : }
1690 : else
1691 0 : pSh->EndAction();
1692 0 : pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
1693 0 : pSh = (SwViewShell*)pSh->GetNext();
1694 :
1695 0 : } while ( pSh != GetCurrShell() );
1696 0 : }
1697 :
1698 0 : void SwRootFrm::UnoRemoveAllActions()
1699 : {
1700 0 : SwViewShell *pSh = GetCurrShell();
1701 0 : if ( pSh )
1702 0 : do
1703 : {
1704 : // #i84729#
1705 : // No end action, if <SwViewShell> instance is currently in its end action.
1706 : // Recursives calls to <::EndAction()> are not allowed.
1707 0 : if ( !pSh->IsInEndAction() )
1708 : {
1709 : OSL_ENSURE(!pSh->GetRestoreActions(), "Restore action count is already set!");
1710 0 : sal_Bool bCrsr = pSh->ISA( SwCrsrShell );
1711 0 : sal_Bool bFE = pSh->ISA( SwFEShell );
1712 0 : sal_uInt16 nRestore = 0;
1713 0 : while( pSh->ActionCount() )
1714 : {
1715 0 : if( bCrsr )
1716 : {
1717 0 : ((SwCrsrShell*)pSh)->EndAction();
1718 0 : ((SwCrsrShell*)pSh)->CallChgLnk();
1719 0 : if ( bFE )
1720 0 : ((SwFEShell*)pSh)->SetChainMarker();
1721 : }
1722 : else
1723 0 : pSh->EndAction();
1724 0 : nRestore++;
1725 : }
1726 0 : pSh->SetRestoreActions(nRestore);
1727 : }
1728 0 : pSh->LockView(sal_True);
1729 0 : pSh = (SwViewShell*)pSh->GetNext();
1730 :
1731 0 : } while ( pSh != GetCurrShell() );
1732 0 : }
1733 :
1734 0 : void SwRootFrm::UnoRestoreAllActions()
1735 : {
1736 0 : SwViewShell *pSh = GetCurrShell();
1737 0 : if ( pSh )
1738 0 : do
1739 : {
1740 0 : sal_uInt16 nActions = pSh->GetRestoreActions();
1741 0 : while( nActions-- )
1742 : {
1743 0 : if ( pSh->ISA( SwCrsrShell ) )
1744 0 : ((SwCrsrShell*)pSh)->StartAction();
1745 : else
1746 0 : pSh->StartAction();
1747 : }
1748 0 : pSh->SetRestoreActions(0);
1749 0 : pSh->LockView(sal_False);
1750 0 : pSh = (SwViewShell*)pSh->GetNext();
1751 :
1752 0 : } while ( pSh != GetCurrShell() );
1753 0 : }
1754 :
1755 : // Helper functions for SwRootFrm::CheckViewLayout
1756 : static void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
1757 :
1758 0 : static void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
1759 : {
1760 0 : SwSortedObjs* pSortedObj = 0;
1761 0 : const bool bPage = pFrm->IsPageFrm();
1762 :
1763 0 : if ( bPage )
1764 0 : pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
1765 : else
1766 0 : pSortedObj = pFrm->GetDrawObjs();
1767 :
1768 0 : for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
1769 : {
1770 0 : SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
1771 :
1772 0 : const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
1773 0 : const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
1774 :
1775 : // all except from the as character anchored objects are moved
1776 : // when processing the page frame:
1777 0 : const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR);
1778 0 : if ( !bPage && !bAsChar )
1779 0 : continue;
1780 :
1781 0 : SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
1782 :
1783 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
1784 : {
1785 0 : SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
1786 0 : lcl_MoveAllLowers( pFlyFrm, rOffset );
1787 0 : pFlyFrm->NotifyDrawObj();
1788 : // --> let the active embedded object be moved
1789 0 : if ( pFlyFrm->Lower() )
1790 : {
1791 0 : if ( pFlyFrm->Lower()->IsNoTxtFrm() )
1792 : {
1793 0 : SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
1794 0 : SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm();
1795 0 : SwViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0;
1796 0 : if ( pSh )
1797 : {
1798 0 : SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
1799 0 : if ( pNode )
1800 : {
1801 0 : svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
1802 0 : if ( xObj.is() )
1803 : {
1804 0 : SwViewShell* pTmp = pSh;
1805 0 : do
1806 : {
1807 0 : SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
1808 0 : if ( pFEShell )
1809 0 : pFEShell->MoveObjectIfActive( xObj, rOffset );
1810 0 : pTmp = static_cast<SwViewShell*>( pTmp->GetNext() );
1811 : } while( pTmp != pSh );
1812 : }
1813 : }
1814 : }
1815 : }
1816 : }
1817 : }
1818 0 : else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
1819 : {
1820 0 : SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
1821 :
1822 : // don't touch objects that are not yet positioned:
1823 0 : const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
1824 0 : if ( bNotYetPositioned )
1825 0 : continue;
1826 :
1827 0 : const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
1828 0 : const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
1829 0 : pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
1830 0 : pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
1831 :
1832 : // clear contour cache
1833 0 : if ( pAnchoredDrawObj->GetFrmFmt().GetSurround().IsContour() )
1834 0 : ClrContourCache( pAnchoredDrawObj->GetDrawObj() );
1835 : }
1836 : // #i92511#
1837 : // cache for object rectangle inclusive spaces has to be invalidated.
1838 0 : pAnchoredObj->InvalidateObjRectWithSpaces();
1839 0 : }
1840 0 : }
1841 :
1842 0 : static void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
1843 : {
1844 0 : const SwRect aFrm( pFrm->Frm() );
1845 :
1846 : // first move the current frame
1847 0 : pFrm->Frm().Pos() += rOffset;
1848 :
1849 : // Don't forget accessibility:
1850 0 : if( pFrm->IsAccessibleFrm() )
1851 : {
1852 0 : SwRootFrm *pRootFrm = pFrm->getRootFrm();
1853 0 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
1854 0 : pRootFrm->GetCurrShell() )
1855 : {
1856 0 : pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
1857 : }
1858 : }
1859 :
1860 : // the move any objects
1861 0 : lcl_MoveAllLowerObjs( pFrm, rOffset );
1862 :
1863 : // finally, for layout frames we have to call this function recursively:
1864 0 : if ( pFrm->ISA(SwLayoutFrm) )
1865 : {
1866 0 : SwFrm* pLowerFrm = pFrm->GetLower();
1867 0 : while ( pLowerFrm )
1868 : {
1869 0 : lcl_MoveAllLowers( pLowerFrm, rOffset );
1870 0 : pLowerFrm = pLowerFrm->GetNext();
1871 : }
1872 : }
1873 0 : }
1874 :
1875 : // Calculate how the pages have to be positioned
1876 0 : void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
1877 : {
1878 : // #i91432#
1879 : // No calculation of page positions, if only an empty page is present.
1880 : // This situation occurs when <SwRootFrm> instance is in construction
1881 : // and the document contains only left pages.
1882 0 : if ( Lower()->GetNext() == 0 &&
1883 0 : static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
1884 : {
1885 0 : return;
1886 : }
1887 :
1888 0 : if ( !pVisArea )
1889 : {
1890 : // no early return for bNewPage
1891 0 : if ( mnViewWidth < 0 )
1892 0 : mnViewWidth = 0;
1893 : }
1894 : else
1895 : {
1896 : OSL_ENSURE( pViewOpt, "CheckViewLayout required ViewOptions" );
1897 :
1898 0 : const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns();
1899 0 : const bool bBookMode = pViewOpt->IsViewLayoutBookMode();
1900 :
1901 0 : if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
1902 0 : return;
1903 :
1904 0 : mnColumns = nColumns;
1905 0 : mbBookMode = bBookMode;
1906 0 : mnViewWidth = pVisArea->Width();
1907 0 : mbSidebarChanged = false;
1908 : }
1909 :
1910 0 : if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
1911 : {
1912 0 : mnColumns = 1;
1913 0 : mbBookMode = false;
1914 : }
1915 :
1916 0 : Calc();
1917 :
1918 0 : const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
1919 0 : SetCallbackActionEnabled( sal_False );
1920 :
1921 0 : maPageRects.clear();
1922 :
1923 0 : const long nBorder = Frm().Pos().getX();
1924 0 : const long nVisWidth = mnViewWidth - 2 * nBorder;
1925 0 : const long nGapBetweenPages = GAPBETWEENPAGES;
1926 :
1927 : // check how many pages fit into the first page layout row:
1928 0 : SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
1929 :
1930 : // will contain the number of pages per row. 0 means that
1931 : // the page does not fit.
1932 0 : long nWidthRemain = nVisWidth;
1933 :
1934 : // after one row has been processed, these variables contain
1935 : // the width of the row and the maxium of the page heights
1936 0 : long nCurrentRowHeight = 0;
1937 0 : long nCurrentRowWidth = 0;
1938 :
1939 : // these variables are used to finally set the size of the
1940 : // root frame
1941 0 : long nSumRowHeight = 0;
1942 0 : SwTwips nMinPageLeft = TWIPS_MAX;
1943 0 : SwTwips nMaxPageRight = 0;
1944 0 : SwPageFrm* pStartOfRow = pPageFrm;
1945 0 : sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
1946 0 : bool bFirstRow = true;
1947 :
1948 0 : bool bPageChanged = false;
1949 0 : const bool bRTL = !IsLeftToRightViewLayout();
1950 0 : const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() );
1951 :
1952 0 : while ( pPageFrm )
1953 : {
1954 : // we consider the current page to be "start of row" if
1955 : // 1. it is the first page in the current row or
1956 : // 2. it is the second page in the row and the first page is an empty page in non-book view:
1957 0 : const bool bStartOfRow = pPageFrm == pStartOfRow ||
1958 0 : ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
1959 :
1960 0 : const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
1961 :
1962 : // no half doc border space for first page in each row and
1963 0 : long nPageWidth = 0;
1964 0 : long nPageHeight = 0;
1965 :
1966 0 : if ( mbBookMode )
1967 : {
1968 0 : const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
1969 :
1970 0 : nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
1971 0 : nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
1972 : }
1973 : else
1974 : {
1975 0 : if ( !pPageFrm->IsEmptyPage() )
1976 : {
1977 0 : nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
1978 0 : nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
1979 : }
1980 : }
1981 :
1982 0 : if ( !bEmptyPage )
1983 0 : ++nNumberOfPagesInRow;
1984 :
1985 : // finish current row if
1986 : // 1. in dynamic mode the current page does not fit anymore or
1987 : // 2. the current page exceeds the maximum number of columns
1988 0 : bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
1989 0 : (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
1990 :
1991 : // make sure that at least one page goes to the current row:
1992 0 : if ( !bRowFinished || bStartOfRow )
1993 : {
1994 : // current page is allowed to be in current row
1995 0 : nWidthRemain = nWidthRemain - nPageWidth;
1996 :
1997 0 : nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
1998 0 : nCurrentRowHeight = std::max( nCurrentRowHeight, nPageHeight );
1999 :
2000 0 : pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
2001 :
2002 0 : if ( !pPageFrm )
2003 0 : bRowFinished = true;
2004 : }
2005 :
2006 0 : if ( bRowFinished )
2007 : {
2008 : // pPageFrm now points to the first page in the new row or null
2009 : // pStartOfRow points to the first page in the current row
2010 :
2011 : // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2012 0 : if ( !pPageFrm && nWidthRemain > 0 )
2013 : {
2014 : // find last page in current row:
2015 0 : const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
2016 0 : while( pLastPageInCurrentRow->GetNext() )
2017 0 : pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
2018 :
2019 0 : if ( pLastPageInCurrentRow->IsEmptyPage() )
2020 0 : pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
2021 :
2022 : // check how many times the last page would still fit into the remaining space:
2023 0 : sal_uInt16 nNumberOfVirtualPages = 0;
2024 0 : const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
2025 0 : SwTwips nRemain = nWidthRemain;
2026 0 : SwTwips nVirtualPagesWidth = 0;
2027 0 : SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
2028 :
2029 0 : while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
2030 : {
2031 0 : SwTwips nLastPageWidthWithGap = nLastPageWidth;
2032 0 : if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
2033 0 : nLastPageWidthWithGap += nGapBetweenPages;
2034 :
2035 0 : if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
2036 : {
2037 0 : ++nNumberOfVirtualPages;
2038 0 : nVirtualPagesWidth += nLastPageWidthWithGap;
2039 : }
2040 0 : nRemain = nRemain - nLastPageWidthWithGap;
2041 : }
2042 :
2043 0 : nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
2044 : }
2045 :
2046 : // first page in book mode is always special:
2047 0 : if ( bFirstRow && mbBookMode )
2048 : {
2049 : // #i88036#
2050 : nCurrentRowWidth +=
2051 0 : pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2052 : }
2053 :
2054 : // center page if possible
2055 : const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
2056 0 : ( nVisWidth - nCurrentRowWidth ) / 2 :
2057 0 : 0;
2058 :
2059 : // adjust positions of pages in current row
2060 0 : long nX = nSizeDiff;
2061 :
2062 0 : const long nRowStart = nBorder + nSizeDiff;
2063 0 : const long nRowEnd = nRowStart + nCurrentRowWidth;
2064 :
2065 0 : if ( bFirstRow && mbBookMode )
2066 : {
2067 : // #i88036#
2068 0 : nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2069 : }
2070 :
2071 0 : SwPageFrm* pEndOfRow = pPageFrm;
2072 0 : SwPageFrm* pPageToAdjust = pStartOfRow;
2073 :
2074 0 : do
2075 : {
2076 0 : const SwPageFrm* pFormatPage = pPageToAdjust;
2077 0 : if ( mbBookMode )
2078 0 : pFormatPage = &pPageToAdjust->GetFormatPage();
2079 :
2080 0 : const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
2081 0 : const Point aOldPagePos = pPageToAdjust->Frm().Pos();
2082 0 : const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT;
2083 : const SwTwips nLeftPageAddOffset = bLeftSidebar ?
2084 : nSidebarWidth :
2085 0 : 0;
2086 :
2087 0 : Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
2088 0 : Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
2089 :
2090 : // RTL view layout: Calculate mirrored page position
2091 0 : if ( bRTL )
2092 : {
2093 0 : const long nXOffsetInRow = aNewPagePos.getX() - nRowStart;
2094 0 : aNewPagePos.setX(nRowEnd - nXOffsetInRow - nCurrentPageWidth);
2095 0 : aNewPagePosWithLeftOffset = aNewPagePos;
2096 0 : aNewPagePosWithLeftOffset.setX(aNewPagePosWithLeftOffset.getX() + nLeftPageAddOffset);
2097 : }
2098 :
2099 0 : if ( aNewPagePosWithLeftOffset != aOldPagePos )
2100 : {
2101 0 : lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
2102 0 : pPageToAdjust->SetCompletePaint();
2103 0 : bPageChanged = true;
2104 : }
2105 :
2106 : // calculate area covered by the current page and store to
2107 : // maPageRects. This is used e.g., for cursor setting
2108 0 : const bool bFirstColumn = pPageToAdjust == pStartOfRow;
2109 0 : const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
2110 0 : const bool bLastRow = !pEndOfRow;
2111 :
2112 0 : nMinPageLeft = std::min( nMinPageLeft, aNewPagePos.getX() );
2113 0 : nMaxPageRight = std::max( nMaxPageRight, aNewPagePos.getX() + nCurrentPageWidth);
2114 :
2115 : // border of nGapBetweenPages around the current page:
2116 0 : SwRect aPageRectWithBorders( aNewPagePos.getX() - nGapBetweenPages,
2117 : aNewPagePos.getY(),
2118 0 : pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
2119 0 : nCurrentRowHeight );
2120 :
2121 : static const long nOuterClickDiff = 1000000;
2122 :
2123 : // adjust borders for these special cases:
2124 0 : if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
2125 0 : aPageRectWithBorders.SubLeft( nOuterClickDiff );
2126 0 : if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
2127 0 : aPageRectWithBorders.AddRight( nOuterClickDiff );
2128 0 : if ( bFirstRow )
2129 0 : aPageRectWithBorders.SubTop( nOuterClickDiff );
2130 0 : if ( bLastRow )
2131 0 : aPageRectWithBorders.AddBottom( nOuterClickDiff );
2132 :
2133 0 : maPageRects.push_back( aPageRectWithBorders );
2134 :
2135 0 : nX = nX + nCurrentPageWidth;
2136 0 : pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
2137 :
2138 : // distance to next page
2139 0 : if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
2140 : {
2141 : // in book view, we add the x gap before left (even) pages:
2142 0 : if ( mbBookMode )
2143 : {
2144 0 : if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
2145 0 : nX = nX + nGapBetweenPages;
2146 : }
2147 : else
2148 : {
2149 : // in non-book view, dont add x gap before
2150 : // 1. the last empty page in a row
2151 : // 2. after an empty page
2152 0 : const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
2153 0 : ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
2154 :
2155 0 : if ( !bDontAddGap )
2156 0 : nX = nX + nGapBetweenPages;
2157 : }
2158 : }
2159 : }
2160 : while ( pPageToAdjust != pEndOfRow );
2161 :
2162 : // adjust values for root frame size
2163 0 : nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
2164 :
2165 : // start new row:
2166 0 : nCurrentRowHeight = 0;
2167 0 : nCurrentRowWidth = 0;
2168 0 : pStartOfRow = pEndOfRow;
2169 0 : nWidthRemain = nVisWidth;
2170 0 : nNumberOfPagesInRow = 0;
2171 0 : bFirstRow = false;
2172 : } // end row finished
2173 : } // end while
2174 :
2175 : // set size of root frame:
2176 0 : const Size aOldSize( Frm().SSize() );
2177 0 : const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
2178 :
2179 0 : if ( bPageChanged || aNewSize != aOldSize )
2180 : {
2181 0 : ChgSize( aNewSize );
2182 0 : ::AdjustSizeChgNotify( this );
2183 0 : Calc();
2184 :
2185 0 : SwViewShell* pSh = GetCurrShell();
2186 :
2187 0 : if ( pSh && pSh->GetDoc()->GetDocShell() )
2188 : {
2189 0 : pSh->SetFirstVisPageInvalid();
2190 0 : if (bOldCallbackActionEnabled)
2191 : {
2192 0 : pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2193 0 : pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
2194 : }
2195 : }
2196 : }
2197 :
2198 0 : maPagesArea.Pos( Frm().Pos() );
2199 0 : maPagesArea.SSize( aNewSize );
2200 0 : if ( TWIPS_MAX != nMinPageLeft )
2201 0 : maPagesArea._Left( nMinPageLeft );
2202 :
2203 0 : SetCallbackActionEnabled( bOldCallbackActionEnabled );
2204 : }
2205 :
2206 0 : bool SwRootFrm::IsLeftToRightViewLayout() const
2207 : {
2208 : // Layout direction determined by layout direction of the first page.
2209 : // #i88036#
2210 : // Only ask a non-empty page frame for its layout direction
2211 : const SwPageFrm& rPage =
2212 0 : dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
2213 0 : return !rPage.IsRightToLeft() && !rPage.IsVertical();
2214 : }
2215 :
2216 0 : const SwPageFrm& SwPageFrm::GetFormatPage() const
2217 : {
2218 0 : const SwPageFrm* pRet = this;
2219 0 : if ( IsEmptyPage() )
2220 : {
2221 0 : pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
2222 : // #i88035#
2223 : // Typically a right empty page frame has a next non-empty page frame and
2224 : // a left empty page frame has a previous non-empty page frame.
2225 : // But under certain cirsumstances this assumption is not true -
2226 : // e.g. during insertion of a left page at the end of the document right
2227 : // after a left page in an intermediate state a right empty page does not
2228 : // have a next page frame.
2229 0 : if ( pRet == 0 )
2230 : {
2231 0 : if ( OnRightPage() )
2232 : {
2233 0 : pRet = static_cast<const SwPageFrm*>( GetPrev() );
2234 : }
2235 : else
2236 : {
2237 0 : pRet = static_cast<const SwPageFrm*>( GetNext() );
2238 : }
2239 : }
2240 : OSL_ENSURE( pRet,
2241 : "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
2242 : }
2243 0 : return *pRet;
2244 : }
2245 :
2246 0 : bool SwPageFrm::IsOverHeaderFooterArea( const Point& rPt, FrameControlType &rControl ) const
2247 : {
2248 0 : long nUpperLimit = 0;
2249 0 : long nLowerLimit = 0;
2250 0 : const SwFrm* pFrm = Lower();
2251 0 : while ( pFrm )
2252 : {
2253 0 : if ( pFrm->IsBodyFrm() )
2254 : {
2255 0 : nUpperLimit = pFrm->Frm().Top();
2256 0 : nLowerLimit = pFrm->Frm().Bottom();
2257 : }
2258 0 : else if ( pFrm->IsFtnContFrm() )
2259 0 : nLowerLimit = pFrm->Frm().Bottom();
2260 :
2261 0 : pFrm = pFrm->GetNext();
2262 : }
2263 :
2264 0 : SwRect aHeaderArea( Frm().TopLeft(),
2265 0 : Size( Frm().Width(), nUpperLimit - Frm().Top() ) );
2266 :
2267 0 : if ( aHeaderArea.IsInside( rPt ) )
2268 : {
2269 0 : rControl = Header;
2270 0 : return true;
2271 : }
2272 : else
2273 : {
2274 0 : SwRect aFooterArea( Point( Frm().Left(), nLowerLimit ),
2275 0 : Size( Frm().Width(), Frm().Bottom() - nLowerLimit ) );
2276 :
2277 0 : if ( aFooterArea.IsInside( rPt ) )
2278 : {
2279 0 : rControl = Footer;
2280 0 : return true;
2281 : }
2282 : }
2283 :
2284 0 : return false;
2285 : }
2286 :
2287 0 : SwTextGridItem const* GetGridItem(SwPageFrm const*const pPage)
2288 : {
2289 0 : if (pPage && pPage->HasGrid())
2290 : {
2291 : SwTextGridItem const& rGridItem(
2292 0 : pPage->GetPageDesc()->GetMaster().GetTextGrid());
2293 0 : if (GRID_NONE != rGridItem.GetGridType())
2294 : {
2295 0 : return &rGridItem;
2296 : }
2297 : }
2298 0 : return 0;
2299 : }
2300 :
2301 0 : sal_uInt16 GetGridWidth(SwTextGridItem const& rG, SwDoc const& rDoc)
2302 : {
2303 0 : return (rDoc.IsSquaredPageMode()) ? rG.GetBaseHeight() : rG.GetBaseWidth();
2304 : }
2305 :
2306 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|