Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/layout/trvlfrm.cxx
Warning:line 768, column 53
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name trvlfrm.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/layout/trvlfrm.cxx

/home/maarten/src/libreoffice/core/sw/source/core/layout/trvlfrm.cxx

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

/home/maarten/src/libreoffice/core/sw/source/core/inc/frame.hxx

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#ifndef INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
21#define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX
22
23#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
24#include <editeng/borderline.hxx>
25#include <svl/poolitem.hxx>
26#include <swtypes.hxx>
27#include <swrect.hxx>
28#include <calbck.hxx>
29#include <svl/SfxBroadcaster.hxx>
30#include <o3tl/typed_flags_set.hxx>
31#include <com/sun/star/style/TabStop.hpp>
32#include <basegfx/matrix/b2dhommatrix.hxx>
33#include <vcl/outdev.hxx>
34
35#include <memory>
36
37namespace drawinglayer::processor2d { class BaseProcessor2D; }
38
39class SwLayoutFrame;
40class SwRootFrame;
41class SwPageFrame;
42class SwBodyFrame;
43class SwFlyFrame;
44class SwSectionFrame;
45class SwFootnoteFrame;
46class SwFootnoteBossFrame;
47class SwTabFrame;
48class SwRowFrame;
49class SwContentFrame;
50class SwAttrSet;
51class Color;
52class SwBorderAttrs;
53class SwCache;
54class SvxBrushItem;
55class SvxFormatBreakItem;
56class SwFormatPageDesc;
57class SwSelectionList;
58struct SwPosition;
59struct SwCursorMoveState;
60class SwFormat;
61class SwPrintData;
62class SwSortedObjs;
63class SwAnchoredObject;
64enum class SvxFrameDirection;
65class IDocumentDrawModelAccess;
66
67// Each FrameType is represented here as a bit.
68// The bits must be set in a way that it can be determined with masking of
69// which kind of FrameType an instance is _and_ from what classes it was derived.
70// Each frame has in its base class a member that must be set by the
71// constructors accordingly.
72enum class SwFrameType
73{
74 None = 0x0000,
75 Root = 0x0001,
76 Page = 0x0002,
77 Column = 0x0004,
78 Header = 0x0008,
79 Footer = 0x0010,
80 FtnCont = 0x0020,
81 Ftn = 0x0040,
82 Body = 0x0080,
83 Fly = 0x0100,
84 Section = 0x0200,
85// UNUSED 0x0400
86 Tab = 0x0800,
87 Row = 0x1000,
88 Cell = 0x2000,
89 Txt = 0x4000,
90 NoTxt = 0x8000,
91};
92
93namespace o3tl
94{
95 template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {};
96};
97
98// for internal use some common combinations
99#define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF)
100#define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff)
101#define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt)
102#define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column)
103#define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt)
104#define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell)
105#define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section
| SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType
::Txt)
(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt)
106#define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer)
107#define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body)
108
109// for GetNextLeaf/GetPrevLeaf.
110enum MakePageType
111{
112 MAKEPAGE_NONE, // do not create page/footnote
113 MAKEPAGE_APPEND, // only append page if needed
114 MAKEPAGE_INSERT, // add or append page if needed
115 MAKEPAGE_FTN, // add footnote if needed
116 MAKEPAGE_NOSECTION // Don't create section frames
117};
118
119namespace drawinglayer::attribute {
120 class SdrAllFillAttributesHelper;
121 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
122}
123
124/// Helper class to isolate geometry-defining members of SwFrame
125/// and to control their accesses. Moved to own class to have no
126/// hidden accesses to 'private' members anymore.
127///
128/// Added most important flags about the state of this geometric
129/// information and if it is valid or not
130class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition
131{
132private:
133 friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &);
134
135 // The absolute position and size of the SwFrame in the document.
136 // This values are set by the layouter implementations
137 SwRect maFrameArea;
138
139 // The 'inner' Frame Area defined by a SwRect relative to FrameArea:
140 // When identical to FrameArea, Pos() will be (0, 0) and Size identical.
141 SwRect maFramePrintArea;
142
143 // bitfield
144 bool mbFrameAreaPositionValid : 1;
145 bool mbFrameAreaSizeValid : 1;
146 bool mbFramePrintAreaValid : 1;
147
148 // #i65250#
149 // frame ID is now in general available - used for layout loop control
150 static sal_uInt32 mnLastFrameId;
151 const sal_uInt32 mnFrameId;
152
153protected:
154 // write access to mb*Valid flags
155 void setFrameAreaPositionValid(bool bNew);
156 void setFrameAreaSizeValid(bool bNew);
157 void setFramePrintAreaValid(bool bNew);
158
159public:
160 SwFrameAreaDefinition();
161 virtual ~SwFrameAreaDefinition();
162
163 // read access to mb*Valid flags
164 bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; }
165 bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; }
166 bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; }
167
168 // syntactic sugar: test whole FrameAreaDefinition
169 bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); }
170
171 // #i65250#
172 sal_uInt32 GetFrameId() const { return mnFrameId; }
173
174 // read accesses to FrameArea definitions - only const access allowed.
175 // Do *not* const_cast results, it is necessary to track changes. use
176 // the below offered WriteAccess helper classes instead
177 const SwRect& getFrameArea() const { return maFrameArea; }
178 const SwRect& getFramePrintArea() const { return maFramePrintArea; }
179
180 // helper class(es) for FrameArea manipulation. These
181 // have to be used to apply changes to FrameAreas. They hold a copy of the
182 // SwRect for manipulation. It gets written back at destruction. Thus, this
183 // mechanism depends on scope usage, take care. It prevents errors using
184 // different instances of SwFrame in get/set methods which is more safe
185 class FrameAreaWriteAccess : public SwRect
186 {
187 private:
188 SwFrameAreaDefinition& mrTarget;
189
190 FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete;
191 FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete;
192
193 public:
194 FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {}
195 ~FrameAreaWriteAccess();
196 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
197 };
198
199 // same helper for FramePrintArea
200 class FramePrintAreaWriteAccess : public SwRect
201 {
202 private:
203 SwFrameAreaDefinition& mrTarget;
204
205 FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete;
206 FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete;
207
208 public:
209 FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {}
210 ~FramePrintAreaWriteAccess();
211 void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; }
212 };
213
214 // RotateFlyFrame3 - Support for Transformations
215 // Hand out the Transformations for the current FrameAreaDefinition
216 // for the FrameArea and FramePrintArea.
217 // FramePrintArea is not relative to FrameArea in this
218 // transformation representation (to make it easier to use and understand).
219 // There is no 'set' method since SwFrame is a layout object. For
220 // some cases rotation will be included (used for SwGrfNode in inner
221 // SwFrame of a SwFlyFrame)
222 virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const;
223 virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
224
225 // RotateFlyFrame3 - Support for Transformations
226 // Modify current transformations by applying given translation
227 virtual void transform_translate(const Point& rOffset);
228};
229
230/// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate
231/// transformable. It provides some tooling to do so. To use, add as member
232/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >')
233class TransformableSwFrame
234{
235private:
236 // The SwFrameAreaDefinition to work on
237 SwFrameAreaDefinition& mrSwFrameAreaDefinition;
238
239 // FrameAreaTransformation and FramePrintAreaTransformation
240 // !identity when needed (translate/scale is used (e.g. rotation))
241 basegfx::B2DHomMatrix maFrameAreaTransformation;
242 basegfx::B2DHomMatrix maFramePrintAreaTransformation;
243
244public:
245 TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition)
246 : mrSwFrameAreaDefinition(rSwFrameAreaDefinition),
247 maFrameAreaTransformation(),
248 maFramePrintAreaTransformation()
249 {
250 }
251
252 // get SwFrameArea in transformation form
253 const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const
254 {
255 return maFrameAreaTransformation;
256 }
257
258 // get SwFramePrintArea in transformation form
259 const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const
260 {
261 return maFramePrintAreaTransformation;
262 }
263
264 // Helpers to re-create the untransformed SwRect(s) originally
265 // in the SwFrameAreaDefinition, based on the current Transformations.
266 SwRect getUntransformedFrameArea() const;
267 SwRect getUntransformedFramePrintArea() const;
268
269 // Helper method to re-create FrameAreaTransformations based on the
270 // current FrameAreaDefinition transformed by given rotation and Center
271 void createFrameAreaTransformations(
272 double fRotation,
273 const basegfx::B2DPoint& rCenter);
274
275 // Tooling method to reset the SwRect(s) in the current
276 // SwFrameAreaDefinition which are already adapted to
277 // Transformation back to the untransformed state, using
278 // the getUntransformedFrame*Area calls above when needed.
279 // Only the SwRect(s) are changed back, not the transformations.
280 void restoreFrameAreas();
281
282 // Re-Creates the SwRect(s) as BoundAreas based on the current
283 // set Transformations.
284 void adaptFrameAreasToTransformations();
285
286 // Modify current definitions by applying the given transformation
287 void transform(const basegfx::B2DHomMatrix& aTransform);
288};
289
290/**
291 * Base class of the Writer layout elements.
292 *
293 * This includes not only fly frames, but everything down to the paragraph
294 * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion
295 * instances are used.)
296 */
297class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster
298{
299 // the hidden Frame
300 friend class SwFlowFrame;
301 friend class SwLayoutFrame;
302 friend class SwLooping;
303 friend class SwDeletionChecker; // for GetDep()
304
305 // voids lower during creation of a column
306 friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart );
307 friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling );
308
309 // for validating a mistakenly invalidated one in SwContentFrame::MakeAll
310 friend void ValidateSz( SwFrame *pFrame );
311 // implemented in text/txtftn.cxx, prevents Footnote oscillation
312 friend void ValidateText( SwFrame *pFrame );
313
314 friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt );
315
316 // cache for (border) attributes
317 static SwCache *mpCache;
318
319 SwRootFrame *mpRoot;
320 SwLayoutFrame *mpUpper;
321 SwFrame *mpNext;
322 SwFrame *mpPrev;
323
324 // sw_redlinehide: hide these dangerous SwClient functions
325 using SwClient::GetRegisteredInNonConst;
326 using SwClient::GetRegisteredIn;
327
328 SwFrame *FindNext_();
329 SwFrame *FindPrev_();
330
331 /** method to determine next content frame in the same environment
332 for a flow frame (content frame, table frame, section frame)
333
334 #i27138# - adding documentation:
335 Travelling downwards through the layout to determine the next content
336 frame in the same environment. There are several environments in a
337 document, which form a closed context regarding this function. These
338 environments are:
339 - Each page header
340 - Each page footer
341 - Each unlinked fly frame
342 - Each group of linked fly frames
343 - All footnotes
344 - All document body frames
345 #i27138# - adding parameter <_bInSameFootnote>
346 Its default value is <false>. If its value is <true>, the environment
347 'All footnotes' is no longer treated. Instead each footnote is treated
348 as an own environment.
349
350 @param _bInSameFootnote
351 input parameter - boolean indicating, that the found next content
352 frame has to be in the same footnote frame. This parameter is only
353 relevant for flow frames in footnotes.
354
355 @return SwContentFrame*
356 pointer to the found next content frame. It's NULL, if none exists.
357 */
358 SwContentFrame* FindNextCnt_( const bool _bInSameFootnote );
359
360 /** method to determine previous content frame in the same environment
361 for a flow frame (content frame, table frame, section frame)
362
363 #i27138#
364 Travelling upwards through the layout to determine the previous content
365 frame in the same environment. There are several environments in a
366 document, which form a closed context regarding this function. These
367 environments are:
368 - Each page header
369 - Each page footer
370 - Each unlinked fly frame
371 - Each group of linked fly frames
372 - All footnotes
373 - All document body frames
374 #i27138# - adding parameter <_bInSameFootnote>
375 Its default value is <false>. If its value is <true>, the environment
376 'All footnotes' is no longer treated. Instead each footnote is treated
377 as an own environment.
378
379 The found previous content frame has to be in the same footnote frame. This is only
380 relevant for flow frames in footnotes.
381
382 @return SwContentFrame*
383 pointer to the found previous content frame. It's NULL, if none exists.
384 */
385 SwContentFrame* FindPrevCnt_();
386
387 void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & );
388 SwFrame* GetIndNext_();
389 void SetDirFlags( bool bVert );
390
391 const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const;
392
393 SwPageFrame* ImplFindPageFrame();
394
395protected:
396 std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null
397 SwFrameType mnFrameType; //Who am I?
398
399 bool mbInDtor : 1;
400 bool mbInvalidR2L : 1;
401 bool mbDerivedR2L : 1;
402 bool mbRightToLeft : 1;
403 bool mbInvalidVert : 1;
404 bool mbDerivedVert : 1;
405 bool mbVertical : 1;
406
407 bool mbVertLR : 1;
408 bool mbVertLRBT : 1;
409
410 bool mbValidLineNum : 1;
411 bool mbFixSize : 1;
412
413 // if true, frame will be painted completely even content was changed
414 // only partially. For ContentFrames a border (from Action) will exclusively
415 // painted if <mbCompletePaint> is true.
416 bool mbCompletePaint : 1;
417
418 bool mbRetouche : 1; // frame is responsible for retouching
419
420 bool mbInfInvalid : 1; // InfoFlags are invalid
421 bool mbInfBody : 1; // Frame is in document body
422 bool mbInfTab : 1; // Frame is in a table
423 bool mbInfFly : 1; // Frame is in a Fly
424 bool mbInfFootnote : 1; // Frame is in a footnote
425 bool mbInfSct : 1; // Frame is in a section
426 bool mbColLocked : 1; // lock Grow/Shrink for column-wise section
427 // or fly frames, will be set in Format
428 bool m_isInDestroy : 1;
429 bool mbForbidDelete : 1;
430
431 void ColLock() { mbColLocked = true; }
432 void ColUnlock() { mbColLocked = false; }
433
434 virtual void DestroyImpl();
435 virtual ~SwFrame() override;
436
437 // Only used by SwRootFrame Ctor to get 'this' into mpRoot...
438 void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; }
439
440 SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote );
441 void PrepareMake(vcl::RenderContext* pRenderContext);
442 void OptPrepareMake();
443 virtual void MakePos();
444 // Format next frame of table frame to assure keeping attributes.
445 // In case of nested tables method <SwFrame::MakeAll()> is called to
446 // avoid formatting of superior table frame.
447 friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame );
448
449 virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0;
450 // adjust frames of a page
451 SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false );
452
453 // change only frame size not the size of PrtArea
454 virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
455 virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0;
456
457 /// use these so we can grep for SwFrame's GetRegisteredIn accesses
458 /// beware that SwTextFrame may return sw::WriterMultiListener
459 SwModify *GetDep() { return GetRegisteredInNonConst(); }
460 const SwModify *GetDep() const { return GetRegisteredIn(); }
461
462 SwFrame( SwModify*, SwFrame* );
463
464 void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse );
465
466 /** enumeration for the different invalidations
467 #i28701#
468 */
469 enum InvalidationType
470 {
471 INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL
472 };
473
474 /** method to determine, if an invalidation is allowed.
475 #i28701
476 */
477 virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const;
478
479 /** method to perform additional actions on an invalidation
480
481 #i28701#
482 Method has *only* to contain actions, which has to be performed on
483 *every* assignment of the corresponding flag to <false>.
484 */
485 virtual void ActionOnInvalidation( const InvalidationType _nInvalid );
486
487 // draw shadow and borders
488 void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const;
489 virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override;
490
491 virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( );
492
493public:
494 virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips )
495 {
496 return css::uno::Sequence< css::style::TabStop >();
497 }
498
499
500 SwFrameType GetType() const { return mnFrameType; }
501
502 static SwCache &GetCache() { return *mpCache; }
503 static SwCache *GetCachePtr() { return mpCache; }
504 static void SetCache( SwCache *pNew ) { mpCache = pNew; }
505
506 // change PrtArea size and FrameSize
507 SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false );
508 SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false );
509
510 // different methods for inserting in layout tree (for performance reasons)
511
512 // insert before pBehind or at the end of the chain below mpUpper
513 void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind );
514 // insert after pBefore or at the beginning of the chain below mpUpper
515 void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore );
516 // insert before pBehind or at the end of the chain while considering
517 // the siblings of pSct
518 bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct );
519 void RemoveFromLayout();
520
521 // For internal use only - who ignores this will be put in a sack and has
522 // to stay there for two days
523 // Does special treatment for Get_[Next|Prev]Leaf() (for tables).
524 SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd );
525 SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage );
526 SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage );
527 SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage );
528 SwLayoutFrame *GetNextCellLeaf();
529 SwLayoutFrame *GetPrevLeaf ();
530 SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote );
531 SwLayoutFrame *GetPrevSctLeaf();
532 SwLayoutFrame *GetPrevCellLeaf();
533 const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd,
534 const SwFrame *pAnch ) const;
535
536 bool WrongPageDesc( SwPageFrame* pNew );
537
538 //#i28701# - new methods to append/remove drawing objects
539 void AppendDrawObj( SwAnchoredObject& _rNewObj );
540 void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj );
541
542 // work with chain of FlyFrames
543 void AppendFly( SwFlyFrame *pNew );
544 void RemoveFly( SwFlyFrame *pToRemove );
545 const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); }
546 SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); }
547 // #i28701# - change purpose of method and adjust its name
548 void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true );
549
550 virtual void PaintSwFrameShadowAndBorder(
551 const SwRect&,
552 const SwPageFrame* pPage,
553 const SwBorderAttrs&) const;
554 void PaintBaBo( const SwRect&, const SwPageFrame *pPage,
555 const bool bOnlyTextBackground = false) const;
556 void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage,
557 const SwBorderAttrs &,
558 const bool bLowerMode = false,
559 const bool bLowerBorder = false,
560 const bool bOnlyTextBackground = false ) const;
561 void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*,
562 const Color *pColor,
563 const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const;
564
565 std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const;
566 void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const;
567
568 // retouch, not in the area of the given Rect!
569 void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const;
570
571 bool GetBackgroundBrush(
572 drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes,
573 const SvxBrushItem*& rpBrush,
574 const Color*& rpColor,
575 SwRect &rOrigRect,
576 bool bLowerMode,
577 bool bConsiderTextBox ) const;
578
579 inline void SetCompletePaint() const;
580 inline void ResetCompletePaint() const;
581 bool IsCompletePaint() const { return mbCompletePaint; }
582
583 inline void SetRetouche() const;
584 inline void ResetRetouche() const;
585 bool IsRetouche() const { return mbRetouche; }
586
587 void SetInfFlags();
588 void InvalidateInfFlags() { mbInfInvalid = true; }
589 inline bool IsInDocBody() const; // use InfoFlags, determine flags
590 inline bool IsInFootnote() const; // if necessary
591 inline bool IsInTab() const;
592 inline bool IsInFly() const;
593 inline bool IsInSct() const;
594
595 // If frame is inside a split table row, this function returns
596 // the corresponding row frame in the follow table.
597 const SwRowFrame* IsInSplitTableRow() const;
598
599 // If frame is inside a follow flow row, this function returns
600 // the corresponding row frame master table
601 const SwRowFrame* IsInFollowFlowRow() const;
602
603 bool IsInBalancedSection() const;
604
605 inline bool IsVertical() const;
606 inline bool IsVertLR() const;
607 inline bool IsVertLRBT() const;
608
609 void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; }
610 void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; }
611 inline bool IsRightToLeft() const;
612 void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; }
613
614 void CheckDirChange();
615 // returns upper left frame position for LTR and
616 // upper right frame position for Asian / RTL frames
617 Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const;
618
619 /** determine, if frame is moveable in given environment
620
621 method replaced 'old' method <bool IsMoveable() const>.
622 Determines, if frame is moveable in given environment. if no environment
623 is given (parameter _pLayoutFrame == 0), the movability in the actual
624 environment (<GetUpper()) is checked.
625
626 @param _pLayoutFrame
627 input parameter - given environment (layout frame), in which the movability
628 will be checked. If not set ( == 0 ), actual environment is taken.
629
630 @return boolean, indicating, if frame is moveable in given environment
631 */
632 bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const;
633
634 // Is it permitted for the (Text)Frame to add a footnote in the current
635 // environment (not e.g. for repeating table headlines)
636 bool IsFootnoteAllowed() const;
637
638 virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr );
639
640 virtual void CheckDirection( bool bVert );
641
642 void ReinitializeFrameSizeAttrFlags();
643
644 /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for
645 /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead
646 const SwAttrSet *GetAttrSet() const;
647 virtual const SvxFormatBreakItem& GetBreakItem() const;
648 virtual const SwFormatPageDesc& GetPageDescItem() const;
649
650 bool HasFixSize() const { return mbFixSize; }
651
652 // check all pages (starting from the given) and correct them if needed
653 static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr);
654
655 // might return 0, with and without const
656 SwFrame *GetNext() { return mpNext; }
657 SwFrame *GetPrev() { return mpPrev; }
658 SwLayoutFrame *GetUpper() { return mpUpper; }
659 SwRootFrame *getRootFrame(){ return mpRoot; }
660 SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); }
661 SwFrame *FindColFrame();
662 SwRowFrame *FindRowFrame();
663 SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false );
664 SwTabFrame *ImplFindTabFrame();
665 SwFootnoteFrame *ImplFindFootnoteFrame();
666 SwFlyFrame *ImplFindFlyFrame();
667 SwSectionFrame *ImplFindSctFrame();
668 const SwBodyFrame *ImplFindBodyFrame() const;
669 SwFrame *FindFooterOrHeader();
670 SwFrame *GetLower();
671 const SwFrame *GetNext() const { return mpNext; }
672 const SwFrame *GetPrev() const { return mpPrev; }
673 const SwLayoutFrame *GetUpper() const { return mpUpper; }
674 const SwRootFrame *getRootFrame() const { return mpRoot; }
675 inline SwTabFrame *FindTabFrame();
676 inline SwFootnoteFrame *FindFootnoteFrame();
677 inline SwFlyFrame *FindFlyFrame();
678 inline SwSectionFrame *FindSctFrame();
679 inline SwFrame *FindNext();
680 // #i27138# - add parameter <_bInSameFootnote>
681 SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false );
682 inline SwFrame *FindPrev();
683 inline const SwPageFrame *FindPageFrame() const;
684 inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const;
685 inline const SwFrame *FindColFrame() const;
686 inline const SwFrame *FindFooterOrHeader() const;
687 inline const SwTabFrame *FindTabFrame() const;
688 inline const SwFootnoteFrame *FindFootnoteFrame() const;
689 inline const SwFlyFrame *FindFlyFrame() const;
690 inline const SwSectionFrame *FindSctFrame() const;
691 inline const SwBodyFrame *FindBodyFrame() const;
692 inline const SwFrame *FindNext() const;
693 // #i27138# - add parameter <_bInSameFootnote>
694 const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const;
695 inline const SwFrame *FindPrev() const;
696 const SwFrame *GetLower() const;
697
698 SwContentFrame* FindPrevCnt();
699
700 const SwContentFrame* FindPrevCnt() const;
701
702 // #i79774#
703 SwFrame* GetIndPrev_() const;
704 SwFrame* GetIndPrev() const
705 { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); }
706
707 SwFrame* GetIndNext()
708 { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); }
709 const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); }
710
711 sal_uInt16 GetPhyPageNum() const; // page number without offset
712 sal_uInt16 GetVirtPageNum() const; // page number with offset
713 bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; };
714 bool WannaRightPage() const;
715 bool OnFirstPage() const;
716
717 inline const SwLayoutFrame *GetPrevLayoutLeaf() const;
718 inline const SwLayoutFrame *GetNextLayoutLeaf() const;
719 inline SwLayoutFrame *GetPrevLayoutLeaf();
720 inline SwLayoutFrame *GetNextLayoutLeaf();
721
722 virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted"
723 inline void OptCalc() const; // here we assume (for optimization) that
724 // the predecessors are already formatted
725 Point GetRelPos() const;
726
727 // PaintArea is the area where content might be displayed.
728 // The margin of a page or the space between columns belongs to it.
729 SwRect GetPaintArea() const;
730
731 // UnionFrame is the union of Frame- and PrtArea, normally identical
732 // to the FrameArea except in case of negative Prt margins.
733 SwRect UnionFrame( bool bBorder = false ) const;
734
735 virtual Size ChgSize( const Size& aNewSize );
736
737 virtual void Cut() = 0;
738 virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0;
739
740 void ValidateLineNum() { mbValidLineNum = true; }
741
742 bool GetValidLineNumFlag()const { return mbValidLineNum; }
743
744 // Only invalidate Frame
745 // #i28701# - add call to method <ActionOnInvalidation(..)>
746 // for all invalidation methods.
747 // #i28701# - use method <InvalidationAllowed(..)> to
748 // decide, if invalidation will to be performed or not.
749 // #i26945# - no additional invalidation, if it's already
750 // invalidate.
751 void InvalidateSize_()
752 {
753 if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) )
754 {
755 setFrameAreaSizeValid(false);
756 ActionOnInvalidation( INVALID_SIZE );
757 }
758 }
759 void InvalidatePrt_()
760 {
761 if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) )
762 {
763 setFramePrintAreaValid(false);
764 ActionOnInvalidation( INVALID_PRTAREA );
765 }
766 }
767 void InvalidatePos_()
768 {
769 if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) )
770 {
771 setFrameAreaPositionValid(false);
772 ActionOnInvalidation( INVALID_POS );
773 }
774 }
775 void InvalidateLineNum_()
776 {
777 if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) )
778 {
779 mbValidLineNum = false;
780 ActionOnInvalidation( INVALID_LINENUM );
781 }
782 }
783 void InvalidateAll_()
784 {
785 if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) )
786 {
787 setFrameAreaSizeValid(false);
788 setFrameAreaPositionValid(false);
789 setFramePrintAreaValid(false);
790 ActionOnInvalidation( INVALID_ALL );
791 }
792 }
793 // also notify page at the same time
794 inline void InvalidateSize();
795 inline void InvalidatePrt();
796 inline void InvalidatePos();
797 inline void InvalidateLineNum();
798 inline void InvalidateAll();
799 void ImplInvalidateSize();
800 void ImplInvalidatePrt();
801 void ImplInvalidatePos();
802 void ImplInvalidateLineNum();
803
804 inline void InvalidateNextPos( bool bNoFootnote = false );
805 void ImplInvalidateNextPos( bool bNoFootnote );
806
807 /** method to invalidate printing area of next frame
808 #i11859#
809 */
810 void InvalidateNextPrtArea();
811
812 void InvalidatePage( const SwPageFrame *pPage = nullptr ) const;
813
814 virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
815
816 virtual bool GetModelPositionForViewPoint( SwPosition *, Point&,
817 SwCursorMoveState* = nullptr, bool bTestBackground = false ) const;
818 virtual bool GetCharRect( SwRect &, const SwPosition&,
819 SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const;
820 virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&,
821 SwPrintData const*const pPrintData = nullptr ) const;
822
823 // HACK: shortcut between frame and formatting
824 // It's your own fault if you cast void* incorrectly! In any case check
825 // the void* for 0.
826 virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear,
827 const void *pVoid = nullptr, bool bNotify = true );
828
829 // true if it is the correct class, false otherwise
830 inline bool IsLayoutFrame() const;
831 inline bool IsRootFrame() const;
832 inline bool IsPageFrame() const;
833 inline bool IsColumnFrame() const;
834 inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames
835 inline bool IsHeaderFrame() const;
836 inline bool IsFooterFrame() const;
837 inline bool IsFootnoteContFrame() const;
838 inline bool IsFootnoteFrame() const;
839 inline bool IsBodyFrame() const;
840 inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame
841 inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame
842 inline bool IsFlyFrame() const;
843 inline bool IsSctFrame() const;
844 inline bool IsTabFrame() const;
845 inline bool IsRowFrame() const;
846 inline bool IsCellFrame() const;
847 inline bool IsContentFrame() const;
848 inline bool IsTextFrame() const;
849 inline bool IsNoTextFrame() const;
850 // Frames where its PrtArea depends on their neighbors and that are
851 // positioned in the content flow
852 inline bool IsFlowFrame() const;
853 // Frames that are capable of retouching or that might need to retouch behind
854 // themselves
855 inline bool IsRetoucheFrame() const;
856 inline bool IsAccessibleFrame() const;
857
858 void PrepareCursor(); // CursorShell is allowed to call this
859
860 // Is the Frame (or the section containing it) protected? Same for Fly in
861 // Fly in ... and footnotes
862 bool IsProtected() const;
863
864 bool IsColLocked() const { return mbColLocked; }
865 virtual bool IsDeleteForbidden() const { return mbForbidDelete; }
866
867 /// this is the only way to delete a SwFrame instance
868 static void DestroyFrame(SwFrame *const pFrame);
869
870 bool IsInDtor() const { return mbInDtor; }
871
872 // No inline cause we need the function pointers
873 long GetTopMargin() const;
874 long GetBottomMargin() const;
875 long GetLeftMargin() const;
876 long GetRightMargin() const;
877 void SetTopBottomMargins( long, long );
878 void SetLeftRightMargins( long, long );
879 void SetRightLeftMargins( long, long );
880 long GetPrtLeft() const;
881 long GetPrtBottom() const;
882 long GetPrtRight() const;
883 long GetPrtTop() const;
884 bool SetMinLeft( long );
885 bool SetMaxBottom( long );
886 bool SetMaxRight( long );
887 void MakeBelowPos( const SwFrame*, const SwFrame*, bool );
888 void MakeLeftPos( const SwFrame*, const SwFrame*, bool );
889 void MakeRightPos( const SwFrame*, const SwFrame*, bool );
890 bool IsNeighbourFrame() const
891 { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); }
892
893 // NEW TABLES
894 // Some functions for covered/covering table cells. This way unnecessary
895 // includes can be avoided
896 virtual bool IsLeaveUpperAllowed() const;
897 virtual bool IsCoveredCell() const;
898 bool IsInCoveredCell() const;
899
900 // #i81146# new loop control
901 bool KnowsFormat( const SwFormat& rFormat ) const;
902 void RegisterToFormat( SwFormat& rFormat );
903 void ValidateThisAndAllLowers( const sal_uInt16 nStage );
904
905 void ForbidDelete() { mbForbidDelete = true; }
906 void AllowDelete() { mbForbidDelete = false; }
907
908 drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
909 bool supportsFullDrawingLayerFillAttributeSet() const;
910
911public:
912 // if writer is NULL, dumps the layout structure as XML in layout.xml
913 virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const;
914 void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const;
915 void dumpInfosAsXml(xmlTextWriterPtr writer) const;
916 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const;
917 void dumpChildrenAsXml(xmlTextWriterPtr writer) const;
918 bool IsCollapse() const;
919};
920
921inline bool SwFrame::IsInDocBody() const
922{
923 if ( mbInfInvalid )
924 const_cast<SwFrame*>(this)->SetInfFlags();
925 return mbInfBody;
926}
927inline bool SwFrame::IsInFootnote() const
928{
929 if ( mbInfInvalid )
930 const_cast<SwFrame*>(this)->SetInfFlags();
931 return mbInfFootnote;
932}
933inline bool SwFrame::IsInTab() const
934{
935 if ( mbInfInvalid
23.1
Field 'mbInfInvalid' is false
23.1
Field 'mbInfInvalid' is false
)
18
Assuming field 'mbInfInvalid' is false
19
Taking false branch
24
Taking false branch
936 const_cast<SwFrame*>(this)->SetInfFlags();
937 return mbInfTab;
20
Returning value, which participates in a condition later
25
Returning zero, which participates in a condition later
938}
939inline bool SwFrame::IsInFly() const
940{
941 if ( mbInfInvalid )
942 const_cast<SwFrame*>(this)->SetInfFlags();
943 return mbInfFly;
944}
945inline bool SwFrame::IsInSct() const
946{
947 if ( mbInfInvalid )
948 const_cast<SwFrame*>(this)->SetInfFlags();
949 return mbInfSct;
950}
951bool SwFrame::IsVertical() const
952{
953 if( mbInvalidVert )
954 const_cast<SwFrame*>(this)->SetDirFlags( true );
955 return mbVertical;
956}
957inline bool SwFrame::IsVertLR() const
958{
959 return mbVertLR;
960}
961inline bool SwFrame::IsVertLRBT() const
962{
963 return mbVertLRBT;
964}
965inline bool SwFrame::IsRightToLeft() const
966{
967 if( mbInvalidR2L )
968 const_cast<SwFrame*>(this)->SetDirFlags( false );
969 return mbRightToLeft;
970}
971
972inline void SwFrame::SetCompletePaint() const
973{
974 const_cast<SwFrame*>(this)->mbCompletePaint = true;
975}
976inline void SwFrame::ResetCompletePaint() const
977{
978 const_cast<SwFrame*>(this)->mbCompletePaint = false;
979}
980
981inline void SwFrame::SetRetouche() const
982{
983 const_cast<SwFrame*>(this)->mbRetouche = true;
984}
985inline void SwFrame::ResetRetouche() const
986{
987 const_cast<SwFrame*>(this)->mbRetouche = false;
988}
989
990inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf()
991{
992 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf());
993}
994inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf()
995{
996 return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf());
997}
998inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const
999{
1000 return ImplGetNextLayoutLeaf( true );
1001}
1002inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const
1003{
1004 return ImplGetNextLayoutLeaf( false );
1005}
1006
1007inline void SwFrame::InvalidateSize()
1008{
1009 if ( isFrameAreaSizeValid() )
1010 {
1011 ImplInvalidateSize();
1012 }
1013}
1014inline void SwFrame::InvalidatePrt()
1015{
1016 if ( isFramePrintAreaValid() )
1017 {
1018 ImplInvalidatePrt();
1019 }
1020}
1021inline void SwFrame::InvalidatePos()
1022{
1023 if ( isFrameAreaPositionValid() )
1024 {
1025 ImplInvalidatePos();
1026 }
1027}
1028inline void SwFrame::InvalidateLineNum()
1029{
1030 if ( mbValidLineNum )
1031 ImplInvalidateLineNum();
1032}
1033inline void SwFrame::InvalidateAll()
1034{
1035 if ( InvalidationAllowed( INVALID_ALL ) )
1036 {
1037 if ( isFrameAreaDefinitionValid() )
1038 {
1039 ImplInvalidatePos();
1040 }
1041
1042 setFrameAreaSizeValid(false);
1043 setFrameAreaPositionValid(false);
1044 setFramePrintAreaValid(false);
1045
1046 // #i28701#
1047 ActionOnInvalidation( INVALID_ALL );
1048 }
1049}
1050inline void SwFrame::InvalidateNextPos( bool bNoFootnote )
1051{
1052 if ( mpNext && !mpNext->IsSctFrame() )
1053 mpNext->InvalidatePos();
1054 else
1055 ImplInvalidateNextPos( bNoFootnote );
1056}
1057
1058inline void SwFrame::OptCalc() const
1059{
1060 if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() )
1061 {
1062 const_cast<SwFrame*>(this)->OptPrepareMake();
1063 }
1064}
1065inline const SwPageFrame *SwFrame::FindPageFrame() const
1066{
1067 return const_cast<SwFrame*>(this)->FindPageFrame();
1068}
1069inline const SwFrame *SwFrame::FindColFrame() const
1070{
1071 return const_cast<SwFrame*>(this)->FindColFrame();
1072}
1073inline const SwFrame *SwFrame::FindFooterOrHeader() const
1074{
1075 return const_cast<SwFrame*>(this)->FindFooterOrHeader();
1076}
1077inline SwTabFrame *SwFrame::FindTabFrame()
1078{
1079 return IsInTab() ? ImplFindTabFrame() : nullptr;
1080}
1081inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const
1082{
1083 return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote );
1084}
1085inline SwFootnoteFrame *SwFrame::FindFootnoteFrame()
1086{
1087 return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr;
1088}
1089inline SwFlyFrame *SwFrame::FindFlyFrame()
1090{
1091 return IsInFly() ? ImplFindFlyFrame() : nullptr;
1092}
1093inline SwSectionFrame *SwFrame::FindSctFrame()
1094{
1095 return IsInSct() ? ImplFindSctFrame() : nullptr;
1096}
1097
1098inline const SwBodyFrame *SwFrame::FindBodyFrame() const
1099{
1100 return IsInDocBody() ? ImplFindBodyFrame() : nullptr;
1101}
1102
1103inline const SwTabFrame *SwFrame::FindTabFrame() const
1104{
1105 return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr;
7
Assuming the condition is true
8
'?' condition is true
9
Value assigned to field 'mpUpper'
10
Returning pointer, which participates in a condition later
1106}
1107inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const
1108{
1109 return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr;
1110}
1111inline const SwFlyFrame *SwFrame::FindFlyFrame() const
1112{
1113 return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr;
1114}
1115inline const SwSectionFrame *SwFrame::FindSctFrame() const
1116{
1117 return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr;
1118}
1119inline SwFrame *SwFrame::FindNext()
1120{
1121 if ( mpNext )
1122 return mpNext;
1123 else
1124 return FindNext_();
1125}
1126inline const SwFrame *SwFrame::FindNext() const
1127{
1128 if ( mpNext )
1129 return mpNext;
1130 else
1131 return const_cast<SwFrame*>(this)->FindNext_();
1132}
1133inline SwFrame *SwFrame::FindPrev()
1134{
1135 if ( mpPrev && !mpPrev->IsSctFrame() )
1136 return mpPrev;
1137 else
1138 return FindPrev_();
1139}
1140inline const SwFrame *SwFrame::FindPrev() const
1141{
1142 if ( mpPrev && !mpPrev->IsSctFrame() )
1143 return mpPrev;
1144 else
1145 return const_cast<SwFrame*>(this)->FindPrev_();
1146}
1147
1148inline bool SwFrame::IsLayoutFrame() const
1149{
1150 return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF));
1151}
1152inline bool SwFrame::IsRootFrame() const
1153{
1154 return mnFrameType == SwFrameType::Root;
1155}
1156inline bool SwFrame::IsPageFrame() const
1157{
1158 return mnFrameType == SwFrameType::Page;
1159}
1160inline bool SwFrame::IsColumnFrame() const
1161{
1162 return mnFrameType == SwFrameType::Column;
1163}
1164inline bool SwFrame::IsFootnoteBossFrame() const
1165{
1166 return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column));
1167}
1168inline bool SwFrame::IsHeaderFrame() const
1169{
1170 return mnFrameType == SwFrameType::Header;
1171}
1172inline bool SwFrame::IsFooterFrame() const
1173{
1174 return mnFrameType == SwFrameType::Footer;
1175}
1176inline bool SwFrame::IsFootnoteContFrame() const
1177{
1178 return mnFrameType == SwFrameType::FtnCont;
1179}
1180inline bool SwFrame::IsFootnoteFrame() const
1181{
1182 return mnFrameType == SwFrameType::Ftn;
1183}
1184inline bool SwFrame::IsBodyFrame() const
1185{
1186 return mnFrameType == SwFrameType::Body;
1187}
1188inline bool SwFrame::IsFlyFrame() const
1189{
1190 return mnFrameType == SwFrameType::Fly;
1191}
1192inline bool SwFrame::IsSctFrame() const
1193{
1194 return mnFrameType == SwFrameType::Section;
1195}
1196inline bool SwFrame::IsTabFrame() const
1197{
1198 return mnFrameType == SwFrameType::Tab;
1199}
1200inline bool SwFrame::IsRowFrame() const
1201{
1202 return mnFrameType == SwFrameType::Row;
1203}
1204inline bool SwFrame::IsCellFrame() const
1205{
1206 return mnFrameType == SwFrameType::Cell;
1207}
1208inline bool SwFrame::IsContentFrame() const
1209{
1210 return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt));
1211}
1212inline bool SwFrame::IsTextFrame() const
1213{
1214 return mnFrameType == SwFrameType::Txt;
1215}
1216inline bool SwFrame::IsNoTextFrame() const
1217{
1218 return mnFrameType == SwFrameType::NoTxt;
1219}
1220inline bool SwFrame::IsFlowFrame() const
1221{
1222 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section));
1223}
1224inline bool SwFrame::IsRetoucheFrame() const
1225{
1226 return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn));
1227}
1228inline bool SwFrame::IsAccessibleFrame() const
1229{
1230 return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header |
SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType
::Tab | SwFrameType::Cell | SwFrameType::Txt)
);
1231}
1232
1233//use this to protect a SwFrame for a given scope from getting deleted
1234class SwFrameDeleteGuard
1235{
1236private:
1237 SwFrame *m_pForbidFrame;
1238public:
1239 //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete
1240 //it in e.g. SwSectionFrame::MergeNext etc because we will need it
1241 //again after the SwFrameDeleteGuard dtor
1242 explicit SwFrameDeleteGuard(SwFrame* pFrame)
1243 : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ?
1244 pFrame : nullptr)
1245 {
1246 if (m_pForbidFrame)
1247 m_pForbidFrame->ForbidDelete();
1248 }
1249
1250 SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete;
1251
1252 ~SwFrameDeleteGuard()
1253 {
1254 if (m_pForbidFrame)
1255 m_pForbidFrame->AllowDelete();
1256 }
1257
1258 SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete;
1259};
1260
1261typedef long (SwFrame::*SwFrameGet)() const;
1262typedef bool (SwFrame::*SwFrameMax)( long );
1263typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool );
1264typedef long (*SwOperator)( long, long );
1265typedef void (SwFrame::*SwFrameSet)( long, long );
1266
1267struct SwRectFnCollection
1268{
1269 SwRectGet fnGetTop;
1270 SwRectGet fnGetBottom;
1271 SwRectGet fnGetLeft;
1272 SwRectGet fnGetRight;
1273 SwRectGet fnGetWidth;
1274 SwRectGet fnGetHeight;
1275 SwRectPoint fnGetPos;
1276 SwRectSize fnGetSize;
1277
1278 SwRectSet fnSetTop;
1279 SwRectSet fnSetBottom;
1280 SwRectSet fnSetLeft;
1281 SwRectSet fnSetRight;
1282 SwRectSet fnSetWidth;
1283 SwRectSet fnSetHeight;
1284
1285 SwRectSet fnSubTop;
1286 SwRectSet fnAddBottom;
1287 SwRectSet fnSubLeft;
1288 SwRectSet fnAddRight;
1289 SwRectSet fnAddWidth;
1290 SwRectSet fnAddHeight;
1291
1292 SwRectSet fnSetPosX;
1293 SwRectSet fnSetPosY;
1294
1295 SwFrameGet fnGetTopMargin;
1296 SwFrameGet fnGetBottomMargin;
1297 SwFrameGet fnGetLeftMargin;
1298 SwFrameGet fnGetRightMargin;
1299 SwFrameSet fnSetXMargins;
1300 SwFrameSet fnSetYMargins;
1301 SwFrameGet fnGetPrtTop;
1302 SwFrameGet fnGetPrtBottom;
1303 SwFrameGet fnGetPrtLeft;
1304 SwFrameGet fnGetPrtRight;
1305 SwRectDist fnTopDist;
1306 SwRectDist fnBottomDist;
1307 SwRectDist fnLeftDist;
1308 SwRectDist fnRightDist;
1309 SwFrameMax fnSetLimit;
1310 SwRectMax fnOverStep;
1311
1312 SwRectSetPos fnSetPos;
1313 SwFrameMakePos fnMakePos;
1314 SwOperator fnXDiff;
1315 SwOperator fnYDiff;
1316 SwOperator fnXInc;
1317 SwOperator fnYInc;
1318
1319 SwRectSetTwice fnSetLeftAndWidth;
1320 SwRectSetTwice fnSetTopAndHeight;
1321};
1322
1323typedef SwRectFnCollection* SwRectFn;
1324
1325// This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical)
1326extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T;
1327class SwRectFnSet {
1328public:
1329 explicit SwRectFnSet(const SwFrame *pFrame)
1330 : m_bVert(pFrame->IsVertical())
1331 , m_bVertL2R(pFrame->IsVertLR())
1332 , m_bVertL2RB2T(pFrame->IsVertLRBT())
1333 {
1334 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1335 }
1336
1337 void Refresh(const SwFrame *pFrame)
1338 {
1339 m_bVert = pFrame->IsVertical();
1340 m_bVertL2R = pFrame->IsVertLR();
1341 m_bVertL2RB2T = pFrame->IsVertLRBT();
1342 m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori;
1343 }
1344
1345 bool IsVert() const { return m_bVert; }
1346 bool IsVertL2R() const { return m_bVertL2R; }
1347 SwRectFn FnRect() const { return m_fnRect; }
1348
1349 bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const
1350 {
1351 return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)()
1352 || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)());
1353 }
1354
1355 long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); }
1356 long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); }
1357 long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); }
1358 long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); }
1359 long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); }
1360 long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); }
1361 Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); }
1362 Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); }
1363
1364 void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); }
1365 void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); }
1366 void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); }
1367 void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); }
1368 void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); }
1369 void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); }
1370
1371 void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); }
1372 void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); }
1373 void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); }
1374 void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); }
1375 void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); }
1376 void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); }
1377
1378 void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); }
1379 void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); }
1380
1381 long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); }
1382 long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); }
1383 long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); }
1384 long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); }
1385 void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); }
1386 void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); }
1387 long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); }
1388 long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); }
1389 long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); }
1390 long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); }
1391 long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); }
1392 long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); }
1393 long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); }
1394 long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); }
1395 void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); }
1396 bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); }
1397
1398 void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); }
1399 void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); }
1400 long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); }
1401 long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); }
1402 long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); }
1403 long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); }
1404
1405 void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); }
1406 void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); }
1407
1408private:
1409 bool m_bVert;
1410 bool m_bVertL2R;
1411 bool m_bVertL2RB2T;
1412 SwRectFn m_fnRect;
1413};
1414
1415#endif
1416
1417/* vim:set shiftwidth=4 softtabstop=4 expandtab: */