LibreOffice Module sw (master)  1
trvlfrm.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 <hints.hxx>
21 #include <comphelper/flagguard.hxx>
22 #include <tools/line.hxx>
23 #include <editeng/opaqitem.hxx>
24 #include <editeng/protitem.hxx>
25 #include <vcl/settings.hxx>
26 #include <fmtpdsc.hxx>
27 #include <fmtsrnd.hxx>
28 #include <pagedesc.hxx>
29 #include <pagefrm.hxx>
30 #include <rootfrm.hxx>
31 #include <ftnfrm.hxx>
32 #include <flyfrm.hxx>
33 #include <tabfrm.hxx>
34 #include <rowfrm.hxx>
35 #include <cellfrm.hxx>
36 #include <txtfrm.hxx>
37 #include <notxtfrm.hxx>
38 #include <viewopt.hxx>
40 #include <viscrs.hxx>
41 #include <dflyobj.hxx>
42 #include <crstate.hxx>
43 #include <dcontact.hxx>
44 #include <sortedobjs.hxx>
45 #include <txatbase.hxx>
46 #include <fmtfld.hxx>
47 #include <fldbas.hxx>
48 #include <frmatr.hxx>
49 #include <frmtool.hxx>
50 #include <ndtxt.hxx>
51 #include <undobj.hxx>
52 
53 #include <swselectionlist.hxx>
54 #include <comphelper/lok.hxx>
55 
56 namespace {
57  bool lcl_GetCursorOfst_Objects( const SwPageFrame* pPageFrame, bool bSearchBackground,
58  SwPosition *pPos, Point const & rPoint, SwCursorMoveState* pCMS )
59  {
60  bool bRet = false;
61  Point aPoint( rPoint );
62  SwOrderIter aIter( pPageFrame );
63  aIter.Top();
64  while ( aIter() )
65  {
66  const SwVirtFlyDrawObj* pObj =
67  static_cast<const SwVirtFlyDrawObj*>(aIter());
68  const SwAnchoredObject* pAnchoredObj = GetUserCall( aIter() )->GetAnchoredObj( aIter() );
69  const SwFormatSurround& rSurround = pAnchoredObj->GetFrameFormat().GetSurround();
70  const SvxOpaqueItem& rOpaque = pAnchoredObj->GetFrameFormat().GetOpaque();
71  bool bInBackground = ( rSurround.GetSurround() == css::text::WrapTextMode_THROUGH ) && !rOpaque.GetValue();
72 
73  bool bBackgroundMatches = bInBackground == bSearchBackground;
74 
75  const SwFlyFrame* pFly = pObj ? pObj->GetFlyFrame() : nullptr;
76  if ( pFly && bBackgroundMatches &&
77  ( ( pCMS && pCMS->m_bSetInReadOnly ) ||
78  !pFly->IsProtected() ) &&
79  pFly->GetCursorOfst( pPos, aPoint, pCMS ) )
80  {
81  bRet = true;
82  break;
83  }
84 
85  if ( pCMS && pCMS->m_bStop )
86  return false;
87  aIter.Prev();
88  }
89  return bRet;
90  }
91 
92  double lcl_getDistance( const SwRect& rRect, const Point& rPoint )
93  {
94  double nDist = 0.0;
95 
96  // If the point is inside the rectangle, then distance is 0
97  // Otherwise, compute the distance to the center of the rectangle.
98  if ( !rRect.IsInside( rPoint ) )
99  {
100  tools::Line aLine( rPoint, rRect.Center( ) );
101  nDist = aLine.GetLength( );
102  }
103 
104  return nDist;
105  }
106 }
107 
108 //For SwFlyFrame::GetCursorOfst
110 {
111 public:
112  // So the compiler can initialize the class already. No DTOR and member
113  // as public members
117 
118  bool ChkOsz( const SwFlyFrame *pFly )
119  {
120  bool bRet = true;
121  if ( pFly != pStack1 && pFly != pStack2 )
122  {
123  pStack1 = pStack2;
124  pStack2 = pFly;
125  bRet = false;
126  }
127  return bRet;
128  }
129 
130  void Entry( const SwFlyFrame *pFly )
131  {
132  if ( !pEntry )
133  pEntry = pStack1 = pFly;
134  }
135 
136  void Exit( const SwFlyFrame *pFly )
137  {
138  if ( pFly == pEntry )
139  pEntry = pStack1 = pStack2 = nullptr;
140  }
141 };
142 
143 static SwCursorOszControl g_OszCtrl = { nullptr, nullptr, nullptr };
144 
147  SwCursorMoveState* pCMS, bool ) const
148 {
149  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
150  bool bRet = false;
151  const SwFrame *pFrame = Lower();
152  while ( !bRet && pFrame )
153  {
154  pFrame->Calc(pRenderContext);
155 
156  // #i43742# New function
157  const bool bContentCheck = pFrame->IsTextFrame() && pCMS && pCMS->m_bContentCheck;
158  const SwRect aPaintRect( bContentCheck ?
159  pFrame->UnionFrame() :
160  pFrame->GetPaintArea() );
161 
162  if ( aPaintRect.IsInside( rPoint ) &&
163  ( bContentCheck || pFrame->GetCursorOfst( pPos, rPoint, pCMS ) ) )
164  bRet = true;
165  else
166  pFrame = pFrame->GetNext();
167  if ( pCMS && pCMS->m_bStop )
168  return false;
169  }
170  return bRet;
171 }
172 
176  SwCursorMoveState* pCMS, bool bTestBackground ) const
177 {
178  Point aPoint( rPoint );
179 
180  // check, if we have to adjust the point
181  if ( !getFrameArea().IsInside( aPoint ) )
182  {
183  aPoint.setX( std::max( aPoint.X(), getFrameArea().Left() ) );
184  aPoint.setX( std::min( aPoint.X(), getFrameArea().Right() ) );
185  aPoint.setY( std::max( aPoint.Y(), getFrameArea().Top() ) );
186  aPoint.setY( std::min( aPoint.Y(), getFrameArea().Bottom() ) );
187  }
188 
189  bool bRet = false;
190  //Could it be a free flying one?
191  //If his content should be protected, we can't set the Cursor in it, thus
192  //all changes should be impossible.
193  if ( GetSortedObjs() )
194  {
195  bRet = lcl_GetCursorOfst_Objects( this, false, pPos, rPoint, pCMS );
196  }
197 
198  if ( !bRet )
199  {
200  SwPosition aBackPos( *pPos );
201  SwPosition aTextPos( *pPos );
202 
203  //We fix the StartPoint if no Content below the page 'answers' and then
204  //start all over again one page before the current one.
205  //However we can't use Flys in such a case.
206  if (!SwLayoutFrame::GetCursorOfst(&aTextPos, aPoint, pCMS))
207  {
208  if ( pCMS && (pCMS->m_bStop || pCMS->m_bExactOnly) )
209  {
210  pCMS->m_bStop = true;
211  return false;
212  }
213 
214  const SwContentFrame *pCnt = GetContentPos( aPoint, false, false, pCMS, false );
215  // GetContentPos may have modified pCMS
216  if ( pCMS && pCMS->m_bStop )
217  return false;
218 
219  bool bTextRet = false;
220 
221  OSL_ENSURE( pCnt, "Cursor is gone to a Black hole" );
222  if( pCMS && pCMS->m_pFill && pCnt->IsTextFrame() )
223  bTextRet = pCnt->GetCursorOfst( &aTextPos, rPoint, pCMS );
224  else
225  bTextRet = pCnt->GetCursorOfst( &aTextPos, aPoint, pCMS );
226 
227  if ( !bTextRet )
228  {
229  // Set point to pCnt, delete mark
230  // this may happen, if pCnt is hidden
231  if (pCnt->IsTextFrame())
232  {
233  aTextPos = static_cast<SwTextFrame const*>(pCnt)->MapViewToModelPos(TextFrameIndex(0));
234  }
235  else
236  {
237  assert(pCnt->IsNoTextFrame());
238  aTextPos = SwPosition( *static_cast<SwNoTextFrame const*>(pCnt)->GetNode() );
239  }
240  }
241  }
242 
243  SwContentNode* pContentNode = aTextPos.nNode.GetNode().GetContentNode();
244  bool bConsiderBackground = true;
245  // If the text position is a clickable field, then that should have priority.
246  if (pContentNode && pContentNode->IsTextNode())
247  {
248  SwTextNode* pTextNd = pContentNode->GetTextNode();
249  SwTextAttr* pTextAttr = pTextNd->GetTextAttrForCharAt(aTextPos.nContent.GetIndex(), RES_TXTATR_FIELD);
250  if (pTextAttr)
251  {
252  const SwField* pField = pTextAttr->GetFormatField().GetField();
253  if (pField->IsClickable())
254  bConsiderBackground = false;
255  }
256  }
257 
258  bool bBackRet = false;
259  // Check objects in the background if nothing else matched
260  if ( GetSortedObjs() )
261  {
262  bBackRet = lcl_GetCursorOfst_Objects( this, true, &aBackPos, rPoint, pCMS );
263  }
264 
265  if (bConsiderBackground && bTestBackground && bBackRet)
266  {
267  (*pPos) = aBackPos;
268  }
269  else if (!bBackRet)
270  {
271  (*pPos) = aTextPos;
272  }
273  else // bBackRet && !(bConsiderBackground && bTestBackground)
274  {
275  /* In order to provide a selection as accurate as possible when we have both
276  * text and background object, then we compute the distance between both
277  * would-be positions and the click point. The shortest distance wins.
278  */
279  double nTextDistance = 0;
280  bool bValidTextDistance = false;
281  if (pContentNode)
282  {
283  SwContentFrame* pTextFrame = pContentNode->getLayoutFrame( getRootFrame( ) );
284 
285  // try this again but prefer the "previous" position
286  SwCursorMoveState aMoveState;
287  SwCursorMoveState *const pState(pCMS ? pCMS : &aMoveState);
289  pState->m_bPosMatchesBounds, true);
290  SwPosition prevTextPos(*pPos);
291  SwLayoutFrame::GetCursorOfst(&prevTextPos, aPoint, pState);
292 
293  SwRect aTextRect;
294  pTextFrame->GetCharRect(aTextRect, prevTextPos);
295 
296  if (prevTextPos.nContent < pContentNode->Len())
297  {
298  // aRextRect is just a line on the left edge of the
299  // previous character; to get a better measure from
300  // lcl_getDistance, extend that to a rectangle over
301  // the entire character.
302  SwPosition const nextTextPos(prevTextPos.nNode,
303  SwIndex(prevTextPos.nContent, +1));
304  SwRect nextTextRect;
305  pTextFrame->GetCharRect(nextTextRect, nextTextPos);
306  SwRectFnSet aRectFnSet(pTextFrame);
307  if (aRectFnSet.GetTop(aTextRect) ==
308  aRectFnSet.GetTop(nextTextRect)) // same line?
309  {
310  // need to handle mixed RTL/LTR portions somehow
311  if (aRectFnSet.GetLeft(aTextRect) <
312  aRectFnSet.GetLeft(nextTextRect))
313  {
314  aRectFnSet.SetRight( aTextRect,
315  aRectFnSet.GetLeft(nextTextRect));
316  }
317  else // RTL
318  {
319  aRectFnSet.SetLeft( aTextRect,
320  aRectFnSet.GetLeft(nextTextRect));
321  }
322  }
323  }
324 
325  nTextDistance = lcl_getDistance(aTextRect, rPoint);
326  bValidTextDistance = true;
327  }
328 
329  double nBackDistance = 0;
330  bool bValidBackDistance = false;
331  SwContentNode* pBackNd = aBackPos.nNode.GetNode( ).GetContentNode( );
332  if ( pBackNd && bConsiderBackground)
333  {
334  // FIXME There are still cases were we don't have the proper node here.
335  SwContentFrame* pBackFrame = pBackNd->getLayoutFrame( getRootFrame( ) );
336  SwRect rBackRect;
337  if (pBackFrame)
338  {
339  pBackFrame->GetCharRect( rBackRect, aBackPos );
340 
341  nBackDistance = lcl_getDistance( rBackRect, rPoint );
342  bValidBackDistance = true;
343  }
344  }
345 
346  if ( bValidTextDistance && bValidBackDistance && basegfx::fTools::more( nTextDistance, nBackDistance ) )
347  {
348  (*pPos) = aBackPos;
349  }
350  else
351  {
352  (*pPos) = aTextPos;
353  }
354  }
355  }
356 
357  rPoint = aPoint;
358  return true;
359 }
360 
361 bool SwLayoutFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
362 {
363  if( rRect.IsOver(GetPaintArea()) )
364  {
365  const SwFrame* pFrame = Lower();
366  while( pFrame )
367  {
368  pFrame->FillSelection( rList, rRect );
369  pFrame = pFrame->GetNext();
370  }
371  }
372  return false;
373 }
374 
375 bool SwPageFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
376 {
377  bool bRet = false;
378  if( rRect.IsOver(GetPaintArea()) )
379  {
380  bRet = SwLayoutFrame::FillSelection( rList, rRect );
381  if( GetSortedObjs() )
382  {
383  const SwSortedObjs &rObjs = *GetSortedObjs();
384  for (SwAnchoredObject* pAnchoredObj : rObjs)
385  {
386  if( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr )
387  continue;
388  const SwFlyFrame* pFly = static_cast<const SwFlyFrame*>(pAnchoredObj);
389  if( pFly->FillSelection( rList, rRect ) )
390  bRet = true;
391  }
392  }
393  }
394  return bRet;
395 }
396 
397 bool SwRootFrame::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
398 {
399  const SwFrame *pPage = Lower();
400  const long nBottom = rRect.Bottom();
401  while( pPage )
402  {
403  if( pPage->getFrameArea().Top() < nBottom )
404  {
405  if( pPage->getFrameArea().Bottom() > rRect.Top() )
406  pPage->FillSelection( aSelList, rRect );
407  pPage = pPage->GetNext();
408  }
409  else
410  pPage = nullptr;
411  }
412  return !aSelList.isEmpty();
413 }
414 
420  SwCursorMoveState* pCMS, bool bTestBackground ) const
421 {
422  const bool bOldAction = IsCallbackActionEnabled();
423  const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( false );
424  OSL_ENSURE( (Lower() && Lower()->IsPageFrame()), "No PageFrame found." );
425  if( pCMS && pCMS->m_pFill )
426  pCMS->m_bFillRet = false;
427  Point aOldPoint = rPoint;
428 
429  // search for page containing rPoint. The borders around the pages are considered
430  const SwPageFrame* pPage = GetPageAtPos( rPoint, nullptr, true );
431 
432  // #i95626#
433  // special handling for <rPoint> beyond root frames area
434  if ( !pPage &&
435  rPoint.X() > getFrameArea().Right() &&
436  rPoint.Y() > getFrameArea().Bottom() )
437  {
438  pPage = dynamic_cast<const SwPageFrame*>(Lower());
439  while ( pPage && pPage->GetNext() )
440  {
441  pPage = dynamic_cast<const SwPageFrame*>(pPage->GetNext());
442  }
443  }
444  if ( pPage )
445  {
446  pPage->SwPageFrame::GetCursorOfst( pPos, rPoint, pCMS, bTestBackground );
447  }
448 
449  const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( bOldAction );
450  if( pCMS )
451  {
452  if( pCMS->m_bStop )
453  return false;
454  if( pCMS->m_pFill )
455  return pCMS->m_bFillRet;
456  }
457  return aOldPoint == rPoint;
458 }
459 
467  SwCursorMoveState* pCMS, bool ) const
468 {
469  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
470  // cell frame does not necessarily have a lower (split table cell)
471  if ( !Lower() )
472  return false;
473 
474  if ( !(pCMS && pCMS->m_bSetInReadOnly) &&
475  GetFormat()->GetProtect().IsContentProtected() )
476  return false;
477 
478  if ( pCMS && pCMS->m_eState == MV_TBLSEL )
479  {
480  const SwTabFrame *pTab = FindTabFrame();
481  if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
482  {
483  pCMS->m_bStop = true;
484  return false;
485  }
486  }
487 
488  if ( Lower() )
489  {
490  if ( Lower()->IsLayoutFrame() )
491  return SwLayoutFrame::GetCursorOfst( pPos, rPoint, pCMS );
492  else
493  {
494  Calc(pRenderContext);
495  bool bRet = false;
496 
497  const SwFrame *pFrame = Lower();
498  while ( pFrame && !bRet )
499  {
500  pFrame->Calc(pRenderContext);
501  if ( pFrame->getFrameArea().IsInside( rPoint ) )
502  {
503  bRet = pFrame->GetCursorOfst( pPos, rPoint, pCMS );
504  if ( pCMS && pCMS->m_bStop )
505  return false;
506  }
507  pFrame = pFrame->GetNext();
508  }
509  if ( !bRet )
510  {
511  const bool bFill = pCMS && pCMS->m_pFill;
512  Point aPoint( rPoint );
513  const SwContentFrame *pCnt = GetContentPos( rPoint, true );
514  if( bFill && pCnt->IsTextFrame() )
515  {
516  rPoint = aPoint;
517  }
518  pCnt->GetCursorOfst( pPos, rPoint, pCMS );
519  }
520  return true;
521  }
522  }
523 
524  return false;
525 }
526 
527 //Problem: If two Flys have the same size and share the same position then
528 //they end inside each other.
529 //Because we recursively check if a Point doesn't randomly lie inside another
530 //fly which lies completely inside the current Fly we could trigger an endless
531 //loop with the mentioned situation above.
532 //Using the helper class SwCursorOszControl we prevent the recursion. During
533 //a recursion GetCursorOfst picks the one which lies on top.
535  SwCursorMoveState* pCMS, bool ) const
536 {
537  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
538  g_OszCtrl.Entry( this );
539 
540  //If the Points lies inside the Fly, we try hard to set the Cursor inside it.
541  //However if the Point sits inside a Fly which is completely located inside
542  //the current one, we call GetCursorOfst for it.
543  Calc(pRenderContext);
544  bool bInside = getFrameArea().IsInside( rPoint ) && Lower();
545  bool bRet = false;
546 
547  //If a Frame contains a graphic, but only text was requested, it basically
548  //won't accept the Cursor.
549  if ( bInside && pCMS && pCMS->m_eState == MV_SETONLYTEXT &&
550  (!Lower() || Lower()->IsNoTextFrame()) )
551  bInside = false;
552 
553  const SwPageFrame *pPage = FindPageFrame();
554  if ( bInside && pPage && pPage->GetSortedObjs() )
555  {
556  SwOrderIter aIter( pPage );
557  aIter.Top();
558  while ( aIter() && !bRet )
559  {
560  const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
561  const SwFlyFrame* pFly = pObj ? pObj->GetFlyFrame() : nullptr;
562  if ( pFly && pFly->getFrameArea().IsInside( rPoint ) &&
563  getFrameArea().IsInside( pFly->getFrameArea() ) )
564  {
565  if (g_OszCtrl.ChkOsz(pFly))
566  break;
567  bRet = pFly->GetCursorOfst( pPos, rPoint, pCMS );
568  if ( bRet )
569  break;
570  if ( pCMS && pCMS->m_bStop )
571  return false;
572  }
573  aIter.Next();
574  }
575  }
576 
577  while ( bInside && !bRet )
578  {
579  const SwFrame *pFrame = Lower();
580  while ( pFrame && !bRet )
581  {
582  pFrame->Calc(pRenderContext);
583  if ( pFrame->getFrameArea().IsInside( rPoint ) )
584  {
585  bRet = pFrame->GetCursorOfst( pPos, rPoint, pCMS );
586  if ( pCMS && pCMS->m_bStop )
587  return false;
588  }
589  pFrame = pFrame->GetNext();
590  }
591  if ( !bRet )
592  {
593  const bool bFill = pCMS && pCMS->m_pFill;
594  Point aPoint( rPoint );
595  const SwContentFrame *pCnt = GetContentPos( rPoint, true, false, pCMS );
596  if ( pCMS && pCMS->m_bStop )
597  return false;
598  if( bFill && pCnt->IsTextFrame() )
599  {
600  rPoint = aPoint;
601  }
602  pCnt->GetCursorOfst( pPos, rPoint, pCMS );
603  bRet = true;
604  }
605  }
606  g_OszCtrl.Exit( this );
607  return bRet;
608 }
609 
612 {
613  if( &pPam->GetNode() != GetNode() )
614  return false;
615  const_cast<SwContentNode*>(GetNode())->
616  MakeStartIndex(&pPam->GetPoint()->nContent);
617  return true;
618 }
619 
620 bool SwNoTextFrame::RightMargin(SwPaM *pPam, bool) const
621 {
622  if( &pPam->GetNode() != GetNode() )
623  return false;
624  const_cast<SwContentNode*>(GetNode())->
625  MakeEndIndex(&pPam->GetPoint()->nContent);
626  return true;
627 }
628 
629 static const SwContentFrame *lcl_GetNxtCnt( const SwContentFrame* pCnt )
630 {
631  return pCnt->GetNextContentFrame();
632 }
633 
634 static const SwContentFrame *lcl_GetPrvCnt( const SwContentFrame* pCnt )
635 {
636  return pCnt->GetPrevContentFrame();
637 }
638 
639 typedef const SwContentFrame *(*GetNxtPrvCnt)( const SwContentFrame* );
640 
642 static bool lcl_IsInRepeatedHeadline( const SwFrame *pFrame,
643  const SwTabFrame** ppTFrame = nullptr )
644 {
645  const SwTabFrame *pTab = pFrame->FindTabFrame();
646  if( ppTFrame )
647  *ppTFrame = pTab;
648  return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrame );
649 }
650 
652 //MA 1998-01-26: Chg also skip other protected areas
653 //FME: Skip follow flow cells
655  GetNxtPrvCnt fnNxtPrv,
656  bool bMissHeadline,
657  bool bInReadOnly,
658  bool bMissFollowFlowLine )
659 {
660  if ( pCnt && pCnt->IsInTab() )
661  {
662  bool bProtect = true;
663  while ( pCnt && bProtect )
664  {
665  const SwLayoutFrame *pCell = pCnt->GetUpper();
666  while ( pCell && !pCell->IsCellFrame() )
667  pCell = pCell->GetUpper();
668  if ( !pCell ||
669  ( ( bInReadOnly || !pCell->GetFormat()->GetProtect().IsContentProtected() ) &&
670  ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
671  ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
672  !pCell->IsCoveredCell() ) )
673  bProtect = false;
674  else
675  pCnt = (*fnNxtPrv)( pCnt );
676  }
677  }
678  else if ( !bInReadOnly )
679  while ( pCnt && pCnt->IsProtected() )
680  pCnt = (*fnNxtPrv)( pCnt );
681 
682  return pCnt;
683 }
684 
685 static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
686  GetNxtPrvCnt fnNxtPrv, bool bInReadOnly )
687 {
688  OSL_ENSURE( FrameContainsNode(*pStart, pPam->GetNode().GetIndex()),
689  "lcl_UpDown doesn't work for others." );
690 
691  const SwContentFrame *pCnt = nullptr;
692 
693  //We have to cheat a little bit during a table selection: Go to the
694  //beginning of the cell while going up and go to the end of the cell while
695  //going down.
696  bool bTableSel = false;
697  if ( pStart->IsInTab() &&
698  pPam->GetNode().StartOfSectionNode() !=
699  pPam->GetNode( false ).StartOfSectionNode() )
700  {
701  bTableSel = true;
702  const SwLayoutFrame *pCell = pStart->GetUpper();
703  while ( !pCell->IsCellFrame() )
704  pCell = pCell->GetUpper();
705 
706  // Check, if cell has a Prev/Follow cell:
707  const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
708  const SwLayoutFrame* pTmpCell = bFwd ?
709  static_cast<const SwCellFrame*>(pCell)->GetFollowCell() :
710  static_cast<const SwCellFrame*>(pCell)->GetPreviousCell();
711 
712  const SwContentFrame* pTmpStart = pStart;
713  while ( pTmpCell && nullptr != ( pTmpStart = pTmpCell->ContainsContent() ) )
714  {
715  pCell = pTmpCell;
716  pTmpCell = bFwd ?
717  static_cast<const SwCellFrame*>(pCell)->GetFollowCell() :
718  static_cast<const SwCellFrame*>(pCell)->GetPreviousCell();
719  }
720  const SwContentFrame *pNxt = pCnt = pTmpStart;
721 
722  while ( pCell->IsAnLower( pNxt ) )
723  {
724  pCnt = pNxt;
725  pNxt = (*fnNxtPrv)( pNxt );
726  }
727  }
728 
729  pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
730  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
731 
732  const SwTabFrame *pStTab = pStart->FindTabFrame();
733  const SwTabFrame *pTable = nullptr;
734  const bool bTab = pStTab || (pCnt && pCnt->IsInTab());
735  bool bEnd = !bTab;
736 
737  const SwFrame* pVertRefFrame = pStart;
738  if ( bTableSel && pStTab )
739  pVertRefFrame = pStTab;
740  SwRectFnSet aRectFnSet(pVertRefFrame);
741 
742  SwTwips nX = 0;
743  if ( bTab )
744  {
745  // pStart or pCnt is inside a table. nX will be used for travelling:
746  SwRect aRect( pStart->getFrameArea() );
747  pStart->GetCharRect( aRect, *pPam->GetPoint() );
748  Point aCenter = aRect.Center();
749  nX = aRectFnSet.IsVert() ? aCenter.Y() : aCenter.X();
750 
751  pTable = pCnt ? pCnt->FindTabFrame() : nullptr;
752  if ( !pTable )
753  pTable = pStTab;
754 
755  if ( pStTab &&
756  !pStTab->GetUpper()->IsInTab() &&
757  !pTable->GetUpper()->IsInTab() )
758  {
759  const SwFrame *pCell = pStart->GetUpper();
760  while ( pCell && !pCell->IsCellFrame() )
761  pCell = pCell->GetUpper();
762  OSL_ENSURE( pCell, "could not find the cell" );
763  nX = aRectFnSet.XInc(aRectFnSet.GetLeft(pCell->getFrameArea()),
764  aRectFnSet.GetWidth(pCell->getFrameArea()) / 2);
765 
766  //The flow leads from one table to the next. The X-value needs to be
767  //corrected based on the middle of the starting cell by the amount
768  //of the offset of the tables.
769  if ( pStTab != pTable )
770  {
771  nX += aRectFnSet.GetLeft(pTable->getFrameArea()) -
772  aRectFnSet.GetLeft(pStTab->getFrameArea());
773  }
774  }
775 
776  // Restrict nX to the left and right borders of pTab:
777  // (is this really necessary?)
778  if (pTable && !pTable->GetUpper()->IsInTab())
779  {
780  const bool bRTL = pTable->IsRightToLeft();
781  const long nPrtLeft = bRTL ?
782  aRectFnSet.GetPrtRight(*pTable) :
783  aRectFnSet.GetPrtLeft(*pTable);
784  if (bRTL != (aRectFnSet.XDiff(nPrtLeft, nX) > 0))
785  nX = nPrtLeft;
786  else
787  {
788  const long nPrtRight = bRTL ?
789  aRectFnSet.GetPrtLeft(*pTable) :
790  aRectFnSet.GetPrtRight(*pTable);
791  if (bRTL != (aRectFnSet.XDiff(nX, nPrtRight) > 0))
792  nX = nPrtRight;
793  }
794  }
795  }
796 
797  do
798  {
799  //If I'm in the DocumentBody, I want to stay there.
800  if ( pStart->IsInDocBody() )
801  {
802  while ( pCnt && (!pCnt->IsInDocBody() ||
803  (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
804  {
805  pCnt = (*fnNxtPrv)( pCnt );
806  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
807  }
808  }
809 
810  //If I'm in the FootNoteArea, I try to reach the next FootNoteArea in
811  //case of necessity.
812  else if ( pStart->IsInFootnote() )
813  {
814  while ( pCnt && (!pCnt->IsInFootnote() ||
815  (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
816  {
817  pCnt = (*fnNxtPrv)( pCnt );
818  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
819  }
820  }
821 
822  //In Flys we can go ahead blindly as long as we find a Content.
823  else if ( pStart->IsInFly() )
824  {
825  if ( pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow() )
826  {
827  pCnt = (*fnNxtPrv)( pCnt );
828  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
829  }
830  }
831 
832  //Otherwise I'll just refuse to leave to current area.
833  else if ( pCnt )
834  {
835  const SwFrame *pUp = pStart->GetUpper();
836  while (pUp && pUp->GetUpper() && !(pUp->GetType() & FRM_HEADFOOT))
837  pUp = pUp->GetUpper();
838  bool bSame = false;
839  const SwFrame *pCntUp = pCnt->GetUpper();
840  while ( pCntUp && !bSame )
841  {
842  if ( pUp == pCntUp )
843  bSame = true;
844  else
845  pCntUp = pCntUp->GetUpper();
846  }
847  if ( !bSame )
848  pCnt = nullptr;
849  else if (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()) // i73332
850  {
851  pCnt = (*fnNxtPrv)( pCnt );
852  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
853  }
854  }
855 
856  if ( bTab )
857  {
858  if ( !pCnt )
859  bEnd = true;
860  else
861  {
862  const SwTabFrame *pTab = pCnt->FindTabFrame();
863  if( !pTab )
864  bEnd = true;
865  else
866  {
867  if ( pTab != pTable )
868  {
869  //The flow leads from one table to the next. The X-value
870  //needs to be corrected by the amount of the offset of
871  //the tables
872  if ( pTable &&
873  !pTab->GetUpper()->IsInTab() &&
874  !pTable->GetUpper()->IsInTab() )
875  nX += pTab->getFrameArea().Left() - pTable->getFrameArea().Left();
876  pTable = pTab;
877  }
878  const SwLayoutFrame *pCell = pCnt->GetUpper();
879  while ( pCell && !pCell->IsCellFrame() )
880  pCell = pCell->GetUpper();
881 
882  Point aInsideCell;
883  Point aInsideCnt;
884  if ( pCell )
885  {
886  long nTmpTop = aRectFnSet.GetTop(pCell->getFrameArea());
887  if ( aRectFnSet.IsVert() )
888  {
889  if ( nTmpTop )
890  nTmpTop = aRectFnSet.XInc(nTmpTop, -1);
891 
892  aInsideCell = Point( nTmpTop, nX );
893  }
894  else
895  aInsideCell = Point( nX, nTmpTop );
896  }
897 
898  long nTmpTop = aRectFnSet.GetTop(pCnt->getFrameArea());
899  if ( aRectFnSet.IsVert() )
900  {
901  if ( nTmpTop )
902  nTmpTop = aRectFnSet.XInc(nTmpTop, -1);
903 
904  aInsideCnt = Point( nTmpTop, nX );
905  }
906  else
907  aInsideCnt = Point( nX, nTmpTop );
908 
909  if ( pCell && pCell->getFrameArea().IsInside( aInsideCell ) )
910  {
911  bEnd = true;
912  //Get the right Content out of the cell.
913  if ( !pCnt->getFrameArea().IsInside( aInsideCnt ) )
914  {
915  pCnt = pCell->ContainsContent();
916  if ( fnNxtPrv == lcl_GetPrvCnt )
917  while ( pCell->IsAnLower(pCnt->GetNextContentFrame()) )
918  pCnt = pCnt->GetNextContentFrame();
919  }
920  }
921  else if ( pCnt->getFrameArea().IsInside( aInsideCnt ) )
922  bEnd = true;
923  }
924  }
925  if ( !bEnd )
926  {
927  pCnt = (*fnNxtPrv)( pCnt );
928  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
929  }
930  }
931 
932  } while ( !bEnd ||
933  (pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()));
934 
935  if (pCnt == nullptr)
936  {
937  return false;
938  }
939  if (pCnt->IsTextFrame())
940  {
941  SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pCnt));
942  *pPam->GetPoint() = pFrame->MapViewToModelPos(TextFrameIndex(
943  fnNxtPrv == lcl_GetPrvCnt
944  ? pFrame->GetText().getLength()
945  : 0));
946  }
947  else
948  { // set the Point on the Content-Node
949  assert(pCnt->IsNoTextFrame());
950  SwContentNode *const pCNd = const_cast<SwContentNode*>(static_cast<SwNoTextFrame const*>(pCnt)->GetNode());
951  pPam->GetPoint()->nNode = *pCNd;
952  if ( fnNxtPrv == lcl_GetPrvCnt )
953  pCNd->MakeEndIndex( &pPam->GetPoint()->nContent );
954  else
955  pCNd->MakeStartIndex( &pPam->GetPoint()->nContent );
956  }
957  return true;
958 }
959 
960 bool SwContentFrame::UnitUp( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
961 {
962  return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
963 }
964 
965 bool SwContentFrame::UnitDown( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
966 {
967  return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
968 }
969 
975 sal_uInt16 SwRootFrame::GetCurrPage( const SwPaM *pActualCursor ) const
976 {
977  OSL_ENSURE( pActualCursor, "got no page cursor" );
978  SwFrame const*const pActFrame = pActualCursor->GetPoint()->nNode.GetNode().
980  pActualCursor->GetPoint());
981  return pActFrame->FindPageFrame()->GetPhyPageNum();
982 }
983 
991 sal_uInt16 SwRootFrame::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
992 {
993  vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr;
994  OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "No page available." );
995 
996  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
997  bool bEnd =false;
998  while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
999  { if ( pPage->GetNext() )
1000  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1001  else
1002  { //Search the first ContentFrame and format until a new page is started
1003  //or until the ContentFrame are all done.
1004  const SwContentFrame *pContent = pPage->ContainsContent();
1005  while ( pContent && pPage->IsAnLower( pContent ) )
1006  {
1007  pContent->Calc(pRenderContext);
1008  pContent = pContent->GetNextContentFrame();
1009  }
1010  //Either this is a new page or we found the last page.
1011  if ( pPage->GetNext() )
1012  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1013  else
1014  bEnd = true;
1015  }
1016  }
1017  //pPage now points to the 'requested' page. Now we have to create the PaM
1018  //on the beginning of the first ContentFrame in the body-text.
1019  //If this is a footnote-page, the PaM will be set in the first footnote.
1020  const SwContentFrame *pContent = pPage->ContainsContent();
1021  if ( pPage->IsFootnotePage() )
1022  while ( pContent && !pContent->IsInFootnote() )
1023  pContent = pContent->GetNextContentFrame();
1024  else
1025  while ( pContent && !pContent->IsInDocBody() )
1026  pContent = pContent->GetNextContentFrame();
1027  if ( pContent )
1028  {
1029  assert(pContent->IsTextFrame());
1030  SwTextFrame const*const pFrame(static_cast<const SwTextFrame*>(pContent));
1031  *pToSet->GetPoint() = pFrame->MapViewToModelPos(pFrame->GetOfst());
1032 
1033  SwShellCursor* pSCursor = dynamic_cast<SwShellCursor*>(pToSet);
1034  if( pSCursor )
1035  {
1036  Point &rPt = pSCursor->GetPtPos();
1037  rPt = pContent->getFrameArea().Pos();
1038  rPt += pContent->getFramePrintArea().Pos();
1039  }
1040  return pPage->GetPhyPageNum();
1041  }
1042  return 0;
1043 }
1044 
1046 {
1047  return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindFirstBodyContent();
1048 }
1049 
1051 {
1052  return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindLastBodyContent();
1053 }
1054 
1056 {
1057  SwLayoutFrame *pNext =
1058  (pFrame->GetNext() && pFrame->GetNext()->IsLayoutFrame()) ?
1059  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFrame->GetNext())) : nullptr;
1060  // #i39402# in case of an empty page
1061  if(pNext && !pNext->ContainsContent())
1062  pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrame()) ?
1063  static_cast<SwLayoutFrame*>(pNext->GetNext()) : nullptr;
1064  return pNext;
1065 }
1066 
1068 {
1069  return const_cast<SwLayoutFrame*>(pFrame);
1070 }
1071 
1073 {
1074  SwLayoutFrame *pPrev =
1075  (pFrame->GetPrev() && pFrame->GetPrev()->IsLayoutFrame()) ?
1076  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFrame->GetPrev())) : nullptr;
1077  // #i39402# in case of an empty page
1078  if(pPrev && !pPrev->ContainsContent())
1079  pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrame()) ?
1080  static_cast<SwLayoutFrame*>(pPrev->GetPrev()) : nullptr;
1081  return pPrev;
1082 }
1083 
1088 bool GetFrameInPage( const SwContentFrame *pCnt, SwWhichPage fnWhichPage,
1089  SwPosPage fnPosPage, SwPaM *pPam )
1090 {
1091  //First find the requested page, at first the current, then the one which
1092  //was requests through fnWichPage.
1093  const SwLayoutFrame *pLayoutFrame = pCnt->FindPageFrame();
1094  if ( !pLayoutFrame || (nullptr == (pLayoutFrame = (*fnWhichPage)(pLayoutFrame))) )
1095  return false;
1096 
1097  //Now the desired ContentFrame below the page
1098  if( nullptr == (pCnt = (*fnPosPage)(pLayoutFrame)) )
1099  return false;
1100  else
1101  {
1102  // repeated headlines in tables
1103  if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
1104  {
1105  const SwTabFrame* pTab = pCnt->FindTabFrame();
1106  if ( pTab->IsFollow() )
1107  {
1108  if ( pTab->IsInHeadline( *pCnt ) )
1109  {
1110  SwLayoutFrame* pRow = pTab->GetFirstNonHeadlineRow();
1111  if ( pRow )
1112  {
1113  // We are in the first line of a follow table
1114  // with repeated headings.
1115  // To actually make a "real" move we take the first content
1116  // of the next row
1117  pCnt = pRow->ContainsContent();
1118  if ( ! pCnt )
1119  return false;
1120  }
1121  }
1122  }
1123  }
1124 
1125  assert(pCnt->IsTextFrame());
1126  SwTextFrame const*const pFrame(static_cast<const SwTextFrame*>(pCnt));
1127  TextFrameIndex const nIdx((fnPosPage == GetFirstSub)
1128  ? pFrame->GetOfst()
1129  : (pFrame->GetFollow())
1130  ? pFrame->GetFollow()->GetOfst() - TextFrameIndex(1)
1131  : TextFrameIndex(pFrame->GetText().getLength()));
1132  *pPam->GetPoint() = pFrame->MapViewToModelPos(nIdx);
1133  return true;
1134  }
1135 }
1136 
1137 static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2)
1138 {
1139  //Calculate the distance between the two points.
1140  //'delta' X^2 + 'delta'Y^2 = 'distance'^2
1141  sal_uInt64 dX = std::max( rPt1.X(), rPt2.X() ) -
1142  std::min( rPt1.X(), rPt2.X() ),
1143  dY = std::max( rPt1.Y(), rPt2.Y() ) -
1144  std::min( rPt1.Y(), rPt2.Y() );
1145  return (dX * dX) + (dY * dY);
1146 }
1147 
1154 static const SwLayoutFrame* lcl_Inside( const SwContentFrame *pCnt, Point const & rPt )
1155 {
1156  const SwLayoutFrame* pUp = pCnt->GetUpper();
1157  while( pUp )
1158  {
1159  if( pUp->IsPageBodyFrame() || pUp->IsFooterFrame() || pUp->IsHeaderFrame() )
1160  {
1161  if( rPt.Y() >= pUp->getFrameArea().Top() && rPt.Y() <= pUp->getFrameArea().Bottom() )
1162  return pUp;
1163  return nullptr;
1164  }
1165  if( pUp->IsFootnoteContFrame() )
1166  return pUp->getFrameArea().IsInside( rPt ) ? pUp : nullptr;
1167  pUp = pUp->GetUpper();
1168  }
1169  return nullptr;
1170 }
1171 
1180  const bool bDontLeave,
1181  const bool bBodyOnly,
1182  SwCursorMoveState *pCMS,
1183  const bool bDefaultExpand ) const
1184 {
1185  //Determine the first ContentFrame.
1186  const SwLayoutFrame *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
1187  static_cast<const SwLayoutFrame*>(GetPrev()) : this;
1188  const SwContentFrame *pContent = pStart->ContainsContent();
1189 
1190  if ( !pContent && (GetPrev() && !bDontLeave) )
1191  pContent = ContainsContent();
1192 
1193  if ( bBodyOnly && pContent && !pContent->IsInDocBody() )
1194  while ( pContent && !pContent->IsInDocBody() )
1195  pContent = pContent->GetNextContentFrame();
1196 
1197  const SwContentFrame *pActual= pContent;
1198  const SwLayoutFrame *pInside = nullptr;
1199  sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
1200  Point aPoint = rPoint;
1201  sal_uInt64 nDistance = SAL_MAX_UINT64;
1202 
1203  while ( true ) //A loop to be sure we always find one.
1204  {
1205  while ( pContent &&
1206  ((!bDontLeave || IsAnLower( pContent )) &&
1207  (pContent->GetPhyPageNum() <= nMaxPage)) )
1208  {
1209  if ( pContent->getFrameArea().Width() &&
1210  ( !bBodyOnly || pContent->IsInDocBody() ) )
1211  {
1212  //If the Content lies in a protected area (cell, Footnote, section),
1213  //we search the next Content which is not protected.
1214  const SwContentFrame *pComp = pContent;
1215  pContent = ::lcl_MissProtectedFrames( pContent, lcl_GetNxtCnt, false,
1216  pCMS && pCMS->m_bSetInReadOnly, false );
1217  if ( pComp != pContent )
1218  continue;
1219 
1220  if ( !pContent->IsTextFrame() || !static_cast<const SwTextFrame*>(pContent)->IsHiddenNow() )
1221  {
1222  SwRect aContentFrame( pContent->UnionFrame() );
1223  if ( aContentFrame.IsInside( rPoint ) )
1224  {
1225  pActual = pContent;
1226  aPoint = rPoint;
1227  break;
1228  }
1229  //The distance from rPoint to the nearest Point of pContent
1230  //will now be calculated.
1231  Point aContentPoint( rPoint );
1232 
1233  //First set the vertical position
1234  if ( aContentFrame.Top() > aContentPoint.Y() )
1235  aContentPoint.setY( aContentFrame.Top() );
1236  else if ( aContentFrame.Bottom() < aContentPoint.Y() )
1237  aContentPoint.setY( aContentFrame.Bottom() );
1238 
1239  //Now the horizontal position
1240  if ( aContentFrame.Left() > aContentPoint.X() )
1241  aContentPoint.setX( aContentFrame.Left() );
1242  else if ( aContentFrame.Right() < aContentPoint.X() )
1243  aContentPoint.setX( aContentFrame.Right() );
1244 
1245  // pInside is a page area in which the point lies. As soon
1246  // as pInside != 0 only frames are accepted which are
1247  // placed inside.
1248  if( !pInside || ( pInside->IsAnLower( pContent ) &&
1249  ( !pContent->IsInFootnote() || pInside->IsFootnoteContFrame() ) ) )
1250  {
1251  const sal_uInt64 nDiff = ::CalcDiff(aContentPoint, rPoint);
1252  bool bBetter = nDiff < nDistance; // This one is nearer
1253  if( !pInside )
1254  {
1255  pInside = lcl_Inside( pContent, rPoint );
1256  if( pInside ) // In the "right" page area
1257  bBetter = true;
1258  }
1259  if( bBetter )
1260  {
1261  aPoint = aContentPoint;
1262  nDistance = nDiff;
1263  pActual = pContent;
1264  }
1265  }
1266  }
1267  }
1268  pContent = pContent->GetNextContentFrame();
1269  if ( bBodyOnly )
1270  while ( pContent && !pContent->IsInDocBody() )
1271  pContent = pContent->GetNextContentFrame();
1272  }
1273  if ( !pActual )
1274  { //If we not yet found one we have to expand the searched
1275  //area, sometime we will find one!
1276  //MA 1997-01-09: Opt for many empty pages - if we only search inside
1277  //the body, we can expand the searched area sufficiently in one step.
1278  if ( bBodyOnly )
1279  {
1280  while ( !pContent && pStart->GetPrev() )
1281  {
1282  ++nMaxPage;
1283  if( !pStart->GetPrev()->IsLayoutFrame() )
1284  return nullptr;
1285  pStart = static_cast<const SwLayoutFrame*>(pStart->GetPrev());
1286  pContent = pStart->IsInDocBody()
1287  ? pStart->ContainsContent()
1288  : pStart->FindPageFrame()->FindFirstBodyContent();
1289  }
1290  if ( !pContent ) // Somewhere down the road we have to start with one!
1291  {
1292  pContent = pStart->FindPageFrame()->GetUpper()->ContainsContent();
1293  while ( pContent && !pContent->IsInDocBody() )
1294  pContent = pContent->GetNextContentFrame();
1295  if ( !pContent )
1296  return nullptr; // There is no document content yet!
1297  }
1298  }
1299  else
1300  {
1301  ++nMaxPage;
1302  if ( pStart->GetPrev() )
1303  {
1304  if( !pStart->GetPrev()->IsLayoutFrame() )
1305  return nullptr;
1306  pStart = static_cast<const SwLayoutFrame*>(pStart->GetPrev());
1307  pContent = pStart->ContainsContent();
1308  }
1309  else // Somewhere down the road we have to start with one!
1310  pContent = pStart->FindPageFrame()->GetUpper()->ContainsContent();
1311  }
1312  pActual = pContent;
1313  }
1314  else
1315  break;
1316  }
1317 
1318  OSL_ENSURE( pActual, "no Content found." );
1319  OSL_ENSURE( !bBodyOnly || pActual->IsInDocBody(), "Content not in Body." );
1320 
1321  //Special case for selecting tables not in repeated TableHeadlines.
1322  if ( pActual->IsInTab() && pCMS && pCMS->m_eState == MV_TBLSEL )
1323  {
1324  const SwTabFrame *pTab = pActual->FindTabFrame();
1325  if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
1326  {
1327  pCMS->m_bStop = true;
1328  return nullptr;
1329  }
1330  }
1331 
1332  //A small correction at the first/last
1333  Size aActualSize( pActual->getFramePrintArea().SSize() );
1334  if ( aActualSize.Height() > pActual->GetUpper()->getFramePrintArea().Height() )
1335  aActualSize.setHeight( pActual->GetUpper()->getFramePrintArea().Height() );
1336 
1337  SwRectFnSet aRectFnSet(pActual);
1338  if ( !pActual->GetPrev() &&
1339  aRectFnSet.YDiff( aRectFnSet.GetPrtTop(*pActual),
1340  aRectFnSet.IsVert() ? rPoint.X() : rPoint.Y() ) > 0 )
1341  {
1342  aPoint.setY( pActual->getFrameArea().Top() + pActual->getFramePrintArea().Top() );
1343  aPoint.setX( pActual->getFrameArea().Left() +
1344  ( pActual->IsRightToLeft() || aRectFnSet.IsVert() ?
1345  pActual->getFramePrintArea().Right() :
1346  pActual->getFramePrintArea().Left() ) );
1347  }
1348  else if ( !pActual->GetNext() &&
1349  aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pActual),
1350  aRectFnSet.IsVert() ? rPoint.X() : rPoint.Y() ) < 0 )
1351  {
1352  aPoint.setY( pActual->getFrameArea().Top() + pActual->getFramePrintArea().Bottom() );
1353  aPoint.setX( pActual->getFrameArea().Left() +
1354  ( pActual->IsRightToLeft() || aRectFnSet.IsVert() ?
1355  pActual->getFramePrintArea().Left() :
1356  pActual->getFramePrintArea().Right() ) );
1357  }
1358 
1359  //Bring the Point into the PrtArea
1360  const SwRect aRect( pActual->getFrameArea().Pos() + pActual->getFramePrintArea().Pos(),
1361  aActualSize );
1362  if ( aPoint.Y() < aRect.Top() )
1363  aPoint.setY( aRect.Top() );
1364  else if ( aPoint.Y() > aRect.Bottom() )
1365  aPoint.setY( aRect.Bottom() );
1366  if ( aPoint.X() < aRect.Left() )
1367  aPoint.setX( aRect.Left() );
1368  else if ( aPoint.X() > aRect.Right() )
1369  aPoint.setX( aRect.Right() );
1370  rPoint = aPoint;
1371  return pActual;
1372 }
1373 
1375 void SwPageFrame::GetContentPosition( const Point &rPt, SwPosition &rPos ) const
1376 {
1377  //Determine the first ContentFrame.
1378  const SwContentFrame *pContent = ContainsContent();
1379  if ( pContent )
1380  {
1381  //Look back one more (if possible).
1382  const SwContentFrame *pTmp = pContent->GetPrevContentFrame();
1383  while ( pTmp && !pTmp->IsInDocBody() )
1384  pTmp = pTmp->GetPrevContentFrame();
1385  if ( pTmp )
1386  pContent = pTmp;
1387  }
1388  else
1389  pContent = GetUpper()->ContainsContent();
1390 
1391  const SwContentFrame *pAct = pContent;
1392  Point aAct = rPt;
1393  sal_uInt64 nDist = SAL_MAX_UINT64;
1394 
1395  while ( pContent )
1396  {
1397  SwRect aContentFrame( pContent->UnionFrame() );
1398  if ( aContentFrame.IsInside( rPt ) )
1399  {
1400  //This is the nearest one.
1401  pAct = pContent;
1402  break;
1403  }
1404 
1405  //Calculate the distance from rPt to the nearest point of pContent.
1406  Point aPoint( rPt );
1407 
1408  //Calculate the vertical position first
1409  if ( aContentFrame.Top() > rPt.Y() )
1410  aPoint.setY( aContentFrame.Top() );
1411  else if ( aContentFrame.Bottom() < rPt.Y() )
1412  aPoint.setY( aContentFrame.Bottom() );
1413 
1414  //And now the horizontal position
1415  if ( aContentFrame.Left() > rPt.X() )
1416  aPoint.setX( aContentFrame.Left() );
1417  else if ( aContentFrame.Right() < rPt.X() )
1418  aPoint.setX( aContentFrame.Right() );
1419 
1420  const sal_uInt64 nDiff = ::CalcDiff( aPoint, rPt );
1421  if ( nDiff < nDist )
1422  {
1423  aAct = aPoint;
1424  nDist = nDiff;
1425  pAct = pContent;
1426  }
1427  else if ( aContentFrame.Top() > getFrameArea().Bottom() )
1428  //In terms of fields, it's not possible to be closer any more!
1429  break;
1430 
1431  pContent = pContent->GetNextContentFrame();
1432  while ( pContent && !pContent->IsInDocBody() )
1433  pContent = pContent->GetNextContentFrame();
1434  }
1435 
1436  //Bring the point into the PrtArea.
1437  const SwRect aRect( pAct->getFrameArea().Pos() + pAct->getFramePrintArea().Pos(), pAct->getFramePrintArea().SSize() );
1438  if ( aAct.Y() < aRect.Top() )
1439  aAct.setY( aRect.Top() );
1440  else if ( aAct.Y() > aRect.Bottom() )
1441  aAct.setY( aRect.Bottom() );
1442  if ( aAct.X() < aRect.Left() )
1443  aAct.setX( aRect.Left() );
1444  else if ( aAct.X() > aRect.Right() )
1445  aAct.setX( aRect.Right() );
1446 
1447  if (!pAct->isFrameAreaDefinitionValid() ||
1448  (pAct->IsTextFrame() && !static_cast<SwTextFrame const*>(pAct)->HasPara()))
1449  {
1450  // ContentFrame not formatted -> always on node-beginning
1451  // tdf#100635 also if the SwTextFrame would require reformatting,
1452  // which is unwanted in case this is called from text formatting code
1453  rPos = static_cast<SwTextFrame const*>(pAct)->MapViewToModelPos(TextFrameIndex(0));
1454  }
1455  else
1456  {
1457  SwCursorMoveState aTmpState( MV_SETONLYTEXT );
1458  pAct->GetCursorOfst( &rPos, aAct, &aTmpState );
1459  }
1460 }
1461 
1468 Point SwRootFrame::GetNextPrevContentPos( const Point& rPoint, bool bNext ) const
1469 {
1470  vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr;
1471  // #123110# - disable creation of an action by a callback
1472  // event during processing of this method. Needed because formatting is
1473  // triggered by this method.
1474  DisableCallbackAction aDisableCallbackAction(const_cast<SwRootFrame&>(*this));
1475  //Search the first ContentFrame and his successor in the body area.
1476  //To be efficient (and not formatting too much) we'll start at the correct
1477  //page.
1478  const SwLayoutFrame *pPage = static_cast<const SwLayoutFrame*>(Lower());
1479  if( pPage )
1480  while( pPage->GetNext() && pPage->getFrameArea().Bottom() < rPoint.Y() )
1481  pPage = static_cast<const SwLayoutFrame*>(pPage->GetNext());
1482 
1483  const SwContentFrame *pCnt = pPage ? pPage->ContainsContent() : ContainsContent();
1484  while ( pCnt && !pCnt->IsInDocBody() )
1485  pCnt = pCnt->GetNextContentFrame();
1486 
1487  if ( !pCnt )
1488  return Point( 0, 0 );
1489 
1490  pCnt->Calc(pRenderContext);
1491  if( !bNext )
1492  {
1493  // As long as the point lies before the first ContentFrame and there are
1494  // still precedent pages I'll go to the next page.
1495  while ( rPoint.Y() < pCnt->getFrameArea().Top() && pPage->GetPrev() )
1496  {
1497  pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev());
1498  pCnt = pPage->ContainsContent();
1499  while ( !pCnt )
1500  {
1501  pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev());
1502  if ( pPage )
1503  pCnt = pPage->ContainsContent();
1504  else
1505  return ContainsContent()->UnionFrame().Pos();
1506  }
1507  pCnt->Calc(pRenderContext);
1508  }
1509  }
1510 
1511  //Does the point lie above the first ContentFrame?
1512  if ( rPoint.Y() < pCnt->getFrameArea().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
1513  return pCnt->UnionFrame().Pos();
1514 
1515  Point aRet(0, 0);
1516  do
1517  {
1518  //Does the point lie in the current ContentFrame?
1519  SwRect aContentFrame( pCnt->UnionFrame() );
1520  if ( aContentFrame.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
1521  {
1522  aRet = rPoint;
1523  break;
1524  }
1525 
1526  //Is the current one the last ContentFrame?
1527  //If the next ContentFrame lies behind the point, then the current on is the
1528  //one we searched.
1529  const SwContentFrame *pNxt = pCnt->GetNextContentFrame();
1530  while ( pNxt && !pNxt->IsInDocBody() )
1531  pNxt = pNxt->GetNextContentFrame();
1532 
1533  //Does the point lie behind the last ContentFrame?
1534  if ( !pNxt )
1535  {
1536  aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() );
1537  break;
1538  }
1539 
1540  //If the next ContentFrame lies behind the point then it is the one we
1541  //searched.
1542  const SwTabFrame* pTFrame;
1543  pNxt->Calc(pRenderContext);
1544  if( pNxt->getFrameArea().Top() > rPoint.Y() &&
1545  !lcl_IsInRepeatedHeadline( pCnt, &pTFrame ) &&
1546  ( !pTFrame || pNxt->getFrameArea().Left() > rPoint.X() ))
1547  {
1548  if (bNext)
1549  aRet = pNxt->getFrameArea().Pos();
1550  else
1551  aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() );
1552  break;
1553  }
1554  pCnt = pNxt;
1555  }
1556  while (pCnt);
1557  return aRet;
1558 }
1559 
1567 Point SwRootFrame::GetPagePos( sal_uInt16 nPageNum ) const
1568 {
1569  OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "No page available." );
1570 
1571  const SwPageFrame *pPage = static_cast<const SwPageFrame*>(Lower());
1572  while ( true )
1573  {
1574  if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
1575  break;
1576  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1577  }
1578  return pPage->getFrameArea().Pos();
1579 }
1580 
1585 SwPageFrame* SwRootFrame::GetPageByPageNum( sal_uInt16 _nPageNum ) const
1586 {
1587  const SwPageFrame* pPageFrame = static_cast<const SwPageFrame*>( Lower() );
1588  while ( pPageFrame && pPageFrame->GetPhyPageNum() < _nPageNum )
1589  {
1590  pPageFrame = static_cast<const SwPageFrame*>( pPageFrame->GetNext() );
1591  }
1592 
1593  if ( pPageFrame && pPageFrame->GetPhyPageNum() == _nPageNum )
1594  {
1595  return const_cast<SwPageFrame*>( pPageFrame );
1596  }
1597  else
1598  {
1599  return nullptr;
1600  }
1601 }
1602 
1606 bool SwRootFrame::IsDummyPage( sal_uInt16 nPageNum ) const
1607 {
1608  if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
1609  return true;
1610 
1611  const SwPageFrame *pPage = static_cast<const SwPageFrame*>(Lower());
1612  while( pPage && nPageNum < pPage->GetPhyPageNum() )
1613  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1614  return !pPage || pPage->IsEmptyPage();
1615 }
1616 
1622 {
1623  if (IsTextFrame())
1624  {
1625  const SwDoc *pDoc = &static_cast<const SwTextFrame*>(this)->GetDoc();
1626  bool isFormProtected=pDoc->GetDocumentSettingManager().get(DocumentSettingId::PROTECT_FORM );
1627  if (isFormProtected)
1628  {
1629  return false; // TODO a hack for now, well deal with it later, I we return true here we have a "double" locking
1630  }
1631  }
1632  //The Frame can be protected in borders, cells or sections.
1633  //Also goes up FlyFrames recursive and from footnote to anchor.
1634  const SwFrame *pFrame = this;
1635  do
1636  {
1637  if (pFrame->IsTextFrame())
1638  { // sw_redlinehide: redlines can't overlap section nodes, so any node will do
1639  if (static_cast<SwTextFrame const*>(pFrame)->GetTextNodeFirst()->IsInProtectSect())
1640  {
1641  return true;
1642  }
1643  }
1644  else if ( pFrame->IsContentFrame() )
1645  {
1646  assert(pFrame->IsNoTextFrame());
1647  if (static_cast<const SwNoTextFrame*>(pFrame)->GetNode() &&
1648  static_cast<const SwNoTextFrame*>(pFrame)->GetNode()->IsInProtectSect())
1649  {
1650  return true;
1651  }
1652  }
1653  else
1654  {
1655  if ( static_cast<const SwLayoutFrame*>(pFrame)->GetFormat() &&
1656  static_cast<const SwLayoutFrame*>(pFrame)->GetFormat()->
1657  GetProtect().IsContentProtected() )
1658  return true;
1659  if ( pFrame->IsCoveredCell() )
1660  return true;
1661  }
1662  if ( pFrame->IsFlyFrame() )
1663  {
1664  //In a chain the protection of the content can be specified by the
1665  //master of the chain.
1666  if ( static_cast<const SwFlyFrame*>(pFrame)->GetPrevLink() )
1667  {
1668  const SwFlyFrame *pMaster = static_cast<const SwFlyFrame*>(pFrame);
1669  do
1670  { pMaster = pMaster->GetPrevLink();
1671  } while ( pMaster->GetPrevLink() );
1672  if ( pMaster->IsProtected() )
1673  return true;
1674  }
1675  pFrame = static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame();
1676  }
1677  else if ( pFrame->IsFootnoteFrame() )
1678  pFrame = static_cast<const SwFootnoteFrame*>(pFrame)->GetRef();
1679  else
1680  pFrame = pFrame->GetUpper();
1681 
1682  } while ( pFrame );
1683 
1684  return false;
1685 }
1686 
1688 sal_uInt16 SwFrame::GetPhyPageNum() const
1689 {
1690  const SwPageFrame *pPage = FindPageFrame();
1691  return pPage ? pPage->GetPhyPageNum() : 0;
1692 }
1693 
1706 {
1707  const SwPageFrame *pPage = FindPageFrame();
1708  if ( !pPage || !pPage->GetUpper() )
1709  return true;
1710 
1711  const SwFrame *pFlow = pPage->FindFirstBodyContent();
1712  const SwPageDesc *pDesc = nullptr;
1714  if ( pFlow )
1715  {
1716  if ( pFlow->IsInTab() )
1717  pFlow = pFlow->FindTabFrame();
1718  const SwFlowFrame *pTmp = SwFlowFrame::CastFlowFrame( pFlow );
1719  if ( !pTmp->IsFollow() )
1720  {
1721  const SwFormatPageDesc& rPgDesc = pFlow->GetPageDescItem();
1722  pDesc = rPgDesc.GetPageDesc();
1723  oPgNum = rPgDesc.GetNumOffset();
1724  }
1725  }
1726  if ( !pDesc )
1727  {
1728  SwPageFrame *pPrv = const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pPage->GetPrev()));
1729  if( pPrv && pPrv->IsEmptyPage() )
1730  pPrv = static_cast<SwPageFrame*>(pPrv->GetPrev());
1731  if( pPrv )
1732  pDesc = pPrv->GetPageDesc()->GetFollow();
1733  else
1734  {
1735  const SwDoc* pDoc = pPage->GetFormat()->GetDoc();
1736  pDesc = &pDoc->GetPageDesc( 0 );
1737  }
1738  }
1739  OSL_ENSURE( pDesc, "No pagedescriptor" );
1740  bool bOdd;
1741  if( oPgNum )
1742  bOdd = (oPgNum.get() % 2) != 0;
1743  else
1744  {
1745  bOdd = pPage->OnRightPage();
1746  if( pPage->GetPrev() && static_cast<const SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() )
1747  bOdd = !bOdd;
1748  }
1749  if( !pPage->IsEmptyPage() )
1750  {
1751  if( !pDesc->GetRightFormat() )
1752  bOdd = false;
1753  else if( !pDesc->GetLeftFormat() )
1754  bOdd = true;
1755  }
1756  return bOdd;
1757 }
1758 
1760 {
1761  bool bRet = false;
1762  const SwPageFrame *pPage = FindPageFrame();
1763 
1764  if (pPage)
1765  {
1766  const SwPageFrame* pPrevFrame = dynamic_cast<const SwPageFrame*>(pPage->GetPrev());
1767  if (pPrevFrame)
1768  {
1769  if (pPrevFrame->IsEmptyPage() && pPrevFrame->GetPhyPageNum()==1)
1770  {
1771  // This was the first page of the document, but its page number
1772  // was set to an even number, so a blank page was automatically
1773  // inserted before it to make this be a "left" page.
1774  // We still use the first page format of the page style here.
1775  bRet = true;
1776  } else {
1777  const SwPageDesc* pDesc = pPage->GetPageDesc();
1778  bRet = pPrevFrame->GetPageDesc() != pDesc;
1779  }
1780  }
1781  else
1782  bRet = true;
1783  }
1784  return bRet;
1785 }
1786 
1787 void SwFrame::Calc(vcl::RenderContext* pRenderContext) const
1788 {
1790  {
1791  const_cast<SwFrame*>(this)->PrepareMake(pRenderContext);
1792  }
1793 }
1794 
1796 {
1797  Point aRet( getFrameArea().Pos() );
1798  // here we cast since SwLayoutFrame is declared only as forwarded
1799  aRet -= GetUpper()->getFramePrintArea().Pos();
1800  aRet -= GetUpper()->getFrameArea().Pos();
1801  return aRet;
1802 }
1803 
1805 sal_uInt16 SwFrame::GetVirtPageNum() const
1806 {
1807  const SwPageFrame *pPage = FindPageFrame();
1808  if ( !pPage || !pPage->GetUpper() )
1809  return 0;
1810 
1811  sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
1812  if ( !static_cast<const SwRootFrame*>(pPage->GetUpper())->IsVirtPageNum() )
1813  return nPhyPage;
1814 
1815  //Search the nearest section using the virtual page number.
1816  //Because searching backwards needs a lot of time we search specific using
1817  //the dependencies. From the PageDescs we get the attributes and from the
1818  //attributes we get the sections.
1819  const SwPageFrame *pVirtPage = nullptr;
1820  const SwFrame *pFrame = nullptr;
1821  const SfxItemPool &rPool = pPage->GetFormat()->GetDoc()->GetAttrPool();
1822  for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(RES_PAGEDESC))
1823  {
1824  const SwFormatPageDesc *pDesc = dynamic_cast<const SwFormatPageDesc*>(pItem);
1825  if ( !pDesc )
1826  continue;
1827 
1828  if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
1829  {
1830  const SwModify *pMod = pDesc->GetDefinedIn();
1831  SwVirtPageNumInfo aInfo( pPage );
1832  pMod->GetInfo( aInfo );
1833  if ( aInfo.GetPage() )
1834  {
1835  if( !pVirtPage || aInfo.GetPage()->GetPhyPageNum() > pVirtPage->GetPhyPageNum() )
1836  {
1837  pVirtPage = aInfo.GetPage();
1838  pFrame = aInfo.GetFrame();
1839  }
1840  }
1841  }
1842  }
1843  if ( pFrame )
1844  {
1846  if (oNumOffset)
1847  {
1848  return nPhyPage - pFrame->GetPhyPageNum() + oNumOffset.get();
1849  }
1850  else
1851  {
1852  return nPhyPage - pFrame->GetPhyPageNum();
1853  }
1854  }
1855  return nPhyPage;
1856 }
1857 
1860 {
1861  //Find Union-Rects and tables (Follows) of the selection.
1862  OSL_ENSURE( rTableCursor.GetContentNode() && rTableCursor.GetContentNode( false ),
1863  "Tabselection not on Cnt." );
1864 
1865  bool bRet = false;
1866 
1867  // For new table models there's no need to ask the layout...
1868  if( rTableCursor.NewTableSelection() )
1869  return true;
1870 
1871  Point aPtPt, aMkPt;
1872  {
1873  SwShellCursor* pShCursor = dynamic_cast<SwShellCursor*>(&rTableCursor);
1874 
1875  if( pShCursor )
1876  {
1877  aPtPt = pShCursor->GetPtPos();
1878  aMkPt = pShCursor->GetMkPos();
1879  }
1880  }
1881 
1882  // #151012# Made code robust here
1883  const SwContentNode* pTmpStartNode = rTableCursor.GetContentNode();
1884  const SwContentNode* pTmpEndNode = rTableCursor.GetContentNode(false);
1885 
1886  std::pair<Point, bool> tmp(aPtPt, false);
1887  const SwFrame *const pTmpStartFrame = pTmpStartNode ? pTmpStartNode->getLayoutFrame(this, nullptr, &tmp) : nullptr;
1888  tmp.first = aMkPt;
1889  const SwFrame *const pTmpEndFrame = pTmpEndNode ? pTmpEndNode->getLayoutFrame(this, nullptr, &tmp) : nullptr;
1890 
1891  const SwLayoutFrame* pStart = pTmpStartFrame ? pTmpStartFrame->GetUpper() : nullptr;
1892  const SwLayoutFrame* pEnd = pTmpEndFrame ? pTmpEndFrame->GetUpper() : nullptr;
1893 
1894  OSL_ENSURE( pStart && pEnd, "MakeTableCursors: Good to have the code robust here!" );
1895 
1896  /* #109590# Only change table boxes if the frames are
1897  valid. Needed because otherwise the table cursor after moving
1898  table cells by dnd resulted in an empty tables cursor. */
1899  if ( pStart && pEnd && pStart->isFrameAreaDefinitionValid() && pEnd->isFrameAreaDefinitionValid())
1900  {
1901  SwSelUnions aUnions;
1902  ::MakeSelUnions( aUnions, pStart, pEnd );
1903 
1904  SwSelBoxes aNew;
1905 
1906  const bool bReadOnlyAvailable = rTableCursor.IsReadOnlyAvailable();
1907 
1908  for (SwSelUnion & rUnion : aUnions)
1909  {
1910  const SwTabFrame *pTable = rUnion.GetTable();
1911 
1912  // Skip any repeated headlines in the follow:
1913  SwLayoutFrame* pRow = pTable->IsFollow() ?
1914  pTable->GetFirstNonHeadlineRow() :
1915  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pTable->Lower()));
1916 
1917  while ( pRow )
1918  {
1919  if ( pRow->getFrameArea().IsOver( rUnion.GetUnion() ) )
1920  {
1921  const SwLayoutFrame *pCell = pRow->FirstCell();
1922 
1923  while ( pCell && pRow->IsAnLower( pCell ) )
1924  {
1925  OSL_ENSURE( pCell->IsCellFrame(), "Frame without cell" );
1926  if( IsFrameInTableSel( rUnion.GetUnion(), pCell ) &&
1927  (bReadOnlyAvailable ||
1928  !pCell->GetFormat()->GetProtect().IsContentProtected()))
1929  {
1930  SwTableBox* pInsBox = const_cast<SwTableBox*>(
1931  static_cast<const SwCellFrame*>(pCell)->GetTabBox());
1932  aNew.insert( pInsBox );
1933  }
1934  if ( pCell->GetNext() )
1935  {
1936  pCell = static_cast<const SwLayoutFrame*>(pCell->GetNext());
1937  if ( pCell->Lower() && pCell->Lower()->IsRowFrame() )
1938  pCell = pCell->FirstCell();
1939  }
1940  else
1941  {
1942  const SwLayoutFrame* pLastCell = pCell;
1943  do
1944  {
1945  pCell = pCell->GetNextLayoutLeaf();
1946  } while ( pCell && pLastCell->IsAnLower( pCell ) );
1947  // For sections with columns
1948  if( pCell && pCell->IsInTab() )
1949  {
1950  while( !pCell->IsCellFrame() )
1951  {
1952  pCell = pCell->GetUpper();
1953  OSL_ENSURE( pCell, "Where's my cell?" );
1954  }
1955  }
1956  }
1957  }
1958  }
1959  pRow = static_cast<SwLayoutFrame*>(pRow->GetNext());
1960  }
1961  }
1962 
1963  rTableCursor.ActualizeSelection( aNew );
1964  bRet = true;
1965  }
1966 
1967  return bRet;
1968 }
1969 
1970 static void Sub( SwRegionRects& rRegion, const SwRect& rRect )
1971 {
1972  if( rRect.Width() > 1 && rRect.Height() > 1 &&
1973  rRect.IsOver( rRegion.GetOrigin() ))
1974  rRegion -= rRect;
1975 }
1976 
1977 static void Add( SwRegionRects& rRegion, const SwRect& rRect )
1978 {
1979  if( rRect.Width() > 1 && rRect.Height() > 1 )
1980  rRegion += rRect;
1981 }
1982 
1983 /*
1984  * The following situations can happen:
1985  * 1. Start and end lie in one screen-row and in the same node
1986  * -> one rectangle out of start and end; and we're okay
1987  * 2. Start and end lie in one frame (therefore in the same node!)
1988  * -> expand start to the right, end to the left and if more than two
1989  * screen-rows are involved - calculate the in-between
1990  * 3. Start and end lie in different frames
1991  * -> expand start to the right until frame-end, calculate Rect
1992  * expand end to the left until frame-start, calculate Rect
1993  * and if more than two frames are involved add the PrtArea of all
1994  * frames which lie in between
1995  *
1996  * Big reorganization because of the FlyFrame - those need to be locked out.
1997  * Exceptions: - The Fly in which the selection took place (if it took place
1998  * in a Fly)
1999  * - The Flys which are underrun by the text
2000  * - The Flys which are anchored to somewhere inside the selection.
2001  * Functioning: First a SwRegion with a root gets initialized.
2002  * Out of the region the inverted sections are cut out. The
2003  * section gets compressed and finally inverted and thereby the
2004  * inverted rectangles are available.
2005  * In the end the Flys are cut out of the section.
2006  */
2008 {
2009  SwPosition *pStartPos = rCursor.Start(),
2010  *pEndPos = rCursor.GetPoint() == pStartPos ? rCursor.GetMark() : rCursor.GetPoint();
2011 
2012  SwViewShell *pSh = GetCurrShell();
2013 
2014  bool bIgnoreVisArea = true;
2015  if (pSh)
2016  bIgnoreVisArea = pSh->GetViewOptions()->IsPDFExport() || comphelper::LibreOfficeKit::isActive();
2017 
2018  // #i12836# enhanced pdf
2019  SwRegionRects aRegion( !bIgnoreVisArea ?
2020  pSh->VisArea() :
2021  getFrameArea() );
2022  if( !pStartPos->nNode.GetNode().IsContentNode() ||
2023  !pStartPos->nNode.GetNode().GetContentNode()->getLayoutFrame(this) ||
2024  ( pStartPos->nNode != pEndPos->nNode &&
2025  ( !pEndPos->nNode.GetNode().IsContentNode() ||
2026  !pEndPos->nNode.GetNode().GetContentNode()->getLayoutFrame(this) ) ) )
2027  {
2028  return;
2029  }
2030 
2031  DisableCallbackAction a(*this); // the GetCharRect below may format
2032 
2033  //First obtain the ContentFrames for the start and the end - those are needed
2034  //anyway.
2035  std::pair<Point, bool> tmp(rCursor.GetSttPos(), true);
2036  SwContentFrame* pStartFrame = pStartPos->nNode.GetNode().
2037  GetContentNode()->getLayoutFrame(this, pStartPos, &tmp);
2038 
2039  tmp.first = rCursor.GetEndPos();
2040  SwContentFrame* pEndFrame = pEndPos->nNode.GetNode().
2041  GetContentNode()->getLayoutFrame(this, pEndPos, &tmp);
2042 
2043  assert(pStartFrame && pEndFrame && "No ContentFrames found.");
2044  //tdf#119224 start and end are expected to exist for the scope of this function
2045  SwFrameDeleteGuard aStartFrameGuard(pStartFrame), aEndFrameGuard(pEndFrame);
2046 
2047  //Do not subtract the FlyFrames in which selected Frames lie.
2048  SwSortedObjs aSortObjs;
2049  if ( pStartFrame->IsInFly() )
2050  {
2051  const SwAnchoredObject* pObj = pStartFrame->FindFlyFrame();
2052  OSL_ENSURE( pObj, "No Start Object." );
2053  if (pObj) aSortObjs.Insert( *const_cast<SwAnchoredObject*>(pObj) );
2054  const SwAnchoredObject* pObj2 = pEndFrame->FindFlyFrame();
2055  OSL_ENSURE( pObj2, "SwRootFrame::CalcFrameRects(..) - FlyFrame missing - looks like an invalid selection" );
2056  if ( pObj2 != nullptr && pObj2 != pObj )
2057  {
2058  aSortObjs.Insert( *const_cast<SwAnchoredObject*>(pObj2) );
2059  }
2060  }
2061 
2062  // if a selection which is not allowed exists, we correct what is not
2063  // allowed (header/footer/table-headline) for two pages.
2064  do { // middle check loop
2065  const SwLayoutFrame* pSttLFrame = pStartFrame->GetUpper();
2067  while( pSttLFrame &&
2068  ! (cHdFtTableHd & pSttLFrame->GetType() ))
2069  pSttLFrame = pSttLFrame->GetUpper();
2070  if( !pSttLFrame )
2071  break;
2072  const SwLayoutFrame* pEndLFrame = pEndFrame->GetUpper();
2073  while( pEndLFrame &&
2074  ! (cHdFtTableHd & pEndLFrame->GetType() ))
2075  pEndLFrame = pEndLFrame->GetUpper();
2076  if( !pEndLFrame )
2077  break;
2078 
2079  OSL_ENSURE( pEndLFrame->GetType() == pSttLFrame->GetType(),
2080  "Selection over different content" );
2081  switch( pSttLFrame->GetType() )
2082  {
2083  case SwFrameType::Header:
2084  case SwFrameType::Footer:
2085  // On different pages? Then always on the start-page
2086  if( pEndLFrame->FindPageFrame() != pSttLFrame->FindPageFrame() )
2087  {
2088  // Set end- to the start-ContentFrame
2089  if( pStartPos == rCursor.GetPoint() )
2090  pEndFrame = pStartFrame;
2091  else
2092  pStartFrame = pEndFrame;
2093  }
2094  break;
2095  case SwFrameType::Tab:
2096  // On different pages? Then check for table-headline
2097  {
2098  const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pSttLFrame);
2099  if( ( pTabFrame->GetFollow() ||
2100  static_cast<const SwTabFrame*>(pEndLFrame)->GetFollow() ) &&
2101  pTabFrame->GetTable()->GetRowsToRepeat() > 0 &&
2102  pTabFrame->GetLower() != static_cast<const SwTabFrame*>(pEndLFrame)->GetLower() &&
2103  ( lcl_IsInRepeatedHeadline( pStartFrame ) ||
2104  lcl_IsInRepeatedHeadline( pEndFrame ) ) )
2105  {
2106  // Set end- to the start-ContentFrame
2107  if( pStartPos == rCursor.GetPoint() )
2108  pEndFrame = pStartFrame;
2109  else
2110  pStartFrame = pEndFrame;
2111  }
2112  }
2113  break;
2114  default: break;
2115  }
2116  } while( false );
2117 
2118  SwCursorMoveState aTmpState( MV_NONE );
2119  aTmpState.m_b2Lines = true;
2120  aTmpState.m_bNoScroll = true;
2121  aTmpState.m_nCursorBidiLevel = pStartFrame->IsRightToLeft() ? 1 : 0;
2122 
2123  //ContentRects to Start- and EndFrames.
2124  SwRect aStRect, aEndRect;
2125  pStartFrame->GetCharRect( aStRect, *pStartPos, &aTmpState );
2126  std::unique_ptr<Sw2LinesPos> pSt2Pos = std::move(aTmpState.m_p2Lines);
2127  aTmpState.m_nCursorBidiLevel = pEndFrame->IsRightToLeft() ? 1 : 0;
2128 
2129  pEndFrame->GetCharRect( aEndRect, *pEndPos, &aTmpState );
2130  std::unique_ptr<Sw2LinesPos> pEnd2Pos = std::move(aTmpState.m_p2Lines);
2131 
2132  SwRect aStFrame ( pStartFrame->UnionFrame( true ) );
2133  aStFrame.Intersection( pStartFrame->GetPaintArea() );
2134  SwRect aEndFrame( pStartFrame == pEndFrame ? aStFrame : pEndFrame->UnionFrame( true ) );
2135  if( pStartFrame != pEndFrame )
2136  {
2137  aEndFrame.Intersection( pEndFrame->GetPaintArea() );
2138  }
2139  SwRectFnSet aRectFnSet(pStartFrame);
2140  const bool bR2L = pStartFrame->IsRightToLeft();
2141  const bool bEndR2L = pEndFrame->IsRightToLeft();
2142  const bool bB2T = pStartFrame->IsVertLRBT();
2143 
2144  // If there's no doubleline portion involved or start and end are both
2145  // in the same doubleline portion, all works fine, but otherwise
2146  // we need the following...
2147  if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
2148  pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
2149  {
2150  // If we have a start(end) position inside a doubleline portion
2151  // the surrounded part of the doubleline portion is subtracted
2152  // from the region and the aStRect(aEndRect) is set to the
2153  // end(start) of the doubleline portion.
2154  if( pSt2Pos )
2155  {
2156  SwRect aTmp( aStRect );
2157 
2158  // BiDi-Portions are swimming against the current.
2159  const bool bPorR2L = ( MultiPortionType::BIDI == pSt2Pos->nMultiType ) ?
2160  ! bR2L :
2161  bR2L;
2162 
2163  if( MultiPortionType::BIDI == pSt2Pos->nMultiType &&
2164  aRectFnSet.GetWidth(pSt2Pos->aPortion2) )
2165  {
2166  // nested bidi portion
2167  long nRightAbs = aRectFnSet.GetRight(pSt2Pos->aPortion);
2168  nRightAbs -= aRectFnSet.GetLeft(pSt2Pos->aPortion2);
2169  long nLeftAbs = nRightAbs - aRectFnSet.GetWidth(pSt2Pos->aPortion2);
2170 
2171  aRectFnSet.SetRight( aTmp, nRightAbs );
2172 
2173  if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
2174  {
2175  SwRect aTmp2( pSt2Pos->aPortion );
2176  aRectFnSet.SetRight( aTmp2, nLeftAbs );
2177  aTmp2.Intersection( aEndFrame );
2178  Sub( aRegion, aTmp2 );
2179  }
2180  }
2181  else
2182  {
2183  if( bPorR2L )
2184  aRectFnSet.SetLeft( aTmp, aRectFnSet.GetLeft(pSt2Pos->aPortion) );
2185  else
2186  aRectFnSet.SetRight( aTmp, aRectFnSet.GetRight(pSt2Pos->aPortion) );
2187  }
2188 
2189  if( MultiPortionType::ROT_90 == pSt2Pos->nMultiType ||
2190  aRectFnSet.GetTop(pSt2Pos->aPortion) ==
2191  aRectFnSet.GetTop(aTmp) )
2192  {
2193  aRectFnSet.SetTop( aTmp, aRectFnSet.GetTop(pSt2Pos->aLine) );
2194  }
2195 
2196  aTmp.Intersection( aStFrame );
2197  Sub( aRegion, aTmp );
2198 
2199  SwTwips nTmp = aRectFnSet.GetBottom(pSt2Pos->aLine);
2200  if( MultiPortionType::ROT_90 != pSt2Pos->nMultiType &&
2201  aRectFnSet.BottomDist( aStRect, nTmp ) > 0 )
2202  {
2203  aRectFnSet.SetTop( aTmp, aRectFnSet.GetBottom(aTmp) );
2204  aRectFnSet.SetBottom( aTmp, nTmp );
2205  if( aRectFnSet.BottomDist( aStRect, aRectFnSet.GetBottom(pSt2Pos->aPortion) ) > 0 )
2206  {
2207  if( bPorR2L )
2208  aRectFnSet.SetRight( aTmp, aRectFnSet.GetRight(pSt2Pos->aPortion) );
2209  else
2210  aRectFnSet.SetLeft( aTmp, aRectFnSet.GetLeft(pSt2Pos->aPortion) );
2211  }
2212  aTmp.Intersection( aStFrame );
2213  Sub( aRegion, aTmp );
2214  }
2215 
2216  aStRect = pSt2Pos->aLine;
2217  aRectFnSet.SetLeft( aStRect, bR2L ?
2218  aRectFnSet.GetLeft(pSt2Pos->aPortion) :
2219  aRectFnSet.GetRight(pSt2Pos->aPortion) );
2220  aRectFnSet.SetWidth( aStRect, 1 );
2221  }
2222 
2223  if( pEnd2Pos )
2224  {
2225  SwRectFnSet fnRectX(pEndFrame);
2226  SwRect aTmp( aEndRect );
2227 
2228  // BiDi-Portions are swimming against the current.
2229  const bool bPorR2L = ( MultiPortionType::BIDI == pEnd2Pos->nMultiType ) ?
2230  ! bEndR2L :
2231  bEndR2L;
2232 
2233  if( MultiPortionType::BIDI == pEnd2Pos->nMultiType &&
2234  fnRectX.GetWidth(pEnd2Pos->aPortion2) )
2235  {
2236  // nested bidi portion
2237  long nRightAbs = fnRectX.GetRight(pEnd2Pos->aPortion);
2238  nRightAbs = nRightAbs - fnRectX.GetLeft(pEnd2Pos->aPortion2);
2239  long nLeftAbs = nRightAbs - fnRectX.GetWidth(pEnd2Pos->aPortion2);
2240 
2241  fnRectX.SetLeft( aTmp, nLeftAbs );
2242 
2243  if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
2244  {
2245  SwRect aTmp2( pEnd2Pos->aPortion );
2246  fnRectX.SetLeft( aTmp2, nRightAbs );
2247  aTmp2.Intersection( aEndFrame );
2248  Sub( aRegion, aTmp2 );
2249  }
2250  }
2251  else
2252  {
2253  if ( bPorR2L )
2254  fnRectX.SetRight( aTmp, fnRectX.GetRight(pEnd2Pos->aPortion) );
2255  else
2256  fnRectX.SetLeft( aTmp, fnRectX.GetLeft(pEnd2Pos->aPortion) );
2257  }
2258 
2259  if( MultiPortionType::ROT_90 == pEnd2Pos->nMultiType ||
2260  fnRectX.GetBottom(pEnd2Pos->aPortion) ==
2261  fnRectX.GetBottom(aEndRect) )
2262  {
2263  fnRectX.SetBottom( aTmp, fnRectX.GetBottom(pEnd2Pos->aLine) );
2264  }
2265 
2266  aTmp.Intersection( aEndFrame );
2267  Sub( aRegion, aTmp );
2268 
2269  // The next statement means neither ruby nor rotate(90):
2270  if( MultiPortionType::RUBY != pEnd2Pos->nMultiType && MultiPortionType::ROT_90 != pEnd2Pos->nMultiType )
2271  {
2272  SwTwips nTmp = fnRectX.GetTop(pEnd2Pos->aLine);
2273  if( fnRectX.GetTop(aEndRect) != nTmp )
2274  {
2275  fnRectX.SetBottom( aTmp, fnRectX.GetTop(aTmp) );
2276  fnRectX.SetTop( aTmp, nTmp );
2277  if( fnRectX.GetTop(aEndRect) !=
2278  fnRectX.GetTop(pEnd2Pos->aPortion) )
2279  {
2280  if( bPorR2L )
2281  fnRectX.SetLeft( aTmp, fnRectX.GetLeft(pEnd2Pos->aPortion) );
2282  else
2283  fnRectX.SetRight( aTmp, fnRectX.GetRight(pEnd2Pos->aPortion) );
2284  }
2285  aTmp.Intersection( aEndFrame );
2286  Sub( aRegion, aTmp );
2287  }
2288  }
2289 
2290  aEndRect = pEnd2Pos->aLine;
2291  fnRectX.SetLeft( aEndRect, bEndR2L ?
2292  fnRectX.GetRight(pEnd2Pos->aPortion) :
2293  fnRectX.GetLeft(pEnd2Pos->aPortion) );
2294  fnRectX.SetWidth( aEndRect, 1 );
2295  }
2296  }
2297  else if( pSt2Pos && pEnd2Pos &&
2298  MultiPortionType::BIDI == pSt2Pos->nMultiType &&
2299  MultiPortionType::BIDI == pEnd2Pos->nMultiType &&
2300  pSt2Pos->aPortion == pEnd2Pos->aPortion &&
2301  pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
2302  {
2303  // This is the ugly special case, where the selection starts and
2304  // ends in the same bidi portion but one start or end is inside a
2305  // nested bidi portion.
2306 
2307  if ( aRectFnSet.GetWidth(pSt2Pos->aPortion2) )
2308  {
2309  SwRect aTmp( aStRect );
2310  long nRightAbs = aRectFnSet.GetRight(pSt2Pos->aPortion);
2311  nRightAbs -= aRectFnSet.GetLeft(pSt2Pos->aPortion2);
2312  long nLeftAbs = nRightAbs - aRectFnSet.GetWidth(pSt2Pos->aPortion2);
2313 
2314  aRectFnSet.SetRight( aTmp, nRightAbs );
2315  aTmp.Intersection( aStFrame );
2316  Sub( aRegion, aTmp );
2317 
2318  aStRect = pSt2Pos->aLine;
2319  aRectFnSet.SetLeft( aStRect, bR2L ? nRightAbs : nLeftAbs );
2320  aRectFnSet.SetWidth( aStRect, 1 );
2321  }
2322 
2323  SwRectFnSet fnRectX(pEndFrame);
2324  if ( fnRectX.GetWidth(pEnd2Pos->aPortion2) )
2325  {
2326  SwRect aTmp( aEndRect );
2327  long nRightAbs = fnRectX.GetRight(pEnd2Pos->aPortion);
2328  nRightAbs -= fnRectX.GetLeft(pEnd2Pos->aPortion2);
2329  long nLeftAbs = nRightAbs - fnRectX.GetWidth(pEnd2Pos->aPortion2);
2330 
2331  fnRectX.SetLeft( aTmp, nLeftAbs );
2332  aTmp.Intersection( aEndFrame );
2333  Sub( aRegion, aTmp );
2334 
2335  aEndRect = pEnd2Pos->aLine;
2336  fnRectX.SetLeft( aEndRect, bEndR2L ? nLeftAbs : nRightAbs );
2337  fnRectX.SetWidth( aEndRect, 1 );
2338  }
2339  }
2340 
2341  // The charrect may be outside the paintarea (for cursortravelling)
2342  // but the selection has to be restricted to the paintarea
2343  if( aStRect.Left() < aStFrame.Left() )
2344  aStRect.Left( aStFrame.Left() );
2345  else if( aStRect.Left() > aStFrame.Right() )
2346  aStRect.Left( aStFrame.Right() );
2347  SwTwips nTmp = aStRect.Right();
2348  if( nTmp < aStFrame.Left() )
2349  aStRect.Right( aStFrame.Left() );
2350  else if( nTmp > aStFrame.Right() )
2351  aStRect.Right( aStFrame.Right() );
2352  if( aEndRect.Left() < aEndFrame.Left() )
2353  aEndRect.Left( aEndFrame.Left() );
2354  else if( aEndRect.Left() > aEndFrame.Right() )
2355  aEndRect.Left( aEndFrame.Right() );
2356  nTmp = aEndRect.Right();
2357  if( nTmp < aEndFrame.Left() )
2358  aEndRect.Right( aEndFrame.Left() );
2359  else if( nTmp > aEndFrame.Right() )
2360  aEndRect.Right( aEndFrame.Right() );
2361 
2362  if( pStartFrame == pEndFrame )
2363  {
2364  bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
2365  ( MultiPortionType::BIDI == pSt2Pos->nMultiType ||
2366  MultiPortionType::ROT_270 == pSt2Pos->nMultiType ||
2367  MultiPortionType::ROT_90 == pSt2Pos->nMultiType ) &&
2368  pSt2Pos->aPortion == pEnd2Pos->aPortion;
2369  //case 1: (Same frame and same row)
2370  if( bSameRotatedOrBidi ||
2371  aRectFnSet.GetTop(aStRect) == aRectFnSet.GetTop(aEndRect) )
2372  {
2373  Point aTmpSt( aStRect.Pos() );
2374  Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
2375  if (bSameRotatedOrBidi || bR2L || bB2T)
2376  {
2377  if( aTmpSt.Y() > aTmpEnd.Y() )
2378  {
2379  long nTmpY = aTmpEnd.Y();
2380  aTmpEnd.setY( aTmpSt.Y() );
2381  aTmpSt.setY( nTmpY );
2382  }
2383  if( aTmpSt.X() > aTmpEnd.X() )
2384  {
2385  long nTmpX = aTmpEnd.X();
2386  aTmpEnd.setX( aTmpSt.X() );
2387  aTmpSt.setX( nTmpX );
2388  }
2389  }
2390 
2391  SwRect aTmp( aTmpSt, aTmpEnd );
2392  // Bug 34888: If content is selected which doesn't take space
2393  // away (i.e. PostIts, RefMarks, TOXMarks), then at
2394  // least set the width of the Cursor.
2395  if( 1 == aRectFnSet.GetWidth(aTmp) &&
2396  pStartPos->nContent.GetIndex() !=
2397  pEndPos->nContent.GetIndex() )
2398  {
2399  OutputDevice* pOut = pSh->GetOut();
2400  long nCursorWidth = pOut->GetSettings().GetStyleSettings().
2401  GetCursorSize();
2402  aRectFnSet.SetWidth( aTmp, pOut->PixelToLogic(
2403  Size( nCursorWidth, 0 ) ).Width() );
2404  }
2405  aTmp.Intersection( aStFrame );
2406  Sub( aRegion, aTmp );
2407  }
2408  //case 2: (Same frame, but not the same line)
2409  else
2410  {
2411  SwTwips lLeft, lRight;
2412  if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
2413  {
2414  lLeft = aRectFnSet.GetLeft(pSt2Pos->aPortion);
2415  lRight = aRectFnSet.GetRight(pSt2Pos->aPortion);
2416  }
2417  else
2418  {
2419  lLeft = aRectFnSet.GetLeft(pStartFrame->getFrameArea()) +
2420  aRectFnSet.GetLeft(pStartFrame->getFramePrintArea());
2421  lRight = aRectFnSet.GetRight(aEndFrame);
2422  }
2423  if( lLeft < aRectFnSet.GetLeft(aStFrame) )
2424  lLeft = aRectFnSet.GetLeft(aStFrame);
2425  if( lRight > aRectFnSet.GetRight(aStFrame) )
2426  lRight = aRectFnSet.GetRight(aStFrame);
2427  SwRect aSubRect( aStRect );
2428  //First line
2429  if( bR2L )
2430  aRectFnSet.SetLeft( aSubRect, lLeft );
2431  else
2432  aRectFnSet.SetRight( aSubRect, lRight );
2433  Sub( aRegion, aSubRect );
2434 
2435  //If there's at least a twips between start- and endline,
2436  //so the whole area between will be added.
2437  SwTwips aTmpBottom = aRectFnSet.GetBottom(aStRect);
2438  SwTwips aTmpTop = aRectFnSet.GetTop(aEndRect);
2439  if( aTmpBottom != aTmpTop )
2440  {
2441  aRectFnSet.SetLeft( aSubRect, lLeft );
2442  aRectFnSet.SetRight( aSubRect, lRight );
2443  aRectFnSet.SetTop( aSubRect, aTmpBottom );
2444  aRectFnSet.SetBottom( aSubRect, aTmpTop );
2445  Sub( aRegion, aSubRect );
2446  }
2447  //and the last line
2448  aSubRect = aEndRect;
2449  if( bR2L )
2450  aRectFnSet.SetRight( aSubRect, lRight );
2451  else
2452  aRectFnSet.SetLeft( aSubRect, lLeft );
2453  Sub( aRegion, aSubRect );
2454  }
2455  }
2456  //case 3: (Different frames, maybe with other frames between)
2457  else
2458  {
2459  //The startframe first...
2460  SwRect aSubRect( aStRect );
2461  if( bR2L )
2462  aRectFnSet.SetLeft( aSubRect, aRectFnSet.GetLeft(aStFrame));
2463  else
2464  aRectFnSet.SetRight( aSubRect, aRectFnSet.GetRight(aStFrame));
2465  Sub( aRegion, aSubRect );
2466  SwTwips nTmpTwips = aRectFnSet.GetBottom(aStRect);
2467  if( aRectFnSet.GetBottom(aStFrame) != nTmpTwips )
2468  {
2469  aSubRect = aStFrame;
2470  aRectFnSet.SetTop( aSubRect, nTmpTwips );
2471  Sub( aRegion, aSubRect );
2472  }
2473 
2474  //Now the frames between, if there are any
2475  bool const bBody = pStartFrame->IsInDocBody();
2476  const SwTableBox* pCellBox = pStartFrame->GetUpper()->IsCellFrame() ?
2477  static_cast<const SwCellFrame*>(pStartFrame->GetUpper())->GetTabBox() : nullptr;
2478  if (pSh->IsSelectAll())
2479  pCellBox = nullptr;
2480 
2481  const SwContentFrame *pContent = pStartFrame->GetNextContentFrame();
2482  SwRect aPrvRect;
2483 
2484  OSL_ENSURE( pContent,
2485  "<SwRootFrame::CalcFrameRects(..)> - no content frame. This is a serious defect" );
2486  while ( pContent && pContent != pEndFrame )
2487  {
2488  if ( pContent->IsInFly() )
2489  {
2490  const SwAnchoredObject* pObj = pContent->FindFlyFrame();
2491  if (!aSortObjs.Contains(*pObj))
2492  { // is this even possible, assuming valid cursor pos.?
2493  aSortObjs.Insert( *const_cast<SwAnchoredObject*>(pObj) );
2494  }
2495  }
2496 
2497  // Consider only frames which have the same IsInDocBody value like pStartFrame
2498  // If pStartFrame is inside a SwCellFrame, consider only frames which are inside the
2499  // same cell frame (or its follow cell)
2500  const SwTableBox* pTmpCellBox = pContent->GetUpper()->IsCellFrame() ?
2501  static_cast<const SwCellFrame*>(pContent->GetUpper())->GetTabBox() : nullptr;
2502  if (pSh->IsSelectAll())
2503  pTmpCellBox = nullptr;
2504  if ( bBody == pContent->IsInDocBody() &&
2505  ( !pCellBox || pCellBox == pTmpCellBox ) )
2506  {
2507  SwRect aCRect( pContent->UnionFrame( true ) );
2508  aCRect.Intersection( pContent->GetPaintArea() );
2509  if( aCRect.IsOver( aRegion.GetOrigin() ))
2510  {
2511  SwRect aTmp( aPrvRect );
2512  aTmp.Union( aCRect );
2513  if ( (aPrvRect.Height() * aPrvRect.Width() +
2514  aCRect.Height() * aCRect.Width()) ==
2515  (aTmp.Height() * aTmp.Width()) )
2516  {
2517  aPrvRect.Union( aCRect );
2518  }
2519  else
2520  {
2521  if ( aPrvRect.HasArea() )
2522  Sub( aRegion, aPrvRect );
2523  aPrvRect = aCRect;
2524  }
2525  }
2526  }
2527  pContent = pContent->GetNextContentFrame();
2528  OSL_ENSURE( pContent,
2529  "<SwRootFrame::CalcFrameRects(..)> - no content frame. This is a serious defect!" );
2530  }
2531  if ( aPrvRect.HasArea() )
2532  Sub( aRegion, aPrvRect );
2533 
2534  //At least the endframe...
2535  aRectFnSet.Refresh(pEndFrame);
2536  nTmpTwips = aRectFnSet.GetTop(aEndRect);
2537  if( aRectFnSet.GetTop(aEndFrame) != nTmpTwips )
2538  {
2539  aSubRect = aEndFrame;
2540  aRectFnSet.SetBottom( aSubRect, nTmpTwips );
2541  Sub( aRegion, aSubRect );
2542  }
2543  aSubRect = aEndRect;
2544  if( bEndR2L )
2545  aRectFnSet.SetRight(aSubRect, aRectFnSet.GetRight(aEndFrame));
2546  else
2547  aRectFnSet.SetLeft( aSubRect, aRectFnSet.GetLeft(aEndFrame) );
2548  Sub( aRegion, aSubRect );
2549  }
2550 
2551  aRegion.Invert();
2552  pSt2Pos.reset();
2553  pEnd2Pos.reset();
2554 
2555  // Cut out Flys during loop. We don't cut out Flys when:
2556  // - the Lower is StartFrame/EndFrame (FlyInCnt and all other Flys which again
2557  // sit in it)
2558  // - if in the Z-order we have Flys above those in which the StartFrame is
2559  // placed
2560  // - if they are anchored to inside the selection and thus part of it
2561  const SwPageFrame *pPage = pStartFrame->FindPageFrame();
2562  const SwPageFrame *pEndPage = pEndFrame->FindPageFrame();
2563 
2564  while ( pPage )
2565  {
2566  if ( pPage->GetSortedObjs() )
2567  {
2568  const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
2569  for (SwAnchoredObject* pAnchoredObj : rObjs)
2570  {
2571  if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) == nullptr )
2572  continue;
2573  const SwFlyFrame* pFly = static_cast<const SwFlyFrame*>(pAnchoredObj);
2574  const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
2575  const SwFormatSurround &rSur = pFly->GetFormat()->GetSurround();
2576  SwFormatAnchor const& rAnchor(pAnchoredObj->GetFrameFormat().GetAnchor());
2577  const SwPosition* anchoredAt = rAnchor.GetContentAnchor();
2578  bool inSelection = (
2579  anchoredAt != nullptr
2580  && ( (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
2581  && IsDestroyFrameAnchoredAtChar(*anchoredAt, *pStartPos, *pEndPos))
2582  || (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
2583  && *pStartPos <= *anchoredAt
2584  && *anchoredAt < *pEndPos)));
2585  if (anchoredAt != nullptr
2586  && rAnchor.GetAnchorId() != RndStdIds::FLY_AT_CHAR
2587  && *anchoredAt == *pEndPos)
2588  {
2589  const SwNodes& nodes = anchoredAt->GetDoc()->GetNodes();
2590  if( *pEndPos == SwPosition( nodes.GetEndOfContent()))
2591  inSelection = true;
2592  else
2593  {
2594  SwNodeIndex idx( nodes.GetEndOfContent());
2595  if( SwContentNode* last = SwNodes::GoPrevious( &idx ))
2596  inSelection = *pEndPos == SwPosition( *last, last->Len());
2597  }
2598  }
2599  if( inSelection )
2600  Add( aRegion, pFly->getFrameArea() );
2601  else if ( !pFly->IsAnLower( pStartFrame ) &&
2602  (rSur.GetSurround() != css::text::WrapTextMode_THROUGH &&
2603  !rSur.IsContour()) )
2604  {
2605  if ( aSortObjs.Contains( *pAnchoredObj ) )
2606  continue;
2607 
2608  bool bSub = true;
2609  const sal_uInt32 nPos = pObj->GetOrdNum();
2610  for ( size_t k = 0; bSub && k < aSortObjs.size(); ++k )
2611  {
2612  OSL_ENSURE( dynamic_cast< const SwFlyFrame *>( aSortObjs[k] ) != nullptr,
2613  "<SwRootFrame::CalcFrameRects(..)> - object in <aSortObjs> of unexpected type" );
2614  const SwFlyFrame* pTmp = static_cast<SwFlyFrame*>(aSortObjs[k]);
2615  do
2616  {
2617  if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
2618  {
2619  bSub = false;
2620  }
2621  else
2622  {
2623  pTmp = pTmp->GetAnchorFrame()->FindFlyFrame();
2624  }
2625  } while ( bSub && pTmp );
2626  }
2627  if ( bSub )
2628  Sub( aRegion, pFly->getFrameArea() );
2629  }
2630  }
2631  }
2632  if ( pPage == pEndPage )
2633  break;
2634  else
2635  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
2636  }
2637 
2638  //Because it looks better, we close the DropCaps.
2639  SwRect aDropRect;
2640  if ( pStartFrame->IsTextFrame() )
2641  {
2642  if ( static_cast<const SwTextFrame*>(pStartFrame)->GetDropRect( aDropRect ) )
2643  Sub( aRegion, aDropRect );
2644  }
2645  if ( pEndFrame != pStartFrame && pEndFrame->IsTextFrame() )
2646  {
2647  if ( static_cast<const SwTextFrame*>(pEndFrame)->GetDropRect( aDropRect ) )
2648  Sub( aRegion, aDropRect );
2649  }
2650 
2651  rCursor.assign( aRegion.begin(), aRegion.end() );
2652 }
2653 
2654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Primary passes the call to the first page.
Definition: trvlfrm.cxx:419
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:341
bool IsContour() const
Definition: fmtsrnd.hxx:53
const SwVirtFlyDrawObj * GetVirtDrawObj() const
Definition: fly.cxx:2721
Base class of the Writer layout elements.
Definition: frame.hxx:295
Base class that provides the general functionalities for frames that are allowed at page breaks (flow...
Definition: flowfrm.hxx:58
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
virtual sal_Int32 Len() const
Definition: node.cxx:1180
long BottomDist(const SwRect &rRect, long nPos) const
Definition: frame.hxx:1390
const SdrObject * Next()
Definition: frmtool.cxx:2503
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
bool IsFollow() const
Definition: flowfrm.hxx:166
virtual bool RightMargin(SwPaM *, bool bAPI=false) const override
Definition: trvlfrm.cxx:620
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2810
void SetCallbackActionEnabled(bool b)
Definition: rootfrm.hxx:381
void GetContentPosition(const Point &rPt, SwPosition &rPos) const
Same as SwLayoutFrame::GetContentPos().
Definition: trvlfrm.cxx:1375
Marks a position in the document model.
Definition: pam.hxx:35
const SwRect & GetOrigin() const
Definition: swregion.hxx:47
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:98
const SwField * GetField() const
Definition: fmtfld.hxx:70
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:758
bool IsInDocBody() const
Definition: frame.hxx:919
static bool lcl_IsInRepeatedHeadline(const SwFrame *pFrame, const SwTabFrame **ppTFrame=nullptr)
Frame in repeated headline?
Definition: trvlfrm.cxx:642
const SwPageFrame * GetPageAtPos(const Point &rPt, const Size *pSize=nullptr, bool bExtend=false) const
Point rPt: The point that should be used to find the page Size pSize: If given, we return the (first)...
Definition: findfrm.cxx:572
bool IsInFly() const
Definition: frame.hxx:937
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:39
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
void Entry(const SwFlyFrame *pFly)
Definition: trvlfrm.cxx:130
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:62
virtual bool get(DocumentSettingId id) const override
Return the specified document setting.
sal_uInt16 GetCurrPage(const SwPaM *) const
Query/set the current Page and the collective Page count We'll format as much as necessary.
Definition: trvlfrm.cxx:975
static bool more(const double &rfValA, const double &rfValB)
stay with the cursor inside text
Definition: crstate.hxx:127
const SwTable * GetTable() const
Definition: tabfrm.hxx:144
SwNodeIndex nNode
Definition: pam.hxx:37
void Refresh(const SwFrame *pFrame)
Definition: frame.hxx:1335
bool IsInFootnote() const
Definition: frame.hxx:925
SwFrameType GetType() const
Definition: frame.hxx:498
default
Definition: crstate.hxx:123
SwLayoutFrame * GetPrevFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1072
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
const StyleSettings & GetStyleSettings() const
const SwPosition * GetMark() const
Definition: pam.hxx:209
Base class of all fields.
Definition: fldbas.hxx:280
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
sal_uInt8 m_nCursorBidiLevel
Definition: crstate.hxx:139
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1147
const SwFlyFrame * pStack1
Definition: trvlfrm.cxx:115
Definition: doc.hxx:185
helper class to disable creation of an action by a callback event in particular, change event from a ...
Definition: rootfrm.hxx:440
static SwContentNode * GetContentNode(SwDoc *pDoc, SwNodeIndex &rIdx, bool bNext)
Definition: fltshell.cxx:80
bool m_bSetInReadOnly
ReadOnly areas may be entered.
Definition: crstate.hxx:148
void Height(long nNew)
Definition: swrect.hxx:189
sal_uInt16 sal_Char sal_Char * pDesc
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1354
const Point & GetSttPos() const
Definition: viscrs.hxx:146
bool m_bExactOnly
let GetCursorOfst look for exact matches only, i.e.
Definition: crstate.hxx:145
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1288
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
This class is used as parameter for creation of a block cursor selection.
bool IsVert() const
Definition: frame.hxx:1343
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:193
void Pos(const Point &rNew)
Definition: swrect.hxx:167
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
bool IsCellFrame() const
Definition: frame.hxx:1202
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:185
void Top()
Definition: frmtool.cxx:2450
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
SwContentFrame * FindFirstBodyContent()
Definition: pagefrm.hxx:333
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1290
virtual const SwFormatPageDesc & GetPageDescItem() const
Definition: findfrm.cxx:659
long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1385
bool IsDestroyFrameAnchoredAtChar(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
will DelContentIndex destroy a frame anchored at character at rAnchorPos?
Definition: undobj.cxx:1547
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2622
SwLayoutFrame * GetThisFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1067
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
SwContact * GetUserCall(const SdrObject *pObj)
Returns the UserCall if applicable from the group object.
Definition: dcontact.cxx:170
virtual bool GetInfo(SfxPoolItem &) const override
Definition: calbck.cxx:206
bool IsFootnoteFrame() const
Definition: frame.hxx:1178
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:167
static void Sub(SwRegionRects &rRegion, const SwRect &rRect)
Definition: trvlfrm.cxx:1970
SwLayoutFrame * GetNextFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1055
bool m_bFillRet
only used temporary in FillMode
Definition: crstate.hxx:147
static SwCursorOszControl g_OszCtrl
Definition: trvlfrm.cxx:143
void PrepareMake(vcl::RenderContext *pRenderContext)
Prepares the Frame for "formatting" (MakeAll()).
Definition: calcmove.cxx:241
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:190
bool IsSelectAll() const
Definition: viewsh.hxx:568
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
SwTextAttr * GetTextAttrForCharAt(const sal_Int32 nIndex, const sal_uInt16 nWhich=RES_TXTATR_END) const
get the text attribute at position nIndex which owns the dummy character CH_TXTATR_* at that position...
Definition: ndtxt.cxx:3059
long YDiff(long n1, long n2) const
Definition: frame.hxx:1399
SwRect GetPaintArea() const
|* The paintarea is the area, in which the content of a frame is allowed |* to be displayed...
Definition: ssfrm.cxx:581
bool WannaRightPage() const
Decides if the page want to be a rightpage or not.
Definition: trvlfrm.cxx:1705
bool IsFlyFrame() const
Definition: frame.hxx:1186
wrapper class for the positioning of Writer fly frames and drawing objects
long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1386
const SwPageFrame * GetPage() const
Definition: hints.hxx:271
void Top(const long nTop)
Definition: swrect.hxx:202
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:175
void setX(long nX)
SwFlyFrame * GetPrevLink() const
Definition: flyfrm.hxx:172
bool IsEmptyPage() const
Definition: pagefrm.hxx:143
bool IsInTab() const
Definition: frame.hxx:931
SwRect & Intersection(const SwRect &rRect)
Definition: swrect.cxx:54
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:375
void CalcFrameRects(SwShellCursor &)
Definition: trvlfrm.cxx:2007
bool IsTextFrame() const
Definition: frame.hxx:1210
virtual bool UnitUp(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:960
const SwContentFrame *(* GetNxtPrvCnt)(const SwContentFrame *)
Definition: trvlfrm.cxx:639
bool OnRightPage() const
Definition: frame.hxx:711
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
static const SwContentFrame * lcl_GetNxtCnt(const SwContentFrame *pCnt)
Definition: trvlfrm.cxx:629
bool IsPageBodyFrame() const
Definition: layfrm.hxx:214
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:191
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const
Definition: unusedf.cxx:40
SwContentFrame * GetPrevContentFrame() const
Definition: cntfrm.hxx:106
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1087
long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1355
long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1356
void Right(const long nRight)
Definition: swrect.hxx:198
void setY(long nY)
virtual bool UnitDown(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:965
virtual bool LeftMargin(SwPaM *) const override
Layout dependent cursor travelling.
Definition: trvlfrm.cxx:611
SwPageFrame * GetPageByPageNum(sal_uInt16 _nPageNum) const
Get page frame by physical page number looping through the lowers, which are page frame...
Definition: trvlfrm.cxx:1585
void SetBottom(SwRect &rRect, long nNew) const
Definition: frame.hxx:1363
virtual bool GetCharRect(SwRect &, const SwPosition &, SwCursorMoveState *=nullptr, bool bAllowFarAway=true) const
Definition: unusedf.cxx:71
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:164
sal_uInt16 GetVirtPageNum() const
Definition: trvlfrm.cxx:1805
const ::boost::optional< sal_uInt16 > & GetNumOffset() const
Definition: fmtpdsc.hxx:65
bool IsContentNode() const
Definition: node.hxx:628
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
bool FrameContainsNode(SwContentFrame const &rFrame, sal_uLong nNodeIndex)
Definition: txtfrm.cxx:296
Point GetRelPos() const
Definition: trvlfrm.cxx:1795
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:397
void SetWidth(SwRect &rRect, long nNew) const
Definition: frame.hxx:1366
bool IsContentFrame() const
Definition: frame.hxx:1206
void SetTop(SwRect &rRect, long nNew) const
Definition: frame.hxx:1362
double GetLength() const
void Exit(const SwFlyFrame *pFly)
Definition: trvlfrm.cxx:136
const SwSortedObjs * GetSortedObjs() const
Definition: pagefrm.hxx:118
#define SAL_MAX_UINT64
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
long XInc(long n1, long n2) const
Definition: frame.hxx:1400
const SwRect & VisArea() const
Definition: viewsh.cxx:571
#define FRM_HEADFOOT
Definition: frame.hxx:106
SwContentFrame * GetLastSub(const SwLayoutFrame *pLayout)
Definition: trvlfrm.cxx:1050
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
long XDiff(long n1, long n2) const
Definition: frame.hxx:1398
SwFrameType
Definition: frame.hxx:72
bool Insert(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:206
bool IsCoveredCell() const
Definition: tabfrm.cxx:5701
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:877
static bool lcl_UpDown(SwPaM *pPam, const SwContentFrame *pStart, GetNxtPrvCnt fnNxtPrv, bool bInReadOnly)
Definition: trvlfrm.cxx:685
size_t size() const
Definition: sortedobjs.cxx:42
SwPageFrame * FindPageFrame()
Definition: frame.hxx:658
SwLayoutFrame *(* SwWhichPage)(const SwLayoutFrame *)
Definition: cshtyp.hxx:34
SwFrameFormat * GetLeftFormat(bool const bFirst=false)
Definition: pagedesc.cxx:362
bool IsDummyPage(sal_uInt16 nPageNum) const
Definition: trvlfrm.cxx:1606
bool isEmpty() const
Reports if the list does not contain any text portion.
const SwFrame * Lower() const
Definition: layfrm.hxx:101
SwPageDesc * GetPageDesc()
Definition: pagefrm.hxx:129
SwContentNode * GetContentNode()
Definition: node.hxx:615
FlyAnchors.
Definition: fmtanchr.hxx:34
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
bool HasArea() const
Definition: swrect.hxx:290
static const SwContentFrame * lcl_MissProtectedFrames(const SwContentFrame *pCnt, GetNxtPrvCnt fnNxtPrv, bool bMissHeadline, bool bInReadOnly, bool bMissFollowFlowLine)
Skip protected table cells. Optionally also skip repeated headlines.
Definition: trvlfrm.cxx:654
bool isFramePrintAreaValid() const
Definition: frame.hxx:164
Marks a character position inside a document model node.
Definition: index.hxx:37
const SwFlyFrame * pEntry
Definition: trvlfrm.cxx:114
bool IsRowFrame() const
Definition: frame.hxx:1198
sal_uInt32 GetOrdNum() const
static const SwLayoutFrame * lcl_Inside(const SwContentFrame *pCnt, Point const &rPt)
Check if the point lies inside the page part in which also the ContentFrame lies. ...
Definition: trvlfrm.cxx:1154
not in repeated headlines
Definition: crstate.hxx:128
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
SwFrame * GetPrev()
Definition: frame.hxx:655
const Point & GetMkPos() const
Definition: viscrs.hxx:144
bool IsContentProtected() const
const SwRowFrame * IsInFollowFlowRow() const
Definition: findfrm.cxx:1774
Marks a node in the document model.
Definition: ndindex.hxx:31
void MakeSelUnions(SwSelUnions &rUnions, const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:1756
bool IsPDFExport() const
Definition: viewopt.hxx:378
const AllSettings & GetSettings() const
bool isFrameAreaPositionValid() const
Definition: frame.hxx:162
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the ContentFrame owning the PrtArea containing the point.
Definition: trvlfrm.cxx:146
static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2)
Definition: trvlfrm.cxx:1137
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
void SSize(const Size &rNew)
Definition: swrect.hxx:176
SwRect UnionFrame(bool bBorder=false) const
|* The unionframe is the framearea (getFrameArea()) of a frame expanded by the |* printarea...
Definition: ssfrm.cxx:676
bool isFrameAreaSizeValid() const
Definition: frame.hxx:163
virtual const SwAnchoredObject * GetAnchoredObj(const SdrObject *_pSdrObj) const =0
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the page containing the searched point.
Definition: trvlfrm.cxx:175
A page of the document layout.
Definition: pagefrm.hxx:40
bool m_bNoScroll
No scrolling of undersized textframes.
Definition: crstate.hxx:151
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const
Definition: unusedf.cxx:46
bool m_b2Lines
Check 2line portions and fill p2Lines.
Definition: crstate.hxx:150
long GetPrtRight(const SwFrame &rFrame) const
Definition: frame.hxx:1388
long X() const
const SwModify * GetDefinedIn() const
Query / set where attribute is anchored.
Definition: fmtpdsc.hxx:69
bool MakeTableCursors(SwTableCursor &)
Calculates the cells included from the current selection.
Definition: trvlfrm.cxx:1859
SwContentFrame * GetFirstSub(const SwLayoutFrame *pLayout)
Definition: trvlfrm.cxx:1045
const SwPosition * Start() const
Definition: pam.hxx:212
std::unique_ptr< Sw2LinesPos > m_p2Lines
for selections inside/around 2line portions
Definition: crstate.hxx:135
Point Center() const
Definition: swrect.cxx:33
bool IsInProtectSect() const
Is node in a protected area?
Definition: node.cxx:408
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:246
const SwFrame * GetFrame() const
Definition: hints.hxx:273
SwDoc * GetDoc()
Which Doc contains the nodes-array?
Definition: ndarr.hxx:305
const SwCellFrame * FirstCell() const
Calls ContainsAny first to reach the innermost cell.
Definition: findfrm.cxx:112
Point PixelToLogic(const Point &rDevicePt) const
void SetLeft(SwRect &rRect, long nNew) const
Definition: frame.hxx:1364
long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1387
SwFillCursorPos * m_pFill
for automatic filling with tabs etc
Definition: crstate.hxx:134
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1357
virtual bool IsReadOnlyAvailable() const
Definition: swcrsr.cxx:144
bool IsLayoutFrame() const
Definition: frame.hxx:1146
void Left(const long nLeft)
Definition: swrect.hxx:193
static void Add(SwRegionRects &rRegion, const SwRect &rRect)
Definition: trvlfrm.cxx:1977
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void Bottom(const long nBottom)
Definition: swrect.hxx:207
const SwContentNode * GetNode() const
Definition: notxtfrm.hxx:60
SwFlyFrame * GetFlyFrame()
Definition: dflyobj.hxx:130
#define RES_TXTATR_FIELD
Definition: hintids.hxx:151
SwContentFrame * FindLastBodyContent()
Searches the last ContentFrame in BodyText below the page.
Definition: findfrm.cxx:51
SwRowFrame * GetFirstNonHeadlineRow() const
Definition: tabfrm.cxx:5360
SwContentFrame *(* SwPosPage)(const SwLayoutFrame *)
Definition: cshtyp.hxx:38
const SvxOpaqueItem & GetOpaque(bool=true) const
Definition: frmatr.hxx:80
general base class for all free-flowing frames
Definition: flyfrm.hxx:60
bool IsFrameInTableSel(const SwRect &rUnion, const SwFrame *pCell)
Definition: tblsel.cxx:660
sal_uInt16 SetCurrPage(SwCursor *, sal_uInt16 nPageNum)
Returns a PaM which sits at the beginning of the requested page.
Definition: trvlfrm.cxx:991
virtual SwFrameFormat & GetFrameFormat()=0
bool GetFrameInPage(const SwContentFrame *pCnt, SwWhichPage fnWhichPage, SwPosPage fnPosPage, SwPaM *pPam)
Returns the first/last Contentframe (controlled using the parameter fnPosPage) of the current/previou...
Definition: trvlfrm.cxx:1088
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1688
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
void Width(long nNew)
Definition: swrect.hxx:185
std::vector< SwSelUnion > SwSelUnions
Definition: tblsel.hxx:138
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
If this is about a Content-carrying cell the Cursor will be force inserted into one of the ContentFra...
Definition: trvlfrm.cxx:466
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool IsInside(const Point &rPOINT) const
Definition: swrect.cxx:107
SwFrameFormat * GetRightFormat(bool const bFirst=false)
Layout uses the following methods to obtain a format in order to be able to create a page...
Definition: pagedesc.cxx:369
bool IsNoTextFrame() const
Definition: frame.hxx:1214
const SwFlyFrame * pStack2
Definition: trvlfrm.cxx:116
SwNodes & GetNodes()
Definition: doc.hxx:402
Item2Range GetItemSurrogates(sal_uInt16 nWhich) const
bool IsRightToLeft() const
Definition: frame.hxx:963
::sw::DocumentSettingManager & GetDocumentSettingManager()
Definition: doc.cxx:185
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:386
SwFrame * GetLower()
Definition: findfrm.cxx:169
bool IsPageFrame() const
Definition: frame.hxx:1154
const Point & GetPtPos() const
Definition: viscrs.hxx:142
void SetRight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1365
CursorMoveState m_eState
Definition: crstate.hxx:138
bool m_bPosMatchesBounds
GetCursorOfst should not return the next position if screen position is inside second have of bound r...
Definition: crstate.hxx:152
bool OnFirstPage() const
Definition: trvlfrm.cxx:1759
const SwTabFrame * GetFollow() const
Definition: tabfrm.hxx:243
virtual bool GetCursorOfst(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the ContentFrame owning the PrtArea containing the point.
Definition: trvlfrm.cxx:534
bool Contains(const SwAnchoredObject &_rAnchoredObj) const
Definition: sortedobjs.cxx:243
const Point & GetEndPos() const
Definition: viscrs.hxx:148
virtual void Calc(vcl::RenderContext *pRenderContext) const override
Definition: fly.cxx:2820
long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1353
void ActualizeSelection(const SwSelBoxes &rBoxes)
Definition: swcrsr.cxx:2449
const SvxProtectItem & GetProtect(bool=true) const
Definition: frmatr.hxx:82
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
const SwFrame * GetAnchorFrame() const
const SwLayoutFrame * GetNextLayoutLeaf() const
Definition: frame.hxx:996
Point GetPagePos(sal_uInt16 nPageNum) const
Returns the absolute document position of the desired page.
Definition: trvlfrm.cxx:1567
std::pair< const_iterator, bool > insert(Value &&x)
bool IsFootnoteContFrame() const
Definition: frame.hxx:1174
bool ChkOsz(const SwFlyFrame *pFly)
Definition: trvlfrm.cxx:118
#define RES_PAGEDESC
Definition: hintids.hxx:200
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:125
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
Point GetNextPrevContentPos(const Point &rPoint, bool bNext) const
Search the nearest Content to the passed point.
Definition: trvlfrm.cxx:1468
SwTableLine * GetUpper()
Definition: swtable.hxx:421
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:204
sal_Int32 nPos
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
class for collecting anchored objects
Definition: sortedobjs.hxx:48
bool NewTableSelection()
Definition: swcrsr.cxx:2428
const SwContentFrame * GetContentPos(Point &rPoint, const bool bDontLeave, const bool bBodyOnly=false, SwCursorMoveState *pCMS=nullptr, const bool bDefaultExpand=true) const
Finds the closest Content for the SPoint Is used for Pages, Flys and Cells if GetCursorOfst failed...
Definition: trvlfrm.cxx:1179
bool IsTextNode() const
Definition: node.hxx:636
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1245
bool IsClickable() const
Is this field clickable?
Definition: fldbas.cxx:758
sal_uInt16 GetPageNum() const
Definition: rootfrm.hxx:307
bool IsFooterFrame() const
Definition: frame.hxx:1170
static const SwContentFrame * lcl_GetPrvCnt(const SwContentFrame *pCnt)
Definition: trvlfrm.cxx:634
SwRootFrame * getRootFrame()
Definition: frame.hxx:657
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
bool IsCallbackActionEnabled() const
Definition: rootfrm.hxx:382
long Y() const
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1309
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
bool IsHeaderFrame() const
Definition: frame.hxx:1166
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:361
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5341
void SAL_CALL last(const css::awt::SpinEvent &rEvent) override
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:393
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1621
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1075
SwFrame * GetNext()
Definition: frame.hxx:654
void setHeight(long nHeight)