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