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