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