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