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 271 : SwBodyFrm::SwBodyFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
83 271 : SwLayoutFrm( pFmt, pSib )
84 : {
85 271 : nType = FRMC_BODY;
86 271 : }
87 :
88 : /*************************************************************************
89 : |*
90 : |* SwBodyFrm::Format()
91 : |*
92 : |*************************************************************************/
93 332 : 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 332 : if ( !bValidSize )
103 : {
104 273 : SwTwips nHeight = GetUpper()->Prt().Height();
105 273 : SwTwips nWidth = GetUpper()->Prt().Width();
106 273 : const SwFrm *pFrm = GetUpper()->Lower();
107 273 : do
108 : {
109 273 : 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 273 : pFrm = pFrm->GetNext();
117 : } while ( pFrm );
118 273 : if ( nHeight < 0 )
119 0 : nHeight = 0;
120 273 : Frm().Height( nHeight );
121 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
122 273 : if( IsVertical() && !IsVertLR() && !IsReverse() && nWidth != Frm().Width() )
123 0 : Frm().Pos().X() += Frm().Width() - nWidth;
124 273 : Frm().Width( nWidth );
125 : }
126 :
127 332 : bool bNoGrid = true;
128 332 : 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 332 : if( bNoGrid )
171 : {
172 332 : Prt().Pos().X() = Prt().Pos().Y() = 0;
173 332 : Prt().Height( Frm().Height() );
174 332 : Prt().Width( Frm().Width() );
175 : }
176 332 : bValidSize = bValidPrtArea = sal_True;
177 332 : }
178 :
179 270 : 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 270 : SwLayoutFrm::Paint(rRect);
193 270 : }
194 :
195 : /*************************************************************************
196 : |*
197 : |* SwPageFrm::SwPageFrm(), ~SwPageFrm()
198 : |*
199 : |*************************************************************************/
200 268 : 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 268 : mbLayoutInProgress( false )
207 : {
208 268 : SetDerivedVert( sal_False );
209 268 : SetDerivedR2L( sal_False );
210 268 : if( pDesc )
211 : {
212 268 : bHasGrid = sal_True;
213 268 : GETGRID( this )
214 268 : if( !pGrid )
215 268 : bHasGrid = sal_False;
216 : }
217 : else
218 0 : bHasGrid = sal_False;
219 268 : SetMaxFtnHeight( pPgDsc->GetFtnInfo().GetHeight() ?
220 268 : pPgDsc->GetFtnInfo().GetHeight() : LONG_MAX ),
221 268 : nType = FRMC_PAGE;
222 268 : bInvalidLayout = bInvalidCntnt = bInvalidSpelling = bInvalidSmartTags = bInvalidAutoCmplWrds = bInvalidWordCount = sal_True;
223 268 : bInvalidFlyLayout = bInvalidFlyCntnt = bInvalidFlyInCnt = bFtnPage = bEndNotePage = sal_False;
224 :
225 268 : ViewShell *pSh = getRootFrm()->GetCurrShell();
226 268 : const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
227 268 : 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 268 : Frm().SSize( pFmt->GetFrmSize().GetSize() );
237 :
238 : //Body-Bereich erzeugen und einsetzen, aber nur wenn ich nicht gerade
239 : //eine Leerseite bin.
240 268 : SwDoc *pDoc = pFmt->GetDoc();
241 268 : if ( sal_False == (bEmptyPage = (pFmt == pDoc->GetEmptyPageFmt())) )
242 : {
243 267 : bEmptyPage = sal_False;
244 267 : Calc(); //Damit die PrtArea stimmt.
245 267 : SwBodyFrm *pBodyFrm = new SwBodyFrm( pDoc->GetDfltFrmFmt(), this );
246 267 : pBodyFrm->ChgSize( Prt().SSize() );
247 267 : pBodyFrm->Paste( this );
248 267 : pBodyFrm->Calc(); //Damit die Spalten korrekt
249 : //eingesetzt werden koennen.
250 267 : pBodyFrm->InvalidatePos();
251 :
252 267 : if ( bBrowseMode )
253 0 : _InvalidateSize(); //Alles nur gelogen
254 :
255 : //Header/Footer einsetzen, nur rufen wenn aktiv.
256 267 : if ( pFmt->GetHeader().IsActive() )
257 26 : PrepareHeader();
258 267 : if ( pFmt->GetFooter().IsActive() )
259 22 : PrepareFooter();
260 :
261 267 : const SwFmtCol &rCol = pFmt->GetCol();
262 267 : if ( rCol.GetNumCols() > 1 )
263 : {
264 2 : const SwFmtCol aOld; //ChgColumns() verlaesst sich darauf, dass ein
265 : //Old-Wert hereingereicht wird.
266 2 : pBodyFrm->ChgColumns( aOld, rCol );
267 : }
268 : }
269 268 : }
270 :
271 225 : SwPageFrm::~SwPageFrm()
272 : {
273 : // Cleanup the header-footer controls in the SwEditWin
274 75 : ViewShell* pSh = getRootFrm()->GetCurrShell();
275 75 : SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( pSh );
276 75 : if ( pWrtSh )
277 : {
278 0 : SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
279 0 : rEditWin.GetFrameControlsManager( ).RemoveControls( this );
280 : }
281 :
282 : //FlyContainer entleeren, delete der Flys uebernimmt der Anchor
283 : //(Basisklasse SwFrm)
284 75 : 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 9 : for ( sal_uInt16 i = 0; i < pSortedObjs->Count(); ++i )
290 : {
291 5 : SwAnchoredObject* pAnchoredObj = (*pSortedObjs)[i];
292 5 : pAnchoredObj->SetPageFrm( 0L );
293 : }
294 4 : delete pSortedObjs;
295 4 : pSortedObjs = 0; //Auf 0 setzen, sonst rauchts beim Abmdelden von Flys!
296 : }
297 :
298 : //Damit der Zugriff auf zerstoerte Seiten verhindert werden kann.
299 75 : if ( !IsEmptyPage() ) //#59184# sollte fuer Leerseiten unnoetig sein.
300 : {
301 75 : SwDoc *pDoc = GetFmt() ? GetFmt()->GetDoc() : NULL;
302 75 : if( pDoc && !pDoc->IsInDtor() )
303 : {
304 0 : if ( pSh )
305 : {
306 0 : SwViewImp *pImp = pSh->Imp();
307 0 : pImp->SetFirstVisPageInvalid();
308 0 : if ( pImp->IsAction() )
309 0 : pImp->GetLayAction().SetAgain();
310 : // OD 12.02.2003 #i9719#, #105645# - retouche area of page
311 : // including border and shadow area.
312 0 : const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
313 0 : SwRect aRetoucheRect;
314 0 : SwPageFrm::GetBorderAndShadowBoundRect( Frm(), pSh, aRetoucheRect, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
315 0 : pSh->AddPaintRect( aRetoucheRect );
316 : }
317 : }
318 : }
319 150 : }
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 527 : void SwPageFrm::CheckDirection( sal_Bool bVert )
347 : {
348 : sal_uInt16 nDir =
349 527 : ((SvxFrameDirectionItem&)GetFmt()->GetFmtAttr( RES_FRAMEDIR )).GetValue();
350 527 : if( bVert )
351 : {
352 270 : 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 269 : bVertLR = 0;
356 269 : bVertical = 0;
357 : }
358 : else
359 : {
360 1 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
361 1 : 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 1 : bVertical = 1;
370 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
371 1 : if(FRMDIR_VERT_TOP_RIGHT == nDir)
372 0 : bVertLR = 0;
373 1 : else if(FRMDIR_VERT_TOP_LEFT==nDir)
374 0 : bVertLR = 1;
375 : }
376 : }
377 :
378 270 : bReverse = 0;
379 270 : bInvalidVert = 0;
380 : }
381 : else
382 : {
383 257 : if( FRMDIR_HORI_RIGHT_TOP == nDir )
384 0 : bRightToLeft = 1;
385 : else
386 257 : bRightToLeft = 0;
387 257 : bInvalidR2L = 0;
388 : }
389 527 : }
390 :
391 : /*************************************************************************
392 : |*
393 : |* SwPageFrm::PreparePage()
394 : |*
395 : |* Beschreibung Erzeugt die Spezifischen Flys zur Seite und formatiert
396 : |* generischen Cntnt
397 : |*
398 : |*************************************************************************/
399 590 : static void lcl_FormatLay( SwLayoutFrm *pLay )
400 : {
401 : //Alle LayoutFrms - nicht aber Tables, Flys o.ae. - formatieren.
402 :
403 590 : SwFrm *pTmp = pLay->Lower();
404 : //Erst die untergeordneten
405 1552 : while ( pTmp )
406 : {
407 372 : if ( pTmp->GetType() & 0x00FF )
408 323 : ::lcl_FormatLay( (SwLayoutFrm*)pTmp );
409 372 : pTmp = pTmp->GetNext();
410 : }
411 590 : pLay->Calc();
412 590 : }
413 :
414 268 : 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 508 : for ( sal_uInt16 i = 0; i < rTbl.size(); ++i )
421 : {
422 : SdrObject *pSdrObj;
423 240 : SwFrmFmt *pFmt = rTbl[i];
424 240 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
425 240 : if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
426 : {
427 0 : 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 0 : bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
441 0 : pSdrObj = 0;
442 0 : 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 0 : SwPageFrm *pPg = pPage->IsEmptyPage() ? (SwPageFrm*)pPage->GetNext() : pPage;
457 0 : if ( bSdrObj )
458 : {
459 : // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
460 : SwDrawContact *pContact =
461 0 : static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
462 0 : 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 0 : if ( pContact->GetAnchorFrm() )
475 0 : pContact->DisconnectFromLayout( false );
476 0 : 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 268 : }
496 :
497 268 : void SwPageFrm::PreparePage( sal_Bool bFtn )
498 : {
499 268 : 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 268 : ::RegistFlys( this, this );
508 :
509 268 : if ( Lower() )
510 : {
511 267 : ::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 268 : if ( !bFtn && !IsEmptyPage() )
520 : {
521 267 : SwDoc *pDoc = GetFmt()->GetDoc();
522 :
523 267 : if ( GetPrev() && ((SwPageFrm*)GetPrev())->IsEmptyPage() )
524 1 : lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), (SwPageFrm*)GetPrev() );
525 267 : lcl_MakeObjs( *pDoc->GetSpzFrmFmts(), this );
526 :
527 : //Kopf-/Fusszeilen) formatieren.
528 267 : SwLayoutFrm *pLow = (SwLayoutFrm*)Lower();
529 849 : while ( pLow )
530 : {
531 315 : 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 315 : pLow = (SwLayoutFrm*)pLow->GetNext();
541 : }
542 : }
543 268 : }
544 :
545 : /*************************************************************************
546 : |*
547 : |* SwPageFrm::Modify()
548 : |*
549 : |*************************************************************************/
550 2 : void SwPageFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
551 : {
552 2 : ViewShell *pSh = getRootFrm()->GetCurrShell();
553 2 : if ( pSh )
554 2 : pSh->SetFirstVisPageInvalid();
555 2 : sal_uInt8 nInvFlags = 0;
556 :
557 2 : if( pNew && RES_ATTRSET_CHG == pNew->Which() )
558 : {
559 0 : SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
560 0 : SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
561 0 : SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
562 0 : SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
563 0 : while( true )
564 : {
565 : _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
566 : (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
567 0 : &aOldSet, &aNewSet );
568 0 : if( aNIter.IsAtEnd() )
569 0 : break;
570 0 : aNIter.NextItem();
571 0 : aOIter.NextItem();
572 : }
573 0 : if ( aOldSet.Count() || aNewSet.Count() )
574 0 : SwLayoutFrm::Modify( &aOldSet, &aNewSet );
575 : }
576 : else
577 2 : _UpdateAttr( pOld, pNew, nInvFlags );
578 :
579 2 : 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 2 : }
596 :
597 2 : void SwPageFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
598 : sal_uInt8 &rInvFlags,
599 : SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
600 : {
601 2 : bool bClear = true;
602 2 : const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
603 2 : 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 0 : bClear = false;
723 : }
724 2 : 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 2 : }
737 :
738 : /*************************************************************************
739 : |*
740 : |* SwPageFrm::GetInfo()
741 : |*
742 : |* Beschreibung erfragt Informationen
743 : |*
744 : *************************************************************************/
745 : // erfrage vom Modify Informationen
746 2 : bool SwPageFrm::GetInfo( SfxPoolItem & rInfo ) const
747 : {
748 2 : if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
749 : {
750 : // es gibt einen PageFrm also wird er benutzt
751 2 : 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 4 : SwPageDesc *SwPageFrm::FindPageDesc()
786 : {
787 : //0.
788 4 : 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 4 : SwPageDesc *pRet = 0;
802 :
803 : //5.
804 4 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
805 4 : 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 4 : SwFrm *pFlow = FindFirstBodyCntnt();
820 4 : if ( pFlow && pFlow->IsInTab() )
821 0 : pFlow = pFlow->FindTabFrm();
822 :
823 : //1.
824 4 : if ( pFlow )
825 : {
826 3 : SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
827 3 : if ( !pTmp->IsFollow() )
828 3 : pRet = (SwPageDesc*)pFlow->GetAttrSet()->GetPageDesc().GetPageDesc();
829 : }
830 :
831 : //3. und 3.1
832 4 : 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 4 : if ( !pRet )
841 2 : pRet = GetPrev() ?
842 2 : ((SwPageFrm*)GetPrev())->GetPageDesc()->GetFollow() : 0;
843 :
844 : //4.
845 4 : if ( !pRet )
846 1 : pRet = &GetFmt()->GetDoc()->GetPageDesc( 0 );
847 :
848 :
849 : OSL_ENSURE( pRet, "Kein Descriptor gefunden." );
850 4 : return pRet;
851 : }
852 :
853 : //Wenn der RootFrm seine Groesse aendert muss benachrichtigt werden.
854 283 : void AdjustSizeChgNotify( SwRootFrm *pRoot )
855 : {
856 283 : const sal_Bool bOld = pRoot->IsSuperfluous();
857 283 : pRoot->bCheckSuperfluous = sal_False;
858 283 : ViewShell *pSh = pRoot->GetCurrShell();
859 283 : if ( pSh )
860 : {
861 283 : do
862 : {
863 283 : if( pRoot == pSh->GetLayout() )
864 : {
865 283 : pSh->SizeChgNotify();
866 283 : if ( pSh->Imp() )
867 283 : pSh->Imp()->NotifySizeChg( pRoot->Frm().SSize() );
868 : }
869 283 : pSh = (ViewShell*)pSh->GetNext();
870 283 : } while ( pSh != pRoot->GetCurrShell() );
871 : }
872 283 : pRoot->bCheckSuperfluous = bOld;
873 283 : }
874 :
875 :
876 267 : inline void SetLastPage( SwPageFrm *pPage )
877 : {
878 267 : ((SwRootFrm*)pPage->GetUpper())->pLastPage = pPage;
879 267 : }
880 :
881 : /*************************************************************************
882 : |*
883 : |* SwPageFrm::Cut()
884 : |*
885 : |*************************************************************************/
886 0 : void SwPageFrm::Cut()
887 : {
888 : // PAGES01
889 : //AdjustRootSize( CHG_CUTPAGE, 0 );
890 :
891 0 : ViewShell *pSh = getRootFrm()->GetCurrShell();
892 0 : if ( !IsEmptyPage() )
893 : {
894 0 : if ( GetNext() )
895 0 : GetNext()->InvalidatePos();
896 :
897 : //Flys deren Anker auf anderen Seiten stehen umhaengen.
898 : //DrawObjecte spielen hier keine Rolle.
899 0 : 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 0 : if ( pSh && pSh->GetWin() )
924 0 : pSh->InvalidateWindows( Frm() );
925 : }
926 :
927 : // die Seitennummer der Root runterzaehlen.
928 0 : ((SwRootFrm*)GetUpper())->DecrPhyPageNums();
929 0 : SwPageFrm *pPg = (SwPageFrm*)GetNext();
930 0 : 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 0 : ::SetLastPage( (SwPageFrm*)GetPrev() );
940 :
941 0 : SwFrm* pRootFrm = GetUpper();
942 :
943 : // Alle Verbindungen kappen.
944 0 : Remove();
945 :
946 : // PAGES01
947 0 : if ( pRootFrm )
948 0 : static_cast<SwRootFrm*>(pRootFrm)->CheckViewLayout( 0, 0 );
949 0 : }
950 :
951 : /*************************************************************************
952 : |*
953 : |* SwPageFrm::Paste()
954 : |*
955 : |*************************************************************************/
956 268 : 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 268 : InsertBefore( (SwLayoutFrm*)pParent, pSibling );
967 :
968 : // die Seitennummer am Root hochzaehlen.
969 268 : ((SwRootFrm*)GetUpper())->IncrPhyPageNums();
970 268 : if( GetPrev() )
971 32 : SetPhyPageNum( ((SwPageFrm*)GetPrev())->GetPhyPageNum() + 1 );
972 : else
973 236 : SetPhyPageNum( 1 );
974 268 : SwPageFrm *pPg = (SwPageFrm*)GetNext();
975 268 : if ( pPg )
976 : {
977 3 : while ( pPg )
978 : {
979 1 : pPg->IncrPhyPageNum(); //inline ++nPhyPageNum
980 1 : pPg->_InvalidatePos();
981 1 : pPg->InvalidateLayout();
982 1 : pPg = (SwPageFrm*)pPg->GetNext();
983 : }
984 : }
985 : else
986 267 : ::SetLastPage( this );
987 :
988 268 : if( Frm().Width() != pParent->Prt().Width() )
989 237 : _InvalidateSize();
990 :
991 268 : InvalidatePos();
992 :
993 268 : ViewShell *pSh = getRootFrm()->GetCurrShell();
994 268 : if ( pSh )
995 268 : pSh->SetFirstVisPageInvalid();
996 : // PAGES01
997 268 : getRootFrm()->CheckViewLayout( 0, 0 );
998 268 : }
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 1 : pFmtWish = pDesc->GetFirstFmt();
1103 : else
1104 1 : 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 1 : pPage->SetFrmFmt( pFmtWish );
1193 : }
1194 1 : else if ( !pFmtWish ) //6.
1195 : {
1196 : //Format mit verdrehter Logic besorgen.
1197 1 : if (bFirst)
1198 1 : pFmtWish = bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
1199 1 : if (!pFmtWish)
1200 0 : pFmtWish = bOdd ? pDesc->GetLeftFmt() : pDesc->GetRightFmt();
1201 1 : if ( pPage->GetFmt() != pFmtWish )
1202 1 : pPage->SetFrmFmt( pFmtWish );
1203 : }
1204 : #if OSL_DEBUG_LEVEL > 0
1205 : else
1206 : {
1207 : OSL_FAIL( "CheckPageDescs, missing solution" );
1208 : }
1209 : #endif
1210 : }
1211 2 : if ( bCheckEmpty )
1212 : {
1213 : //Es kann noch sein, dass die Leerseite schlicht ueberflussig ist.
1214 : //Obiger Algorithmus kann dies leider nicht feststellen.
1215 : //Eigentlich muesste die Leerseite einfach praeventiv entfernt
1216 : //werden; sie wuerde ja ggf. wieder eingefuegt.
1217 : //Die EmptyPage ist genau dann ueberfluessig, wenn die Folgeseite
1218 : //auch ohne sie auskommt. Dazu muessen wir uns die Verhaeltnisse
1219 : //genauer ansehen. Wir bestimmen den PageDesc und die virtuelle
1220 : //Seitennummer manuell.
1221 0 : SwPageFrm *pPg = (SwPageFrm*)pPage->GetNext();
1222 0 : if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
1223 : {
1224 : //Die Folgeseite hat kein Problem ein FrmFmt zu finden oder keinen
1225 : //Nachfolger, also ist die Leerseite ueberfluessig.
1226 0 : SwPageFrm *pTmp = (SwPageFrm*)pPage->GetNext();
1227 0 : pPage->Cut();
1228 0 : delete pPage;
1229 0 : if ( pStart == pPage )
1230 0 : pStart = pTmp;
1231 0 : pPage = pTmp;
1232 0 : continue;
1233 : }
1234 : }
1235 2 : pPage = (SwPageFrm*)pPage->GetNext();
1236 : }
1237 :
1238 2 : pRoot->SetAssertFlyPages();
1239 2 : pRoot->AssertPageFlys( pStart );
1240 :
1241 2 : if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFlds()) )
1242 : {
1243 1 : SwDocPosUpdate aMsgHnt( nDocPos );
1244 1 : pDoc->UpdatePageFlds( &aMsgHnt );
1245 : }
1246 :
1247 : #if OSL_DEBUG_LEVEL > 0
1248 : //Ein paar Pruefungen muessen schon erlaubt sein.
1249 :
1250 : //1. Keine zwei EmptyPages hintereinander.
1251 : //2. Alle PageDescs richtig?
1252 : bool bEmpty = false;
1253 : SwPageFrm *pPg = pStart;
1254 : while ( pPg )
1255 : {
1256 : if ( pPg->IsEmptyPage() )
1257 : {
1258 : if ( bEmpty )
1259 : {
1260 : OSL_FAIL( "Doppelte Leerseiten." );
1261 : break; //Einmal reicht.
1262 : }
1263 : bEmpty = true;
1264 : }
1265 : else
1266 : bEmpty = false;
1267 :
1268 : //MA 21. Jun. 95: Kann zu testzwecken 'rein, ist aber bei zyklen durchaus
1269 : //moeglich: Ein paar Seiten, auf der ersten 'erste Seite' anwenden,
1270 : //rechte als folge der ersten, linke als folge der rechten, rechte als
1271 : //folge der linken.
1272 : // OSL_ENSURE( pPg->GetPageDesc() == pPg->FindPageDesc(),
1273 : // "Seite mit falschem Descriptor." );
1274 :
1275 : pPg = (SwPageFrm*)pPg->GetNext();
1276 : }
1277 : #endif
1278 : }
1279 :
1280 : /*************************************************************************
1281 : |*
1282 : |* SwFrm::InsertPage()
1283 : |*
1284 : |*************************************************************************/
1285 1 : SwPageFrm *SwFrm::InsertPage( SwPageFrm *pPrevPage, sal_Bool bFtn )
1286 : {
1287 1 : SwRootFrm *pRoot = (SwRootFrm*)pPrevPage->GetUpper();
1288 1 : SwPageFrm *pSibling = (SwPageFrm*)pRoot->GetLower();
1289 1 : SwPageDesc *pDesc = pSibling->GetPageDesc();
1290 :
1291 1 : pSibling = (SwPageFrm*)pPrevPage->GetNext();
1292 : //Rechte (ungerade) oder linke (gerade) Seite einfuegen?
1293 1 : bool bNextOdd = !pPrevPage->OnRightPage();
1294 1 : bool bWishedOdd = bNextOdd;
1295 :
1296 : //Welcher PageDesc gilt?
1297 : //Bei CntntFrm der aus dem Format wenn einer angegeben ist,
1298 : //der Follow vom bereits in der PrevPage gueltigen sonst.
1299 1 : pDesc = 0;
1300 1 : if ( IsFlowFrm() && !SwFlowFrm::CastFlowFrm( this )->IsFollow() )
1301 1 : { SwFmtPageDesc &rDesc = (SwFmtPageDesc&)GetAttrSet()->GetPageDesc();
1302 1 : pDesc = rDesc.GetPageDesc();
1303 1 : if ( rDesc.GetNumOffset() )
1304 : {
1305 0 : bWishedOdd = rDesc.GetNumOffset() % 2 ? true : false;
1306 : //Die Gelegenheit nutzen wir um das Flag an der Root zu pflegen.
1307 0 : pRoot->SetVirtPageNum( sal_True );
1308 : }
1309 : }
1310 1 : if ( !pDesc )
1311 1 : pDesc = pPrevPage->GetPageDesc()->GetFollow();
1312 :
1313 : OSL_ENSURE( pDesc, "Missing PageDesc" );
1314 1 : if( !(bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1315 0 : bWishedOdd = !bWishedOdd;
1316 1 : bool bWishedFirst = pDesc != pPrevPage->GetPageDesc();
1317 1 : if (bWishedFirst && !pDesc->GetFirstFmt())
1318 0 : bWishedFirst = false;
1319 :
1320 1 : SwDoc *pDoc = pPrevPage->GetFmt()->GetDoc();
1321 : SwFrmFmt *pFmt;
1322 1 : bool bCheckPages = false;
1323 : //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben eine
1324 : //Leerseite einfuegen.
1325 1 : if( bWishedOdd != bNextOdd )
1326 0 : { pFmt = pDoc->GetEmptyPageFmt();
1327 0 : SwPageDesc *pTmpDesc = pPrevPage->GetPageDesc();
1328 0 : SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pTmpDesc );
1329 0 : pPage->Paste( pRoot, pSibling );
1330 0 : pPage->PreparePage( bFtn );
1331 : //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1332 : //Es sei denn, es ist eine Fussnotenseite
1333 0 : if ( pSibling && !pSibling->IsFtnPage() &&
1334 0 : !pSibling->FindFirstBodyCntnt() )
1335 : {
1336 0 : SwPageFrm *pDel = pSibling;
1337 0 : pSibling = (SwPageFrm*)pSibling->GetNext();
1338 0 : if ( !pDoc->GetFtnIdxs().empty() )
1339 0 : pRoot->RemoveFtns( pDel, sal_True );
1340 0 : pDel->Cut();
1341 0 : delete pDel;
1342 : }
1343 : else
1344 0 : bCheckPages = true;
1345 : }
1346 1 : if (bWishedFirst && !pDesc->IsFirstShared())
1347 0 : pFmt = pDesc->GetFirstFmt();
1348 : else
1349 1 : pFmt = bWishedOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt();
1350 : OSL_ENSURE( pFmt, "Descriptor without format." );
1351 1 : SwPageFrm *pPage = new SwPageFrm( pFmt, pRoot, pDesc );
1352 1 : pPage->Paste( pRoot, pSibling );
1353 1 : pPage->PreparePage( bFtn );
1354 : //Wenn der Sibling keinen Bodytext enthaelt kann ich ihn vernichten
1355 : //Es sei denn es ist eine Fussnotenseite.
1356 2 : if ( pSibling && !pSibling->IsFtnPage() &&
1357 1 : !pSibling->FindFirstBodyCntnt() )
1358 : {
1359 0 : SwPageFrm *pDel = pSibling;
1360 0 : pSibling = (SwPageFrm*)pSibling->GetNext();
1361 0 : if ( !pDoc->GetFtnIdxs().empty() )
1362 0 : pRoot->RemoveFtns( pDel, sal_True );
1363 0 : pDel->Cut();
1364 0 : delete pDel;
1365 : }
1366 : else
1367 1 : bCheckPages = true;
1368 :
1369 1 : if ( pSibling )
1370 : {
1371 1 : if ( bCheckPages )
1372 : {
1373 1 : CheckPageDescs( pSibling, sal_False );
1374 1 : ViewShell *pSh = getRootFrm()->GetCurrShell();
1375 1 : SwViewImp *pImp = pSh ? pSh->Imp() : 0;
1376 1 : if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
1377 : {
1378 0 : const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
1379 0 : if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
1380 0 : pImp->GetLayAction().SetCheckPageNumDirect(
1381 0 : pSibling->GetPhyPageNum() );
1382 0 : return pPage;
1383 : }
1384 : }
1385 : else
1386 0 : pRoot->AssertPageFlys( pSibling );
1387 : }
1388 :
1389 : //Fuer das Aktualisieren der Seitennummern-Felder gibt nDocPos
1390 : //die Seitenposition an, _ab_ der invalidiert werden soll.
1391 1 : ViewShell *pSh = getRootFrm()->GetCurrShell();
1392 1 : if ( !pSh || !pSh->Imp()->IsUpdateExpFlds() )
1393 : {
1394 1 : SwDocPosUpdate aMsgHnt( pPrevPage->Frm().Top() );
1395 1 : pDoc->UpdatePageFlds( &aMsgHnt );
1396 : }
1397 1 : return pPage;
1398 : }
1399 :
1400 3208 : sw::sidebarwindows::SidebarPosition SwPageFrm::SidebarPosition() const
1401 : {
1402 3208 : ViewShell *pSh = getRootFrm()->GetCurrShell();
1403 3208 : if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
1404 : {
1405 0 : return sw::sidebarwindows::SIDEBAR_RIGHT;
1406 : }
1407 : else
1408 : {
1409 3208 : const bool bLTR = getRootFrm()->IsLeftToRightViewLayout();
1410 3208 : const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
1411 3208 : const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());
1412 :
1413 : return bRightSidebar
1414 : ? sw::sidebarwindows::SIDEBAR_RIGHT
1415 3208 : : sw::sidebarwindows::SIDEBAR_LEFT;
1416 : }
1417 : }
1418 :
1419 : /*************************************************************************
1420 : |*
1421 : |* SwRootFrm::GrowFrm()
1422 : |*
1423 : |*************************************************************************/
1424 :
1425 0 : SwTwips SwRootFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1426 : {
1427 0 : if ( !bTst )
1428 0 : Frm().SSize().Height() += nDist;
1429 0 : return nDist;
1430 : }
1431 : /*************************************************************************
1432 : |*
1433 : |* SwRootFrm::ShrinkFrm()
1434 : |*
1435 : |*************************************************************************/
1436 0 : SwTwips SwRootFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
1437 : {
1438 : OSL_ENSURE( nDist >= 0, "nDist < 0." );
1439 : OSL_ENSURE( nDist <= Frm().Height(), "nDist > als aktuelle Groesse." );
1440 :
1441 0 : if ( !bTst )
1442 0 : Frm().SSize().Height() -= nDist;
1443 0 : return nDist;
1444 : }
1445 :
1446 : /*************************************************************************
1447 : |*
1448 : |* SwRootFrm::RemoveSuperfluous()
1449 : |*
1450 : |* Beschreibung: Entfernung von ueberfluessigen Seiten.
1451 : |* Arbeitet nur wenn das Flag bCheckSuperfluous gesetzt ist.
1452 : |* Definition: Eine Seite ist genau dann leer, wenn der
1453 : |* Body-Textbereich keinen CntntFrm enthaelt, aber nicht, wenn noch
1454 : |* mindestens ein Fly an der Seite klebt.
1455 : |* Die Seite ist auch dann nicht leer, wenn sie noch eine
1456 : |* Fussnote enthaelt.
1457 : |* Es muss zweimal angesetzt werden um leeren Seiten aufzuspueren:
1458 : |* - einmal fuer die Endnotenseiten.
1459 : |* - und einmal fuer die Seiten des Bodytextes.
1460 : |*
1461 : |*************************************************************************/
1462 3 : void SwRootFrm::RemoveSuperfluous()
1463 : {
1464 3 : if ( !IsSuperfluous() )
1465 3 : return;
1466 3 : bCheckSuperfluous = sal_False;
1467 :
1468 3 : SwPageFrm *pPage = GetLastPage();
1469 3 : long nDocPos = LONG_MAX;
1470 :
1471 : //Jetzt wird fuer die jeweils letzte Seite geprueft ob sie leer ist
1472 : //bei der ersten nicht leeren Seite wird die Schleife beendet.
1473 3 : do
1474 : {
1475 3 : bool bExistEssentialObjs = ( 0 != pPage->GetSortedObjs() );
1476 3 : if ( bExistEssentialObjs )
1477 : {
1478 : //Nur weil die Seite Flys hat sind wir noch lange nicht fertig,
1479 : //denn wenn alle Flys an generischem Inhalt haengen, so ist sie
1480 : //trotzdem ueberfluessig (Ueberpruefung auf DocBody sollte reichen).
1481 : // OD 19.06.2003 #108784# - consider that drawing objects in
1482 : // header/footer are supported now.
1483 3 : bool bOnlySuperfluosObjs = true;
1484 3 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1485 8 : for ( sal_uInt16 i = 0; bOnlySuperfluosObjs && i < rObjs.Count(); ++i )
1486 : {
1487 : // #i28701#
1488 5 : SwAnchoredObject* pAnchoredObj = rObjs[i];
1489 : // OD 2004-01-19 #110582# - do not consider hidden objects
1490 25 : if ( pPage->GetFmt()->GetDoc()->IsVisibleLayerId(
1491 15 : pAnchoredObj->GetDrawObj()->GetLayer() ) &&
1492 5 : !pAnchoredObj->GetAnchorFrm()->FindFooterOrHeader() )
1493 : {
1494 0 : bOnlySuperfluosObjs = false;
1495 : }
1496 : }
1497 3 : bExistEssentialObjs = !bOnlySuperfluosObjs;
1498 : }
1499 :
1500 : // OD 19.06.2003 #108784# - optimization: check first, if essential objects
1501 : // exists.
1502 3 : const SwLayoutFrm* pBody = 0;
1503 12 : if ( bExistEssentialObjs ||
1504 3 : pPage->FindFtnCont() ||
1505 3 : ( 0 != ( pBody = pPage->FindBodyCont() ) &&
1506 3 : ( pBody->ContainsCntnt() ||
1507 : // #i47580#
1508 : // Do not delete page if there's an empty tabframe
1509 : // left. I think it might be correct to use ContainsAny()
1510 : // instead of ContainsCntnt() to cover the empty-table-case,
1511 : // but I'm not fully sure, since ContainsAny() also returns
1512 : // SectionFrames. Therefore I prefer to do it the safe way:
1513 0 : ( pBody->Lower() && pBody->Lower()->IsTabFrm() ) ) ) )
1514 : {
1515 3 : if ( pPage->IsFtnPage() )
1516 : {
1517 0 : while ( pPage->IsFtnPage() )
1518 : {
1519 0 : pPage = (SwPageFrm*)pPage->GetPrev();
1520 : OSL_ENSURE( pPage, "Nur noch Endnotenseiten uebrig." );
1521 : }
1522 0 : continue;
1523 : }
1524 : else
1525 3 : pPage = 0;
1526 : }
1527 :
1528 3 : if ( pPage )
1529 : {
1530 0 : SwPageFrm *pEmpty = pPage;
1531 0 : pPage = (SwPageFrm*)pPage->GetPrev();
1532 0 : if ( !GetFmt()->GetDoc()->GetFtnIdxs().empty() )
1533 0 : RemoveFtns( pEmpty, sal_True );
1534 0 : pEmpty->Cut();
1535 0 : delete pEmpty;
1536 0 : nDocPos = pPage ? pPage->Frm().Top() : 0;
1537 : }
1538 : } while ( pPage );
1539 :
1540 3 : ViewShell *pSh = getRootFrm()->GetCurrShell();
1541 3 : if ( nDocPos != LONG_MAX &&
1542 0 : (!pSh || !pSh->Imp()->IsUpdateExpFlds()) )
1543 : {
1544 0 : SwDocPosUpdate aMsgHnt( nDocPos );
1545 0 : GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
1546 : }
1547 : }
1548 :
1549 : /*************************************************************************
1550 : |*
1551 : |* SwRootFrm::AssertFlyPages()
1552 : |*
1553 : |* Beschreibung Stellt sicher, dass genuegend Seiten vorhanden
1554 : |* sind, damit alle Seitengebundenen Rahmen und DrawObject
1555 : |* untergebracht sind.
1556 : |*
1557 : |*************************************************************************/
1558 237 : void SwRootFrm::AssertFlyPages()
1559 : {
1560 237 : if ( !IsAssertFlyPages() )
1561 237 : return;
1562 237 : bAssertFlyPages = sal_False;
1563 :
1564 237 : SwDoc *pDoc = GetFmt()->GetDoc();
1565 237 : const SwFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1566 :
1567 : //Auf welche Seite will der 'letzte' Fly?
1568 237 : sal_uInt16 nMaxPg = 0;
1569 : sal_uInt16 i;
1570 :
1571 471 : for ( i = 0; i < pTbl->size(); ++i )
1572 : {
1573 234 : const SwFmtAnchor &rAnch = (*pTbl)[i]->GetAnchor();
1574 234 : if ( !rAnch.GetCntntAnchor() && nMaxPg < rAnch.GetPageNum() )
1575 0 : nMaxPg = rAnch.GetPageNum();
1576 : }
1577 : //Wieviele Seiten haben wir derzeit?
1578 237 : SwPageFrm *pPage = (SwPageFrm*)Lower();
1579 538 : while ( pPage && pPage->GetNext() &&
1580 32 : !((SwPageFrm*)pPage->GetNext())->IsFtnPage() )
1581 : {
1582 32 : pPage = (SwPageFrm*)pPage->GetNext();
1583 : }
1584 :
1585 237 : if ( nMaxPg > pPage->GetPhyPageNum() )
1586 : {
1587 : //Die Seiten werden ausgehend von der letzten Seite konsequent
1588 : //nach den Regeln der PageDescs weitergefuehrt.
1589 0 : sal_Bool bOdd = pPage->GetPhyPageNum() % 2 ? sal_True : sal_False;
1590 0 : SwPageDesc *pDesc = pPage->GetPageDesc();
1591 0 : SwFrm *pSibling = pPage->GetNext();
1592 0 : for ( i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
1593 : {
1594 0 : if ( !(bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) )
1595 : {
1596 : //Leerseite einfuegen, die Flys werden aber erst von
1597 : //der naechsten Seite aufgenommen!
1598 0 : pPage = new SwPageFrm( pDoc->GetEmptyPageFmt(), this, pDesc );
1599 0 : pPage->Paste( this, pSibling );
1600 0 : pPage->PreparePage( sal_False );
1601 0 : bOdd = bOdd ? sal_False : sal_True;
1602 0 : ++i;
1603 : }
1604 : pPage = new
1605 : SwPageFrm( (bOdd ? pDesc->GetRightFmt() :
1606 0 : pDesc->GetLeftFmt()), this, pDesc );
1607 0 : pPage->Paste( this, pSibling );
1608 0 : pPage->PreparePage( sal_False );
1609 0 : bOdd = bOdd ? sal_False : sal_True;
1610 0 : pDesc = pDesc->GetFollow();
1611 : }
1612 : //Jetzt koennen die Endnotenseiten natuerlich wieder krumm sein;
1613 : //in diesem Fall werden sie vernichtet.
1614 0 : if ( !pDoc->GetFtnIdxs().empty() )
1615 : {
1616 0 : pPage = (SwPageFrm*)Lower();
1617 0 : while ( pPage && !pPage->IsFtnPage() )
1618 0 : pPage = (SwPageFrm*)pPage->GetNext();
1619 :
1620 0 : if ( pPage )
1621 : {
1622 0 : SwPageDesc *pTmpDesc = pPage->FindPageDesc();
1623 0 : bOdd = pPage->OnRightPage();
1624 0 : if ( pPage->GetFmt() !=
1625 : (bOdd ? pTmpDesc->GetRightFmt() : pTmpDesc->GetLeftFmt()) )
1626 0 : RemoveFtns( pPage, sal_False, sal_True );
1627 : }
1628 : }
1629 : }
1630 : }
1631 :
1632 : /*************************************************************************
1633 : |*
1634 : |* SwRootFrm::AssertPageFlys()
1635 : |*
1636 : |* Beschreibung Stellt sicher, dass ab der uebergebenen Seite
1637 : |* auf allen Seiten die Seitengebunden Objecte auf der richtigen
1638 : |* Seite (Seitennummer stehen).
1639 : |*
1640 : |*************************************************************************/
1641 2 : void SwRootFrm::AssertPageFlys( SwPageFrm *pPage )
1642 : {
1643 6 : while ( pPage )
1644 : {
1645 2 : if ( pPage->GetSortedObjs() )
1646 : {
1647 0 : pPage->GetSortedObjs();
1648 0 : for ( int i = 0;
1649 0 : pPage->GetSortedObjs() && sal_uInt16(i) < pPage->GetSortedObjs()->Count();
1650 : ++i)
1651 : {
1652 : // #i28701#
1653 0 : SwFrmFmt& rFmt = (*pPage->GetSortedObjs())[i]->GetFrmFmt();
1654 0 : const SwFmtAnchor &rAnch = rFmt.GetAnchor();
1655 0 : const sal_uInt16 nPg = rAnch.GetPageNum();
1656 0 : if ((rAnch.GetAnchorId() == FLY_AT_PAGE) &&
1657 0 : nPg != pPage->GetPhyPageNum() )
1658 : {
1659 : //Das er auf der falschen Seite steht muss noch nichts
1660 : //heissen, wenn er eigentlich auf der Vorseite
1661 : //stehen will und diese eine EmptyPage ist.
1662 0 : if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
1663 0 : ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage()) )
1664 : {
1665 : //Umhaengen kann er sich selbst, indem wir ihm
1666 : //einfach ein Modify mit seinem AnkerAttr schicken.
1667 : #if OSL_DEBUG_LEVEL > 1
1668 : const sal_uInt32 nCnt = pPage->GetSortedObjs()->Count();
1669 : rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1670 : OSL_ENSURE( !pPage->GetSortedObjs() ||
1671 : nCnt != pPage->GetSortedObjs()->Count(),
1672 : "Object couldn't be reattached!" );
1673 : #else
1674 0 : rFmt.NotifyClients( 0, (SwFmtAnchor*)&rAnch );
1675 : #endif
1676 0 : --i;
1677 : }
1678 : }
1679 : }
1680 : }
1681 2 : pPage = (SwPageFrm*)pPage->GetNext();
1682 : }
1683 2 : }
1684 :
1685 : /*************************************************************************
1686 : |*
1687 : |* SwRootFrm::ChgSize()
1688 : |*
1689 : |*************************************************************************/
1690 283 : Size SwRootFrm::ChgSize( const Size& aNewSize )
1691 : {
1692 283 : Frm().SSize() = aNewSize;
1693 283 : _InvalidatePrt();
1694 283 : bFixSize = sal_False;
1695 283 : return Frm().SSize();
1696 : }
1697 :
1698 : /*************************************************************************
1699 : |*
1700 : |* SwRootFrm::MakeAll()
1701 : |*
1702 : |*************************************************************************/
1703 519 : void SwRootFrm::MakeAll()
1704 : {
1705 519 : if ( !bValidPos )
1706 236 : { bValidPos = sal_True;
1707 236 : aFrm.Pos().X() = aFrm.Pos().Y() = DOCUMENTBORDER;
1708 : }
1709 519 : if ( !bValidPrtArea )
1710 519 : { bValidPrtArea = sal_True;
1711 519 : aPrt.Pos().X() = aPrt.Pos().Y() = 0;
1712 519 : aPrt.SSize( aFrm.SSize() );
1713 : }
1714 519 : if ( !bValidSize )
1715 : //SSize wird von den Seiten (Cut/Paste) eingestellt.
1716 236 : bValidSize = sal_True;
1717 519 : }
1718 :
1719 : /*************************************************************************
1720 : |*
1721 : |* SwRootFrm::ImplInvalidateBrowseWidth()
1722 : |*
1723 : |*************************************************************************/
1724 0 : void SwRootFrm::ImplInvalidateBrowseWidth()
1725 : {
1726 0 : bBrowseWidthValid = sal_False;
1727 0 : SwFrm *pPg = Lower();
1728 0 : while ( pPg )
1729 : {
1730 0 : pPg->InvalidateSize();
1731 0 : pPg = pPg->GetNext();
1732 : }
1733 0 : }
1734 :
1735 : /*************************************************************************
1736 : |*
1737 : |* SwRootFrm::ImplCalcBrowseWidth()
1738 : |*
1739 : |*************************************************************************/
1740 0 : void SwRootFrm::ImplCalcBrowseWidth()
1741 : {
1742 : OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
1743 : "CalcBrowseWidth and not in BrowseView" );
1744 :
1745 : //Die (minimale) Breite wird von Rahmen, Tabellen und Zeichenobjekten
1746 : //bestimmt. Die Breite wird nicht anhand ihrer aktuellen Groessen bestimmt,
1747 : //sondern anhand der Attribute. Es interessiert also nicht wie breit sie
1748 : //sind, sondern wie breit sie sein wollen.
1749 : //Rahmen und Zeichenobjekte innerhalb ander Objekte (Rahmen, Tabellen)
1750 : //Zaehlen nicht.
1751 : //Seitenraender und Spalten werden hier nicht beruecksichtigt.
1752 :
1753 0 : SwFrm *pFrm = ContainsCntnt();
1754 0 : while ( pFrm && !pFrm->IsInDocBody() )
1755 0 : pFrm = ((SwCntntFrm*)pFrm)->GetNextCntntFrm();
1756 0 : if ( !pFrm )
1757 0 : return;
1758 :
1759 0 : bBrowseWidthValid = sal_True;
1760 0 : ViewShell *pSh = getRootFrm()->GetCurrShell();
1761 : nBrowseWidth = pSh
1762 : ? MINLAY + 2 * pSh->GetOut()->
1763 0 : PixelToLogic( pSh->GetBrowseBorder() ).Width()
1764 0 : : 5000;
1765 0 : do
1766 : {
1767 0 : if ( pFrm->IsInTab() )
1768 0 : pFrm = pFrm->FindTabFrm();
1769 :
1770 0 : if ( pFrm->IsTabFrm() &&
1771 0 : !((SwLayoutFrm*)pFrm)->GetFmt()->GetFrmSize().GetWidthPercent() )
1772 : {
1773 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1774 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
1775 0 : const SwFmtHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
1776 0 : long nWidth = rAttrs.GetSize().Width();
1777 0 : if ( nWidth < USHRT_MAX-2000 && //-2000, weil bei Randeinstellung per
1778 : //Zuppeln das USHRT_MAX verlorengeht!
1779 0 : text::HoriOrientation::FULL != rHori.GetHoriOrient() )
1780 : {
1781 : const SwHTMLTableLayout *pLayoutInfo =
1782 : ((const SwTabFrm *)pFrm)->GetTable()
1783 0 : ->GetHTMLTableLayout();
1784 0 : if ( pLayoutInfo )
1785 0 : nWidth = Min( nWidth, pLayoutInfo->GetBrowseWidthMin() );
1786 :
1787 0 : switch ( rHori.GetHoriOrient() )
1788 : {
1789 : case text::HoriOrientation::NONE:
1790 : // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1791 0 : nWidth += rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm );
1792 0 : break;
1793 : case text::HoriOrientation::LEFT_AND_WIDTH:
1794 0 : nWidth += rAttrs.CalcLeft( pFrm );
1795 0 : break;
1796 : default:
1797 0 : break;
1798 :
1799 : }
1800 0 : nBrowseWidth = Max( nBrowseWidth, nWidth );
1801 0 : }
1802 : }
1803 0 : else if ( pFrm->GetDrawObjs() )
1804 : {
1805 0 : for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1806 : {
1807 : // #i28701#
1808 0 : SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1809 0 : const SwFrmFmt& rFmt = pAnchoredObj->GetFrmFmt();
1810 0 : const sal_Bool bFly = pAnchoredObj->ISA(SwFlyFrm);
1811 0 : if ((bFly && (FAR_AWAY == pAnchoredObj->GetObjRect().Width()))
1812 0 : || rFmt.GetFrmSize().GetWidthPercent())
1813 : {
1814 0 : continue;
1815 : }
1816 :
1817 0 : long nWidth = 0;
1818 0 : switch ( rFmt.GetAnchor().GetAnchorId() )
1819 : {
1820 : case FLY_AS_CHAR:
1821 0 : nWidth = bFly ? rFmt.GetFrmSize().GetWidth() :
1822 0 : pAnchoredObj->GetObjRect().Width();
1823 0 : break;
1824 : case FLY_AT_PARA:
1825 : {
1826 : // #i33170#
1827 : // Reactivated old code because
1828 : // nWidth = pAnchoredObj->GetObjRect().Right()
1829 : // gives wrong results for objects that are still
1830 : // at position FAR_AWAY.
1831 0 : if ( bFly )
1832 : {
1833 0 : nWidth = rFmt.GetFrmSize().GetWidth();
1834 0 : const SwFmtHoriOrient &rHori = rFmt.GetHoriOrient();
1835 0 : switch ( rHori.GetHoriOrient() )
1836 : {
1837 : case text::HoriOrientation::NONE:
1838 0 : nWidth += rHori.GetPos();
1839 0 : break;
1840 : case text::HoriOrientation::INSIDE:
1841 : case text::HoriOrientation::LEFT:
1842 0 : if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
1843 0 : nWidth += pFrm->Prt().Left();
1844 0 : break;
1845 : default:
1846 0 : break;
1847 : }
1848 : }
1849 : else
1850 : //Fuer Zeichenobjekte ist die Auswahl sehr klein,
1851 : //weil sie keine Attribute haben, also durch ihre
1852 : //aktuelle Groesse bestimmt werden.
1853 0 : nWidth = pAnchoredObj->GetObjRect().Right() -
1854 0 : pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
1855 : }
1856 0 : break;
1857 : default: /* do nothing */;
1858 : }
1859 0 : nBrowseWidth = Max( nBrowseWidth, nWidth );
1860 : }
1861 : }
1862 0 : pFrm = pFrm->FindNextCnt();
1863 : } while ( pFrm );
1864 : }
1865 :
1866 : /*************************************************************************
1867 : |*
1868 : |* SwRootFrm::StartAllAction()
1869 : |*
1870 : |*************************************************************************/
1871 :
1872 52 : void SwRootFrm::StartAllAction()
1873 : {
1874 52 : ViewShell *pSh = GetCurrShell();
1875 52 : if ( pSh )
1876 52 : do
1877 52 : { if ( pSh->ISA( SwCrsrShell ) )
1878 52 : ((SwCrsrShell*)pSh)->StartAction();
1879 : else
1880 0 : pSh->StartAction();
1881 52 : pSh = (ViewShell*)pSh->GetNext();
1882 :
1883 52 : } while ( pSh != GetCurrShell() );
1884 52 : }
1885 :
1886 52 : void SwRootFrm::EndAllAction( sal_Bool bVirDev )
1887 : {
1888 52 : ViewShell *pSh = GetCurrShell();
1889 52 : if ( pSh )
1890 52 : do
1891 : {
1892 52 : const sal_Bool bOldEndActionByVirDev = pSh->IsEndActionByVirDev();
1893 52 : pSh->SetEndActionByVirDev( bVirDev );
1894 52 : if ( pSh->ISA( SwCrsrShell ) )
1895 : {
1896 52 : ((SwCrsrShell*)pSh)->EndAction();
1897 52 : ((SwCrsrShell*)pSh)->CallChgLnk();
1898 52 : if ( pSh->ISA( SwFEShell ) )
1899 52 : ((SwFEShell*)pSh)->SetChainMarker();
1900 : }
1901 : else
1902 0 : pSh->EndAction();
1903 52 : pSh->SetEndActionByVirDev( bOldEndActionByVirDev );
1904 52 : pSh = (ViewShell*)pSh->GetNext();
1905 :
1906 52 : } while ( pSh != GetCurrShell() );
1907 52 : }
1908 :
1909 2 : void SwRootFrm::UnoRemoveAllActions()
1910 : {
1911 2 : ViewShell *pSh = GetCurrShell();
1912 2 : if ( pSh )
1913 2 : do
1914 : {
1915 : // #i84729#
1916 : // No end action, if <ViewShell> instance is currently in its end action.
1917 : // Recursives calls to <::EndAction()> are not allowed.
1918 2 : if ( !pSh->IsInEndAction() )
1919 : {
1920 : OSL_ENSURE(!pSh->GetRestoreActions(), "Restore action count is already set!");
1921 2 : sal_Bool bCrsr = pSh->ISA( SwCrsrShell );
1922 2 : sal_Bool bFE = pSh->ISA( SwFEShell );
1923 2 : sal_uInt16 nRestore = 0;
1924 4 : while( pSh->ActionCount() )
1925 : {
1926 0 : if( bCrsr )
1927 : {
1928 0 : ((SwCrsrShell*)pSh)->EndAction();
1929 0 : ((SwCrsrShell*)pSh)->CallChgLnk();
1930 0 : if ( bFE )
1931 0 : ((SwFEShell*)pSh)->SetChainMarker();
1932 : }
1933 : else
1934 0 : pSh->EndAction();
1935 0 : nRestore++;
1936 : }
1937 2 : pSh->SetRestoreActions(nRestore);
1938 : }
1939 2 : pSh->LockView(sal_True);
1940 2 : pSh = (ViewShell*)pSh->GetNext();
1941 :
1942 2 : } while ( pSh != GetCurrShell() );
1943 2 : }
1944 :
1945 2 : void SwRootFrm::UnoRestoreAllActions()
1946 : {
1947 2 : ViewShell *pSh = GetCurrShell();
1948 2 : if ( pSh )
1949 2 : do
1950 : {
1951 2 : sal_uInt16 nActions = pSh->GetRestoreActions();
1952 4 : while( nActions-- )
1953 : {
1954 0 : if ( pSh->ISA( SwCrsrShell ) )
1955 0 : ((SwCrsrShell*)pSh)->StartAction();
1956 : else
1957 0 : pSh->StartAction();
1958 : }
1959 2 : pSh->SetRestoreActions(0);
1960 2 : pSh->LockView(sal_False);
1961 2 : pSh = (ViewShell*)pSh->GetNext();
1962 :
1963 2 : } while ( pSh != GetCurrShell() );
1964 2 : }
1965 :
1966 : // PAGES01: Helper functions for SwRootFrm::CheckViewLayout
1967 : static void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset );
1968 :
1969 812 : static void lcl_MoveAllLowerObjs( SwFrm* pFrm, const Point& rOffset )
1970 : {
1971 812 : SwSortedObjs* pSortedObj = 0;
1972 812 : const bool bPage = pFrm->IsPageFrm();
1973 :
1974 812 : if ( bPage )
1975 288 : pSortedObj = static_cast<SwPageFrm*>(pFrm)->GetSortedObjs();
1976 : else
1977 524 : pSortedObj = pFrm->GetDrawObjs();
1978 :
1979 829 : for ( sal_uInt16 i = 0; pSortedObj && i < pSortedObj->Count(); ++i)
1980 : {
1981 17 : SwAnchoredObject* pAnchoredObj = (*pSortedObj)[i];
1982 :
1983 17 : const SwFrmFmt& rObjFmt = pAnchoredObj->GetFrmFmt();
1984 17 : const SwFmtAnchor& rAnchor = rObjFmt.GetAnchor();
1985 :
1986 : // all except from the as character anchored objects are moved
1987 : // when processing the page frame:
1988 17 : const bool bAsChar = (rAnchor.GetAnchorId() == FLY_AS_CHAR);
1989 17 : if ( !bPage && !bAsChar )
1990 11 : continue;
1991 :
1992 6 : SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );
1993 :
1994 6 : if ( pAnchoredObj->ISA(SwFlyFrm) )
1995 : {
1996 6 : SwFlyFrm* pFlyFrm( static_cast<SwFlyFrm*>(pAnchoredObj) );
1997 6 : lcl_MoveAllLowers( pFlyFrm, rOffset );
1998 6 : pFlyFrm->NotifyDrawObj();
1999 : // --> let the active embedded object be moved
2000 6 : if ( pFlyFrm->Lower() )
2001 : {
2002 6 : if ( pFlyFrm->Lower()->IsNoTxtFrm() )
2003 : {
2004 0 : SwCntntFrm* pCntntFrm = static_cast<SwCntntFrm*>(pFlyFrm->Lower());
2005 0 : SwRootFrm* pRoot = pFlyFrm->Lower()->getRootFrm();
2006 0 : ViewShell *pSh = pRoot ? pRoot->GetCurrShell() : 0;
2007 0 : if ( pSh )
2008 : {
2009 0 : SwOLENode* pNode = pCntntFrm->GetNode()->GetOLENode();
2010 0 : if ( pNode )
2011 : {
2012 0 : svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
2013 0 : if ( xObj.is() )
2014 : {
2015 0 : ViewShell* pTmp = pSh;
2016 0 : do
2017 : {
2018 0 : SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( pTmp );
2019 0 : if ( pFEShell )
2020 0 : pFEShell->MoveObjectIfActive( xObj, rOffset );
2021 0 : pTmp = static_cast<ViewShell*>( pTmp->GetNext() );
2022 : } while( pTmp != pSh );
2023 : }
2024 : }
2025 : }
2026 : }
2027 : }
2028 : }
2029 0 : else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
2030 : {
2031 0 : SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );
2032 :
2033 : // don't touch objects that are not yet positioned:
2034 0 : const bool bNotYetPositioned = pAnchoredDrawObj->NotYetPositioned();
2035 0 : if ( bNotYetPositioned )
2036 0 : continue;
2037 :
2038 0 : const Point aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
2039 0 : const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
2040 0 : pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
2041 0 : pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );
2042 :
2043 : // clear contour cache
2044 0 : if ( pAnchoredDrawObj->GetFrmFmt().GetSurround().IsContour() )
2045 0 : ClrContourCache( pAnchoredDrawObj->GetDrawObj() );
2046 : }
2047 : // #i92511#
2048 : // cache for object rectangle inclusive spaces has to be invalidated.
2049 6 : pAnchoredObj->InvalidateObjRectWithSpaces();
2050 6 : }
2051 812 : }
2052 :
2053 812 : static void lcl_MoveAllLowers( SwFrm* pFrm, const Point& rOffset )
2054 : {
2055 812 : const SwRect aFrm( pFrm->Frm() );
2056 :
2057 : // first move the current frame
2058 812 : pFrm->Frm().Pos() += rOffset;
2059 :
2060 : // Don't forget accessibility:
2061 812 : if( pFrm->IsAccessibleFrm() )
2062 : {
2063 514 : SwRootFrm *pRootFrm = pFrm->getRootFrm();
2064 514 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
2065 0 : pRootFrm->GetCurrShell() )
2066 : {
2067 0 : pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
2068 : }
2069 : }
2070 :
2071 : // the move any objects
2072 812 : lcl_MoveAllLowerObjs( pFrm, rOffset );
2073 :
2074 : // finally, for layout frames we have to call this function recursively:
2075 812 : if ( pFrm->ISA(SwLayoutFrm) )
2076 : {
2077 671 : SwFrm* pLowerFrm = pFrm->GetLower();
2078 1860 : while ( pLowerFrm )
2079 : {
2080 518 : lcl_MoveAllLowers( pLowerFrm, rOffset );
2081 518 : pLowerFrm = pLowerFrm->GetNext();
2082 : }
2083 : }
2084 812 : }
2085 :
2086 : // PAGES01: Calculate how the pages have to be positioned
2087 1603 : void SwRootFrm::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
2088 : {
2089 : // #i91432#
2090 : // No calculation of page positions, if only an empty page is present.
2091 : // This situation occurs when <SwRootFrm> instance is in construction
2092 : // and the document contains only left pages.
2093 3071 : if ( Lower()->GetNext() == 0 &&
2094 1468 : static_cast<SwPageFrm*>(Lower())->IsEmptyPage() )
2095 : {
2096 : return;
2097 : }
2098 :
2099 1603 : if ( !pVisArea )
2100 : {
2101 : // no early return for bNewPage
2102 270 : if ( mnViewWidth < 0 )
2103 236 : mnViewWidth = 0;
2104 : }
2105 : else
2106 : {
2107 : OSL_ENSURE( pViewOpt, "CheckViewLayout required ViewOptions" );
2108 :
2109 1333 : const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns();
2110 1333 : const bool bBookMode = pViewOpt->IsViewLayoutBookMode();
2111 :
2112 1333 : if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
2113 : return;
2114 :
2115 226 : mnColumns = nColumns;
2116 226 : mbBookMode = bBookMode;
2117 226 : mnViewWidth = pVisArea->Width();
2118 226 : mbSidebarChanged = false;
2119 : }
2120 :
2121 496 : if( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE ) )
2122 : {
2123 0 : mnColumns = 1;
2124 0 : mbBookMode = false;
2125 : }
2126 :
2127 496 : Calc();
2128 :
2129 496 : const sal_Bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
2130 496 : SetCallbackActionEnabled( sal_False );
2131 :
2132 496 : maPageRects.clear();
2133 :
2134 496 : const long nBorder = Frm().Pos().X();
2135 496 : const long nVisWidth = mnViewWidth - 2 * nBorder;
2136 496 : const long nGapBetweenPages = GAPBETWEENPAGES;
2137 :
2138 : // check how many pages fit into the first page layout row:
2139 496 : SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(Lower());
2140 :
2141 : // will contain the number of pages per row. 0 means that
2142 : // the page does not fit.
2143 496 : long nWidthRemain = nVisWidth;
2144 :
2145 : // after one row has been processed, these variables contain
2146 : // the width of the row and the maxium of the page heights
2147 496 : long nCurrentRowHeight = 0;
2148 496 : long nCurrentRowWidth = 0;
2149 :
2150 : // these variables are used to finally set the size of the
2151 : // root frame
2152 496 : long nSumRowHeight = 0;
2153 496 : SwTwips nMinPageLeft = TWIPS_MAX;
2154 496 : SwTwips nMaxPageRight = 0;
2155 496 : SwPageFrm* pStartOfRow = pPageFrm;
2156 496 : sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
2157 496 : bool bFirstRow = true;
2158 :
2159 496 : bool bPageChanged = false;
2160 496 : const bool bRTL = !IsLeftToRightViewLayout();
2161 496 : const SwTwips nSidebarWidth = SwPageFrm::GetSidebarBorderWidth( GetCurrShell() );
2162 :
2163 1600 : while ( pPageFrm )
2164 : {
2165 : // we consider the current page to be "start of row" if
2166 : // 1. it is the first page in the current row or
2167 : // 2. it is the second page in the row and the first page is an empty page in non-book view:
2168 : const bool bStartOfRow = pPageFrm == pStartOfRow ||
2169 608 : ( pStartOfRow->IsEmptyPage() && pPageFrm == pStartOfRow->GetNext() && !mbBookMode );
2170 :
2171 608 : const bool bEmptyPage = pPageFrm->IsEmptyPage() && !mbBookMode;
2172 :
2173 : // no half doc border space for first page in each row and
2174 608 : long nPageWidth = 0;
2175 608 : long nPageHeight = 0;
2176 :
2177 608 : if ( mbBookMode )
2178 : {
2179 0 : const SwFrm& rFormatPage = pPageFrm->GetFormatPage();
2180 :
2181 0 : nPageWidth = rFormatPage.Frm().Width() + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrm->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
2182 0 : nPageHeight = rFormatPage.Frm().Height() + nGapBetweenPages;
2183 : }
2184 : else
2185 : {
2186 608 : if ( !pPageFrm->IsEmptyPage() )
2187 : {
2188 604 : nPageWidth = pPageFrm->Frm().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
2189 604 : nPageHeight = pPageFrm->Frm().Height() + nGapBetweenPages;
2190 : }
2191 : }
2192 :
2193 608 : if ( !bEmptyPage )
2194 604 : ++nNumberOfPagesInRow;
2195 :
2196 : // finish current row if
2197 : // 1. in dynamic mode the current page does not fit anymore or
2198 : // 2. the current page exceeds the maximum number of columns
2199 : bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
2200 608 : (0 != mnColumns && mnColumns < nNumberOfPagesInRow);
2201 :
2202 : // make sure that at least one page goes to the current row:
2203 608 : if ( !bRowFinished || bStartOfRow )
2204 : {
2205 : // current page is allowed to be in current row
2206 598 : nWidthRemain = nWidthRemain - nPageWidth;
2207 :
2208 598 : nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
2209 598 : nCurrentRowHeight = Max( nCurrentRowHeight, nPageHeight );
2210 :
2211 598 : pPageFrm = static_cast<SwPageFrm*>(pPageFrm->GetNext());
2212 :
2213 598 : if ( !pPageFrm )
2214 496 : bRowFinished = true;
2215 : }
2216 :
2217 608 : if ( bRowFinished )
2218 : {
2219 : // pPageFrm now points to the first page in the new row or null
2220 : // pStartOfRow points to the first page in the current row
2221 :
2222 : // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
2223 598 : if ( !pPageFrm && nWidthRemain > 0 )
2224 : {
2225 : // find last page in current row:
2226 9 : const SwPageFrm* pLastPageInCurrentRow = pStartOfRow;
2227 18 : while( pLastPageInCurrentRow->GetNext() )
2228 0 : pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetNext());
2229 :
2230 9 : if ( pLastPageInCurrentRow->IsEmptyPage() )
2231 0 : pLastPageInCurrentRow = static_cast<const SwPageFrm*>(pLastPageInCurrentRow->GetPrev());
2232 :
2233 : // check how many times the last page would still fit into the remaining space:
2234 9 : sal_uInt16 nNumberOfVirtualPages = 0;
2235 9 : const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
2236 9 : SwTwips nRemain = nWidthRemain;
2237 9 : SwTwips nVirtualPagesWidth = 0;
2238 9 : SwTwips nLastPageWidth = pLastPageInCurrentRow->Frm().Width() + nSidebarWidth;
2239 :
2240 30 : while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
2241 : {
2242 12 : SwTwips nLastPageWidthWithGap = nLastPageWidth;
2243 12 : if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
2244 12 : nLastPageWidthWithGap += nGapBetweenPages;
2245 :
2246 12 : if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
2247 : {
2248 3 : ++nNumberOfVirtualPages;
2249 3 : nVirtualPagesWidth += nLastPageWidthWithGap;
2250 : }
2251 12 : nRemain = nRemain - nLastPageWidthWithGap;
2252 : }
2253 :
2254 9 : nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
2255 : }
2256 :
2257 : // first page in book mode is always special:
2258 598 : if ( bFirstRow && mbBookMode )
2259 : {
2260 : // #i88036#
2261 : nCurrentRowWidth +=
2262 0 : pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2263 : }
2264 :
2265 : // center page if possible
2266 : const long nSizeDiff = nVisWidth > nCurrentRowWidth ?
2267 : ( nVisWidth - nCurrentRowWidth ) / 2 :
2268 598 : 0;
2269 :
2270 : // adjust positions of pages in current row
2271 598 : long nX = nSizeDiff;
2272 :
2273 598 : const long nRowStart = nBorder + nSizeDiff;
2274 598 : const long nRowEnd = nRowStart + nCurrentRowWidth;
2275 :
2276 598 : if ( bFirstRow && mbBookMode )
2277 : {
2278 : // #i88036#
2279 0 : nX += pStartOfRow->GetFormatPage().Frm().Width() + nSidebarWidth;
2280 : }
2281 :
2282 598 : SwPageFrm* pEndOfRow = pPageFrm;
2283 598 : SwPageFrm* pPageToAdjust = pStartOfRow;
2284 :
2285 598 : do
2286 : {
2287 598 : const SwPageFrm* pFormatPage = pPageToAdjust;
2288 598 : if ( mbBookMode )
2289 0 : pFormatPage = &pPageToAdjust->GetFormatPage();
2290 :
2291 598 : const SwTwips nCurrentPageWidth = pFormatPage->Frm().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
2292 598 : const Point aOldPagePos = pPageToAdjust->Frm().Pos();
2293 598 : const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SIDEBAR_LEFT;
2294 : const SwTwips nLeftPageAddOffset = bLeftSidebar ?
2295 : nSidebarWidth :
2296 598 : 0;
2297 :
2298 598 : Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
2299 598 : Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );
2300 :
2301 : // RTL view layout: Calculate mirrored page position
2302 598 : if ( bRTL )
2303 : {
2304 0 : const long nXOffsetInRow = aNewPagePos.X() - nRowStart;
2305 0 : aNewPagePos.X() = nRowEnd - nXOffsetInRow - nCurrentPageWidth;
2306 0 : aNewPagePosWithLeftOffset = aNewPagePos;
2307 0 : aNewPagePosWithLeftOffset.X() += nLeftPageAddOffset;
2308 : }
2309 :
2310 598 : if ( aNewPagePosWithLeftOffset != aOldPagePos )
2311 : {
2312 288 : lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
2313 288 : pPageToAdjust->SetCompletePaint();
2314 288 : bPageChanged = true;
2315 : }
2316 :
2317 : // calculate area covered by the current page and store to
2318 : // maPageRects. This is used e.g., for cursor setting
2319 598 : const bool bFirstColumn = pPageToAdjust == pStartOfRow;
2320 598 : const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
2321 598 : const bool bLastRow = !pEndOfRow;
2322 :
2323 598 : nMinPageLeft = Min( nMinPageLeft, aNewPagePos.X() );
2324 598 : nMaxPageRight = Max( nMaxPageRight, aNewPagePos.X() + nCurrentPageWidth);
2325 :
2326 : // border of nGapBetweenPages around the current page:
2327 598 : SwRect aPageRectWithBorders( aNewPagePos.X() - nGapBetweenPages,
2328 598 : aNewPagePos.Y(),
2329 598 : pPageToAdjust->Frm().SSize().Width() + nGapBetweenPages + nSidebarWidth,
2330 1794 : nCurrentRowHeight );
2331 :
2332 : static const long nOuterClickDiff = 1000000;
2333 :
2334 : // adjust borders for these special cases:
2335 598 : if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
2336 598 : aPageRectWithBorders.SubLeft( nOuterClickDiff );
2337 598 : if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
2338 598 : aPageRectWithBorders.AddRight( nOuterClickDiff );
2339 598 : if ( bFirstRow )
2340 496 : aPageRectWithBorders.SubTop( nOuterClickDiff );
2341 598 : if ( bLastRow )
2342 496 : aPageRectWithBorders.AddBottom( nOuterClickDiff );
2343 :
2344 598 : maPageRects.push_back( aPageRectWithBorders );
2345 :
2346 598 : nX = nX + nCurrentPageWidth;
2347 598 : pPageToAdjust = static_cast<SwPageFrm*>(pPageToAdjust->GetNext());
2348 :
2349 : // distance to next page
2350 598 : if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
2351 : {
2352 : // in book view, we add the x gap before left (even) pages:
2353 0 : if ( mbBookMode )
2354 : {
2355 0 : if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
2356 0 : nX = nX + nGapBetweenPages;
2357 : }
2358 : else
2359 : {
2360 : // in non-book view, dont add x gap before
2361 : // 1. the last empty page in a row
2362 : // 2. after an empty page
2363 0 : const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
2364 0 : ( static_cast<SwPageFrm*>(pPageToAdjust->GetPrev())->IsEmptyPage() );
2365 :
2366 0 : if ( !bDontAddGap )
2367 0 : nX = nX + nGapBetweenPages;
2368 : }
2369 : }
2370 : }
2371 : while ( pPageToAdjust != pEndOfRow );
2372 :
2373 : // adjust values for root frame size
2374 598 : nSumRowHeight = nSumRowHeight + nCurrentRowHeight;
2375 :
2376 : // start new row:
2377 598 : nCurrentRowHeight = 0;
2378 598 : nCurrentRowWidth = 0;
2379 598 : pStartOfRow = pEndOfRow;
2380 598 : nWidthRemain = nVisWidth;
2381 598 : nNumberOfPagesInRow = 0;
2382 598 : bFirstRow = false;
2383 : } // end row finished
2384 : } // end while
2385 :
2386 : // set size of root frame:
2387 496 : const Size aOldSize( Frm().SSize() );
2388 496 : const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );
2389 :
2390 496 : if ( bPageChanged || aNewSize != aOldSize )
2391 : {
2392 283 : ChgSize( aNewSize );
2393 283 : ::AdjustSizeChgNotify( this );
2394 283 : Calc();
2395 :
2396 283 : ViewShell* pSh = GetCurrShell();
2397 :
2398 283 : if ( pSh && pSh->GetDoc()->GetDocShell() )
2399 : {
2400 283 : pSh->SetFirstVisPageInvalid();
2401 283 : if (bOldCallbackActionEnabled)
2402 : {
2403 16 : pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2404 16 : pSh->GetDoc()->GetDocShell()->Broadcast(SfxSimpleHint(SFX_HINT_DOCCHANGED));
2405 : }
2406 : }
2407 : }
2408 :
2409 496 : maPagesArea.Pos( Frm().Pos() );
2410 496 : maPagesArea.SSize( aNewSize );
2411 496 : if ( TWIPS_MAX != nMinPageLeft )
2412 496 : maPagesArea._Left( nMinPageLeft );
2413 :
2414 496 : SetCallbackActionEnabled( bOldCallbackActionEnabled );
2415 : }
2416 :
2417 7591 : bool SwRootFrm::IsLeftToRightViewLayout() const
2418 : {
2419 : // Layout direction determined by layout direction of the first page.
2420 : // #i88036#
2421 : // Only ask a non-empty page frame for its layout direction
2422 : // const SwPageFrm* pPage = dynamic_cast<const SwPageFrm*>(Lower());
2423 : // return !pPage->IsRightToLeft() && !pPage->IsVertical();
2424 : const SwPageFrm& rPage =
2425 7591 : dynamic_cast<const SwPageFrm*>(Lower())->GetFormatPage();
2426 7591 : return !rPage.IsRightToLeft() && !rPage.IsVertical();
2427 : }
2428 :
2429 7591 : const SwPageFrm& SwPageFrm::GetFormatPage() const
2430 : {
2431 7591 : const SwPageFrm* pRet = this;
2432 7591 : if ( IsEmptyPage() )
2433 : {
2434 0 : pRet = static_cast<const SwPageFrm*>( OnRightPage() ? GetNext() : GetPrev() );
2435 : // #i88035#
2436 : // Typically a right empty page frame has a next non-empty page frame and
2437 : // a left empty page frame has a previous non-empty page frame.
2438 : // But under certain cirsumstances this assumption is not true -
2439 : // e.g. during insertion of a left page at the end of the document right
2440 : // after a left page in an intermediate state a right empty page does not
2441 : // have a next page frame.
2442 0 : if ( pRet == 0 )
2443 : {
2444 0 : if ( OnRightPage() )
2445 : {
2446 0 : pRet = static_cast<const SwPageFrm*>( GetPrev() );
2447 : }
2448 : else
2449 : {
2450 0 : pRet = static_cast<const SwPageFrm*>( GetNext() );
2451 : }
2452 : }
2453 : OSL_ENSURE( pRet,
2454 : "<SwPageFrm::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash." );
2455 : }
2456 7591 : return *pRet;
2457 : }
2458 :
2459 0 : bool SwPageFrm::IsOverHeaderFooterArea( const Point& rPt, FrameControlType &rControl ) const
2460 : {
2461 0 : long nUpperLimit = 0;
2462 0 : long nLowerLimit = 0;
2463 0 : const SwFrm* pFrm = Lower();
2464 0 : while ( pFrm )
2465 : {
2466 0 : if ( pFrm->IsBodyFrm() )
2467 : {
2468 0 : nUpperLimit = pFrm->Frm().Top();
2469 0 : nLowerLimit = pFrm->Frm().Bottom();
2470 : }
2471 0 : else if ( pFrm->IsFtnContFrm() )
2472 0 : nLowerLimit = pFrm->Frm().Bottom();
2473 :
2474 0 : pFrm = pFrm->GetNext();
2475 : }
2476 :
2477 0 : SwRect aHeaderArea( Frm().TopLeft(),
2478 0 : Size( Frm().Width(), nUpperLimit - Frm().Top() ) );
2479 :
2480 0 : if ( aHeaderArea.IsInside( rPt ) )
2481 : {
2482 0 : rControl = Header;
2483 0 : return true;
2484 : }
2485 : else
2486 : {
2487 0 : SwRect aFooterArea( Point( Frm().Left(), nLowerLimit ),
2488 0 : Size( Frm().Width(), Frm().Bottom() - nLowerLimit ) );
2489 :
2490 0 : if ( aFooterArea.IsInside( rPt ) )
2491 : {
2492 0 : rControl = Footer;
2493 0 : return true;
2494 : }
2495 : }
2496 :
2497 0 : return false;
2498 : }
2499 :
2500 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|