File: | home/maarten/src/libreoffice/core/sw/source/core/layout/trvlfrm.cxx |
Warning: | line 768, column 53 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
56 | namespace { | ||||
57 | bool lcl_GetModelPositionForViewPoint_Objects( const SwPageFrame* pPageFrame, bool bSearchBackground, | ||||
58 | SwPosition *pPos, Point const & rPoint, SwCursorMoveState* pCMS ) | ||||
59 | { | ||||
60 | bool bRet = false; | ||||
61 | Point aPoint( rPoint ); | ||||
62 | SwOrderIter aIter( pPageFrame ); | ||||
63 | aIter.Top(); | ||||
64 | while ( aIter() ) | ||||
65 | { | ||||
66 | const SwVirtFlyDrawObj* pObj = | ||||
67 | static_cast<const SwVirtFlyDrawObj*>(aIter()); | ||||
68 | const SwAnchoredObject* pAnchoredObj = GetUserCall( aIter() )->GetAnchoredObj( aIter() ); | ||||
69 | const SwFormatSurround& rSurround = pAnchoredObj->GetFrameFormat().GetSurround(); | ||||
70 | const SvxOpaqueItem& rOpaque = pAnchoredObj->GetFrameFormat().GetOpaque(); | ||||
71 | bool bInBackground = ( rSurround.GetSurround() == css::text::WrapTextMode_THROUGH ) && !rOpaque.GetValue(); | ||||
72 | |||||
73 | bool bBackgroundMatches = bInBackground == bSearchBackground; | ||||
74 | |||||
75 | const SwFlyFrame* pFly = pObj ? pObj->GetFlyFrame() : nullptr; | ||||
76 | if ( pFly && bBackgroundMatches && | ||||
77 | ( ( pCMS && pCMS->m_bSetInReadOnly ) || | ||||
78 | !pFly->IsProtected() ) && | ||||
79 | pFly->GetModelPositionForViewPoint( pPos, aPoint, pCMS ) ) | ||||
80 | { | ||||
81 | bRet = true; | ||||
82 | break; | ||||
83 | } | ||||
84 | |||||
85 | if ( pCMS && pCMS->m_bStop ) | ||||
86 | return false; | ||||
87 | aIter.Prev(); | ||||
88 | } | ||||
89 | return bRet; | ||||
90 | } | ||||
91 | |||||
92 | double lcl_getDistance( const SwRect& rRect, const Point& rPoint ) | ||||
93 | { | ||||
94 | double nDist = 0.0; | ||||
95 | |||||
96 | // If the point is inside the rectangle, then distance is 0 | ||||
97 | // Otherwise, compute the distance to the center of the rectangle. | ||||
98 | if ( !rRect.IsInside( rPoint ) ) | ||||
99 | { | ||||
100 | tools::Line aLine( rPoint, rRect.Center( ) ); | ||||
101 | nDist = aLine.GetLength( ); | ||||
102 | } | ||||
103 | |||||
104 | return nDist; | ||||
105 | } | ||||
106 | } | ||||
107 | |||||
108 | namespace { | ||||
109 | |||||
110 | //For SwFlyFrame::GetModelPositionForViewPoint | ||||
111 | class SwCursorOszControl | ||||
112 | { | ||||
113 | public: | ||||
114 | // So the compiler can initialize the class already. No DTOR and member | ||||
115 | // as public members | ||||
116 | const SwFlyFrame *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 | |||||
147 | static SwCursorOszControl g_OszCtrl = { nullptr, nullptr, nullptr }; | ||||
148 | |||||
149 | /** Searches the ContentFrame owning the PrtArea containing the point. */ | ||||
150 | bool 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 | |||||
179 | bool 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 | |||||
366 | bool SwLayoutFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const | ||||
367 | { | ||||
368 | if( rRect.IsOver(GetPaintArea()) ) | ||||
369 | { | ||||
370 | const SwFrame* pFrame = Lower(); | ||||
371 | while( pFrame ) | ||||
372 | { | ||||
373 | pFrame->FillSelection( rList, rRect ); | ||||
374 | pFrame = pFrame->GetNext(); | ||||
375 | } | ||||
376 | } | ||||
377 | return false; | ||||
378 | } | ||||
379 | |||||
380 | bool SwPageFrame::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const | ||||
381 | { | ||||
382 | bool bRet = false; | ||||
383 | if( rRect.IsOver(GetPaintArea()) ) | ||||
384 | { | ||||
385 | bRet = SwLayoutFrame::FillSelection( rList, rRect ); | ||||
386 | if( GetSortedObjs() ) | ||||
387 | { | ||||
388 | const SwSortedObjs &rObjs = *GetSortedObjs(); | ||||
389 | for (SwAnchoredObject* pAnchoredObj : rObjs) | ||||
390 | { | ||||
391 | 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 | |||||
402 | bool 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 | */ | ||||
424 | bool 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 | */ | ||||
471 | bool 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. | ||||
539 | bool 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 */ | ||||
616 | bool 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 | |||||
625 | bool SwNoTextFrame::RightMargin(SwPaM *pPam, bool) const | ||||
626 | { | ||||
627 | if( &pPam->GetNode() != GetNode() ) | ||||
628 | return false; | ||||
629 | const_cast<SwContentNode*>(GetNode())-> | ||||
630 | MakeEndIndex(&pPam->GetPoint()->nContent); | ||||
631 | return true; | ||||
632 | } | ||||
633 | |||||
634 | static const SwContentFrame *lcl_GetNxtCnt( const SwContentFrame* pCnt ) | ||||
635 | { | ||||
636 | return pCnt->GetNextContentFrame(); | ||||
637 | } | ||||
638 | |||||
639 | static const SwContentFrame *lcl_GetPrvCnt( const SwContentFrame* pCnt ) | ||||
640 | { | ||||
641 | return pCnt->GetPrevContentFrame(); | ||||
642 | } | ||||
643 | |||||
644 | typedef const SwContentFrame *(*GetNxtPrvCnt)( const SwContentFrame* ); | ||||
645 | |||||
646 | /// Frame in repeated headline? | ||||
647 | static bool lcl_IsInRepeatedHeadline( const SwFrame *pFrame, | ||||
648 | const SwTabFrame** ppTFrame = nullptr ) | ||||
649 | { | ||||
650 | const SwTabFrame *pTab = pFrame->FindTabFrame(); | ||||
651 | if( ppTFrame ) | ||||
652 | *ppTFrame = pTab; | ||||
653 | return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrame ); | ||||
654 | } | ||||
655 | |||||
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 | ||||
659 | static 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 | |||||
690 | static 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) | ||||
| |||||
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() && | ||||
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
| ||||
735 | pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTableSel ); | ||||
736 | |||||
737 | const SwTabFrame *pStTab = pStart->FindTabFrame(); | ||||
738 | const SwTabFrame *pTable = nullptr; | ||||
739 | const bool bTab = pStTab || (pCnt && pCnt->IsInTab()); | ||||
740 | bool bEnd = !bTab; | ||||
741 | |||||
742 | const SwFrame* pVertRefFrame = pStart; | ||||
743 | if ( bTableSel
| ||||
744 | pVertRefFrame = pStTab; | ||||
745 | SwRectFnSet aRectFnSet(pVertRefFrame); | ||||
746 | |||||
747 | SwTwips nX = 0; | ||||
748 | if ( bTab
| ||||
749 | { | ||||
750 | // pStart or pCnt is inside a table. nX will be used for travelling: | ||||
751 | SwRect aRect( pStart->getFrameArea() ); | ||||
752 | pStart->GetCharRect( aRect, *pPam->GetPoint() ); | ||||
753 | Point aCenter = aRect.Center(); | ||||
754 | nX = aRectFnSet.IsVert() ? aCenter.Y() : aCenter.X(); | ||||
755 | |||||
756 | pTable = pCnt
| ||||
757 | if ( !pTable
| ||||
758 | pTable = pStTab; | ||||
759 | |||||
760 | if ( pStTab
| ||||
761 | !pStTab->GetUpper()->IsInTab() && | ||||
762 | !pTable->GetUpper()->IsInTab() ) | ||||
763 | { | ||||
764 | const SwFrame *pCell = pStart->GetUpper(); | ||||
765 | while ( pCell && !pCell->IsCellFrame() ) | ||||
766 | pCell = pCell->GetUpper(); | ||||
767 | OSL_ENSURE( pCell, "could not find the cell" )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); | ||||
768 | nX = aRectFnSet.XInc(aRectFnSet.GetLeft(pCell->getFrameArea()), | ||||
| |||||
769 | aRectFnSet.GetWidth(pCell->getFrameArea()) / 2); | ||||
770 | |||||
771 | //The flow leads from one table to the next. The X-value needs to be | ||||
772 | //corrected based on the middle of the starting cell by the amount | ||||
773 | //of the offset of the tables. | ||||
774 | if ( pStTab != pTable ) | ||||
775 | { | ||||
776 | nX += aRectFnSet.GetLeft(pTable->getFrameArea()) - | ||||
777 | aRectFnSet.GetLeft(pStTab->getFrameArea()); | ||||
778 | } | ||||
779 | } | ||||
780 | |||||
781 | // Restrict nX to the left and right borders of pTab: | ||||
782 | // (is this really necessary?) | ||||
783 | if (pTable && !pTable->GetUpper()->IsInTab()) | ||||
784 | { | ||||
785 | const bool bRTL = pTable->IsRightToLeft(); | ||||
786 | const 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 | |||||
965 | bool SwContentFrame::UnitUp( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const | ||||
966 | { | ||||
967 | return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly ); | ||||
968 | } | ||||
969 | |||||
970 | bool SwContentFrame::UnitDown( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const | ||||
971 | { | ||||
972 | return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly ); | ||||
973 | } | ||||
974 | |||||
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 | */ | ||||
980 | sal_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 | */ | ||||
996 | sal_uInt16 SwRootFrame::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum ) | ||||
997 | { | ||||
998 | vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr; | ||||
999 | OSL_ENSURE( Lower() && Lower()->IsPageFrame(), "No page available." )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 | |||||
1050 | SwContentFrame *GetFirstSub( const SwLayoutFrame *pLayout ) | ||||
1051 | { | ||||
1052 | return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindFirstBodyContent(); | ||||
1053 | } | ||||
1054 | |||||
1055 | SwContentFrame *GetLastSub( const SwLayoutFrame *pLayout ) | ||||
1056 | { | ||||
1057 | return const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(pLayout))->FindLastBodyContent(); | ||||
1058 | } | ||||
1059 | |||||
1060 | SwLayoutFrame *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 | |||||
1072 | SwLayoutFrame *GetThisFrame( const SwLayoutFrame *pFrame ) | ||||
1073 | { | ||||
1074 | return const_cast<SwLayoutFrame*>(pFrame); | ||||
1075 | } | ||||
1076 | |||||
1077 | SwLayoutFrame *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 | */ | ||||
1093 | bool GetFrameInPage( const SwContentFrame *pCnt, SwWhichPage fnWhichPage, | ||||
1094 | SwPosPage fnPosPage, SwPaM *pPam ) | ||||
1095 | { | ||||
1096 | //First find the requested page, at first the current, then the one which | ||||
1097 | //was requests through fnWichPage. | ||||
1098 | const SwLayoutFrame *pLayoutFrame = pCnt->FindPageFrame(); | ||||
1099 | if ( !pLayoutFrame || (nullptr == (pLayoutFrame = (*fnWhichPage)(pLayoutFrame))) ) | ||||
1100 | return false; | ||||
1101 | |||||
1102 | //Now the desired ContentFrame below the page | ||||
1103 | pCnt = (*fnPosPage)(pLayoutFrame); | ||||
1104 | if( nullptr == pCnt ) | ||||
1105 | return false; | ||||
1106 | else | ||||
1107 | { | ||||
1108 | // repeated headlines in tables | ||||
1109 | if ( pCnt->IsInTab() && fnPosPage == GetFirstSub ) | ||||
1110 | { | ||||
1111 | const SwTabFrame* pTab = pCnt->FindTabFrame(); | ||||
1112 | if ( pTab->IsFollow() ) | ||||
1113 | { | ||||
1114 | if ( pTab->IsInHeadline( *pCnt ) ) | ||||
1115 | { | ||||
1116 | SwLayoutFrame* pRow = pTab->GetFirstNonHeadlineRow(); | ||||
1117 | if ( pRow ) | ||||
1118 | { | ||||
1119 | // We are in the first line of a follow table | ||||
1120 | // with repeated headings. | ||||
1121 | // To actually make a "real" move we take the first content | ||||
1122 | // of the next row | ||||
1123 | pCnt = pRow->ContainsContent(); | ||||
1124 | if ( ! pCnt ) | ||||
1125 | return false; | ||||
1126 | } | ||||
1127 | } | ||||
1128 | } | ||||
1129 | } | ||||
1130 | |||||
1131 | assert(pCnt->IsTextFrame())(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 | |||||
1143 | static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2) | ||||
1144 | { | ||||
1145 | //Calculate the distance between the two points. | ||||
1146 | //'delta' X^2 + 'delta'Y^2 = 'distance'^2 | ||||
1147 | sal_uInt64 dX = std::max( rPt1.X(), rPt2.X() ) - | ||||
1148 | std::min( rPt1.X(), rPt2.X() ), | ||||
1149 | dY = std::max( rPt1.Y(), rPt2.Y() ) - | ||||
1150 | std::min( rPt1.Y(), rPt2.Y() ); | ||||
1151 | return (dX * dX) + (dY * dY); | ||||
1152 | } | ||||
1153 | |||||
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 | */ | ||||
1160 | static const SwLayoutFrame* lcl_Inside( const SwContentFrame *pCnt, Point const & rPt ) | ||||
1161 | { | ||||
1162 | const SwLayoutFrame* pUp = pCnt->GetUpper(); | ||||
1163 | while( pUp ) | ||||
1164 | { | ||||
1165 | if( pUp->IsPageBodyFrame() || pUp->IsFooterFrame() || pUp->IsHeaderFrame() ) | ||||
1166 | { | ||||
1167 | if( rPt.Y() >= pUp->getFrameArea().Top() && rPt.Y() <= pUp->getFrameArea().Bottom() ) | ||||
1168 | return pUp; | ||||
1169 | return nullptr; | ||||
1170 | } | ||||
1171 | if( pUp->IsFootnoteContFrame() ) | ||||
1172 | return pUp->getFrameArea().IsInside( rPt ) ? pUp : nullptr; | ||||
1173 | pUp = pUp->GetUpper(); | ||||
1174 | } | ||||
1175 | return nullptr; | ||||
1176 | } | ||||
1177 | |||||
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 | */ | ||||
1185 | const 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. */ | ||||
1381 | void 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 | */ | ||||
1474 | Point SwRootFrame::GetNextPrevContentPos( const Point& rPoint, bool bNext ) const | ||||
1475 | { | ||||
1476 | vcl::RenderContext* pRenderContext = GetCurrShell() ? GetCurrShell()->GetOut() : nullptr; | ||||
1477 | // #123110# - disable creation of an action by a callback | ||||
1478 | // event during processing of this method. Needed because formatting is | ||||
1479 | // triggered by this method. | ||||
1480 | DisableCallbackAction aDisableCallbackAction(const_cast<SwRootFrame&>(*this)); | ||||
1481 | //Search the first ContentFrame and his successor in the body area. | ||||
1482 | //To be efficient (and not formatting too much) we'll start at the correct | ||||
1483 | //page. | ||||
1484 | const SwLayoutFrame *pPage = static_cast<const SwLayoutFrame*>(Lower()); | ||||
1485 | if( pPage ) | ||||
1486 | while( pPage->GetNext() && pPage->getFrameArea().Bottom() < rPoint.Y() ) | ||||
1487 | pPage = static_cast<const SwLayoutFrame*>(pPage->GetNext()); | ||||
1488 | |||||
1489 | const SwContentFrame *pCnt = pPage ? pPage->ContainsContent() : ContainsContent(); | ||||
1490 | while ( pCnt && !pCnt->IsInDocBody() ) | ||||
1491 | pCnt = pCnt->GetNextContentFrame(); | ||||
1492 | |||||
1493 | if ( !pCnt ) | ||||
1494 | return Point( 0, 0 ); | ||||
1495 | |||||
1496 | pCnt->Calc(pRenderContext); | ||||
1497 | if( !bNext ) | ||||
1498 | { | ||||
1499 | // As long as the point lies before the first ContentFrame and there are | ||||
1500 | // still precedent pages I'll go to the next page. | ||||
1501 | while ( rPoint.Y() < pCnt->getFrameArea().Top() && pPage->GetPrev() ) | ||||
1502 | { | ||||
1503 | pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev()); | ||||
1504 | pCnt = pPage->ContainsContent(); | ||||
1505 | while ( !pCnt ) | ||||
1506 | { | ||||
1507 | pPage = static_cast<const SwLayoutFrame*>(pPage->GetPrev()); | ||||
1508 | if ( pPage ) | ||||
1509 | pCnt = pPage->ContainsContent(); | ||||
1510 | else | ||||
1511 | return ContainsContent()->UnionFrame().Pos(); | ||||
1512 | } | ||||
1513 | pCnt->Calc(pRenderContext); | ||||
1514 | } | ||||
1515 | } | ||||
1516 | |||||
1517 | //Does the point lie above the first ContentFrame? | ||||
1518 | if ( rPoint.Y() < pCnt->getFrameArea().Top() && !lcl_IsInRepeatedHeadline( pCnt ) ) | ||||
1519 | return pCnt->UnionFrame().Pos(); | ||||
1520 | |||||
1521 | Point aRet(0, 0); | ||||
1522 | do | ||||
1523 | { | ||||
1524 | //Does the point lie in the current ContentFrame? | ||||
1525 | SwRect aContentFrame( pCnt->UnionFrame() ); | ||||
1526 | if ( aContentFrame.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt )) | ||||
1527 | { | ||||
1528 | aRet = rPoint; | ||||
1529 | break; | ||||
1530 | } | ||||
1531 | |||||
1532 | //Is the current one the last ContentFrame? | ||||
1533 | //If the next ContentFrame lies behind the point, then the current on is the | ||||
1534 | //one we searched. | ||||
1535 | const SwContentFrame *pNxt = pCnt->GetNextContentFrame(); | ||||
1536 | while ( pNxt && !pNxt->IsInDocBody() ) | ||||
1537 | pNxt = pNxt->GetNextContentFrame(); | ||||
1538 | |||||
1539 | //Does the point lie behind the last ContentFrame? | ||||
1540 | if ( !pNxt ) | ||||
1541 | { | ||||
1542 | aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() ); | ||||
1543 | break; | ||||
1544 | } | ||||
1545 | |||||
1546 | //If the next ContentFrame lies behind the point then it is the one we | ||||
1547 | //searched. | ||||
1548 | const SwTabFrame* pTFrame; | ||||
1549 | pNxt->Calc(pRenderContext); | ||||
1550 | if( pNxt->getFrameArea().Top() > rPoint.Y() && | ||||
1551 | !lcl_IsInRepeatedHeadline( pCnt, &pTFrame ) && | ||||
1552 | ( !pTFrame || pNxt->getFrameArea().Left() > rPoint.X() )) | ||||
1553 | { | ||||
1554 | if (bNext) | ||||
1555 | aRet = pNxt->getFrameArea().Pos(); | ||||
1556 | else | ||||
1557 | aRet = Point( aContentFrame.Right(), aContentFrame.Bottom() ); | ||||
1558 | break; | ||||
1559 | } | ||||
1560 | pCnt = pNxt; | ||||
1561 | } | ||||
1562 | while (pCnt); | ||||
1563 | return aRet; | ||||
1564 | } | ||||
1565 | |||||
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 | */ | ||||
1573 | Point 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 | */ | ||||
1591 | SwPageFrame* SwRootFrame::GetPageByPageNum( sal_uInt16 _nPageNum ) const | ||||
1592 | { | ||||
1593 | const SwPageFrame* pPageFrame = static_cast<const SwPageFrame*>( Lower() ); | ||||
1594 | while ( pPageFrame && pPageFrame->GetPhyPageNum() < _nPageNum ) | ||||
1595 | { | ||||
1596 | pPageFrame = static_cast<const SwPageFrame*>( pPageFrame->GetNext() ); | ||||
1597 | } | ||||
1598 | |||||
1599 | if ( pPageFrame && pPageFrame->GetPhyPageNum() == _nPageNum ) | ||||
1600 | { | ||||
1601 | return const_cast<SwPageFrame*>( pPageFrame ); | ||||
1602 | } | ||||
1603 | else | ||||
1604 | { | ||||
1605 | return nullptr; | ||||
1606 | } | ||||
1607 | } | ||||
1608 | |||||
1609 | /** | ||||
1610 | * @return true, when the given physical pagenumber doesn't exist or this page is an empty page. | ||||
1611 | */ | ||||
1612 | bool SwRootFrame::IsDummyPage( sal_uInt16 nPageNum ) const | ||||
1613 | { | ||||
1614 | if( !Lower() || !nPageNum || nPageNum > GetPageNum() ) | ||||
1615 | return true; | ||||
1616 | |||||
1617 | const SwPageFrame *pPage = static_cast<const SwPageFrame*>(Lower()); | ||||
1618 | while( pPage && nPageNum < pPage->GetPhyPageNum() ) | ||||
1619 | pPage = static_cast<const SwPageFrame*>(pPage->GetNext()); | ||||
1620 | return !pPage || pPage->IsEmptyPage(); | ||||
1621 | } | ||||
1622 | |||||
1623 | /** Is the Frame or rather the Section in which it lies protected? | ||||
1624 | * | ||||
1625 | * Also Fly in Fly in ... and Footnotes | ||||
1626 | */ | ||||
1627 | bool 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 */ | ||||
1694 | sal_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 | */ | ||||
1713 | bool 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 | |||||
1767 | bool 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 | |||||
1787 | void SwFrame::Calc(vcl::RenderContext* pRenderContext) const | ||||
1788 | { | ||||
1789 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) | ||||
1790 | { | ||||
1791 | const_cast<SwFrame*>(this)->PrepareMake(pRenderContext); | ||||
1792 | } | ||||
1793 | } | ||||
1794 | |||||
1795 | Point 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. */ | ||||
1805 | sal_uInt16 SwFrame::GetVirtPageNum() const | ||||
1806 | { | ||||
1807 | const SwPageFrame *pPage = FindPageFrame(); | ||||
1808 | if ( !pPage || !pPage->GetUpper() ) | ||||
1809 | return 0; | ||||
1810 | |||||
1811 | sal_uInt16 nPhyPage = pPage->GetPhyPageNum(); | ||||
1812 | if ( !static_cast<const SwRootFrame*>(pPage->GetUpper())->IsVirtPageNum() ) | ||||
1813 | return nPhyPage; | ||||
1814 | |||||
1815 | //Search the nearest section using the virtual page number. | ||||
1816 | //Because searching backwards needs a lot of time we search specific using | ||||
1817 | //the dependencies. From the PageDescs we get the attributes and from the | ||||
1818 | //attributes we get the sections. | ||||
1819 | const SwPageFrame *pVirtPage = nullptr; | ||||
1820 | const SwFrame *pFrame = nullptr; | ||||
1821 | const SfxItemPool &rPool = pPage->GetFormat()->GetDoc()->GetAttrPool(); | ||||
1822 | for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(RES_PAGEDESC)) | ||||
1823 | { | ||||
1824 | const SwFormatPageDesc *pDesc = dynamic_cast<const SwFormatPageDesc*>(pItem); | ||||
1825 | if ( !pDesc ) | ||||
1826 | continue; | ||||
1827 | |||||
1828 | if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() ) | ||||
1829 | { | ||||
1830 | const SwModify *pMod = pDesc->GetDefinedIn(); | ||||
1831 | SwVirtPageNumInfo aInfo( pPage ); | ||||
1832 | pMod->GetInfo( aInfo ); | ||||
1833 | if ( aInfo.GetPage() ) | ||||
1834 | { | ||||
1835 | if( !pVirtPage || aInfo.GetPage()->GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) | ||||
1836 | { | ||||
1837 | pVirtPage = aInfo.GetPage(); | ||||
1838 | pFrame = aInfo.GetFrame(); | ||||
1839 | } | ||||
1840 | } | ||||
1841 | } | ||||
1842 | } | ||||
1843 | if ( pFrame ) | ||||
1844 | { | ||||
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. */ | ||||
1859 | bool 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 | |||||
1970 | static void Sub( SwRegionRects& rRegion, const SwRect& rRect ) | ||||
1971 | { | ||||
1972 | if( rRect.Width() > 1 && rRect.Height() > 1 && | ||||
1973 | rRect.IsOver( rRegion.GetOrigin() )) | ||||
1974 | rRegion -= rRect; | ||||
1975 | } | ||||
1976 | |||||
1977 | static void Add( SwRegionRects& rRegion, const SwRect& rRect ) | ||||
1978 | { | ||||
1979 | if( rRect.Width() > 1 && rRect.Height() > 1 ) | ||||
1980 | rRegion += rRect; | ||||
1981 | } | ||||
1982 | |||||
1983 | /* | ||||
1984 | * The following situations can happen: | ||||
1985 | * 1. Start and end lie in one screen-row and in the same node | ||||
1986 | * -> one rectangle out of start and end; and we're okay | ||||
1987 | * 2. Start and end lie in one frame (therefore in the same node!) | ||||
1988 | * -> expand start to the right, end to the left and if more than two | ||||
1989 | * screen-rows are involved - calculate the in-between | ||||
1990 | * 3. Start and end lie in different frames | ||||
1991 | * -> expand start to the right until frame-end, calculate Rect | ||||
1992 | * expand end to the left until frame-start, calculate Rect | ||||
1993 | * and if more than two frames are involved add the PrtArea of all | ||||
1994 | * frames which lie in between | ||||
1995 | * | ||||
1996 | * Big reorganization because of the FlyFrame - those need to be locked out. | ||||
1997 | * Exceptions: - The Fly in which the selection took place (if it took place | ||||
1998 | * in a Fly) | ||||
1999 | * - The Flys which are underrun by the text | ||||
2000 | * - The Flys which are anchored to somewhere inside the selection. | ||||
2001 | * Functioning: First a SwRegion with a root gets initialized. | ||||
2002 | * Out of the region the inverted sections are cut out. The | ||||
2003 | * section gets compressed and finally inverted and thereby the | ||||
2004 | * inverted rectangles are available. | ||||
2005 | * In the end the Flys are cut out of the section. | ||||
2006 | */ | ||||
2007 | void 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: */ |
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 | |||||
37 | namespace drawinglayer::processor2d { class BaseProcessor2D; } | ||||
38 | |||||
39 | class SwLayoutFrame; | ||||
40 | class SwRootFrame; | ||||
41 | class SwPageFrame; | ||||
42 | class SwBodyFrame; | ||||
43 | class SwFlyFrame; | ||||
44 | class SwSectionFrame; | ||||
45 | class SwFootnoteFrame; | ||||
46 | class SwFootnoteBossFrame; | ||||
47 | class SwTabFrame; | ||||
48 | class SwRowFrame; | ||||
49 | class SwContentFrame; | ||||
50 | class SwAttrSet; | ||||
51 | class Color; | ||||
52 | class SwBorderAttrs; | ||||
53 | class SwCache; | ||||
54 | class SvxBrushItem; | ||||
55 | class SvxFormatBreakItem; | ||||
56 | class SwFormatPageDesc; | ||||
57 | class SwSelectionList; | ||||
58 | struct SwPosition; | ||||
59 | struct SwCursorMoveState; | ||||
60 | class SwFormat; | ||||
61 | class SwPrintData; | ||||
62 | class SwSortedObjs; | ||||
63 | class SwAnchoredObject; | ||||
64 | enum class SvxFrameDirection; | ||||
65 | class 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. | ||||
72 | enum 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 | |||||
93 | namespace 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. | ||||
110 | enum 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 | |||||
119 | namespace 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 | ||||
130 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition | ||||
131 | { | ||||
132 | private: | ||||
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 | |||||
153 | protected: | ||||
154 | // write access to mb*Valid flags | ||||
155 | void setFrameAreaPositionValid(bool bNew); | ||||
156 | void setFrameAreaSizeValid(bool bNew); | ||||
157 | void setFramePrintAreaValid(bool bNew); | ||||
158 | |||||
159 | public: | ||||
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 >') | ||||
233 | class TransformableSwFrame | ||||
234 | { | ||||
235 | private: | ||||
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 | |||||
244 | public: | ||||
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 | */ | ||||
297 | class 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 | |||||
395 | protected: | ||||
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 | |||||
493 | public: | ||||
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 | |||||
911 | public: | ||||
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 | |||||
921 | inline bool SwFrame::IsInDocBody() const | ||||
922 | { | ||||
923 | if ( mbInfInvalid ) | ||||
924 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||
925 | return mbInfBody; | ||||
926 | } | ||||
927 | inline bool SwFrame::IsInFootnote() const | ||||
928 | { | ||||
929 | if ( mbInfInvalid ) | ||||
930 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||
931 | return mbInfFootnote; | ||||
932 | } | ||||
933 | inline bool SwFrame::IsInTab() const | ||||
934 | { | ||||
935 | if ( mbInfInvalid
| ||||
936 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||
937 | return mbInfTab; | ||||
938 | } | ||||
939 | inline bool SwFrame::IsInFly() const | ||||
940 | { | ||||
941 | if ( mbInfInvalid ) | ||||
942 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||
943 | return mbInfFly; | ||||
944 | } | ||||
945 | inline bool SwFrame::IsInSct() const | ||||
946 | { | ||||
947 | if ( mbInfInvalid ) | ||||
948 | const_cast<SwFrame*>(this)->SetInfFlags(); | ||||
949 | return mbInfSct; | ||||
950 | } | ||||
951 | bool SwFrame::IsVertical() const | ||||
952 | { | ||||
953 | if( mbInvalidVert ) | ||||
954 | const_cast<SwFrame*>(this)->SetDirFlags( true ); | ||||
955 | return mbVertical; | ||||
956 | } | ||||
957 | inline bool SwFrame::IsVertLR() const | ||||
958 | { | ||||
959 | return mbVertLR; | ||||
960 | } | ||||
961 | inline bool SwFrame::IsVertLRBT() const | ||||
962 | { | ||||
963 | return mbVertLRBT; | ||||
964 | } | ||||
965 | inline bool SwFrame::IsRightToLeft() const | ||||
966 | { | ||||
967 | if( mbInvalidR2L ) | ||||
968 | const_cast<SwFrame*>(this)->SetDirFlags( false ); | ||||
969 | return mbRightToLeft; | ||||
970 | } | ||||
971 | |||||
972 | inline void SwFrame::SetCompletePaint() const | ||||
973 | { | ||||
974 | const_cast<SwFrame*>(this)->mbCompletePaint = true; | ||||
975 | } | ||||
976 | inline void SwFrame::ResetCompletePaint() const | ||||
977 | { | ||||
978 | const_cast<SwFrame*>(this)->mbCompletePaint = false; | ||||
979 | } | ||||
980 | |||||
981 | inline void SwFrame::SetRetouche() const | ||||
982 | { | ||||
983 | const_cast<SwFrame*>(this)->mbRetouche = true; | ||||
984 | } | ||||
985 | inline void SwFrame::ResetRetouche() const | ||||
986 | { | ||||
987 | const_cast<SwFrame*>(this)->mbRetouche = false; | ||||
988 | } | ||||
989 | |||||
990 | inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf() | ||||
991 | { | ||||
992 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf()); | ||||
993 | } | ||||
994 | inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() | ||||
995 | { | ||||
996 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf()); | ||||
997 | } | ||||
998 | inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const | ||||
999 | { | ||||
1000 | return ImplGetNextLayoutLeaf( true ); | ||||
1001 | } | ||||
1002 | inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const | ||||
1003 | { | ||||
1004 | return ImplGetNextLayoutLeaf( false ); | ||||
1005 | } | ||||
1006 | |||||
1007 | inline void SwFrame::InvalidateSize() | ||||
1008 | { | ||||
1009 | if ( isFrameAreaSizeValid() ) | ||||
1010 | { | ||||
1011 | ImplInvalidateSize(); | ||||
1012 | } | ||||
1013 | } | ||||
1014 | inline void SwFrame::InvalidatePrt() | ||||
1015 | { | ||||
1016 | if ( isFramePrintAreaValid() ) | ||||
1017 | { | ||||
1018 | ImplInvalidatePrt(); | ||||
1019 | } | ||||
1020 | } | ||||
1021 | inline void SwFrame::InvalidatePos() | ||||
1022 | { | ||||
1023 | if ( isFrameAreaPositionValid() ) | ||||
1024 | { | ||||
1025 | ImplInvalidatePos(); | ||||
1026 | } | ||||
1027 | } | ||||
1028 | inline void SwFrame::InvalidateLineNum() | ||||
1029 | { | ||||
1030 | if ( mbValidLineNum ) | ||||
1031 | ImplInvalidateLineNum(); | ||||
1032 | } | ||||
1033 | inline 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 | } | ||||
1050 | inline void SwFrame::InvalidateNextPos( bool bNoFootnote ) | ||||
1051 | { | ||||
1052 | if ( mpNext && !mpNext->IsSctFrame() ) | ||||
1053 | mpNext->InvalidatePos(); | ||||
1054 | else | ||||
1055 | ImplInvalidateNextPos( bNoFootnote ); | ||||
1056 | } | ||||
1057 | |||||
1058 | inline void SwFrame::OptCalc() const | ||||
1059 | { | ||||
1060 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) | ||||
1061 | { | ||||
1062 | const_cast<SwFrame*>(this)->OptPrepareMake(); | ||||
1063 | } | ||||
1064 | } | ||||
1065 | inline const SwPageFrame *SwFrame::FindPageFrame() const | ||||
1066 | { | ||||
1067 | return const_cast<SwFrame*>(this)->FindPageFrame(); | ||||
1068 | } | ||||
1069 | inline const SwFrame *SwFrame::FindColFrame() const | ||||
1070 | { | ||||
1071 | return const_cast<SwFrame*>(this)->FindColFrame(); | ||||
1072 | } | ||||
1073 | inline const SwFrame *SwFrame::FindFooterOrHeader() const | ||||
1074 | { | ||||
1075 | return const_cast<SwFrame*>(this)->FindFooterOrHeader(); | ||||
1076 | } | ||||
1077 | inline SwTabFrame *SwFrame::FindTabFrame() | ||||
1078 | { | ||||
1079 | return IsInTab() ? ImplFindTabFrame() : nullptr; | ||||
1080 | } | ||||
1081 | inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const | ||||
1082 | { | ||||
1083 | return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote ); | ||||
1084 | } | ||||
1085 | inline SwFootnoteFrame *SwFrame::FindFootnoteFrame() | ||||
1086 | { | ||||
1087 | return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr; | ||||
1088 | } | ||||
1089 | inline SwFlyFrame *SwFrame::FindFlyFrame() | ||||
1090 | { | ||||
1091 | return IsInFly() ? ImplFindFlyFrame() : nullptr; | ||||
1092 | } | ||||
1093 | inline SwSectionFrame *SwFrame::FindSctFrame() | ||||
1094 | { | ||||
1095 | return IsInSct() ? ImplFindSctFrame() : nullptr; | ||||
1096 | } | ||||
1097 | |||||
1098 | inline const SwBodyFrame *SwFrame::FindBodyFrame() const | ||||
1099 | { | ||||
1100 | return IsInDocBody() ? ImplFindBodyFrame() : nullptr; | ||||
1101 | } | ||||
1102 | |||||
1103 | inline const SwTabFrame *SwFrame::FindTabFrame() const | ||||
1104 | { | ||||
1105 | return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; | ||||
1106 | } | ||||
1107 | inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const | ||||
1108 | { | ||||
1109 | return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr; | ||||
1110 | } | ||||
1111 | inline const SwFlyFrame *SwFrame::FindFlyFrame() const | ||||
1112 | { | ||||
1113 | return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr; | ||||
1114 | } | ||||
1115 | inline const SwSectionFrame *SwFrame::FindSctFrame() const | ||||
1116 | { | ||||
1117 | return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr; | ||||
1118 | } | ||||
1119 | inline SwFrame *SwFrame::FindNext() | ||||
1120 | { | ||||
1121 | if ( mpNext ) | ||||
1122 | return mpNext; | ||||
1123 | else | ||||
1124 | return FindNext_(); | ||||
1125 | } | ||||
1126 | inline const SwFrame *SwFrame::FindNext() const | ||||
1127 | { | ||||
1128 | if ( mpNext ) | ||||
1129 | return mpNext; | ||||
1130 | else | ||||
1131 | return const_cast<SwFrame*>(this)->FindNext_(); | ||||
1132 | } | ||||
1133 | inline SwFrame *SwFrame::FindPrev() | ||||
1134 | { | ||||
1135 | if ( mpPrev && !mpPrev->IsSctFrame() ) | ||||
1136 | return mpPrev; | ||||
1137 | else | ||||
1138 | return FindPrev_(); | ||||
1139 | } | ||||
1140 | inline 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 | |||||
1148 | inline bool SwFrame::IsLayoutFrame() const | ||||
1149 | { | ||||
1150 | return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF)); | ||||
1151 | } | ||||
1152 | inline bool SwFrame::IsRootFrame() const | ||||
1153 | { | ||||
1154 | return mnFrameType == SwFrameType::Root; | ||||
1155 | } | ||||
1156 | inline bool SwFrame::IsPageFrame() const | ||||
1157 | { | ||||
1158 | return mnFrameType == SwFrameType::Page; | ||||
1159 | } | ||||
1160 | inline bool SwFrame::IsColumnFrame() const | ||||
1161 | { | ||||
1162 | return mnFrameType == SwFrameType::Column; | ||||
1163 | } | ||||
1164 | inline bool SwFrame::IsFootnoteBossFrame() const | ||||
1165 | { | ||||
1166 | return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column)); | ||||
1167 | } | ||||
1168 | inline bool SwFrame::IsHeaderFrame() const | ||||
1169 | { | ||||
1170 | return mnFrameType == SwFrameType::Header; | ||||
1171 | } | ||||
1172 | inline bool SwFrame::IsFooterFrame() const | ||||
1173 | { | ||||
1174 | return mnFrameType == SwFrameType::Footer; | ||||
1175 | } | ||||
1176 | inline bool SwFrame::IsFootnoteContFrame() const | ||||
1177 | { | ||||
1178 | return mnFrameType == SwFrameType::FtnCont; | ||||
1179 | } | ||||
1180 | inline bool SwFrame::IsFootnoteFrame() const | ||||
1181 | { | ||||
1182 | return mnFrameType == SwFrameType::Ftn; | ||||
1183 | } | ||||
1184 | inline bool SwFrame::IsBodyFrame() const | ||||
1185 | { | ||||
1186 | return mnFrameType == SwFrameType::Body; | ||||
1187 | } | ||||
1188 | inline bool SwFrame::IsFlyFrame() const | ||||
1189 | { | ||||
1190 | return mnFrameType == SwFrameType::Fly; | ||||
1191 | } | ||||
1192 | inline bool SwFrame::IsSctFrame() const | ||||
1193 | { | ||||
1194 | return mnFrameType == SwFrameType::Section; | ||||
1195 | } | ||||
1196 | inline bool SwFrame::IsTabFrame() const | ||||
1197 | { | ||||
1198 | return mnFrameType == SwFrameType::Tab; | ||||
1199 | } | ||||
1200 | inline bool SwFrame::IsRowFrame() const | ||||
1201 | { | ||||
1202 | return mnFrameType == SwFrameType::Row; | ||||
1203 | } | ||||
1204 | inline bool SwFrame::IsCellFrame() const | ||||
1205 | { | ||||
1206 | return mnFrameType == SwFrameType::Cell; | ||||
1207 | } | ||||
1208 | inline bool SwFrame::IsContentFrame() const | ||||
1209 | { | ||||
1210 | return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)); | ||||
1211 | } | ||||
1212 | inline bool SwFrame::IsTextFrame() const | ||||
1213 | { | ||||
1214 | return mnFrameType == SwFrameType::Txt; | ||||
1215 | } | ||||
1216 | inline bool SwFrame::IsNoTextFrame() const | ||||
1217 | { | ||||
1218 | return mnFrameType == SwFrameType::NoTxt; | ||||
1219 | } | ||||
1220 | inline bool SwFrame::IsFlowFrame() const | ||||
1221 | { | ||||
1222 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section)); | ||||
1223 | } | ||||
1224 | inline bool SwFrame::IsRetoucheFrame() const | ||||
1225 | { | ||||
1226 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn)); | ||||
1227 | } | ||||
1228 | inline 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 | ||||
1234 | class SwFrameDeleteGuard | ||||
1235 | { | ||||
1236 | private: | ||||
1237 | SwFrame *m_pForbidFrame; | ||||
1238 | public: | ||||
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 | |||||
1261 | typedef long (SwFrame::*SwFrameGet)() const; | ||||
1262 | typedef bool (SwFrame::*SwFrameMax)( long ); | ||||
1263 | typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool ); | ||||
1264 | typedef long (*SwOperator)( long, long ); | ||||
1265 | typedef void (SwFrame::*SwFrameSet)( long, long ); | ||||
1266 | |||||
1267 | struct 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 | |||||
1323 | typedef SwRectFnCollection* SwRectFn; | ||||
1324 | |||||
1325 | // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) | ||||
1326 | extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; | ||||
1327 | class SwRectFnSet { | ||||
1328 | public: | ||||
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 | |||||
1408 | private: | ||||
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: */ |