Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include <time.h>
23 : #include "rootfrm.hxx"
24 : #include "pagefrm.hxx"
25 : #include "viewimp.hxx"
26 : #include "crsrsh.hxx"
27 : #include "dflyobj.hxx"
28 : #include "frmtool.hxx"
29 : #include "dcontact.hxx"
30 : #include "viewopt.hxx"
31 : #include "dbg_lay.hxx"
32 : #include "layouter.hxx"
33 : #include "docstat.hxx"
34 : #include "swevent.hxx"
35 :
36 : #include <sfx2/event.hxx>
37 :
38 : #include <ftnidx.hxx>
39 : #include <vcl/svapp.hxx>
40 : #include <editeng/opaqitem.hxx>
41 : #include <SwSmartTagMgr.hxx>
42 :
43 : #define _LAYACT_CXX
44 : #include "layact.hxx"
45 : #include <swwait.hxx>
46 : #include <fmtsrnd.hxx>
47 : #include <docsh.hxx>
48 :
49 : #include "tabfrm.hxx"
50 : #include "ftnfrm.hxx"
51 : #include "txtfrm.hxx"
52 : #include "notxtfrm.hxx"
53 : #include "flyfrms.hxx"
54 : #include "mdiexp.hxx"
55 : #include "sectfrm.hxx"
56 : #include <acmplwrd.hxx>
57 : // #i28701#
58 : #include <sortedobjs.hxx>
59 : #include <objectformatter.hxx>
60 : #include <vector>
61 :
62 : // SwLayAction static stuff
63 :
64 : #define IS_FLYS (pPage->GetSortedObjs())
65 : #define IS_INVAFLY (pPage->IsInvalidFly())
66 :
67 : // Save some typing work to avoid accessing destroyed pages.
68 : #if OSL_DEBUG_LEVEL > 1
69 :
70 : static void BreakPoint()
71 : {
72 : return;
73 : }
74 :
75 : #define XCHECKPAGE \
76 : { if ( IsAgain() ) \
77 : { BreakPoint(); \
78 : if( bNoLoop ) \
79 : pLayoutAccess->GetLayouter()->EndLoopControl(); \
80 : return; \
81 : } \
82 : }
83 : #else
84 : #define XCHECKPAGE \
85 : { if ( IsAgain() ) \
86 : { \
87 : if( bNoLoop ) \
88 : pLayoutAccess->GetLayouter()->EndLoopControl(); \
89 : return; \
90 : } \
91 : }
92 : #endif
93 :
94 : #define RESCHEDULE \
95 : { \
96 : if ( IsReschedule() ) \
97 : { \
98 : ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
99 : } \
100 : }
101 :
102 0 : inline sal_uLong Ticks()
103 : {
104 0 : return 1000 * clock() / CLOCKS_PER_SEC;
105 : }
106 :
107 0 : void SwLayAction::CheckWaitCrsr()
108 : {
109 0 : RESCHEDULE
110 0 : if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
111 0 : ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
112 : {
113 0 : pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), true );
114 : }
115 0 : }
116 :
117 : // Time over already?
118 0 : inline void SwLayAction::CheckIdleEnd()
119 : {
120 0 : if ( !IsInput() )
121 0 : bInput = GetInputType() && Application::AnyInput( GetInputType() );
122 0 : }
123 :
124 0 : void SwLayAction::SetStatBar( sal_Bool bNew )
125 : {
126 0 : if ( bNew )
127 : {
128 0 : nEndPage = pRoot->GetPageNum();
129 0 : nEndPage += nEndPage * 10 / 100;
130 : }
131 : else
132 0 : nEndPage = USHRT_MAX;
133 0 : }
134 :
135 0 : sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
136 : const SwPageFrm *pPage )
137 : {
138 0 : SwRegionRects aTmp( rRect );
139 0 : const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
140 0 : const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
141 : sal_uInt16 i;
142 :
143 0 : for ( i = 0; i < rObjs.Count() && !aTmp.empty(); ++i )
144 : {
145 0 : SdrObject *pO = rObjs[i]->DrawObj();
146 0 : if ( !pO->ISA(SwVirtFlyDrawObj) )
147 0 : continue;
148 :
149 : // OD 2004-01-15 #110582# - do not consider invisible objects
150 0 : const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
151 0 : if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
152 : {
153 0 : continue;
154 : }
155 :
156 0 : SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
157 :
158 0 : if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
159 0 : continue;
160 :
161 0 : if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
162 0 : continue;
163 :
164 0 : if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
165 0 : continue;
166 :
167 0 : if ( pSelfFly )
168 : {
169 0 : const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
170 0 : if ( pO->GetLayer() == pTmp->GetLayer() )
171 : {
172 0 : if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
173 : // Only look at things above us, if inside the same layer
174 0 : continue;
175 : }
176 : else
177 : {
178 0 : const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
179 0 : if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
180 : // Things from other layers are only interesting to us if
181 : // they're not transparent or lie inwards
182 0 : continue;
183 : }
184 : }
185 :
186 : // OD 19.08.2002 #99657#
187 : // Fly frame without a lower have to be subtracted from paint region.
188 : // For checking, if fly frame contains transparent graphic or
189 : // has surrounded contour, assure that fly frame has a lower
190 0 : if ( pFly->Lower() &&
191 0 : pFly->Lower()->IsNoTxtFrm() &&
192 0 : ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
193 0 : pFly->GetFmt()->GetSurround().IsContour() )
194 : )
195 : {
196 0 : continue;
197 : }
198 :
199 : // OD 19.08.2002 #99657#
200 : // Region of a fly frame with transparent background or a transparent
201 : // shadow have not to be subtracted from paint region
202 0 : if ( pFly->IsBackgroundTransparent() ||
203 0 : pFly->IsShadowTransparent() )
204 : {
205 0 : continue;
206 : }
207 :
208 0 : aTmp -= pFly->Frm();
209 : }
210 :
211 0 : sal_Bool bRetPaint = sal_False;
212 0 : for ( SwRects::const_iterator it = aTmp.begin(); it != aTmp.end(); ++it )
213 0 : bRetPaint |= pImp->GetShell()->AddPaintRect( *it );
214 0 : return bRetPaint;
215 : }
216 :
217 0 : inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
218 : const SwPageFrm *pPage,
219 : const SwRect &rRect )
220 : {
221 0 : if ( rRect.HasArea() )
222 : {
223 0 : if ( pPage->GetSortedObjs() )
224 0 : return PaintWithoutFlys( rRect, pCntnt, pPage );
225 : else
226 0 : return pImp->GetShell()->AddPaintRect( rRect );
227 : }
228 0 : return sal_False;
229 : }
230 :
231 : /**
232 : * Depending of the type, the Cntnt is output according to it's changes, or the area
233 : * to be outputted is registered with the region, respectively.
234 : */
235 0 : void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
236 : const SwPageFrm *pPage,
237 : const SwRect &rOldRect,
238 : long nOldBottom )
239 : {
240 0 : SWRECTFN( pCnt )
241 :
242 0 : if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
243 : {
244 0 : SwRect aPaint( pCnt->PaintArea() );
245 0 : if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
246 0 : pCnt->ResetCompletePaint();
247 : }
248 : else
249 : {
250 : // paint the area between printing bottom and frame bottom and
251 : // the area left and right beside the frame, if its height changed.
252 0 : long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
253 0 : long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
254 0 : const bool bHeightDiff = nOldHeight != nNewHeight;
255 0 : if( bHeightDiff )
256 : {
257 : // OD 05.11.2002 #94454# - consider whole potential paint area.
258 : //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
259 0 : SwRect aDrawRect( pCnt->PaintArea() );
260 0 : if( nOldHeight > nNewHeight )
261 0 : nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
262 0 : (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
263 0 : _PaintCntnt( pCnt, pPage, aDrawRect );
264 : }
265 : // paint content area
266 0 : SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
267 0 : _PaintCntnt( pCnt, pPage, aPaintRect );
268 : }
269 :
270 0 : if ( pCnt->IsRetouche() && !pCnt->GetNext() )
271 : {
272 0 : const SwFrm *pTmp = pCnt;
273 0 : if( pCnt->IsInSct() )
274 : {
275 0 : const SwSectionFrm* pSct = pCnt->FindSctFrm();
276 0 : if( pSct->IsRetouche() && !pSct->GetNext() )
277 0 : pTmp = pSct;
278 : }
279 0 : SwRect aRect( pTmp->GetUpper()->PaintArea() );
280 0 : (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
281 0 : if ( !_PaintCntnt( pCnt, pPage, aRect ) )
282 0 : pCnt->ResetRetouche();
283 : }
284 0 : }
285 :
286 0 : SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
287 : pRoot( pRt ),
288 : pImp( pI ),
289 : pOptTab( 0 ),
290 : pWait( 0 ),
291 : nPreInvaPage( USHRT_MAX ),
292 0 : nStartTicks( Ticks() ),
293 : nInputType( 0 ),
294 : nEndPage( USHRT_MAX ),
295 0 : nCheckPageNum( USHRT_MAX )
296 : {
297 0 : bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
298 0 : bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
299 : bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
300 0 : bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
301 : // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
302 0 : mbFormatCntntOnInterrupt = sal_False;
303 :
304 0 : pImp->pLayAct = this; // register there
305 0 : }
306 :
307 0 : SwLayAction::~SwLayAction()
308 : {
309 : OSL_ENSURE( !pWait, "Wait object not destroyed" );
310 0 : pImp->pLayAct = 0; // unregister
311 0 : }
312 :
313 0 : void SwLayAction::Reset()
314 : {
315 0 : pOptTab = 0;
316 0 : nStartTicks = Ticks();
317 0 : nInputType = 0;
318 0 : nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
319 0 : bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
320 : bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
321 0 : bUpdateExpFlds = bBrowseActionStop = sal_False;
322 0 : }
323 :
324 0 : sal_Bool SwLayAction::RemoveEmptyBrowserPages()
325 : {
326 : // switching from the normal to the browser mode, empty pages may be
327 : // retained for an annoyingly long time, so delete them here
328 0 : sal_Bool bRet = sal_False;
329 0 : const SwViewShell *pSh = pRoot->GetCurrShell();
330 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
331 : {
332 0 : SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
333 0 : do
334 : {
335 0 : if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
336 0 : pPage->ContainsCntnt() )
337 0 : pPage = (SwPageFrm*)pPage->GetNext();
338 : else
339 : {
340 0 : bRet = sal_True;
341 0 : SwPageFrm *pDel = pPage;
342 0 : pPage = (SwPageFrm*)pPage->GetNext();
343 0 : pDel->Cut();
344 0 : delete pDel;
345 : }
346 : } while ( pPage );
347 : }
348 0 : return bRet;
349 : }
350 :
351 0 : void SwLayAction::Action()
352 : {
353 0 : bActionInProgress = sal_True;
354 :
355 : //TurboMode? Hands-off during idle-format
356 0 : if ( IsPaint() && !IsIdle() && TurboAction() )
357 : {
358 0 : delete pWait, pWait = 0;
359 0 : pRoot->ResetTurboFlag();
360 0 : bActionInProgress = sal_False;
361 0 : pRoot->DeleteEmptySct();
362 0 : return;
363 : }
364 0 : else if ( pRoot->GetTurbo() )
365 : {
366 0 : pRoot->DisallowTurbo();
367 0 : const SwFrm *pFrm = pRoot->GetTurbo();
368 0 : pRoot->ResetTurbo();
369 0 : pFrm->InvalidatePage();
370 : }
371 0 : pRoot->DisallowTurbo();
372 :
373 0 : if ( IsCalcLayout() )
374 0 : SetCheckPages( sal_False );
375 :
376 0 : InternalAction();
377 0 : bAgain |= RemoveEmptyBrowserPages();
378 0 : while ( IsAgain() )
379 : {
380 0 : bAgain = bNextCycle = sal_False;
381 0 : InternalAction();
382 0 : bAgain |= RemoveEmptyBrowserPages();
383 : }
384 0 : pRoot->DeleteEmptySct();
385 :
386 0 : delete pWait, pWait = 0;
387 :
388 : //Turbo-Action permitted again for all cases.
389 0 : pRoot->ResetTurboFlag();
390 0 : pRoot->ResetTurbo();
391 :
392 0 : SetCheckPages( sal_True );
393 :
394 0 : bActionInProgress = sal_False;
395 : }
396 :
397 0 : SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
398 : {
399 0 : SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
400 0 : SwCntntFrm *pChk = pCnt;
401 0 : sal_Bool bPageChgd = sal_False;
402 0 : while ( pCnt && pCnt->IsFollow() )
403 0 : pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
404 0 : if ( pCnt && pChk != pCnt )
405 0 : { bPageChgd = sal_True;
406 0 : pPage = pCnt->FindPageFrm();
407 : }
408 :
409 0 : if ( !pPage->GetFmt()->GetDoc()->GetFtnIdxs().empty() )
410 : {
411 0 : SwFtnContFrm *pCont = pPage->FindFtnCont();
412 0 : if ( pCont )
413 : {
414 0 : pCnt = pCont->ContainsCntnt();
415 0 : pChk = pCnt;
416 0 : while ( pCnt && pCnt->IsFollow() )
417 0 : pCnt = (SwCntntFrm*)pCnt->FindPrev();
418 0 : if ( pCnt && pCnt != pChk )
419 : {
420 0 : if ( bPageChgd )
421 : {
422 : // Use the 'topmost' page
423 0 : SwPageFrm *pTmp = pCnt->FindPageFrm();
424 0 : if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
425 0 : pPage = pTmp;
426 : }
427 : else
428 0 : pPage = pCnt->FindPageFrm();
429 : }
430 : }
431 : }
432 0 : return pPage;
433 : }
434 :
435 : // #114798# - unlock position on start and end of page
436 : // layout process.
437 0 : static void unlockPositionOfObjects( SwPageFrm *pPageFrm )
438 : {
439 : assert( pPageFrm );
440 :
441 0 : SwSortedObjs* pObjs = pPageFrm->GetSortedObjs();
442 0 : if ( pObjs )
443 : {
444 0 : sal_uInt32 i = 0;
445 0 : for ( ; i < pObjs->Count(); ++i )
446 : {
447 0 : SwAnchoredObject* pObj = (*pObjs)[i];
448 0 : pObj->UnlockPosition();
449 : }
450 : }
451 0 : }
452 :
453 0 : void SwLayAction::InternalAction()
454 : {
455 : OSL_ENSURE( pRoot->Lower()->IsPageFrm(), ":-( No page below the root.");
456 :
457 0 : pRoot->Calc();
458 :
459 : // Figure out the first invalid page or the first one to be formatted,
460 : // respectively. A complete-action means the first invalid page.
461 : // However, the first page to be formatted might be the one having the
462 : // number 1. If we're doing a fake formatting, the number of the first
463 : // page is the number of the first visible page.
464 0 : SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
465 0 : pImp->GetFirstVisPage();
466 0 : if ( !pPage )
467 0 : pPage = (SwPageFrm*)pRoot->Lower();
468 :
469 : // If there's a first-flow-Cntnt in the first visible page that's also a Follow,
470 : // we switch the page back to the original master of that Cntnt.
471 0 : if ( !IsComplete() )
472 0 : pPage = CheckFirstVisPage( pPage );
473 0 : sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
474 :
475 0 : while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
476 0 : pPage = (SwPageFrm*)pPage->GetNext();
477 :
478 0 : IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
479 0 : sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
480 0 : sal_uInt16 nPercentPageNum = 0;
481 0 : while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
482 : {
483 0 : if ( !pPage && nCheckPageNum != USHRT_MAX &&
484 0 : (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
485 : {
486 0 : if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
487 : {
488 0 : SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
489 0 : while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
490 0 : pPg = (SwPageFrm*)pPg->GetNext();
491 0 : if ( pPg )
492 0 : pPage = pPg;
493 0 : if ( !pPage )
494 0 : break;
495 : }
496 0 : SwPageFrm *pTmp = pPage->GetPrev() ?
497 0 : (SwPageFrm*)pPage->GetPrev() : pPage;
498 0 : SetCheckPages( sal_True );
499 0 : SwFrm::CheckPageDescs( pPage, sal_True, &pTmp );
500 0 : SetCheckPages( sal_False );
501 0 : nCheckPageNum = USHRT_MAX;
502 0 : pPage = pTmp;
503 0 : continue;
504 : }
505 :
506 0 : if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
507 : {
508 0 : nPercentPageNum = pPage->GetPhyPageNum();
509 0 : ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
510 : }
511 0 : pOptTab = 0;
512 : // No Shortcut for Idle or CalcLayout
513 0 : if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
514 : {
515 0 : pRoot->DeleteEmptySct();
516 0 : XCHECKPAGE;
517 0 : if ( !IsInterrupt() &&
518 0 : (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
519 : {
520 0 : if ( pRoot->IsAssertFlyPages() )
521 0 : pRoot->AssertFlyPages();
522 0 : if ( pRoot->IsSuperfluous() )
523 : {
524 0 : sal_Bool bOld = IsAgain();
525 0 : pRoot->RemoveSuperfluous();
526 0 : bAgain = bOld;
527 : }
528 0 : if ( IsAgain() )
529 : {
530 0 : if( bNoLoop )
531 0 : pLayoutAccess->GetLayouter()->EndLoopControl();
532 0 : return;
533 : }
534 0 : pPage = (SwPageFrm*)pRoot->Lower();
535 0 : while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
536 0 : pPage = (SwPageFrm*)pPage->GetNext();
537 0 : while ( pPage && pPage->GetNext() &&
538 0 : pPage->GetPhyPageNum() < nFirstPageNum )
539 0 : pPage = (SwPageFrm*)pPage->GetNext();
540 0 : continue;
541 : }
542 0 : break;
543 : }
544 : else
545 : {
546 0 : pRoot->DeleteEmptySct();
547 0 : XCHECKPAGE;
548 :
549 0 : while ( !IsInterrupt() && !IsNextCycle() &&
550 0 : ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
551 : {
552 0 : unlockPositionOfObjects( pPage );
553 :
554 : // #i28701#
555 0 : SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
556 0 : if ( !IS_FLYS )
557 : {
558 : // If there are no (more) Flys, the flags are superfluous.
559 0 : pPage->ValidateFlyLayout();
560 0 : pPage->ValidateFlyCntnt();
561 : }
562 : // #i28701# - change condition
563 0 : while ( !IsInterrupt() && !IsNextCycle() &&
564 0 : ( pPage->IsInvalid() ||
565 0 : (IS_FLYS && IS_INVAFLY) ) )
566 : {
567 : PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
568 0 : XCHECKPAGE;
569 :
570 : // #i81146# new loop control
571 0 : sal_uInt16 nLoopControlRuns_1 = 0;
572 0 : const sal_uInt16 nLoopControlMax = 20;
573 :
574 0 : while ( !IsNextCycle() && pPage->IsInvalidLayout() )
575 : {
576 0 : pPage->ValidateLayout();
577 :
578 0 : if ( ++nLoopControlRuns_1 > nLoopControlMax )
579 : {
580 : OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
581 0 : break;
582 : }
583 :
584 0 : FormatLayout( pPage );
585 0 : XCHECKPAGE;
586 : }
587 : // #i28701# - change condition
588 0 : if ( !IsNextCycle() &&
589 0 : ( pPage->IsInvalidCntnt() ||
590 0 : (IS_FLYS && IS_INVAFLY) ) )
591 : {
592 0 : pPage->ValidateFlyInCnt();
593 0 : pPage->ValidateCntnt();
594 : // #i28701#
595 0 : pPage->ValidateFlyLayout();
596 0 : pPage->ValidateFlyCntnt();
597 0 : if ( !FormatCntnt( pPage ) )
598 : {
599 0 : XCHECKPAGE;
600 0 : pPage->InvalidateCntnt();
601 0 : pPage->InvalidateFlyInCnt();
602 : // #i28701#
603 0 : pPage->InvalidateFlyLayout();
604 0 : pPage->InvalidateFlyCntnt();
605 0 : if ( IsBrowseActionStop() )
606 0 : bInput = sal_True;
607 : }
608 : }
609 0 : if( bNoLoop )
610 0 : pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
611 : }
612 :
613 0 : unlockPositionOfObjects( pPage );
614 : }
615 :
616 : // A previous page may be invalid again.
617 0 : XCHECKPAGE;
618 0 : if ( !IS_FLYS )
619 : {
620 : // If there are no (more) Flys, the flags are superfluous.
621 0 : pPage->ValidateFlyLayout();
622 0 : pPage->ValidateFlyCntnt();
623 : }
624 0 : if ( !IsInterrupt() )
625 : {
626 0 : SetNextCycle( sal_False );
627 :
628 0 : if ( nPreInvaPage != USHRT_MAX )
629 : {
630 0 : if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
631 : {
632 0 : pImp->SetFirstVisPageInvalid();
633 0 : SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
634 0 : nFirstPageNum = pTmpPage->GetPhyPageNum();
635 0 : if( nPreInvaPage < nFirstPageNum )
636 : {
637 0 : nPreInvaPage = nFirstPageNum;
638 0 : pPage = pTmpPage;
639 : }
640 : }
641 0 : while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
642 0 : pPage = (SwPageFrm*)pPage->GetPrev();
643 0 : nPreInvaPage = USHRT_MAX;
644 : }
645 :
646 0 : while ( pPage->GetPrev() &&
647 0 : ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
648 0 : ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
649 0 : ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
650 0 : (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
651 : nFirstPageNum) )
652 : {
653 0 : pPage = (SwPageFrm*)pPage->GetPrev();
654 : }
655 :
656 : // Continue to the next invalid page
657 0 : while ( pPage && !pPage->IsInvalid() &&
658 0 : (!IS_FLYS || !IS_INVAFLY) )
659 : {
660 0 : pPage = (SwPageFrm*)pPage->GetNext();
661 : }
662 0 : if( bNoLoop )
663 0 : pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
664 : }
665 0 : CheckIdleEnd();
666 : }
667 0 : if ( !pPage && !IsInterrupt() &&
668 0 : (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
669 : {
670 0 : if ( pRoot->IsAssertFlyPages() )
671 0 : pRoot->AssertFlyPages();
672 0 : if ( pRoot->IsSuperfluous() )
673 : {
674 0 : sal_Bool bOld = IsAgain();
675 0 : pRoot->RemoveSuperfluous();
676 0 : bAgain = bOld;
677 : }
678 0 : if ( IsAgain() )
679 : {
680 0 : if( bNoLoop )
681 0 : pLayoutAccess->GetLayouter()->EndLoopControl();
682 0 : return;
683 : }
684 0 : pPage = (SwPageFrm*)pRoot->Lower();
685 0 : while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
686 0 : pPage = (SwPageFrm*)pPage->GetNext();
687 0 : while ( pPage && pPage->GetNext() &&
688 0 : pPage->GetPhyPageNum() < nFirstPageNum )
689 0 : pPage = (SwPageFrm*)pPage->GetNext();
690 : }
691 : }
692 0 : if ( IsInterrupt() && pPage )
693 : {
694 : // If we have input, we don't want to format content anymore, but
695 : // we still should clean the layout.
696 : // Otherwise, the following situation might arise:
697 : // The user enters some text at the end of the paragraph of the last
698 : // page, causing the paragraph to create a Follow for the next page.
699 : // Meanwhile the user continues typing, so we have input while
700 : // still formatting.
701 : // The paragraph on the new page has already been partially formatted,
702 : // and the new page has been fully formatted and is set to CompletePaint,
703 : // but hasn't added itself to the area to be output. Then we paint,
704 : // the CompletePaint of the page is reset because the new paragraph
705 : // already added itself, but the borders of the page haven't been painted
706 : // yet.
707 : // Oh well, with the inevitable following LayAction, the page doesn't
708 : // register itself, because it's (LayoutFrm) flags have been reset
709 : // already - the border of the page will never be painted.
710 0 : SwPageFrm *pPg = pPage;
711 0 : XCHECKPAGE;
712 0 : const SwRect &rVis = pImp->GetShell()->VisArea();
713 :
714 0 : while( pPg && pPg->Frm().Bottom() < rVis.Top() )
715 0 : pPg = (SwPageFrm*)pPg->GetNext();
716 0 : if( pPg != pPage )
717 0 : pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
718 :
719 : // set flag for interrupt content formatting
720 0 : mbFormatCntntOnInterrupt = IsInput();
721 0 : long nBottom = rVis.Bottom();
722 : // #i42586# - format current page, if idle action is active
723 : // This is an optimization for the case that the interrupt is created by
724 : // the move of a form control object, which is represented by a window.
725 0 : while ( pPg && ( pPg->Frm().Top() < nBottom ||
726 0 : ( IsIdle() && pPg == pPage ) ) )
727 : {
728 0 : unlockPositionOfObjects( pPg );
729 :
730 0 : XCHECKPAGE;
731 :
732 : // #i81146# new loop control
733 0 : sal_uInt16 nLoopControlRuns_2 = 0;
734 0 : const sal_uInt16 nLoopControlMax = 20;
735 :
736 : // special case: interrupt content formatting
737 : // #i28701# - conditions are incorrect (macros IS_FLYS and IS_INVAFLY only
738 : // works for <pPage>) and are too strict.
739 : // #i50432# - adjust interrupt formatting to normal page formatting - see above.
740 0 : while ( ( mbFormatCntntOnInterrupt &&
741 0 : ( pPg->IsInvalid() ||
742 0 : ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
743 0 : ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
744 : {
745 0 : XCHECKPAGE;
746 : // #i50432# - format also at-page anchored objects
747 0 : SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
748 0 : if ( !pPg->GetSortedObjs() )
749 : {
750 0 : pPg->ValidateFlyLayout();
751 0 : pPg->ValidateFlyCntnt();
752 : }
753 :
754 : // #i81146# new loop control
755 0 : sal_uInt16 nLoopControlRuns_3 = 0;
756 :
757 0 : while ( pPg->IsInvalidLayout() )
758 : {
759 0 : pPg->ValidateLayout();
760 :
761 0 : if ( ++nLoopControlRuns_3 > nLoopControlMax )
762 : {
763 : OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
764 0 : break;
765 : }
766 :
767 0 : FormatLayout( pPg );
768 0 : XCHECKPAGE;
769 : }
770 :
771 : // #i50432#
772 0 : if ( mbFormatCntntOnInterrupt &&
773 0 : ( pPg->IsInvalidCntnt() ||
774 0 : ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
775 : {
776 0 : pPg->ValidateFlyInCnt();
777 0 : pPg->ValidateCntnt();
778 : // #i26945#
779 0 : pPg->ValidateFlyLayout();
780 0 : pPg->ValidateFlyCntnt();
781 :
782 0 : if ( ++nLoopControlRuns_2 > nLoopControlMax )
783 : {
784 : OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
785 0 : break;
786 : }
787 :
788 0 : if ( !FormatCntnt( pPg ) )
789 : {
790 0 : XCHECKPAGE;
791 0 : pPg->InvalidateCntnt();
792 0 : pPg->InvalidateFlyInCnt();
793 : // #i26945#
794 0 : pPg->InvalidateFlyLayout();
795 0 : pPg->InvalidateFlyCntnt();
796 : }
797 : // #i46807# - we are statisfied, if the content is formatted once complete.
798 : else
799 : {
800 0 : break;
801 : }
802 : }
803 : }
804 :
805 0 : unlockPositionOfObjects( pPg );
806 0 : pPg = (SwPageFrm*)pPg->GetNext();
807 : }
808 : // reset flag for special interrupt content formatting.
809 0 : mbFormatCntntOnInterrupt = sal_False;
810 : }
811 0 : pOptTab = 0;
812 0 : if( bNoLoop )
813 0 : pLayoutAccess->GetLayouter()->EndLoopControl();
814 : }
815 :
816 0 : sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
817 : {
818 :
819 0 : const SwPageFrm *pPage = 0;
820 0 : if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
821 : {
822 0 : const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
823 0 : const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
824 0 : pCnt->Calc();
825 0 : if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
826 0 : pCnt->SetRetouche();
827 :
828 0 : pPage = pCnt->FindPageFrm();
829 0 : PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
830 :
831 0 : if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
832 : {
833 0 : const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
834 0 : ((SwTxtFrm*)pCnt)->RecalcAllLines();
835 0 : if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
836 : {
837 0 : if ( IsPaintExtraData() )
838 0 : pImp->GetShell()->AddPaintRect( pCnt->Frm() );
839 : // This is to calculate the remaining LineNums on the page,
840 : // and we don't stop processing here. To perform this inside RecalcAllLines
841 : // would be expensive, because we would have to notify the page even
842 : // in unnecessary cases (normal actions).
843 0 : const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
844 0 : while ( pNxt &&
845 0 : (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
846 0 : pNxt = pNxt->GetNextCntntFrm();
847 0 : if ( pNxt )
848 0 : pNxt->InvalidatePage();
849 : }
850 0 : return sal_False;
851 : }
852 :
853 0 : if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
854 0 : return sal_False;
855 : }
856 0 : if ( !pPage )
857 0 : pPage = pCnt->FindPageFrm();
858 :
859 : // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
860 0 : if ( pCnt->IsTxtFrm() &&
861 : !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
862 0 : *pPage, this ) )
863 : {
864 0 : return sal_False;
865 : }
866 :
867 0 : if ( pPage->IsInvalidCntnt() )
868 0 : return sal_False;
869 0 : return sal_True;
870 : }
871 :
872 0 : sal_Bool SwLayAction::TurboAction()
873 : {
874 0 : sal_Bool bRet = sal_True;
875 :
876 0 : if ( pRoot->GetTurbo() )
877 : {
878 0 : if ( !_TurboAction( pRoot->GetTurbo() ) )
879 : {
880 0 : CheckIdleEnd();
881 0 : bRet = sal_False;
882 : }
883 0 : pRoot->ResetTurbo();
884 : }
885 : else
886 0 : bRet = sal_False;
887 0 : return bRet;
888 : }
889 :
890 0 : static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
891 : {
892 0 : if (
893 0 : !pFrm->IsValid() ||
894 0 : (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
895 : )
896 : {
897 0 : return true;
898 : }
899 0 : return false;
900 : }
901 :
902 0 : static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
903 : {
904 : OSL_ENSURE( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
905 :
906 0 : if (lcl_IsInvaLay(pFrm, nBottom))
907 0 : return pFrm;
908 0 : pFrm = ((SwLayoutFrm*)pFrm)->Lower();
909 0 : while ( pFrm )
910 : {
911 0 : if ( pFrm->IsLayoutFrm() )
912 : {
913 0 : if (lcl_IsInvaLay(pFrm, nBottom))
914 0 : return pFrm;
915 : const SwFrm *pTmp;
916 0 : if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
917 0 : return pTmp;
918 : }
919 0 : pFrm = pFrm->GetNext();
920 : }
921 0 : return 0;
922 : }
923 :
924 0 : static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
925 : const SwCntntFrm *pFirst )
926 : {
927 : const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
928 0 : pLay->ContainsCntnt();
929 0 : while ( pCnt )
930 : {
931 0 : if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
932 : {
933 0 : if ( pCnt->Frm().Top() <= nBottom )
934 0 : return pCnt;
935 : }
936 :
937 0 : if ( pCnt->GetDrawObjs() )
938 : {
939 0 : const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
940 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
941 : {
942 0 : const SwAnchoredObject* pObj = rObjs[i];
943 0 : if ( pObj->ISA(SwFlyFrm) )
944 : {
945 0 : const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
946 0 : if ( pFly->IsFlyInCntFrm() )
947 : {
948 0 : if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
949 0 : pFly->IsCompletePaint() )
950 : {
951 0 : if ( pFly->Frm().Top() <= nBottom )
952 0 : return pFly;
953 : }
954 0 : const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
955 0 : if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
956 0 : return pFrm;
957 : }
958 : }
959 : }
960 : }
961 0 : if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
962 0 : return 0;
963 0 : pCnt = pCnt->GetNextCntntFrm();
964 0 : if ( !pLay->IsAnLower( pCnt ) )
965 0 : break;
966 : }
967 0 : return 0;
968 : }
969 :
970 : // #i37877# - consider drawing objects
971 0 : static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
972 : long _nBottom )
973 : {
974 : OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
975 :
976 0 : for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
977 : {
978 0 : const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
979 0 : if ( pObj->ISA(SwFlyFrm) )
980 : {
981 0 : const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
982 0 : if ( pFly->Frm().Top() <= _nBottom )
983 : {
984 0 : if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
985 0 : return pFly;
986 :
987 : const SwFrm* pTmp;
988 0 : if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
989 0 : pTmp->Frm().Top() <= _nBottom )
990 0 : return pFly;
991 : }
992 : }
993 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
994 : {
995 0 : if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
996 : {
997 0 : return pObj;
998 : }
999 : }
1000 : }
1001 0 : return 0;
1002 : }
1003 :
1004 : /* Returns True if the page lies directly below or right of the visible area.
1005 : *
1006 : * It's possible for things to change in such a way that the processing
1007 : * (of the caller!) has to continue with the predecessor of the passed page.
1008 : * The parameter might therefore get modified!
1009 : * For BrowseMode, you may even activate the ShortCut if the invalid content
1010 : * of the page lies below the visible area.
1011 : */
1012 0 : sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
1013 : {
1014 0 : sal_Bool bRet = sal_False;
1015 0 : const SwViewShell *pSh = pRoot->GetCurrShell();
1016 0 : const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1017 :
1018 : // If the page is not valid, we quickly format it, otherwise
1019 : // there's gonna be no end of trouble
1020 0 : if ( !prPage->IsValid() )
1021 : {
1022 0 : if ( bBrowse )
1023 : {
1024 : // OD 15.10.2002 #103517# - format complete page
1025 : // Thus, loop on all lowers of the page <prPage>, instead of only
1026 : // format its first lower.
1027 : // NOTE: In online layout (bBrowse == true) a page can contain
1028 : // a header frame and/or a footer frame beside the body frame.
1029 0 : prPage->Calc();
1030 0 : SwFrm* pPageLowerFrm = prPage->Lower();
1031 0 : while ( pPageLowerFrm )
1032 : {
1033 0 : pPageLowerFrm->Calc();
1034 0 : pPageLowerFrm = pPageLowerFrm->GetNext();
1035 : }
1036 : }
1037 : else
1038 0 : FormatLayout( prPage );
1039 0 : if ( IsAgain() )
1040 0 : return sal_False;
1041 : }
1042 :
1043 0 : const SwRect &rVis = pImp->GetShell()->VisArea();
1044 0 : if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
1045 0 : (prPage->Frm().Left()>= rVis.Right()) )
1046 : {
1047 0 : bRet = sal_True;
1048 :
1049 : // This is going to be a bit nasty: The first CntntFrm of this
1050 : // page in the Body text needs formatting; if it changes the page during
1051 : // that process, I need to start over a page further back, because we
1052 : // have been processing a PageBreak.
1053 : // Even more uncomfortable: The next CntntFrm must be formatted,
1054 : // because it's possible for empty pages to exist temporarily (for example
1055 : // a paragraph across multiple pages gets deleted or reduced in size).
1056 :
1057 : // This is irrelevant for the browser, if the last Cnt above it
1058 : // isn't visible anymore.
1059 :
1060 0 : const SwPageFrm *p2ndPage = prPage;
1061 : const SwCntntFrm *pCntnt;
1062 0 : const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
1063 0 : if( p2ndPage->IsFtnPage() && pBody )
1064 0 : pBody = (SwLayoutFrm*)pBody->GetNext();
1065 0 : pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1066 0 : while ( p2ndPage && !pCntnt )
1067 : {
1068 0 : p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
1069 0 : if( p2ndPage )
1070 : {
1071 0 : pBody = p2ndPage->FindBodyCont();
1072 0 : if( p2ndPage->IsFtnPage() && pBody )
1073 0 : pBody = (SwLayoutFrm*)pBody->GetNext();
1074 0 : pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1075 : }
1076 : }
1077 0 : if ( pCntnt )
1078 : {
1079 0 : bool bTstCnt = true;
1080 0 : if ( bBrowse )
1081 : {
1082 : // Is the Cnt before already invisible?
1083 0 : const SwFrm *pLst = pCntnt;
1084 0 : if ( pLst->IsInTab() )
1085 0 : pLst = pCntnt->FindTabFrm();
1086 0 : if ( pLst->IsInSct() )
1087 0 : pLst = pCntnt->FindSctFrm();
1088 0 : pLst = pLst->FindPrev();
1089 0 : if ( pLst &&
1090 0 : (pLst->Frm().Top() >= rVis.Bottom() ||
1091 0 : pLst->Frm().Left()>= rVis.Right()) )
1092 : {
1093 0 : bTstCnt = false;
1094 : }
1095 : }
1096 :
1097 0 : if ( bTstCnt )
1098 : {
1099 : // #i27756# - check after each frame calculation,
1100 : // if the content frame has changed the page. If yes, no other
1101 : // frame calculation is performed
1102 0 : bool bPageChg = false;
1103 :
1104 0 : if ( pCntnt->IsInSct() )
1105 : {
1106 0 : const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1107 0 : if ( !pSct->IsValid() )
1108 : {
1109 0 : pSct->Calc();
1110 0 : pSct->SetCompletePaint();
1111 0 : if ( IsAgain() )
1112 0 : return sal_False;
1113 : // #i27756#
1114 0 : bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1115 0 : prPage->GetPrev();
1116 : }
1117 : }
1118 :
1119 0 : if ( !bPageChg && !pCntnt->IsValid() )
1120 : {
1121 0 : pCntnt->Calc();
1122 0 : pCntnt->SetCompletePaint();
1123 0 : if ( IsAgain() )
1124 0 : return sal_False;
1125 : // #i27756#
1126 0 : bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1127 0 : prPage->GetPrev();
1128 : }
1129 :
1130 0 : if ( !bPageChg && pCntnt->IsInTab() )
1131 : {
1132 0 : const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
1133 0 : if ( !pTab->IsValid() )
1134 : {
1135 0 : pTab->Calc();
1136 0 : pTab->SetCompletePaint();
1137 0 : if ( IsAgain() )
1138 0 : return sal_False;
1139 : // #i27756#
1140 0 : bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1141 0 : prPage->GetPrev();
1142 : }
1143 : }
1144 :
1145 0 : if ( !bPageChg && pCntnt->IsInSct() )
1146 : {
1147 0 : const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1148 0 : if ( !pSct->IsValid() )
1149 : {
1150 0 : pSct->Calc();
1151 0 : pSct->SetCompletePaint();
1152 0 : if ( IsAgain() )
1153 0 : return sal_False;
1154 : // #i27756#
1155 0 : bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1156 0 : prPage->GetPrev();
1157 : }
1158 : }
1159 :
1160 : // #i27756#
1161 0 : if ( bPageChg )
1162 : {
1163 0 : bRet = sal_False;
1164 0 : const SwPageFrm* pTmp = pCntnt->FindPageFrm();
1165 0 : if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1166 0 : pTmp->IsInvalid() )
1167 : {
1168 0 : prPage = (SwPageFrm*)pTmp;
1169 : }
1170 : else
1171 : {
1172 0 : prPage = (SwPageFrm*)prPage->GetPrev();
1173 : }
1174 : }
1175 : // #121980# - no shortcut, if at previous page
1176 : // an anchored object is registered, whose anchor is <pCntnt>.
1177 0 : else if ( prPage->GetPrev() &&
1178 0 : static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
1179 : {
1180 : SwSortedObjs* pObjs =
1181 0 : static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
1182 0 : if ( pObjs )
1183 : {
1184 0 : sal_uInt32 i = 0;
1185 0 : for ( ; i < pObjs->Count(); ++i )
1186 : {
1187 0 : SwAnchoredObject* pObj = (*pObjs)[i];
1188 0 : if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
1189 : {
1190 0 : bRet = sal_False;
1191 0 : break;
1192 : }
1193 : }
1194 : }
1195 : }
1196 : }
1197 : }
1198 : }
1199 :
1200 0 : if ( !bRet && bBrowse )
1201 : {
1202 0 : const long nBottom = rVis.Bottom();
1203 0 : const SwAnchoredObject* pObj( 0L );
1204 0 : if ( prPage->GetSortedObjs() &&
1205 0 : (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
1206 0 : 0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1207 0 : pObj->GetObjRect().Top() <= nBottom )
1208 : {
1209 0 : return sal_False;
1210 : }
1211 0 : const SwFrm* pFrm( 0L );
1212 0 : if ( prPage->IsInvalidLayout() &&
1213 0 : 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1214 0 : pFrm->Frm().Top() <= nBottom )
1215 : {
1216 0 : return sal_False;
1217 : }
1218 0 : if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
1219 0 : 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
1220 0 : pFrm->Frm().Top() <= nBottom )
1221 : {
1222 0 : return sal_False;
1223 : }
1224 0 : bRet = sal_True;
1225 : }
1226 0 : return bRet;
1227 : }
1228 :
1229 : // OD 15.11.2002 #105155# - introduce support for vertical layout
1230 0 : sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
1231 : {
1232 : OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1233 0 : if ( IsAgain() )
1234 0 : return sal_False;
1235 :
1236 0 : sal_Bool bChanged = sal_False;
1237 0 : bool bAlreadyPainted = false;
1238 : // OD 11.11.2002 #104414# - remember frame at complete paint
1239 0 : SwRect aFrmAtCompletePaint;
1240 :
1241 0 : if ( !pLay->IsValid() || pLay->IsCompletePaint() )
1242 : {
1243 0 : if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
1244 0 : pLay->GetPrev()->SetCompletePaint();
1245 :
1246 0 : SwRect aOldFrame( pLay->Frm() );
1247 0 : SwRect aOldRect( aOldFrame );
1248 0 : if( pLay->IsPageFrm() )
1249 : {
1250 0 : aOldRect = static_cast<SwPageFrm*>(pLay)->GetBoundRect();
1251 : }
1252 :
1253 0 : pLay->Calc();
1254 0 : if ( aOldFrame != pLay->Frm() )
1255 0 : bChanged = sal_True;
1256 :
1257 0 : bool bNoPaint = false;
1258 0 : if ( pLay->IsPageBodyFrm() &&
1259 0 : pLay->Frm().Pos() == aOldRect.Pos() &&
1260 0 : pLay->Lower() )
1261 : {
1262 0 : const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1263 : // Limitations because of headers / footers
1264 0 : if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
1265 0 : !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
1266 0 : bNoPaint = true;
1267 : }
1268 :
1269 0 : if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1270 : {
1271 0 : SwRect aPaint( pLay->Frm() );
1272 : // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
1273 : // page frames -> enlarge paint rectangle correspondingly.
1274 0 : if ( pLay->IsPageFrm() )
1275 : {
1276 0 : SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1277 0 : aPaint = pPageFrm->GetBoundRect();
1278 : }
1279 :
1280 0 : bool bPageInBrowseMode = pLay->IsPageFrm();
1281 0 : if( bPageInBrowseMode )
1282 : {
1283 0 : const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1284 0 : if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
1285 0 : bPageInBrowseMode = false;
1286 : }
1287 0 : if( bPageInBrowseMode )
1288 : {
1289 : // NOTE: no vertical layout in online layout
1290 : // Is the change even visible?
1291 0 : if ( pLay->IsCompletePaint() )
1292 : {
1293 0 : pImp->GetShell()->AddPaintRect( aPaint );
1294 0 : bAddRect = sal_False;
1295 : }
1296 : else
1297 : {
1298 : sal_uInt16 i;
1299 :
1300 0 : SwRegionRects aRegion( aOldRect );
1301 0 : aRegion -= aPaint;
1302 0 : for ( i = 0; i < aRegion.size(); ++i )
1303 0 : pImp->GetShell()->AddPaintRect( aRegion[i] );
1304 0 : aRegion.ChangeOrigin( aPaint );
1305 0 : aRegion.clear();
1306 0 : aRegion.push_back( aPaint );
1307 0 : aRegion -= aOldRect;
1308 0 : for ( i = 0; i < aRegion.size(); ++i )
1309 0 : pImp->GetShell()->AddPaintRect( aRegion[i] );
1310 : }
1311 : }
1312 : else
1313 : {
1314 0 : pImp->GetShell()->AddPaintRect( aPaint );
1315 0 : bAlreadyPainted = true;
1316 : // OD 11.11.2002 #104414# - remember frame at complete paint
1317 0 : aFrmAtCompletePaint = pLay->Frm();
1318 : }
1319 :
1320 : // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
1321 : // between pages (not only for in online mode).
1322 0 : if ( pLay->IsPageFrm() )
1323 : {
1324 0 : const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
1325 0 : const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
1326 0 : const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1327 0 : const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1328 0 : SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1329 0 : const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1330 0 : SwRect aPageRect( pLay->Frm() );
1331 :
1332 0 : if(pSh)
1333 : {
1334 : SwPageFrm::GetBorderAndShadowBoundRect(aPageRect, pSh,
1335 0 : aPageRect, pPageFrm->IsLeftShadowNeeded(), pPageFrm->IsRightShadowNeeded(),
1336 0 : pPageFrm->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
1337 : }
1338 :
1339 0 : if ( bPrev )
1340 : {
1341 : // top
1342 0 : SwRect aSpaceToPrevPage( aPageRect );
1343 0 : aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
1344 0 : aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
1345 0 : if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1346 0 : pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1347 :
1348 0 : pSh->GetOut()->DrawRect( aSpaceToPrevPage.SVRect() );
1349 :
1350 : // left
1351 0 : aSpaceToPrevPage = aPageRect;
1352 0 : aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
1353 0 : aSpaceToPrevPage.Right( pLay->Frm().Left() );
1354 0 : if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1355 0 : pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1356 : }
1357 0 : if ( bNext )
1358 : {
1359 : // bottom
1360 0 : SwRect aSpaceToNextPage( aPageRect );
1361 0 : aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1362 0 : aSpaceToNextPage.Top( pLay->Frm().Bottom() );
1363 0 : if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1364 0 : pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1365 :
1366 : // right
1367 0 : aSpaceToNextPage = aPageRect;
1368 0 : aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1369 0 : aSpaceToNextPage.Left( pLay->Frm().Right() );
1370 0 : if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1371 0 : pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1372 : }
1373 : }
1374 : }
1375 0 : pLay->ResetCompletePaint();
1376 : }
1377 :
1378 0 : if ( IsPaint() && bAddRect &&
1379 0 : !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
1380 : {
1381 : // OD 15.11.2002 #105155# - vertical layout support
1382 0 : SWRECTFN( pLay );
1383 0 : SwRect aRect( pLay->GetUpper()->PaintArea() );
1384 0 : (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
1385 0 : if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1386 0 : pLay->ResetRetouche();
1387 : }
1388 :
1389 0 : if( bAlreadyPainted )
1390 0 : bAddRect = sal_False;
1391 :
1392 0 : CheckWaitCrsr();
1393 :
1394 0 : if ( IsAgain() )
1395 0 : return sal_False;
1396 :
1397 : // Now, deal with the lowers that are LayoutFrms
1398 :
1399 0 : if ( pLay->IsFtnFrm() ) // no LayFrms as Lower
1400 0 : return bChanged;
1401 :
1402 0 : SwFrm *pLow = pLay->Lower();
1403 0 : sal_Bool bTabChanged = sal_False;
1404 0 : while ( pLow && pLow->GetUpper() == pLay )
1405 : {
1406 0 : if ( pLow->IsLayoutFrm() )
1407 : {
1408 0 : if ( pLow->IsTabFrm() )
1409 0 : bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1410 : // Skip the ones already registered for deletion
1411 0 : else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
1412 0 : bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1413 : }
1414 0 : else if ( pImp->GetShell()->IsPaintLocked() )
1415 : // Shortcut to minimize the cycles. With Lock, the
1416 : // paint is coming either way (primarily for browse)
1417 0 : pLow->OptCalc();
1418 :
1419 0 : if ( IsAgain() )
1420 0 : return sal_False;
1421 0 : pLow = pLow->GetNext();
1422 : }
1423 : // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
1424 : // area has been already added and after formatting its lowers the frame area
1425 : // is enlarged.
1426 0 : SwRect aBoundRect(pLay->IsPageFrm() ? static_cast<SwPageFrm*>(pLay)->GetBoundRect() : pLay->Frm() );
1427 :
1428 0 : if ( bAlreadyPainted &&
1429 0 : ( aBoundRect.Width() > aFrmAtCompletePaint.Width() ||
1430 0 : aBoundRect.Height() > aFrmAtCompletePaint.Height() )
1431 : )
1432 : {
1433 0 : pImp->GetShell()->AddPaintRect( aBoundRect );
1434 : }
1435 0 : return bChanged || bTabChanged;
1436 : }
1437 :
1438 0 : sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
1439 : {
1440 : OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1441 0 : if ( IsAgain() )
1442 0 : return sal_False;
1443 :
1444 0 : sal_Bool bChanged = false;
1445 0 : sal_Bool bAddRect = true;
1446 :
1447 0 : if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1448 : {
1449 : // The Frame has changed, now it's getting formatted.
1450 0 : const SwRect aOldRect( pFly->Frm() );
1451 0 : pFly->Calc();
1452 0 : bChanged = aOldRect != pFly->Frm();
1453 :
1454 0 : if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1455 0 : pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1456 0 : pImp->GetShell()->AddPaintRect( pFly->Frm() );
1457 :
1458 0 : if ( bChanged )
1459 0 : pFly->Invalidate();
1460 : else
1461 0 : pFly->Validate();
1462 :
1463 0 : bAddRect = false;
1464 0 : pFly->ResetCompletePaint();
1465 : }
1466 :
1467 0 : if ( IsAgain() )
1468 0 : return sal_False;
1469 :
1470 : // Now, deal with the lowers that are LayoutFrms
1471 0 : sal_Bool bTabChanged = false;
1472 0 : SwFrm *pLow = pFly->Lower();
1473 0 : while ( pLow )
1474 : {
1475 0 : if ( pLow->IsLayoutFrm() )
1476 : {
1477 0 : if ( pLow->IsTabFrm() )
1478 0 : bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1479 : else
1480 0 : bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1481 : }
1482 0 : pLow = pLow->GetNext();
1483 : }
1484 0 : return bChanged || bTabChanged;
1485 : }
1486 :
1487 : // OD 31.10.2002 #104100#
1488 : // Implement vertical layout support
1489 0 : sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
1490 : {
1491 : OSL_ENSURE( !IsAgain(), "8-) Attention to the invalid page." );
1492 0 : if ( IsAgain() || !pTab->Lower() )
1493 0 : return sal_False;
1494 :
1495 0 : IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
1496 0 : pTimerAccess->BlockIdling();
1497 :
1498 0 : sal_Bool bChanged = sal_False;
1499 0 : bool bPainted = false;
1500 :
1501 0 : const SwPageFrm *pOldPage = pTab->FindPageFrm();
1502 :
1503 : // OD 31.10.2002 #104100# - vertical layout support
1504 : // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
1505 : // <SwRectFn fnRect> for table frame <pTab>.
1506 0 : SWRECTFN( pTab );
1507 :
1508 0 : if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
1509 : {
1510 0 : if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
1511 : {
1512 0 : pTab->GetPrev()->SetCompletePaint();
1513 : }
1514 :
1515 0 : const SwRect aOldRect( pTab->Frm() );
1516 0 : pTab->SetLowersFormatted( sal_False );
1517 0 : pTab->Calc();
1518 0 : if ( aOldRect != pTab->Frm() )
1519 : {
1520 0 : bChanged = sal_True;
1521 : }
1522 0 : const SwRect aPaintFrm = pTab->PaintArea();
1523 :
1524 0 : if ( IsPaint() && bAddRect )
1525 : {
1526 : // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
1527 0 : if ( !pTab->IsCompletePaint() &&
1528 0 : pTab->IsComplete() &&
1529 0 : ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
1530 : // OD 31.10.2002 #104100# - vertical layout support
1531 0 : (pTab->*fnRect->fnGetLeftMargin)() ) &&
1532 0 : pTab->Frm().HasArea()
1533 : )
1534 : {
1535 : // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
1536 0 : SwRect aMarginRect;
1537 :
1538 0 : SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
1539 0 : if ( nLeftMargin > 0)
1540 : {
1541 0 : aMarginRect = pTab->Frm();
1542 0 : (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
1543 0 : pImp->GetShell()->AddPaintRect( aMarginRect );
1544 : }
1545 :
1546 0 : if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
1547 : {
1548 0 : aMarginRect = pTab->Frm();
1549 0 : (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
1550 0 : pImp->GetShell()->AddPaintRect( aMarginRect );
1551 : }
1552 :
1553 0 : SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
1554 0 : if ( nTopMargin > 0)
1555 : {
1556 0 : aMarginRect = pTab->Frm();
1557 0 : (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
1558 0 : pImp->GetShell()->AddPaintRect( aMarginRect );
1559 : }
1560 :
1561 0 : if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
1562 : {
1563 0 : aMarginRect = pTab->Frm();
1564 0 : (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1565 0 : pImp->GetShell()->AddPaintRect( aMarginRect );
1566 : }
1567 : }
1568 0 : else if ( pTab->IsCompletePaint() )
1569 : {
1570 0 : pImp->GetShell()->AddPaintRect( aPaintFrm );
1571 0 : bAddRect = sal_False;
1572 0 : bPainted = true;
1573 : }
1574 :
1575 0 : if ( pTab->IsRetouche() && !pTab->GetNext() )
1576 : {
1577 0 : SwRect aRect( pTab->GetUpper()->PaintArea() );
1578 : // OD 04.11.2002 #104100# - vertical layout support
1579 0 : (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1580 0 : if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1581 0 : pTab->ResetRetouche();
1582 : }
1583 : }
1584 : else
1585 0 : bAddRect = sal_False;
1586 :
1587 0 : if ( pTab->IsCompletePaint() && !pOptTab )
1588 0 : pOptTab = pTab;
1589 0 : pTab->ResetCompletePaint();
1590 : }
1591 0 : if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
1592 : {
1593 : // OD 04.10.2002 #102779#
1594 : // set correct rectangle for retouche: area between bottom of table frame
1595 : // and bottom of paint area of the upper frame.
1596 0 : SwRect aRect( pTab->GetUpper()->PaintArea() );
1597 : // OD 04.11.2002 #104100# - vertical layout support
1598 0 : (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1599 0 : if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1600 0 : pTab->ResetRetouche();
1601 : }
1602 :
1603 0 : CheckWaitCrsr();
1604 :
1605 0 : pTimerAccess->UnblockIdling();
1606 :
1607 : // Ugly shortcut!
1608 0 : if ( pTab->IsLowersFormatted() &&
1609 0 : (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
1610 0 : return sal_False;
1611 :
1612 : // Now, deal with the lowers
1613 0 : if ( IsAgain() )
1614 0 : return sal_False;
1615 :
1616 : // OD 20.10.2003 #112464# - for savety reasons:
1617 : // check page number before formatting lowers.
1618 0 : if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
1619 0 : SetNextCycle( sal_True );
1620 :
1621 : // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
1622 0 : if ( pTab->IsValid() )
1623 : {
1624 0 : SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
1625 0 : while ( pLow )
1626 : {
1627 0 : bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1628 0 : if ( IsAgain() )
1629 0 : return sal_False;
1630 0 : pLow = (SwLayoutFrm*)pLow->GetNext();
1631 : }
1632 : }
1633 :
1634 0 : return bChanged;
1635 : }
1636 :
1637 0 : sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
1638 : {
1639 0 : const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
1640 0 : const SwViewShell *pSh = pRoot->GetCurrShell();
1641 0 : const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1642 :
1643 0 : while ( pCntnt && pPage->IsAnLower( pCntnt ) )
1644 : {
1645 : // If the Cntnt didn't change, we can use a few shortcuts.
1646 0 : const bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
1647 0 : pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
1648 0 : if ( bFull )
1649 : {
1650 : // We do this so we don't have to search later on.
1651 0 : const bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
1652 0 : const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
1653 0 : const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
1654 :
1655 0 : const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
1656 0 : const SwTabFrm *pTab = pCntnt->FindTabFrm();
1657 0 : const bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
1658 0 : const sal_Bool bOldPaint = IsPaint();
1659 0 : bPaint = bOldPaint && !(pTab && pTab == pOptTab);
1660 0 : _FormatCntnt( pCntnt, pPage );
1661 : // #i26945# - reset <bPaint> before format objects
1662 0 : bPaint = bOldPaint;
1663 :
1664 : // OD 2004-05-10 #i28701# - format floating screen object at content frame.
1665 : // No format, if action flag <bAgain> is set or action is interrupted.
1666 : // OD 2004-08-30 #117736# - allow format on interruption of action, if
1667 : // it's the format for this interrupt
1668 : // #i23129#, #i36347# - pass correct page frame
1669 : // to the object formatter.
1670 0 : if ( !IsAgain() &&
1671 0 : ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
1672 0 : pCntnt->IsTxtFrm() &&
1673 : !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
1674 0 : *(pCntnt->FindPageFrm()), this ) )
1675 : {
1676 0 : return sal_False;
1677 : }
1678 :
1679 0 : if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1680 : {
1681 0 : const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1682 0 : ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1683 0 : if ( IsPaintExtraData() && IsPaint() &&
1684 0 : nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1685 0 : pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1686 : }
1687 :
1688 0 : if ( IsAgain() )
1689 0 : return sal_False;
1690 :
1691 : // Temporarily interrupt processing if layout or Flys become invalid again.
1692 : // However not for the BrowseView: The layout is getting invalid
1693 : // all the time because the page height gets adjusted.
1694 : // The same applies if the user wants to continue working and at least one
1695 : // paragraph has been processed.
1696 0 : if ( (!pTab || (pTab && !bInValid)) )
1697 : {
1698 0 : CheckIdleEnd();
1699 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1700 0 : if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
1701 0 : ( !bBrowse && pPage->IsInvalidLayout() ) ||
1702 : // OD 07.05.2003 #109435# - consider interrupt formatting
1703 0 : ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
1704 : )
1705 0 : return sal_False;
1706 : }
1707 0 : if ( pOldUpper != pCntnt->GetUpper() )
1708 : {
1709 0 : const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
1710 0 : if ( nCurNum < pPage->GetPhyPageNum() )
1711 0 : nPreInvaPage = nCurNum;
1712 :
1713 : // If the Frm flowed backwards more than one page, we need to
1714 : // start over again from the beginning, so nothing gets left out.
1715 0 : if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
1716 : {
1717 0 : SetNextCycle( sal_True );
1718 : // OD 07.05.2003 #109435# - consider interrupt formatting
1719 0 : if ( !mbFormatCntntOnInterrupt )
1720 : {
1721 0 : return sal_False;
1722 : }
1723 : }
1724 : }
1725 : // If the Frame moved forwards to the next page, we re-run through
1726 : // the predecessor.
1727 : // This way, we catch predecessors which are now responsible for
1728 : // retouching, but the footers will be touched also.
1729 0 : bool bSetCntnt = true;
1730 0 : if ( pCntntPrev )
1731 : {
1732 0 : if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
1733 0 : pPage->InvalidateCntnt();
1734 0 : if ( pOldUpper != pCntnt->GetUpper() &&
1735 0 : pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
1736 : {
1737 0 : pCntnt = pCntntPrev;
1738 0 : bSetCntnt = false;
1739 : }
1740 : }
1741 0 : if ( bSetCntnt )
1742 : {
1743 0 : if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1744 0 : pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1745 : {
1746 0 : const long nBottom = pImp->GetShell()->VisArea().Bottom();
1747 : const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1748 0 : nBottom, pCntnt );
1749 0 : if ( !pTmp )
1750 : {
1751 0 : if ( (!(IS_FLYS && IS_INVAFLY) ||
1752 0 : !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1753 0 : (!pPage->IsInvalidLayout() ||
1754 0 : !lcl_FindFirstInvaLay( pPage, nBottom )))
1755 0 : SetBrowseActionStop( sal_True );
1756 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1757 0 : if ( !mbFormatCntntOnInterrupt )
1758 : {
1759 0 : return sal_False;
1760 : }
1761 : }
1762 : }
1763 0 : pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
1764 : }
1765 :
1766 0 : RESCHEDULE;
1767 : }
1768 : else
1769 : {
1770 0 : if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1771 : {
1772 0 : const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1773 0 : ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1774 0 : if ( IsPaintExtraData() && IsPaint() &&
1775 0 : nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1776 0 : pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1777 : }
1778 :
1779 : // Do this if the Frm has been formatted before.
1780 0 : if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
1781 0 : IsPaint() )
1782 0 : PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
1783 0 : if ( IsIdle() )
1784 : {
1785 0 : CheckIdleEnd();
1786 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1787 0 : if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
1788 0 : return sal_False;
1789 : }
1790 0 : if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1791 0 : pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1792 : {
1793 0 : const long nBottom = pImp->GetShell()->VisArea().Bottom();
1794 : const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1795 0 : nBottom, pCntnt );
1796 0 : if ( !pTmp )
1797 : {
1798 0 : if ( (!(IS_FLYS && IS_INVAFLY) ||
1799 0 : !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1800 0 : (!pPage->IsInvalidLayout() ||
1801 0 : !lcl_FindFirstInvaLay( pPage, nBottom )))
1802 0 : SetBrowseActionStop( sal_True );
1803 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1804 0 : if ( !mbFormatCntntOnInterrupt )
1805 : {
1806 0 : return sal_False;
1807 : }
1808 : }
1809 : }
1810 0 : pCntnt = pCntnt->GetNextCntntFrm();
1811 : }
1812 : }
1813 0 : CheckWaitCrsr();
1814 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1815 0 : return !IsInterrupt() || mbFormatCntntOnInterrupt;
1816 : }
1817 :
1818 0 : void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
1819 : const SwPageFrm *pPage )
1820 : {
1821 : // We probably only ended up here because the Cntnt holds DrawObjects.
1822 0 : const bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
1823 0 : !pCntnt->IsRetouche();
1824 0 : SWRECTFN( pCntnt )
1825 0 : if ( !bDrawObjsOnly && IsPaint() )
1826 : {
1827 0 : const SwRect aOldRect( pCntnt->UnionFrm() );
1828 0 : const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
1829 0 : pCntnt->OptCalc();
1830 0 : if( IsAgain() )
1831 0 : return;
1832 0 : if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
1833 0 : (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
1834 : {
1835 0 : pCntnt->SetRetouche();
1836 : }
1837 0 : PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
1838 : }
1839 : else
1840 : {
1841 0 : if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
1842 0 : PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
1843 0 : (pCntnt->Frm().*fnRect->fnGetBottom)() );
1844 0 : pCntnt->OptCalc();
1845 : }
1846 : }
1847 :
1848 : /// Returns sal_True if all Cntnts of the Fly have been processed completely.
1849 : /// Returns sal_False if processing has been interrupted prematurely.
1850 0 : sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
1851 : {
1852 0 : const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
1853 :
1854 0 : while ( pCntnt )
1855 : {
1856 : // OD 2004-05-10 #i28701#
1857 0 : _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
1858 :
1859 : // #i28701# - format floating screen objects
1860 : // at content text frame
1861 : // #i23129#, #i36347# - pass correct page frame
1862 : // to the object formatter.
1863 0 : if ( pCntnt->IsTxtFrm() &&
1864 : !SwObjectFormatter::FormatObjsAtFrm(
1865 : *(const_cast<SwCntntFrm*>(pCntnt)),
1866 0 : *(pCntnt->FindPageFrm()), this ) )
1867 : {
1868 : // restart format with first content
1869 0 : pCntnt = pFly->ContainsCntnt();
1870 0 : continue;
1871 : }
1872 :
1873 0 : if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1874 : {
1875 0 : const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1876 0 : ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1877 0 : if ( IsPaintExtraData() && IsPaint() &&
1878 0 : nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1879 0 : pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1880 : }
1881 :
1882 0 : if ( IsAgain() )
1883 0 : return sal_False;
1884 :
1885 : // If there's input, we interrupt processing.
1886 0 : if ( !pFly->IsFlyInCntFrm() )
1887 : {
1888 0 : CheckIdleEnd();
1889 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1890 0 : if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
1891 0 : return sal_False;
1892 : }
1893 0 : pCntnt = pCntnt->GetNextCntntFrm();
1894 : }
1895 0 : CheckWaitCrsr();
1896 : // OD 14.04.2003 #106346# - consider interrupt formatting.
1897 0 : return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
1898 : }
1899 :
1900 0 : sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
1901 : {
1902 : OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
1903 : // robust against misuse by e.g. #i52542#
1904 0 : if( !pCnt->IsTxtFrm() )
1905 0 : return sal_False;
1906 :
1907 0 : const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
1908 :
1909 0 : bool bProcess = false;
1910 0 : switch ( eJob )
1911 : {
1912 : case ONLINE_SPELLING :
1913 0 : bProcess = pTxtNode->IsWrongDirty(); break;
1914 : case AUTOCOMPLETE_WORDS :
1915 0 : bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
1916 : case WORD_COUNT :
1917 0 : bProcess = pTxtNode->IsWordCountDirty(); break;
1918 : case SMART_TAGS :
1919 0 : bProcess = pTxtNode->IsSmartTagDirty(); break;
1920 : }
1921 :
1922 0 : if( bProcess )
1923 : {
1924 0 : SwViewShell *pSh = pImp->GetShell();
1925 0 : if( COMPLETE_STRING == nTxtPos )
1926 : {
1927 0 : --nTxtPos;
1928 0 : if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
1929 : {
1930 0 : SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
1931 0 : if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
1932 : {
1933 0 : pCntntNode = pCrsr->GetCntntNode();
1934 0 : nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
1935 : }
1936 : }
1937 : }
1938 :
1939 0 : switch ( eJob )
1940 : {
1941 : case ONLINE_SPELLING :
1942 : {
1943 0 : SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
1944 0 : bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
1945 0 : if( !bPageValid )
1946 0 : bAllValid = sal_False;
1947 0 : if ( aRepaint.HasArea() )
1948 0 : pImp->GetShell()->InvalidateWindows( aRepaint );
1949 0 : if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
1950 0 : return sal_True;
1951 0 : break;
1952 : }
1953 : case AUTOCOMPLETE_WORDS :
1954 0 : ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
1955 0 : if ( Application::AnyInput( VCL_INPUT_ANY ) )
1956 0 : return sal_True;
1957 0 : break;
1958 : case WORD_COUNT :
1959 : {
1960 0 : const sal_Int32 nEnd = pTxtNode->GetTxt().getLength();
1961 0 : SwDocStat aStat;
1962 0 : pTxtNode->CountWords( aStat, 0, nEnd );
1963 0 : if ( Application::AnyInput( VCL_INPUT_ANY ) )
1964 0 : return sal_True;
1965 0 : break;
1966 : }
1967 : case SMART_TAGS :
1968 : {
1969 : try {
1970 0 : const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
1971 0 : bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
1972 0 : if( !bPageValid )
1973 0 : bAllValid = sal_False;
1974 0 : if ( aRepaint.HasArea() )
1975 0 : pImp->GetShell()->InvalidateWindows( aRepaint );
1976 0 : } catch( const ::com::sun::star::uno::RuntimeException& e) {
1977 : // #i122885# handle smarttag problems gracefully and provide diagnostics
1978 : SAL_WARN( "sw.core", "SMART_TAGS Exception:" << e.Message);
1979 : }
1980 0 : if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
1981 0 : return sal_True;
1982 0 : break;
1983 : }
1984 : }
1985 : }
1986 :
1987 : // The Flys that are anchored to the paragraph need to be considered too.
1988 0 : if ( pCnt->GetDrawObjs() )
1989 : {
1990 0 : const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1991 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1992 : {
1993 0 : SwAnchoredObject* pObj = rObjs[i];
1994 0 : if ( pObj->ISA(SwFlyFrm) )
1995 : {
1996 0 : SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
1997 0 : if ( pFly->IsFlyInCntFrm() )
1998 : {
1999 0 : const SwCntntFrm *pC = pFly->ContainsCntnt();
2000 0 : while( pC )
2001 : {
2002 0 : if ( pC->IsTxtFrm() )
2003 : {
2004 0 : if ( _DoIdleJob( pC, eJob ) )
2005 0 : return sal_True;
2006 : }
2007 0 : pC = pC->GetNextCntntFrm();
2008 : }
2009 : }
2010 : }
2011 : }
2012 : }
2013 0 : return sal_False;
2014 : }
2015 :
2016 0 : sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
2017 : {
2018 : // Spellcheck all contents of the pages. Either only the
2019 : // visible ones or all of them.
2020 0 : const SwViewShell* pViewShell = pImp->GetShell();
2021 0 : const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2022 0 : const SwDoc* pDoc = pViewShell->GetDoc();
2023 :
2024 0 : switch ( eJob )
2025 : {
2026 : case ONLINE_SPELLING :
2027 0 : if( !pViewOptions->IsOnlineSpell() )
2028 0 : return sal_False;
2029 0 : break;
2030 : case AUTOCOMPLETE_WORDS :
2031 0 : if( !pViewOptions->IsAutoCompleteWords() ||
2032 0 : pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
2033 0 : return sal_False;
2034 0 : break;
2035 : case WORD_COUNT :
2036 0 : if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
2037 0 : return sal_False;
2038 0 : break;
2039 : case SMART_TAGS :
2040 0 : if ( pDoc->GetDocShell()->IsHelpDocument() ||
2041 0 : pDoc->isXForms() ||
2042 0 : !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2043 0 : return sal_False;
2044 0 : break;
2045 : default: OSL_FAIL( "Unknown idle job type" );
2046 : }
2047 :
2048 : SwPageFrm *pPage;
2049 0 : if ( bVisAreaOnly )
2050 0 : pPage = pImp->GetFirstVisPage();
2051 : else
2052 0 : pPage = (SwPageFrm*)pRoot->Lower();
2053 :
2054 0 : pCntntNode = NULL;
2055 0 : nTxtPos = COMPLETE_STRING;
2056 :
2057 0 : while ( pPage )
2058 : {
2059 0 : bPageValid = sal_True;
2060 0 : const SwCntntFrm *pCnt = pPage->ContainsCntnt();
2061 0 : while( pCnt && pPage->IsAnLower( pCnt ) )
2062 : {
2063 0 : if ( _DoIdleJob( pCnt, eJob ) )
2064 0 : return sal_True;
2065 0 : pCnt = pCnt->GetNextCntntFrm();
2066 : }
2067 0 : if ( pPage->GetSortedObjs() )
2068 : {
2069 0 : for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
2070 0 : i < pPage->GetSortedObjs()->Count(); ++i )
2071 : {
2072 0 : const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2073 0 : if ( pObj->ISA(SwFlyFrm) )
2074 : {
2075 0 : const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
2076 0 : const SwCntntFrm *pC = pFly->ContainsCntnt();
2077 0 : while( pC )
2078 : {
2079 0 : if ( pC->IsTxtFrm() )
2080 : {
2081 0 : if ( _DoIdleJob( pC, eJob ) )
2082 0 : return sal_True;
2083 : }
2084 0 : pC = pC->GetNextCntntFrm();
2085 : }
2086 : }
2087 : }
2088 : }
2089 :
2090 0 : if( bPageValid )
2091 : {
2092 0 : switch ( eJob )
2093 : {
2094 0 : case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2095 0 : case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2096 0 : case WORD_COUNT : pPage->ValidateWordCount(); break;
2097 0 : case SMART_TAGS : pPage->ValidateSmartTags(); break;
2098 : }
2099 : }
2100 :
2101 0 : pPage = (SwPageFrm*)pPage->GetNext();
2102 0 : if ( pPage && bVisAreaOnly &&
2103 0 : !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
2104 0 : break;
2105 : }
2106 0 : return sal_False;
2107 : }
2108 :
2109 : #if HAVE_FEATURE_DESKTOP && defined DBG_UTIL
2110 : void SwLayIdle::ShowIdle( ColorData eColorData )
2111 : {
2112 : if ( !m_bIndicator )
2113 : {
2114 : m_bIndicator = true;
2115 : Window *pWin = pImp->GetShell()->GetWin();
2116 : if ( pWin )
2117 : {
2118 : Rectangle aRect( 0, 0, 5, 5 );
2119 : aRect = pWin->PixelToLogic( aRect );
2120 : // OD 2004-04-23 #116347#
2121 : pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
2122 : pWin->SetFillColor( eColorData );
2123 : pWin->SetLineColor();
2124 : pWin->DrawRect( aRect );
2125 : pWin->Pop();
2126 : }
2127 : }
2128 : }
2129 : #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
2130 : #else
2131 : #define SHOW_IDLE( ColorData )
2132 : #endif // DBG_UTIL
2133 :
2134 0 : SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
2135 : pRoot( pRt ),
2136 0 : pImp( pI )
2137 : #ifdef DBG_UTIL
2138 : , m_bIndicator( false )
2139 : #endif
2140 : {
2141 : SAL_INFO("sw.idle", "SwLayIdle() entry");
2142 :
2143 0 : pImp->pIdleAct = this;
2144 :
2145 : SHOW_IDLE( COL_LIGHTRED );
2146 :
2147 0 : pImp->GetShell()->EnableSmooth( sal_False );
2148 :
2149 : // First, spellcheck the visible area. Only if there's nothing
2150 : // to do there, we trigger the IdleFormat.
2151 0 : if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
2152 0 : !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
2153 0 : !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) )
2154 : {
2155 : // Format, then register repaint rectangles with the SwViewShell if necessary.
2156 : // This requires running artificial actions, so we don't get undesired
2157 : // effects when for instance the page count gets changed.
2158 : // We remember the shells where the cursor is visible, so we can make
2159 : // it visible again if needed after a document change.
2160 0 : std::vector<bool> aBools;
2161 0 : SwViewShell *pSh = pImp->GetShell();
2162 0 : do
2163 0 : { ++pSh->mnStartAction;
2164 0 : sal_Bool bVis = sal_False;
2165 0 : if ( pSh->ISA(SwCrsrShell) )
2166 : {
2167 0 : bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
2168 : }
2169 0 : aBools.push_back( bVis );
2170 0 : pSh = (SwViewShell*)pSh->GetNext();
2171 0 : } while ( pSh != pImp->GetShell() );
2172 :
2173 0 : SwLayAction aAction( pRoot, pImp );
2174 0 : aAction.SetInputType( VCL_INPUT_ANY );
2175 0 : aAction.SetIdle( sal_True );
2176 0 : aAction.SetWaitAllowed( sal_False );
2177 0 : aAction.Action();
2178 :
2179 : // Further start/end actions only happen if there were paints started
2180 : // somewhere or if the visibility of the CharRects has changed.
2181 0 : bool bActions = false;
2182 0 : sal_uInt16 nBoolIdx = 0;
2183 0 : do
2184 : {
2185 0 : --pSh->mnStartAction;
2186 :
2187 0 : if ( pSh->Imp()->GetRegion() )
2188 0 : bActions = true;
2189 : else
2190 : {
2191 0 : SwRect aTmp( pSh->VisArea() );
2192 0 : pSh->UISizeNotify();
2193 :
2194 : // #137134#
2195 : // Are we supposed to crash if pSh isn't a cursor shell?!
2196 : // bActions |= aTmp != pSh->VisArea() ||
2197 : // aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
2198 :
2199 : // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2200 : // and the cursor is visible.
2201 0 : bActions |= aTmp != pSh->VisArea();
2202 0 : if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
2203 : {
2204 0 : bActions |= ((sal_Bool) aBools[nBoolIdx]) !=
2205 0 : static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
2206 : }
2207 : }
2208 :
2209 0 : pSh = (SwViewShell*)pSh->GetNext();
2210 0 : ++nBoolIdx;
2211 0 : } while ( pSh != pImp->GetShell() );
2212 :
2213 0 : if ( bActions )
2214 : {
2215 : // Prepare start/end actions via CrsrShell, so the cursor, selection
2216 : // and VisArea can be set correctly.
2217 0 : nBoolIdx = 0;
2218 0 : do
2219 : {
2220 0 : sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
2221 :
2222 0 : if ( bCrsrShell )
2223 0 : ((SwCrsrShell*)pSh)->SttCrsrMove();
2224 :
2225 : // If there are accrued paints, it's best to simply invalidate
2226 : // the whole window. Otherwise there would arise paint problems whose
2227 : // solution would be disproportionally expensive.
2228 : //fix(18176):
2229 0 : SwViewImp *pViewImp = pSh->Imp();
2230 0 : bool bUnlock = false;
2231 0 : if ( pViewImp->GetRegion() )
2232 : {
2233 0 : pViewImp->DelRegion();
2234 :
2235 : // Cause a repaint with virtual device.
2236 0 : pSh->LockPaint();
2237 0 : bUnlock = true;
2238 : }
2239 :
2240 0 : if ( bCrsrShell )
2241 : // If the Crsr was visible, we need to make it visible again.
2242 : // Otherwise, EndCrsrMove with sal_True for IdleEnd
2243 0 : ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
2244 0 : if( bUnlock )
2245 : {
2246 0 : if( bCrsrShell )
2247 : {
2248 : // UnlockPaint overwrite the selection from the
2249 : // CrsrShell and calls the virtual method paint
2250 : // to fill the virtual device. This fill dont have
2251 : // paint the selection! -> Set the focus flag at
2252 : // CrsrShell and it dont paint the selection.
2253 0 : ((SwCrsrShell*)pSh)->ShLooseFcs();
2254 0 : pSh->UnlockPaint( sal_True );
2255 0 : ((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
2256 : }
2257 : else
2258 0 : pSh->UnlockPaint( sal_True );
2259 : }
2260 :
2261 0 : pSh = (SwViewShell*)pSh->GetNext();
2262 0 : ++nBoolIdx;
2263 :
2264 0 : } while ( pSh != pImp->GetShell() );
2265 : }
2266 :
2267 0 : if ( !aAction.IsInterrupt() )
2268 : {
2269 0 : if ( !DoIdleJob( WORD_COUNT, sal_False ) )
2270 0 : if ( !DoIdleJob( SMART_TAGS, sal_False ) )
2271 0 : if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
2272 0 : DoIdleJob( AUTOCOMPLETE_WORDS, sal_False );
2273 : }
2274 :
2275 0 : bool bInValid = false;
2276 0 : const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
2277 0 : const SwViewShell* pViewShell = pImp->GetShell();
2278 : // See conditions in DoIdleJob()
2279 0 : const sal_Bool bSpell = rVOpt.IsOnlineSpell();
2280 0 : const sal_Bool bACmplWrd = rVOpt.IsAutoCompleteWords();
2281 0 : const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
2282 0 : const bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
2283 0 : !pViewShell->GetDoc()->isXForms() &&
2284 0 : SwSmartTagMgr::Get().IsSmartTagsEnabled();
2285 :
2286 0 : SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
2287 0 : do
2288 : {
2289 0 : bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
2290 0 : pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
2291 0 : pPg->IsInvalidFlyInCnt() ||
2292 0 : (bSpell && pPg->IsInvalidSpelling()) ||
2293 0 : (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
2294 0 : (bWordCount && pPg->IsInvalidWordCount()) ||
2295 0 : (bSmartTags && pPg->IsInvalidSmartTags());
2296 :
2297 0 : pPg = (SwPageFrm*)pPg->GetNext();
2298 :
2299 0 : } while ( pPg && !bInValid );
2300 :
2301 0 : if ( !bInValid )
2302 : {
2303 0 : pRoot->ResetIdleFormat();
2304 0 : SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
2305 0 : pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
2306 0 : }
2307 : }
2308 :
2309 0 : pImp->GetShell()->EnableSmooth( sal_True );
2310 :
2311 0 : if( pImp->IsAccessible() )
2312 0 : pImp->FireAccessibleEvents();
2313 :
2314 : SAL_INFO("sw.idle", "SwLayIdle() return");
2315 :
2316 : #ifdef DBG_UTIL
2317 : if ( m_bIndicator && pImp->GetShell()->GetWin() )
2318 : {
2319 : // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
2320 : // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
2321 : // purposes, it is not urgent.
2322 : m_bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
2323 : }
2324 : #endif
2325 0 : }
2326 :
2327 0 : SwLayIdle::~SwLayIdle()
2328 : {
2329 0 : pImp->pIdleAct = 0;
2330 0 : }
2331 :
2332 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|