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