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