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