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