xref: /trunk/main/sw/source/core/layout/trvlfrm.cxx (revision 6e9cccf4)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 #include <hints.hxx>
30 #include <tools/bigint.hxx>
31 #include <editeng/protitem.hxx>
32 #include <vcl/settings.hxx>
33 #include <vcl/outdev.hxx>
34 #include <fmtpdsc.hxx>
35 #include <fmtsrnd.hxx>
36 #include <pagedesc.hxx>
37 #include <pagefrm.hxx>
38 #include <rootfrm.hxx>
39 #include <cntfrm.hxx>
40 #include <ftnfrm.hxx>
41 #include <flyfrm.hxx>
42 #include <tabfrm.hxx>
43 #include <rowfrm.hxx>
44 #include <cellfrm.hxx>
45 #include <txtfrm.hxx>
46 #include <viewsh.hxx>
47 #include <viewopt.hxx>
48 #include <doc.hxx>
49 #include <viscrs.hxx>
50 #include <frmfmt.hxx>
51 #include <swtable.hxx>
52 #include <dflyobj.hxx>
53 #include <crstate.hxx>
54 #include <frmtool.hxx>
55 #include <ndtxt.hxx>
56 // OD 2004-05-24 #i28701#
57 #include <sortedobjs.hxx>
58 
59 // FLT_MAX
60 #include <cfloat>
61 #include <swselectionlist.hxx>
62 
63 //Fuer SwFlyFrm::GetCrsrOfst
64 class SwCrsrOszControl
65 {
66 public:
67 	// damit schon der Compiler die Klasse initialisieren kann, keinen
68 	// DTOR und member als publics:
69 	const SwFlyFrm *pEntry;
70 	const SwFlyFrm *pStk1;
71 	const SwFlyFrm *pStk2;
72 
73 //public:
74 //    SwCrsrOszControl() : pStk1( 0 ), pStk2( 0 ) {}; // ; <- ????
75 
ChkOsz(const SwFlyFrm * pFly)76 	sal_Bool ChkOsz( const SwFlyFrm *pFly )
77 		{
78 			sal_Bool bRet = sal_True;
79 			if ( pFly != pStk1 && pFly != pStk2 )
80 			{
81 				pStk1 = pStk2;
82 				pStk2 = pFly;
83 				bRet  = sal_False;
84 			}
85 			return bRet;
86 		}
Entry(const SwFlyFrm * pFly)87 	void Entry( const SwFlyFrm *pFly )
88 		{
89 			if ( !pEntry )
90 				pEntry = pStk1 = pFly;
91 		}
Exit(const SwFlyFrm * pFly)92 	void Exit( const SwFlyFrm *pFly )
93 		{
94 			if ( pFly == pEntry )
95 				pEntry = pStk1 = pStk2 = 0;
96 		}
97 };
98 
99 static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
100 
101 /*************************************************************************
102 |*
103 |*	SwLayoutFrm::GetCrsrOfst()
104 |*
105 |*	Beschreibung:		Sucht denjenigen CntntFrm, innerhalb dessen
106 |* 						PrtArea der Point liegt.
107 |*	Ersterstellung		MA 20. Jul. 92
108 |*	Letzte Aenderung	MA 23. May. 95
109 |*
110 |*************************************************************************/
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const111 sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
112                                SwCrsrMoveState* pCMS ) const
113 {
114 	sal_Bool bRet = sal_False;
115 	const SwFrm *pFrm = Lower();
116 	while ( !bRet && pFrm )
117     {
118         pFrm->Calc();
119 
120         // --> FME 2005-05-13 #i43742# New function: SW_CONTENT_CHECK
121         const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
122         const SwRect aPaintRect( bCntntCheck ?
123                                  pFrm->UnionFrm() :
124                                  pFrm->PaintArea() );
125         // <--
126 
127         if ( aPaintRect.IsInside( rPoint ) &&
128              ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
129 			bRet = sal_True;
130 		else
131 			pFrm = pFrm->GetNext();
132 		if ( pCMS && pCMS->bStop )
133 			return sal_False;
134 	}
135 	return bRet;
136 }
137 
138 /*************************************************************************
139 |*
140 |*	SwPageFrm::GetCrsrOfst()
141 |*
142 |*	Beschreibung:		Sucht die Seite, innerhalb der der gesuchte Point
143 |*						liegt.
144 |*	Ersterstellung		MA 20. Jul. 92
145 |*	Letzte Aenderung	MA 18. Jul. 96
146 |*
147 |*************************************************************************/
148 
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const149 sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
150                              SwCrsrMoveState* pCMS ) const
151 {
152 	sal_Bool bRet	  = sal_False;
153     Point aPoint( rPoint );
154 
155     // check, if we have to adjust the point
156     if ( !Frm().IsInside( aPoint ) )
157     {
158         aPoint.X() = Max( aPoint.X(), Frm().Left() );
159         aPoint.X() = Min( aPoint.X(), Frm().Right() );
160         aPoint.Y() = Max( aPoint.Y(), Frm().Top() );
161         aPoint.Y() = Min( aPoint.Y(), Frm().Bottom() );
162     }
163 
164     //Koennte ein Freifliegender gemeint sein?
165     //Wenn sein Inhalt geschuetzt werden soll, so ist nix mit Crsr
166 	//hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
167     if ( GetSortedObjs() )
168 	{
169         SwOrderIter aIter( this );
170 		aIter.Top();
171 		while ( aIter() )
172 		{
173             const SwVirtFlyDrawObj* pObj =
174                                 static_cast<const SwVirtFlyDrawObj*>(aIter());
175             const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
176             if ( pFly &&
177                  ( ( pCMS ? pCMS->bSetInReadOnly : sal_False ) ||
178                    !pFly->IsProtected() ) &&
179                  pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
180             {
181                 bRet = sal_True;
182                 break;
183             }
184 
185             if ( pCMS && pCMS->bStop )
186 			    return sal_False;
187             aIter.Prev();
188         }
189     }
190 
191     if ( !bRet )
192     {
193         //Wenn kein Cntnt unterhalb der Seite 'antwortet', so korrigieren
194         //wir den StartPoint und fangen nochmal eine Seite vor der
195         //aktuellen an. Mit Flys ist es dann allerdings vorbei.
196         if ( SwLayoutFrm::GetCrsrOfst( pPos, aPoint, pCMS ) )
197             bRet = sal_True;
198         else
199         {
200             if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
201             {
202                 ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
203                 return sal_False;
204             }
205             const SwCntntFrm *pCnt = GetCntntPos( aPoint, sal_False, sal_False, sal_False, pCMS, sal_False );
206             if ( pCMS && pCMS->bStop )
207                 return sal_False;
208 
209             ASSERT( pCnt, "Crsr is gone to a Black hole" );
210             if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
211                 bRet = pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
212             else
213                 bRet = pCnt->GetCrsrOfst( pPos, aPoint, pCMS );
214 
215             if ( !bRet )
216             {
217                 // Set point to pCnt, delete mark
218                 // this may happen, if pCnt is hidden
219                 *pPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
220                 bRet = sal_True;
221             }
222         }
223     }
224 
225     if ( bRet )
226 		rPoint = aPoint;
227 
228     return bRet;
229 }
230 
FillSelection(SwSelectionList & rList,const SwRect & rRect) const231 bool SwLayoutFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
232 {
233     bool bRet = false;
234     if( rRect.IsOver(PaintArea()) )
235     {
236         const SwFrm* pFrm = Lower();
237         while( pFrm )
238         {
239             pFrm->FillSelection( rList, rRect );
240             pFrm = pFrm->GetNext();
241         }
242     }
243     return bRet;
244 }
245 
FillSelection(SwSelectionList & rList,const SwRect & rRect) const246 bool SwPageFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
247 {
248     bool bRet = false;
249     if( rRect.IsOver(PaintArea()) )
250     {
251         bRet = SwLayoutFrm::FillSelection( rList, rRect );
252 		if( GetSortedObjs() )
253 		{
254             const SwSortedObjs &rObjs = *GetSortedObjs();
255 			for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
256 			{
257                 const SwAnchoredObject* pAnchoredObj = rObjs[i];
258                 if( !pAnchoredObj->ISA(SwFlyFrm) )
259 					continue;
260                 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
261                 if( pFly->FillSelection( rList, rRect ) )
262                     bRet = true;
263             }
264         }
265     }
266     return bRet;
267 }
268 
FillSelection(SwSelectionList & aSelList,const SwRect & rRect) const269 bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
270 {
271 	const SwFrm *pPage = Lower();
272     const long nBottom = rRect.Bottom();
273     while( pPage )
274     {
275         if( pPage->Frm().Top() < nBottom )
276         {
277             if( pPage->Frm().Bottom() > rRect.Top() )
278                 pPage->FillSelection( aSelList, rRect );
279             pPage = pPage->GetNext();
280         }
281         else
282             pPage = 0;
283     }
284     return !aSelList.isEmpty();
285 }
286 
287 /*************************************************************************
288 |*
289 |*	SwRootFrm::GetCrsrOfst()
290 |*
291 |*	Beschreibung:		Reicht Primaer den Aufruf an die erste Seite weiter.
292 |*						Wenn der 'reingereichte Point veraendert wird,
293 |*						so wird sal_False zurueckgegeben.
294 |*	Ersterstellung		MA 01. Jun. 92
295 |*	Letzte Aenderung	MA 30. Nov. 94
296 |*
297 |*************************************************************************/
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const298 sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
299                              SwCrsrMoveState* pCMS ) const
300 {
301     sal_Bool bOldAction = IsCallbackActionEnabled();
302 	((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
303 	ASSERT( (Lower() && Lower()->IsPageFrm()), "Keinen PageFrm gefunden." );
304 	if( pCMS && pCMS->pFill )
305 		((SwCrsrMoveState*)pCMS)->bFillRet = sal_False;
306 	Point aOldPoint = rPoint;
307 
308     // PAGES01
309     // search for page containing rPoint. The borders around the pages are considered
310     const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
311 
312     // --> OD 2008-12-23 #i95626#
313     // special handling for <rPoint> beyond root frames area
314     if ( !pPage &&
315          rPoint.X() > Frm().Right() &&
316          rPoint.Y() > Frm().Bottom() )
317     {
318         pPage = dynamic_cast<const SwPageFrm*>(Lower());
319         while ( pPage && pPage->GetNext() )
320         {
321             pPage = dynamic_cast<const SwPageFrm*>(pPage->GetNext());
322         }
323     }
324     // <--
325     if ( pPage )
326     {
327         pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS );
328     }
329 
330     ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
331 	if( pCMS )
332 	{
333 		if( pCMS->bStop )
334 			return sal_False;
335 		if( pCMS->pFill )
336 			return pCMS->bFillRet;
337 	}
338 	return aOldPoint == rPoint;
339 }
340 
341 /*************************************************************************
342 |*
343 |*	SwCellFrm::GetCrsrOfst()
344 |*
345 |*	Beschreibung		Wenn es sich um eine Cntnt-tragende Cell handelt wird
346 |* 						der Crsr notfalls mit Gewalt in einen der CntntFrms
347 |* 						gesetzt.
348 |* 						In geschuetzte Zellen gibt es hier keinen Eingang.
349 |*	Ersterstellung		MA 04. Jun. 93
350 |*	Letzte Aenderung	MA 23. May. 95
351 |*
352 |*************************************************************************/
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const353 sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
354                              SwCrsrMoveState* pCMS ) const
355 {
356     // cell frame does not necessarily have a lower (split table cell)
357     if ( !Lower() )
358         return sal_False;
359 
360 	if ( !(pCMS?pCMS->bSetInReadOnly:sal_False) &&
361 		 GetFmt()->GetProtect().IsCntntProtected() )
362 		return sal_False;
363 
364 	if ( pCMS && pCMS->eState == MV_TBLSEL )
365 	{
366         const SwTabFrm *pTab = FindTabFrm();
367         if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
368         {
369 			((SwCrsrMoveState*)pCMS)->bStop = sal_True;
370 			return sal_False;
371 		}
372 	}
373 
374     if ( Lower() )
375     {
376 	    if ( Lower()->IsLayoutFrm() )
377 		    return SwLayoutFrm::GetCrsrOfst( pPos, rPoint, pCMS );
378 	    else
379 	    {
380     		Calc();
381 		    sal_Bool bRet = sal_False;
382 
383     		const SwFrm *pFrm = Lower();
384 		    while ( pFrm && !bRet )
385 		    {
386     			pFrm->Calc();
387 			    if ( pFrm->Frm().IsInside( rPoint ) )
388 			    {
389     				bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
390 				    if ( pCMS && pCMS->bStop )
391     					return sal_False;
392 			    }
393 			    pFrm = pFrm->GetNext();
394 		    }
395 		    if ( !bRet )
396 		    {
397     			Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
398 			    const SwCntntFrm *pCnt = GetCntntPos( rPoint, sal_True );
399 			    if( pPoint && pCnt->IsTxtFrm() )
400 			    {
401     				pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
402 				    rPoint = *pPoint;
403 			    }
404 			    else
405     				pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
406 			    delete pPoint;
407 		    }
408 		    return sal_True;
409 	    }
410     }
411 
412     return sal_False;
413 }
414 
415 /*************************************************************************
416 |*
417 |*	SwFlyFrm::GetCrsrOfst()
418 |*
419 |*	Ersterstellung		MA 15. Dec. 92
420 |*	Letzte Aenderung	MA 23. May. 95
421 |*
422 |*************************************************************************/
423 //Problem: Wenn zwei Flys genau gleich gross sind und auf derselben
424 //Position stehen, so liegt jeder innerhalb des anderen.
425 //Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines
426 //anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet
427 //und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer
428 //endlosen Rekursion fuehren.
429 //Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das
430 //GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der
431 //am weitesten oben liegt.
432 
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const433 sal_Bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
434 							SwCrsrMoveState* pCMS ) const
435 {
436 	aOszCtrl.Entry( this );
437 
438 	//Wenn der Point innerhalb des Fly sitzt wollen wir energisch
439 	//versuchen den Crsr hineinzusetzen.
440 	//Wenn der Point allerdings in einem Flys sitzt, der sich vollstaendig
441 	//innerhalb des aktuellen befindet, so wird fuer diesen das
442 	//GetCrsrOfst gerufen.
443 	Calc();
444 	sal_Bool bInside = Frm().IsInside( rPoint ) && Lower(),
445 		 bRet = sal_False;
446 
447 	//Wenn der Frm eine Grafik enthaelt, aber nur Text gewuenscht ist, so
448 	//nimmt er den Crsr grundsaetzlich nicht an.
449 	if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
450 		 (!Lower() || Lower()->IsNoTxtFrm()) )
451 		bInside = sal_False;
452 
453 	const SwPageFrm *pPage = FindPageFrm();
454 	if ( bInside && pPage && pPage->GetSortedObjs() )
455 	{
456 		SwOrderIter aIter( pPage );
457 		aIter.Top();
458 		while ( aIter() && !bRet )
459 		{
460             const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
461             const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
462 			if ( pFly && pFly->Frm().IsInside( rPoint ) &&
463 				 Frm().IsInside( pFly->Frm() ) )
464 			{
465 				if ( aOszCtrl.ChkOsz( pFly ) ||
466 					 sal_True == (bRet = pFly->GetCrsrOfst( pPos, rPoint, pCMS )))
467 					break;
468 				if ( pCMS && pCMS->bStop )
469 					return sal_False;
470 			}
471 			aIter.Next();
472 		}
473 	}
474 
475 	while ( bInside && !bRet )
476 	{
477 		const SwFrm *pFrm = Lower();
478 		while ( pFrm && !bRet )
479 		{
480 			pFrm->Calc();
481 			if ( pFrm->Frm().IsInside( rPoint ) )
482 			{
483 				bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
484 				if ( pCMS && pCMS->bStop )
485 					return sal_False;
486 			}
487 			pFrm = pFrm->GetNext();
488 		}
489 		if ( !bRet )
490 		{
491 			Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
492 			const SwCntntFrm *pCnt = GetCntntPos(
493 											rPoint, sal_True, sal_False, sal_False, pCMS );
494 			if ( pCMS && pCMS->bStop )
495 				return sal_False;
496 			if( pPoint && pCnt->IsTxtFrm() )
497 			{
498 				pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
499 				rPoint = *pPoint;
500 			}
501 			else
502 				pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
503 			delete pPoint;
504 			bRet = sal_True;
505 		}
506 	}
507 	aOszCtrl.Exit( this );
508 	return bRet;
509 }
510 
511 /*************************************************************************
512 |*
513 |*	  Beschreibung		Layoutabhaengiges Cursortravelling
514 |*	  Ersterstellung	MA 23. Jul. 92
515 |*	  Letzte Aenderung	MA 06. Sep. 93
516 |*
517 |*************************************************************************/
LeftMargin(SwPaM * pPam) const518 sal_Bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
519 {
520 	if( pPam->GetNode() != (SwCntntNode*)GetNode() )
521 		return sal_False;
522 	((SwCntntNode*)GetNode())->
523 		MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
524 	return sal_True;
525 }
526 
RightMargin(SwPaM * pPam,sal_Bool) const527 sal_Bool SwCntntFrm::RightMargin(SwPaM *pPam, sal_Bool) const
528 {
529 	if( pPam->GetNode() != (SwCntntNode*)GetNode() )
530 		return sal_False;
531 	((SwCntntNode*)GetNode())->
532 		MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
533 	return sal_True;
534 }
535 
lcl_GetNxtCnt(const SwCntntFrm * pCnt)536 const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
537 {
538 	return pCnt->GetNextCntntFrm();
539 }
540 
lcl_GetPrvCnt(const SwCntntFrm * pCnt)541 const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
542 {
543 	return pCnt->GetPrevCntntFrm();
544 }
545 
546 typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
547 
548 //Frame in wiederholter Headline?
lcl_IsInRepeatedHeadline(const SwFrm * pFrm,const SwTabFrm ** ppTFrm=0)549 sal_Bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
550 									const SwTabFrm** ppTFrm = 0 )
551 {
552 	const SwTabFrm *pTab = pFrm->FindTabFrm();
553 	if( ppTFrm )
554 		*ppTFrm = pTab;
555     return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
556 }
557 
558 
559 //Ueberspringen geschuetzter Tabellenzellen. Optional auch
560 //Ueberspringen von wiederholten Headlines.
561 //MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen.
562 // FME: Skip follow flow cells
lcl_MissProtectedFrames(const SwCntntFrm * pCnt,GetNxtPrvCnt fnNxtPrv,sal_Bool bMissHeadline,sal_Bool bInReadOnly,sal_Bool bMissFollowFlowLine)563 const SwCntntFrm * MA_FASTCALL lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
564 													   GetNxtPrvCnt fnNxtPrv,
565 													   sal_Bool bMissHeadline,
566 													   sal_Bool bInReadOnly,
567                                                        sal_Bool bMissFollowFlowLine )
568 {
569 	if ( pCnt && pCnt->IsInTab() )
570 	{
571 		sal_Bool bProtect = sal_True;
572 		while ( pCnt && bProtect )
573 		{
574 			const SwLayoutFrm *pCell = pCnt->GetUpper();
575 			while ( pCell && !pCell->IsCellFrm() )
576 				pCell = pCell->GetUpper();
577             if ( !pCell ||
578 					( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
579 					  ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
580                       ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
581                         !pCell->IsCoveredCell() ) )
582                 bProtect = sal_False;
583 			else
584 				pCnt = (*fnNxtPrv)( pCnt );
585 		}
586 	}
587 	else if ( !bInReadOnly )
588 		while ( pCnt && pCnt->IsProtected() )
589 			pCnt = (*fnNxtPrv)( pCnt );
590 
591 	return pCnt;
592 }
593 
lcl_UpDown(SwPaM * pPam,const SwCntntFrm * pStart,GetNxtPrvCnt fnNxtPrv,sal_Bool bInReadOnly)594 sal_Bool MA_FASTCALL lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
595 					GetNxtPrvCnt fnNxtPrv, sal_Bool bInReadOnly )
596 {
597 	ASSERT( pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
598 			"lcl_UpDown arbeitet nicht fuer andere." );
599 
600 	const SwCntntFrm *pCnt = 0;
601 
602 	//Wenn gerade eine Tabellenselection laeuft muss ein bischen getricktst
603 	//werden: Beim hochlaufen an den Anfang der Zelle gehen, beim runterlaufen
604 	//an das Ende der Zelle gehen.
605     sal_Bool bTblSel = false;
606 	if ( pStart->IsInTab() &&
607 		pPam->GetNode( sal_True )->StartOfSectionNode() !=
608 		pPam->GetNode( sal_False )->StartOfSectionNode() )
609 	{
610         bTblSel = true;
611 		const SwLayoutFrm  *pCell = pStart->GetUpper();
612 		while ( !pCell->IsCellFrm() )
613 			pCell = pCell->GetUpper();
614 
615         //
616         // Check, if cell has a Prev/Follow cell:
617         //
618         const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
619         const SwLayoutFrm* pTmpCell = bFwd ?
620             ((SwCellFrm*)pCell)->GetFollowCell() :
621             ((SwCellFrm*)pCell)->GetPreviousCell();
622 
623         const SwCntntFrm* pTmpStart = pStart;
624         while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
625         {
626 			pCell = pTmpCell;
627             pTmpCell = bFwd ?
628                 ((SwCellFrm*)pCell)->GetFollowCell() :
629                 ((SwCellFrm*)pCell)->GetPreviousCell();
630         }
631 		const SwCntntFrm *pNxt = pCnt = pTmpStart;
632 
633 		while ( pCell->IsAnLower( pNxt ) )
634 		{
635             pCnt = pNxt;
636 			pNxt = (*fnNxtPrv)( pNxt );
637 		}
638 	}
639 
640 	pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
641 	pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
642 
643 
644 	const SwTabFrm *pStTab = pStart->FindTabFrm();
645     const SwTabFrm *pTable = 0;
646 	const sal_Bool bTab = pStTab || (pCnt && pCnt->IsInTab()) ? sal_True : sal_False;
647 	sal_Bool bEnd = bTab ? sal_False : sal_True;
648 
649     const SwFrm* pVertRefFrm = pStart;
650     if ( bTblSel && pStTab )
651         pVertRefFrm = pStTab;
652     SWRECTFN( pVertRefFrm )
653 
654     SwTwips nX = 0;
655 	if ( bTab )
656 	{
657         //
658         // pStart or pCnt is inside a table. nX will be used for travelling:
659         //
660 		SwRect aRect( pStart->Frm() );
661 		pStart->GetCharRect( aRect, *pPam->GetPoint() );
662         Point aCenter = aRect.Center();
663         nX = bVert ? aCenter.Y() : aCenter.X();
664 
665 		pTable = pCnt ? pCnt->FindTabFrm() : 0;
666 		if ( !pTable )
667 			pTable = pStTab;
668 
669 		if ( pStTab &&
670             !pStTab->GetUpper()->IsInTab() &&
671             !pTable->GetUpper()->IsInTab() )
672 		{
673 			const SwFrm *pCell = pStart->GetUpper();
674 			while ( pCell && !pCell->IsCellFrm() )
675 				pCell = pCell->GetUpper();
676 			ASSERT( pCell, "Zelle nicht gefunden." );
677 			nX =  (pCell->Frm().*fnRect->fnGetLeft)() +
678 				  (pCell->Frm().*fnRect->fnGetWidth)() / 2;
679 
680             //Der Fluss fuehrt von einer Tabelle in die nachste. Der X-Wert
681 			//muss ausgehend von der Mitte der Startzelle um die Verschiebung
682 			//der Tabellen korrigiert werden.
683             if ( pStTab != pTable )
684             {
685 			    nX += (pTable->Frm().*fnRect->fnGetLeft)() -
686                       (pStTab->Frm().*fnRect->fnGetLeft)();
687             }
688 		}
689 
690         //
691         // Restrict nX to the left and right borders of pTab:
692         // (is this really necessary?)
693         //
694         if ( !pTable->GetUpper()->IsInTab() )
695         {
696     		const sal_Bool bRTL = pTable->IsRightToLeft();
697             const long nPrtLeft = bRTL ?
698                                 (pTable->*fnRect->fnGetPrtRight)() :
699 							    (pTable->*fnRect->fnGetPrtLeft)();
700 		    if ( (bRTL != (nX < nPrtLeft)) )
701     			nX = nPrtLeft;
702 		    else
703 		    {
704        			const long nPrtRight = bRTL ?
705                                     (pTable->*fnRect->fnGetPrtLeft)() :
706                                     (pTable->*fnRect->fnGetPrtRight)();
707                 if ( (bRTL != (nX > nPrtRight)) )
708         		    nX = nPrtRight;
709 		    }
710         }
711     }
712 
713     do
714 	{
715 		//Wenn ich im DokumentBody bin, so will ich da auch bleiben
716 		if ( pStart->IsInDocBody() )
717         {
718 			while ( pCnt && (!pCnt->IsInDocBody() ||
719 							 (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
720 			{
721 				pCnt = (*fnNxtPrv)( pCnt );
722 				pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
723 			}
724         }
725 
726 		//Wenn ich im Fussnotenbereich bin, so versuche ich notfalls den naechsten
727 		//Fussnotenbereich zu erreichen.
728 		else if ( pStart->IsInFtn() )
729         {
730             while ( pCnt && (!pCnt->IsInFtn() ||
731                             (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
732             {
733 				pCnt = (*fnNxtPrv)( pCnt );
734 				pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
735 			}
736         }
737 
738 		//In Flys kann es Blind weitergehen solange ein Cntnt
739 		//gefunden wird.
740 		else if ( pStart->IsInFly() )
741 		{
742 			if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
743 			{
744 				pCnt = (*fnNxtPrv)( pCnt );
745 				pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
746 			}
747 		}
748 
749 		//Andernfalls weigere ich mich einfach den derzeitigen Bereich zu
750 		//verlassen.
751 		else if ( pCnt )
752 		{
753 			const SwFrm *pUp = pStart->GetUpper();				 //Head/Foot
754 			while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
755 				pUp = pUp->GetUpper();
756 			sal_Bool bSame = sal_False;
757 			const SwFrm *pCntUp = pCnt->GetUpper();
758 			while ( pCntUp && !bSame )
759 			{	if ( pUp == pCntUp )
760 					bSame = sal_True;
761 				else
762 					pCntUp = pCntUp->GetUpper();
763 			}
764 			if ( !bSame )
765 				pCnt = 0;
766             else if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
767             {
768                 pCnt = (*fnNxtPrv)( pCnt );
769                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
770             }
771         }
772 
773 		if ( bTab )
774 		{
775 			if ( !pCnt )
776 				bEnd = sal_True;
777 			else
778 			{	const SwTabFrm *pTab = pCnt->FindTabFrm();
779 				if( !pTab )
780 					bEnd = sal_True;
781 				else
782 				{
783 					if ( pTab != pTable )
784 					{
785                         //Der Fluss fuehrt von einer Tabelle in die nachste. Der
786 						//X-Wert muss um die Verschiebung der Tabellen korrigiert
787 						//werden.
788  						if ( pTable &&
789                               !pTab->GetUpper()->IsInTab() &&
790                             !pTable->GetUpper()->IsInTab() )
791 							nX += pTab->Frm().Left() - pTable->Frm().Left();
792 						pTable = pTab;
793 					}
794 					const SwLayoutFrm *pCell = pTable ? pCnt->GetUpper() : 0;
795 					while ( pCell && !pCell->IsCellFrm() )
796 						pCell = pCell->GetUpper();
797 
798                     Point aInsideCell;
799                     Point aInsideCnt;
800                     if ( pCell )
801                     {
802                         long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
803                         if ( bVert )
804                         {
805                             if ( nTmpTop )
806                                 --nTmpTop;
807 
808                             aInsideCell = Point( nTmpTop, nX );
809                         }
810                         else
811                             aInsideCell = Point( nX, nTmpTop );
812                     }
813 
814                     long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
815                     if ( bVert )
816                     {
817                         if ( nTmpTop )
818                             --nTmpTop;
819 
820                         aInsideCnt = Point( nTmpTop, nX );
821                     }
822                     else
823                         aInsideCnt = Point( nX, nTmpTop );
824 
825 					if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
826 					{
827 						bEnd = sal_True;
828 						//Jetzt noch schnell den richtigen Cntnt in der Zelle
829 						//greifen.
830 						if ( !pCnt->Frm().IsInside( aInsideCnt ) )
831 						{
832 							pCnt = pCell->ContainsCntnt();
833 							if ( fnNxtPrv == lcl_GetPrvCnt )
834 								while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
835 									pCnt = pCnt->GetNextCntntFrm();
836 						}
837 					}
838 					else if ( pCnt->Frm().IsInside( aInsideCnt ) )
839 						bEnd = sal_True;
840 				}
841 			}
842 			if ( !bEnd )
843 			{
844 				pCnt = (*fnNxtPrv)( pCnt );
845 				pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
846 			}
847 		}
848 
849 	} while ( !bEnd ||
850 			  (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
851 
852 	if( pCnt )
853 	{	// setze den Point auf den Content-Node
854 		SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
855 		pPam->GetPoint()->nNode = *pCNd;
856 		if ( fnNxtPrv == lcl_GetPrvCnt )
857 			pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
858 		else
859 			pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
860 		return sal_True;
861 	}
862 	return sal_False;
863 }
864 
UnitUp(SwPaM * pPam,const SwTwips,sal_Bool bInReadOnly) const865 sal_Bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
866 {
867 	return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
868 }
869 
UnitDown(SwPaM * pPam,const SwTwips,sal_Bool bInReadOnly) const870 sal_Bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
871 {
872 	return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
873 }
874 
875 /*************************************************************************
876 |*
877 |*	SwRootFrm::GetCurrPage()
878 |*
879 |*	Beschreibung:		Liefert die Nummer der aktuellen Seite.
880 |*			Wenn die Methode einen PaM bekommt, so ist die aktuelle Seite
881 |*			diejenige in der der PaM sitzt. Anderfalls ist die aktuelle
882 |*			Seite die erste Seite innerhalb der VisibleArea.
883 |*			Es wird nur auf den vorhandenen Seiten gearbeitet!
884 |*	Ersterstellung		MA 20. May. 92
885 |*	Letzte Aenderung	MA 09. Oct. 97
886 |*
887 |*************************************************************************/
GetCurrPage(const SwPaM * pActualCrsr) const888 sal_uInt16 SwRootFrm::GetCurrPage( const SwPaM *pActualCrsr ) const
889 {
890 	ASSERT( pActualCrsr, "Welche Seite soll's denn sein?" );
891     SwFrm const*const pActFrm = pActualCrsr->GetPoint()->nNode.GetNode().
892 									GetCntntNode()->getLayoutFrm( this, 0,
893 													pActualCrsr->GetPoint(),
894 													sal_False );
895 	return pActFrm->FindPageFrm()->GetPhyPageNum();
896 }
897 
898 /*************************************************************************
899 |*
900 |*	SwRootFrm::SetCurrPage()
901 |*
902 |*	Beschreibung:		Liefert einen PaM der am Anfang der gewuenschten
903 |*			Seite sitzt.
904 |*			Formatiert wird soweit notwendig
905 |*			Liefert Null, wenn die Operation nicht moeglich ist.
906 |*			Der PaM sitzt in der letzten Seite, wenn die Seitenzahl zu gross
907 |*			gewaehlt wurde.
908 |*	Ersterstellung		MA 20. May. 92
909 |*	Letzte Aenderung	MA 09. Oct. 97
910 |*
911 |*************************************************************************/
SetCurrPage(SwCursor * pToSet,sal_uInt16 nPageNum)912 sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
913 {
914 	ASSERT( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
915 
916 	SwPageFrm *pPage = (SwPageFrm*)Lower();
917 	sal_Bool bEnd =sal_False;
918 	while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
919 	{	if ( pPage->GetNext() )
920 			pPage = (SwPageFrm*)pPage->GetNext();
921 		else
922 		{	//Ersten CntntFrm Suchen, und solange Formatieren bis
923 			//eine neue Seite angefangen wird oder bis die CntntFrm's alle
924 			//sind.
925 			const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
926 			while ( pCntnt && pPage->IsAnLower( pCntnt ) )
927             {
928                 pCntnt->Calc();
929 				pCntnt = pCntnt->GetNextCntntFrm();
930 			}
931 			//Jetzt ist entweder eine neue Seite da, oder die letzte Seite
932 			//ist gefunden.
933 			if ( pPage->GetNext() )
934 				pPage = (SwPageFrm*)pPage->GetNext();
935 			else
936 				bEnd = sal_True;
937 		}
938 	}
939 	//pPage zeigt jetzt auf die 'gewuenschte' Seite. Jetzt muss noch der
940 	//PaM auf den Anfang des ersten CntntFrm im Body-Text erzeugt werden.
941 	//Wenn es sich um eine Fussnotenseite handelt, wird der PaM in die erste
942 	//Fussnote gesetzt.
943 	const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
944 	if ( pPage->IsFtnPage() )
945 		while ( pCntnt && !pCntnt->IsInFtn() )
946 			pCntnt = pCntnt->GetNextCntntFrm();
947 	else
948 		while ( pCntnt && !pCntnt->IsInDocBody() )
949 			pCntnt = pCntnt->GetNextCntntFrm();
950 	if ( pCntnt )
951 	{
952 		SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
953 		pToSet->GetPoint()->nNode = *pCNd;
954 		pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
955 		pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
956 
957         SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
958 		if( pSCrsr )
959 		{
960 			Point &rPt = pSCrsr->GetPtPos();
961 			rPt = pCntnt->Frm().Pos();
962 			rPt += pCntnt->Prt().Pos();
963 		}
964 		return pPage->GetPhyPageNum();
965 	}
966 	return 0;
967 }
968 
969 /*************************************************************************
970 |*
971 |*	  SwCntntFrm::StartxxPage(), EndxxPage()
972 |*
973 |*	  Beschreibung		Cursor an Anfang/Ende der aktuellen/vorherigen/
974 |*		naechsten Seite. Alle sechs Methoden rufen GetFrmInPage() mit der
975 |*		entsprechenden Parametrisierung.
976 |*		Zwei Parameter steuern die Richtung: einer bestimmt die Seite, der
977 |*		andere Anfang/Ende.
978 |*		Fuer die Bestimmung der Seite und des Cntnt (Anfang/Ende) werden
979 |*		die im folgenden definierten Funktionen benutzt.
980 |*	  Ersterstellung	MA 15. Oct. 92
981 |*	  Letzte Aenderung	MA 28. Feb. 93
982 |*
983 |*************************************************************************/
GetFirstSub(const SwLayoutFrm * pLayout)984 SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
985 {
986 	return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
987 }
988 
GetLastSub(const SwLayoutFrm * pLayout)989 SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
990 {
991 	return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
992 }
993 
GetNextFrm(const SwLayoutFrm * pFrm)994 SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
995 {
996 	SwLayoutFrm *pNext =
997 	    (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
998 											(SwLayoutFrm*)pFrm->GetNext() : 0;
999     // #i39402# in case of an empty page
1000     if(pNext && !pNext->ContainsCntnt())
1001         pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
1002 											(SwLayoutFrm*)pNext->GetNext() : 0;
1003     return pNext;
1004 }
1005 
GetThisFrm(const SwLayoutFrm * pFrm)1006 SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
1007 {
1008 	return (SwLayoutFrm*)pFrm;
1009 }
1010 
GetPrevFrm(const SwLayoutFrm * pFrm)1011 SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
1012 {
1013 	SwLayoutFrm *pPrev =
1014 	    (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
1015 											(SwLayoutFrm*)pFrm->GetPrev() : 0;
1016     // #i39402# in case of an empty page
1017     if(pPrev && !pPrev->ContainsCntnt())
1018         pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
1019 											(SwLayoutFrm*)pPrev->GetPrev() : 0;
1020     return pPrev;
1021 }
1022 
1023 //Jetzt koennen auch die Funktionspointer initialisiert werden;
1024 //sie sind in cshtyp.hxx declariert.
1025 SwPosPage fnPageStart = GetFirstSub;
1026 SwPosPage fnPageEnd = GetLastSub;
1027 SwWhichPage fnPagePrev = GetPrevFrm;
1028 SwWhichPage fnPageCurr = GetThisFrm;
1029 SwWhichPage fnPageNext = GetNextFrm;
1030 
1031 //Liefert den ersten/den letzten Contentframe (gesteuert ueber
1032 //den Parameter fnPosPage) in der
1033 //aktuellen/vorhergehenden/folgenden Seite (gesteuert durch den
1034 //Parameter fnWhichPage).
GetFrmInPage(const SwCntntFrm * pCnt,SwWhichPage fnWhichPage,SwPosPage fnPosPage,SwPaM * pPam)1035 sal_Bool GetFrmInPage( const SwCntntFrm *pCnt, SwWhichPage fnWhichPage,
1036 				   SwPosPage fnPosPage, SwPaM *pPam )
1037 {
1038 	//Erstmal die gewuenschte Seite besorgen, anfangs die aktuelle, dann
1039 	//die die per fnWichPage gewuenscht wurde
1040 	const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
1041 	if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
1042 		return sal_False;
1043 
1044 	//Jetzt den gewuenschen CntntFrm unterhalb der Seite
1045 	if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
1046 		return sal_False;
1047 	else
1048 	{
1049         // repeated headlines in tables
1050         if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
1051         {
1052             const SwTabFrm* pTab = pCnt->FindTabFrm();
1053             if ( pTab->IsFollow() )
1054             {
1055                 if ( pTab->IsInHeadline( *pCnt ) )
1056                 {
1057                     SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
1058                     if ( pRow )
1059                     {
1060                         // We are in the first line of a follow table
1061                         // with repeated headings.
1062                         // To actually make a "real" move we take the first content
1063                         // of the next row
1064                         pCnt = pRow->ContainsCntnt();
1065                         if ( ! pCnt )
1066                             return sal_False;
1067                     }
1068                 }
1069             }
1070         }
1071 
1072 		SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
1073 		pPam->GetPoint()->nNode = *pCNd;
1074 		xub_StrLen nIdx;
1075 		if( fnPosPage == GetFirstSub )
1076 			nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
1077 		else
1078 			nIdx = pCnt->GetFollow() ?
1079 					((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
1080 		pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
1081 		return sal_True;
1082 	}
1083 }
1084 
1085 /*************************************************************************
1086 |*
1087 |*	SwLayoutFrm::GetCntntPos()
1088 |*
1089 |*	Beschreibung		Es wird der nachstliegende Cntnt zum uebergebenen
1090 |* 						gesucht. Betrachtet werden die vorhergehende, die
1091 |* 						aktuelle und die folgende Seite.
1092 |* 						Wenn kein Inhalt gefunden wird, so wird der Bereich
1093  * 						erweitert bis einer gefunden wird.
1094 |* 						Zurueckgegeben wird die 'Semantisch richtige' Position
1095 |* 						innerhalb der PrtArea des gefundenen CntntFrm
1096 |*	Ersterstellung		MA 15. Jul. 92
1097 |*	Letzte Aenderung	MA 09. Jan. 97
1098 |*
1099 |*************************************************************************/
CalcDiff(const Point & rPt1,const Point & rPt2)1100 sal_uLong CalcDiff( const Point &rPt1, const Point &rPt2 )
1101 {
1102 	//Jetzt die Entfernung zwischen den beiden Punkten berechnen.
1103 	//'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
1104 	sal_uInt32 dX = Max( rPt1.X(), rPt2.X() ) -
1105 			   Min( rPt1.X(), rPt2.X() ),
1106 		  dY = Max( rPt1.Y(), rPt2.Y() ) -
1107 			   Min( rPt1.Y(), rPt2.Y() );
1108 	BigInt dX1( dX ), dY1( dY );
1109 	dX1 *= dX1; dY1 *= dY1;
1110 	return ::SqRt( dX1 + dY1 );
1111 }
1112 
1113 // lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem
1114 // auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang
1115 // Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer.
1116 // Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt,
1117 // eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn
1118 // dessen Abstand zum Punkt geringer ist.
1119 
lcl_Inside(const SwCntntFrm * pCnt,Point & rPt)1120 const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
1121 {
1122 	const SwLayoutFrm* pUp = pCnt->GetUpper();
1123 	while( pUp )
1124 	{
1125 		if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
1126 		{
1127 			if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
1128 				return pUp;
1129 			return NULL;
1130 		}
1131 		if( pUp->IsFtnContFrm() )
1132 			return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
1133 		pUp = pUp->GetUpper();
1134 	}
1135 	return NULL;
1136 }
1137 
GetCntntPos(Point & rPoint,const sal_Bool bDontLeave,const sal_Bool bBodyOnly,const sal_Bool bCalc,const SwCrsrMoveState * pCMS,const sal_Bool bDefaultExpand) const1138 const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint,
1139 											const sal_Bool bDontLeave,
1140 											const sal_Bool bBodyOnly,
1141 											const sal_Bool bCalc,
1142 											const SwCrsrMoveState *pCMS,
1143 											const sal_Bool bDefaultExpand ) const
1144 {
1145 	//Ersten CntntFrm ermitteln.
1146 	const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
1147 									(SwLayoutFrm*)GetPrev() : this;
1148 	const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
1149 
1150 	if ( !pCntnt && (GetPrev() && !bDontLeave) )
1151 		pCntnt = ContainsCntnt();
1152 
1153 	if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
1154 		while ( pCntnt && !pCntnt->IsInDocBody() )
1155 			pCntnt = pCntnt->GetNextCntntFrm();
1156 
1157 	const SwCntntFrm *pActual= pCntnt;
1158 	const SwLayoutFrm *pInside = NULL;
1159 	sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
1160 	Point aPoint = rPoint;
1161 	sal_uLong nDistance = ULONG_MAX;
1162 
1163 	while ( sal_True ) 	//Sicherheitsschleifchen, damit immer einer gefunden wird.
1164 	{
1165 		while ( pCntnt &&
1166 				((!bDontLeave || IsAnLower( pCntnt )) &&
1167 				(pCntnt->GetPhyPageNum() <= nMaxPage)) )
1168 		{
1169 			if ( ( bCalc || pCntnt->Frm().Width() ) &&
1170 				 ( !bBodyOnly || pCntnt->IsInDocBody() ) )
1171 			{
1172 				//Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section)
1173 				//liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht.
1174 				const SwCntntFrm *pComp = pCntnt;
1175 				pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, sal_False,
1176 										pCMS ? pCMS->bSetInReadOnly : sal_False, sal_False );
1177 				if ( pComp != pCntnt )
1178 					continue;
1179 
1180 				if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
1181 				{
1182 					if ( bCalc )
1183 						pCntnt->Calc();
1184 
1185 					SwRect aCntFrm( pCntnt->UnionFrm() );
1186 					if ( aCntFrm.IsInside( rPoint ) )
1187 					{
1188 						pActual = pCntnt;
1189 						aPoint = rPoint;
1190 						break;
1191 					}
1192 					//Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird
1193 					//jetzt berechnet.
1194 					Point aCntntPoint( rPoint );
1195 
1196 					//Erst die Vertikale Position einstellen
1197 					if ( aCntFrm.Top() > aCntntPoint.Y() )
1198 						aCntntPoint.Y() = aCntFrm.Top();
1199 					else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
1200 						aCntntPoint.Y() = aCntFrm.Bottom();
1201 
1202 					//Jetzt die Horizontale Position
1203 					if ( aCntFrm.Left() > aCntntPoint.X() )
1204 						aCntntPoint.X() = aCntFrm.Left();
1205 					else if ( aCntFrm.Right() < aCntntPoint.X() )
1206 						aCntntPoint.X() = aCntFrm.Right();
1207 
1208 					// pInside ist ein Seitenbereich, in dem der Punkt liegt,
1209 					// sobald pInside!=0 ist, werden nur noch Frames akzeptiert,
1210 					// die innerhalb liegen.
1211 					if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
1212 						( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
1213 					{
1214 						const sal_uLong nDiff = ::CalcDiff( aCntntPoint, rPoint );
1215 						sal_Bool bBetter = nDiff < nDistance;  // Dichter dran
1216 						if( !pInside )
1217 						{
1218 							pInside = lcl_Inside( pCntnt, rPoint );
1219 							if( pInside )  // Im "richtigen" Seitenteil
1220 								bBetter = sal_True;
1221 						}
1222 						if( bBetter )
1223 						{
1224 							aPoint = aCntntPoint;
1225 							nDistance = nDiff;
1226 							pActual = pCntnt;
1227 						}
1228 					}
1229 				}
1230 			}
1231 			pCntnt = pCntnt->GetNextCntntFrm();
1232 			if ( bBodyOnly )
1233 				while ( pCntnt && !pCntnt->IsInDocBody() )
1234 					pCntnt = pCntnt->GetNextCntntFrm();
1235 		}
1236 		if ( !pActual )
1237 		{	//Wenn noch keiner gefunden wurde muss der Suchbereich erweitert
1238 			//werden, irgenwann muessen wir einen Finden!
1239 			//MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im
1240 			//Body suchen, koennen wir den Suchbereich gleich in einem
1241 			//Schritt hinreichend erweitern.
1242 			if ( bBodyOnly )
1243 			{
1244 				while ( !pCntnt && pStart->GetPrev() )
1245 				{
1246 					++nMaxPage;
1247 					if( !pStart->GetPrev()->IsLayoutFrm() )
1248 						return 0;
1249 					pStart = (SwLayoutFrm*)pStart->GetPrev();
1250 					pCntnt = pStart->IsInDocBody()
1251 								? pStart->ContainsCntnt()
1252 								: pStart->FindPageFrm()->FindFirstBodyCntnt();
1253 				}
1254 				if ( !pCntnt )	//irgendwann muessen wir mit irgendeinem Anfangen!
1255 				{
1256 					pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1257 					while ( pCntnt && !pCntnt->IsInDocBody() )
1258 						pCntnt = pCntnt->GetNextCntntFrm();
1259 					if ( !pCntnt )
1260 						return 0;	//Es gibt noch keine Dokumentinhalt!
1261 				}
1262 			}
1263 			else
1264 			{
1265 				++nMaxPage;
1266 				if ( pStart->GetPrev() )
1267 				{
1268 					if( !pStart->GetPrev()->IsLayoutFrm() )
1269 						return 0;
1270 					pStart = (SwLayoutFrm*)pStart->GetPrev();
1271 					pCntnt = pStart->ContainsCntnt();
1272 				}
1273 				else //irgendwann muessen wir mit irgendeinem Anfangen!
1274 					pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1275 			}
1276 			pActual = pCntnt;
1277 		}
1278 		else
1279 			break;
1280 	}
1281 
1282 #ifdef DBG_UTIL
1283 	ASSERT( pActual, "Keinen Cntnt gefunden." );
1284 	if ( bBodyOnly )
1285 		ASSERT( pActual->IsInDocBody(), "Cnt nicht im Body." );
1286 #endif
1287 
1288 	//Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte
1289 	//TblHedlines.
1290 	if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL )
1291 	{
1292         const SwTabFrm *pTab = pActual->FindTabFrm();
1293         if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
1294         {
1295             ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
1296             return 0;
1297         }
1298     }
1299 
1300 	//Jetzt noch eine kleine Korrektur beim ersten/letzten
1301 	Size aActualSize( pActual->Prt().SSize() );
1302 	if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
1303 		aActualSize.Height() = pActual->GetUpper()->Prt().Height();
1304 
1305     SWRECTFN( pActual )
1306 	if ( !pActual->GetPrev() &&
1307 		 (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
1308                               bVert ? rPoint.X() : rPoint.Y() ) > 0 )
1309     {
1310         aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
1311         aPoint.X() = pActual->Frm().Left() +
1312                         ( pActual->IsRightToLeft() || bVert ?
1313                           pActual->Prt().Right() :
1314                           pActual->Prt().Left() );
1315     }
1316 	else if ( !pActual->GetNext() &&
1317               (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
1318                                    bVert ? rPoint.X() : rPoint.Y() ) < 0 )
1319     {
1320         aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
1321         aPoint.X() = pActual->Frm().Left() +
1322                         ( pActual->IsRightToLeft() || bVert ?
1323                           pActual->Prt().Left() :
1324                           pActual->Prt().Right() );
1325 	}
1326 
1327 	//Und den Point in die PrtArea bringen
1328 	if ( bCalc )
1329 		pActual->Calc();
1330 	const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
1331 						aActualSize );
1332 	if ( aPoint.Y() < aRect.Top() )
1333 		aPoint.Y() = aRect.Top();
1334 	else if ( aPoint.Y() > aRect.Bottom() )
1335 		aPoint.Y() = aRect.Bottom();
1336 	if ( aPoint.X() < aRect.Left() )
1337 		aPoint.X() = aRect.Left();
1338 	else if ( aPoint.X() > aRect.Right() )
1339 		aPoint.X() = aRect.Right();
1340 	rPoint = aPoint;
1341 	return pActual;
1342 }
1343 
1344 /*************************************************************************
1345 |*
1346 |*	SwPageFrm::GetCntntPosition()
1347 |*
1348 |*	Beschreibung		Analog zu SwLayoutFrm::GetCntntPos().
1349 |* 						Spezialisiert fuer Felder in Rahmen.
1350 |*
1351 |*	Ersterstellung		MA 22. Mar. 95
1352 |*	Letzte Aenderung	MA 07. Nov. 95
1353 |*
1354 |*************************************************************************/
GetCntntPosition(const Point & rPt,SwPosition & rPos) const1355 void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
1356 {
1357 	//Ersten CntntFrm ermitteln.
1358 	const SwCntntFrm *pCntnt = ContainsCntnt();
1359 	if ( pCntnt )
1360 	{
1361 		//Einen weiter zurueck schauen (falls moeglich).
1362 		const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
1363 		while ( pTmp && !pTmp->IsInDocBody() )
1364 			pTmp = pTmp->GetPrevCntntFrm();
1365 		if ( pTmp )
1366 			pCntnt = pTmp;
1367 	}
1368 	else
1369 		pCntnt = GetUpper()->ContainsCntnt();
1370 
1371 	const SwCntntFrm *pAct = pCntnt;
1372 	Point aAct 		 = rPt;
1373 	sal_uLong nDist		 = ULONG_MAX;
1374 
1375 	while ( pCntnt )
1376 	{
1377 		SwRect aCntFrm( pCntnt->UnionFrm() );
1378 		if ( aCntFrm.IsInside( rPt ) )
1379 		{
1380 			//dichter gehts nimmer.
1381 			pAct = pCntnt;
1382 			break;
1383 		}
1384 
1385 		//Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen.
1386 		Point aPoint( rPt );
1387 
1388 		//Erst die vertikale Position einstellen
1389 		if ( aCntFrm.Top() > rPt.Y() )
1390 			aPoint.Y() = aCntFrm.Top();
1391 		else if ( aCntFrm.Bottom() < rPt.Y() )
1392 			aPoint.Y() = aCntFrm.Bottom();
1393 
1394 		//Jetzt die horizontale Position
1395 		if ( aCntFrm.Left() > rPt.X() )
1396 			aPoint.X() = aCntFrm.Left();
1397 		else if ( aCntFrm.Right() < rPt.X() )
1398 			aPoint.X() = aCntFrm.Right();
1399 
1400 		const sal_uLong nDiff = ::CalcDiff( aPoint, rPt );
1401 		if ( nDiff < nDist )
1402 		{
1403 			aAct	= aPoint;
1404 			nDist	= nDiff;
1405 			pAct	= pCntnt;
1406 		}
1407 		else if ( aCntFrm.Top() > Frm().Bottom() )
1408 			//Dichter wirds im Sinne der Felder nicht mehr!
1409 			break;
1410 
1411 		pCntnt = pCntnt->GetNextCntntFrm();
1412 		while ( pCntnt && !pCntnt->IsInDocBody() )
1413 			pCntnt = pCntnt->GetNextCntntFrm();
1414 	}
1415 
1416 	//Und den Point in die PrtArea bringen
1417 	const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() );
1418 	if ( aAct.Y() < aRect.Top() )
1419 		aAct.Y() = aRect.Top();
1420 	else if ( aAct.Y() > aRect.Bottom() )
1421 		aAct.Y() = aRect.Bottom();
1422 	if ( aAct.X() < aRect.Left() )
1423 		aAct.X() = aRect.Left();
1424 	else if ( aAct.X() > aRect.Right() )
1425 		aAct.X() = aRect.Right();
1426 
1427 	if( !pAct->IsValid() )
1428 	{
1429 		// CntntFrm nicht formatiert -> immer auf Node-Anfang
1430 		SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
1431 		ASSERT( pCNd, "Wo ist mein CntntNode?" );
1432 		rPos.nNode = *pCNd;
1433 		rPos.nContent.Assign( pCNd, 0 );
1434 	}
1435 	else
1436 	{
1437 		SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
1438 		pAct->GetCrsrOfst( &rPos, aAct, &aTmpState );
1439 	}
1440 }
1441 
1442 /*************************************************************************
1443 |*
1444 |*	SwRootFrm::GetNextPrevCntntPos()
1445 |*
1446 |*	Beschreibung		Es wird der naechstliegende Cntnt zum uebergebenen
1447 |* 						Point gesucht. Es wird nur im BodyText gesucht.
1448 |*	Ersterstellung		MA 15. Jul. 92
1449 |*	Letzte Aenderung	JP 11.10.2001
1450 |*
1451 |*************************************************************************/
1452 
1453 // --> OD 2005-05-25 #123110# - helper class to disable creation of an action
1454 // by a callback event - e.g., change event from a drawing object
1455 class DisableCallbackAction
1456 {
1457     private:
1458         SwRootFrm& mrRootFrm;
1459         sal_Bool mbOldCallbackActionState;
1460 
1461     public:
DisableCallbackAction(const SwRootFrm & _rRootFrm)1462         DisableCallbackAction( const SwRootFrm& _rRootFrm ) :
1463             mrRootFrm( const_cast<SwRootFrm&>(_rRootFrm) ),
1464             mbOldCallbackActionState( _rRootFrm.IsCallbackActionEnabled() )
1465         {
1466             mrRootFrm.SetCallbackActionEnabled( sal_False );
1467         }
1468 
~DisableCallbackAction()1469         ~DisableCallbackAction()
1470         {
1471             mrRootFrm.SetCallbackActionEnabled( mbOldCallbackActionState );
1472         }
1473 };
1474 // <--
1475 
1476 //!!!!! Es wird nur der vertikal naechstliegende gesucht.
1477 //JP 11.10.2001: only in tables we try to find the right column - Bug 72294
GetNextPrevCntntPos(const Point & rPoint,sal_Bool bNext) const1478 Point SwRootFrm::GetNextPrevCntntPos( const Point& rPoint, sal_Bool bNext ) const
1479 {
1480     // --> OD 2005-05-25 #123110# - disable creation of an action by a callback
1481     // event during processing of this method. Needed because formatting is
1482     // triggered by this method.
1483     DisableCallbackAction aDisableCallbackAction( *this );
1484     // <--
1485 	//Ersten CntntFrm und seinen Nachfolger im Body-Bereich suchen
1486 	//Damit wir uns nicht tot suchen (und vor allem nicht zuviel formatieren)
1487 	//gehen wir schon mal von der richtigen Seite aus.
1488 	SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
1489     if( pPage )
1490         while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
1491             pPage = (SwLayoutFrm*)pPage->GetNext();
1492 
1493 	const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
1494 	while ( pCnt && !pCnt->IsInDocBody() )
1495 		pCnt = pCnt->GetNextCntntFrm();
1496 
1497 	if ( !pCnt )
1498 		return Point( 0, 0 );
1499 
1500 	pCnt->Calc();
1501 	if( !bNext )
1502 	{
1503 		// Solange der Point vor dem ersten CntntFrm liegt und es noch
1504 		// vorhergehende Seiten gibt gehe ich jeweils eine Seite nach vorn.
1505 		while ( rPoint.Y() < pCnt->Frm().Top() && pPage->GetPrev() )
1506 		{
1507 			pPage = (SwLayoutFrm*)pPage->GetPrev();
1508 			pCnt = pPage->ContainsCntnt();
1509 			while ( !pCnt )
1510 			{
1511 				pPage = (SwLayoutFrm*)pPage->GetPrev();
1512 				if ( pPage )
1513 					pCnt = pPage->ContainsCntnt();
1514 				else
1515 					return ContainsCntnt()->UnionFrm().Pos();
1516 			}
1517 			pCnt->Calc();
1518 		}
1519 	}
1520 
1521 	//Liegt der Point ueber dem ersten CntntFrm?
1522 	if ( rPoint.Y() < pCnt->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
1523 		return pCnt->UnionFrm().Pos();
1524 
1525 	while ( pCnt )
1526 	{
1527 		//Liegt der Point im aktuellen CntntFrm?
1528 		SwRect aCntFrm( pCnt->UnionFrm() );
1529 		if ( aCntFrm.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
1530 			return rPoint;
1531 
1532 		//Ist der aktuelle der letzte CntntFrm? ||
1533 		//Wenn der naechste CntntFrm hinter dem Point liegt, ist der
1534 		//aktuelle der gesuchte.
1535 		const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1536 		while ( pNxt && !pNxt->IsInDocBody() )
1537 			pNxt = pNxt->GetNextCntntFrm();
1538 
1539 		//Liegt der Point hinter dem letzten CntntFrm?
1540 		if ( !pNxt )
1541 			return Point( aCntFrm.Right(), aCntFrm.Bottom() );
1542 
1543 		//Wenn der naechste CntntFrm hinter dem Point liegt ist er der
1544 		//gesuchte.
1545 		const SwTabFrm* pTFrm;
1546 		pNxt->Calc();
1547 		if( pNxt->Frm().Top() > rPoint.Y() &&
1548 			!lcl_IsInRepeatedHeadline( pCnt, &pTFrm ) &&
1549 			( !pTFrm || pNxt->Frm().Left() > rPoint.X() ))
1550 		{
1551 			if( bNext )
1552 				return pNxt->Frm().Pos();
1553 			return Point( aCntFrm.Right(), aCntFrm.Bottom() );
1554 		}
1555 		pCnt = pNxt;
1556 	}
1557 	return Point( 0, 0 );
1558 }
1559 
1560 /*************************************************************************
1561 |*
1562 |*	SwRootFrm::GetPagePos()
1563 |*
1564 |*	Beschreibung:	Liefert die absolute Dokumentpositon der gewuenschten
1565 |*			Seite.
1566 |*			Formatiert wird nur soweit notwendig und nur dann wenn bFormat=sal_True
1567 |*			Liefert Null, wenn die Operation nicht moeglich ist.
1568 |*			Die Pos ist die der letzten Seite, wenn die Seitenzahl zu gross
1569 |*			gewaehlt wurde.
1570 |*	Ersterstellung		MA 01. Jun. 92
1571 |*	Letzte Aenderung	MA 09. Oct. 97
1572 |*
1573 |*************************************************************************/
GetPagePos(sal_uInt16 nPageNum) const1574 Point SwRootFrm::GetPagePos( sal_uInt16 nPageNum ) const
1575 {
1576 	ASSERT( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
1577 
1578 	const SwPageFrm *pPage = (const SwPageFrm*)Lower();
1579 	while ( sal_True )
1580 	{
1581 		if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
1582 			break;
1583 		pPage = (const SwPageFrm*)pPage->GetNext();
1584 	}
1585 	return pPage->Frm().Pos();
1586 }
1587 
1588 /** get page frame by phyiscal page number
1589 
1590     OD 14.01.2003 #103492#
1591 
1592     @return pointer to the page frame with the given physical page number
1593 */
GetPageByPageNum(sal_uInt16 _nPageNum) const1594 SwPageFrm* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum ) const
1595 {
1596     const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>( Lower() );
1597     while ( pPageFrm && pPageFrm->GetPhyPageNum() < _nPageNum )
1598     {
1599           pPageFrm = static_cast<const SwPageFrm*>( pPageFrm->GetNext() );
1600     }
1601 
1602     if ( pPageFrm && pPageFrm->GetPhyPageNum() == _nPageNum )
1603     {
1604         return const_cast<SwPageFrm*>( pPageFrm );
1605     }
1606     else
1607     {
1608         return 0;
1609     }
1610 }
1611 
1612 /*************************************************************************
1613 |*
1614 |*  SwRootFrm::IsDummyPage(sal_uInt16)
1615 |*
1616 |*  Description: Returns sal_True, when the given physical pagenumber does't exist
1617 |*               or this page is an empty page.
1618 |*************************************************************************/
IsDummyPage(sal_uInt16 nPageNum) const1619 sal_Bool SwRootFrm::IsDummyPage( sal_uInt16 nPageNum ) const
1620 {
1621     if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
1622         return sal_True;
1623 
1624 	const SwPageFrm *pPage = (const SwPageFrm*)Lower();
1625     while( pPage && nPageNum < pPage->GetPhyPageNum() )
1626 		pPage = (const SwPageFrm*)pPage->GetNext();
1627     return pPage ? pPage->IsEmptyPage() : sal_True;
1628 }
1629 
1630 
1631 /*************************************************************************
1632 |*
1633 |*	  SwFrm::IsProtected()
1634 |*
1635 |*	  Beschreibung		Ist der Frm bzw. die Section in der er steht
1636 |* 						geschuetzt?
1637 |* 						Auch Fly in Fly in ... und Fussnoten
1638 |*
1639 |*	  Ersterstellung	MA 28. Jul. 93
1640 |*	  Letzte Aenderung	MA 06. Nov. 97
1641 |*
1642 |*************************************************************************/
IsProtected() const1643 sal_Bool SwFrm::IsProtected() const
1644 {
1645     if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
1646     {
1647         const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
1648         bool isFormProtected=pDoc->get(IDocumentSettingAccess::PROTECT_FORM );
1649         if (isFormProtected)
1650         {
1651             return sal_False; // TODO a hack for now, well deal with it laster, I we return true here we have a "double" locking
1652         }
1653     }
1654     //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein.
1655     //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker.
1656     const SwFrm *pFrm = this;
1657     do
1658     {
1659         if ( pFrm->IsCntntFrm() )
1660         {
1661             if ( ((SwCntntFrm*)pFrm)->GetNode() &&
1662                  ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
1663                 return sal_True;
1664         }
1665         else
1666         {
1667             if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
1668                  ((SwLayoutFrm*)pFrm)->GetFmt()->
1669                  GetProtect().IsCntntProtected() )
1670                 return sal_True;
1671             if ( pFrm->IsCoveredCell() )
1672                 return sal_True;
1673         }
1674         if ( pFrm->IsFlyFrm() )
1675         {
1676             //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette
1677             //vorgegeben werden.
1678             if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
1679             {
1680                 SwFlyFrm *pMaster = (SwFlyFrm*)pFrm;
1681                 do
1682                 {   pMaster = pMaster->GetPrevLink();
1683                 } while ( pMaster->GetPrevLink() );
1684                 if ( pMaster->IsProtected() )
1685                     return sal_True;
1686             }
1687             pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
1688         }
1689         else if ( pFrm->IsFtnFrm() )
1690             pFrm = ((SwFtnFrm*)pFrm)->GetRef();
1691         else
1692             pFrm = pFrm->GetUpper();
1693 
1694     } while ( pFrm );
1695 
1696     return sal_False;
1697 }
1698 
1699 /*************************************************************************
1700 |*
1701 |*	  SwFrm::GetPhyPageNum()
1702 |*	  Beschreibung:		Liefert die physikalische Seitennummer
1703 |*
1704 |*	  Ersterstellung	OK 06.07.93 08:35
1705 |*	  Letzte Aenderung	MA 30. Nov. 94
1706 |*
1707 |*************************************************************************/
GetPhyPageNum() const1708 sal_uInt16 SwFrm::GetPhyPageNum() const
1709 {
1710 	const SwPageFrm *pPage = FindPageFrm();
1711 	return pPage ? pPage->GetPhyPageNum() : 0;
1712 }
1713 
1714 /*-----------------26.02.01 11:25-------------------
1715  * SwFrm::WannaRightPage()
1716  * decides if the page want to be a rightpage or not.
1717  * If the first content of the page has a page descriptor,
1718  * we take the follow of the page descriptor of the last not empty page.
1719  * If this descriptor allows only right(left) pages and the page
1720  * isn't an empty page then it wanna be such right(left) page.
1721  * If the descriptor allows right and left pages, we look for a number offset
1722  * in the first content. If there is one, odd number results right pages,
1723  * even number results left pages.
1724  * If there is no number offset, we take the physical page number instead,
1725  * but a previous empty page don't count.
1726  * --------------------------------------------------*/
1727 
WannaRightPage() const1728 sal_Bool SwFrm::WannaRightPage() const
1729 {
1730 	const SwPageFrm *pPage = FindPageFrm();
1731 	if ( !pPage || !pPage->GetUpper() )
1732 		return sal_True;
1733 
1734 	const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
1735 	SwPageDesc *pDesc = 0;
1736 	sal_uInt16 nPgNum = 0;
1737 	if ( pFlow )
1738 	{
1739 		if ( pFlow->IsInTab() )
1740 			pFlow = pFlow->FindTabFrm();
1741 		const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
1742 		if ( !pTmp->IsFollow() )
1743 		{
1744 			const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
1745 			pDesc = (SwPageDesc*)rPgDesc.GetPageDesc();
1746 			nPgNum = rPgDesc.GetNumOffset();
1747 		}
1748 	}
1749 	if ( !pDesc )
1750 	{
1751 		SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1752 		if( pPrv && pPrv->IsEmptyPage() )
1753 			pPrv = (SwPageFrm*)pPrv->GetPrev();
1754 		if( pPrv )
1755 			pDesc = pPrv->GetPageDesc()->GetFollow();
1756 		else
1757 		{
1758 			const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
1759 			pDesc = (SwPageDesc*)&pDoc->GetPageDesc( 0 );
1760 		}
1761 	}
1762 	ASSERT( pDesc, "No pagedescriptor" );
1763 	sal_Bool bOdd;
1764 	if( nPgNum )
1765 		bOdd = nPgNum % 2 ? sal_True : sal_False;
1766 	else
1767 	{
1768 		bOdd = pPage->OnRightPage();
1769 		if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
1770 			bOdd = !bOdd;
1771 	}
1772 	if( !pPage->IsEmptyPage() )
1773 	{
1774 		if( !pDesc->GetRightFmt() )
1775 			bOdd = sal_False;
1776 		else if( !pDesc->GetLeftFmt() )
1777 			bOdd = sal_True;
1778 	}
1779 	return bOdd;
1780 }
1781 
1782 /*************************************************************************
1783 |*
1784 |*	  SwFrm::GetVirtPageNum()
1785 |*	  Beschreibung:		Liefert die virtuelle Seitennummer mit Offset
1786 |*
1787 |*	  Ersterstellung	OK 06.07.93 08:35
1788 |*	  Letzte Aenderung	MA 30. Nov. 94
1789 |*
1790 |*************************************************************************/
GetVirtPageNum() const1791 sal_uInt16 SwFrm::GetVirtPageNum() const
1792 {
1793 	const SwPageFrm *pPage = FindPageFrm();
1794 	if ( !pPage || !pPage->GetUpper() )
1795 		return 0;
1796 
1797 	sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
1798 	if ( !((SwRootFrm*)pPage->GetUpper())->IsVirtPageNum() )
1799 		return nPhyPage;
1800 
1801 	//Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen.
1802 	//Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen
1803 	//wir jetzt gezielt ueber die Abhaengigkeiten.
1804 	//von den PageDescs bekommen wir die Attribute, von den Attributen
1805 	//wiederum bekommen wir die Absaetze.
1806 	const SwPageFrm *pVirtPage = 0;
1807 	const SwFrm *pFrm = 0;
1808 	const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
1809 	const SfxPoolItem* pItem;
1810 	sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
1811 	for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1812 	{
1813 		if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
1814 			continue;
1815 
1816 		const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
1817 		if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
1818 		{
1819 			const SwModify *pMod = pDesc->GetDefinedIn();
1820 			SwVirtPageNumInfo aInfo( pPage );
1821 			pMod->GetInfo( aInfo );
1822 			if ( aInfo.GetPage() )
1823 			{
1824 				if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
1825 					GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
1826 				{
1827 					pVirtPage = aInfo.GetPage();
1828 					pFrm = aInfo.GetFrm();
1829 				}
1830 			}
1831 		}
1832 	}
1833 	if ( pFrm )
1834 		return nPhyPage - pFrm->GetPhyPageNum() +
1835 			   pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
1836 	return nPhyPage;
1837 }
1838 
1839 /*************************************************************************
1840 |*
1841 |*	SwRootFrm::MakeTblCrsrs()
1842 |*
1843 |*	Ersterstellung		MA 14. May. 93
1844 |*	Letzte Aenderung	MA 02. Feb. 94
1845 |*
1846 |*************************************************************************/
1847 //Ermitteln und einstellen derjenigen Zellen die von der Selektion
1848 //eingeschlossen sind.
1849 
MakeTblCrsrs(SwTableCursor & rTblCrsr)1850 bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
1851 {
1852     //Union-Rects und Tabellen (Follows) der Selektion besorgen.
1853 	ASSERT( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( sal_False ),
1854 			"Tabselection nicht auf Cnt." );
1855 
1856     bool bRet = false;
1857 
1858     // For new table models there's no need to ask the layout..
1859     if( rTblCrsr.NewTableSelection() )
1860         return true;
1861 
1862 	Point aPtPt, aMkPt;
1863 	{
1864         SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
1865 
1866 		if( pShCrsr )
1867 		{
1868 			aPtPt = pShCrsr->GetPtPos();
1869 			aMkPt = pShCrsr->GetMkPos();
1870 		}
1871 	}
1872 
1873     // --> FME 2008-01-14 #151012# Made code robust here:
1874     const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
1875     const SwCntntNode* pTmpEndNode   = rTblCrsr.GetCntntNode(sal_False);
1876 
1877     const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, sal_False ) : 0;
1878     const SwFrm* pTmpEndFrm   = pTmpEndNode   ?   pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, sal_False ) : 0;
1879 
1880     const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
1881     const SwLayoutFrm* pEnd   = pTmpEndFrm   ? pTmpEndFrm->GetUpper() : 0;
1882 
1883     ASSERT( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" )
1884     // <--
1885 
1886     /* #109590# Only change table boxes if the frames are
1887         valid. Needed because otherwise the table cursor after moving
1888         table cells by dnd resulted in an empty tables cursor.  */
1889     if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
1890     {
1891         SwSelUnions aUnions;
1892         ::MakeSelUnions( aUnions, pStart, pEnd );
1893 
1894         SwSelBoxes aNew;
1895 
1896         const sal_Bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
1897 
1898         for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i )
1899         {
1900             SwSelUnion *pUnion = aUnions[i];
1901             const SwTabFrm *pTable = pUnion->GetTable();
1902 
1903             // Skip any repeated headlines in the follow:
1904             SwLayoutFrm* pRow = pTable->IsFollow() ?
1905                                 pTable->GetFirstNonHeadlineRow() :
1906                                 (SwLayoutFrm*)pTable->Lower();
1907 
1908             while ( pRow )
1909             {
1910                 if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
1911                 {
1912                     const SwLayoutFrm *pCell = pRow->FirstCell();
1913 
1914                     while ( pCell && pRow->IsAnLower( pCell ) )
1915                     {
1916                         ASSERT( pCell->IsCellFrm(), "Frame ohne Celle" );
1917                         if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
1918                             (bReadOnlyAvailable ||
1919                              !pCell->GetFmt()->GetProtect().IsCntntProtected()))
1920                         {
1921                             SwTableBox* pInsBox = (SwTableBox*)
1922                                 ((SwCellFrm*)pCell)->GetTabBox();
1923                             aNew.Insert( pInsBox );
1924                         }
1925                         if ( pCell->GetNext() )
1926                         {
1927                             pCell = (const SwLayoutFrm*)pCell->GetNext();
1928                             if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
1929                                 pCell = pCell->FirstCell();
1930                         }
1931                         else
1932                         {
1933                             const SwLayoutFrm* pLastCell = pCell;
1934                             do
1935                             {
1936                                 pCell = pCell->GetNextLayoutLeaf();
1937                             } while ( pCell && pLastCell->IsAnLower( pCell ) );
1938                             // Fuer (spaltige) Bereiche...
1939                             if( pCell && pCell->IsInTab() )
1940                             {
1941                                 while( !pCell->IsCellFrm() )
1942                                 {
1943                                     pCell = pCell->GetUpper();
1944                                     ASSERT( pCell, "Where's my cell?" );
1945                                 }
1946                             }
1947                         }
1948                     }
1949                 }
1950                 pRow = (SwLayoutFrm*)pRow->GetNext();
1951             }
1952         }
1953 
1954         rTblCrsr.ActualizeSelection( aNew );
1955         bRet = true;
1956     }
1957 
1958     return bRet;
1959 }
1960 
1961 
1962 /*************************************************************************
1963 |*
1964 |*	SwRootFrm::CalcFrmRects
1965 |*
1966 |*	Ersterstellung		MA 24. Aug. 92
1967 |*	Letzte Aenderung	MA 24. Aug. 93
1968 |*
1969 |*************************************************************************/
1970 
1971 /*
1972  * nun koennen folgende Situationen auftreten:
1973  *	1. Start und Ende liegen in einer Bildschirm - Zeile und im
1974  * 	   gleichen Node
1975  *		-> aus Start und End ein Rectangle, dann Ok
1976  *	2. Start und Ende liegen in einem Frame (dadurch im gleichen Node!)
1977  *		-> Start nach rechts, End nach links erweitern,
1978  *		   und bei mehr als 2 Bildschirm - Zeilen, das dazwischen
1979  *		   liegende berechnen
1980  * 	3. Start und Ende liegen in verschiedenen Frames
1981  *		-> Start nach rechts erweitern, bis Frame-Ende Rect berechnen
1982  *		   Ende nach links erweitern, bis Frame-Start Rect berechnen
1983  *		   und bei mehr als 2 Frames von allen dazwischen liegenden
1984  * 		   Frames die PrtArea dazu.
1985  *
1986  * Grosser Umbau wg. der FlyFrm; denn diese muessen ausgespart werden.
1987  * Ausnahmen: - Der Fly in dem die Selektion stattfindet (wenn sie in einem Fly
1988  *				stattfindet).
1989  * 			  - Die Flys, die vom Text unterlaufen werden.
1990  * Arbeitsweise: Zuerst wird eine SwRegion mit der Root initialisiert.
1991  * 				 Aus der Region werden die zu invertierenden Bereiche
1992  * 				 ausgestantzt. Die Region wird Komprimiert und letztlich
1993  * 				 invertiert. Damit liegen dann die zu invertierenden
1994  * 				 Rechtecke vor.
1995  * 				 Am Ende werden die Flys aus der Region ausgestanzt.
1996  */
1997 
Sub(SwRegionRects & rRegion,const SwRect & rRect)1998 inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
1999 {
2000 	if( rRect.Width() > 1 && rRect.Height() > 1 &&
2001 		rRect.IsOver( rRegion.GetOrigin() ))
2002 		rRegion -= rRect;
2003 }
2004 
CalcFrmRects(SwShellCrsr & rCrsr)2005 void SwRootFrm::CalcFrmRects(
2006     SwShellCrsr &rCrsr )
2007 {
2008     SwPosition *pStartPos = rCrsr.Start(),
2009                *pEndPos   = rCrsr.GetPoint() == pStartPos ? rCrsr.GetMark() : rCrsr.GetPoint();
2010 
2011     ViewShell *pSh = GetCurrShell();
2012 
2013     SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
2014                            pSh->VisArea() :
2015                            Frm() );
2016     if( !pStartPos->nNode.GetNode().IsCntntNode() ||
2017         !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
2018         ( pStartPos->nNode != pEndPos->nNode &&
2019           ( !pEndPos->nNode.GetNode().IsCntntNode() ||
2020             !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
2021     {
2022         return;
2023     }
2024 
2025     //Erstmal die CntntFrms zum Start und End besorgen, die brauch ich auf
2026     //jedenfall.
2027     SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
2028         GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
2029 
2030     SwCntntFrm const* pEndFrm   = pEndPos->nNode.GetNode().
2031         GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
2032 
2033     ASSERT( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
2034 
2035     //Damit die FlyFrms, in denen selektierte Frames stecken, nicht
2036     //abgezogen werden
2037     SwSortedObjs aSortObjs;
2038     if ( pStartFrm->IsInFly() )
2039     {
2040         const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
2041         aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
2042         const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
2043         ASSERT( pObj2 != NULL, "SwRootFrm::CalcFrmRects(..) - FlyFrame missing - looks like an invalid selection" );
2044         if ( pObj2 != NULL && pObj2 != pObj )
2045         {
2046             aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
2047         }
2048     }
2049 
2050     // falls eine nicht erlaubte Selection besteht, dann korrigiere das
2051     // nicht erlaubt ist Header/Footer/TableHeadline ueber 2 Seiten
2052     do
2053     {	// middle check loop
2054         const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
2055         const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
2056         while ( pSttLFrm
2057                 && !( cHdFtTblHd & pSttLFrm->GetType() ) )
2058         {
2059             pSttLFrm = pSttLFrm->GetUpper();
2060         }
2061         if ( !pSttLFrm )
2062             break;
2063         const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
2064         while ( pEndLFrm
2065                 && !( cHdFtTblHd & pEndLFrm->GetType() ) )
2066         {
2067             pEndLFrm = pEndLFrm->GetUpper();
2068         }
2069         if ( !pEndLFrm )
2070             break;
2071 
2072         ASSERT( pEndLFrm->GetType() == pSttLFrm->GetType(),
2073             "Selection ueber unterschiedliche Inhalte" );
2074         switch (pSttLFrm->GetType())
2075         {
2076         case FRM_HEADER:
2077             case FRM_FOOTER:
2078             // auf unterschiedlichen Seiten ??
2079             // dann immer auf die Start-Seite
2080             if ( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
2081             {
2082                 // End- auf den Start-CntntFrame setzen
2083                 if ( pStartPos == rCrsr.GetPoint() )
2084                     pEndFrm = pStartFrm;
2085                 else
2086                     pStartFrm = pEndFrm;
2087             }
2088             break;
2089         case FRM_TAB:
2090             // auf unterschiedlichen Seiten ??
2091             // existiert
2092             // dann teste auf Tabelle-Headline
2093         {
2094             const SwTabFrm* pTabFrm = (SwTabFrm*) pSttLFrm;
2095             if ( ( pTabFrm->GetFollow()
2096                    || ( (SwTabFrm*) pEndLFrm )->GetFollow() )
2097                  && pTabFrm->GetTable()->GetRowsToRepeat() > 0
2098                  && pTabFrm->GetLower() != ( (SwTabFrm*) pEndLFrm )->GetLower()
2099                  && ( lcl_IsInRepeatedHeadline( pStartFrm )
2100                       || lcl_IsInRepeatedHeadline( pEndFrm ) ) )
2101             {
2102                 // End- auf den Start-CntntFrame setzen
2103                 if ( pStartPos == rCrsr.GetPoint() )
2104                     pEndFrm = pStartFrm;
2105                 else
2106                     pStartFrm = pEndFrm;
2107             }
2108         }
2109             break;
2110         }
2111     } while ( sal_False);
2112 
2113     SwCrsrMoveState aTmpState( MV_NONE );
2114     aTmpState.b2Lines = sal_True;
2115     aTmpState.bNoScroll = sal_True;
2116     aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
2117 
2118     //CntntRects zu Start- und EndFrms.
2119     SwRect aStRect, aEndRect;
2120     pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
2121     Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
2122     aTmpState.p2Lines = NULL;
2123     aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
2124 
2125     pEndFrm->GetCharRect( aEndRect, *pEndPos, &aTmpState );
2126     Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
2127 
2128     SwRect aStFrm( pStartFrm->UnionFrm( sal_True ) );
2129     aStFrm.Intersection( pStartFrm->PaintArea() );
2130     SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm : pEndFrm->UnionFrm( sal_True ) );
2131     if ( pStartFrm != pEndFrm )
2132     {
2133         aEndFrm.Intersection( pEndFrm->PaintArea() );
2134     }
2135     SWRECTFN( pStartFrm )
2136     const sal_Bool bR2L = pStartFrm->IsRightToLeft();
2137     const sal_Bool bEndR2L = pEndFrm->IsRightToLeft();
2138 
2139     // If there's no doubleline portion involved or start and end are both
2140     // in the same doubleline portion, all works fine, but otherwise
2141     // we need the following...
2142     if ( pSt2Pos != pEnd2Pos
2143          && ( !pSt2Pos || !pEnd2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
2144     {
2145         // If we have a start(end) position inside a doubleline portion
2146         // the surrounded part of the doubleline portion is subtracted
2147         // from the region and the aStRect(aEndRect) is set to the
2148         // end(start) of the doubleline portion.
2149         if ( pSt2Pos )
2150         {
2151             SwRect aTmp( aStRect );
2152 
2153             // BiDi-Portions are swimming against the current.
2154             const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
2155                                                                           !bR2L :
2156                                                                           bR2L;
2157 
2158             if ( MT_BIDI == pSt2Pos->nMultiType
2159                  && ( pSt2Pos->aPortion2.*fnRect->fnGetWidth )() )
2160             {
2161                 // nested bidi portion
2162                 long nRightAbs = ( pSt2Pos->aPortion.*fnRect->fnGetRight )();
2163                 nRightAbs -= ( pSt2Pos->aPortion2.*fnRect->fnGetLeft )();
2164                 long nLeftAbs = nRightAbs - ( pSt2Pos->aPortion2.*fnRect->fnGetWidth )();
2165 
2166                 ( aTmp.*fnRect->fnSetRight )( nRightAbs );
2167 
2168                 if ( !pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
2169                 {
2170                     SwRect aTmp2( pSt2Pos->aPortion );
2171                     ( aTmp2.*fnRect->fnSetRight )( nLeftAbs );
2172                     aTmp2.Intersection( aEndFrm );
2173                     Sub( aRegion, aTmp2 );
2174                 }
2175             }
2176             else
2177             {
2178                 if ( bPorR2L )
2179                     ( aTmp.*fnRect->fnSetLeft )(
2180                         ( pSt2Pos->aPortion.*fnRect->fnGetLeft )() );
2181                 else
2182                     ( aTmp.*fnRect->fnSetRight )(
2183                         ( pSt2Pos->aPortion.*fnRect->fnGetRight )() );
2184             }
2185 
2186             if ( MT_ROT_90 == pSt2Pos->nMultiType
2187                  || ( pSt2Pos->aPortion.*fnRect->fnGetTop )() == ( aTmp.*fnRect->fnGetTop )() )
2188             {
2189                 ( aTmp.*fnRect->fnSetTop )(
2190                     ( pSt2Pos->aLine.*fnRect->fnGetTop )() );
2191             }
2192 
2193             aTmp.Intersection( aStFrm );
2194             Sub( aRegion, aTmp );
2195 
2196             SwTwips nTmp = ( pSt2Pos->aLine.*fnRect->fnGetBottom )();
2197             if ( MT_ROT_90 != pSt2Pos->nMultiType
2198                  && ( aStRect.*fnRect->fnBottomDist )( nTmp ) > 0 )
2199             {
2200                 ( aTmp.*fnRect->fnSetTop )( ( aTmp.*fnRect->fnGetBottom )() );
2201                 ( aTmp.*fnRect->fnSetBottom )( nTmp );
2202                 if ( ( aStRect.*fnRect->fnBottomDist )( ( pSt2Pos->aPortion.*fnRect->fnGetBottom )() ) > 0 )
2203                 {
2204                     if ( bPorR2L )
2205                         ( aTmp.*fnRect->fnSetRight )(
2206                             ( pSt2Pos->aPortion.*fnRect->fnGetRight )() );
2207                     else
2208                         ( aTmp.*fnRect->fnSetLeft )(
2209                             ( pSt2Pos->aPortion.*fnRect->fnGetLeft )() );
2210                 }
2211                 aTmp.Intersection( aStFrm );
2212                 Sub( aRegion, aTmp );
2213             }
2214 
2215             aStRect = pSt2Pos->aLine;
2216             ( aStRect.*fnRect->fnSetLeft )( bR2L ?
2217                                                    ( pSt2Pos->aPortion.*fnRect->fnGetLeft )() :
2218                                                    ( pSt2Pos->aPortion.*fnRect->fnGetRight )() );
2219             ( aStRect.*fnRect->fnSetWidth )( 1 );
2220         }
2221 
2222         if ( pEnd2Pos )
2223         {
2224             SWRECTFNX( pEndFrm )
2225             SwRect aTmp( aEndRect );
2226 
2227             // BiDi-Portions are swimming against the current.
2228             const sal_Bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
2229                                                                            !bEndR2L :
2230                                                                            bEndR2L;
2231 
2232             if ( MT_BIDI == pEnd2Pos->nMultiType
2233                  && ( pEnd2Pos->aPortion2.*fnRectX->fnGetWidth )() )
2234             {
2235                 // nested bidi portion
2236                 long nRightAbs = ( pEnd2Pos->aPortion.*fnRectX->fnGetRight )();
2237                 nRightAbs = nRightAbs - ( pEnd2Pos->aPortion2.*fnRectX->fnGetLeft )();
2238                 long nLeftAbs = nRightAbs - ( pEnd2Pos->aPortion2.*fnRectX->fnGetWidth )();
2239 
2240                 ( aTmp.*fnRectX->fnSetLeft )( nLeftAbs );
2241 
2242                 if ( !pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
2243                 {
2244                     SwRect aTmp2( pEnd2Pos->aPortion );
2245                     ( aTmp2.*fnRectX->fnSetLeft )( nRightAbs );
2246                     aTmp2.Intersection( aEndFrm );
2247                     Sub( aRegion, aTmp2 );
2248                 }
2249             }
2250             else
2251             {
2252                 if ( bPorR2L )
2253                     ( aTmp.*fnRectX->fnSetRight )(
2254                         ( pEnd2Pos->aPortion.*fnRectX->fnGetRight )() );
2255                 else
2256                     ( aTmp.*fnRectX->fnSetLeft )(
2257                         ( pEnd2Pos->aPortion.*fnRectX->fnGetLeft )() );
2258             }
2259 
2260             if ( MT_ROT_90 == pEnd2Pos->nMultiType
2261                  || ( pEnd2Pos->aPortion.*fnRectX->fnGetBottom )() == ( aEndRect.*fnRectX->fnGetBottom )() )
2262             {
2263                 ( aTmp.*fnRectX->fnSetBottom )(
2264                     ( pEnd2Pos->aLine.*fnRectX->fnGetBottom )() );
2265             }
2266 
2267             aTmp.Intersection( aEndFrm );
2268             Sub( aRegion, aTmp );
2269 
2270             // The next statement means neither ruby nor rotate(90):
2271             if ( !( MT_RUBY & pEnd2Pos->nMultiType ) )
2272             {
2273                 SwTwips nTmp = ( pEnd2Pos->aLine.*fnRectX->fnGetTop )();
2274                 if ( ( aEndRect.*fnRectX->fnGetTop )() != nTmp )
2275                 {
2276                     ( aTmp.*fnRectX->fnSetBottom )(
2277                         ( aTmp.*fnRectX->fnGetTop )() );
2278                     ( aTmp.*fnRectX->fnSetTop )( nTmp );
2279                     if ( ( aEndRect.*fnRectX->fnGetTop )() !=
2280                          ( pEnd2Pos->aPortion.*fnRectX->fnGetTop )() )
2281                     {
2282                         if ( bPorR2L )
2283                             ( aTmp.*fnRectX->fnSetLeft )(
2284                                 ( pEnd2Pos->aPortion.*fnRectX->fnGetLeft )() );
2285                         else
2286                             ( aTmp.*fnRectX->fnSetRight )(
2287                                 ( pEnd2Pos->aPortion.*fnRectX->fnGetRight )() );
2288                     }
2289                     aTmp.Intersection( aEndFrm );
2290                     Sub( aRegion, aTmp );
2291                 }
2292             }
2293 
2294             aEndRect = pEnd2Pos->aLine;
2295             ( aEndRect.*fnRectX->fnSetLeft )( bEndR2L ?
2296                                                         ( pEnd2Pos->aPortion.*fnRectX->fnGetRight )() :
2297                                                         ( pEnd2Pos->aPortion.*fnRectX->fnGetLeft )() );
2298             ( aEndRect.*fnRectX->fnSetWidth )( 1 );
2299         }
2300     }
2301     else if ( pSt2Pos && pEnd2Pos
2302               && MT_BIDI == pSt2Pos->nMultiType
2303               && MT_BIDI == pEnd2Pos->nMultiType
2304               && pSt2Pos->aPortion == pEnd2Pos->aPortion
2305               && pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
2306     {
2307         // This is the ugly special case, where the selection starts and
2308         // ends in the same bidi portion but one start or end is inside a
2309         // nested bidi portion.
2310 
2311         if ( ( pSt2Pos->aPortion2.*fnRect->fnGetWidth )() )
2312         {
2313             SwRect aTmp( aStRect );
2314             long nRightAbs = ( pSt2Pos->aPortion.*fnRect->fnGetRight )();
2315             nRightAbs -= ( pSt2Pos->aPortion2.*fnRect->fnGetLeft )();
2316             long nLeftAbs = nRightAbs - ( pSt2Pos->aPortion2.*fnRect->fnGetWidth )();
2317 
2318             ( aTmp.*fnRect->fnSetRight )( nRightAbs );
2319             aTmp.Intersection( aStFrm );
2320             Sub( aRegion, aTmp );
2321 
2322             aStRect = pSt2Pos->aLine;
2323             ( aStRect.*fnRect->fnSetLeft )( bR2L ? nRightAbs : nLeftAbs );
2324             ( aStRect.*fnRect->fnSetWidth )( 1 );
2325         }
2326 
2327         SWRECTFNX( pEndFrm )
2328         if ( ( pEnd2Pos->aPortion2.*fnRectX->fnGetWidth )() )
2329         {
2330             SwRect aTmp( aEndRect );
2331             long nRightAbs = ( pEnd2Pos->aPortion.*fnRectX->fnGetRight )();
2332             nRightAbs -= ( pEnd2Pos->aPortion2.*fnRectX->fnGetLeft )();
2333             long nLeftAbs = nRightAbs - ( pEnd2Pos->aPortion2.*fnRectX->fnGetWidth )();
2334 
2335             ( aTmp.*fnRectX->fnSetLeft )( nLeftAbs );
2336             aTmp.Intersection( aEndFrm );
2337             Sub( aRegion, aTmp );
2338 
2339             aEndRect = pEnd2Pos->aLine;
2340             ( aEndRect.*fnRectX->fnSetLeft )( bEndR2L ? nLeftAbs : nRightAbs );
2341             ( aEndRect.*fnRectX->fnSetWidth )( 1 );
2342         }
2343     }
2344 
2345     // The charrect may be outside the paintarea (for cursortravelling)
2346     // but the selection has to be restricted to the paintarea
2347     if ( aStRect.Left() < aStFrm.Left() )
2348         aStRect.Left( aStFrm.Left() );
2349     else if ( aStRect.Left() > aStFrm.Right() )
2350         aStRect.Left( aStFrm.Right() );
2351     SwTwips nTmp = aStRect.Right();
2352     if ( nTmp < aStFrm.Left() )
2353         aStRect.Right( aStFrm.Left() );
2354     else if ( nTmp > aStFrm.Right() )
2355         aStRect.Right( aStFrm.Right() );
2356     if ( aEndRect.Left() < aEndFrm.Left() )
2357         aEndRect.Left( aEndFrm.Left() );
2358     else if ( aEndRect.Left() > aEndFrm.Right() )
2359         aEndRect.Left( aEndFrm.Right() );
2360     nTmp = aEndRect.Right();
2361     if ( nTmp < aEndFrm.Left() )
2362         aEndRect.Right( aEndFrm.Left() );
2363     else if ( nTmp > aEndFrm.Right() )
2364         aEndRect.Right( aEndFrm.Right() );
2365 
2366     if ( pStartFrm == pEndFrm )
2367     {
2368         sal_Bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos
2369                                       && ( MT_BIDI & pSt2Pos->nMultiType )
2370                                       && pSt2Pos->aPortion == pEnd2Pos->aPortion;
2371         //case 1: (Same frame and same row)
2372         if ( bSameRotatedOrBidi
2373              || ( aStRect.*fnRect->fnGetTop )() == ( aEndRect.*fnRect->fnGetTop )() )
2374         {
2375             Point aTmpSt( aStRect.Pos() );
2376             Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
2377             if ( bSameRotatedOrBidi || bR2L )
2378             {
2379                 if ( aTmpSt.Y() > aTmpEnd.Y() )
2380                 {
2381                     long nTmpY = aTmpEnd.Y();
2382                     aTmpEnd.Y() = aTmpSt.Y();
2383                     aTmpSt.Y() = nTmpY;
2384                 }
2385                 if ( aTmpSt.X() > aTmpEnd.X() )
2386                 {
2387                     long nTmpX = aTmpEnd.X();
2388                     aTmpEnd.X() = aTmpSt.X();
2389                     aTmpSt.X() = nTmpX;
2390                 }
2391             }
2392 
2393             SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
2394             // Bug 34888: falls Inhalt selektiert ist, der keinen Platz
2395             //			  einnimmt (z.B. PostIts,RefMarks, TOXMarks),
2396             //			  dann mindestens die Breite des Crsr setzen.
2397             if ( 1 == ( aTmp.*fnRect->fnGetWidth )() &&
2398                  pStartPos->nContent.GetIndex() !=
2399                  pEndPos->nContent.GetIndex() )
2400             {
2401                 OutputDevice* pOut = pSh->GetOut();
2402                 long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
2403                         GetCursorSize();
2404                 ( aTmp.*fnRect->fnSetWidth )( pOut->PixelToLogic(
2405                     Size( nCrsrWidth, 0 ) ).Width() );
2406             }
2407             aTmp.Intersection( aStFrm );
2408             Sub( aRegion, aTmp );
2409         }
2410         //case 2: (Same frame, but not the same line)
2411         else
2412         {
2413             SwTwips lLeft, lRight;
2414             if ( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
2415             {
2416                 lLeft = ( pSt2Pos->aPortion.*fnRect->fnGetLeft )();
2417                 lRight = ( pSt2Pos->aPortion.*fnRect->fnGetRight )();
2418             }
2419             else
2420             {
2421                 lLeft = ( pStartFrm->Frm().*fnRect->fnGetLeft )() +
2422                         ( pStartFrm->Prt().*fnRect->fnGetLeft )();
2423                 lRight = ( pStartFrm->Frm().*fnRect->fnGetLeft )() +
2424                          ( pStartFrm->Prt().*fnRect->fnGetRight )();
2425             }
2426             if ( lLeft < ( aStFrm.*fnRect->fnGetLeft )() )
2427                 lLeft = ( aStFrm.*fnRect->fnGetLeft )();
2428             if ( lRight > ( aStFrm.*fnRect->fnGetRight )() )
2429                 lRight = ( aStFrm.*fnRect->fnGetRight )();
2430             SwRect aSubRect( aStRect );
2431             //First line
2432             if ( bR2L )
2433                 ( aSubRect.*fnRect->fnSetLeft )( lLeft );
2434             else
2435                 ( aSubRect.*fnRect->fnSetRight )( lRight );
2436             Sub( aRegion, aSubRect );
2437 
2438             //If there's at least a twips between start- and endline,
2439             //so the whole area between will be added.
2440             SwTwips aTmpBottom = ( aStRect.*fnRect->fnGetBottom )();
2441             SwTwips aTmpTop = ( aEndRect.*fnRect->fnGetTop )();
2442             if ( aTmpBottom != aTmpTop )
2443             {
2444                 ( aSubRect.*fnRect->fnSetLeft )( lLeft );
2445                 ( aSubRect.*fnRect->fnSetRight )( lRight );
2446                 ( aSubRect.*fnRect->fnSetTop )( aTmpBottom );
2447                 ( aSubRect.*fnRect->fnSetBottom )( aTmpTop );
2448                 Sub( aRegion, aSubRect );
2449             }
2450             //and the last line
2451             aSubRect = aEndRect;
2452             if ( bR2L )
2453                 ( aSubRect.*fnRect->fnSetRight )( lRight );
2454             else
2455                 ( aSubRect.*fnRect->fnSetLeft )( lLeft );
2456             Sub( aRegion, aSubRect );
2457         }
2458     }
2459     //case 3: (Different frames, maybe with ohther frames between
2460     else
2461     {
2462         //The startframe first...
2463         SwRect aSubRect( aStRect );
2464         if ( bR2L )
2465             ( aSubRect.*fnRect->fnSetLeft )( ( aStFrm.*fnRect->fnGetLeft )() );
2466         else
2467             ( aSubRect.*fnRect->fnSetRight )( ( aStFrm.*fnRect->fnGetRight )() );
2468         Sub( aRegion, aSubRect );
2469         SwTwips nTmpTwips = ( aStRect.*fnRect->fnGetBottom )();
2470         if ( ( aStFrm.*fnRect->fnGetBottom )() != nTmpTwips )
2471         {
2472             aSubRect = aStFrm;
2473             ( aSubRect.*fnRect->fnSetTop )( nTmpTwips );
2474             Sub( aRegion, aSubRect );
2475         }
2476 
2477         //Now the frames between, if there are any
2478         sal_Bool bBody = pStartFrm->IsInDocBody();
2479         const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
2480                                                                           ( (SwCellFrm*) pStartFrm->GetUpper() )->GetTabBox() :
2481                                                                           0;
2482         const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
2483         SwRect aPrvRect;
2484 
2485         ASSERT( pCntnt,
2486             "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2487         while (pCntnt && pCntnt != pEndFrm)
2488         {
2489             if ( pCntnt->IsInFly() )
2490             {
2491                 const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
2492                 aSortObjs.Insert( *( const_cast< SwAnchoredObject* >( pObj ) ) );
2493             }
2494 
2495             // Consider only frames which have the same IsInDocBody value like pStartFrm
2496             // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
2497             // same cell frame (or its follow cell)
2498             const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
2499                                                                               ( (SwCellFrm*) pCntnt->GetUpper() )->GetTabBox() :
2500                                                                               0;
2501             if ( bBody == pCntnt->IsInDocBody() &&
2502                  ( !pCellBox || pCellBox == pTmpCellBox ) )
2503             {
2504                 SwRect aCRect( pCntnt->UnionFrm( sal_True ) );
2505                 aCRect.Intersection( pCntnt->PaintArea() );
2506                 if ( aCRect.IsOver( aRegion.GetOrigin() ) )
2507                 {
2508                     SwRect aTmp( aPrvRect );
2509                     aTmp.Union( aCRect );
2510                     if ( ( aPrvRect.Height() * aPrvRect.Width() +
2511                            aCRect.Height() * aCRect.Width() )
2512                          ==
2513                          ( aTmp.Height() * aTmp.Width() ) )
2514                     {
2515                         aPrvRect.Union( aCRect );
2516                     }
2517                     else
2518                     {
2519                         if ( aPrvRect.HasArea() )
2520                             Sub( aRegion, aPrvRect );
2521                         aPrvRect = aCRect;
2522                     }
2523                 }
2524             }
2525             pCntnt = pCntnt->GetNextCntntFrm();
2526             ASSERT( pCntnt,
2527                 "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2528         }
2529         if ( aPrvRect.HasArea() )
2530             Sub( aRegion, aPrvRect );
2531 
2532         //At least the endframe...
2533         bVert = pEndFrm->IsVertical();
2534         bRev = pEndFrm->IsReverse();
2535         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2536         fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
2537                          ( bRev ? fnRectB2T : fnRectHori );
2538         nTmpTwips = ( aEndRect.*fnRect->fnGetTop )();
2539         if ( ( aEndFrm.*fnRect->fnGetTop )() != nTmpTwips )
2540         {
2541             aSubRect = aEndFrm;
2542             ( aSubRect.*fnRect->fnSetBottom )( nTmpTwips );
2543             Sub( aRegion, aSubRect );
2544         }
2545         aSubRect = aEndRect;
2546         if ( bEndR2L )
2547             ( aSubRect.*fnRect->fnSetRight )( ( aEndFrm.*fnRect->fnGetRight )() );
2548         else
2549             ( aSubRect.*fnRect->fnSetLeft )( ( aEndFrm.*fnRect->fnGetLeft )() );
2550         Sub( aRegion, aSubRect );
2551     }
2552 
2553     aRegion.Invert();
2554     delete pSt2Pos;
2555     delete pEnd2Pos;
2556 
2557     //Flys mit Durchlauf ausstanzen. Nicht ausgestanzt werden Flys:
2558     //- die Lower des StartFrm/EndFrm sind (FlyInCnt und alle Flys die wiederum
2559     //	darin sitzen)
2560     //- in der Z-Order ueber denjenigen Flys stehen in denen sich der StartFrm
2561     //	befindet.
2562     const SwPageFrm *pPage		= pStartFrm->FindPageFrm();
2563     const SwPageFrm *pEndPage	= pEndFrm->FindPageFrm();
2564 
2565     while ( pPage )
2566     {
2567         if ( pPage->GetSortedObjs() )
2568         {
2569             const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
2570             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2571             {
2572                 SwAnchoredObject* pAnchoredObj = rObjs[i];
2573                 if ( !pAnchoredObj->ISA(SwFlyFrm) )
2574                     continue;
2575                 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
2576                 const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
2577                 const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
2578                 if ( !pFly->IsAnLower( pStartFrm ) &&
2579                     (rSur.GetSurround() != SURROUND_THROUGHT &&
2580                     !rSur.IsContour()) )
2581                 {
2582                     if ( aSortObjs.Contains( *pAnchoredObj ) )
2583                         continue;
2584 
2585                     sal_Bool bSub = sal_True;
2586                     const sal_uInt32 nPos = pObj->GetOrdNum();
2587                     for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k )
2588                     {
2589                         ASSERT( aSortObjs[k]->ISA(SwFlyFrm),
2590                             "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
2591                         const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
2592                         do
2593                         {
2594                             if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
2595                             {
2596                                 bSub = sal_False;
2597                             }
2598                             else
2599                             {
2600                                 pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
2601                             }
2602                         } while ( bSub && pTmp );
2603                     }
2604                     if ( bSub )
2605                         Sub( aRegion, pFly->Frm() );
2606                 }
2607             }
2608         }
2609         if ( pPage == pEndPage )
2610             break;
2611         else
2612             pPage = (SwPageFrm*)pPage->GetNext();
2613     }
2614 
2615     //Weil's besser aussieht noch die DropCaps ausschliessen.
2616     SwRect aDropRect;
2617     if ( pStartFrm->IsTxtFrm() )
2618     {
2619         if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
2620             Sub( aRegion, aDropRect );
2621     }
2622     if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
2623     {
2624         if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
2625             Sub( aRegion, aDropRect );
2626     }
2627 
2628     rCrsr.Remove( 0, rCrsr.Count() );
2629     rCrsr.Insert( &aRegion, 0 );
2630 }
2631 
2632 
2633