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