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