xref: /trunk/main/sw/source/core/layout/layact.cxx (revision 0c72d66f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 
29 #include <time.h>
30 #include "rootfrm.hxx"
31 #include "pagefrm.hxx"
32 #include "cntfrm.hxx"
33 #include "doc.hxx"
34 #include "IDocumentDrawModelAccess.hxx"
35 #include "IDocumentSettingAccess.hxx"
36 #include "IDocumentLayoutAccess.hxx"
37 #include "IDocumentStatistics.hxx"
38 #include "IDocumentTimerAccess.hxx"
39 #include "viewimp.hxx"
40 #include "crsrsh.hxx"
41 #include "dflyobj.hxx"
42 #include "flyfrm.hxx"
43 #include "frmtool.hxx"
44 #include "dcontact.hxx"
45 #include "ndtxt.hxx"    // OnlineSpelling
46 #include "frmfmt.hxx"
47 #include "swregion.hxx"
48 #include "viewopt.hxx"  // OnlineSpelling ueber Internal-TabPage testen.
49 #include "pam.hxx"		// OnlineSpelling wg. der aktuellen Cursorposition
50 #include "dbg_lay.hxx"
51 #include "layouter.hxx" // LoopControlling
52 #include "docstat.hxx"
53 #include "swevent.hxx"
54 
55 #include <sfx2/event.hxx>
56 
57 #include <ftnidx.hxx>
58 #include <vcl/window.hxx>
59 #include <vcl/svapp.hxx>
60 #include <editeng/opaqitem.hxx>
61 #include <editeng/brshitem.hxx>
62 #include <SwSmartTagMgr.hxx>
63 
64 #define _SVSTDARR_BOOLS
65 #include <svl/svstdarr.hxx>
66 
67 #define _LAYACT_CXX
68 #include "layact.hxx"
69 #include <swwait.hxx>
70 #include <fmtsrnd.hxx>
71 #include <fmtanchr.hxx>
72 #include <tools/shl.hxx>
73 #include <sfx2/progress.hxx>
74 #ifndef _DOCSH_HXX
75 #include <docsh.hxx>
76 #endif
77 
78 #include "swmodule.hxx"
79 #include "fmtline.hxx"
80 #include "tabfrm.hxx"
81 #include "ftnfrm.hxx"
82 #include "txtfrm.hxx"
83 #include "notxtfrm.hxx"
84 #include "flyfrms.hxx"
85 #include "mdiexp.hxx"
86 #include "fmtornt.hxx"
87 #include "sectfrm.hxx"
88 #include "lineinfo.hxx"
89 #include <acmplwrd.hxx>
90 // --> OD 2004-06-28 #i28701#
91 #include <sortedobjs.hxx>
92 #include <objectformatter.hxx>
93 #include <PostItMgr.hxx>
94 
95 // <--
96 //#pragma optimize("ity",on)
97 
98 /*************************************************************************
99 |*
100 |*	SwLayAction Statisches Geraffel
101 |*
102 |*	Ersterstellung		MA 22. Dec. 93
103 |*	Letzte Aenderung	MA 22. Dec. 93
104 |*
105 |*************************************************************************/
106 
107 #define IS_FLYS (pPage->GetSortedObjs())
108 #define IS_INVAFLY (pPage->IsInvalidFly())
109 
110 
111 //Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
112 #ifdef DBG_UTIL
113 
BreakPoint()114 static void BreakPoint()
115 {
116 	return;
117 }
118 
119 #define CHECKPAGE \
120 			{	if ( IsAgain() ) \
121 				{	BreakPoint(); \
122 					return; \
123 				} \
124 			}
125 
126 #define XCHECKPAGE \
127 			{	if ( IsAgain() ) \
128 				{	BreakPoint(); \
129 					if( bNoLoop ) \
130 						pLayoutAccess->GetLayouter()->EndLoopControl(); \
131 					return; \
132 				} \
133 			}
134 #else
135 #define CHECKPAGE \
136 			{	if ( IsAgain() ) \
137 					return; \
138 			}
139 
140 #define XCHECKPAGE \
141 			{	if ( IsAgain() ) \
142 				{ \
143 					if( bNoLoop ) \
144 						pLayoutAccess->GetLayouter()->EndLoopControl(); \
145 					return; \
146 				} \
147 			}
148 #endif
149 
150 #define RESCHEDULE \
151 	{ \
152 		if ( IsReschedule() ) \
153 		{ \
154 			if (pProgress) pProgress->Reschedule(); \
155 			::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
156 		} \
157 	}
158 
Ticks()159 inline sal_uLong Ticks()
160 {
161 	return 1000 * clock() / CLOCKS_PER_SEC;
162 }
163 
CheckWaitCrsr()164 void SwLayAction::CheckWaitCrsr()
165 {
166 	RESCHEDULE
167 	if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
168 		 ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
169 	{
170 		pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), true );
171 	}
172 }
173 
174 /*************************************************************************
175 |*
176 |*	SwLayAction::CheckIdleEnd()
177 |*
178 |*	Ersterstellung		MA 12. Aug. 94
179 |*	Letzte Aenderung	MA 24. Jun. 96
180 |*
181 |*************************************************************************/
182 //Ist es wirklich schon soweit...
CheckIdleEnd()183 inline void SwLayAction::CheckIdleEnd()
184 {
185 	if ( !IsInput() )
186 		bInput = GetInputType() && Application::AnyInput( GetInputType() );
187 }
188 
189 /*************************************************************************
190 |*
191 |*	SwLayAction::SetStatBar()
192 |*
193 |*	Ersterstellung		MA 10. Aug. 94
194 |*	Letzte Aenderung	MA 06. Aug. 95
195 |*
196 |*************************************************************************/
SetStatBar(sal_Bool bNew)197 void SwLayAction::SetStatBar( sal_Bool bNew )
198 {
199 	if ( bNew )
200 	{
201 		nEndPage = pRoot->GetPageNum();
202 		nEndPage += nEndPage * 10 / 100;
203 	}
204 	else
205 		nEndPage = USHRT_MAX;
206 }
207 
208 /*************************************************************************
209 |*
210 |*	SwLayAction::PaintCntnt()
211 |*
212 |* 	Beschreibung		Je nach Typ wird der Cntnt entsprechend seinen
213 |* 		Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
214 |* 		Region eingetragen.
215 |* 		PaintCntnt:  fuellt die Region,
216 |*	Ersterstellung		BP 19. Jan. 92
217 |*	Letzte Aenderung	MA 10. Sep. 96
218 |*
219 |*************************************************************************/
PaintWithoutFlys(const SwRect & rRect,const SwCntntFrm * pCnt,const SwPageFrm * pPage)220 sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
221 									const SwPageFrm *pPage )
222 {
223 	SwRegionRects aTmp( rRect );
224 	const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
225 	const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
226 	sal_uInt16 i;
227 
228 	for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
229 	{
230 		SdrObject *pO = rObjs[i]->DrawObj();
231 		if ( !pO->ISA(SwVirtFlyDrawObj) )
232 			continue;
233 
234 		// OD 2004-01-15 #110582# - do not consider invisible objects
235 		const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
236 		if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
237 		{
238 			continue;
239 		}
240 
241 		SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
242 
243 		if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
244 			continue;
245 
246 		if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
247 			continue;
248 
249 		if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
250 			continue;
251 
252 		if ( pSelfFly )
253 		{
254 			const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
255 			if ( pO->GetLayer() == pTmp->GetLayer() )
256 			{
257 				if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
258 					//Im gleichen Layer werden nur obenliegende beachtet.
259 					continue;
260 			}
261 			else
262 			{
263 				const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
264 				if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
265 					//Aus anderem Layer interessieren uns nur nicht transparente
266 					//oder innenliegende
267 					continue;
268 			}
269 		}
270 
271         /// OD 19.08.2002 #99657#
272         ///     Fly frame without a lower have to be subtracted from paint region.
273         ///     For checking, if fly frame contains transparent graphic or
274         ///     has surrounded contour, assure that fly frame has a lower
275         if ( pFly->Lower() &&
276              pFly->Lower()->IsNoTxtFrm() &&
277              ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
278                pFly->GetFmt()->GetSurround().IsContour() )
279            )
280 		{
281 			continue;
282 		}
283 
284         /// OD 19.08.2002 #99657#
285         ///     Region of a fly frame with transparent background or a transparent
286         ///     shadow have not to be subtracted from paint region
287         if ( pFly->IsBackgroundTransparent() ||
288              pFly->IsShadowTransparent() )
289         {
290             continue;
291         }
292 
293 		aTmp -= pFly->Frm();
294 	}
295 
296 	sal_Bool bRetPaint = sal_False;
297 	const SwRect *pData = aTmp.GetData();
298 	for ( i = 0; i < aTmp.Count(); ++pData, ++i )
299 		bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
300 	return bRetPaint;
301 }
302 
_PaintCntnt(const SwCntntFrm * pCntnt,const SwPageFrm * pPage,const SwRect & rRect)303 inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
304 									  const SwPageFrm *pPage,
305 									  const SwRect &rRect )
306 {
307 	if ( rRect.HasArea() )
308 	{
309 		if ( pPage->GetSortedObjs() )
310 			return PaintWithoutFlys( rRect, pCntnt, pPage );
311 		else
312 			return pImp->GetShell()->AddPaintRect( rRect );
313 	}
314 	return sal_False;
315 }
316 
PaintCntnt(const SwCntntFrm * pCnt,const SwPageFrm * pPage,const SwRect & rOldRect,long nOldBottom)317 void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
318 							  const SwPageFrm *pPage,
319                               const SwRect &rOldRect,
320                               long nOldBottom )
321 {
322 	SWRECTFN( pCnt )
323 
324 	if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
325 	{
326 		SwRect aPaint( pCnt->PaintArea() );
327 		if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
328 			pCnt->ResetCompletePaint();
329 	}
330 	else
331 	{
332         // paint the area between printing bottom and frame bottom and
333         // the area left and right beside the frame, if its height changed.
334         long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
335         long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
336         const bool bHeightDiff = nOldHeight != nNewHeight;
337         if( bHeightDiff )
338         {
339             // OD 05.11.2002 #94454# - consider whole potential paint area.
340             //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
341             SwRect aDrawRect( pCnt->PaintArea() );
342             if( nOldHeight > nNewHeight )
343                 nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
344             (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
345             _PaintCntnt( pCnt, pPage, aDrawRect );
346         }
347         // paint content area
348         SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
349         _PaintCntnt( pCnt, pPage, aPaintRect );
350 	}
351 
352 	if ( pCnt->IsRetouche() && !pCnt->GetNext() )
353 	{
354 		const SwFrm *pTmp = pCnt;
355 		if( pCnt->IsInSct() )
356 		{
357 			const SwSectionFrm* pSct = pCnt->FindSctFrm();
358 			if( pSct->IsRetouche() && !pSct->GetNext() )
359 				pTmp = pSct;
360 		}
361 		SwRect aRect( pTmp->GetUpper()->PaintArea() );
362 		(aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
363 		if ( !_PaintCntnt( pCnt, pPage, aRect ) )
364 			pCnt->ResetRetouche();
365 	}
366 }
367 
368 /*************************************************************************
369 |*
370 |*	SwLayAction::SwLayAction()
371 |*
372 |*	Ersterstellung		MA 30. Oct. 92
373 |*	Letzte Aenderung	MA 09. Jun. 95
374 |*
375 |*************************************************************************/
SwLayAction(SwRootFrm * pRt,SwViewImp * pI)376 SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
377 	pRoot( pRt ),
378 	pImp( pI ),
379 	pOptTab( 0 ),
380 	pWait( 0 ),
381 	pProgress(NULL),
382 	nPreInvaPage( USHRT_MAX ),
383 	nStartTicks( Ticks() ),
384 	nInputType( 0 ),
385 	nEndPage( USHRT_MAX ),
386 	nCheckPageNum( USHRT_MAX )
387 {
388 	bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
389 	bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
390 	bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
391 	bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
392 	// OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
393 	mbFormatCntntOnInterrupt = sal_False;
394 
395 	pImp->pLayAct = this;   //Anmelden
396 }
397 
~SwLayAction()398 SwLayAction::~SwLayAction()
399 {
400 	ASSERT( !pWait, "Wait object not destroyed" );
401 	pImp->pLayAct = 0;		//Abmelden
402 }
403 
404 /*************************************************************************
405 |*
406 |*	SwLayAction::Reset()
407 |*
408 |*	Ersterstellung		MA 11. Aug. 94
409 |*	Letzte Aenderung	MA 09. Jun. 95
410 |*
411 |*************************************************************************/
Reset()412 void SwLayAction::Reset()
413 {
414 	pOptTab = 0;
415 	nStartTicks = Ticks();
416 	nInputType = 0;
417 	nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
418 	bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
419 	bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
420 	bUpdateExpFlds = bBrowseActionStop = sal_False;
421 }
422 
423 /*************************************************************************
424 |*
425 |*	SwLayAction::RemoveEmptyBrowserPages()
426 |*
427 |*	Ersterstellung		MA 10. Sep. 97
428 |*	Letzte Aenderung	MA 10. Sep. 97
429 |*
430 |*************************************************************************/
431 
RemoveEmptyBrowserPages()432 sal_Bool SwLayAction::RemoveEmptyBrowserPages()
433 {
434 	//Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
435 	//unangenehm lange stehen. Diese beseiten wir mal schnell.
436 	sal_Bool bRet = sal_False;
437 	const ViewShell *pSh = pRoot->GetCurrShell();
438 	if( pSh && pSh->GetViewOptions()->getBrowseMode() )
439 	{
440 		SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
441 		do
442 		{
443 			if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
444 				 pPage->ContainsCntnt() )
445 				pPage = (SwPageFrm*)pPage->GetNext();
446 			else
447 			{
448 				bRet = sal_True;
449 				SwPageFrm *pDel = pPage;
450 				pPage = (SwPageFrm*)pPage->GetNext();
451 				pDel->Cut();
452 				delete pDel;
453 			}
454 		} while ( pPage );
455 	}
456 	return bRet;
457 }
458 
459 
460 /*************************************************************************
461 |*
462 |*	SwLayAction::Action()
463 |*
464 |*	Ersterstellung		MA 10. Aug. 94
465 |*	Letzte Aenderung	MA 06. Aug. 95
466 |*
467 |*************************************************************************/
Action()468 void SwLayAction::Action()
469 {
470 	bActionInProgress = sal_True;
471 
472 	//TurboMode? Disqualifiziert fuer Idle-Format.
473 	if ( IsPaint() && !IsIdle() && TurboAction() )
474 	{
475 		delete pWait, pWait = 0;
476 		pRoot->ResetTurboFlag();
477 		bActionInProgress = sal_False;
478 		pRoot->DeleteEmptySct();
479 		return;
480 	}
481 	else if ( pRoot->GetTurbo() )
482 	{
483 		pRoot->DisallowTurbo();
484 		const SwFrm *pFrm = pRoot->GetTurbo();
485 		pRoot->ResetTurbo();
486 		pFrm->InvalidatePage();
487 	}
488 	pRoot->DisallowTurbo();
489 
490 	if ( IsCalcLayout() )
491 		SetCheckPages( sal_False );
492 
493 	InternalAction();
494 	bAgain |= RemoveEmptyBrowserPages();
495 	while ( IsAgain() )
496 	{
497 		bAgain = bNextCycle = sal_False;
498 		InternalAction();
499 		bAgain |= RemoveEmptyBrowserPages();
500 	}
501 	pRoot->DeleteEmptySct();
502 
503 	delete pWait, pWait = 0;
504 
505 	//Turbo-Action ist auf jedenfall wieder erlaubt.
506 	pRoot->ResetTurboFlag();
507 	pRoot->ResetTurbo();
508 
509 	SetCheckPages( sal_True );
510 
511 	bActionInProgress = sal_False;
512 }
513 
CheckFirstVisPage(SwPageFrm * pPage)514 SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
515 {
516 	SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
517 	SwCntntFrm *pChk = pCnt;
518 	sal_Bool bPageChgd = sal_False;
519 	while ( pCnt && pCnt->IsFollow() )
520 		pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
521 	if ( pCnt && pChk != pCnt )
522 	{	bPageChgd = sal_True;
523 		pPage = pCnt->FindPageFrm();
524 	}
525 
526 	if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
527 	{
528 		SwFtnContFrm *pCont = pPage->FindFtnCont();
529 		if ( pCont )
530 		{
531 			pCnt = pCont->ContainsCntnt();
532 			pChk = pCnt;
533 			while ( pCnt && pCnt->IsFollow() )
534 				pCnt = (SwCntntFrm*)pCnt->FindPrev();
535 			if ( pCnt && pCnt != pChk )
536 			{
537 				if ( bPageChgd )
538 				{
539 					//Die 'oberste' Seite benutzten.
540 					SwPageFrm *pTmp = pCnt->FindPageFrm();
541 					if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
542 						pPage = pTmp;
543 				}
544 				else
545 					pPage = pCnt->FindPageFrm();
546 			}
547 		}
548 	}
549 	return pPage;
550 }
551 
552 // OD 2004-05-12 #i28701#
553 // --> OD 2004-11-03 #i114798# - unlock position on start and end of page
554 // layout process.
555 class NotifyLayoutOfPageInProgress
556 {
557     private:
558         SwPageFrm& mrPageFrm;
559 
_UnlockPositionOfObjs()560         void _UnlockPositionOfObjs()
561         {
562             SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
563             if ( pObjs )
564             {
565                 sal_uInt32 i = 0;
566                 for ( ; i < pObjs->Count(); ++i )
567                 {
568                     SwAnchoredObject* pObj = (*pObjs)[i];
569                     pObj->UnlockPosition();
570                 }
571             }
572         }
573     public:
NotifyLayoutOfPageInProgress(SwPageFrm & _rPageFrm)574         NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
575             : mrPageFrm( _rPageFrm )
576         {
577             _UnlockPositionOfObjs();
578             _rPageFrm.SetLayoutInProgress( true );
579         }
~NotifyLayoutOfPageInProgress()580         ~NotifyLayoutOfPageInProgress()
581         {
582             mrPageFrm.SetLayoutInProgress( false );
583             _UnlockPositionOfObjs();
584         }
585 };
586 // <--
587 
InternalAction()588 void SwLayAction::InternalAction()
589 {
590 	ASSERT( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
591 
592 	pRoot->Calc();
593 
594 	//Die erste ungueltige bzw. zu formatierende Seite ermitteln.
595 	//Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
596 	//erste zu formatierende Seite diejenige Seite mit der Numemr eins.
597 	//Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
598 	//der ersten Sichtbaren Seite.
599 	SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
600 				pImp->GetFirstVisPage();
601 	if ( !pPage )
602 		pPage = (SwPageFrm*)pRoot->Lower();
603 
604 	//Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
605 	//ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
606 	//Cntnt's
607 	if ( !IsComplete() )
608 		pPage = CheckFirstVisPage( pPage );
609 	sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
610 
611 	while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
612 		pPage = (SwPageFrm*)pPage->GetNext();
613 
614 	IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
615 	sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
616 	sal_uInt16 nPercentPageNum = 0;
617 	while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
618 	{
619 		if ( !pPage && nCheckPageNum != USHRT_MAX &&
620 			 (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
621 		{
622 			if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
623 			{
624 				SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
625 				while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
626 					pPg = (SwPageFrm*)pPg->GetNext();
627 				if ( pPg )
628 					pPage = pPg;
629 				if ( !pPage )
630 					break;
631 			}
632 			SwPageFrm *pTmp = pPage->GetPrev() ?
633 										(SwPageFrm*)pPage->GetPrev() : pPage;
634 			SetCheckPages( sal_True );
635 			SwFrm::CheckPageDescs( pPage );
636 			SetCheckPages( sal_False );
637 			nCheckPageNum = USHRT_MAX;
638 			pPage = pTmp;
639 			continue;
640 		}
641 
642 		if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
643 		{
644 			nPercentPageNum = pPage->GetPhyPageNum();
645 			::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
646 		}
647 		pOptTab = 0;
648 			 //Kein ShortCut fuer Idle oder CalcLayout
649 		if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
650 		{
651 			pRoot->DeleteEmptySct();
652 			XCHECKPAGE;
653 			if ( !IsInterrupt() &&
654 				 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
655 			{
656 				if ( pRoot->IsAssertFlyPages() )
657 					pRoot->AssertFlyPages();
658 				if ( pRoot->IsSuperfluous() )
659 				{
660 					sal_Bool bOld = IsAgain();
661 					pRoot->RemoveSuperfluous();
662 					bAgain = bOld;
663 				}
664 				if ( IsAgain() )
665 				{
666 					if( bNoLoop )
667 						pLayoutAccess->GetLayouter()->EndLoopControl();
668 					return;
669 				}
670 				pPage = (SwPageFrm*)pRoot->Lower();
671 				while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
672 					pPage = (SwPageFrm*)pPage->GetNext();
673 				while ( pPage && pPage->GetNext() &&
674 						pPage->GetPhyPageNum() < nFirstPageNum )
675 					pPage = (SwPageFrm*)pPage->GetNext();
676 				continue;
677 			}
678 			break;
679 		}
680 		else
681 		{
682 			pRoot->DeleteEmptySct();
683 			XCHECKPAGE;
684 
685             // OD 2004-05-12 #i28701# - scope for instance of class
686             // <NotifyLayoutOfPageInProgress>
687             {
688                 NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
689 
690                 while ( !IsInterrupt() && !IsNextCycle() &&
691                         ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
692                 {
693                     // OD 2004-05-10 #i28701#
694                     SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
695                     if ( !IS_FLYS )
696                     {
697                         //Wenn keine Flys (mehr) da sind, sind die Flags
698                         //mehr als fluessig.
699                         pPage->ValidateFlyLayout();
700                         pPage->ValidateFlyCntnt();
701                     }
702                     // OD 2004-05-10 #i28701# - change condition
703                     while ( !IsInterrupt() && !IsNextCycle() &&
704                             ( pPage->IsInvalid() ||
705                               (IS_FLYS && IS_INVAFLY) ) )
706                     {
707                         PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
708                         XCHECKPAGE;
709 
710                         // FME 2007-08-30 #i81146# new loop control
711                         sal_uInt16 nLoopControlRuns_1 = 0;
712                         const sal_uInt16 nLoopControlMax = 20;
713 
714                         while ( !IsNextCycle() && pPage->IsInvalidLayout() )
715                         {
716                             pPage->ValidateLayout();
717 
718                             if ( ++nLoopControlRuns_1 > nLoopControlMax )
719                             {
720 #if OSL_DEBUG_LEVEL > 1
721                                 ASSERT( false, "LoopControl_1 in SwLayAction::InternalAction" )
722 #endif
723                                 break;
724                             }
725 
726                             FormatLayout( pPage );
727                             XCHECKPAGE;
728                         }
729                         // OD 2004-05-10 #i28701# - change condition
730                         if ( !IsNextCycle() &&
731                              ( pPage->IsInvalidCntnt() ||
732                                (IS_FLYS && IS_INVAFLY) ) )
733                         {
734                             pPage->ValidateFlyInCnt();
735                             pPage->ValidateCntnt();
736                             // --> OD 2004-05-10 #i28701#
737                             pPage->ValidateFlyLayout();
738                             pPage->ValidateFlyCntnt();
739                             // <--
740                             if ( !FormatCntnt( pPage ) )
741                             {
742                                 XCHECKPAGE;
743                                 pPage->InvalidateCntnt();
744                                 pPage->InvalidateFlyInCnt();
745                                 // --> OD 2004-05-10 #i28701#
746                                 pPage->InvalidateFlyLayout();
747                                 pPage->InvalidateFlyCntnt();
748                                 // <--
749                                 if ( IsBrowseActionStop() )
750                                     bInput = sal_True;
751                             }
752                         }
753                         if( bNoLoop )
754                             pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
755                     }
756                 }
757             } // end of scope for instance of class <NotifyLayoutOfPageInProgress>
758 
759 
760             //Eine vorige Seite kann wieder invalid sein.
761 			XCHECKPAGE;
762 			if ( !IS_FLYS )
763 			{
764 				//Wenn keine Flys (mehr) da sind, sind die Flags
765 				//mehr als fluessig.
766 				pPage->ValidateFlyLayout();
767 				pPage->ValidateFlyCntnt();
768 			}
769 			if ( !IsInterrupt() )
770 			{
771 				SetNextCycle( sal_False );
772 
773 				if ( nPreInvaPage != USHRT_MAX )
774 				{
775 					if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
776 					{
777 						pImp->SetFirstVisPageInvalid();
778 						SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
779 						nFirstPageNum = pTmpPage->GetPhyPageNum();
780 						if( nPreInvaPage < nFirstPageNum )
781 						{
782 							nPreInvaPage = nFirstPageNum;
783 							pPage = pTmpPage;
784 						}
785 					}
786 					while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
787 						pPage = (SwPageFrm*)pPage->GetPrev();
788 					nPreInvaPage = USHRT_MAX;
789 				}
790 
791                 while ( pPage->GetPrev() &&
792 						( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
793 						  ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
794 							((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
795 						(((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
796 							nFirstPageNum) )
797 				{
798 					pPage = (SwPageFrm*)pPage->GetPrev();
799                 }
800 
801                 //Weiter bis zur naechsten invaliden Seite.
802 				while ( pPage && !pPage->IsInvalid() &&
803 						(!IS_FLYS || !IS_INVAFLY) )
804 				{
805 					pPage = (SwPageFrm*)pPage->GetNext();
806 				}
807 				if( bNoLoop )
808 					pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
809 			}
810             CheckIdleEnd();
811 		}
812 		if ( !pPage && !IsInterrupt() &&
813 			 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
814 		{
815 			if ( pRoot->IsAssertFlyPages() )
816 				pRoot->AssertFlyPages();
817 			if ( pRoot->IsSuperfluous() )
818 			{
819 				sal_Bool bOld = IsAgain();
820 				pRoot->RemoveSuperfluous();
821 				bAgain = bOld;
822 			}
823 			if ( IsAgain() )
824 			{
825 				if( bNoLoop )
826 					pLayoutAccess->GetLayouter()->EndLoopControl();
827 				return;
828 			}
829 			pPage = (SwPageFrm*)pRoot->Lower();
830 			while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
831 				pPage = (SwPageFrm*)pPage->GetNext();
832 			while ( pPage && pPage->GetNext() &&
833 					pPage->GetPhyPageNum() < nFirstPageNum )
834 				pPage = (SwPageFrm*)pPage->GetNext();
835 		}
836 	}
837 	if ( IsInterrupt() && pPage )
838 	{
839 		//Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
840 		//Das Layout muessen wir aber schon in Ordnung bringen.
841 		//Andernfalls kann folgende Situation auftreten (Bug: 3244):
842 		//Am Ende des Absatz der letzten Seite wird Text eingegeben, so dass
843 		//der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
844 		//wird gleich schnell weitergetippt - Es liegt waehrend der
845 		//Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
846 		//bereits anformatiert, die neue Seite ist Formatiert und steht
847 		//auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
848 		//eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
849 		//zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
850 		//aber die Raender der Seite werden nicht gepaintet. Naja, bei der
851 		//zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
852 		//nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
853 		//wurden -- Der Rand der Seite wird nie gepaintet.
854 		SwPageFrm *pPg = pPage;
855 		XCHECKPAGE;
856 		const SwRect &rVis = pImp->GetShell()->VisArea();
857 
858 		while( pPg && pPg->Frm().Bottom() < rVis.Top() )
859 			pPg = (SwPageFrm*)pPg->GetNext();
860 		if( pPg != pPage )
861 			pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
862 
863         // OD 14.04.2003 #106346# - set flag for interrupt content formatting
864         mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
865         long nBottom = rVis.Bottom();
866         // --> OD 2005-02-15 #i42586# - format current page, if idle action is active
867         // This is an optimization for the case that the interrupt is created by
868         // the move of a form control object, which is represented by a window.
869         while ( pPg && ( pPg->Frm().Top() < nBottom ||
870                          ( IsIdle() && pPg == pPage ) ) )
871         // <--
872 		{
873             // --> OD 2004-10-11 #i26945# - follow-up of #i28701#
874             NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
875 
876             XCHECKPAGE;
877 
878             // FME 2007-08-30 #i81146# new loop control
879             sal_uInt16 nLoopControlRuns_2 = 0;
880             const sal_uInt16 nLoopControlMax = 20;
881 
882             // OD 14.04.2003 #106346# - special case: interrupt content formatting
883             // --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
884             // are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
885             // and are too strict.
886             // --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
887             // normal page formatting - see above.
888             while ( ( mbFormatCntntOnInterrupt &&
889                       ( pPg->IsInvalid() ||
890                         ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
891                     ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
892             {
893                 XCHECKPAGE;
894                 // --> OD 2005-06-09 #i50432# - format also at-page anchored objects
895                 SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
896                 // <--
897                 // --> OD 2005-06-09 #i50432#
898                 if ( !pPg->GetSortedObjs() )
899                 {
900                     pPg->ValidateFlyLayout();
901                     pPg->ValidateFlyCntnt();
902                 }
903                 // <--
904 
905                 // FME 2007-08-30 #i81146# new loop control
906                 sal_uInt16 nLoopControlRuns_3 = 0;
907 
908                 while ( pPg->IsInvalidLayout() )
909                 {
910                     pPg->ValidateLayout();
911 
912                     if ( ++nLoopControlRuns_3 > nLoopControlMax )
913                     {
914 #if OSL_DEBUG_LEVEL > 1
915                         ASSERT( false, "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" )
916 #endif
917                         break;
918                     }
919 
920                     FormatLayout( pPg );
921                     XCHECKPAGE;
922                 }
923 
924                 // --> OD 2005-06-09 #i50432#
925                 if ( mbFormatCntntOnInterrupt &&
926                      ( pPg->IsInvalidCntnt() ||
927                        ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
928                 // <--
929                 {
930                     pPg->ValidateFlyInCnt();
931                     pPg->ValidateCntnt();
932                     // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
933                     pPg->ValidateFlyLayout();
934                     pPg->ValidateFlyCntnt();
935                     // <--
936 
937                     if ( ++nLoopControlRuns_2 > nLoopControlMax )
938                     {
939 #if OSL_DEBUG_LEVEL > 1
940                         ASSERT( false, "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" )
941 #endif
942                         break;
943                     }
944 
945                     if ( !FormatCntnt( pPg ) )
946                     {
947                         XCHECKPAGE;
948                         pPg->InvalidateCntnt();
949                         pPg->InvalidateFlyInCnt();
950                         // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
951                         pPg->InvalidateFlyLayout();
952                         pPg->InvalidateFlyCntnt();
953                         // <--
954                     }
955                     // --> OD 2005-04-06 #i46807# - we are satisfied, if the
956                     // content is formatted once complete.
957                     else
958                     {
959                         break;
960                     }
961                     // <--
962                 }
963             }
964             // <--
965 			pPg = (SwPageFrm*)pPg->GetNext();
966 		}
967 		// OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
968 		mbFormatCntntOnInterrupt = sal_False;
969 	}
970 	pOptTab = 0;
971 	if( bNoLoop )
972 		pLayoutAccess->GetLayouter()->EndLoopControl();
973 }
974 /*************************************************************************
975 |*
976 |*	SwLayAction::TurboAction(), _TurboAction()
977 |*
978 |*	Ersterstellung		MA 04. Dec. 92
979 |*	Letzte Aenderung	MA 15. Aug. 93
980 |*
981 |*************************************************************************/
_TurboAction(const SwCntntFrm * pCnt)982 sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
983 {
984 
985 	const SwPageFrm *pPage = 0;
986 	if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
987 	{
988 		const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
989 		const long	 nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
990 		pCnt->Calc();
991 		if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
992 			pCnt->SetRetouche();
993 
994 		pPage = pCnt->FindPageFrm();
995 		PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
996 
997 		if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
998 		{
999 			const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
1000 			((SwTxtFrm*)pCnt)->RecalcAllLines();
1001 			if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
1002 			{
1003 				if ( IsPaintExtraData() )
1004 					pImp->GetShell()->AddPaintRect( pCnt->Frm() );
1005 				//Damit die restlichen LineNums auf der Seite bereichnet werden
1006 				//und nicht hier abgebrochen wird.
1007 				//Das im RecalcAllLines zu erledigen waere teuer, weil dort
1008 				//auch in unnoetigen Faellen (normale Action) auch immer die
1009 				//Seite benachrichtigt werden muesste.
1010 				const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1011 				while ( pNxt &&
1012 						(pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
1013 					pNxt = pNxt->GetNextCntntFrm();
1014 				if ( pNxt )
1015 					pNxt->InvalidatePage();
1016 			}
1017 			return sal_False;
1018 		}
1019 
1020 		if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
1021 			return sal_False;
1022 	}
1023 	if ( !pPage )
1024 		pPage = pCnt->FindPageFrm();
1025 
1026     // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
1027     if ( pCnt->IsTxtFrm() &&
1028          !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
1029                                               *pPage, this ) )
1030     {
1031         return sal_False;
1032     }
1033 
1034 	if ( pPage->IsInvalidCntnt() )
1035 		return sal_False;
1036 	return sal_True;
1037 }
1038 
TurboAction()1039 sal_Bool SwLayAction::TurboAction()
1040 {
1041 	sal_Bool bRet = sal_True;
1042 
1043 	if ( pRoot->GetTurbo() )
1044 	{
1045 		if ( !_TurboAction( pRoot->GetTurbo() ) )
1046 		{
1047 			CheckIdleEnd();
1048 			bRet = sal_False;
1049 		}
1050 		pRoot->ResetTurbo();
1051 	}
1052 	else
1053 		bRet = sal_False;
1054 	return bRet;
1055 }
1056 /*************************************************************************
1057 |*
1058 |*	SwLayAction::IsShortCut()
1059 |*
1060 |*	Beschreibung:		Liefert ein True, wenn die Seite vollstaendig unter
1061 |* 		oder rechts neben dem sichbaren Bereich liegt.
1062 |* 		Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
1063 |* 		die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
1064 |* 		uebergebenen Seite weitergefuehrt werden muss. Der Parameter wird
1065 |* 		also ggf. veraendert!
1066 |*		Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
1067 |*		wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
1068 |*		bereiches liegt.
1069 |*	Ersterstellung		MA 30. Oct. 92
1070 |*	Letzte Aenderung	MA 18. Jul. 96
1071 |*
1072 |*************************************************************************/
lcl_IsInvaLay(const SwFrm * pFrm,long nBottom)1073 static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
1074 {
1075 	if (
1076 	     !pFrm->IsValid() ||
1077 	     (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
1078 	   )
1079 	{
1080 		return true;
1081 	}
1082 	return false;
1083 }
1084 
lcl_FindFirstInvaLay(const SwFrm * pFrm,long nBottom)1085 static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
1086 {
1087 	ASSERT( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
1088 
1089 	if (lcl_IsInvaLay(pFrm, nBottom))
1090 		return pFrm;
1091 	pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1092 	while ( pFrm )
1093 	{
1094 		if ( pFrm->IsLayoutFrm() )
1095 		{
1096 			if (lcl_IsInvaLay(pFrm, nBottom))
1097 				return pFrm;
1098 			const SwFrm *pTmp;
1099 			if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
1100 				return pTmp;
1101 		}
1102 		pFrm = pFrm->GetNext();
1103 	}
1104 	return 0;
1105 }
1106 
lcl_FindFirstInvaCntnt(const SwLayoutFrm * pLay,long nBottom,const SwCntntFrm * pFirst)1107 static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
1108 									 const SwCntntFrm *pFirst )
1109 {
1110 	const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
1111 									  pLay->ContainsCntnt();
1112 	while ( pCnt )
1113 	{
1114 		if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
1115 		{
1116 			if ( pCnt->Frm().Top() <= nBottom )
1117 				return pCnt;
1118 		}
1119 
1120 		if ( pCnt->GetDrawObjs() )
1121 		{
1122             const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1123 			for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1124 			{
1125                 const SwAnchoredObject* pObj = rObjs[i];
1126                 if ( pObj->ISA(SwFlyFrm) )
1127 				{
1128                     const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1129 					if ( pFly->IsFlyInCntFrm() )
1130 					{
1131 						if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
1132 							 pFly->IsCompletePaint() )
1133 						{
1134 							if ( pFly->Frm().Top() <= nBottom )
1135 								return pFly;
1136 						}
1137 						const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
1138 						if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
1139 							return pFrm;
1140 					}
1141 				}
1142 			}
1143 		}
1144 		if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
1145 			return 0;
1146 		pCnt = pCnt->GetNextCntntFrm();
1147 		if ( !pLay->IsAnLower( pCnt ) )
1148 			break;
1149 	}
1150 	return 0;
1151 }
1152 
1153 // --> OD 2005-02-21 #i37877# - consider drawing objects
lcl_FindFirstInvaObj(const SwPageFrm * _pPage,long _nBottom)1154 static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
1155                                               long _nBottom )
1156 {
1157     ASSERT( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" )
1158 
1159     for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
1160 	{
1161         const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
1162         if ( pObj->ISA(SwFlyFrm) )
1163 		{
1164             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1165             if ( pFly->Frm().Top() <= _nBottom )
1166 			{
1167 				if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
1168 					return pFly;
1169 
1170                 const SwFrm* pTmp;
1171                 if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
1172                      pTmp->Frm().Top() <= _nBottom )
1173                     return pFly;
1174 			}
1175 		}
1176         else if ( pObj->ISA(SwAnchoredDrawObject) )
1177         {
1178             if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
1179             {
1180                 return pObj;
1181             }
1182         }
1183 	}
1184 	return 0;
1185 }
1186 // <--
1187 
IsShortCut(SwPageFrm * & prPage)1188 sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
1189 {
1190 	sal_Bool bRet = sal_False;
1191 	const ViewShell *pSh = pRoot->GetCurrShell();
1192 	const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1193 
1194 	//Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
1195 	//gibts nix als Aerger.
1196 	if ( !prPage->IsValid() )
1197 	{
1198 		if ( bBrowse )
1199 		{
1200             /// OD 15.10.2002 #103517# - format complete page
1201             /// Thus, loop on all lowers of the page <prPage>, instead of only
1202             /// format its first lower.
1203             /// NOTE: In online layout (bBrowse == sal_True) a page can contain
1204             ///     a header frame and/or a footer frame beside the body frame.
1205 			prPage->Calc();
1206             SwFrm* pPageLowerFrm = prPage->Lower();
1207             while ( pPageLowerFrm )
1208             {
1209                 pPageLowerFrm->Calc();
1210                 pPageLowerFrm = pPageLowerFrm->GetNext();
1211             }
1212 		}
1213 		else
1214 			FormatLayout( prPage );
1215 		if ( IsAgain() )
1216 			return sal_False;
1217 	}
1218 
1219 
1220 	const SwRect &rVis = pImp->GetShell()->VisArea();
1221 	if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
1222 		 (prPage->Frm().Left()>= rVis.Right()) )
1223 	{
1224 		bRet = sal_True;
1225 
1226 		//Jetzt wird es ein bisschen unangenehm: Der erste CntntFrm dieser Seite
1227 		//im Bodytext muss formatiert werden, wenn er dabei die Seite
1228 		//wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
1229 		//es wurde ein PageBreak verarbeitet.
1230 //Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
1231 		//formatiert werden, denn es kann passieren, dass kurzfristig
1232 		//leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
1233 		//wird geloescht oder verkleinert).
1234 
1235 		//Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
1236 		//nicht mehr sichtbar ist.
1237 
1238 		const SwPageFrm *p2ndPage = prPage;
1239 		const SwCntntFrm *pCntnt;
1240 		const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
1241 		if( p2ndPage->IsFtnPage() && pBody )
1242 			pBody = (SwLayoutFrm*)pBody->GetNext();
1243 		pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1244 		while ( p2ndPage && !pCntnt )
1245 		{
1246 			p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
1247 			if( p2ndPage )
1248 			{
1249 				pBody = p2ndPage->FindBodyCont();
1250 				if( p2ndPage->IsFtnPage() && pBody )
1251 					pBody = (SwLayoutFrm*)pBody->GetNext();
1252 				pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1253 			}
1254 		}
1255 		if ( pCntnt )
1256 		{
1257 			sal_Bool bTstCnt = sal_True;
1258 			if ( bBrowse )
1259 			{
1260 				//Der Cnt davor schon nicht mehr sichtbar?
1261 				const SwFrm *pLst = pCntnt;
1262 				if ( pLst->IsInTab() )
1263 					pLst = pCntnt->FindTabFrm();
1264 				if ( pLst->IsInSct() )
1265 					pLst = pCntnt->FindSctFrm();
1266 				pLst = pLst->FindPrev();
1267 				if ( pLst &&
1268 					 (pLst->Frm().Top() >= rVis.Bottom() ||
1269 					  pLst->Frm().Left()>= rVis.Right()) )
1270 				{
1271 					bTstCnt = sal_False;
1272 				}
1273 			}
1274 
1275 			if ( bTstCnt )
1276 			{
1277                 // --> OD 2004-06-04 #i27756# - check after each frame calculation,
1278                 // if the content frame has changed the page. If yes, no other
1279                 // frame calculation is performed
1280                 bool bPageChg = false;
1281 
1282                 if ( pCntnt->IsInSct() )
1283 				{
1284 					const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1285 					if ( !pSct->IsValid() )
1286 					{
1287 						pSct->Calc();
1288 						pSct->SetCompletePaint();
1289 						if ( IsAgain() )
1290 							return sal_False;
1291                         // --> OD 2004-06-04 #i27756#
1292                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1293                                    prPage->GetPrev();
1294 					}
1295 				}
1296 
1297                 if ( !bPageChg && !pCntnt->IsValid() )
1298                 {
1299                     pCntnt->Calc();
1300 					pCntnt->SetCompletePaint();
1301 					if ( IsAgain() )
1302 						return sal_False;
1303                     // --> OD 2004-06-04 #i27756#
1304                     bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1305                                prPage->GetPrev();
1306 				}
1307 
1308                 if ( !bPageChg && pCntnt->IsInTab() )
1309 				{
1310 					const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
1311 					if ( !pTab->IsValid() )
1312 					{
1313 						pTab->Calc();
1314 						pTab->SetCompletePaint();
1315 						if ( IsAgain() )
1316 							return sal_False;
1317                         // --> OD 2004-06-04 #i27756#
1318                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1319                                    prPage->GetPrev();
1320 					}
1321 				}
1322 
1323                 if ( !bPageChg && pCntnt->IsInSct() )
1324 				{
1325 					const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1326 					if ( !pSct->IsValid() )
1327 					{
1328 						pSct->Calc();
1329 						pSct->SetCompletePaint();
1330 						if ( IsAgain() )
1331 							return sal_False;
1332                         // --> OD 2004-06-04 #i27756#
1333                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1334                                    prPage->GetPrev();
1335 					}
1336 				}
1337 
1338                 // --> OD 2004-06-04 #i27756#
1339                 if ( bPageChg )
1340 				{
1341 					bRet = sal_False;
1342                     const SwPageFrm* pTmp = pCntnt->FindPageFrm();
1343                     if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1344                          pTmp->IsInvalid() )
1345                     {
1346 						prPage = (SwPageFrm*)pTmp;
1347                     }
1348 					else
1349                     {
1350 						prPage = (SwPageFrm*)prPage->GetPrev();
1351                     }
1352 				}
1353                 // --> OD 2005-04-25 #121980# - no shortcut, if at previous page
1354                 // an anchored object is registered, whose anchor is <pCntnt>.
1355                 else if ( prPage->GetPrev() &&
1356                           static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
1357                 {
1358                     SwSortedObjs* pObjs =
1359                         static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
1360                     if ( pObjs )
1361                     {
1362                         sal_uInt32 i = 0;
1363                         for ( ; i < pObjs->Count(); ++i )
1364                         {
1365                             SwAnchoredObject* pObj = (*pObjs)[i];
1366                             if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
1367                             {
1368                                 bRet = sal_False;
1369                                 break;
1370                             }
1371                         }
1372                     }
1373                 }
1374                 // <--
1375 			}
1376 		}
1377 	}
1378 
1379 	if ( !bRet && bBrowse )
1380 	{
1381 		const long nBottom = rVis.Bottom();
1382         const SwAnchoredObject* pObj( 0L );
1383         if ( prPage->GetSortedObjs() &&
1384 			 (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
1385              0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1386              pObj->GetObjRect().Top() <= nBottom )
1387 		{
1388 			return sal_False;
1389 		}
1390         const SwFrm* pFrm( 0L );
1391 		if ( prPage->IsInvalidLayout() &&
1392 			 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1393 			 pFrm->Frm().Top() <= nBottom )
1394 		{
1395 			return sal_False;
1396 		}
1397 		if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
1398 			 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
1399 			 pFrm->Frm().Top() <= nBottom )
1400 		{
1401 			return sal_False;
1402 		}
1403 		bRet = sal_True;
1404 	}
1405 	return bRet;
1406 }
1407 
1408 /*************************************************************************
1409 |*
1410 |*	SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
1411 |*
1412 |*	Ersterstellung		MA 30. Oct. 92
1413 |*	Letzte Aenderung	MA 18. May. 98
1414 |*
1415 |*************************************************************************/
1416 // OD 15.11.2002 #105155# - introduce support for vertical layout
FormatLayout(SwLayoutFrm * pLay,sal_Bool bAddRect)1417 sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
1418 {
1419 	ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1420 	if ( IsAgain() )
1421 		return sal_False;
1422 
1423 	sal_Bool bChanged = sal_False;
1424 	sal_Bool bAlreadyPainted = sal_False;
1425 	// OD 11.11.2002 #104414# - remember frame at complete paint
1426 	SwRect aFrmAtCompletePaint;
1427 
1428 	if ( !pLay->IsValid() || pLay->IsCompletePaint() )
1429 	{
1430 		if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
1431 			pLay->GetPrev()->SetCompletePaint();
1432 
1433 		SwRect aOldRect( pLay->Frm() );
1434 		pLay->Calc();
1435 		if ( aOldRect != pLay->Frm() )
1436 			bChanged = sal_True;
1437 
1438 		sal_Bool bNoPaint = sal_False;
1439         if ( pLay->IsPageBodyFrm() &&
1440              pLay->Frm().Pos() == aOldRect.Pos() &&
1441              pLay->Lower() )
1442 		{
1443             const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1444 			//Einschraenkungen wegen Kopf-/Fusszeilen
1445             if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
1446                 !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
1447 				bNoPaint = sal_True;
1448 		}
1449 
1450 		if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1451 		{
1452 			SwRect aPaint( pLay->Frm() );
1453             // OD 13.02.2003 #i9719#, #105645# - consider border (shadow removed now) for
1454             // page frames -> enlarge paint rectangle correspondingly.
1455             if ( pLay->IsPageFrm() )
1456             {
1457                 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1458                 const int nBorderWidth =
1459                         pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->BorderPxWidth(), 0 ) ).Width();
1460 
1461 				//mod #i6193# added sidebar width
1462                 const SwPostItMgr* pPostItMgr = pImp->GetShell()->GetPostItMgr();
1463 				const int nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
1464                 switch ( pPageFrm->SidebarPosition() )
1465                 {
1466                     case sw::sidebarwindows::SIDEBAR_LEFT:
1467                     {
1468                         aPaint.Left( aPaint.Left() - nBorderWidth - nSidebarWidth);
1469                         aPaint.Right( aPaint.Right() + nBorderWidth );
1470                     }
1471                     break;
1472                     case sw::sidebarwindows::SIDEBAR_RIGHT:
1473                     {
1474                         aPaint.Left( aPaint.Left() - nBorderWidth );
1475                         aPaint.Right( aPaint.Right() + nBorderWidth + nSidebarWidth);
1476                     }
1477                     break;
1478                     case sw::sidebarwindows::SIDEBAR_NONE:
1479                         // nothing to do
1480                     break;
1481                 }
1482 				aPaint.Top( aPaint.Top() - nBorderWidth );
1483 				aPaint.Bottom( aPaint.Bottom() + nBorderWidth );
1484             }
1485 
1486             sal_Bool bPageInBrowseMode = pLay->IsPageFrm();
1487             if( bPageInBrowseMode )
1488             {
1489                 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1490                 if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
1491                     bPageInBrowseMode = sal_False;
1492             }
1493             if( bPageInBrowseMode )
1494 			{
1495                 // NOTE: no vertical layout in online layout
1496                 //Ist die Aenderung ueberhaupt sichtbar?
1497 				if ( pLay->IsCompletePaint() )
1498 				{
1499 					pImp->GetShell()->AddPaintRect( aPaint );
1500 					bAddRect = sal_False;
1501 				}
1502 				else
1503 				{
1504 					sal_uInt16 i;
1505 
1506 					SwRegionRects aRegion( aOldRect );
1507 					aRegion -= aPaint;
1508 					for ( i = 0; i < aRegion.Count(); ++i )
1509 						pImp->GetShell()->AddPaintRect( aRegion[i] );
1510 					aRegion.ChangeOrigin( aPaint );
1511 					aRegion.Remove( 0, aRegion.Count() );
1512 					aRegion.Insert( aPaint, 0 );
1513 					aRegion -= aOldRect;
1514 					for ( i = 0; i < aRegion.Count(); ++i )
1515 						pImp->GetShell()->AddPaintRect( aRegion[i] );
1516 				}
1517 
1518 			}
1519 			else
1520 			{
1521 				pImp->GetShell()->AddPaintRect( aPaint );
1522                 bAlreadyPainted = sal_True;
1523                 // OD 11.11.2002 #104414# - remember frame at complete paint
1524                 aFrmAtCompletePaint = pLay->Frm();
1525 			}
1526 
1527             // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
1528             // between pages (not only for in online mode).
1529             if ( pLay->IsPageFrm() )
1530             {
1531                 const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
1532                 const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
1533                 const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1534                 const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1535 
1536                 if ( bPrev )
1537                 {
1538                     // top
1539                     SwRect aSpaceToPrevPage( pLay->Frm() );
1540                     const SwTwips nTop = aSpaceToPrevPage.Top() - nHalfDocBorder;
1541                     if ( nTop >= 0 )
1542                         aSpaceToPrevPage.Top( nTop );
1543                     aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
1544                     pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1545 
1546                     // left
1547                     aSpaceToPrevPage = pLay->Frm();
1548                     const SwTwips nLeft = aSpaceToPrevPage.Left() - nHalfDocBorder;
1549                     if ( nLeft >= 0 )
1550                         aSpaceToPrevPage.Left( nLeft );
1551                     aSpaceToPrevPage.Right( pLay->Frm().Left() );
1552                     pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1553                 }
1554                 if ( bNext )
1555                 {
1556                     // bottom
1557                     SwRect aSpaceToNextPage( pLay->Frm() );
1558                     aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1559                     aSpaceToNextPage.Top( pLay->Frm().Bottom() );
1560                     pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1561 
1562                     // right
1563                     aSpaceToNextPage = pLay->Frm();
1564                     aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1565                     aSpaceToNextPage.Left( pLay->Frm().Right() );
1566                     pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1567                 }
1568             }
1569         }
1570 		pLay->ResetCompletePaint();
1571 	}
1572 
1573 	if ( IsPaint() && bAddRect &&
1574 		 !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
1575 	{
1576         // OD 15.11.2002 #105155# - vertical layout support
1577         SWRECTFN( pLay );
1578         SwRect aRect( pLay->GetUpper()->PaintArea() );
1579         (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
1580 		if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1581 			pLay->ResetRetouche();
1582 	}
1583 
1584 	if( bAlreadyPainted )
1585 		bAddRect = sal_False;
1586 
1587 	CheckWaitCrsr();
1588 
1589 	if ( IsAgain() )
1590 		return sal_False;
1591 
1592 	//Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1593 
1594 	if ( pLay->IsFtnFrm() )	//Hat keine LayFrms als Lower.
1595 		return bChanged;
1596 
1597 	SwFrm *pLow = pLay->Lower();
1598 	sal_Bool bTabChanged = sal_False;
1599 	while ( pLow && pLow->GetUpper() == pLay )
1600 	{
1601 		if ( pLow->IsLayoutFrm() )
1602 		{
1603 			if ( pLow->IsTabFrm() )
1604 				bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1605 			// bereits zum Loeschen angemeldete Ueberspringen
1606 			else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
1607 				bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1608 		}
1609 		else if ( pImp->GetShell()->IsPaintLocked() )
1610 			//Abkuerzung um die Zyklen zu minimieren, bei Lock kommt das
1611 			//Paint sowieso (Primaer fuer Browse)
1612 			pLow->OptCalc();
1613 
1614 		if ( IsAgain() )
1615 			return sal_False;
1616 		pLow = pLow->GetNext();
1617 	}
1618     // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
1619     // area has been already added and after formatting its lower the frame area
1620     // is enlarged.
1621     if ( bAlreadyPainted &&
1622          ( pLay->Frm().Width() > aFrmAtCompletePaint.Width() ||
1623            pLay->Frm().Height() > aFrmAtCompletePaint.Height() )
1624        )
1625     {
1626         pImp->GetShell()->AddPaintRect( pLay->Frm() );
1627     }
1628     return bChanged || bTabChanged;
1629 }
1630 
FormatLayoutFly(SwFlyFrm * pFly)1631 sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
1632 {
1633 	ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1634 	if ( IsAgain() )
1635 		return sal_False;
1636 
1637 	sal_Bool bChanged = false;
1638 	sal_Bool bAddRect = true;
1639 
1640 	if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1641 	{
1642 		//Der Frame hat sich veraendert, er wird jetzt Formatiert
1643 		const SwRect aOldRect( pFly->Frm() );
1644 		pFly->Calc();
1645 		bChanged = aOldRect != pFly->Frm();
1646 
1647         if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1648                     pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1649             pImp->GetShell()->AddPaintRect( pFly->Frm() );
1650 
1651         if ( bChanged )
1652             pFly->Invalidate();
1653         else
1654             pFly->Validate();
1655 /*
1656         //mba: it's unclear why we should invalidate always, so I remove it
1657 		//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1658 	    if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1659 			pImp->GetShell()->AddPaintRect( pFly->Frm() );
1660 
1661         pFly->Invalidate();
1662 */
1663         bAddRect = false;
1664 		pFly->ResetCompletePaint();
1665 	}
1666 
1667 	if ( IsAgain() )
1668 		return sal_False;
1669 
1670 	//Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1671 	sal_Bool bTabChanged = false;
1672 	SwFrm *pLow = pFly->Lower();
1673 	while ( pLow )
1674 	{
1675 		if ( pLow->IsLayoutFrm() )
1676 		{
1677 			if ( pLow->IsTabFrm() )
1678 				bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1679 			else
1680 				bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1681 		}
1682 		pLow = pLow->GetNext();
1683 	}
1684 	return bChanged || bTabChanged;
1685 }
1686 
1687 // OD 31.10.2002 #104100#
1688 // Implement vertical layout support
FormatLayoutTab(SwTabFrm * pTab,sal_Bool bAddRect)1689 sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
1690 {
1691 	ASSERT( !IsAgain(), "8-) Ungueltige Seite beachten." );
1692 	if ( IsAgain() || !pTab->Lower() )
1693 		return sal_False;
1694 
1695 	IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
1696 	pTimerAccess->BlockIdling();
1697 
1698 	sal_Bool bChanged = sal_False;
1699 	sal_Bool bPainted = sal_False;
1700 
1701 	const SwPageFrm *pOldPage = pTab->FindPageFrm();
1702 
1703 	// OD 31.10.2002 #104100# - vertical layout support
1704 	// use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
1705 	// <SwRectFn fnRect> for table frame <pTab>.
1706 	SWRECTFN( pTab );
1707 
1708 	if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
1709 	{
1710 		if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
1711         {
1712 			pTab->GetPrev()->SetCompletePaint();
1713         }
1714 
1715         const SwRect aOldRect( pTab->Frm() );
1716 		pTab->SetLowersFormatted( sal_False );
1717 		pTab->Calc();
1718 		if ( aOldRect != pTab->Frm() )
1719         {
1720 			bChanged = sal_True;
1721         }
1722         const SwRect aPaintFrm = pTab->PaintArea();
1723 
1724 		if ( IsPaint() && bAddRect )
1725 		{
1726             // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
1727             if ( !pTab->IsCompletePaint() &&
1728                  pTab->IsComplete() &&
1729 				 ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
1730                    // OD 31.10.2002 #104100# - vertical layout support
1731                    (pTab->*fnRect->fnGetLeftMargin)() ) &&
1732                  pTab->Frm().HasArea()
1733                )
1734 			{
1735                 // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
1736                 SwRect aMarginRect;
1737 
1738                 SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
1739                 if ( nLeftMargin > 0)
1740                 {
1741                     aMarginRect = pTab->Frm();
1742                     (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
1743                     pImp->GetShell()->AddPaintRect( aMarginRect );
1744                 }
1745 
1746                 if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
1747                 {
1748                     aMarginRect = pTab->Frm();
1749                     (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
1750                     pImp->GetShell()->AddPaintRect( aMarginRect );
1751                 }
1752 
1753                 SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
1754                 if ( nTopMargin > 0)
1755                 {
1756                     aMarginRect = pTab->Frm();
1757                     (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
1758                     pImp->GetShell()->AddPaintRect( aMarginRect );
1759                 }
1760 
1761                 if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
1762                 {
1763                     aMarginRect = pTab->Frm();
1764                     (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1765                     pImp->GetShell()->AddPaintRect( aMarginRect );
1766                 }
1767 			}
1768 			else if ( pTab->IsCompletePaint() )
1769 			{
1770 				pImp->GetShell()->AddPaintRect( aPaintFrm );
1771 				bAddRect = sal_False;
1772 				bPainted = sal_True;
1773 			}
1774 
1775             if ( pTab->IsRetouche() && !pTab->GetNext() )
1776 			{
1777 				SwRect aRect( pTab->GetUpper()->PaintArea() );
1778                 // OD 04.11.2002 #104100# - vertical layout support
1779                 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1780                 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1781 					pTab->ResetRetouche();
1782 			}
1783 		}
1784 		else
1785 			bAddRect = sal_False;
1786 
1787         if ( pTab->IsCompletePaint() && !pOptTab )
1788 			pOptTab = pTab;
1789 		pTab->ResetCompletePaint();
1790 	}
1791 	if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
1792 	{
1793         // OD 04.10.2002 #102779#
1794         // set correct rectangle for retouche: area between bottom of table frame
1795         // and bottom of paint area of the upper frame.
1796         SwRect aRect( pTab->GetUpper()->PaintArea() );
1797         // OD 04.11.2002 #104100# - vertical layout support
1798         (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1799 		if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1800 			pTab->ResetRetouche();
1801 	}
1802 
1803 	CheckWaitCrsr();
1804 
1805     pTimerAccess->UnblockIdling();
1806 
1807 	//Heftige Abkuerzung!
1808 	if ( pTab->IsLowersFormatted() &&
1809          (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
1810 		return sal_False;
1811 
1812 	//Jetzt noch die Lowers versorgen
1813 	if ( IsAgain() )
1814 		return sal_False;
1815 
1816     // OD 20.10.2003 #112464# - for safety reasons:
1817     // check page number before formatting lowers.
1818     if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
1819         SetNextCycle( sal_True );
1820 
1821     // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
1822     if ( pTab->IsValid() )
1823     {
1824         SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
1825         while ( pLow )
1826         {
1827             bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1828             if ( IsAgain() )
1829                 return sal_False;
1830             pLow = (SwLayoutFrm*)pLow->GetNext();
1831         }
1832     }
1833 
1834 	return bChanged;
1835 }
1836 
1837 /*************************************************************************
1838 |*
1839 |*	SwLayAction::FormatCntnt()
1840 |*
1841 |*	Ersterstellung		MA 30. Oct. 92
1842 |*	Letzte Aenderung	MA 16. Nov. 95
1843 |*
1844 |*************************************************************************/
FormatCntnt(const SwPageFrm * pPage)1845 sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
1846 {
1847 	const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
1848 	const ViewShell *pSh = pRoot->GetCurrShell();
1849 	const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1850 
1851 	while ( pCntnt && pPage->IsAnLower( pCntnt ) )
1852 	{
1853 		//Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
1854 		//Abkuerzungen nutzen.
1855 		const sal_Bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
1856 						   pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
1857 		if ( bFull )
1858 		{
1859 			//Damit wir nacher nicht suchen muessen.
1860 			const sal_Bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
1861 			const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
1862 			const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
1863 
1864 			const SwLayoutFrm*pOldUpper  = pCntnt->GetUpper();
1865 			const SwTabFrm *pTab = pCntnt->FindTabFrm();
1866 			const sal_Bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
1867 			const sal_Bool bOldPaint = IsPaint();
1868 			bPaint = bOldPaint && !(pTab && pTab == pOptTab);
1869 			_FormatCntnt( pCntnt, pPage );
1870             // --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
1871             bPaint = bOldPaint;
1872             // <--
1873 
1874             // OD 2004-05-10 #i28701# - format floating screen object at content frame.
1875             // No format, if action flag <bAgain> is set or action is interrupted.
1876             // OD 2004-08-30 #117736# - allow format on interruption of action, if
1877             // it's the format for this interrupt
1878             // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
1879             // to the object formatter.
1880             if ( !IsAgain() &&
1881                  ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
1882                  pCntnt->IsTxtFrm() &&
1883                  !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
1884                                                       *(pCntnt->FindPageFrm()), this ) )
1885             // <--
1886             {
1887                 return sal_False;
1888             }
1889 
1890 			if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1891 			{
1892 				const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1893 				((SwTxtFrm*)pCntnt)->RecalcAllLines();
1894 				if ( IsPaintExtraData() && IsPaint() &&
1895 					 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1896 					pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1897 			}
1898 
1899 			if ( IsAgain() )
1900 				return sal_False;
1901 
1902 			//Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
1903 			//vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
1904 			//das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
1905 			//Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
1906 			//Absatz verarbeitet wurde.
1907 			if ( (!pTab || (pTab && !bInValid)) )
1908 			{
1909                 CheckIdleEnd();
1910                 // OD 14.04.2003 #106346# - consider interrupt formatting.
1911                 if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
1912                      ( !bBrowse && pPage->IsInvalidLayout() ) ||
1913                      // OD 07.05.2003 #109435# - consider interrupt formatting
1914                      ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
1915                    )
1916 					return sal_False;
1917 			}
1918 			if ( pOldUpper != pCntnt->GetUpper() )
1919 			{
1920 				const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
1921 				if ( nCurNum < pPage->GetPhyPageNum() )
1922 					nPreInvaPage = nCurNum;
1923 
1924 				//Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
1925 				//fangen wir nocheinmal von vorn an damit wir nichts auslassen.
1926 				if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
1927 				{
1928 					SetNextCycle( sal_True );
1929                     // OD 07.05.2003 #109435# - consider interrupt formatting
1930                     if ( !mbFormatCntntOnInterrupt )
1931                     {
1932                         return sal_False;
1933                     }
1934 				}
1935 			}
1936 			//Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
1937 			//den Vorgaenger nocheinmal durchlaufen.
1938 			//So werden einerseits Vorgaenger erwischt, die jetzt fuer Retouche
1939 			//verantwortlich sind, andererseits werden die Fusszeilen
1940 			//auch angefasst.
1941 			sal_Bool bSetCntnt = sal_True;
1942 			if ( pCntntPrev )
1943 			{
1944                 if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
1945 					pPage->InvalidateCntnt();
1946 				if ( pOldUpper != pCntnt->GetUpper() &&
1947 					 pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
1948 				{
1949 					pCntnt = pCntntPrev;
1950 					bSetCntnt = sal_False;
1951 				}
1952 			}
1953 			if ( bSetCntnt )
1954 			{
1955 				if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1956 					 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1957 				{
1958 					const long nBottom = pImp->GetShell()->VisArea().Bottom();
1959 					const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1960 															nBottom, pCntnt );
1961 					if ( !pTmp )
1962 					{
1963 						if ( (!(IS_FLYS && IS_INVAFLY) ||
1964                               !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1965 							  (!pPage->IsInvalidLayout() ||
1966 							   !lcl_FindFirstInvaLay( pPage, nBottom )))
1967 							SetBrowseActionStop( sal_True );
1968                         // OD 14.04.2003 #106346# - consider interrupt formatting.
1969                         if ( !mbFormatCntntOnInterrupt )
1970                         {
1971                             return sal_False;
1972                         }
1973 					}
1974 				}
1975 				pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
1976 			}
1977 
1978 			RESCHEDULE;
1979 		}
1980 		else
1981 		{
1982 			if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1983 			{
1984 				const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1985 				((SwTxtFrm*)pCntnt)->RecalcAllLines();
1986 				if ( IsPaintExtraData() && IsPaint() &&
1987 					 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1988 					pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1989 			}
1990 
1991 			//Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
1992 			if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
1993 				  IsPaint() )
1994 				PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
1995 			if ( IsIdle() )
1996 			{
1997 				CheckIdleEnd();
1998                 // OD 14.04.2003 #106346# - consider interrupt formatting.
1999                 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2000 					return sal_False;
2001 			}
2002 			if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
2003 				 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
2004 			{
2005 				const long nBottom = pImp->GetShell()->VisArea().Bottom();
2006 				const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
2007 													nBottom, pCntnt );
2008 				if ( !pTmp )
2009 				{
2010 					if ( (!(IS_FLYS && IS_INVAFLY) ||
2011                             !lcl_FindFirstInvaObj( pPage, nBottom )) &&
2012 							(!pPage->IsInvalidLayout() ||
2013 							!lcl_FindFirstInvaLay( pPage, nBottom )))
2014 						SetBrowseActionStop( sal_True );
2015                     // OD 14.04.2003 #106346# - consider interrupt formatting.
2016                     if ( !mbFormatCntntOnInterrupt )
2017                     {
2018                         return sal_False;
2019                     }
2020 				}
2021 			}
2022 			pCntnt = pCntnt->GetNextCntntFrm();
2023 		}
2024 	}
2025 	CheckWaitCrsr();
2026 	// OD 14.04.2003 #106346# - consider interrupt formatting.
2027 	return !IsInterrupt() || mbFormatCntntOnInterrupt;
2028 }
2029 /*************************************************************************
2030 |*
2031 |*	SwLayAction::_FormatCntnt()
2032 |*
2033 |* 	Beschreibung		Returnt sal_True wenn der Absatz verarbeitet wurde,
2034 |* 						sal_False wenn es nichts zu verarbeiten gab.
2035 |*	Ersterstellung		MA 07. Dec. 92
2036 |*	Letzte Aenderung	MA 11. Mar. 98
2037 |*
2038 |*************************************************************************/
_FormatCntnt(const SwCntntFrm * pCntnt,const SwPageFrm * pPage)2039 void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
2040                                 const SwPageFrm  *pPage )
2041 {
2042 	//wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
2043 	const sal_Bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
2044 						 !pCntnt->IsRetouche();
2045 	SWRECTFN( pCntnt )
2046 	if ( !bDrawObjsOnly && IsPaint() )
2047 	{
2048 		const SwRect aOldRect( pCntnt->UnionFrm() );
2049 		const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
2050 		pCntnt->OptCalc();
2051 		if( IsAgain() )
2052 			return;
2053         if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
2054                                 (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
2055         {
2056 			pCntnt->SetRetouche();
2057         }
2058         PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
2059 	}
2060 	else
2061 	{
2062 		if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
2063             PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
2064                         (pCntnt->Frm().*fnRect->fnGetBottom)() );
2065 		pCntnt->OptCalc();
2066 	}
2067 }
2068 
2069 /*************************************************************************
2070 |*
2071 |*	SwLayAction::_FormatFlyCntnt()
2072 |*
2073 |*	Beschreibung:
2074 |* 		- Returnt sal_True wenn alle Cntnts des Flys vollstaendig verarbeitet
2075 |* 		  wurden. sal_False wenn vorzeitig unterbrochen wurde.
2076 |*	Ersterstellung		MA 02. Dec. 92
2077 |*	Letzte Aenderung	MA 24. Jun. 96
2078 |*
2079 |*************************************************************************/
_FormatFlyCntnt(const SwFlyFrm * pFly)2080 sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
2081 {
2082 	const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2083 
2084 	while ( pCntnt )
2085 	{
2086         // OD 2004-05-10 #i28701#
2087         _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
2088 
2089         // --> OD 2004-07-23 #i28701# - format floating screen objects
2090         // at content text frame
2091         // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
2092         // to the object formatter.
2093         if ( pCntnt->IsTxtFrm() &&
2094              !SwObjectFormatter::FormatObjsAtFrm(
2095                                             *(const_cast<SwCntntFrm*>(pCntnt)),
2096                                             *(pCntnt->FindPageFrm()), this ) )
2097         // <--
2098         {
2099             // restart format with first content
2100             pCntnt = pFly->ContainsCntnt();
2101             continue;
2102         }
2103         // <--
2104 
2105 		if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
2106 		{
2107 			const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
2108 			((SwTxtFrm*)pCntnt)->RecalcAllLines();
2109 			if ( IsPaintExtraData() && IsPaint() &&
2110 				 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
2111 				pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
2112 		}
2113 
2114 		if ( IsAgain() )
2115 			return sal_False;
2116 
2117 		//wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
2118 		if ( !pFly->IsFlyInCntFrm() )
2119 		{
2120 			CheckIdleEnd();
2121 			// OD 14.04.2003 #106346# - consider interrupt formatting.
2122 			if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2123 				return sal_False;
2124 		}
2125 		pCntnt = pCntnt->GetNextCntntFrm();
2126 	}
2127 	CheckWaitCrsr();
2128 	// OD 14.04.2003 #106346# - consider interrupt formatting.
2129 	return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
2130 }
2131 
IsStopPrt() const2132 sal_Bool SwLayAction::IsStopPrt() const
2133 {
2134 	sal_Bool bResult = sal_False;
2135 
2136 	if (pImp != NULL && pProgress != NULL)
2137 		bResult = pImp->IsStopPrt();
2138 
2139 	return bResult;
2140 }
2141 
2142 /*************************************************************************
2143 |*
2144 |*	SwLayAction::FormatSpelling(), _FormatSpelling()
2145 |*
2146 |*	Ersterstellung		AMA 01. Feb. 96
2147 |*	Letzte Aenderung	AMA 01. Feb. 96
2148 |*
2149 |*************************************************************************/
_DoIdleJob(const SwCntntFrm * pCnt,IdleJobType eJob)2150 sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
2151 {
2152 	ASSERT( pCnt->IsTxtFrm(), "NoTxt neighbor of Txt" );
2153     // robust against misuse by e.g. #i52542#
2154     if( !pCnt->IsTxtFrm() )
2155         return sal_False;
2156 
2157     const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
2158 
2159     bool bProcess = false;
2160     switch ( eJob )
2161     {
2162         case ONLINE_SPELLING :
2163             bProcess = pTxtNode->IsWrongDirty(); break;
2164         case AUTOCOMPLETE_WORDS :
2165             bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
2166         case WORD_COUNT :
2167             bProcess = pTxtNode->IsWordCountDirty(); break;
2168         case SMART_TAGS :   // SMARTTAGS
2169             bProcess = pTxtNode->IsSmartTagDirty(); break;
2170     }
2171 
2172     if( bProcess )
2173 	{
2174         ViewShell *pSh = pImp->GetShell();
2175         if( STRING_LEN == nTxtPos )
2176 		{
2177 			--nTxtPos;
2178             if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
2179 			{
2180 				SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
2181 				if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
2182 				{
2183 					pCntntNode = pCrsr->GetCntntNode();
2184 					nTxtPos =  pCrsr->GetPoint()->nContent.GetIndex();
2185 				}
2186 			}
2187 		}
2188 
2189         switch ( eJob )
2190         {
2191             case ONLINE_SPELLING :
2192             {
2193                 SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode,  *pSh->GetViewOptions(), nTxtPos ) );
2194                 bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
2195                 if( !bPageValid )
2196                     bAllValid = sal_False;
2197                 if ( aRepaint.HasArea() )
2198                     pImp->GetShell()->InvalidateWindows( aRepaint );
2199                 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2200                     return sal_True;
2201                 break;
2202             }
2203             case AUTOCOMPLETE_WORDS :
2204                 ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
2205                 if ( Application::AnyInput( INPUT_ANY ) )
2206                     return sal_True;
2207                 break;
2208             case WORD_COUNT :
2209             {
2210                 const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
2211                 SwDocStat aStat;
2212                 pTxtNode->CountWords( aStat, 0, nEnd );
2213                 if ( Application::AnyInput( INPUT_ANY ) )
2214                     return sal_True;
2215                 break;
2216             }
2217             case SMART_TAGS : // SMARTTAGS
2218             {
2219                 try {
2220                     const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
2221                     bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
2222                     if( !bPageValid )
2223                         bAllValid = sal_False;
2224                     if ( aRepaint.HasArea() )
2225                         pImp->GetShell()->InvalidateWindows( aRepaint );
2226                 } catch( const ::com::sun::star::uno::RuntimeException& e) {
2227                     // #i122885# handle smarttag problems gracefully and provide diagnostics
2228                     DBG_WARNING( rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
2229                 }
2230                 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2231                     return sal_True;
2232                 break;
2233             }
2234         }
2235     }
2236 
2237 	//Die im Absatz verankerten Flys wollen auch mitspielen.
2238 	if ( pCnt->GetDrawObjs() )
2239 	{
2240         const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2241 		for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2242 		{
2243             SwAnchoredObject* pObj = rObjs[i];
2244             if ( pObj->ISA(SwFlyFrm) )
2245 			{
2246                 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
2247 				if ( pFly->IsFlyInCntFrm() )
2248 				{
2249 					const SwCntntFrm *pC = pFly->ContainsCntnt();
2250 					while( pC )
2251 					{
2252                         if ( pC->IsTxtFrm() )
2253                         {
2254                             if ( _DoIdleJob( pC, eJob ) )
2255                                 return sal_True;
2256                         }
2257 						pC = pC->GetNextCntntFrm();
2258 					}
2259 				}
2260 			}
2261 		}
2262 	}
2263 	return sal_False;
2264 }
2265 
DoIdleJob(IdleJobType eJob,sal_Bool bVisAreaOnly)2266 sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
2267 {
2268 	//Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
2269 	//Seiten oder eben aller.
2270 	const ViewShell* pViewShell = pImp->GetShell();
2271 	const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2272 	const SwDoc* pDoc = pViewShell->GetDoc();
2273 
2274     switch ( eJob )
2275     {
2276         case ONLINE_SPELLING :
2277             if( !pViewOptions->IsOnlineSpell() )
2278                 return sal_False;
2279             break;
2280         case AUTOCOMPLETE_WORDS :
2281             if( !pViewOptions->IsAutoCompleteWords() ||
2282                  pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
2283                 return sal_False;
2284             break;
2285         case WORD_COUNT :
2286             if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
2287                 return sal_False;
2288             break;
2289         case SMART_TAGS :
2290             if ( pDoc->GetDocShell()->IsHelpDocument() ||
2291                  pDoc->isXForms() ||
2292                 !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2293                 return sal_False;
2294             break;
2295         default: ASSERT( false, "Unknown idle job type" )
2296     }
2297 
2298 	SwPageFrm *pPage;
2299 	if ( bVisAreaOnly )
2300 		pPage = pImp->GetFirstVisPage();
2301 	else
2302 		pPage = (SwPageFrm*)pRoot->Lower();
2303 
2304 	pCntntNode = NULL;
2305 	nTxtPos = STRING_LEN;
2306 
2307 	while ( pPage )
2308 	{
2309         bPageValid = sal_True;
2310 		const SwCntntFrm *pCnt = pPage->ContainsCntnt();
2311 		while( pCnt && pPage->IsAnLower( pCnt ) )
2312 		{
2313             if ( _DoIdleJob( pCnt, eJob ) )
2314 				return sal_True;
2315 			pCnt = pCnt->GetNextCntntFrm();
2316 		}
2317 		if ( pPage->GetSortedObjs() )
2318 		{
2319 			for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
2320 								i < pPage->GetSortedObjs()->Count(); ++i )
2321 			{
2322                 const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2323                 if ( pObj->ISA(SwFlyFrm) )
2324 				{
2325                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
2326 					const SwCntntFrm *pC = pFly->ContainsCntnt();
2327 					while( pC )
2328 					{
2329                         if ( pC->IsTxtFrm() )
2330                         {
2331                             if ( _DoIdleJob( pC, eJob ) )
2332                                 return sal_True;
2333                         }
2334 						pC = pC->GetNextCntntFrm();
2335 					}
2336 				}
2337 			}
2338 		}
2339 
2340 		if( bPageValid )
2341         {
2342             switch ( eJob )
2343             {
2344                 case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2345                 case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2346                 case WORD_COUNT : pPage->ValidateWordCount(); break;
2347                 case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
2348             }
2349         }
2350 
2351 		pPage = (SwPageFrm*)pPage->GetNext();
2352 		if ( pPage && bVisAreaOnly &&
2353 			 !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
2354              break;
2355     }
2356 	return sal_False;
2357 }
2358 
2359 
2360 #ifdef DBG_UTIL
2361 #if OSL_DEBUG_LEVEL > 1
2362 
2363 /*************************************************************************
2364 |*
2365 |*	void SwLayIdle::SwLayIdle()
2366 |*
2367 |*	Ersterstellung		MA ??
2368 |*	Letzte Aenderung	MA 09. Jun. 94
2369 |*
2370 |*************************************************************************/
ShowIdle(ColorData eColorData)2371 void SwLayIdle::ShowIdle( ColorData eColorData )
2372 {
2373 	if ( !bIndicator )
2374 	{
2375 		bIndicator = sal_True;
2376 		Window *pWin = pImp->GetShell()->GetWin();
2377 		if ( pWin )
2378 		{
2379 			Rectangle aRect( 0, 0, 5, 5 );
2380 			aRect = pWin->PixelToLogic( aRect );
2381 			// OD 2004-04-23 #116347#
2382 			pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
2383 			pWin->SetFillColor( eColorData );
2384 			pWin->SetLineColor();
2385 			pWin->DrawRect( aRect );
2386 			pWin->Pop();
2387 		}
2388 	}
2389 }
2390 #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
2391 #else
2392 #define SHOW_IDLE( ColorData )
2393 #endif
2394 #else
2395 #define SHOW_IDLE( ColorData )
2396 #endif
2397 
2398 /*************************************************************************
2399 |*
2400 |*	void SwLayIdle::SwLayIdle()
2401 |*
2402 |*	Ersterstellung		MA 30. Oct. 92
2403 |*	Letzte Aenderung	MA 23. May. 95
2404 |*
2405 |*************************************************************************/
SwLayIdle(SwRootFrm * pRt,SwViewImp * pI)2406 SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
2407 	pRoot( pRt ),
2408 	pImp( pI )
2409 #ifdef DBG_UTIL
2410 #if OSL_DEBUG_LEVEL > 1
2411 	, bIndicator( sal_False )
2412 #endif
2413 #endif
2414 {
2415 	pImp->pIdleAct = this;
2416 
2417 	SHOW_IDLE( COL_LIGHTRED );
2418 
2419 	pImp->GetShell()->EnableSmooth( sal_False );
2420 
2421 	//Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
2422 	//zu tun war wird das IdleFormat angestossen.
2423     if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
2424          !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
2425          !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
2426     {
2427 		//Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
2428 		//Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
2429 		//Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
2430 		//Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
2431 		//wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
2432 		SvBools aBools;
2433 		ViewShell *pSh = pImp->GetShell();
2434 		do
2435 		{	++pSh->nStartAction;
2436 			sal_Bool bVis = sal_False;
2437 			if ( pSh->ISA(SwCrsrShell) )
2438 			{
2439 #ifdef SW_CRSR_TIMER
2440 				((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( sal_False );
2441 #endif
2442 				bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
2443 			}
2444 			aBools.push_back( bVis );
2445 			pSh = (ViewShell*)pSh->GetNext();
2446 		} while ( pSh != pImp->GetShell() );
2447 
2448 		SwLayAction aAction( pRoot, pImp );
2449 		aAction.SetInputType( INPUT_ANY );
2450 		aAction.SetIdle( sal_True );
2451 		aAction.SetWaitAllowed( sal_False );
2452 		aAction.Action();
2453 
2454 		//Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
2455 		//sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
2456 		sal_Bool bActions = sal_False;
2457 		sal_uInt16 nBoolIdx = 0;
2458 		do
2459         {
2460             --pSh->nStartAction;
2461 
2462             if ( pSh->Imp()->GetRegion() )
2463 				bActions = sal_True;
2464 			else
2465 			{
2466 				SwRect aTmp( pSh->VisArea() );
2467 				pSh->UISizeNotify();
2468 
2469                 // --> FME 2006-08-03 #137134#
2470                 // Are we supposed to crash if pSh isn't a cursor shell?!
2471                 // bActions |= aTmp != pSh->VisArea() ||
2472                 //             aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
2473 
2474                 // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2475                 // and the cursor is visible.
2476                 bActions |= aTmp != pSh->VisArea();
2477                 if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
2478                 {
2479                     bActions |= aBools[nBoolIdx] !=
2480                                 static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
2481                 }
2482             }
2483 
2484 			pSh = (ViewShell*)pSh->GetNext();
2485 			++nBoolIdx;
2486 		} while ( pSh != pImp->GetShell() );
2487 
2488 		if ( bActions )
2489 		{
2490 			//Start- EndActions aufsetzen. ueber die CrsrShell, damit der
2491 			//Cursor/Selektion und die VisArea korrekt gesetzt werden.
2492 			nBoolIdx = 0;
2493 			do
2494             {
2495                 sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
2496 
2497 				if ( bCrsrShell )
2498 					((SwCrsrShell*)pSh)->SttCrsrMove();
2499 //				else
2500 //					pSh->StartAction();
2501 
2502 				//Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
2503 				//gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
2504 				//deren Loesung unverhaeltnissmaessig aufwendig waere.
2505 				//fix(18176):
2506                 SwViewImp *pViewImp = pSh->Imp();
2507 				sal_Bool bUnlock = sal_False;
2508                 if ( pViewImp->GetRegion() )
2509 				{
2510                     pViewImp->DelRegion();
2511 
2512 					//Fuer Repaint mit virtuellem Device sorgen.
2513 					pSh->LockPaint();
2514 					bUnlock = sal_True;
2515 				}
2516 
2517 				if ( bCrsrShell )
2518 					//Wenn der Crsr sichbar war wieder sichbar machen, sonst
2519 					//EndCrsrMove mit sal_True fuer IdleEnd.
2520 					((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
2521 //				else
2522 //					pSh->EndAction();
2523 				if( bUnlock )
2524 				{
2525 					if( bCrsrShell )
2526 					{
2527 						// UnlockPaint overwrite the selection from the
2528 						// CrsrShell and calls the virtual method paint
2529 						// to fill the virtual device. This fill dont have
2530 						// paint the selection! -> Set the focus flag at
2531 						// CrsrShell and it dont paint the selection.
2532 						((SwCrsrShell*)pSh)->ShLooseFcs();
2533 						pSh->UnlockPaint( sal_True );
2534 						((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
2535 					}
2536 					else
2537 						pSh->UnlockPaint( sal_True );
2538 				}
2539 
2540 				pSh = (ViewShell*)pSh->GetNext();
2541 				++nBoolIdx;
2542 
2543 			} while ( pSh != pImp->GetShell() );
2544 		}
2545 
2546 		if ( !aAction.IsInterrupt() )
2547         {
2548             if ( !DoIdleJob( WORD_COUNT, sal_False ) )
2549                 if ( !DoIdleJob( SMART_TAGS, sal_False ) )
2550                     if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
2551                         DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
2552         }
2553 
2554         bool bInValid = false;
2555 		const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
2556         const ViewShell* pViewShell = pImp->GetShell();
2557         // See conditions in DoIdleJob()
2558         const sal_Bool bSpell     = rVOpt.IsOnlineSpell();
2559         const sal_Bool bACmplWrd  = rVOpt.IsAutoCompleteWords();
2560         const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
2561         const sal_Bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
2562                                 !pViewShell->GetDoc()->isXForms() &&
2563                                 SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
2564 
2565 		SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
2566 		do
2567         {
2568             bInValid = pPg->IsInvalidCntnt()    || pPg->IsInvalidLayout() ||
2569 					   pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
2570 					   pPg->IsInvalidFlyInCnt() ||
2571 					   (bSpell && pPg->IsInvalidSpelling()) ||
2572                        (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
2573                        (bWordCount && pPg->IsInvalidWordCount()) ||
2574                        (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
2575 
2576 			pPg = (SwPageFrm*)pPg->GetNext();
2577 
2578         } while ( pPg && !bInValid );
2579 
2580         if ( !bInValid )
2581 		{
2582 			pRoot->ResetIdleFormat();
2583 			SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
2584             pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
2585 		}
2586 	}
2587 
2588 	pImp->GetShell()->EnableSmooth( sal_True );
2589 
2590     if( pImp->IsAccessible() )
2591         pImp->FireAccessibleEvents();
2592 
2593 #ifdef DBG_UTIL
2594 #if OSL_DEBUG_LEVEL > 1
2595 	if ( bIndicator && pImp->GetShell()->GetWin() )
2596 	{
2597 		// #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
2598 		// This should be replaced by an overlay object in the future, anyways. Since it's only for debug
2599 		// purposes, it is not urgent.
2600 		static bool bCheckWithoutInvalidating(true);
2601 		if(bCheckWithoutInvalidating)
2602 		{
2603 			bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
2604 		}
2605 		else
2606 		{
2607 			Rectangle aRect( 0, 0, 5, 5 );
2608 			aRect = pImp->GetShell()->GetWin()->PixelToLogic( aRect );
2609 			pImp->GetShell()->GetWin()->Invalidate( aRect );
2610 		}
2611 	}
2612 #endif
2613 #endif
2614 }
2615 
~SwLayIdle()2616 SwLayIdle::~SwLayIdle()
2617 {
2618 	pImp->pIdleAct = 0;
2619 }
2620 
2621 /* vim: set noet sw=4 ts=4: */
2622