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