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