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