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 20 : bool lcl_GetCrsrOfst_Objects( const SwPageFrm* pPageFrm, bool bSearchBackground,
53 : SwPosition *pPos, Point& rPoint, SwCrsrMoveState* pCMS )
54 : {
55 20 : bool bRet = false;
56 20 : Point aPoint( rPoint );
57 20 : SwOrderIter aIter( pPageFrm );
58 20 : aIter.Top();
59 68 : while ( aIter() )
60 : {
61 : const SwVirtFlyDrawObj* pObj =
62 28 : static_cast<const SwVirtFlyDrawObj*>(aIter());
63 28 : const SwAnchoredObject* pAnchoredObj = GetUserCall( aIter() )->GetAnchoredObj( aIter() );
64 28 : const SwFmtSurround& rSurround = pAnchoredObj->GetFrmFmt().GetSurround();
65 28 : const SvxOpaqueItem& rOpaque = pAnchoredObj->GetFrmFmt().GetOpaque();
66 28 : bool bInBackground = ( rSurround.GetSurround() == SURROUND_THROUGHT ) && !rOpaque.GetValue();
67 :
68 70 : bool bBackgroundMatches = ( bInBackground && bSearchBackground ) ||
69 84 : ( !bInBackground && !bSearchBackground );
70 :
71 28 : const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
72 56 : if ( pFly && bBackgroundMatches &&
73 14 : ( ( pCMS && pCMS->bSetInReadOnly ) ||
74 42 : !pFly->IsProtected() ) &&
75 14 : pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
76 : {
77 0 : bRet = true;
78 0 : break;
79 : }
80 :
81 28 : if ( pCMS && pCMS->bStop )
82 0 : return false;
83 28 : aIter.Prev();
84 : }
85 20 : 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 14 : void Entry( const SwFlyFrm *pFly )
127 : {
128 14 : if ( !pEntry )
129 14 : pEntry = pStk1 = pFly;
130 14 : }
131 :
132 14 : void Exit( const SwFlyFrm *pFly )
133 : {
134 14 : if ( pFly == pEntry )
135 14 : pEntry = pStk1 = pStk2 = 0;
136 14 : }
137 : };
138 :
139 : static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
140 :
141 : /** Searches the CntntFrm owning the PrtArea containing the point. */
142 1044 : bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
143 : SwCrsrMoveState* pCMS, bool ) const
144 : {
145 1044 : bool bRet = false;
146 1044 : const SwFrm *pFrm = Lower();
147 3140 : while ( !bRet && pFrm )
148 : {
149 1052 : pFrm->Calc();
150 :
151 : // #i43742# New function
152 1052 : const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
153 : const SwRect aPaintRect( bCntntCheck ?
154 : pFrm->UnionFrm() :
155 1052 : pFrm->PaintArea() );
156 :
157 1484 : if ( aPaintRect.IsInside( rPoint ) &&
158 735 : ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
159 432 : bRet = true;
160 : else
161 620 : pFrm = pFrm->GetNext();
162 1052 : if ( pCMS && pCMS->bStop )
163 0 : return false;
164 : }
165 1044 : return bRet;
166 : }
167 :
168 : /** Searches the page containing the searched point. */
169 :
170 529 : bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
171 : SwCrsrMoveState* pCMS, bool bTestBackground ) const
172 : {
173 529 : bool bRet = false;
174 529 : Point aPoint( rPoint );
175 :
176 : // check, if we have to adjust the point
177 529 : 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 529 : bool bTextRet = false;
186 529 : 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 529 : if ( GetSortedObjs() )
192 : {
193 10 : bRet = lcl_GetCrsrOfst_Objects( this, false, pPos, rPoint, pCMS );
194 : }
195 :
196 529 : if ( !bRet )
197 : {
198 529 : SwPosition aBackPos( *pPos );
199 1054 : SwPosition aTextPos( *pPos );
200 :
201 : //We fix the StartPoint if no Cntnt 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 529 : if ( SwLayoutFrm::GetCrsrOfst( &aTextPos, aPoint, pCMS ) )
205 : {
206 216 : bTextRet = true;
207 : }
208 : else
209 : {
210 313 : if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
211 : {
212 4 : ((SwCrsrMoveState*)pCMS)->bStop = true;
213 4 : return false;
214 : }
215 309 : const SwCntntFrm *pCnt = GetCntntPos( aPoint, false, false, false, pCMS, false );
216 309 : if ( pCMS && pCMS->bStop )
217 0 : return false;
218 :
219 : OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
220 309 : if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
221 0 : bTextRet = pCnt->GetCrsrOfst( &aTextPos, rPoint, pCMS );
222 : else
223 309 : bTextRet = pCnt->GetCrsrOfst( &aTextPos, aPoint, pCMS );
224 :
225 309 : if ( !bTextRet )
226 : {
227 : // Set point to pCnt, delete mark
228 : // this may happen, if pCnt is hidden
229 57 : aTextPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
230 57 : bTextRet = true;
231 : }
232 : }
233 :
234 525 : SwCntntNode* pTextNd = aTextPos.nNode.GetNode( ).GetCntntNode( );
235 525 : bool bConsiderBackground = true;
236 : // If the text position is a clickable field, then that should have priority.
237 525 : if (pTextNd && pTextNd->IsTxtNode())
238 : {
239 525 : SwTxtNode* pTxtNd = pTextNd->GetTxtNode();
240 525 : SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(aTextPos.nContent.GetIndex(), RES_TXTATR_FIELD);
241 525 : if (pTxtAttr)
242 : {
243 0 : const SwField* pField = pTxtAttr->GetFmtFld().GetField();
244 0 : if (pField->IsClickable())
245 0 : bConsiderBackground = false;
246 : }
247 : }
248 :
249 : // Check objects in the background if nothing else matched
250 525 : if ( GetSortedObjs() )
251 : {
252 10 : bBackRet = lcl_GetCrsrOfst_Objects( this, true, &aBackPos, rPoint, pCMS );
253 : }
254 :
255 525 : if ( ( bConsiderBackground && bTestBackground && bBackRet ) || !bTextRet )
256 : {
257 0 : bRet = bBackRet;
258 0 : (*pPos) = aBackPos;
259 : }
260 525 : else if (bTextRet && !bBackRet)
261 : {
262 525 : bRet = bTextRet;
263 525 : (*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 ( pTextNd )
274 : {
275 0 : SwCntntFrm* pTextFrm = pTextNd->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 < pTextNd->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 : SwCntntNode* pBackNd = aBackPos.nNode.GetNode( ).GetCntntNode( );
324 0 : if ( pBackNd && bConsiderBackground)
325 : {
326 : // FIXME There are still cases were we don't have the proper node here.
327 0 : SwCntntFrm* 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 525 : }
349 : }
350 :
351 525 : if ( bRet )
352 525 : rPoint = aPoint;
353 :
354 525 : 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 529 : bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
418 : SwCrsrMoveState* pCMS, bool bTestBackground ) const
419 : {
420 529 : const bool bOldAction = IsCallbackActionEnabled();
421 529 : ((SwRootFrm*)this)->SetCallbackActionEnabled( false );
422 : OSL_ENSURE( (Lower() && Lower()->IsPageFrm()), "No PageFrm found." );
423 529 : if( pCMS && pCMS->pFill )
424 0 : ((SwCrsrMoveState*)pCMS)->bFillRet = false;
425 529 : Point aOldPoint = rPoint;
426 :
427 : // search for page containing rPoint. The borders around the pages are considerd
428 529 : const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
429 :
430 : // #i95626#
431 : // special handling for <rPoint> beyond root frames area
432 529 : if ( !pPage &&
433 529 : 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 529 : if ( pPage )
443 : {
444 529 : pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS, bTestBackground );
445 : }
446 :
447 529 : ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
448 529 : if( pCMS )
449 : {
450 529 : if( pCMS->bStop )
451 4 : return false;
452 525 : if( pCMS->pFill )
453 0 : return pCMS->bFillRet;
454 : }
455 525 : return aOldPoint == rPoint;
456 : }
457 :
458 : /**
459 : * If this is about a Cntnt-carrying cell the Crsr will be force inserted into one of the CntntFrms
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 : GetFmt()->GetProtect().IsCntntProtected() )
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 : ((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 SwCntntFrm *pCnt = GetCntntPos( rPoint, true );
511 0 : if( bFill && pCnt->IsTxtFrm() )
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 14 : bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
532 : SwCrsrMoveState* pCMS, bool ) const
533 : {
534 14 : 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 14 : Calc();
540 14 : bool bInside = Frm().IsInside( rPoint ) && Lower();
541 14 : 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 14 : if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
546 0 : (!Lower() || Lower()->IsNoTxtFrm()) )
547 0 : bInside = false;
548 :
549 14 : const SwPageFrm *pPage = FindPageFrm();
550 14 : 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 28 : 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 SwCntntFrm *pCnt = GetCntntPos( rPoint, true, false, false, pCMS );
592 0 : if ( pCMS && pCMS->bStop )
593 0 : return false;
594 0 : if( bFill && pCnt->IsTxtFrm() )
595 : {
596 0 : rPoint = aPoint;
597 : }
598 0 : pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
599 0 : bRet = true;
600 : }
601 : }
602 14 : aOszCtrl.Exit( this );
603 14 : return bRet;
604 : }
605 :
606 : /** Layout dependent cursor travelling */
607 0 : bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
608 : {
609 0 : if( &pPam->GetNode() != (SwCntntNode*)GetNode() )
610 0 : return false;
611 0 : ((SwCntntNode*)GetNode())->
612 0 : MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
613 0 : return true;
614 : }
615 :
616 0 : bool SwCntntFrm::RightMargin(SwPaM *pPam, bool) const
617 : {
618 0 : if( &pPam->GetNode() != (SwCntntNode*)GetNode() )
619 0 : return false;
620 0 : ((SwCntntNode*)GetNode())->
621 0 : MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
622 0 : return true;
623 : }
624 :
625 4 : static const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
626 : {
627 4 : return pCnt->GetNextCntntFrm();
628 : }
629 :
630 8 : static const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
631 : {
632 8 : return pCnt->GetPrevCntntFrm();
633 : }
634 :
635 : typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
636 :
637 : /// Frame in repeated headline?
638 12 : static bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
639 : const SwTabFrm** ppTFrm = 0 )
640 : {
641 12 : const SwTabFrm *pTab = pFrm->FindTabFrm();
642 12 : if( ppTFrm )
643 0 : *ppTFrm = pTab;
644 12 : 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 447 : static const SwCntntFrm * lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
651 : GetNxtPrvCnt fnNxtPrv,
652 : bool bMissHeadline,
653 : bool bInReadOnly,
654 : bool bMissFollowFlowLine )
655 : {
656 447 : if ( pCnt && pCnt->IsInTab() )
657 : {
658 116 : bool bProtect = true;
659 348 : while ( pCnt && bProtect )
660 : {
661 116 : const SwLayoutFrm *pCell = pCnt->GetUpper();
662 232 : while ( pCell && !pCell->IsCellFrm() )
663 0 : pCell = pCell->GetUpper();
664 232 : if ( !pCell ||
665 116 : (( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
666 244 : ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
667 232 : ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
668 116 : !pCell->IsCoveredCell()) ) )
669 116 : bProtect = false;
670 : else
671 0 : pCnt = (*fnNxtPrv)( pCnt );
672 : }
673 : }
674 331 : else if ( !bInReadOnly )
675 496 : while ( pCnt && pCnt->IsProtected() )
676 0 : pCnt = (*fnNxtPrv)( pCnt );
677 :
678 447 : return pCnt;
679 : }
680 :
681 6 : static bool lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
682 : GetNxtPrvCnt fnNxtPrv, bool bInReadOnly )
683 : {
684 : OSL_ENSURE( &pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
685 : "lcl_UpDown doesn't work for others." );
686 :
687 6 : const SwCntntFrm *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 6 : bool bTblSel = false;
693 12 : if ( pStart->IsInTab() &&
694 6 : pPam->GetNode( true ).StartOfSectionNode() !=
695 6 : pPam->GetNode( false ).StartOfSectionNode() )
696 : {
697 0 : bTblSel = 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 : ((SwCellFrm*)pCell)->GetFollowCell() :
706 0 : ((SwCellFrm*)pCell)->GetPreviousCell();
707 :
708 0 : const SwCntntFrm* pTmpStart = pStart;
709 0 : while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
710 : {
711 0 : pCell = pTmpCell;
712 : pTmpCell = bFwd ?
713 : ((SwCellFrm*)pCell)->GetFollowCell() :
714 0 : ((SwCellFrm*)pCell)->GetPreviousCell();
715 : }
716 0 : const SwCntntFrm *pNxt = pCnt = pTmpStart;
717 :
718 0 : while ( pCell->IsAnLower( pNxt ) )
719 : {
720 0 : pCnt = pNxt;
721 0 : pNxt = (*fnNxtPrv)( pNxt );
722 : }
723 : }
724 :
725 6 : pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
726 6 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
727 :
728 6 : const SwTabFrm *pStTab = pStart->FindTabFrm();
729 6 : const SwTabFrm *pTable = 0;
730 6 : const bool bTab = pStTab || (pCnt && pCnt->IsInTab());
731 6 : bool bEnd = !bTab;
732 :
733 6 : const SwFrm* pVertRefFrm = pStart;
734 6 : if ( bTblSel && pStTab )
735 0 : pVertRefFrm = pStTab;
736 6 : SWRECTFN( pVertRefFrm )
737 :
738 6 : SwTwips nX = 0;
739 6 : if ( bTab )
740 : {
741 : // pStart or pCnt is inside a table. nX will be used for travelling:
742 6 : SwRect aRect( pStart->Frm() );
743 6 : pStart->GetCharRect( aRect, *pPam->GetPoint() );
744 6 : Point aCenter = aRect.Center();
745 6 : nX = bVert ? aCenter.Y() : aCenter.X();
746 :
747 6 : pTable = pCnt ? pCnt->FindTabFrm() : 0;
748 6 : if ( !pTable )
749 0 : pTable = pStTab;
750 :
751 12 : if ( pStTab &&
752 12 : !pStTab->GetUpper()->IsInTab() &&
753 6 : !pTable->GetUpper()->IsInTab() )
754 : {
755 6 : const SwFrm *pCell = pStart->GetUpper();
756 12 : while ( pCell && !pCell->IsCellFrm() )
757 0 : pCell = pCell->GetUpper();
758 : OSL_ENSURE( pCell, "could not find the cell" );
759 6 : nX = (pCell->Frm().*fnRect->fnGetLeft)() +
760 6 : (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 6 : 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 6 : if ( !pTable->GetUpper()->IsInTab() )
775 : {
776 6 : const bool bRTL = pTable->IsRightToLeft();
777 : const long nPrtLeft = bRTL ?
778 0 : (pTable->*fnRect->fnGetPrtRight)() :
779 6 : (pTable->*fnRect->fnGetPrtLeft)();
780 6 : if ( bRTL != (nX < nPrtLeft) )
781 0 : nX = nPrtLeft;
782 : else
783 : {
784 : const long nPrtRight = bRTL ?
785 0 : (pTable->*fnRect->fnGetPrtLeft)() :
786 6 : (pTable->*fnRect->fnGetPrtRight)();
787 6 : if ( bRTL != (nX > nPrtRight) )
788 0 : nX = nPrtRight;
789 : }
790 : }
791 : }
792 :
793 12 : do
794 : {
795 : //If I'm in the DocumentBody, I wan't to stay there.
796 12 : if ( pStart->IsInDocBody() )
797 : {
798 36 : while ( pCnt && (!pCnt->IsInDocBody() ||
799 24 : (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
800 : {
801 0 : pCnt = (*fnNxtPrv)( pCnt );
802 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
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->IsInFtn() )
809 : {
810 0 : while ( pCnt && (!pCnt->IsInFtn() ||
811 0 : (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
812 : {
813 0 : pCnt = (*fnNxtPrv)( pCnt );
814 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
815 : }
816 : }
817 :
818 : //In Flys we can go ahead blindly as long as we find a Cntnt.
819 0 : else if ( pStart->IsInFly() )
820 : {
821 0 : if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
822 : {
823 0 : pCnt = (*fnNxtPrv)( pCnt );
824 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
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(); //Head/Foot
832 0 : while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
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->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
846 : {
847 0 : pCnt = (*fnNxtPrv)( pCnt );
848 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
849 : }
850 : }
851 :
852 12 : if ( bTab )
853 : {
854 12 : if ( !pCnt )
855 0 : bEnd = true;
856 : else
857 : {
858 12 : const SwTabFrm *pTab = pCnt->FindTabFrm();
859 12 : if( !pTab )
860 0 : bEnd = true;
861 : else
862 : {
863 12 : 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 12 : const SwLayoutFrm *pCell = pCnt->GetUpper();
875 24 : while ( pCell && !pCell->IsCellFrm() )
876 0 : pCell = pCell->GetUpper();
877 :
878 12 : Point aInsideCell;
879 12 : Point aInsideCnt;
880 12 : if ( pCell )
881 : {
882 12 : long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
883 12 : if ( bVert )
884 : {
885 0 : if ( nTmpTop )
886 0 : --nTmpTop;
887 :
888 0 : aInsideCell = Point( nTmpTop, nX );
889 : }
890 : else
891 12 : aInsideCell = Point( nX, nTmpTop );
892 : }
893 :
894 12 : long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
895 12 : if ( bVert )
896 : {
897 0 : if ( nTmpTop )
898 0 : --nTmpTop;
899 :
900 0 : aInsideCnt = Point( nTmpTop, nX );
901 : }
902 : else
903 12 : aInsideCnt = Point( nX, nTmpTop );
904 :
905 12 : if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
906 : {
907 6 : bEnd = true;
908 : //Get the right Cntnt out of the cell.
909 6 : if ( !pCnt->Frm().IsInside( aInsideCnt ) )
910 : {
911 0 : pCnt = pCell->ContainsCntnt();
912 0 : if ( fnNxtPrv == lcl_GetPrvCnt )
913 0 : while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
914 0 : pCnt = pCnt->GetNextCntntFrm();
915 : }
916 : }
917 6 : else if ( pCnt->Frm().IsInside( aInsideCnt ) )
918 0 : bEnd = true;
919 : }
920 : }
921 12 : if ( !bEnd )
922 : {
923 6 : pCnt = (*fnNxtPrv)( pCnt );
924 6 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
925 : }
926 : }
927 :
928 18 : } while ( !bEnd ||
929 6 : (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
930 :
931 6 : if( pCnt )
932 : { // set the Point on the Content-Node
933 6 : SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
934 6 : pPam->GetPoint()->nNode = *pCNd;
935 6 : if ( fnNxtPrv == lcl_GetPrvCnt )
936 4 : pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
937 : else
938 2 : pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
939 6 : return true;
940 : }
941 0 : return false;
942 : }
943 :
944 4 : bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
945 : {
946 4 : return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
947 : }
948 :
949 2 : bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
950 : {
951 2 : 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 : GetCntntNode()->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 6 : sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
977 : {
978 : OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "No page available." );
979 :
980 6 : SwPageFrm *pPage = (SwPageFrm*)Lower();
981 6 : bool bEnd =false;
982 18 : while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
983 6 : { if ( pPage->GetNext() )
984 6 : pPage = (SwPageFrm*)pPage->GetNext();
985 : else
986 : { //Search the first CntntFrm and format until a new page is started
987 : //or until the CntntFrm are all done.
988 0 : const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
989 0 : while ( pCntnt && pPage->IsAnLower( pCntnt ) )
990 : {
991 0 : pCntnt->Calc();
992 0 : pCntnt = pCntnt->GetNextCntntFrm();
993 : }
994 : //Either this is a new page or we found the last page.
995 0 : if ( pPage->GetNext() )
996 0 : pPage = (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 CntntFrm in the body-text.
1003 : //If this is a footnote-page, the PaM will be set in the first footnote.
1004 6 : const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
1005 6 : if ( pPage->IsFtnPage() )
1006 0 : while ( pCntnt && !pCntnt->IsInFtn() )
1007 0 : pCntnt = pCntnt->GetNextCntntFrm();
1008 : else
1009 16 : while ( pCntnt && !pCntnt->IsInDocBody() )
1010 4 : pCntnt = pCntnt->GetNextCntntFrm();
1011 6 : if ( pCntnt )
1012 : {
1013 6 : SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
1014 6 : pToSet->GetPoint()->nNode = *pCNd;
1015 6 : pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
1016 6 : pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
1017 :
1018 6 : SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
1019 6 : if( pSCrsr )
1020 : {
1021 6 : Point &rPt = pSCrsr->GetPtPos();
1022 6 : rPt = pCntnt->Frm().Pos();
1023 6 : rPt += pCntnt->Prt().Pos();
1024 : }
1025 6 : return pPage->GetPhyPageNum();
1026 : }
1027 0 : return 0;
1028 : }
1029 :
1030 66 : SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
1031 : {
1032 66 : return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
1033 : }
1034 :
1035 4 : SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
1036 : {
1037 4 : return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
1038 : }
1039 :
1040 2 : SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
1041 : {
1042 : SwLayoutFrm *pNext =
1043 4 : (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
1044 4 : (SwLayoutFrm*)pFrm->GetNext() : 0;
1045 : // #i39402# in case of an empty page
1046 2 : if(pNext && !pNext->ContainsCntnt())
1047 0 : pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
1048 0 : (SwLayoutFrm*)pNext->GetNext() : 0;
1049 2 : return pNext;
1050 : }
1051 :
1052 66 : SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
1053 : {
1054 66 : return (SwLayoutFrm*)pFrm;
1055 : }
1056 :
1057 2 : SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
1058 : {
1059 : SwLayoutFrm *pPrev =
1060 4 : (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
1061 4 : (SwLayoutFrm*)pFrm->GetPrev() : 0;
1062 : // #i39402# in case of an empty page
1063 2 : if(pPrev && !pPrev->ContainsCntnt())
1064 0 : pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
1065 0 : (SwLayoutFrm*)pPrev->GetPrev() : 0;
1066 2 : 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 70 : bool GetFrmInPage( const SwCntntFrm *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 70 : const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
1087 70 : if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
1088 0 : return false;
1089 :
1090 : //Now the desired CntntFrm below the page
1091 70 : if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
1092 0 : return false;
1093 : else
1094 : {
1095 : // repeated headlines in tables
1096 70 : if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
1097 : {
1098 12 : const SwTabFrm* pTab = pCnt->FindTabFrm();
1099 12 : if ( pTab->IsFollow() )
1100 : {
1101 8 : 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->ContainsCntnt();
1111 0 : if ( ! pCnt )
1112 0 : return false;
1113 : }
1114 : }
1115 : }
1116 : }
1117 :
1118 70 : SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
1119 70 : pPam->GetPoint()->nNode = *pCNd;
1120 : sal_Int32 nIdx;
1121 70 : if( fnPosPage == GetFirstSub )
1122 66 : nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
1123 : else
1124 4 : nIdx = pCnt->GetFollow() ?
1125 4 : ((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
1126 70 : pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
1127 70 : return true;
1128 : }
1129 : }
1130 :
1131 378 : 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 1134 : sal_uInt64 dX = std::max( rPt1.X(), rPt2.X() ) -
1136 756 : std::min( rPt1.X(), rPt2.X() ),
1137 1134 : dY = std::max( rPt1.Y(), rPt2.Y() ) -
1138 756 : std::min( rPt1.Y(), rPt2.Y() );
1139 378 : return (dX * dX) + (dY * dY);
1140 : }
1141 :
1142 : /** Check if the point lies inside the page part in which also the CntntFrame 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 CntntFrm 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 378 : static const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
1149 : {
1150 378 : const SwLayoutFrm* pUp = pCnt->GetUpper();
1151 1068 : while( pUp )
1152 : {
1153 690 : if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
1154 : {
1155 378 : if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
1156 248 : return pUp;
1157 130 : return NULL;
1158 : }
1159 312 : if( pUp->IsFtnContFrm() )
1160 0 : return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
1161 312 : pUp = pUp->GetUpper();
1162 : }
1163 0 : return NULL;
1164 : }
1165 :
1166 : /** Search for the nearest Cntnt 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 CntntFrm.
1172 : */
1173 315 : const SwCntntFrm *SwLayoutFrm::GetCntntPos( 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 CntntFrm.
1181 630 : const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
1182 315 : (SwLayoutFrm*)GetPrev() : this;
1183 315 : const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
1184 :
1185 315 : if ( !pCntnt && (GetPrev() && !bDontLeave) )
1186 0 : pCntnt = ContainsCntnt();
1187 :
1188 315 : if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
1189 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
1190 0 : pCntnt = pCntnt->GetNextCntntFrm();
1191 :
1192 315 : const SwCntntFrm *pActual= pCntnt;
1193 315 : const SwLayoutFrm *pInside = NULL;
1194 315 : sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
1195 315 : Point aPoint = rPoint;
1196 315 : sal_uInt64 nDistance = SAL_MAX_UINT64;
1197 :
1198 : while ( true ) //A loop to be sure we always find one.
1199 : {
1200 2163 : while ( pCntnt &&
1201 1022 : ((!bDontLeave || IsAnLower( pCntnt )) &&
1202 511 : (pCntnt->GetPhyPageNum() <= nMaxPage)) )
1203 : {
1204 1381 : if ( ( bCalc || pCntnt->Frm().Width() ) &&
1205 439 : ( !bBodyOnly || pCntnt->IsInDocBody() ) )
1206 : {
1207 : //If the Cntnt lies in a protected area (cell, Ftn, section),
1208 : //we search the next Cntnt which is not protected.
1209 435 : const SwCntntFrm *pComp = pCntnt;
1210 : pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, false,
1211 435 : pCMS && pCMS->bSetInReadOnly, false );
1212 435 : if ( pComp != pCntnt )
1213 0 : continue;
1214 :
1215 435 : if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
1216 : {
1217 378 : if ( bCalc )
1218 0 : pCntnt->Calc();
1219 :
1220 378 : SwRect aCntFrm( pCntnt->UnionFrm() );
1221 378 : if ( aCntFrm.IsInside( rPoint ) )
1222 : {
1223 0 : pActual = pCntnt;
1224 0 : aPoint = rPoint;
1225 0 : break;
1226 : }
1227 : //The distance from rPoint to the nearest Point of pCntnt
1228 : //will now be calculated.
1229 378 : Point aCntntPoint( rPoint );
1230 :
1231 : //First set the vertical position
1232 378 : if ( aCntFrm.Top() > aCntntPoint.Y() )
1233 130 : aCntntPoint.Y() = aCntFrm.Top();
1234 248 : else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
1235 248 : aCntntPoint.Y() = aCntFrm.Bottom();
1236 :
1237 : //Now the horizontal position
1238 378 : if ( aCntFrm.Left() > aCntntPoint.X() )
1239 120 : aCntntPoint.X() = aCntFrm.Left();
1240 258 : else if ( aCntFrm.Right() < aCntntPoint.X() )
1241 0 : aCntntPoint.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 756 : if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
1247 0 : ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
1248 : {
1249 378 : const sal_uInt64 nDiff = ::CalcDiff(aCntntPoint, rPoint);
1250 378 : bool bBetter = nDiff < nDistance; // This one is nearer
1251 378 : if( !pInside )
1252 : {
1253 378 : pInside = lcl_Inside( pCntnt, rPoint );
1254 378 : if( pInside ) // In the "right" page area
1255 248 : bBetter = true;
1256 : }
1257 378 : if( bBetter )
1258 : {
1259 258 : aPoint = aCntntPoint;
1260 258 : nDistance = nDiff;
1261 258 : pActual = pCntnt;
1262 : }
1263 : }
1264 : }
1265 : }
1266 511 : pCntnt = pCntnt->GetNextCntntFrm();
1267 511 : if ( bBodyOnly )
1268 160 : while ( pCntnt && !pCntnt->IsInDocBody() )
1269 0 : pCntnt = pCntnt->GetNextCntntFrm();
1270 : }
1271 315 : 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 ( !pCntnt && pStart->GetPrev() )
1279 : {
1280 0 : ++nMaxPage;
1281 0 : if( !pStart->GetPrev()->IsLayoutFrm() )
1282 0 : return 0;
1283 0 : pStart = (SwLayoutFrm*)pStart->GetPrev();
1284 0 : pCntnt = pStart->IsInDocBody()
1285 : ? pStart->ContainsCntnt()
1286 0 : : pStart->FindPageFrm()->FindFirstBodyCntnt();
1287 : }
1288 0 : if ( !pCntnt ) // Somewhere down the road we have to start with one!
1289 : {
1290 0 : pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1291 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
1292 0 : pCntnt = pCntnt->GetNextCntntFrm();
1293 0 : if ( !pCntnt )
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 = (SwLayoutFrm*)pStart->GetPrev();
1305 0 : pCntnt = pStart->ContainsCntnt();
1306 : }
1307 : else // Somewhere down the road we have to start with one!
1308 0 : pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1309 : }
1310 0 : pActual = pCntnt;
1311 : }
1312 : else
1313 315 : break;
1314 : }
1315 :
1316 : OSL_ENSURE( pActual, "no Cntnt found." );
1317 : OSL_ENSURE( !bBodyOnly || pActual->IsInDocBody(), "Cntnt not in Body." );
1318 :
1319 : //Special case for selecting tables not in repeated TblHeadlines.
1320 315 : 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 : ((SwCrsrMoveState*)pCMS)->bStop = true;
1326 0 : return 0;
1327 : }
1328 : }
1329 :
1330 : //A small correction at the first/last
1331 315 : Size aActualSize( pActual->Prt().SSize() );
1332 315 : if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
1333 0 : aActualSize.Height() = pActual->GetUpper()->Prt().Height();
1334 :
1335 315 : SWRECTFN( pActual )
1336 628 : if ( !pActual->GetPrev() &&
1337 626 : (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
1338 939 : bVert ? rPoint.X() : rPoint.Y() ) > 0 )
1339 : {
1340 10 : aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
1341 30 : aPoint.X() = pActual->Frm().Left() +
1342 20 : ( pActual->IsRightToLeft() || bVert ?
1343 0 : pActual->Prt().Right() :
1344 20 : pActual->Prt().Left() );
1345 : }
1346 610 : else if ( !pActual->GetNext() &&
1347 610 : (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
1348 915 : bVert ? rPoint.X() : rPoint.Y() ) < 0 )
1349 : {
1350 301 : aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
1351 903 : aPoint.X() = pActual->Frm().Left() +
1352 602 : ( pActual->IsRightToLeft() || bVert ?
1353 0 : pActual->Prt().Left() :
1354 602 : pActual->Prt().Right() );
1355 : }
1356 :
1357 : //Bring the Point in to the PrtArea
1358 315 : if ( bCalc )
1359 0 : pActual->Calc();
1360 630 : const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
1361 315 : aActualSize );
1362 315 : if ( aPoint.Y() < aRect.Top() )
1363 0 : aPoint.Y() = aRect.Top();
1364 315 : else if ( aPoint.Y() > aRect.Bottom() )
1365 0 : aPoint.Y() = aRect.Bottom();
1366 315 : if ( aPoint.X() < aRect.Left() )
1367 0 : aPoint.X() = aRect.Left();
1368 315 : else if ( aPoint.X() > aRect.Right() )
1369 0 : aPoint.X() = aRect.Right();
1370 315 : rPoint = aPoint;
1371 315 : return pActual;
1372 : }
1373 :
1374 : /** Same as SwLayoutFrm::GetCntntPos(). Specialized for fields and border. */
1375 0 : void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
1376 : {
1377 : //Determine the first CntntFrm.
1378 0 : const SwCntntFrm *pCntnt = ContainsCntnt();
1379 0 : if ( pCntnt )
1380 : {
1381 : //Look back one more (if possible).
1382 0 : const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
1383 0 : while ( pTmp && !pTmp->IsInDocBody() )
1384 0 : pTmp = pTmp->GetPrevCntntFrm();
1385 0 : if ( pTmp )
1386 0 : pCntnt = pTmp;
1387 : }
1388 : else
1389 0 : pCntnt = GetUpper()->ContainsCntnt();
1390 :
1391 0 : const SwCntntFrm *pAct = pCntnt;
1392 0 : Point aAct = rPt;
1393 0 : sal_uInt64 nDist = SAL_MAX_UINT64;
1394 :
1395 0 : while ( pCntnt )
1396 : {
1397 0 : SwRect aCntFrm( pCntnt->UnionFrm() );
1398 0 : if ( aCntFrm.IsInside( rPt ) )
1399 : {
1400 : //This is the nearest one.
1401 0 : pAct = pCntnt;
1402 0 : break;
1403 : }
1404 :
1405 : //Calculate the distance from rPt to the nearest point of pCntnt.
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 = pCntnt;
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 : pCntnt = pCntnt->GetNextCntntFrm();
1432 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
1433 0 : pCntnt = pCntnt->GetNextCntntFrm();
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 : // CntntFrm not formated -> always on node-beginning
1450 0 : SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
1451 : OSL_ENSURE( pCNd, "Where is my CntntNode?" );
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 : 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 Cntnt 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::GetNextPrevCntntPos( 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 CntntFrm 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 : SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
1500 0 : if( pPage )
1501 0 : while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
1502 0 : pPage = (SwLayoutFrm*)pPage->GetNext();
1503 :
1504 0 : const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
1505 0 : while ( pCnt && !pCnt->IsInDocBody() )
1506 0 : pCnt = pCnt->GetNextCntntFrm();
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 CntntFrm 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 = (SwLayoutFrm*)pPage->GetPrev();
1519 0 : pCnt = pPage->ContainsCntnt();
1520 0 : while ( !pCnt )
1521 : {
1522 0 : pPage = (SwLayoutFrm*)pPage->GetPrev();
1523 0 : if ( pPage )
1524 0 : pCnt = pPage->ContainsCntnt();
1525 : else
1526 0 : return ContainsCntnt()->UnionFrm().Pos();
1527 : }
1528 0 : pCnt->Calc();
1529 : }
1530 : }
1531 :
1532 : //Does the point lie above the first CntntFrm?
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 CntntFrm?
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 CntntFrm?
1548 : //If the next CntntFrm lies behind the point, then the current on is the
1549 : //one we searched.
1550 0 : const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1551 0 : while ( pNxt && !pNxt->IsInDocBody() )
1552 0 : pNxt = pNxt->GetNextCntntFrm();
1553 :
1554 : //Does the point lie behind the last CntntFrm?
1555 0 : if ( !pNxt )
1556 : {
1557 0 : aRet = Point( aCntFrm.Right(), aCntFrm.Bottom() );
1558 0 : break;
1559 : }
1560 :
1561 : //If the next CntntFrm 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 = (const SwPageFrm*)Lower();
1593 : while ( true )
1594 : {
1595 0 : if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
1596 0 : break;
1597 0 : pPage = (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 = (const SwPageFrm*)Lower();
1633 0 : while( pPage && nPageNum < pPage->GetPhyPageNum() )
1634 0 : pPage = (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 33124 : bool SwFrm::IsProtected() const
1643 : {
1644 33124 : if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
1645 : {
1646 33072 : const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
1647 33072 : bool isFormProtected=pDoc->GetDocumentSettingManager().get(IDocumentSettingAccess::PROTECT_FORM );
1648 33072 : if (isFormProtected)
1649 : {
1650 4 : 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 33120 : const SwFrm *pFrm = this;
1656 136971 : do
1657 : {
1658 136983 : if ( pFrm->IsCntntFrm() )
1659 : {
1660 66240 : if ( ((SwCntntFrm*)pFrm)->GetNode() &&
1661 33120 : ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
1662 12 : return true;
1663 : }
1664 : else
1665 : {
1666 207726 : if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
1667 103863 : ((SwLayoutFrm*)pFrm)->GetFmt()->
1668 103863 : GetProtect().IsCntntProtected() )
1669 0 : return true;
1670 103863 : if ( pFrm->IsCoveredCell() )
1671 0 : return true;
1672 : }
1673 136971 : if ( pFrm->IsFlyFrm() )
1674 : {
1675 : //In a chain the protection of the content can be specified by the
1676 : //master of the chain.
1677 30 : if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
1678 : {
1679 0 : SwFlyFrm *pMaster = (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 30 : pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
1687 : }
1688 136941 : else if ( pFrm->IsFtnFrm() )
1689 26 : pFrm = ((SwFtnFrm*)pFrm)->GetRef();
1690 : else
1691 136915 : pFrm = pFrm->GetUpper();
1692 :
1693 : } while ( pFrm );
1694 :
1695 33108 : return false;
1696 : }
1697 :
1698 : /** @return the physical page number */
1699 20588 : sal_uInt16 SwFrm::GetPhyPageNum() const
1700 : {
1701 20588 : const SwPageFrm *pPage = FindPageFrm();
1702 20588 : 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 wanna 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 1990 : bool SwFrm::WannaRightPage() const
1717 : {
1718 1990 : const SwPageFrm *pPage = FindPageFrm();
1719 1990 : if ( !pPage || !pPage->GetUpper() )
1720 0 : return true;
1721 :
1722 1990 : const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
1723 1990 : const SwPageDesc *pDesc = 0;
1724 1990 : ::boost::optional<sal_uInt16> oPgNum;
1725 1990 : if ( pFlow )
1726 : {
1727 1684 : if ( pFlow->IsInTab() )
1728 116 : pFlow = pFlow->FindTabFrm();
1729 1684 : const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
1730 1684 : if ( !pTmp->IsFollow() )
1731 : {
1732 1538 : const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
1733 1538 : pDesc = rPgDesc.GetPageDesc();
1734 1538 : oPgNum = rPgDesc.GetNumOffset();
1735 : }
1736 : }
1737 1990 : if ( !pDesc )
1738 : {
1739 1726 : SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1740 1726 : if( pPrv && pPrv->IsEmptyPage() )
1741 0 : pPrv = (SwPageFrm*)pPrv->GetPrev();
1742 1726 : if( pPrv )
1743 1390 : pDesc = pPrv->GetPageDesc()->GetFollow();
1744 : else
1745 : {
1746 336 : const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
1747 336 : pDesc = &pDoc->GetPageDesc( 0 );
1748 : }
1749 : }
1750 : OSL_ENSURE( pDesc, "No pagedescriptor" );
1751 : bool bOdd;
1752 1990 : if( oPgNum )
1753 68 : bOdd = (oPgNum.get() % 2) != 0;
1754 : else
1755 : {
1756 1922 : bOdd = pPage->OnRightPage();
1757 1922 : if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1758 8 : bOdd = !bOdd;
1759 : }
1760 1990 : if( !pPage->IsEmptyPage() )
1761 : {
1762 1964 : if( !pDesc->GetRightFmt() )
1763 8 : bOdd = false;
1764 1956 : else if( !pDesc->GetLeftFmt() )
1765 10 : bOdd = true;
1766 : }
1767 1990 : return bOdd;
1768 : }
1769 :
1770 3818 : bool SwFrm::OnFirstPage() const
1771 : {
1772 3818 : bool bRet = false;
1773 3818 : const SwPageFrm *pPage = FindPageFrm();
1774 :
1775 3818 : if (pPage)
1776 : {
1777 3818 : const SwPageFrm* pPrevFrm = dynamic_cast<const SwPageFrm*>(pPage->GetPrev());
1778 3818 : if (pPrevFrm)
1779 : {
1780 3346 : const SwPageDesc* pDesc = pPage->GetPageDesc();
1781 3346 : bRet = pPrevFrm->GetPageDesc() != pDesc;
1782 : }
1783 : else
1784 472 : bRet = true;
1785 : }
1786 3818 : return bRet;
1787 : }
1788 :
1789 : /** @return the virtual page number with the offset. */
1790 5667 : sal_uInt16 SwFrm::GetVirtPageNum() const
1791 : {
1792 5667 : const SwPageFrm *pPage = FindPageFrm();
1793 5667 : if ( !pPage || !pPage->GetUpper() )
1794 0 : return 0;
1795 :
1796 5667 : sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
1797 5667 : if ( !(static_cast<const SwRootFrm*>(pPage->GetUpper()))->IsVirtPageNum() )
1798 5261 : return nPhyPage;
1799 :
1800 : //Search the nearest section using the virtual page number.
1801 : //Because searching backwards needs a lot of time we search specific using
1802 : //the dependencies. From the PageDescs we get the attributes and from the
1803 : //attributes we get the sections.
1804 406 : const SwPageFrm *pVirtPage = 0;
1805 406 : const SwFrm *pFrm = 0;
1806 406 : const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
1807 : const SfxPoolItem* pItem;
1808 406 : sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
1809 3172 : for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1810 : {
1811 2766 : if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
1812 1180 : continue;
1813 :
1814 1586 : const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
1815 1586 : if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
1816 : {
1817 626 : const SwModify *pMod = pDesc->GetDefinedIn();
1818 626 : SwVirtPageNumInfo aInfo( pPage );
1819 626 : pMod->GetInfo( aInfo );
1820 626 : if ( aInfo.GetPage() )
1821 : {
1822 372 : if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
1823 44 : GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
1824 : {
1825 326 : pVirtPage = aInfo.GetPage();
1826 326 : pFrm = aInfo.GetFrm();
1827 : }
1828 626 : }
1829 : }
1830 : }
1831 406 : if ( pFrm )
1832 : {
1833 284 : ::boost::optional<sal_uInt16> oNumOffset = pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
1834 284 : if (oNumOffset)
1835 : {
1836 284 : return nPhyPage - pFrm->GetPhyPageNum() + oNumOffset.get();
1837 : }
1838 : else
1839 : {
1840 0 : return nPhyPage - pFrm->GetPhyPageNum();
1841 284 : }
1842 : }
1843 122 : return nPhyPage;
1844 : }
1845 :
1846 : /** Determines and sets those cells which are enclosed by the selection. */
1847 826 : bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
1848 : {
1849 : //Find Union-Rects and tables (Follows) of the selection.
1850 : OSL_ENSURE( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( false ),
1851 : "Tabselection nicht auf Cnt." );
1852 :
1853 826 : bool bRet = false;
1854 :
1855 : // For new table models there's no need to ask the layout..
1856 826 : if( rTblCrsr.NewTableSelection() )
1857 826 : return true;
1858 :
1859 0 : Point aPtPt, aMkPt;
1860 : {
1861 0 : SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
1862 :
1863 0 : if( pShCrsr )
1864 : {
1865 0 : aPtPt = pShCrsr->GetPtPos();
1866 0 : aMkPt = pShCrsr->GetMkPos();
1867 : }
1868 : }
1869 :
1870 : // #151012# Made code robust here
1871 0 : const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
1872 0 : const SwCntntNode* pTmpEndNode = rTblCrsr.GetCntntNode(false);
1873 :
1874 0 : const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, false ) : 0;
1875 0 : const SwFrm* pTmpEndFrm = pTmpEndNode ? pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, false ) : 0;
1876 :
1877 0 : const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
1878 0 : const SwLayoutFrm* pEnd = pTmpEndFrm ? pTmpEndFrm->GetUpper() : 0;
1879 :
1880 : OSL_ENSURE( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" );
1881 :
1882 : /* #109590# Only change table boxes if the frames are
1883 : valid. Needed because otherwise the table cursor after moving
1884 : table cells by dnd resulted in an empty tables cursor. */
1885 0 : if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
1886 : {
1887 0 : SwSelUnions aUnions;
1888 0 : ::MakeSelUnions( aUnions, pStart, pEnd );
1889 :
1890 0 : SwSelBoxes aNew;
1891 :
1892 0 : const bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
1893 :
1894 0 : for ( size_t i = 0; i < aUnions.size(); ++i )
1895 : {
1896 0 : SwSelUnion *pUnion = &aUnions[i];
1897 0 : const SwTabFrm *pTable = pUnion->GetTable();
1898 :
1899 : // Skip any repeated headlines in the follow:
1900 0 : SwLayoutFrm* pRow = pTable->IsFollow() ?
1901 : pTable->GetFirstNonHeadlineRow() :
1902 0 : (SwLayoutFrm*)pTable->Lower();
1903 :
1904 0 : while ( pRow )
1905 : {
1906 0 : if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
1907 : {
1908 0 : const SwLayoutFrm *pCell = pRow->FirstCell();
1909 :
1910 0 : while ( pCell && pRow->IsAnLower( pCell ) )
1911 : {
1912 : OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
1913 0 : if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
1914 0 : (bReadOnlyAvailable ||
1915 0 : !pCell->GetFmt()->GetProtect().IsCntntProtected()))
1916 : {
1917 : SwTableBox* pInsBox = (SwTableBox*)
1918 0 : ((SwCellFrm*)pCell)->GetTabBox();
1919 0 : aNew.insert( pInsBox );
1920 : }
1921 0 : if ( pCell->GetNext() )
1922 : {
1923 0 : pCell = (const SwLayoutFrm*)pCell->GetNext();
1924 0 : if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
1925 0 : pCell = pCell->FirstCell();
1926 : }
1927 : else
1928 : {
1929 0 : const SwLayoutFrm* pLastCell = pCell;
1930 0 : do
1931 : {
1932 0 : pCell = pCell->GetNextLayoutLeaf();
1933 0 : } while ( pCell && pLastCell->IsAnLower( pCell ) );
1934 : // For sections with columns
1935 0 : if( pCell && pCell->IsInTab() )
1936 : {
1937 0 : while( !pCell->IsCellFrm() )
1938 : {
1939 0 : pCell = pCell->GetUpper();
1940 : OSL_ENSURE( pCell, "Where's my cell?" );
1941 : }
1942 : }
1943 : }
1944 : }
1945 : }
1946 0 : pRow = (SwLayoutFrm*)pRow->GetNext();
1947 : }
1948 : }
1949 :
1950 0 : rTblCrsr.ActualizeSelection( aNew );
1951 0 : bRet = true;
1952 : }
1953 :
1954 0 : return bRet;
1955 : }
1956 :
1957 2410 : inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
1958 : {
1959 4604 : if( rRect.Width() > 1 && rRect.Height() > 1 &&
1960 2194 : rRect.IsOver( rRegion.GetOrigin() ))
1961 2120 : rRegion -= rRect;
1962 2410 : }
1963 :
1964 0 : inline void Add( SwRegionRects& rRegion, const SwRect& rRect )
1965 : {
1966 0 : if( rRect.Width() > 1 && rRect.Height() > 1 )
1967 0 : rRegion += rRect;
1968 0 : }
1969 :
1970 : /*
1971 : * The following situations can happen:
1972 : * 1. Start and end lie in one screen-row and in the same node
1973 : * -> one rectangle out of start and end; and we're okay
1974 : * 2. Start and end lie in one frame (therefore in the same node!)
1975 : * -> expand start to the right, end to the left and if more than two
1976 : * screen-rows are involved - calculate the in-between
1977 : * 3. Start and end lie in different frames
1978 : * -> expand start to the right until frame-end, calculate Rect
1979 : * expand end to the left until frame-start, calculate Rect
1980 : * and if more than two frames are involved add the PrtArea of all
1981 : * frames which lie in between
1982 : *
1983 : * Big reorganization because of the FlyFrm - those need to be locked out.
1984 : * Exceptions: - The Fly in which the selection took place (if it took place
1985 : * in a Fly)
1986 : * - The Flys which are underrun by the text
1987 : * - The Flys which are anchored to somewhere inside the selection.
1988 : * Functioning: First a SwRegion with a root gets initialized.
1989 : * Out of the region the inverted sections are cut out. The
1990 : * section gets compressed and finally inverted and thereby the
1991 : * inverted rectangles are available.
1992 : * In the end the Flys are cut out of the section.
1993 : */
1994 1502 : void SwRootFrm::CalcFrmRects(SwShellCrsr &rCrsr)
1995 : {
1996 1502 : SwPosition *pStartPos = rCrsr.Start(),
1997 1502 : *pEndPos = rCrsr.GetPoint() == pStartPos ? rCrsr.GetMark() : rCrsr.GetPoint();
1998 :
1999 1502 : SwViewShell *pSh = GetCurrShell();
2000 :
2001 : // #i12836# enhanced pdf
2002 1502 : SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
2003 : pSh->VisArea() :
2004 3004 : Frm() );
2005 4506 : if( !pStartPos->nNode.GetNode().IsCntntNode() ||
2006 3004 : !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
2007 1766 : ( pStartPos->nNode != pEndPos->nNode &&
2008 528 : ( !pEndPos->nNode.GetNode().IsCntntNode() ||
2009 264 : !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
2010 : {
2011 1502 : return;
2012 : }
2013 :
2014 : //First obtain the CntntFrms for the start and the end - those are needed
2015 : //anyway.
2016 1502 : SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
2017 3004 : GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
2018 :
2019 1502 : SwCntntFrm const* pEndFrm = pEndPos->nNode.GetNode().
2020 3004 : GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
2021 :
2022 : OSL_ENSURE( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
2023 :
2024 : //Do not subtract the FlyFrms in which selected Frames lie.
2025 3004 : SwSortedObjs aSortObjs;
2026 1502 : if ( pStartFrm->IsInFly() )
2027 : {
2028 0 : const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
2029 : OSL_ENSURE( pObj, "No Start Object." );
2030 0 : if (pObj) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
2031 0 : const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
2032 : OSL_ENSURE( pObj2, "SwRootFrm::CalcFrmRects(..) - FlyFrame missing - looks like an invalid selection" );
2033 0 : if ( pObj2 != NULL && pObj2 != pObj )
2034 : {
2035 0 : aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
2036 : }
2037 : }
2038 :
2039 : // if a selection which is not allowed exists, we correct what is not
2040 : // allowed (header/footer/table-headline) for two pages.
2041 : do { // middle check loop
2042 1502 : const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
2043 1502 : const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
2044 12006 : while( pSttLFrm &&
2045 4524 : ! (cHdFtTblHd & pSttLFrm->GetType() ))
2046 4478 : pSttLFrm = pSttLFrm->GetUpper();
2047 1502 : if( !pSttLFrm )
2048 1456 : break;
2049 46 : const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
2050 366 : while( pEndLFrm &&
2051 138 : ! (cHdFtTblHd & pEndLFrm->GetType() ))
2052 136 : pEndLFrm = pEndLFrm->GetUpper();
2053 46 : if( !pEndLFrm )
2054 44 : break;
2055 :
2056 : OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(),
2057 : "Selection over different content" );
2058 2 : switch( pSttLFrm->GetType() )
2059 : {
2060 : case FRM_HEADER:
2061 : case FRM_FOOTER:
2062 : // On different pages? Then always on the start-page
2063 0 : if( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
2064 : {
2065 : // Set end- to the start-CntntFrame
2066 0 : if( pStartPos == rCrsr.GetPoint() )
2067 0 : pEndFrm = pStartFrm;
2068 : else
2069 0 : pStartFrm = pEndFrm;
2070 : }
2071 0 : break;
2072 : case FRM_TAB:
2073 : // On different pages? Then check for table-headline
2074 : {
2075 2 : const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm;
2076 6 : if( ( pTabFrm->GetFollow() ||
2077 2 : ((SwTabFrm*)pEndLFrm)->GetFollow() ) &&
2078 0 : pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
2079 2 : pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() &&
2080 0 : ( lcl_IsInRepeatedHeadline( pStartFrm ) ||
2081 0 : lcl_IsInRepeatedHeadline( pEndFrm ) ) )
2082 : {
2083 : // Set end- to the start-CntntFrame
2084 0 : if( pStartPos == rCrsr.GetPoint() )
2085 0 : pEndFrm = pStartFrm;
2086 : else
2087 0 : pStartFrm = pEndFrm;
2088 : }
2089 : }
2090 2 : break;
2091 : }
2092 : } while( false );
2093 :
2094 1502 : SwCrsrMoveState aTmpState( MV_NONE );
2095 1502 : aTmpState.b2Lines = true;
2096 1502 : aTmpState.bNoScroll = true;
2097 1502 : aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
2098 :
2099 : //CntntRects to Start- and EndFrms.
2100 1502 : SwRect aStRect, aEndRect;
2101 1502 : pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
2102 1502 : Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
2103 1502 : aTmpState.p2Lines = NULL;
2104 1502 : aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
2105 :
2106 1502 : pEndFrm->GetCharRect( aEndRect, *pEndPos, &aTmpState );
2107 1502 : Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
2108 :
2109 1502 : SwRect aStFrm ( pStartFrm->UnionFrm( true ) );
2110 1502 : aStFrm.Intersection( pStartFrm->PaintArea() );
2111 1502 : SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm : pEndFrm->UnionFrm( true ) );
2112 1502 : if( pStartFrm != pEndFrm )
2113 : {
2114 270 : aEndFrm.Intersection( pEndFrm->PaintArea() );
2115 : }
2116 1502 : SWRECTFN( pStartFrm )
2117 1502 : const bool bR2L = pStartFrm->IsRightToLeft();
2118 1502 : const bool bEndR2L = pEndFrm->IsRightToLeft();
2119 :
2120 : // If there's no doubleline portion involved or start and end are both
2121 : // in the same doubleline portion, all works fine, but otherwise
2122 : // we need the following...
2123 1502 : if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
2124 0 : pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
2125 : {
2126 : // If we have a start(end) position inside a doubleline portion
2127 : // the surrounded part of the doubleline portion is subtracted
2128 : // from the region and the aStRect(aEndRect) is set to the
2129 : // end(start) of the doubleline portion.
2130 136 : if( pSt2Pos )
2131 : {
2132 0 : SwRect aTmp( aStRect );
2133 :
2134 : // BiDi-Portions are swimming against the current.
2135 0 : const bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
2136 : ! bR2L :
2137 0 : bR2L;
2138 :
2139 0 : if( MT_BIDI == pSt2Pos->nMultiType &&
2140 0 : (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
2141 : {
2142 : // nested bidi portion
2143 0 : long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2144 0 : nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
2145 0 : long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
2146 :
2147 0 : (aTmp.*fnRect->fnSetRight)( nRightAbs );
2148 :
2149 0 : if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
2150 : {
2151 0 : SwRect aTmp2( pSt2Pos->aPortion );
2152 0 : (aTmp2.*fnRect->fnSetRight)( nLeftAbs );
2153 0 : aTmp2.Intersection( aEndFrm );
2154 0 : Sub( aRegion, aTmp2 );
2155 : }
2156 : }
2157 : else
2158 : {
2159 0 : if( bPorR2L )
2160 : (aTmp.*fnRect->fnSetLeft)(
2161 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
2162 : else
2163 : (aTmp.*fnRect->fnSetRight)(
2164 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
2165 : }
2166 :
2167 0 : if( MT_ROT_90 == pSt2Pos->nMultiType ||
2168 0 : (pSt2Pos->aPortion.*fnRect->fnGetTop)() ==
2169 0 : (aTmp.*fnRect->fnGetTop)() )
2170 : {
2171 : (aTmp.*fnRect->fnSetTop)(
2172 0 : (pSt2Pos->aLine.*fnRect->fnGetTop)() );
2173 : }
2174 :
2175 0 : aTmp.Intersection( aStFrm );
2176 0 : Sub( aRegion, aTmp );
2177 :
2178 0 : SwTwips nTmp = (pSt2Pos->aLine.*fnRect->fnGetBottom)();
2179 0 : if( MT_ROT_90 != pSt2Pos->nMultiType &&
2180 0 : (aStRect.*fnRect->fnBottomDist)( nTmp ) > 0 )
2181 : {
2182 0 : (aTmp.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetBottom)() );
2183 0 : (aTmp.*fnRect->fnSetBottom)( nTmp );
2184 0 : if( (aStRect.*fnRect->fnBottomDist)(
2185 0 : (pSt2Pos->aPortion.*fnRect->fnGetBottom)() ) > 0 )
2186 : {
2187 0 : if( bPorR2L )
2188 : (aTmp.*fnRect->fnSetRight)(
2189 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
2190 : else
2191 : (aTmp.*fnRect->fnSetLeft)(
2192 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
2193 : }
2194 0 : aTmp.Intersection( aStFrm );
2195 0 : Sub( aRegion, aTmp );
2196 : }
2197 :
2198 0 : aStRect = pSt2Pos->aLine;
2199 : (aStRect.*fnRect->fnSetLeft)( bR2L ?
2200 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() :
2201 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
2202 0 : (aStRect.*fnRect->fnSetWidth)( 1 );
2203 : }
2204 :
2205 136 : if( pEnd2Pos )
2206 : {
2207 136 : SWRECTFNX( pEndFrm )
2208 136 : SwRect aTmp( aEndRect );
2209 :
2210 : // BiDi-Portions are swimming against the current.
2211 136 : const bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
2212 : ! bEndR2L :
2213 136 : bEndR2L;
2214 :
2215 136 : if( MT_BIDI == pEnd2Pos->nMultiType &&
2216 0 : (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
2217 : {
2218 : // nested bidi portion
2219 0 : long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
2220 0 : nRightAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
2221 0 : long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
2222 :
2223 0 : (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
2224 :
2225 0 : if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
2226 : {
2227 0 : SwRect aTmp2( pEnd2Pos->aPortion );
2228 0 : (aTmp2.*fnRectX->fnSetLeft)( nRightAbs );
2229 0 : aTmp2.Intersection( aEndFrm );
2230 0 : Sub( aRegion, aTmp2 );
2231 : }
2232 : }
2233 : else
2234 : {
2235 136 : if ( bPorR2L )
2236 : (aTmp.*fnRectX->fnSetRight)(
2237 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
2238 : else
2239 : (aTmp.*fnRectX->fnSetLeft)(
2240 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
2241 : }
2242 :
2243 272 : if( MT_ROT_90 == pEnd2Pos->nMultiType ||
2244 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetBottom)() ==
2245 136 : (aEndRect.*fnRectX->fnGetBottom)() )
2246 : {
2247 : (aTmp.*fnRectX->fnSetBottom)(
2248 48 : (pEnd2Pos->aLine.*fnRectX->fnGetBottom)() );
2249 : }
2250 :
2251 136 : aTmp.Intersection( aEndFrm );
2252 136 : Sub( aRegion, aTmp );
2253 :
2254 : // The next statement means neither ruby nor rotate(90):
2255 136 : if( !( MT_RUBY & pEnd2Pos->nMultiType ) )
2256 : {
2257 30 : SwTwips nTmp = (pEnd2Pos->aLine.*fnRectX->fnGetTop)();
2258 30 : if( (aEndRect.*fnRectX->fnGetTop)() != nTmp )
2259 : {
2260 : (aTmp.*fnRectX->fnSetBottom)(
2261 30 : (aTmp.*fnRectX->fnGetTop)() );
2262 30 : (aTmp.*fnRectX->fnSetTop)( nTmp );
2263 60 : if( (aEndRect.*fnRectX->fnGetTop)() !=
2264 30 : (pEnd2Pos->aPortion.*fnRectX->fnGetTop)() )
2265 : {
2266 30 : if( bPorR2L )
2267 : (aTmp.*fnRectX->fnSetLeft)(
2268 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
2269 : else
2270 : (aTmp.*fnRectX->fnSetRight)(
2271 30 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
2272 : }
2273 30 : aTmp.Intersection( aEndFrm );
2274 30 : Sub( aRegion, aTmp );
2275 : }
2276 : }
2277 :
2278 136 : aEndRect = pEnd2Pos->aLine;
2279 : (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ?
2280 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() :
2281 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
2282 136 : (aEndRect.*fnRectX->fnSetWidth)( 1 );
2283 : }
2284 : }
2285 1366 : else if( pSt2Pos && pEnd2Pos &&
2286 0 : MT_BIDI == pSt2Pos->nMultiType &&
2287 0 : MT_BIDI == pEnd2Pos->nMultiType &&
2288 1366 : pSt2Pos->aPortion == pEnd2Pos->aPortion &&
2289 0 : pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
2290 : {
2291 : // This is the ugly special case, where the selection starts and
2292 : // ends in the same bidi portion but one start or end is inside a
2293 : // nested bidi portion.
2294 :
2295 0 : if ( (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
2296 : {
2297 0 : SwRect aTmp( aStRect );
2298 0 : long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2299 0 : nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
2300 0 : long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
2301 :
2302 0 : (aTmp.*fnRect->fnSetRight)( nRightAbs );
2303 0 : aTmp.Intersection( aStFrm );
2304 0 : Sub( aRegion, aTmp );
2305 :
2306 0 : aStRect = pSt2Pos->aLine;
2307 0 : (aStRect.*fnRect->fnSetLeft)( bR2L ? nRightAbs : nLeftAbs );
2308 0 : (aStRect.*fnRect->fnSetWidth)( 1 );
2309 : }
2310 :
2311 0 : SWRECTFNX( pEndFrm )
2312 0 : if ( (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
2313 : {
2314 0 : SwRect aTmp( aEndRect );
2315 0 : long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
2316 0 : nRightAbs -= (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
2317 0 : long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
2318 :
2319 0 : (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
2320 0 : aTmp.Intersection( aEndFrm );
2321 0 : Sub( aRegion, aTmp );
2322 :
2323 0 : aEndRect = pEnd2Pos->aLine;
2324 0 : (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ? nLeftAbs : nRightAbs );
2325 0 : (aEndRect.*fnRectX->fnSetWidth)( 1 );
2326 : }
2327 : }
2328 :
2329 : // The charrect may be outside the paintarea (for cursortravelling)
2330 : // but the selection has to be restricted to the paintarea
2331 1502 : if( aStRect.Left() < aStFrm.Left() )
2332 2 : aStRect.Left( aStFrm.Left() );
2333 1500 : else if( aStRect.Left() > aStFrm.Right() )
2334 0 : aStRect.Left( aStFrm.Right() );
2335 1502 : SwTwips nTmp = aStRect.Right();
2336 1502 : if( nTmp < aStFrm.Left() )
2337 2 : aStRect.Right( aStFrm.Left() );
2338 1500 : else if( nTmp > aStFrm.Right() )
2339 0 : aStRect.Right( aStFrm.Right() );
2340 1502 : if( aEndRect.Left() < aEndFrm.Left() )
2341 2 : aEndRect.Left( aEndFrm.Left() );
2342 1500 : else if( aEndRect.Left() > aEndFrm.Right() )
2343 0 : aEndRect.Left( aEndFrm.Right() );
2344 1502 : nTmp = aEndRect.Right();
2345 1502 : if( nTmp < aEndFrm.Left() )
2346 2 : aEndRect.Right( aEndFrm.Left() );
2347 1500 : else if( nTmp > aEndFrm.Right() )
2348 0 : aEndRect.Right( aEndFrm.Right() );
2349 :
2350 1502 : if( pStartFrm == pEndFrm )
2351 : {
2352 0 : bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
2353 1232 : ( MT_BIDI & pSt2Pos->nMultiType ) &&
2354 1232 : pSt2Pos->aPortion == pEnd2Pos->aPortion;
2355 : //case 1: (Same frame and same row)
2356 2464 : if( bSameRotatedOrBidi ||
2357 1232 : (aStRect.*fnRect->fnGetTop)() == (aEndRect.*fnRect->fnGetTop)() )
2358 : {
2359 1162 : Point aTmpSt( aStRect.Pos() );
2360 1162 : Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
2361 1162 : if( bSameRotatedOrBidi || bR2L )
2362 : {
2363 0 : if( aTmpSt.Y() > aTmpEnd.Y() )
2364 : {
2365 0 : long nTmpY = aTmpEnd.Y();
2366 0 : aTmpEnd.Y() = aTmpSt.Y();
2367 0 : aTmpSt.Y() = nTmpY;
2368 : }
2369 0 : if( aTmpSt.X() > aTmpEnd.X() )
2370 : {
2371 0 : long nTmpX = aTmpEnd.X();
2372 0 : aTmpEnd.X() = aTmpSt.X();
2373 0 : aTmpSt.X() = nTmpX;
2374 : }
2375 : }
2376 :
2377 1162 : SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
2378 : // Bug 34888: If content is selected which doesn't take space
2379 : // away (i.e. PostIts, RefMarks, TOXMarks), then at
2380 : // least set the width of the Crsr.
2381 1330 : if( 1 == (aTmp.*fnRect->fnGetWidth)() &&
2382 168 : pStartPos->nContent.GetIndex() !=
2383 168 : pEndPos->nContent.GetIndex() )
2384 : {
2385 138 : OutputDevice* pOut = pSh->GetOut();
2386 138 : long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
2387 138 : GetCursorSize();
2388 : (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic(
2389 138 : Size( nCrsrWidth, 0 ) ).Width() );
2390 : }
2391 1162 : aTmp.Intersection( aStFrm );
2392 1162 : Sub( aRegion, aTmp );
2393 : }
2394 : //case 2: (Same frame, but not the same line)
2395 : else
2396 : {
2397 : SwTwips lLeft, lRight;
2398 70 : if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
2399 : {
2400 0 : lLeft = (pSt2Pos->aPortion.*fnRect->fnGetLeft)();
2401 0 : lRight = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2402 : }
2403 : else
2404 : {
2405 70 : lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
2406 70 : (pStartFrm->Prt().*fnRect->fnGetLeft)();
2407 70 : lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
2408 70 : (pStartFrm->Prt().*fnRect->fnGetRight)();
2409 : }
2410 70 : if( lLeft < (aStFrm.*fnRect->fnGetLeft)() )
2411 0 : lLeft = (aStFrm.*fnRect->fnGetLeft)();
2412 70 : if( lRight > (aStFrm.*fnRect->fnGetRight)() )
2413 0 : lRight = (aStFrm.*fnRect->fnGetRight)();
2414 70 : SwRect aSubRect( aStRect );
2415 : //First line
2416 70 : if( bR2L )
2417 0 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2418 : else
2419 70 : (aSubRect.*fnRect->fnSetRight)( lRight );
2420 70 : Sub( aRegion, aSubRect );
2421 :
2422 : //If there's at least a twips between start- and endline,
2423 : //so the whole area between will be added.
2424 70 : SwTwips aTmpBottom = (aStRect.*fnRect->fnGetBottom)();
2425 70 : SwTwips aTmpTop = (aEndRect.*fnRect->fnGetTop)();
2426 70 : if( aTmpBottom != aTmpTop )
2427 : {
2428 10 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2429 10 : (aSubRect.*fnRect->fnSetRight)( lRight );
2430 10 : (aSubRect.*fnRect->fnSetTop)( aTmpBottom );
2431 10 : (aSubRect.*fnRect->fnSetBottom)( aTmpTop );
2432 10 : Sub( aRegion, aSubRect );
2433 : }
2434 : //and the last line
2435 70 : aSubRect = aEndRect;
2436 70 : if( bR2L )
2437 0 : (aSubRect.*fnRect->fnSetRight)( lRight );
2438 : else
2439 70 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2440 70 : Sub( aRegion, aSubRect );
2441 : }
2442 : }
2443 : //case 3: (Different frames, maybe with other frames between)
2444 : else
2445 : {
2446 : //The startframe first...
2447 270 : SwRect aSubRect( aStRect );
2448 270 : if( bR2L )
2449 0 : (aSubRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)());
2450 : else
2451 270 : (aSubRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)());
2452 270 : Sub( aRegion, aSubRect );
2453 270 : SwTwips nTmpTwips = (aStRect.*fnRect->fnGetBottom)();
2454 270 : if( (aStFrm.*fnRect->fnGetBottom)() != nTmpTwips )
2455 : {
2456 80 : aSubRect = aStFrm;
2457 80 : (aSubRect.*fnRect->fnSetTop)( nTmpTwips );
2458 80 : Sub( aRegion, aSubRect );
2459 : }
2460 :
2461 : //Now the frames between, if there are any
2462 270 : bool const bBody = pStartFrm->IsInDocBody();
2463 270 : const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
2464 270 : ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
2465 270 : if (pSh->IsSelectAll())
2466 44 : pCellBox = 0;
2467 :
2468 270 : const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
2469 270 : SwRect aPrvRect;
2470 :
2471 : OSL_ENSURE( pCntnt,
2472 : "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2473 816 : while ( pCntnt && pCntnt != pEndFrm )
2474 : {
2475 276 : if ( pCntnt->IsInFly() )
2476 : {
2477 0 : const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
2478 0 : aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
2479 : }
2480 :
2481 : // Consider only frames which have the same IsInDocBody value like pStartFrm
2482 : // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
2483 : // same cell frame (or its follow cell)
2484 276 : const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
2485 276 : ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
2486 276 : if (pSh->IsSelectAll())
2487 92 : pTmpCellBox = 0;
2488 552 : if ( bBody == pCntnt->IsInDocBody() &&
2489 0 : ( !pCellBox || pCellBox == pTmpCellBox ) )
2490 : {
2491 276 : SwRect aCRect( pCntnt->UnionFrm( true ) );
2492 276 : aCRect.Intersection( pCntnt->PaintArea() );
2493 276 : if( aCRect.IsOver( aRegion.GetOrigin() ))
2494 : {
2495 208 : SwRect aTmp( aPrvRect );
2496 208 : aTmp.Union( aCRect );
2497 624 : if ( (aPrvRect.Height() * aPrvRect.Width() +
2498 208 : aCRect.Height() * aCRect.Width()) ==
2499 208 : (aTmp.Height() * aTmp.Width()) )
2500 : {
2501 22 : aPrvRect.Union( aCRect );
2502 : }
2503 : else
2504 : {
2505 186 : if ( aPrvRect.HasArea() )
2506 60 : Sub( aRegion, aPrvRect );
2507 186 : aPrvRect = aCRect;
2508 : }
2509 : }
2510 : }
2511 276 : pCntnt = pCntnt->GetNextCntntFrm();
2512 : OSL_ENSURE( pCntnt,
2513 : "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect!" );
2514 : }
2515 270 : if ( aPrvRect.HasArea() )
2516 126 : Sub( aRegion, aPrvRect );
2517 :
2518 : //At least the endframe...
2519 270 : bVert = pEndFrm->IsVertical();
2520 270 : bRev = pEndFrm->IsReverse();
2521 0 : fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
2522 270 : ( bRev ? fnRectB2T : fnRectHori );
2523 270 : nTmpTwips = (aEndRect.*fnRect->fnGetTop)();
2524 270 : if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips )
2525 : {
2526 126 : aSubRect = aEndFrm;
2527 126 : (aSubRect.*fnRect->fnSetBottom)( nTmpTwips );
2528 126 : Sub( aRegion, aSubRect );
2529 : }
2530 270 : aSubRect = aEndRect;
2531 270 : if( bEndR2L )
2532 0 : (aSubRect.*fnRect->fnSetRight)((aEndFrm.*fnRect->fnGetRight)());
2533 : else
2534 270 : (aSubRect.*fnRect->fnSetLeft)( (aEndFrm.*fnRect->fnGetLeft)() );
2535 270 : Sub( aRegion, aSubRect );
2536 : }
2537 :
2538 1502 : aRegion.Invert();
2539 1502 : delete pSt2Pos;
2540 1502 : delete pEnd2Pos;
2541 :
2542 : // Cut out Flys during loop. We don't cut out Flys when:
2543 : // - the Lower is StartFrm/EndFrm (FlyInCnt and all other Flys which again
2544 : // sit in it)
2545 : // - if in the Z-order we have Flys above those in which the StartFrm is
2546 : // placed
2547 : // - if they are anchored to inside the selection and thus part of it
2548 1502 : const SwPageFrm *pPage = pStartFrm->FindPageFrm();
2549 1502 : const SwPageFrm *pEndPage = pEndFrm->FindPageFrm();
2550 :
2551 3018 : while ( pPage )
2552 : {
2553 1516 : if ( pPage->GetSortedObjs() )
2554 : {
2555 0 : const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
2556 0 : for ( size_t i = 0; i < rObjs.size(); ++i )
2557 : {
2558 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
2559 0 : if ( !pAnchoredObj->ISA(SwFlyFrm) )
2560 0 : continue;
2561 0 : const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
2562 0 : const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
2563 0 : const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
2564 0 : const SwPosition* anchoredAt = pAnchoredObj->GetFrmFmt().GetAnchor().GetCntntAnchor();
2565 0 : bool inSelection = ( anchoredAt != NULL && *pStartPos <= *anchoredAt && *anchoredAt < *pEndPos );
2566 0 : if( anchoredAt != NULL && *anchoredAt == *pEndPos )
2567 : {
2568 0 : const SwNodes& nodes = anchoredAt->GetDoc()->GetNodes();
2569 0 : if( *pEndPos == SwPosition( nodes.GetEndOfContent()))
2570 0 : inSelection = true;
2571 : else
2572 : {
2573 0 : SwNodeIndex idx( nodes.GetEndOfContent());
2574 0 : if( SwCntntNode* last = nodes.GoPrevious( &idx ))
2575 0 : inSelection = *pEndPos == SwPosition( *last, last->Len());
2576 : }
2577 : }
2578 0 : if( inSelection )
2579 0 : Add( aRegion, pFly->Frm() );
2580 0 : else if ( !pFly->IsAnLower( pStartFrm ) &&
2581 0 : (rSur.GetSurround() != SURROUND_THROUGHT &&
2582 0 : !rSur.IsContour()) )
2583 : {
2584 0 : if ( aSortObjs.Contains( *pAnchoredObj ) )
2585 0 : continue;
2586 :
2587 0 : bool bSub = true;
2588 0 : const sal_uInt32 nPos = pObj->GetOrdNum();
2589 0 : for ( size_t k = 0; bSub && k < aSortObjs.size(); ++k )
2590 : {
2591 : OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm),
2592 : "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexpected type" );
2593 0 : const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
2594 0 : do
2595 : {
2596 0 : if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
2597 : {
2598 0 : bSub = false;
2599 : }
2600 : else
2601 : {
2602 0 : pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
2603 : }
2604 0 : } while ( bSub && pTmp );
2605 : }
2606 0 : if ( bSub )
2607 0 : Sub( aRegion, pFly->Frm() );
2608 : }
2609 : }
2610 : }
2611 1516 : if ( pPage == pEndPage )
2612 1502 : break;
2613 : else
2614 14 : pPage = (SwPageFrm*)pPage->GetNext();
2615 : }
2616 :
2617 : //Because it looks better, we close the DropCaps.
2618 1502 : SwRect aDropRect;
2619 1502 : if ( pStartFrm->IsTxtFrm() )
2620 : {
2621 1502 : if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
2622 0 : Sub( aRegion, aDropRect );
2623 : }
2624 1502 : if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
2625 : {
2626 270 : if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
2627 0 : Sub( aRegion, aDropRect );
2628 : }
2629 :
2630 3004 : rCrsr.assign( aRegion.begin(), aRegion.end() );
2631 270 : }
2632 :
2633 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|