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_GetModelPositionForViewPoint_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->GetModelPositionForViewPoint( 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 namespace {
109 
110 //For SwFlyFrame::GetModelPositionForViewPoint
111 class SwCursorOszControl
112 {
113 public:
114  // So the compiler can initialize the class already. No DTOR and member
115  // as public members
116  const SwFlyFrame* m_pEntry;
117  const SwFlyFrame* m_pStack1;
118  const SwFlyFrame* m_pStack2;
119 
120  bool ChkOsz( const SwFlyFrame *pFly )
121  {
122  bool bRet = true;
123  if (pFly != m_pStack1 && pFly != m_pStack2)
124  {
125  m_pStack1 = m_pStack2;
126  m_pStack2 = pFly;
127  bRet = false;
128  }
129  return bRet;
130  }
131 
132  void Entry( const SwFlyFrame *pFly )
133  {
134  if (!m_pEntry)
135  m_pEntry = m_pStack1 = pFly;
136  }
137 
138  void Exit( const SwFlyFrame *pFly )
139  {
140  if (pFly == m_pEntry)
141  m_pEntry = m_pStack1 = m_pStack2 = nullptr;
142  }
143 };
144 
145 }
146 
147 static SwCursorOszControl g_OszCtrl = { nullptr, nullptr, nullptr };
148 
151  SwCursorMoveState* pCMS, bool ) const
152 {
153  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
154  bool bRet = false;
155  const SwFrame *pFrame = Lower();
156  while ( !bRet && pFrame )
157  {
158  pFrame->Calc(pRenderContext);
159 
160  // #i43742# New function
161  const bool bContentCheck = pFrame->IsTextFrame() && pCMS && pCMS->m_bContentCheck;
162  const SwRect aPaintRect( bContentCheck ?
163  pFrame->UnionFrame() :
164  pFrame->GetPaintArea() );
165 
166  if ( aPaintRect.IsInside( rPoint ) &&
167  ( bContentCheck || pFrame->GetModelPositionForViewPoint( pPos, rPoint, pCMS ) ) )
168  bRet = true;
169  else
170  pFrame = pFrame->GetNext();
171  if ( pCMS && pCMS->m_bStop )
172  return false;
173  }
174  return bRet;
175 }
176 
180  SwCursorMoveState* pCMS, bool bTestBackground ) const
181 {
182  Point aPoint( rPoint );
183 
184  // check, if we have to adjust the point
185  if ( !getFrameArea().IsInside( aPoint ) )
186  {
187  aPoint.setX( std::max( aPoint.X(), getFrameArea().Left() ) );
188  aPoint.setX( std::min( aPoint.X(), getFrameArea().Right() ) );
189  aPoint.setY( std::max( aPoint.Y(), getFrameArea().Top() ) );
190  aPoint.setY( std::min( aPoint.Y(), getFrameArea().Bottom() ) );
191  }
192 
193  bool bRet = false;
194  //Could it be a free flying one?
195  //If his content should be protected, we can't set the Cursor in it, thus
196  //all changes should be impossible.
197  if ( GetSortedObjs() )
198  {
199  bRet = lcl_GetModelPositionForViewPoint_Objects( this, false, pPos, rPoint, pCMS );
200  }
201 
202  if ( !bRet )
203  {
204  SwPosition aBackPos( *pPos );
205  SwPosition aTextPos( *pPos );
206 
207  //We fix the StartPoint if no Content below the page 'answers' and then
208  //start all over again one page before the current one.
209  //However we can't use Flys in such a case.
210  if (!SwLayoutFrame::GetModelPositionForViewPoint(&aTextPos, aPoint, pCMS))
211  {
212  if ( pCMS && (pCMS->m_bStop || pCMS->m_bExactOnly) )
213  {
214  pCMS->m_bStop = true;
215  return false;
216  }
217 
218  const SwContentFrame *pCnt = GetContentPos( aPoint, false, false, pCMS, false );
219  // GetContentPos may have modified pCMS
220  if ( pCMS && pCMS->m_bStop )
221  return false;
222 
223  bool bTextRet = false;
224 
225  OSL_ENSURE( pCnt, "Cursor is gone to a Black hole" );
226  if( pCMS && pCMS->m_pFill && pCnt->IsTextFrame() )
227  bTextRet = pCnt->GetModelPositionForViewPoint( &aTextPos, rPoint, pCMS );
228  else
229  bTextRet = pCnt->GetModelPositionForViewPoint( &aTextPos, aPoint, pCMS );
230 
231  if ( !bTextRet )
232  {
233  // Set point to pCnt, delete mark
234  // this may happen, if pCnt is hidden
235  if (pCnt->IsTextFrame())
236  {
237  aTextPos = static_cast<SwTextFrame const*>(pCnt)->MapViewToModelPos(TextFrameIndex(0));
238  }
239  else
240  {
241  assert(pCnt->IsNoTextFrame());
242  aTextPos = SwPosition( *static_cast<SwNoTextFrame const*>(pCnt)->GetNode() );
243  }
244  }
245  }
246 
247  SwContentNode* pContentNode = aTextPos.nNode.GetNode().GetContentNode();
248  bool bConsiderBackground = true;
249  // If the text position is a clickable field, then that should have priority.
250  if (pContentNode && pContentNode->IsTextNode())
251  {
252  SwTextNode* pTextNd = pContentNode->GetTextNode();
253  SwTextAttr* pTextAttr = pTextNd->GetTextAttrForCharAt(aTextPos.nContent.GetIndex(), RES_TXTATR_FIELD);
254  if (pTextAttr)
255  {
256  const SwField* pField = pTextAttr->GetFormatField().GetField();
257  if (pField->IsClickable())
258  bConsiderBackground = false;
259  }
260  }
261 
262  bool bBackRet = false;
263  // Check objects in the background if nothing else matched
264  if ( GetSortedObjs() )
265  {
266  bBackRet = lcl_GetModelPositionForViewPoint_Objects( this, true, &aBackPos, rPoint, pCMS );
267  }
268 
269  if (bConsiderBackground && bTestBackground && bBackRet)
270  {
271  (*pPos) = aBackPos;
272  }
273  else if (!bBackRet)
274  {
275  (*pPos) = aTextPos;
276  }
277  else // bBackRet && !(bConsiderBackground && bTestBackground)
278  {
279  /* In order to provide a selection as accurate as possible when we have both
280  * text and background object, then we compute the distance between both
281  * would-be positions and the click point. The shortest distance wins.
282  */
283  double nTextDistance = 0;
284  bool bValidTextDistance = false;
285  if (pContentNode)
286  {
287  SwContentFrame* pTextFrame = pContentNode->getLayoutFrame( getRootFrame( ) );
288 
289  // try this again but prefer the "previous" position
290  SwCursorMoveState aMoveState;
291  SwCursorMoveState *const pState(pCMS ? pCMS : &aMoveState);
293  pState->m_bPosMatchesBounds, true);
294  SwPosition prevTextPos(*pPos);
295  if (SwLayoutFrame::GetModelPositionForViewPoint(&prevTextPos, aPoint, pState))
296  {
297  SwRect aTextRect;
298  pTextFrame->GetCharRect(aTextRect, prevTextPos);
299 
300  if (prevTextPos.nContent < pContentNode->Len())
301  {
302  // aRextRect is just a line on the left edge of the
303  // previous character; to get a better measure from
304  // lcl_getDistance, extend that to a rectangle over
305  // the entire character.
306  SwPosition const nextTextPos(prevTextPos.nNode,
307  SwIndex(prevTextPos.nContent, +1));
308  SwRect nextTextRect;
309  pTextFrame->GetCharRect(nextTextRect, nextTextPos);
310  SwRectFnSet aRectFnSet(pTextFrame);
311  if (aRectFnSet.GetTop(aTextRect) ==
312  aRectFnSet.GetTop(nextTextRect)) // same line?
313  {
314  // need to handle mixed RTL/LTR portions somehow
315  if (aRectFnSet.GetLeft(aTextRect) <
316  aRectFnSet.GetLeft(nextTextRect))
317  {
318  aRectFnSet.SetRight( aTextRect,
319  aRectFnSet.GetLeft(nextTextRect));
320  }
321  else // RTL
322  {
323  aRectFnSet.SetLeft( aTextRect,
324  aRectFnSet.GetLeft(nextTextRect));
325  }
326  }
327  }
328 
329  nTextDistance = lcl_getDistance(aTextRect, rPoint);
330  bValidTextDistance = true;
331  }
332  }
333 
334  double nBackDistance = 0;
335  bool bValidBackDistance = false;
336  SwContentNode* pBackNd = aBackPos.nNode.GetNode( ).GetContentNode( );
337  if ( pBackNd && bConsiderBackground)
338  {
339  // FIXME There are still cases were we don't have the proper node here.
340  SwContentFrame* pBackFrame = pBackNd->getLayoutFrame( getRootFrame( ) );
341  if (pBackFrame)
342  {
343  SwRect rBackRect;
344  pBackFrame->GetCharRect( rBackRect, aBackPos );
345 
346  nBackDistance = lcl_getDistance( rBackRect, rPoint );
347  bValidBackDistance = true;
348  }
349  }
350 
351  if ( bValidTextDistance && bValidBackDistance && basegfx::fTools::more( nTextDistance, nBackDistance ) )
352  {
353  (*pPos) = aBackPos;
354  }
355  else
356  {
357  (*pPos) = aTextPos;
358  }
359  }
360  }
361 
362  rPoint = aPoint;
363  return true;
364 }
365 
366 bool SwLayoutFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
367 {
368  if( rRect.IsOver(GetPaintArea()) )
369  {
370  const SwFrame* pFrame = Lower();
371  while( pFrame )
372  {
373  pFrame->FillSelection( rList, rRect );
374  pFrame = pFrame->GetNext();
375  }
376  }
377  return false;
378 }
379 
380 bool SwPageFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
381 {
382  bool bRet = false;
383  if( rRect.IsOver(GetPaintArea()) )
384  {
385  bRet = SwLayoutFrame::FillSelection( rList, rRect );
386  if( GetSortedObjs() )
387  {
388  const SwSortedObjs &rObjs = *GetSortedObjs();
389  for (SwAnchoredObject* pAnchoredObj : rObjs)
390  {
391  const SwFlyFrame* pFly = dynamic_cast<const SwFlyFrame*>(pAnchoredObj);
392  if( !pFly )
393  continue;
394  if( pFly->FillSelection( rList, rRect ) )
395  bRet = true;
396  }
397  }
398  }
399  return bRet;
400 }
401 
402 bool SwRootFrame::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
403 {
404  const SwFrame *pPage = Lower();
405  const tools::Long nBottom = rRect.Bottom();
406  while( pPage )
407  {
408  if( pPage->getFrameArea().Top() < nBottom )
409  {
410  if( pPage->getFrameArea().Bottom() > rRect.Top() )
411  pPage->FillSelection( aSelList, rRect );
412  pPage = pPage->GetNext();
413  }
414  else
415  pPage = nullptr;
416  }
417  return !aSelList.isEmpty();
418 }
419 
425  SwCursorMoveState* pCMS, bool bTestBackground ) const
426 {
427  const bool bOldAction = IsCallbackActionEnabled();
428  const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( false );
429  OSL_ENSURE( (Lower() && Lower()->IsPageFrame()), "No PageFrame found." );
430  if( pCMS && pCMS->m_pFill )
431  pCMS->m_bFillRet = false;
432  Point aOldPoint = rPoint;
433 
434  // search for page containing rPoint. The borders around the pages are considered
435  const SwPageFrame* pPage = GetPageAtPos( rPoint, nullptr, true );
436 
437  // #i95626#
438  // special handling for <rPoint> beyond root frames area
439  if ( !pPage &&
440  rPoint.X() > getFrameArea().Right() &&
441  rPoint.Y() > getFrameArea().Bottom() )
442  {
443  pPage = dynamic_cast<const SwPageFrame*>(Lower());
444  while ( pPage && pPage->GetNext() )
445  {
446  pPage = dynamic_cast<const SwPageFrame*>(pPage->GetNext());
447  }
448  }
449  if ( pPage )
450  {
451  pPage->SwPageFrame::GetModelPositionForViewPoint( pPos, rPoint, pCMS, bTestBackground );
452  }
453 
454  const_cast<SwRootFrame*>(this)->SetCallbackActionEnabled( bOldAction );
455  if( pCMS )
456  {
457  if( pCMS->m_bStop )
458  return false;
459  if( pCMS->m_pFill )
460  return pCMS->m_bFillRet;
461  }
462  return aOldPoint == rPoint;
463 }
464 
472  SwCursorMoveState* pCMS, bool ) const
473 {
474  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
475  // cell frame does not necessarily have a lower (split table cell)
476  if ( !Lower() )
477  return false;
478 
479  if ( !(pCMS && pCMS->m_bSetInReadOnly) &&
480  GetFormat()->GetProtect().IsContentProtected() )
481  return false;
482 
483  if ( pCMS && pCMS->m_eState == CursorMoveState::TableSel )
484  {
485  const SwTabFrame *pTab = FindTabFrame();
486  if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
487  {
488  pCMS->m_bStop = true;
489  return false;
490  }
491  }
492 
493  if ( Lower() )
494  {
495  if ( Lower()->IsLayoutFrame() )
496  return SwLayoutFrame::GetModelPositionForViewPoint( pPos, rPoint, pCMS );
497  else
498  {
499  Calc(pRenderContext);
500  bool bRet = false;
501 
502  const SwFrame *pFrame = Lower();
503  while ( pFrame && !bRet )
504  {
505  pFrame->Calc(pRenderContext);
506  if ( pFrame->getFrameArea().IsInside( rPoint ) )
507  {
508  bRet = pFrame->GetModelPositionForViewPoint( pPos, rPoint, pCMS );
509  if ( pCMS && pCMS->m_bStop )
510  return false;
511  }
512  pFrame = pFrame->GetNext();
513  }
514  if ( !bRet )
515  {
516  const bool bFill = pCMS && pCMS->m_pFill;
517  Point aPoint( rPoint );
518  const SwContentFrame *pCnt = GetContentPos( rPoint, true );
519  if( bFill && pCnt->IsTextFrame() )
520  {
521  rPoint = aPoint;
522  }
523  pCnt->GetModelPositionForViewPoint( pPos, rPoint, pCMS );
524  }
525  return true;
526  }
527  }
528 
529  return false;
530 }
531 
532 //Problem: If two Flys have the same size and share the same position then
533 //they end inside each other.
534 //Because we recursively check if a Point doesn't randomly lie inside another
535 //fly which lies completely inside the current Fly we could trigger an endless
536 //loop with the mentioned situation above.
537 //Using the helper class SwCursorOszControl we prevent the recursion. During
538 //a recursion GetModelPositionForViewPoint picks the one which lies on top.
540  SwCursorMoveState* pCMS, bool ) const
541 {
542  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
543  g_OszCtrl.Entry( this );
544 
545  //If the Points lies inside the Fly, we try hard to set the Cursor inside it.
546  //However if the Point sits inside a Fly which is completely located inside
547  //the current one, we call GetModelPositionForViewPoint for it.
548  Calc(pRenderContext);
549  bool bInside = getFrameArea().IsInside( rPoint ) && Lower();
550  bool bRet = false;
551 
552  //If a Frame contains a graphic, but only text was requested, it basically
553  //won't accept the Cursor.
554  if ( bInside && pCMS && pCMS->m_eState == CursorMoveState::SetOnlyText &&
555  (!Lower() || Lower()->IsNoTextFrame()) )
556  bInside = false;
557 
558  const SwPageFrame *pPage = FindPageFrame();
559  if ( bInside && pPage && pPage->GetSortedObjs() )
560  {
561  SwOrderIter aIter( pPage );
562  aIter.Top();
563  while ( aIter() && !bRet )
564  {
565  const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
566  const SwFlyFrame* pFly = pObj ? pObj->GetFlyFrame() : nullptr;
567  if ( pFly && pFly->getFrameArea().IsInside( rPoint ) &&
568  getFrameArea().IsInside( pFly->getFrameArea() ) )
569  {
570  if (g_OszCtrl.ChkOsz(pFly))
571  break;
572  bRet = pFly->GetModelPositionForViewPoint( pPos, rPoint, pCMS );
573  if ( bRet )
574  break;
575  if ( pCMS && pCMS->m_bStop )
576  return false;
577  }
578  aIter.Next();
579  }
580  }
581 
582  while ( bInside && !bRet )
583  {
584  const SwFrame *pFrame = Lower();
585  while ( pFrame && !bRet )
586  {
587  pFrame->Calc(pRenderContext);
588  if ( pFrame->getFrameArea().IsInside( rPoint ) )
589  {
590  bRet = pFrame->GetModelPositionForViewPoint( pPos, rPoint, pCMS );
591  if ( pCMS && pCMS->m_bStop )
592  return false;
593  }
594  pFrame = pFrame->GetNext();
595  }
596  if ( !bRet )
597  {
598  const bool bFill = pCMS && pCMS->m_pFill;
599  Point aPoint( rPoint );
600  const SwContentFrame *pCnt = GetContentPos( rPoint, true, false, pCMS );
601  if ( pCMS && pCMS->m_bStop )
602  return false;
603  if( bFill && pCnt->IsTextFrame() )
604  {
605  rPoint = aPoint;
606  }
607  pCnt->GetModelPositionForViewPoint( pPos, rPoint, pCMS );
608  bRet = true;
609  }
610  }
611  g_OszCtrl.Exit( this );
612  return bRet;
613 }
614 
617 {
618  if( &pPam->GetNode() != GetNode() )
619  return false;
620  const_cast<SwContentNode*>(GetNode())->
621  MakeStartIndex(&pPam->GetPoint()->nContent);
622  return true;
623 }
624 
625 bool SwNoTextFrame::RightMargin(SwPaM *pPam, bool) const
626 {
627  if( &pPam->GetNode() != GetNode() )
628  return false;
629  const_cast<SwContentNode*>(GetNode())->
630  MakeEndIndex(&pPam->GetPoint()->nContent);
631  return true;
632 }
633 
634 static const SwContentFrame *lcl_GetNxtCnt( const SwContentFrame* pCnt )
635 {
636  return pCnt->GetNextContentFrame();
637 }
638 
639 static const SwContentFrame *lcl_GetPrvCnt( const SwContentFrame* pCnt )
640 {
641  return pCnt->GetPrevContentFrame();
642 }
643 
644 typedef const SwContentFrame *(*GetNxtPrvCnt)( const SwContentFrame* );
645 
647 static bool lcl_IsInRepeatedHeadline( const SwFrame *pFrame,
648  const SwTabFrame** ppTFrame = nullptr )
649 {
650  const SwTabFrame *pTab = pFrame->FindTabFrame();
651  if( ppTFrame )
652  *ppTFrame = pTab;
653  return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrame );
654 }
655 
657 //MA 1998-01-26: Chg also skip other protected areas
658 //FME: Skip follow flow cells
660  GetNxtPrvCnt fnNxtPrv,
661  bool bMissHeadline,
662  bool bInReadOnly,
663  bool bMissFollowFlowLine )
664 {
665  if ( pCnt && pCnt->IsInTab() )
666  {
667  bool bProtect = true;
668  while ( pCnt && bProtect )
669  {
670  const SwLayoutFrame *pCell = pCnt->GetUpper();
671  while ( pCell && !pCell->IsCellFrame() )
672  pCell = pCell->GetUpper();
673  if ( !pCell ||
674  ( ( bInReadOnly || !pCell->GetFormat()->GetProtect().IsContentProtected() ) &&
675  ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
676  ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
677  !pCell->IsCoveredCell() ) )
678  bProtect = false;
679  else
680  pCnt = (*fnNxtPrv)( pCnt );
681  }
682  }
683  else if ( !bInReadOnly )
684  while ( pCnt && pCnt->IsProtected() )
685  pCnt = (*fnNxtPrv)( pCnt );
686 
687  return pCnt;
688 }
689 
690 static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart,
691  GetNxtPrvCnt fnNxtPrv, bool bInReadOnly )
692 {
693  OSL_ENSURE( FrameContainsNode(*pStart, pPam->GetNode().GetIndex()),
694  "lcl_UpDown doesn't work for others." );
695 
696  const SwContentFrame *pCnt = nullptr;
697 
698  //We have to cheat a little bit during a table selection: Go to the
699  //beginning of the cell while going up and go to the end of the cell while
700  //going down.
701  bool bTableSel = false;
702  if ( pStart->IsInTab() &&
703  pPam->GetNode().StartOfSectionNode() !=
704  pPam->GetNode( false ).StartOfSectionNode() )
705  {
706  bTableSel = true;
707  const SwLayoutFrame *pCell = pStart->GetUpper();
708  while ( !pCell->IsCellFrame() )
709  pCell = pCell->GetUpper();
710 
711  // Check, if cell has a Prev/Follow cell:
712  const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
713  const SwLayoutFrame* pTmpCell = bFwd ?
714  static_cast<const SwCellFrame*>(pCell)->GetFollowCell() :
715  static_cast<const SwCellFrame*>(pCell)->GetPreviousCell();
716 
717  const SwContentFrame* pTmpStart = pStart;
718  while ( pTmpCell && nullptr != ( pTmpStart = pTmpCell->ContainsContent() ) )
719  {
720  pCell = pTmpCell;
721  pTmpCell = bFwd ?
722  static_cast<const SwCellFrame*>(pCell)->GetFollowCell() :
723  static_cast<const SwCellFrame*>(pCell)->GetPreviousCell();
724  }
725  const SwContentFrame *pNxt = pCnt = pTmpStart;
726 
727  while ( pCell->IsAnLower( pNxt ) )
728  {
729  pCnt = pNxt;
730  pNxt = (*fnNxtPrv)( pNxt );
731  }
732  }
733 
734  pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
735  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
736 
737  const SwTabFrame *pStTab = pStart->FindTabFrame();
738  const SwTabFrame *pTable = nullptr;
739  const bool bTab = pStTab || (pCnt && pCnt->IsInTab());
740  bool bEnd = !bTab;
741 
742  const SwFrame* pVertRefFrame = pStart;
743  if ( bTableSel && pStTab )
744  pVertRefFrame = pStTab;
745  SwRectFnSet aRectFnSet(pVertRefFrame);
746 
747  SwTwips nX = 0;
748  if ( bTab )
749  {
750  // pStart or pCnt is inside a table. nX will be used for travelling:
751  SwRect aRect( pStart->getFrameArea() );
752  pStart->GetCharRect( aRect, *pPam->GetPoint() );
753  Point aCenter = aRect.Center();
754  nX = aRectFnSet.IsVert() ? aCenter.Y() : aCenter.X();
755 
756  pTable = pCnt ? pCnt->FindTabFrame() : nullptr;
757  if ( !pTable )
758  pTable = pStTab;
759 
760  if ( pStTab &&
761  !pStTab->GetUpper()->IsInTab() &&
762  !pTable->GetUpper()->IsInTab() )
763  {
764  const SwFrame *pCell = pStart->GetUpper();
765  while ( pCell && !pCell->IsCellFrame() )
766  pCell = pCell->GetUpper();
767  OSL_ENSURE( pCell, "could not find the cell" );
768  nX = aRectFnSet.XInc(aRectFnSet.GetLeft(pCell->getFrameArea()),
769  aRectFnSet.GetWidth(pCell->getFrameArea()) / 2);
770 
771  //The flow leads from one table to the next. The X-value needs to be
772  //corrected based on the middle of the starting cell by the amount
773  //of the offset of the tables.
774  if ( pStTab != pTable )
775  {
776  nX += aRectFnSet.GetLeft(pTable->getFrameArea()) -
777  aRectFnSet.GetLeft(pStTab->getFrameArea());
778  }
779  }
780 
781  // Restrict nX to the left and right borders of pTab:
782  // (is this really necessary?)
783  if (pTable && !pTable->GetUpper()->IsInTab())
784  {
785  const bool bRTL = pTable->IsRightToLeft();
786  const tools::Long nPrtLeft = bRTL ?
787  aRectFnSet.GetPrtRight(*pTable) :
788  aRectFnSet.GetPrtLeft(*pTable);
789  if (bRTL != (aRectFnSet.XDiff(nPrtLeft, nX) > 0))
790  nX = nPrtLeft;
791  else
792  {
793  const tools::Long nPrtRight = bRTL ?
794  aRectFnSet.GetPrtLeft(*pTable) :
795  aRectFnSet.GetPrtRight(*pTable);
796  if (bRTL != (aRectFnSet.XDiff(nX, nPrtRight) > 0))
797  nX = nPrtRight;
798  }
799  }
800  }
801 
802  do
803  {
804  //If I'm in the DocumentBody, I want to stay there.
805  if ( pStart->IsInDocBody() )
806  {
807  while ( pCnt && (!pCnt->IsInDocBody() ||
808  (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
809  {
810  pCnt = (*fnNxtPrv)( pCnt );
811  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
812  }
813  }
814 
815  //If I'm in the FootNoteArea, I try to reach the next FootNoteArea in
816  //case of necessity.
817  else if ( pStart->IsInFootnote() )
818  {
819  while ( pCnt && (!pCnt->IsInFootnote() ||
820  (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow())))
821  {
822  pCnt = (*fnNxtPrv)( pCnt );
823  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
824  }
825  }
826 
827  //In Flys we can go ahead blindly as long as we find a Content.
828  else if ( pStart->IsInFly() )
829  {
830  if ( pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow() )
831  {
832  pCnt = (*fnNxtPrv)( pCnt );
833  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
834  }
835  }
836 
837  //Otherwise I'll just refuse to leave to current area.
838  else if ( pCnt )
839  {
840  const SwFrame *pUp = pStart->GetUpper();
841  while (pUp && pUp->GetUpper() && !(pUp->GetType() & FRM_HEADFOOT))
842  pUp = pUp->GetUpper();
843  bool bSame = false;
844  const SwFrame *pCntUp = pCnt->GetUpper();
845  while ( pCntUp && !bSame )
846  {
847  if ( pUp == pCntUp )
848  bSame = true;
849  else
850  pCntUp = pCntUp->GetUpper();
851  }
852  if ( !bSame )
853  pCnt = nullptr;
854  else if (pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()) // i73332
855  {
856  pCnt = (*fnNxtPrv)( pCnt );
857  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
858  }
859  }
860 
861  if ( bTab )
862  {
863  if ( !pCnt )
864  bEnd = true;
865  else
866  {
867  const SwTabFrame *pTab = pCnt->FindTabFrame();
868  if( !pTab )
869  bEnd = true;
870  else
871  {
872  if ( pTab != pTable )
873  {
874  //The flow leads from one table to the next. The X-value
875  //needs to be corrected by the amount of the offset of
876  //the tables
877  if ( pTable &&
878  !pTab->GetUpper()->IsInTab() &&
879  !pTable->GetUpper()->IsInTab() )
880  nX += pTab->getFrameArea().Left() - pTable->getFrameArea().Left();
881  pTable = pTab;
882  }
883  const SwLayoutFrame *pCell = pCnt->GetUpper();
884  while ( pCell && !pCell->IsCellFrame() )
885  pCell = pCell->GetUpper();
886 
887  Point aInsideCell;
888  Point aInsideCnt;
889  if ( pCell )
890  {
891  tools::Long nTmpTop = aRectFnSet.GetTop(pCell->getFrameArea());
892  if ( aRectFnSet.IsVert() )
893  {
894  if ( nTmpTop )
895  nTmpTop = aRectFnSet.XInc(nTmpTop, -1);
896 
897  aInsideCell = Point( nTmpTop, nX );
898  }
899  else
900  aInsideCell = Point( nX, nTmpTop );
901  }
902 
903  tools::Long nTmpTop = aRectFnSet.GetTop(pCnt->getFrameArea());
904  if ( aRectFnSet.IsVert() )
905  {
906  if ( nTmpTop )
907  nTmpTop = aRectFnSet.XInc(nTmpTop, -1);
908 
909  aInsideCnt = Point( nTmpTop, nX );
910  }
911  else
912  aInsideCnt = Point( nX, nTmpTop );
913 
914  if ( pCell && pCell->getFrameArea().IsInside( aInsideCell ) )
915  {
916  bEnd = true;
917  //Get the right Content out of the cell.
918  if ( !pCnt->getFrameArea().IsInside( aInsideCnt ) )
919  {
920  pCnt = pCell->ContainsContent();
921  if ( fnNxtPrv == lcl_GetPrvCnt )
922  while ( pCell->IsAnLower(pCnt->GetNextContentFrame()) )
923  pCnt = pCnt->GetNextContentFrame();
924  }
925  }
926  else if ( pCnt->getFrameArea().IsInside( aInsideCnt ) )
927  bEnd = true;
928  }
929  }
930  if ( !bEnd )
931  {
932  pCnt = (*fnNxtPrv)( pCnt );
933  pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel );
934  }
935  }
936 
937  } while ( !bEnd ||
938  (pCnt && pCnt->IsTextFrame() && static_cast<const SwTextFrame*>(pCnt)->IsHiddenNow()));
939 
940  if (pCnt == nullptr)
941  {
942  return false;
943  }
944  if (pCnt->IsTextFrame())
945  {
946  SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pCnt));
947  *pPam->GetPoint() = pFrame->MapViewToModelPos(TextFrameIndex(
948  fnNxtPrv == lcl_GetPrvCnt
949  ? pFrame->GetText().getLength()
950  : 0));
951  }
952  else
953  { // set the Point on the Content-Node
954  assert(pCnt->IsNoTextFrame());
955  SwContentNode *const pCNd = const_cast<SwContentNode*>(static_cast<SwNoTextFrame const*>(pCnt)->GetNode());
956  pPam->GetPoint()->nNode = *pCNd;
957  if ( fnNxtPrv == lcl_GetPrvCnt )
958  pCNd->MakeEndIndex( &pPam->GetPoint()->nContent );
959  else
960  pCNd->MakeStartIndex( &pPam->GetPoint()->nContent );
961  }
962  return true;
963 }
964 
965 bool SwContentFrame::UnitUp( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
966 {
967  return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
968 }
969 
970 bool SwContentFrame::UnitDown( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
971 {
972  return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
973 }
974 
980 sal_uInt16 SwRootFrame::GetCurrPage( const SwPaM *pActualCursor ) const
981 {
982  OSL_ENSURE( pActualCursor, "got no page cursor" );
983  SwFrame const*const pActFrame = pActualCursor->GetPoint()->nNode.GetNode().
985  pActualCursor->GetPoint());
986  return pActFrame->FindPageFrame()->GetPhyPageNum();
987 }
988 
996 sal_uInt16 SwRootFrame::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
997 {
998  vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr;
999  OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "No page available." );
1000 
1001  SwPageFrame *pPage = static_cast<SwPageFrame*>(Lower());
1002  bool bEnd =false;
1003  while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
1004  { if ( pPage->GetNext() )
1005  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1006  else
1007  { //Search the first ContentFrame and format until a new page is started
1008  //or until the ContentFrame are all done.
1009  const SwContentFrame *pContent = pPage->ContainsContent();
1010  while ( pContent && pPage->IsAnLower( pContent ) )
1011  {
1012  pContent->Calc(pRenderContext);
1013  pContent = pContent->GetNextContentFrame();
1014  }
1015  //Either this is a new page or we found the last page.
1016  if ( pPage->GetNext() )
1017  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
1018  else
1019  bEnd = true;
1020  }
1021  }
1022  //pPage now points to the 'requested' page. Now we have to create the PaM
1023  //on the beginning of the first ContentFrame in the body-text.
1024  //If this is a footnote-page, the PaM will be set in the first footnote.
1025  const SwContentFrame *pContent = pPage->ContainsContent();
1026  if ( pPage->IsFootnotePage() )
1027  while ( pContent && !pContent->IsInFootnote() )
1028  pContent = pContent->GetNextContentFrame();
1029  else
1030  while ( pContent && !pContent->IsInDocBody() )
1031  pContent = pContent->GetNextContentFrame();
1032  if ( pContent )
1033  {
1034  assert(pContent->IsTextFrame());
1035  SwTextFrame const*const pFrame(static_cast<const SwTextFrame*>(pContent));
1036  *pToSet->GetPoint() = pFrame->MapViewToModelPos(pFrame->GetOffset());
1037 
1038  SwShellCursor* pSCursor = dynamic_cast<SwShellCursor*>(pToSet);
1039  if( pSCursor )
1040  {
1041  Point &rPt = pSCursor->GetPtPos();
1042  rPt = pContent->getFrameArea().Pos();
1043  rPt += pContent->getFramePrintArea().Pos();
1044  }
1045  return pPage->GetPhyPageNum();
1046  }
1047  return 0;
1048 }
1049 
1051 {
1052  return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindFirstBodyContent();
1053 }
1054 
1056 {
1057  return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindLastBodyContent();
1058 }
1059 
1061 {
1062  SwLayoutFrame *pNext =
1063  (pFrame->GetNext() && pFrame->GetNext()->IsLayoutFrame()) ?
1064  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFrame->GetNext())) : nullptr;
1065  // #i39402# in case of an empty page
1066  if(pNext && !pNext->ContainsContent())
1067  pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrame()) ?
1068  static_cast<SwLayoutFrame*>(pNext->GetNext()) : nullptr;
1069  return pNext;
1070 }
1071 
1073 {
1074  return const_cast<SwLayoutFrame*>(pFrame);
1075 }
1076 
1078 {
1079  SwLayoutFrame *pPrev =
1080  (pFrame->GetPrev() && pFrame->GetPrev()->IsLayoutFrame()) ?
1081  const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFrame->GetPrev())) : nullptr;
1082  // #i39402# in case of an empty page
1083  if(pPrev && !pPrev->ContainsContent())
1084  pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrame()) ?
1085  static_cast<SwLayoutFrame*>(pPrev->GetPrev()) : nullptr;
1086  return pPrev;
1087 }
1088 
1093 bool GetFrameInPage( const SwContentFrame *pCnt, SwWhichPage fnWhichPage,
1094  SwPosPage fnPosPage, SwPaM *pPam )
1095 {
1096  //First find the requested page, at first the current, then the one which
1097  //was requests through fnWichPage.
1098  const SwLayoutFrame *pLayoutFrame = pCnt->FindPageFrame();
1099  if ( !pLayoutFrame || (nullptr == (pLayoutFrame = (*fnWhichPage)(pLayoutFrame))) )
1100  return false;
1101 
1102  //Now the desired ContentFrame below the page
1103  pCnt = (*fnPosPage)(pLayoutFrame);
1104  if( nullptr == pCnt )
1105  return false;
1106  else
1107  {
1108  // repeated headlines in tables
1109  if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
1110  {
1111  const SwTabFrame* pTab = pCnt->FindTabFrame();
1112  if ( pTab->IsFollow() )
1113  {
1114  if ( pTab->IsInHeadline( *pCnt ) )
1115  {
1116  SwLayoutFrame* pRow = pTab->GetFirstNonHeadlineRow();
1117  if ( pRow )
1118  {
1119  // We are in the first line of a follow table
1120  // with repeated headings.
1121  // To actually make a "real" move we take the first content
1122  // of the next row
1123  pCnt = pRow->ContainsContent();
1124  if ( ! pCnt )
1125  return false;
1126  }
1127  }
1128  }
1129  }
1130 
1131  assert(pCnt->IsTextFrame());
1132  SwTextFrame const*const pFrame(static_cast<const SwTextFrame*>(pCnt));
1133  TextFrameIndex const nIdx((fnPosPage == GetFirstSub)
1134  ? pFrame->GetOffset()
1135  : (pFrame->GetFollow())
1136  ? pFrame->GetFollow()->GetOffset() - TextFrameIndex(1)
1137  : TextFrameIndex(pFrame->GetText().getLength()));
1138  *pPam->GetPoint() = pFrame->MapViewToModelPos(nIdx);
1139  return true;
1140  }
1141 }
1142 
1143 static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2)
1144 {
1145  //Calculate the distance between the two points.
1146  //'delta' X^2 + 'delta'Y^2 = 'distance'^2
1147  sal_uInt64 dX = std::max( rPt1.X(), rPt2.X() ) -
1148  std::min( rPt1.X(), rPt2.X() ),
1149  dY = std::max( rPt1.Y(), rPt2.Y() ) -
1150  std::min( rPt1.Y(), rPt2.Y() );
1151  return (dX * dX) + (dY * dY);
1152 }
1153 
1160 static const SwLayoutFrame* lcl_Inside( const SwContentFrame *pCnt, Point const & rPt )
1161 {
1162  const SwLayoutFrame* pUp = pCnt->GetUpper();
1163  while( pUp )
1164  {
1165  if( pUp->IsPageBodyFrame() || pUp->IsFooterFrame() || pUp->IsHeaderFrame() )
1166  {
1167  if( rPt.Y() >= pUp->getFrameArea().Top() && rPt.Y() <= pUp->getFrameArea().Bottom() )
1168  return pUp;
1169  return nullptr;
1170  }
1171  if( pUp->IsFootnoteContFrame() )
1172  return pUp->getFrameArea().IsInside( rPt ) ? pUp : nullptr;
1173  pUp = pUp->GetUpper();
1174  }
1175  return nullptr;
1176 }
1177 
1186  const bool bDontLeave,
1187  const bool bBodyOnly,
1188  SwCursorMoveState *pCMS,
1189  const bool bDefaultExpand ) const
1190 {
1191  //Determine the first ContentFrame.
1192  const SwLayoutFrame *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
1193  static_cast<const SwLayoutFrame*>(GetPrev()) : this;
1194  const SwContentFrame *pContent = pStart->ContainsContent();
1195 
1196  if ( !pContent && (GetPrev() && !bDontLeave) )
1197  pContent = ContainsContent();
1198 
1199  if ( bBodyOnly && pContent && !pContent->IsInDocBody() )
1200  while ( pContent && !pContent->IsInDocBody() )
1201  pContent = pContent->GetNextContentFrame();
1202 
1203  const SwContentFrame *pActual= pContent;
1204  const SwLayoutFrame *pInside = nullptr;
1205  sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
1206  Point aPoint = rPoint;
1207  sal_uInt64 nDistance = SAL_MAX_UINT64;
1208 
1209  while ( true ) //A loop to be sure we always find one.
1210  {
1211  while ( pContent &&
1212  ((!bDontLeave || IsAnLower( pContent )) &&
1213  (pContent->GetPhyPageNum() <= nMaxPage)) )
1214  {
1215  if ( pContent->getFrameArea().Width() &&
1216  ( !bBodyOnly || pContent->IsInDocBody() ) )
1217  {
1218  //If the Content lies in a protected area (cell, Footnote, section),
1219  //we search the next Content which is not protected.
1220  const SwContentFrame *pComp = pContent;
1221  pContent = ::lcl_MissProtectedFrames( pContent, lcl_GetNxtCnt, false,
1222  pCMS && pCMS->m_bSetInReadOnly, false );
1223  if ( pComp != pContent )
1224  continue;
1225 
1226  if ( !pContent->IsTextFrame() || !static_cast<const SwTextFrame*>(pContent)->IsHiddenNow() )
1227  {
1228  SwRect aContentFrame( pContent->UnionFrame() );
1229  if ( aContentFrame.IsInside( rPoint ) )
1230  {
1231  pActual = pContent;
1232  aPoint = rPoint;
1233  break;
1234  }
1235  //The distance from rPoint to the nearest Point of pContent
1236  //will now be calculated.
1237  Point aContentPoint( rPoint );
1238 
1239  //First set the vertical position
1240  if ( aContentFrame.Top() > aContentPoint.Y() )
1241  aContentPoint.setY( aContentFrame.Top() );
1242  else if ( aContentFrame.Bottom() < aContentPoint.Y() )
1243  aContentPoint.setY( aContentFrame.Bottom() );
1244 
1245  //Now the horizontal position
1246  if ( aContentFrame.Left() > aContentPoint.X() )
1247  aContentPoint.setX( aContentFrame.Left() );
1248  else if ( aContentFrame.Right() < aContentPoint.X() )
1249  aContentPoint.setX( aContentFrame.Right() );
1250 
1251  // pInside is a page area in which the point lies. As soon
1252  // as pInside != 0 only frames are accepted which are
1253  // placed inside.
1254  if( !pInside || ( pInside->IsAnLower( pContent ) &&
1255  ( !pContent->IsInFootnote() || pInside->IsFootnoteContFrame() ) ) )
1256  {
1257  const sal_uInt64 nDiff = ::CalcDiff(aContentPoint, rPoint);
1258  bool bBetter = nDiff < nDistance; // This one is nearer
1259  if( !pInside )
1260  {
1261  pInside = lcl_Inside( pContent, rPoint );
1262  if( pInside ) // In the "right" page area
1263  bBetter = true;
1264  }
1265  if( bBetter )
1266  {
1267  aPoint = aContentPoint;
1268  nDistance = nDiff;
1269  pActual = pContent;
1270  }
1271  }
1272  }
1273  }
1274  pContent = pContent->GetNextContentFrame();
1275  if ( bBodyOnly )
1276  while ( pContent && !pContent->IsInDocBody() )
1277  pContent = pContent->GetNextContentFrame();
1278  }
1279  if ( !pActual )
1280  { //If we not yet found one we have to expand the searched
1281  //area, sometime we will find one!
1282  //MA 1997-01-09: Opt for many empty pages - if we only search inside
1283  //the body, we can expand the searched area sufficiently in one step.
1284  if ( bBodyOnly )
1285  {
1286  while ( !pContent && pStart->GetPrev() )
1287  {
1288  ++nMaxPage;
1289  if( !pStart->GetPrev()->IsLayoutFrame() )
1290  return nullptr;
1291  pStart = static_cast<const SwLayoutFrame*>(pStart->GetPrev());
1292  pContent = pStart->IsInDocBody()
1293  ? pStart->ContainsContent()
1294  : pStart->FindPageFrame()->FindFirstBodyContent();
1295  }
1296  if ( !pContent ) // Somewhere down the road we have to start with one!
1297  {
1298  pContent = pStart->FindPageFrame()->GetUpper()->ContainsContent();
1299  while ( pContent && !pContent->IsInDocBody() )
1300  pContent = pContent->GetNextContentFrame();
1301  if ( !pContent )
1302  return nullptr; // There is no document content yet!
1303  }
1304  }
1305  else
1306  {
1307  ++nMaxPage;
1308  if ( pStart->GetPrev() )
1309  {
1310  if( !pStart->GetPrev()->IsLayoutFrame() )
1311  return nullptr;
1312  pStart = static_cast<const SwLayoutFrame*>(pStart->GetPrev());
1313  pContent = pStart->ContainsContent();
1314  }
1315  else // Somewhere down the road we have to start with one!
1316  pContent = pStart->FindPageFrame()->GetUpper()->ContainsContent();
1317  }
1318  pActual = pContent;
1319  }
1320  else
1321  break;
1322  }
1323 
1324  OSL_ENSURE( pActual, "no Content found." );
1325  OSL_ENSURE( !bBodyOnly || pActual->IsInDocBody(), "Content not in Body." );
1326 
1327  //Special case for selecting tables not in repeated TableHeadlines.
1328  if ( pActual->IsInTab() && pCMS && pCMS->m_eState == CursorMoveState::TableSel )
1329  {
1330  const SwTabFrame *pTab = pActual->FindTabFrame();
1331  if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
1332  {
1333  pCMS->m_bStop = true;
1334  return nullptr;
1335  }
1336  }
1337 
1338  //A small correction at the first/last
1339  Size aActualSize( pActual->getFramePrintArea().SSize() );
1340  if ( aActualSize.Height() > pActual->GetUpper()->getFramePrintArea().Height() )
1341  aActualSize.setHeight( pActual->GetUpper()->getFramePrintArea().Height() );
1342 
1343  SwRectFnSet aRectFnSet(pActual);
1344  if ( !pActual->GetPrev() &&
1345  aRectFnSet.YDiff( aRectFnSet.GetPrtTop(*pActual),
1346  aRectFnSet.IsVert() ? rPoint.X() : rPoint.Y() ) > 0 )
1347  {
1348  aPoint.setY( pActual->getFrameArea().Top() + pActual->getFramePrintArea().Top() );
1349  aPoint.setX( pActual->getFrameArea().Left() +
1350  ( pActual->IsRightToLeft() || aRectFnSet.IsVert() ?
1351  pActual->getFramePrintArea().Right() :
1352  pActual->getFramePrintArea().Left() ) );
1353  }
1354  else if ( !pActual->GetNext() &&
1355  aRectFnSet.YDiff( aRectFnSet.GetPrtBottom(*pActual),
1356  aRectFnSet.IsVert() ? rPoint.X() : rPoint.Y() ) < 0 )
1357  {
1358  aPoint.setY( pActual->getFrameArea().Top() + pActual->getFramePrintArea().Bottom() );
1359  aPoint.setX( pActual->getFrameArea().Left() +
1360  ( pActual->IsRightToLeft() || aRectFnSet.IsVert() ?
1361  pActual->getFramePrintArea().Left() :
1362  pActual->getFramePrintArea().Right() ) );
1363  }
1364 
1365  //Bring the Point into the PrtArea
1366  const SwRect aRect( pActual->getFrameArea().Pos() + pActual->getFramePrintArea().Pos(),
1367  aActualSize );
1368  if ( aPoint.Y() < aRect.Top() )
1369  aPoint.setY( aRect.Top() );
1370  else if ( aPoint.Y() > aRect.Bottom() )
1371  aPoint.setY( aRect.Bottom() );
1372  if ( aPoint.X() < aRect.Left() )
1373  aPoint.setX( aRect.Left() );
1374  else if ( aPoint.X() > aRect.Right() )
1375  aPoint.setX( aRect.Right() );
1376  rPoint = aPoint;
1377  return pActual;
1378 }
1379 
1381 void SwPageFrame::GetContentPosition( const Point &rPt, SwPosition &rPos ) const
1382 {
1383  //Determine the first ContentFrame.
1385  if ( pContent )
1386  {
1387  //Look back one more (if possible).
1388  const SwContentFrame *pTmp = pContent->GetPrevContentFrame();
1389  while ( pTmp && !pTmp->IsInDocBody() )
1390  pTmp = pTmp->GetPrevContentFrame();
1391  if ( pTmp )
1392  pContent = pTmp;
1393  }
1394  else
1395  pContent = GetUpper()->ContainsContent();
1396 
1397  const SwContentFrame *pAct = pContent;
1398  Point aAct = rPt;
1399  sal_uInt64 nDist = SAL_MAX_UINT64;
1400 
1401  while ( pContent )
1402  {
1403  SwRect aContentFrame( pContent->UnionFrame() );
1404  if ( aContentFrame.IsInside( rPt ) )
1405  {
1406  //This is the nearest one.
1407  pAct = pContent;
1408  break;
1409  }
1410 
1411  //Calculate the distance from rPt to the nearest point of pContent.
1412  Point aPoint( rPt );
1413 
1414  //Calculate the vertical position first
1415  if ( aContentFrame.Top() > rPt.Y() )
1416  aPoint.setY( aContentFrame.Top() );
1417  else if ( aContentFrame.Bottom() < rPt.Y() )
1418  aPoint.setY( aContentFrame.Bottom() );
1419 
1420  //And now the horizontal position
1421  if ( aContentFrame.Left() > rPt.X() )
1422  aPoint.setX( aContentFrame.Left() );
1423  else if ( aContentFrame.Right() < rPt.X() )
1424  aPoint.setX( aContentFrame.Right() );
1425 
1426  const sal_uInt64 nDiff = ::CalcDiff( aPoint, rPt );
1427  if ( nDiff < nDist )
1428  {
1429  aAct = aPoint;
1430  nDist = nDiff;
1431  pAct = pContent;
1432  }
1433  else if ( aContentFrame.Top() > getFrameArea().Bottom() )
1434  //In terms of fields, it's not possible to be closer any more!
1435  break;
1436 
1437  pContent = pContent->GetNextContentFrame();
1438  while ( pContent && !pContent->IsInDocBody() )
1439  pContent = pContent->GetNextContentFrame();
1440  }
1441 
1442  //Bring the point into the PrtArea.
1443  const SwRect aRect( pAct->getFrameArea().Pos() + pAct->getFramePrintArea().Pos(), pAct->getFramePrintArea().SSize() );
1444  if ( aAct.Y() < aRect.Top() )
1445  aAct.setY( aRect.Top() );
1446  else if ( aAct.Y() > aRect.Bottom() )
1447  aAct.setY( aRect.Bottom() );
1448  if ( aAct.X() < aRect.Left() )
1449  aAct.setX( aRect.Left() );
1450  else if ( aAct.X() > aRect.Right() )
1451  aAct.setX( aRect.Right() );
1452 
1453  if (!pAct->isFrameAreaDefinitionValid() ||
1454  (pAct->IsTextFrame() && !static_cast<SwTextFrame const*>(pAct)->HasPara()))
1455  {
1456  // ContentFrame not formatted -> always on node-beginning
1457  // tdf#100635 also if the SwTextFrame would require reformatting,
1458  // which is unwanted in case this is called from text formatting code
1459  rPos = static_cast<SwTextFrame const*>(pAct)->MapViewToModelPos(TextFrameIndex(0));
1460  }
1461  else
1462  {
1464  pAct->GetModelPositionForViewPoint( &rPos, aAct, &aTmpState );
1465  }
1466 }
1467 
1474 Point SwRootFrame::GetNextPrevContentPos( const Point& rPoint, bool bNext ) const
1475 {
1476  vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr;
1477  // #123110# - disable creation of an action by a callback
1478  // event during processing of this method. Needed because formatting is
1479  // triggered by this method.
1480  DisableCallbackAction aDisableCallbackAction(const_cast<SwRootFrame&>(*this));
1481  //Search the first ContentFrame and his successor in the body area.
1482  //To be efficient (and not formatting too much) we'll start at the correct
1483  //page.
1484  const SwLayoutFrame *pPage = static_cast<const SwLayoutFrame*>(Lower());
1485  if( pPage )
1486  while( pPage->GetNext() && pPage->getFrameArea().Bottom() < rPoint.Y() )
1487  pPage = static_cast<const SwLayoutFrame*>(pPage->GetNext());
1488 
1489  const SwContentFrame *pCnt = pPage ? pPage->ContainsContent() : ContainsContent();
1490  while ( pCnt && !pCnt->IsInDocBody() )
1491  pCnt = pCnt->GetNextContentFrame();
1492 
1493  if ( !pCnt )
1494  return Point( 0, 0 );
1495 
1496  pCnt->Calc(pRenderContext);
1497  if( !bNext )
1498  {
1499  // As long as the point lies before the first ContentFrame and there are
1500  // still precedent pages I'll go to the next page.
1501  while ( rPoint.Y() < pCnt->getFrameArea().Top() && pPage->GetPrev() )
1502  {
1503  pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev());
1504  pCnt = pPage->ContainsContent();
1505  while ( !pCnt )
1506  {
1507  pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev());
1508  if ( pPage )
1509  pCnt = pPage->ContainsContent();
1510  else
1511  return ContainsContent()->UnionFrame().Pos();
1512  }
1513  pCnt->Calc(pRenderContext);
1514  }
1515  }
1516 
1517  //Does the point lie above the first ContentFrame?
1518  if ( rPoint.Y() < pCnt->getFrameArea().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
1519  return pCnt->UnionFrame().Pos();
1520 
1521  Point aRet(0, 0);
1522  do
1523  {
1524  //Does the point lie in the current ContentFrame?
1525  SwRect aContentFrame( pCnt->UnionFrame() );
1526  if ( aContentFrame.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
1527  {
1528  aRet = rPoint;
1529  break;
1530  }
1531 
1532  //Is the current one the last ContentFrame?
1533  //If the next ContentFrame lies behind the point, then the current on is the
1534  //one we searched.
1535  const SwContentFrame *pNxt = pCnt->GetNextContentFrame();
1536  while ( pNxt && !pNxt->IsInDocBody() )
1537  pNxt = pNxt->GetNextContentFrame();
1538 
1539  //Does the point lie behind the last ContentFrame?
1540  if ( !pNxt )
1541  {
1542  aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() );
1543  break;
1544  }
1545 
1546  //If the next ContentFrame lies behind the point then it is the one we
1547  //searched.
1548  const SwTabFrame* pTFrame;
1549  pNxt->Calc(pRenderContext);
1550  if( pNxt->getFrameArea().Top() > rPoint.Y() &&
1551  !lcl_IsInRepeatedHeadline( pCnt, &pTFrame ) &&
1552  ( !pTFrame || pNxt->getFrameArea().Left() > rPoint.X() ))
1553  {
1554  if (bNext)
1555  aRet = pNxt->getFrameArea().Pos();
1556  else
1557  aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() );
1558  break;
1559  }
1560  pCnt = pNxt;
1561  }
1562  while (pCnt);
1563  return aRet;
1564 }
1565 
1573 Point SwRootFrame::GetPagePos( sal_uInt16 nPageNum ) const
1574 {
1575  OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "No page available." );
1576 
1577  const SwPageFrame *pPage = static_cast<const SwPageFrame*>(Lower());
1578  while ( true )
1579  {
1580  if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
1581  break;
1582  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1583  }
1584  return pPage->getFrameArea().Pos();
1585 }
1586 
1591 SwPageFrame* SwRootFrame::GetPageByPageNum( sal_uInt16 _nPageNum ) const
1592 {
1593  const SwPageFrame* pPageFrame = static_cast<const SwPageFrame*>( Lower() );
1594  while ( pPageFrame && pPageFrame->GetPhyPageNum() < _nPageNum )
1595  {
1596  pPageFrame = static_cast<const SwPageFrame*>( pPageFrame->GetNext() );
1597  }
1598 
1599  if ( pPageFrame && pPageFrame->GetPhyPageNum() == _nPageNum )
1600  {
1601  return const_cast<SwPageFrame*>( pPageFrame );
1602  }
1603  else
1604  {
1605  return nullptr;
1606  }
1607 }
1608 
1612 bool SwRootFrame::IsDummyPage( sal_uInt16 nPageNum ) const
1613 {
1614  if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
1615  return true;
1616 
1617  const SwPageFrame *pPage = static_cast<const SwPageFrame*>(Lower());
1618  while( pPage && nPageNum < pPage->GetPhyPageNum() )
1619  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1620  return !pPage || pPage->IsEmptyPage();
1621 }
1622 
1628 {
1629  if (IsTextFrame())
1630  {
1631  const SwDoc *pDoc = &static_cast<const SwTextFrame*>(this)->GetDoc();
1632  bool isFormProtected=pDoc->GetDocumentSettingManager().get(DocumentSettingId::PROTECT_FORM );
1633  if (isFormProtected)
1634  {
1635  return false; // TODO a hack for now, well deal with it later, I we return true here we have a "double" locking
1636  }
1637  }
1638  //The Frame can be protected in borders, cells or sections.
1639  //Also goes up FlyFrames recursive and from footnote to anchor.
1640  const SwFrame *pFrame = this;
1641  do
1642  {
1643  if (pFrame->IsTextFrame())
1644  { // sw_redlinehide: redlines can't overlap section nodes, so any node will do
1645  if (static_cast<SwTextFrame const*>(pFrame)->GetTextNodeFirst()->IsInProtectSect())
1646  {
1647  return true;
1648  }
1649  }
1650  else if ( pFrame->IsContentFrame() )
1651  {
1652  assert(pFrame->IsNoTextFrame());
1653  if (static_cast<const SwNoTextFrame*>(pFrame)->GetNode() &&
1654  static_cast<const SwNoTextFrame*>(pFrame)->GetNode()->IsInProtectSect())
1655  {
1656  return true;
1657  }
1658  }
1659  else
1660  {
1661  if ( static_cast<const SwLayoutFrame*>(pFrame)->GetFormat() &&
1662  static_cast<const SwLayoutFrame*>(pFrame)->GetFormat()->
1663  GetProtect().IsContentProtected() )
1664  return true;
1665  if ( pFrame->IsCoveredCell() )
1666  return true;
1667  }
1668  if ( pFrame->IsFlyFrame() )
1669  {
1670  //In a chain the protection of the content can be specified by the
1671  //master of the chain.
1672  if ( static_cast<const SwFlyFrame*>(pFrame)->GetPrevLink() )
1673  {
1674  const SwFlyFrame *pMaster = static_cast<const SwFlyFrame*>(pFrame);
1675  do
1676  { pMaster = pMaster->GetPrevLink();
1677  } while ( pMaster->GetPrevLink() );
1678  if ( pMaster->IsProtected() )
1679  return true;
1680  }
1681  pFrame = static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame();
1682  }
1683  else if ( pFrame->IsFootnoteFrame() )
1684  pFrame = static_cast<const SwFootnoteFrame*>(pFrame)->GetRef();
1685  else
1686  pFrame = pFrame->GetUpper();
1687 
1688  } while ( pFrame );
1689 
1690  return false;
1691 }
1692 
1694 sal_uInt16 SwFrame::GetPhyPageNum() const
1695 {
1696  const SwPageFrame *pPage = FindPageFrame();
1697  return pPage ? pPage->GetPhyPageNum() : 0;
1698 }
1699 
1714 {
1715  const SwPageFrame *pPage = FindPageFrame();
1716  if ( !pPage || !pPage->GetUpper() )
1717  return true;
1718 
1719  const SwFrame *pFlow = pPage->FindFirstBodyContent();
1720  const SwPageDesc *pDesc = nullptr;
1721  ::std::optional<sal_uInt16> oPgNum;
1722  if ( pFlow )
1723  {
1724  if ( pFlow->IsInTab() )
1725  pFlow = pFlow->FindTabFrame();
1726  const SwFlowFrame *pTmp = SwFlowFrame::CastFlowFrame( pFlow );
1727  if ( !pTmp->IsFollow() )
1728  {
1729  const SwFormatPageDesc& rPgDesc = pFlow->GetPageDescItem();
1730  pDesc = rPgDesc.GetPageDesc();
1731  oPgNum = rPgDesc.GetNumOffset();
1732  }
1733  }
1734  if ( !pDesc )
1735  {
1736  SwPageFrame *pPrv = const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pPage->GetPrev()));
1737  if( pPrv && pPrv->IsEmptyPage() )
1738  pPrv = static_cast<SwPageFrame*>(pPrv->GetPrev());
1739  if( pPrv )
1740  pDesc = pPrv->GetPageDesc()->GetFollow();
1741  else
1742  {
1743  const SwDoc* pDoc = pPage->GetFormat()->GetDoc();
1744  pDesc = &pDoc->GetPageDesc( 0 );
1745  }
1746  }
1747  OSL_ENSURE( pDesc, "No pagedescriptor" );
1748  bool isRightPage;
1749  if( oPgNum )
1750  isRightPage = sw::IsRightPageByNumber(*mpRoot, *oPgNum);
1751  else
1752  {
1753  isRightPage = pPage->OnRightPage();
1754  if( pPage->GetPrev() && static_cast<const SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() )
1755  isRightPage = !isRightPage;
1756  }
1757  if( !pPage->IsEmptyPage() )
1758  {
1759  if( !pDesc->GetRightFormat() )
1760  isRightPage = false;
1761  else if( !pDesc->GetLeftFormat() )
1762  isRightPage = true;
1763  }
1764  return isRightPage;
1765 }
1766 
1768 {
1769  bool bRet = false;
1770  const SwPageFrame *pPage = FindPageFrame();
1771 
1772  if (pPage)
1773  {
1774  const SwPageFrame* pPrevFrame = dynamic_cast<const SwPageFrame*>(pPage->GetPrev());
1775  if (pPrevFrame)
1776  {
1777  // first page of layout may be empty page, but only if it starts with "Left Page" style
1778  const SwPageDesc* pDesc = pPage->GetPageDesc();
1779  bRet = pPrevFrame->GetPageDesc() != pDesc;
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 sw::BroadcastingModify *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  {
1845  ::std::optional<sal_uInt16> oNumOffset = pFrame->GetPageDescItem().GetNumOffset();
1846  if (oNumOffset)
1847  {
1848  return nPhyPage - pFrame->GetPhyPageNum() + *oNumOffset;
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 
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  tools::Long nRightAbs = aRectFnSet.GetRight(pSt2Pos->aPortion);
2168  nRightAbs -= aRectFnSet.GetLeft(pSt2Pos->aPortion2);
2169  tools::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  tools::Long nRightAbs = fnRectX.GetRight(pEnd2Pos->aPortion);
2238  nRightAbs = nRightAbs - fnRectX.GetLeft(pEnd2Pos->aPortion2);
2239  tools::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  tools::Long nRightAbs = aRectFnSet.GetRight(pSt2Pos->aPortion);
2311  nRightAbs -= aRectFnSet.GetLeft(pSt2Pos->aPortion2);
2312  tools::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  tools::Long nRightAbs = fnRectX.GetRight(pEnd2Pos->aPortion);
2328  nRightAbs -= fnRectX.GetLeft(pEnd2Pos->aPortion2);
2329  tools::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  tools::Long nTmpY = aTmpEnd.Y();
2380  aTmpEnd.setY( aTmpSt.Y() );
2381  aTmpSt.setY( nTmpY );
2382  }
2383  if( aTmpSt.X() > aTmpEnd.X() )
2384  {
2385  tools::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  tools::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  const SwFlyFrame* pFly = dynamic_cast<const SwFlyFrame*>(pAnchoredObj);
2572  if ( !pFly )
2573  continue;
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  && IsSelectFrameAnchoredAtPara(*anchoredAt, *pStartPos, *pEndPos))));
2584  if( inSelection )
2585  Add( aRegion, pFly->getFrameArea() );
2586  else if ( !pFly->IsAnLower( pStartFrame ) &&
2587  (rSur.GetSurround() != css::text::WrapTextMode_THROUGH &&
2588  !rSur.IsContour()) )
2589  {
2590  if ( aSortObjs.Contains( *pAnchoredObj ) )
2591  continue;
2592 
2593  bool bSub = true;
2594  const sal_uInt32 nPos = pObj->GetOrdNum();
2595  for ( size_t k = 0; bSub && k < aSortObjs.size(); ++k )
2596  {
2597  OSL_ENSURE( dynamic_cast< const SwFlyFrame *>( aSortObjs[k] ) != nullptr,
2598  "<SwRootFrame::CalcFrameRects(..)> - object in <aSortObjs> of unexpected type" );
2599  const SwFlyFrame* pTmp = static_cast<SwFlyFrame*>(aSortObjs[k]);
2600  do
2601  {
2602  if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
2603  {
2604  bSub = false;
2605  }
2606  else
2607  {
2608  pTmp = pTmp->GetAnchorFrame()->FindFlyFrame();
2609  }
2610  } while ( bSub && pTmp );
2611  }
2612  if ( bSub )
2613  Sub( aRegion, pFly->getFrameArea() );
2614  }
2615  }
2616  }
2617  if ( pPage == pEndPage )
2618  break;
2619  else
2620  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
2621  }
2622 
2623  //Because it looks better, we close the DropCaps.
2624  SwRect aDropRect;
2625  if ( pStartFrame->IsTextFrame() )
2626  {
2627  if ( static_cast<const SwTextFrame*>(pStartFrame)->GetDropRect( aDropRect ) )
2628  Sub( aRegion, aDropRect );
2629  }
2630  if ( pEndFrame != pStartFrame && pEndFrame->IsTextFrame() )
2631  {
2632  if ( static_cast<const SwTextFrame*>(pEndFrame)->GetDropRect( aDropRect ) )
2633  Sub( aRegion, aDropRect );
2634  }
2635 
2636  rCursor.assign( aRegion.begin(), aRegion.end() );
2637 }
2638 
2639 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:207
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:338
void SetTop(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1367
const sw::BroadcastingModify * GetDefinedIn() const
Query / set where attribute is anchored.
Definition: fmtpdsc.hxx:69
bool IsContour() const
Definition: fmtsrnd.hxx:53
const SwVirtFlyDrawObj * GetVirtDrawObj() const
Definition: fly.cxx:2770
Base class of the Writer layout elements.
Definition: frame.hxx:298
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:151
virtual sal_Int32 Len() const
Definition: node.cxx:1241
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the page containing the searched point.
Definition: trvlfrm.cxx:179
const ::std::optional< sal_uInt16 > & GetNumOffset() const
Definition: fmtpdsc.hxx:65
tools::Long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1361
const SdrObject * Next()
Definition: frmtool.cxx:2624
sal_uLong GetIndex() const
Definition: node.hxx:290
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
void Right(const tools::Long nRight)
Definition: swrect.hxx:200
bool IsFollow() const
Definition: flowfrm.hxx:166
virtual bool RightMargin(SwPaM *, bool bAPI=false) const override
Definition: trvlfrm.cxx:625
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2859
void SetCallbackActionEnabled(bool b)
Definition: rootfrm.hxx:385
void GetContentPosition(const Point &rPt, SwPosition &rPos) const
Same as SwLayoutFrame::GetContentPos().
Definition: trvlfrm.cxx:1381
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:110
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:817
bool IsInDocBody() const
Definition: frame.hxx:924
tools::Long GetPrtRight(const SwFrame &rFrame) const
Definition: frame.hxx:1393
static bool lcl_IsInRepeatedHeadline(const SwFrame *pFrame, const SwTabFrame **ppTFrame=nullptr)
Frame in repeated headline?
Definition: trvlfrm.cxx:647
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:573
bool IsInFly() const
Definition: frame.hxx:942
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:41
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SwRootFrame * mpRoot
Definition: frame.hxx:320
tools::Long BottomDist(const SwRect &rRect, tools::Long nPos) const
Definition: frame.hxx:1395
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:62
virtual bool get(DocumentSettingId id) const override
Return the specified document setting.
static SwContentNode * GetContentNode(SwDoc &rDoc, SwNodeIndex &rIdx, bool bNext)
Definition: fltshell.cxx:53
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:980
static bool more(const double &rfValA, const double &rfValB)
const SwTable * GetTable() const
Definition: tabfrm.hxx:144
void Left(const tools::Long nLeft)
Definition: swrect.hxx:195
SwNodeIndex nNode
Definition: pam.hxx:37
void Refresh(const SwFrame *pFrame)
Definition: frame.hxx:1340
bool IsInFootnote() const
Definition: frame.hxx:930
sal_uInt16 char char * pDesc
SwFrameType GetType() const
Definition: frame.hxx:503
SwLayoutFrame * GetPrevFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1077
long Long
const SwRect & getFramePrintArea() const
Definition: frame.hxx:179
const StyleSettings & GetStyleSettings() const
const SwPosition * GetMark() const
Definition: pam.hxx:209
Base class of all fields.
Definition: fldbas.hxx:289
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
tools::Long XInc(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1405
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:1208
Definition: doc.hxx:186
helper class to disable creation of an action by a callback event in particular, change event from a ...
Definition: rootfrm.hxx:449
bool m_bSetInReadOnly
ReadOnly areas may be entered.
Definition: crstate.hxx:148
const Point & GetSttPos() const
Definition: viscrs.hxx:146
bool m_bExactOnly
let GetModelPositionForViewPoint look for exact matches only, i.e.
Definition: crstate.hxx:145
SwNode & GetNode() const
Definition: ndindex.hxx:119
bool IsSelectFrameAnchoredAtPara(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
is a fly anchored at paragraph at rAnchorPos selected?
Definition: undobj.cxx:1632
This class is used as parameter for creation of a block cursor selection.
bool IsVert() const
Definition: frame.hxx:1348
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:195
void Pos(const Point &rNew)
Definition: swrect.hxx:169
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
bool IsCellFrame() const
Definition: frame.hxx:1207
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:186
void Top()
Definition: frmtool.cxx:2571
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
SwContentFrame * FindFirstBodyContent()
Definition: pagefrm.hxx:337
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1283
virtual const SwFormatPageDesc & GetPageDescItem() const
Definition: findfrm.cxx:660
tools::Long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1362
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:1591
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2647
SwLayoutFrame * GetThisFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1072
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
SwContact * GetUserCall(const SdrObject *pObj)
Returns the UserCall if applicable from the group object.
Definition: dcontact.cxx:171
virtual bool GetInfo(SfxPoolItem &) const override
Definition: calbck.cxx:188
bool IsFootnoteFrame() const
Definition: frame.hxx:1183
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:170
static void Sub(SwRegionRects &rRegion, const SwRect &rRect)
Definition: trvlfrm.cxx:1970
SwLayoutFrame * GetNextFrame(const SwLayoutFrame *pFrame)
Definition: trvlfrm.cxx:1060
bool m_bFillRet
only used temporary in FillMode
Definition: crstate.hxx:147
static SwCursorOszControl g_OszCtrl
Definition: trvlfrm.cxx:147
not in repeated headlines
void PrepareMake(vcl::RenderContext *pRenderContext)
Prepares the Frame for "formatting" (MakeAll()).
Definition: calcmove.cxx:246
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:191
bool IsSelectAll() const
Definition: viewsh.hxx:565
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const
Definition: unusedf.cxx:47
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:3021
tools::Long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1358
SwRect GetPaintArea() const
|* The paintarea is the area, in which the content of a frame is allowed |* to be displayed...
Definition: ssfrm.cxx:588
bool WannaRightPage() const
Decides if the page want to be a right page or not.
Definition: trvlfrm.cxx:1713
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Primary passes the call to the first page.
Definition: trvlfrm.cxx:424
bool IsFlyFrame() const
Definition: frame.hxx:1191
void SetBottom(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1368
wrapper class for the positioning of Writer fly frames and drawing objects
const SwPageFrame * GetPage() const
Definition: hints.hxx:302
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:178
SwFlyFrame * GetPrevLink() const
Definition: flyfrm.hxx:173
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
bool IsEmptyPage() const
Definition: pagefrm.hxx:144
bool IsInTab() const
Definition: frame.hxx:936
SwRect & Intersection(const SwRect &rRect)
Definition: swrect.cxx:56
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:380
void CalcFrameRects(SwShellCursor &)
Definition: trvlfrm.cxx:2007
bool IsTextFrame() const
Definition: frame.hxx:1215
virtual bool UnitUp(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:965
oslFileHandle & pOut
const SwContentFrame *(* GetNxtPrvCnt)(const SwContentFrame *)
Definition: trvlfrm.cxx:644
tools::Long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1392
void Width(tools::Long nNew)
Definition: swrect.hxx:187
bool OnRightPage() const
Definition: frame.hxx:716
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
static const SwContentFrame * lcl_GetNxtCnt(const SwContentFrame *pCnt)
Definition: trvlfrm.cxx:634
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:41
SwContentFrame * GetPrevContentFrame() const
Definition: cntfrm.hxx:106
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1092
tools::Long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1360
virtual bool UnitDown(SwPaM *, const SwTwips nOffset, bool bSetInReadOnly) const
Definition: trvlfrm.cxx:970
virtual bool LeftMargin(SwPaM *) const override
Layout dependent cursor travelling.
Definition: trvlfrm.cxx:616
SwPageFrame * GetPageByPageNum(sal_uInt16 _nPageNum) const
Get page frame by physical page number looping through the lowers, which are page frame...
Definition: trvlfrm.cxx:1591
virtual bool GetCharRect(SwRect &, const SwPosition &, SwCursorMoveState *=nullptr, bool bAllowFarAway=true) const
Definition: unusedf.cxx:72
sal_uInt16 GetVirtPageNum() const
Definition: trvlfrm.cxx:1805
tools::Long XDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1403
bool IsContentNode() const
Definition: node.hxx:631
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:284
Point GetRelPos() const
Definition: trvlfrm.cxx:1795
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:402
bool IsContentFrame() const
Definition: frame.hxx:1211
double GetLength() const
const SwSortedObjs * GetSortedObjs() const
Definition: pagefrm.hxx:119
#define SAL_MAX_UINT64
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the ContentFrame owning the PrtArea containing the point.
Definition: trvlfrm.cxx:539
tools::Long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1391
const SwRect & VisArea() const
Definition: viewsh.cxx:560
#define FRM_HEADFOOT
Definition: frame.hxx:107
uno_Any a
SwContentFrame * GetLastSub(const SwLayoutFrame *pLayout)
Definition: trvlfrm.cxx:1055
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
SwFrameType
Definition: frame.hxx:73
bool Insert(SwAnchoredObject &_rAnchoredObj)
Definition: sortedobjs.cxx:207
virtual bool IsCoveredCell() const
Definition: tabfrm.cxx:5885
const SwPageDesc & GetPageDesc(const size_t i) const
Definition: doc.hxx:880
static bool lcl_UpDown(SwPaM *pPam, const SwContentFrame *pStart, GetNxtPrvCnt fnNxtPrv, bool bInReadOnly)
Definition: trvlfrm.cxx:690
size_t size() const
Definition: sortedobjs.cxx:42
SwPageFrame * FindPageFrame()
Definition: frame.hxx:663
SwLayoutFrame *(* SwWhichPage)(const SwLayoutFrame *)
Definition: cshtyp.hxx:34
SwFrameFormat * GetLeftFormat(bool const bFirst=false)
Definition: pagedesc.cxx:361
bool IsDummyPage(sal_uInt16 nPageNum) const
Definition: trvlfrm.cxx:1612
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:130
SwContentNode * GetContentNode()
Definition: node.hxx:618
FlyAnchors.
Definition: fmtanchr.hxx:34
void SetRight(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1370
SwLayoutFrame * GetUpper()
Definition: frame.hxx:661
bool HasArea() const
Definition: swrect.hxx:288
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:659
bool isFramePrintAreaValid() const
Definition: frame.hxx:167
Marks a character position inside a document model node.
Definition: index.hxx:33
::rtl::Reference< Content > pContent
bool IsRowFrame() const
Definition: frame.hxx:1203
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:1160
tools::Long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1390
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
SwFrame * GetPrev()
Definition: frame.hxx:660
const Point & GetMkPos() const
Definition: viscrs.hxx:144
bool IsContentProtected() const
const SwRowFrame * IsInFollowFlowRow() const
Definition: findfrm.cxx:1786
void MakeSelUnions(SwSelUnions &rUnions, const SwLayoutFrame *pStart, const SwLayoutFrame *pEnd, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:1771
bool IsPDFExport() const
Definition: viewopt.hxx:403
const AllSettings & GetSettings() const
bool isFrameAreaPositionValid() const
Definition: frame.hxx:165
tools::Long YDiff(tools::Long n1, tools::Long n2) const
Definition: frame.hxx:1404
static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2)
Definition: trvlfrm.cxx:1143
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:178
SwRect UnionFrame(bool bBorder=false) const
|* The unionframe is the framearea (getFrameArea()) of a frame expanded by the |* printarea...
Definition: ssfrm.cxx:695
bool isFrameAreaSizeValid() const
Definition: frame.hxx:166
virtual const SwAnchoredObject * GetAnchoredObj(const SdrObject *_pSdrObj) const =0
A page of the document layout.
Definition: pagefrm.hxx:41
bool m_bNoScroll
No scrolling of undersized textframes.
Definition: crstate.hxx:151
bool m_b2Lines
Check 2line portions and fill p2Lines.
Definition: crstate.hxx:150
stay with the cursor inside text
bool MakeTableCursors(SwTableCursor &)
Calculates the cells included from the current selection.
Definition: trvlfrm.cxx:1859
tools::Long SwTwips
Definition: swtypes.hxx:49
SwContentFrame * GetFirstSub(const SwLayoutFrame *pLayout)
Definition: trvlfrm.cxx:1050
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:35
bool IsInProtectSect() const
Is node in a protected area?
Definition: node.cxx:414
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:245
const SwFrame * GetFrame() const
Definition: hints.hxx:304
const SwCellFrame * FirstCell() const
Calls ContainsAny first to reach the innermost cell.
Definition: findfrm.cxx:113
Point PixelToLogic(const Point &rDevicePt) const
SwFillCursorPos * m_pFill
for automatic filling with tabs etc
Definition: crstate.hxx:134
virtual bool IsReadOnlyAvailable() const
Definition: swcrsr.cxx:152
bool IsLayoutFrame() const
Definition: frame.hxx:1151
static void Add(SwRegionRects &rRegion, const SwRect &rRect)
Definition: trvlfrm.cxx:1977
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:209
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
const SwContentNode * GetNode() const
Definition: notxtfrm.hxx:67
SwFlyFrame * GetFlyFrame()
Definition: dflyobj.hxx:128
void SetWidth(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1371
SwContentFrame * FindLastBodyContent()
Searches the last ContentFrame in BodyText below the page.
Definition: findfrm.cxx:52
SwRowFrame * GetFirstNonHeadlineRow() const
Definition: tabfrm.cxx:5540
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:670
bool IsRightPageByNumber(SwRootFrame const &rLayout, sal_uInt16 nPageNum)
Definition: frmtool.cxx:2989
sal_uInt16 SetCurrPage(SwCursor *, sal_uInt16 nPageNum)
Returns a PaM which sits at the beginning of the requested page.
Definition: trvlfrm.cxx:996
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:1093
sal_uInt16 GetPhyPageNum() const
Definition: trvlfrm.cxx:1694
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Searches the ContentFrame owning the PrtArea containing the point.
Definition: trvlfrm.cxx:150
std::vector< SwSelUnion > SwSelUnions
Definition: tblsel.hxx:138
sal_Int32 GetIndex() const
Definition: index.hxx:91
bool IsInside(const Point &rPOINT) const
Definition: swrect.cxx:105
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:368
bool IsNoTextFrame() const
Definition: frame.hxx:1219
Item2Range GetItemSurrogates(sal_uInt16 nWhich) const
bool IsRightToLeft() const
Definition: frame.hxx:968
::sw::DocumentSettingManager & GetDocumentSettingManager()
Definition: doc.cxx:186
void Top(const tools::Long nTop)
Definition: swrect.hxx:204
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:393
SwFrame * GetLower()
Definition: findfrm.cxx:170
bool IsPageFrame() const
Definition: frame.hxx:1159
const Point & GetPtPos() const
Definition: viscrs.hxx:142
CursorMoveState m_eState
Definition: crstate.hxx:138
bool m_bPosMatchesBounds
GetModelPositionForViewPoint should not return the next position if screen position is inside second ...
Definition: crstate.hxx:152
bool OnFirstPage() const
Definition: trvlfrm.cxx:1767
const SwTabFrame * GetFollow() const
Definition: tabfrm.hxx:243
void setHeight(tools::Long nHeight)
bool Contains(const SwAnchoredObject &_rAnchoredObj) const
Definition: sortedobjs.cxx:244
const Point & GetEndPos() const
Definition: viscrs.hxx:148
tools::Long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1359
virtual void Calc(vcl::RenderContext *pRenderContext) const override
Definition: fly.cxx:2869
void ActualizeSelection(const SwSelBoxes &rBoxes)
Definition: swcrsr.cxx:2536
void SetLeft(SwRect &rRect, tools::Long nNew) const
Definition: frame.hxx:1369
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:1001
Point GetPagePos(sal_uInt16 nPageNum) const
Returns the absolute document position of the desired page.
Definition: trvlfrm.cxx:1573
std::pair< const_iterator, bool > insert(Value &&x)
bool IsFootnoteContFrame() const
Definition: frame.hxx:1179
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:123
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:67
Point GetNextPrevContentPos(const Point &rPoint, bool bNext) const
Search the nearest Content to the passed point.
Definition: trvlfrm.cxx:1474
SwTableLine * GetUpper()
Definition: swtable.hxx:428
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:208
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:2515
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 GetModelPositionForView...
Definition: trvlfrm.cxx:1185
bool IsTextNode() const
Definition: node.hxx:639
void Height(tools::Long nNew)
Definition: swrect.hxx:191
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1238
bool IsClickable() const
Is this field clickable?
Definition: fldbas.cxx:807
sal_uInt16 GetPageNum() const
Definition: rootfrm.hxx:311
bool IsFooterFrame() const
Definition: frame.hxx:1175
static const SwContentFrame * lcl_GetPrvCnt(const SwContentFrame *pCnt)
Definition: trvlfrm.cxx:639
SwRootFrame * getRootFrame()
Definition: frame.hxx:662
virtual bool GetModelPositionForViewPoint(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:471
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:30
bool IsCallbackActionEnabled() const
Definition: rootfrm.hxx:386
sal_uInt16 nPos
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1317
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:848
bool IsHeaderFrame() const
Definition: frame.hxx:1171
virtual bool FillSelection(SwSelectionList &rList, const SwRect &rRect) const override
Definition: trvlfrm.cxx:366
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5521
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:394
bool IsProtected() const
Is the Frame or rather the Section in which it lies protected?
Definition: trvlfrm.cxx:1627
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1080
SwFrame * GetNext()
Definition: frame.hxx:659