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