/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"


#include <hintids.hxx>
#include <svl/itemiter.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/adjitem.hxx>
#include <editeng/brkitem.hxx>
#include <svx/svdobj.hxx>
#include <crsrsh.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <pagefrm.hxx>
#include <cntfrm.hxx>
#include <rootfrm.hxx>
#include <pam.hxx>
#include <ndtxt.hxx>
#include <fldbas.hxx>
#include <swtable.hxx>
#include <docary.hxx>
#include <txtfld.hxx>
#include <fmtfld.hxx>
#include <txtftn.hxx>
#include <txtinet.hxx>
#include <fmtinfmt.hxx>
#include <txttxmrk.hxx>
#include <frmfmt.hxx>
#include <flyfrm.hxx>
#include <viscrs.hxx>
#include <callnk.hxx>
#include <doctxm.hxx>
#include <docfld.hxx>
#include <expfld.hxx>
#include <reffld.hxx>
#include <flddat.hxx>
#include <cellatr.hxx>
#include <swundo.hxx>
#include <redline.hxx>
#include <fmtcntnt.hxx>
#include <fmthdft.hxx>
#include <pagedesc.hxx>
#include <fesh.hxx>
#include <charfmt.hxx>
#include <fmturl.hxx>
#include "txtfrm.hxx"
#include <wrong.hxx>
#include <switerator.hxx>
#include <vcl/window.hxx>
#include <docufld.hxx> // OD 2008-06-19 #i90516#

using namespace ::com::sun::star;


// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
sal_Bool SwCrsrShell::GotoNextNum()
{
	sal_Bool bRet = GetDoc()->GotoNextNum( *pCurCrsr->GetPoint() );
	if( bRet )
	{
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
		SwCrsrSaveState aSaveState( *pCurCrsr );
		if( !ActionPend() )
		{
			SET_CURR_SHELL( this );
			// dann versuche den Cursor auf die Position zu setzen,
			// auf halber Heohe vom Char-SRectangle
			Point aPt( pCurCrsr->GetPtPos() );
			SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), &aPt,
														pCurCrsr->GetPoint() );
			pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
			pFrm->Calc();
            if( pFrm->IsVertical() )
            {
                aPt.X() = aCharRect.Center().X();
                aPt.Y() = pFrm->Frm().Top() + nUpDownX;
            }
            else
            {
                aPt.Y() = aCharRect.Center().Y();
                aPt.X() = pFrm->Frm().Left() + nUpDownX;
            }
			pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
            bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
                                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
			if( bRet )
				UpdateCrsr(SwCrsrShell::UPDOWN |
						SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
						SwCrsrShell::READONLY );
		}
	}
	return bRet;
}


sal_Bool SwCrsrShell::GotoPrevNum()
{
	sal_Bool bRet = GetDoc()->GotoPrevNum( *pCurCrsr->GetPoint() );
	if( bRet )
	{
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
		SwCrsrSaveState aSaveState( *pCurCrsr );
		if( !ActionPend() )
		{
			SET_CURR_SHELL( this );
			// dann versuche den Cursor auf die Position zu setzen,
			// auf halber Heohe vom Char-SRectangle
			Point aPt( pCurCrsr->GetPtPos() );
			SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->getLayoutFrm( GetLayout(), &aPt,
														pCurCrsr->GetPoint() );
			pFrm->GetCharRect( aCharRect, *pCurCrsr->GetPoint() );
			pFrm->Calc();
            if( pFrm->IsVertical() )
            {
                aPt.X() = aCharRect.Center().X();
                aPt.Y() = pFrm->Frm().Top() + nUpDownX;
            }
            else
            {
                aPt.Y() = aCharRect.Center().Y();
                aPt.X() = pFrm->Frm().Left() + nUpDownX;
            }
			pFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
            bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
                                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
			if( bRet )
				UpdateCrsr(SwCrsrShell::UPDOWN |
						SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
						SwCrsrShell::READONLY );
		}
	}
	return bRet;
}

// springe aus dem Content zum Header

sal_Bool SwCrsrShell::GotoHeaderTxt()
{
	const SwFrm* pFrm = GetCurrFrm()->FindPageFrm();
	while( pFrm && !pFrm->IsHeaderFrm() )
		pFrm = pFrm->GetLower();
	// Header gefunden, dann suche den 1.Cntnt-Frame
	while( pFrm && !pFrm->IsCntntFrm() )
		pFrm = pFrm->GetLower();
	if( pFrm )
	{
		SET_CURR_SHELL( this );
		// hole den Header-Frame
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
        SwCursor *pTmpCrsr = getShellCrsr( true );
		SwCrsrSaveState aSaveState( *pTmpCrsr );
		pFrm->Calc();
		Point aPt( pFrm->Frm().Pos() + pFrm->Prt().Pos() );
		pFrm->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
		if( !pTmpCrsr->IsSelOvr() )
			UpdateCrsr();
		else
			pFrm = 0;
	}
	return 0 != pFrm;
}


// springe aus dem Content zum Footer

sal_Bool SwCrsrShell::GotoFooterTxt()
{
	const SwPageFrm* pFrm = GetCurrFrm()->FindPageFrm();
	if( pFrm )
	{
        const SwFrm* pLower = pFrm->GetLastLower();

		while( pLower && !pLower->IsFooterFrm() )
			pLower = pLower->GetLower();
		// Header gefunden, dann suche den 1.Cntnt-Frame
		while( pLower && !pLower->IsCntntFrm() )
			pLower = pLower->GetLower();

		if( pLower )
		{
            SwCursor *pTmpCrsr = getShellCrsr( true );
            SET_CURR_SHELL( this );
			// hole eine Position im Footer
			SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
			SwCrsrSaveState aSaveState( *pTmpCrsr );
			pLower->Calc();
			Point aPt( pLower->Frm().Pos() + pLower->Prt().Pos() );
			pLower->GetCrsrOfst( pTmpCrsr->GetPoint(), aPt );
			if( !pTmpCrsr->IsSelOvr() )
				UpdateCrsr();
			else
				pFrm = 0;
		}
		else
			pFrm = 0;
	}
	else
		pFrm = 0;
	return 0 != pFrm;
}

sal_Bool SwCrsrShell::SetCrsrInHdFt( sal_uInt16 nDescNo, sal_Bool bInHeader )
{
	sal_Bool bRet = sal_False;
    SwDoc *pMyDoc = GetDoc();

	SET_CURR_SHELL( this );

	if( USHRT_MAX == nDescNo )
	{
		// dann den akt. nehmen
		const SwPageFrm* pPage = GetCurrFrm()->FindPageFrm();
		if( pPage )
            for( sal_uInt16 i = 0; i < pMyDoc->GetPageDescCnt(); ++i )
				if( pPage->GetPageDesc() ==
                    &const_cast<const SwDoc *>(pMyDoc)->GetPageDesc( i ) )
				{
					nDescNo = i;
					break;
				}
	}

    if( USHRT_MAX != nDescNo && nDescNo < pMyDoc->GetPageDescCnt() )
	{
		//dann teste mal, ob ueberhaupt das Attribut vorhanden ist.
        const SwPageDesc& rDesc = const_cast<const SwDoc *>(pMyDoc)
            ->GetPageDesc( nDescNo );
		const SwFmtCntnt* pCnt = 0;
		if( bInHeader )
		{
			// gespiegelte Seiten??? erstmal nicht beachten
			const SwFmtHeader& rHd = rDesc.GetMaster().GetHeader();
			if( rHd.GetHeaderFmt() )
				pCnt = &rHd.GetHeaderFmt()->GetCntnt();
		}
		else
		{
			const SwFmtFooter& rFt = rDesc.GetMaster().GetFooter();
			if( rFt.GetFooterFmt() )
				pCnt = &rFt.GetFooterFmt()->GetCntnt();
		}

		if( pCnt && pCnt->GetCntntIdx() )
		{
			SwNodeIndex aIdx( *pCnt->GetCntntIdx(), 1 );
			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
			if( !pCNd )
                pCNd = pMyDoc->GetNodes().GoNext( &aIdx );

			const SwFrm* pFrm;
			Point aPt( pCurCrsr->GetPtPos() );

			if( pCNd && 0 != ( pFrm = pCNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False ) ))
			{
				// dann kann der Cursor ja auch hinein gesetzt werden
				SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
				SwCrsrSaveState aSaveState( *pCurCrsr );

				ClearMark();

				SwPosition& rPos = *pCurCrsr->GetPoint();
				rPos.nNode = *pCNd;
				rPos.nContent.Assign( pCNd, 0 );

				bRet = !pCurCrsr->IsSelOvr();
				if( bRet )
					UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
								SwCrsrShell::READONLY );
			}
		}
	}
	return bRet;
}

// springe zum naechsten Verzeichnis

sal_Bool SwCrsrShell::GotoNextTOXBase( const String* pName )
{
	sal_Bool bRet = sal_False;

	const SwSectionFmts& rFmts = GetDoc()->GetSections();
	SwCntntNode* pFnd = 0;
	for( sal_uInt16 n = rFmts.Count(); n; )
	{
		const SwSection* pSect = rFmts[ --n ]->GetSection();
		const SwSectionNode* pSectNd;
		if( TOX_CONTENT_SECTION == pSect->GetType() &&
			0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
			 pCurCrsr->GetPoint()->nNode < pSectNd->GetIndex() &&
			( !pFnd || pFnd->GetIndex() > pSectNd->GetIndex() ) &&
// JP 10.12.96: solange wir nur 3 Typen kennen und UI-seitig keine anderen
//				einstellbar sind, muss ueber den Titel gesucht werden!
//			( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTypeName() ) &&
			( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
			)
		{
			SwNodeIndex aIdx( *pSectNd, 1 );
			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
			if( !pCNd )
				pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
			const SwCntntFrm* pCFrm;
			if( pCNd &&
				pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
				0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
				( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
			{
				pFnd = pCNd;
			}
		}
	}
	if( pFnd )
	{
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
		SwCrsrSaveState aSaveState( *pCurCrsr );
		pCurCrsr->GetPoint()->nNode = *pFnd;
		pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
		bRet = !pCurCrsr->IsSelOvr();
		if( bRet )
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	}
	return bRet;
}

// springe zum vorherigen Verzeichnis


sal_Bool SwCrsrShell::GotoPrevTOXBase( const String* pName )
{
	sal_Bool bRet = sal_False;

	const SwSectionFmts& rFmts = GetDoc()->GetSections();
	SwCntntNode* pFnd = 0;
	for( sal_uInt16 n = rFmts.Count(); n; )
	{
		const SwSection* pSect = rFmts[ --n ]->GetSection();
		const SwSectionNode* pSectNd;
		if( TOX_CONTENT_SECTION == pSect->GetType() &&
			0 != ( pSectNd = pSect->GetFmt()->GetSectionNode() ) &&
			pCurCrsr->GetPoint()->nNode > pSectNd->EndOfSectionIndex() &&
			( !pFnd || pFnd->GetIndex() < pSectNd->GetIndex() ) &&
// JP 10.12.96: solange wir nur 3 Typen kennen und UI-seitig keine anderen
//				einstellbar sind, muss ueber den Titel gesucht werden!
//			( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTypeName() ) &&
			( !pName || *pName == ((SwTOXBaseSection*)pSect)->GetTOXName() )
			)
		{
			SwNodeIndex aIdx( *pSectNd, 1 );
			SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
			if( !pCNd )
				pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
			const SwCntntFrm* pCFrm;
			if( pCNd &&
				pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex() &&
				0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
				( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
			{
				pFnd = pCNd;
			}
		}
	}

	if( pFnd )
	{
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
		SwCrsrSaveState aSaveState( *pCurCrsr );
		pCurCrsr->GetPoint()->nNode = *pFnd;
		pCurCrsr->GetPoint()->nContent.Assign( pFnd, 0 );
		bRet = !pCurCrsr->IsSelOvr();
		if( bRet )
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	}
	return bRet;
}

// springe zum Verzeichnis vom TOXMark

sal_Bool SwCrsrShell::GotoTOXMarkBase()
{
	sal_Bool bRet = sal_False;

	SwTOXMarks aMarks;
	sal_uInt16 nCnt = GetDoc()->GetCurTOXMark( *pCurCrsr->GetPoint(), aMarks );
	if( nCnt )
	{
		// dann nehme den 1. und hole den Verzeichnis-Typ.
		// Suche in seiner Abhaengigkeitsliste nach dem eigentlichem
		// Verzeichnis
		const SwTOXType* pType = aMarks[0]->GetTOXType();
		SwIterator<SwTOXBase,SwTOXType> aIter( *pType );
		const SwSectionNode* pSectNd;
		const SwSectionFmt* pSectFmt;

		for( SwTOXBase* pTOX = aIter.First(); pTOX; pTOX = aIter.Next() )
        {
			if( pTOX->ISA( SwTOXBaseSection ) &&
				0 != ( pSectFmt = ((SwTOXBaseSection*)pTOX)->GetFmt() ) &&
				0 != ( pSectNd = pSectFmt->GetSectionNode() ))
			{
				SwNodeIndex aIdx( *pSectNd, 1 );
				SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
				if( !pCNd )
					pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
				const SwCntntFrm* pCFrm;
				if( pCNd &&
					pCNd->EndOfSectionIndex() < pSectNd->EndOfSectionIndex() &&
					0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout() ) ) &&
					( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
				{
					SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
					SwCrsrSaveState aSaveState( *pCurCrsr );
					pCurCrsr->GetPoint()->nNode = *pCNd;
					pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
					bRet = !pCurCrsr->IsInProtectTable() &&
							!pCurCrsr->IsSelOvr();
					if( bRet )
						UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
					break;
				}
			}
	}
	}
	return bRet;
}


	// springe zur naechsten (vorherigen) Tabellenformel
	// optional auch nur zu kaputten Formeln springen
sal_Bool SwCrsrShell::GotoNxtPrvTblFormula( sal_Bool bNext, sal_Bool bOnlyErrors )
{
	if( IsTableMode() )
		return sal_False;

	sal_Bool bFnd = sal_False;
	SwPosition& rPos = *pCurCrsr->GetPoint();

	Point aPt;
	SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
	if( !bNext )
		aFndPos.nNode = 0;
	_SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );

	{
		const SwNode* pSttNd = rPos.nNode.GetNode().FindTableBoxStartNode();
		if( pSttNd )
		{
			const SwTableBox* pTBox = pSttNd->FindTableNode()->GetTable().
										GetTblBox( pSttNd->GetIndex() );
			if( pTBox )
				aCurGEF = _SetGetExpFld( *pTBox );
		}
	}

	if( rPos.nNode < GetDoc()->GetNodes().GetEndOfExtras() )
		// auch beim Einsammeln wird nur der erste Frame benutzt!
		aCurGEF.SetBodyPos( *rPos.nNode.GetNode().GetCntntNode()->getLayoutFrm( GetLayout(),
								&aPt, &rPos, sal_False ) );
	{
		const SfxPoolItem* pItem;
		const SwTableBox* pTBox;
		sal_uInt32 n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA );

		for( n = 0; n < nMaxItems; ++n )
			if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem2(
										RES_BOXATR_FORMULA, n ) ) &&
				0 != (pTBox = ((SwTblBoxFormula*)pItem)->GetTableBox() ) &&
				pTBox->GetSttNd() &&
				pTBox->GetSttNd()->GetNodes().IsDocNodes() &&
				( !bOnlyErrors ||
				  !((SwTblBoxFormula*)pItem)->HasValidBoxes() ) )
			{
				const SwCntntFrm* pCFrm;
				SwNodeIndex aIdx( *pTBox->GetSttNd() );
				const SwCntntNode* pCNd = GetDoc()->GetNodes().GoNext( &aIdx );
				if( pCNd && 0 != ( pCFrm = pCNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False ) ) &&
					(IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
				{
					_SetGetExpFld aCmp( *pTBox );
					aCmp.SetBodyPos( *pCFrm );

					if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
							  : ( aCmp < aCurGEF && aFndGEF < aCmp ))
					{
						aFndGEF = aCmp;
						bFnd = sal_True;
					}
				}
			}
	}

	if( bFnd )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCurCrsr );

		aFndGEF.GetPosOfContent( rPos );
		pCurCrsr->DeleteMark();

		bFnd = !pCurCrsr->IsSelOvr();
		if( bFnd )
			UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
						SwCrsrShell::READONLY );
	}
	return bFnd;
}

// springe zum naechsten (vorherigen) Verzeichniseintrag
sal_Bool SwCrsrShell::GotoNxtPrvTOXMark( sal_Bool bNext )
{
	if( IsTableMode() )
		return sal_False;

	sal_Bool bFnd = sal_False;
	SwPosition& rPos = *pCurCrsr->GetPoint();

	Point aPt;
	SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() );
	if( !bNext )
		aFndPos.nNode = 0;
	_SetGetExpFld aFndGEF( aFndPos ), aCurGEF( rPos );

	if( rPos.nNode.GetIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() )
		// auch beim Einsammeln wird nur der erste Frame benutzt!
		aCurGEF.SetBodyPos( *rPos.nNode.GetNode().
						GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, &rPos, sal_False ) );
	{
		const SfxPoolItem* pItem;
		const SwCntntFrm* pCFrm;
		const SwTxtNode* pTxtNd;
		const SwTxtTOXMark* pTxtTOX;
		sal_uInt32 n, nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK );

		for( n = 0; n < nMaxItems; ++n )
			if( 0 != (pItem = GetDoc()->GetAttrPool().GetItem2(
										RES_TXTATR_TOXMARK, n ) ) &&
				0 != (pTxtTOX = ((SwTOXMark*)pItem)->GetTxtTOXMark() ) &&
				( pTxtNd = &pTxtTOX->GetTxtNode())->GetNodes().IsDocNodes() &&
				0 != ( pCFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, 0, sal_False )) &&
				( IsReadOnlyAvailable() || !pCFrm->IsProtected() ))
			{
				SwNodeIndex aNdIndex( *pTxtNd );	// UNIX benoetigt dieses Obj.
				_SetGetExpFld aCmp( aNdIndex, *pTxtTOX, 0 );
				aCmp.SetBodyPos( *pCFrm );

				if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF )
						  : ( aCmp < aCurGEF && aFndGEF < aCmp ))
				{
					aFndGEF = aCmp;
					bFnd = sal_True;
				}
			}
	}

	if( bFnd )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCurCrsr );

		aFndGEF.GetPosOfContent( rPos );

		bFnd = !pCurCrsr->IsSelOvr();
		if( bFnd )
			UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
						SwCrsrShell::READONLY );
	}
	return bFnd;
}

/*--------------------------------------------------------------------
	 Beschreibung: Traveling zwischen Markierungen
 --------------------------------------------------------------------*/

const SwTOXMark& SwCrsrShell::GotoTOXMark( const SwTOXMark& rStart,
											SwTOXSearch eDir )
{
	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCurCrsr );

	const SwTOXMark& rNewMark = GetDoc()->GotoTOXMark( rStart, eDir,
													IsReadOnlyAvailable() );
	// Position setzen
	SwPosition& rPos = *GetCrsr()->GetPoint();
	rPos.nNode = rNewMark.GetTxtTOXMark()->GetTxtNode();
	rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
						 *rNewMark.GetTxtTOXMark()->GetStart() );

	if( !pCurCrsr->IsSelOvr() )
		UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
					SwCrsrShell::READONLY );

	return rNewMark;
}

// springe zum naechsten / vorherigen FeldTypen

void lcl_MakeFldLst(
    _SetGetExpFlds& rLst,
    const SwFieldType& rFldType,
    const bool bInReadOnly,
    const bool bChkInpFlag = false )
{
    // es muss immer der 1. Frame gesucht werden
    Point aPt;
    SwTxtFld* pTxtFld = NULL;
    SwIterator<SwFmtFld,SwFieldType> aIter(rFldType);
    for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
    {
        pTxtFld = pFmtFld->GetTxtFld();
        if ( pTxtFld != NULL
             && ( !bChkInpFlag
                  || ((SwSetExpField*)pTxtFld->GetFmtFld().GetField())->GetInputFlag() ) )
        {
            const SwTxtNode& rTxtNode = pTxtFld->GetTxtNode();
            const SwCntntFrm* pCFrm =
                rTxtNode.getLayoutFrm( rTxtNode.GetDoc()->GetCurrentLayout(), &aPt, 0, sal_False );
            if ( pCFrm != NULL
                 && ( bInReadOnly || !pCFrm->IsProtected() ) )
            {
                _SetGetExpFld* pNew = new _SetGetExpFld( SwNodeIndex( rTxtNode ), pTxtFld );
                pNew->SetBodyPos( *pCFrm );
                rLst.Insert( pNew );
            }
        }
    }
}


sal_Bool SwCrsrShell::MoveFldType(
    const SwFieldType* pFldType,
    const bool bNext,
    const sal_uInt16 nResType,
    const bool bAddSetExpressionFldsToInputFlds )
{
    // sortierte Liste aller Felder
    _SetGetExpFlds aSrtLst( 64 );

    if ( pFldType )
    {
        if( RES_INPUTFLD != pFldType->Which() && !pFldType->GetDepends() )
        {
            return sal_False;
        }

        // Modify-Object gefunden, trage alle Felder ins Array ein
        ::lcl_MakeFldLst( aSrtLst, *pFldType, ( IsReadOnlyAvailable() ? true : false ) );

        if( RES_INPUTFLD == pFldType->Which() && bAddSetExpressionFldsToInputFlds )
        {
            // es gibt noch versteckte InputFelder in den SetExp. Feldern
            const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
            const sal_uInt16 nSize = rFldTypes.Count();
            for( sal_uInt16 i=0; i < nSize; ++i )
            {
                pFldType = rFldTypes[ i ];
                if ( RES_SETEXPFLD == pFldType->Which() )
                {
                    ::lcl_MakeFldLst( aSrtLst, *pFldType, ( IsReadOnlyAvailable() ? true : false ), true );
                }
            }
        }
    }
    else
    {
        const SwFldTypes& rFldTypes = *pDoc->GetFldTypes();
        const sal_uInt16 nSize = rFldTypes.Count();
        for( sal_uInt16 i=0; i < nSize; ++i )
        {
            pFldType = rFldTypes[ i ];
            if( nResType == pFldType->Which() )
            {
                ::lcl_MakeFldLst( aSrtLst, *pFldType, ( IsReadOnlyAvailable() ? true : false ) );
            }
        }
    }

	// keine Felder gefunden?
	if( !aSrtLst.Count() )
		return sal_False;

	sal_uInt16 nPos;
	SwCursor* pCrsr = getShellCrsr( true );
	{
		// JP 19.08.98: es muss immer ueber das Feld gesucht werden, damit
		//				auch immer das richtige gefunden wird, wenn welche in
		//				Rahmen stehen, die in einem Absatz verankert sind,
		//				in dem ein Feld steht - siehe auch Bug 55247
		const SwPosition& rPos = *pCrsr->GetPoint();

		SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
		ASSERT( pTNd, "Wo ist mein CntntNode?" );

        SwTxtFld * pTxtFld = pTNd->GetFldTxtAttrAt( rPos.nContent.GetIndex(), true );
        const bool bDelFld = ( pTxtFld == NULL );
        if( bDelFld )
        {
            // create dummy for the search
            SwFmtFld* pFmtFld = new SwFmtFld( SwDateTimeField(
                (SwDateTimeFieldType*)pDoc->GetSysFldType( RES_DATETIMEFLD ) ) );

            pTxtFld = new SwTxtFld( *pFmtFld, rPos.nContent.GetIndex(), pDoc->IsClipBoard() );
            pTxtFld->ChgTxtNode( pTNd );
        }

        SwIndex aSearchIdx( rPos.nContent );
        if ( !bDelFld && pTxtFld->HasContent() )
        {
            aSearchIdx = *(pTxtFld->GetStart());
        }
        _SetGetExpFld aSrch( rPos.nNode, pTxtFld, &aSearchIdx );
        if( rPos.nNode.GetIndex() < pDoc->GetNodes().GetEndOfExtras().GetIndex() )
        {
            // auch beim Einsammeln wird nur der erste Frame benutzt!
            Point aPt;
            aSrch.SetBodyPos( *pTNd->getLayoutFrm( GetLayout(), &aPt, &rPos, sal_False ) );
        }

        sal_Bool bFound = aSrtLst.Seek_Entry( &aSrch, &nPos );
        if( bDelFld )
        {
            delete (SwFmtFld*)&pTxtFld->GetAttr();
            delete pTxtFld;
        }

        if( bFound )		// stehe auf einem ?
        {
            if( bNext )
            {
                if( ++nPos >= aSrtLst.Count() )
                    return sal_False;					// schon am Ende
            }
            else if( !nPos-- )
                return sal_False;	  	// weiter nach vorne geht nicht
        }
        else if( bNext ? nPos >= aSrtLst.Count() : !nPos--)
        {
            return sal_False;
        }
    }
    const _SetGetExpFld& rFnd = **( aSrtLst.GetData() + nPos );


	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCrsr );

	rFnd.GetPosOfContent( *pCrsr->GetPoint() );
    sal_Bool bRet = !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
                                     nsSwCursorSelOverFlags::SELOVER_TOGGLE );
	if( bRet )
		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	return bRet;
}


sal_Bool SwCrsrShell::GotoFld( const SwFmtFld& rFld )
{
	sal_Bool bRet = sal_False;
	if( rFld.GetTxtFld() )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen

		SwCursor* pCrsr = getShellCrsr( true );
		SwCrsrSaveState aSaveState( *pCrsr );

		SwTxtNode* pTNd = (SwTxtNode*)rFld.GetTxtFld()->GetpTxtNode();
		pCrsr->GetPoint()->nNode = *pTNd;
		pCrsr->GetPoint()->nContent.Assign( pTNd, *rFld.GetTxtFld()->GetStart() );

		bRet = !pCrsr->IsSelOvr();
		if( bRet )
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	}
	return bRet;
}


SwTxtFld * SwCrsrShell::GetTxtFldAtPos(
    const SwPosition* pPos,
    const bool bIncludeInputFldAtStart ) const
{
    SwTxtFld* pTxtFld = NULL;

    SwTxtNode * const pNode = pPos->nNode.GetNode().GetTxtNode();
    if ( pNode != NULL )
    {
        pTxtFld = pNode->GetFldTxtAttrAt( pPos->nContent.GetIndex(), bIncludeInputFldAtStart );
    }

    return pTxtFld;
}


SwField* SwCrsrShell::GetFieldAtCrsr(
    const SwPaM* pCrsr,
    const bool bIncludeInputFldAtStart ) const
{
    SwField* pFieldAtCrsr = NULL;

    SwTxtFld* pTxtFld = GetTxtFldAtPos( pCrsr->Start(), bIncludeInputFldAtStart );
    if ( pTxtFld != NULL
        && pCrsr->Start()->nNode == pCrsr->End()->nNode )
    {
        const xub_StrLen nTxtFldLength =
            pTxtFld->End() != NULL
            ? *(pTxtFld->End()) - *(pTxtFld->GetStart())
            : 1;
        if ( ( pCrsr->End()->nContent.GetIndex() - pCrsr->Start()->nContent.GetIndex() ) <= nTxtFldLength )
        {
            pFieldAtCrsr = (SwField*)pTxtFld->GetFmtFld().GetField();
        }
    }

    return pFieldAtCrsr;
}


SwField* SwCrsrShell::GetCurFld( const bool bIncludeInputFldAtStart ) const
{
    SwPaM* pCrsr = GetCrsr();
    if ( pCrsr->GetNext() != pCrsr )
    {
        // multi selection not handled.
        return NULL;
    }

    SwField* pCurFld = GetFieldAtCrsr( pCrsr, bIncludeInputFldAtStart );;
    if ( pCurFld != NULL
         && RES_TABLEFLD == pCurFld->GetTyp()->Which() )
    {
        // TabellenFormel ? wandel internen in externen Namen um
        const SwTableNode* pTblNd = IsCrsrInTbl();
        ((SwTblField*)pCurFld)->PtrToBoxNm( pTblNd ? &pTblNd->GetTable() : 0 );
    }

    return pCurFld;
}


bool SwCrsrShell::CrsrInsideInputFld() const
{
    bool bCrsrInsideInputFld = false;

    const SwPaM* pCrsr = GetCrsr();
    const SwPaM* pFirst = pCrsr;
    do
    {
        bCrsrInsideInputFld = dynamic_cast<const SwInputField*>(GetFieldAtCrsr( pCrsr, false )) != NULL;

        pCrsr = static_cast<SwPaM*>(pCrsr->GetNext());
    } while ( !bCrsrInsideInputFld
              && pCrsr != pFirst );

    return bCrsrInsideInputFld;
}


bool SwCrsrShell::PosInsideInputFld( const SwPosition& rPos ) const
{
    return dynamic_cast<const SwTxtInputFld*>(GetTxtFldAtPos( &rPos, false )) != NULL;
}


bool SwCrsrShell::DocPtInsideInputFld( const Point& rDocPt ) const
{
    SwPosition aPos( *(GetCrsr()->Start()) );
    Point aDocPt( rDocPt );
    if ( GetLayout()->GetCrsrOfst( &aPos, aDocPt ) )
    {
        return PosInsideInputFld( aPos );
    }
    return false;
}


xub_StrLen SwCrsrShell::StartOfInputFldAtPos( const SwPosition& rPos ) const
{
    const SwTxtInputFld* pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtFldAtPos( &rPos, true ));
    if ( pTxtInputFld == NULL )
    {
        ASSERT( false, "<SwEditShell::StartOfInputFldAtPos(..)> - no Input Field at given position" );
        return 0;
    }
    return *(pTxtInputFld->GetStart());
}


xub_StrLen SwCrsrShell::EndOfInputFldAtPos( const SwPosition& rPos ) const
{
    const SwTxtInputFld* pTxtInputFld = dynamic_cast<const SwTxtInputFld*>(GetTxtFldAtPos( &rPos, true ));
    if ( pTxtInputFld == NULL )
    {
        ASSERT( false, "<SwEditShell::EndOfInputFldAtPos(..)> - no Input Field at given position" );
        return 0;
    }
    return *(pTxtInputFld->End());
}


void SwCrsrShell::GotoOutline( sal_uInt16 nIdx )
{
	SwCursor* pCrsr = getShellCrsr( true );

	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCrsr );

	const SwNodes& rNds = GetDoc()->GetNodes();
	SwTxtNode* pTxtNd = (SwTxtNode*)rNds.GetOutLineNds()[ nIdx ]->GetTxtNode();
	pCrsr->GetPoint()->nNode = *pTxtNd;
	pCrsr->GetPoint()->nContent.Assign( pTxtNd, 0 );

	if( !pCrsr->IsSelOvr() )
		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
}


sal_Bool SwCrsrShell::GotoOutline( const String& rName )
{
	SwCursor* pCrsr = getShellCrsr( true );

	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCrsr );

	sal_Bool bRet = sal_False;
	if( pDoc->GotoOutline( *pCrsr->GetPoint(), rName ) && !pCrsr->IsSelOvr() )
	{
		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
		bRet = sal_True;
	}
	return bRet;
}



sal_Bool SwCrsrShell::GotoNextOutline()			// naechster Node mit Outline-Num.
{
	SwCursor* pCrsr = getShellCrsr( true );
	const SwNodes& rNds = GetDoc()->GetNodes();

	SwNode* pNd = pCrsr->GetNode();
	sal_uInt16 nPos;
	if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
		++nPos;

	if( nPos == rNds.GetOutLineNds().Count() )
		return sal_False;

	pNd = rNds.GetOutLineNds()[ nPos ];

	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCrsr );
	pCrsr->GetPoint()->nNode = *pNd;
	pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );

	sal_Bool bRet = !pCrsr->IsSelOvr();
	if( bRet )
		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	return bRet;
}


sal_Bool SwCrsrShell::GotoPrevOutline()			// vorheriger Node mit Outline-Num.
{
	SwCursor* pCrsr = getShellCrsr( true );
	const SwNodes& rNds = GetDoc()->GetNodes();

	SwNode* pNd = pCrsr->GetNode();
	sal_uInt16 nPos;
	rNds.GetOutLineNds().Seek_Entry( pNd, &nPos );

	sal_Bool bRet = sal_False;
	if( nPos )
	{
		--nPos;	// davor

		pNd = rNds.GetOutLineNds()[ nPos ];
		if( pNd->GetIndex() > pCrsr->GetPoint()->nNode.GetIndex() )
			return sal_False;

		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCrsr );
		pCrsr->GetPoint()->nNode = *pNd;
		pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)pNd, 0 );

		bRet = !pCrsr->IsSelOvr();
		if( bRet )
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	}
	return bRet;
}


	// suche die "Outline-Position" vom vorherigen Outline-Node mit dem
	// Level.
sal_uInt16 SwCrsrShell::GetOutlinePos( sal_uInt8 nLevel )
{
	SwPaM* pCrsr = getShellCrsr( true );
	const SwNodes& rNds = GetDoc()->GetNodes();

	SwNode* pNd = pCrsr->GetNode();
	sal_uInt16 nPos;
	if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ))
		nPos++;			// steht auf der Position, fuers while zum Naechsten

	while( nPos-- )		// immer den davor testen !
	{
		pNd = rNds.GetOutLineNds()[ nPos ];

		//if( ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() <= nLevel )//#outline level,zhaojianwei
		if( ((SwTxtNode*)pNd)->GetAttrOutlineLevel()-1 <= nLevel )//<-end,zhaojianwei
			return nPos;

	}
	return USHRT_MAX;		// davor keiner mehr also Ende
}


sal_Bool SwCrsrShell::MakeOutlineSel( sal_uInt16 nSttPos, sal_uInt16 nEndPos,
									sal_Bool bWithChilds )
{
	const SwNodes& rNds = GetDoc()->GetNodes();
	const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
	if( !rOutlNds.Count() )		// wie jetzt ???
		return sal_False;

	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen

	if( nSttPos > nEndPos )			// sollte jemand das vertauscht haben?
	{
		ASSERT( !this, "Start- > Ende-Position im Array" );
		sal_uInt16 nTmp = nSttPos;
		nSttPos = nEndPos;
		nEndPos = nTmp;
	}

	SwNode* pSttNd = rOutlNds[ nSttPos ];
	SwNode* pEndNd = rOutlNds[ nEndPos ];

	if( bWithChilds )
	{
		//sal_uInt8 nLevel = pEndNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
        const int nLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end.zhaojianwei
		for( ++nEndPos; nEndPos < rOutlNds.Count(); ++nEndPos )
		{
			pEndNd = rOutlNds[ nEndPos ];
			//sal_uInt8 nNxtLevel = pEndNd->GetTxtNode()->GetTxtColl()->GetOutlineLevel();//#outline level,zhaojianwei
            const int nNxtLevel = pEndNd->GetTxtNode()->GetAttrOutlineLevel()-1;//<-end,zhaojianwei
			if( nNxtLevel <= nLevel )
				break;			// EndPos steht jetzt auf dem naechsten
		}
	}
	// ohne Childs, dann aber zumindest auf den naechsten
	else if( ++nEndPos < rOutlNds.Count() )
		pEndNd = rOutlNds[ nEndPos ];

	if( nEndPos == rOutlNds.Count() )		// kein Ende gefunden
		pEndNd = &rNds.GetEndOfContent();

	KillPams();

	SwCrsrSaveState aSaveState( *pCurCrsr );

	// Jetzt das Ende ans Ende vom voherigen ContentNode setzen
	pCurCrsr->GetPoint()->nNode = *pSttNd;
	pCurCrsr->GetPoint()->nContent.Assign( pSttNd->GetCntntNode(), 0 );
	pCurCrsr->SetMark();
	pCurCrsr->GetPoint()->nNode = *pEndNd;
	pCurCrsr->Move( fnMoveBackward, fnGoNode );		// ans Ende vom Vorgaenger

	// und schon ist alles selektiert
	sal_Bool bRet = !pCurCrsr->IsSelOvr();
	if( bRet )
		UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	return bRet;
}


// springe zu dieser Refmark
sal_Bool SwCrsrShell::GotoRefMark( const String& rRefMark, sal_uInt16 nSubType,
									sal_uInt16 nSeqNo )
{
	SET_CURR_SHELL( this );
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCurCrsr );

	sal_uInt16 nPos;
	SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark,
													nSubType, nSeqNo, &nPos );
	if( pTxtNd && pTxtNd->GetNodes().IsDocNodes() )
	{
		pCurCrsr->GetPoint()->nNode = *pTxtNd;
		pCurCrsr->GetPoint()->nContent.Assign( pTxtNd, nPos );

		if( !pCurCrsr->IsSelOvr() )
		{
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
			return sal_True;
		}
	}
	return sal_False;
}

sal_Bool SwCrsrShell::IsPageAtPos( const Point &rPt ) const
{
    if( GetLayout() )
        return 0 != GetLayout()->GetPageAtPos( rPt );
    return sal_False;
}

sal_Bool SwCrsrShell::GetContentAtPos( const Point& rPt,
                                   SwContentAtPos& rCntntAtPos,
                                   sal_Bool bSetCrsr,
                                   SwRect* pFldRect )
{
    SET_CURR_SHELL( this );
    sal_Bool bRet = sal_False;

    if( !IsTableMode() )
    {
        Point aPt( rPt );
        SwPosition aPos( *pCurCrsr->GetPoint() );

        SwTxtNode* pTxtNd;
        SwCntntFrm *pFrm(0);
        SwTxtAttr* pTxtAttr;
        SwCrsrMoveState aTmpState;
        aTmpState.bFieldInfo = sal_True;
        aTmpState.bExactOnly = !( SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos );
        aTmpState.bCntntCheck = (SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos) ?  sal_True : sal_False;
        aTmpState.bSetInReadOnly = IsReadOnlyAvailable();

        SwSpecialPos aSpecialPos;
        aTmpState.pSpecialPos = ( SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos ) ?
                                &aSpecialPos : 0;

        const sal_Bool bCrsrFoundExact = GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
        pTxtNd = aPos.nNode.GetNode().GetTxtNode();

        const SwNodes& rNds = GetDoc()->GetNodes();
        if( pTxtNd
            && SwContentAtPos::SW_OUTLINE & rCntntAtPos.eCntntAtPos
            && rNds.GetOutLineNds().Count() )
        {
            const SwTxtNode* pONd = pTxtNd->FindOutlineNodeOfLevel( MAXLEVEL-1);
            if( pONd )
            {
                rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_OUTLINE;
                rCntntAtPos.sStr = pONd->GetExpandTxt( 0, STRING_LEN, true );
                bRet = sal_True;
            }
        }
        else if ( SwContentAtPos::SW_CONTENT_CHECK & rCntntAtPos.eCntntAtPos
                  && bCrsrFoundExact )
        {
            bRet = sal_True;
        }
        else if( pTxtNd
                 && SwContentAtPos::SW_NUMLABEL & rCntntAtPos.eCntntAtPos)
        {
            bRet = aTmpState.bInNumPortion;
            rCntntAtPos.aFnd.pNode = pTxtNd;

            Size aSizeLogic(aTmpState.nInNumPostionOffset, 0);
            Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic);
            rCntntAtPos.nDist = aSizePixel.Width();
        }
        else if( bCrsrFoundExact && pTxtNd )
        {
            if( !aTmpState.bPosCorr )
            {
                if ( !bRet
                     && SwContentAtPos::SW_SMARTTAG & rCntntAtPos.eCntntAtPos
                     && !aTmpState.bFtnNoInfo )
                {
                    const SwWrongList* pSmartTagList = pTxtNd->GetSmartTags();
                    xub_StrLen nCurrent = aPos.nContent.GetIndex();
                    xub_StrLen nBegin = nCurrent;
                    xub_StrLen nLen = 1;

                    if ( pSmartTagList && pSmartTagList->InWrongWord( nCurrent, nLen ) && !pTxtNd->IsSymbol(nBegin) )
                    {
                        const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
                        const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
                        if ( pSubList )
                        {
                            nCurrent = aTmpState.pSpecialPos->nCharOfst;

                            if ( pSubList->InWrongWord( nCurrent, nLen ) )
                                bRet = sal_True;
                        }
                        else
                            bRet = sal_True;

                        if( bRet && bSetCrsr )
                        {
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
                            pCurCrsr->DeleteMark();
                            *pCurCrsr->GetPoint() = aPos;
                            if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION | nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
                                bRet = sal_False;
                            else
                                UpdateCrsr();
                        }
                        if( bRet )
                        {
                            rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_SMARTTAG;

                            if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                                pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
                        }
                    }
                }

                if ( !bRet
                     && ( SwContentAtPos::SW_FIELD | SwContentAtPos::SW_CLICKFIELD ) & rCntntAtPos.eCntntAtPos
                     && !aTmpState.bFtnNoInfo )
                {
                    pTxtAttr = pTxtNd->GetFldTxtAttrAt( aPos.nContent.GetIndex() );
                    const SwField* pFld = pTxtAttr != NULL
                                          ? pTxtAttr->GetFmtFld().GetField()
                                          : 0;
                    if ( SwContentAtPos::SW_CLICKFIELD & rCntntAtPos.eCntntAtPos
                         && pFld && !pFld->HasClickHdl() )
                    {
                        pFld = 0;
                    }

                    if ( pFld )
                    {
                        if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                            pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );

                        if( bSetCrsr )
                        {
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            pCurCrsr->DeleteMark();
                            *pCurCrsr->GetPoint() = aPos;
                            if( pCurCrsr->IsSelOvr() )
                            {
                                // Click-Felder in geschuetzten Bereichen zulassen
                                // Nur Platzhalter geht nicht!
                                if( SwContentAtPos::SW_FIELD & rCntntAtPos.eCntntAtPos
                                    || RES_JUMPEDITFLD == pFld->Which() )
                                    pFld = 0;
                            }
                            else
                                UpdateCrsr();
                        }
                        else if( RES_TABLEFLD == pFld->Which() &&
                            ((SwTblField*)pFld)->IsIntrnlName() )
                        {
                            // erzeuge aus der internen (fuer CORE)
                            // die externe (fuer UI) Formel
                            const SwTableNode* pTblNd = pTxtNd->FindTableNode();
                            if( pTblNd )		// steht in einer Tabelle
                                ((SwTblField*)pFld)->PtrToBoxNm( &pTblNd->GetTable() );
                        }
                    }

                    if( pFld )
                    {
                        rCntntAtPos.aFnd.pFld = pFld;
                        rCntntAtPos.pFndTxtAttr = pTxtAttr;
                        rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FIELD;
                        bRet = sal_True;
                    }
                }

                if( !bRet && SwContentAtPos::SW_FORMCTRL & rCntntAtPos.eCntntAtPos )
                {
                    IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
                    sw::mark::IFieldmark* pFldBookmark = pMarksAccess->getFieldmarkFor( aPos );
                    if( bCrsrFoundExact && pTxtNd && pFldBookmark) {
                        rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FORMCTRL;
                        rCntntAtPos.aFnd.pFldmark = pFldBookmark;
                        bRet=sal_True;
                    }
                }

                if( !bRet && SwContentAtPos::SW_FTN & rCntntAtPos.eCntntAtPos )
                {
                    if( aTmpState.bFtnNoInfo )
                    {
                        // stehe ueber dem Zeichen der Fussnote (??)
                        bRet = sal_True;
                        if( bSetCrsr )
                        {
                            *pCurCrsr->GetPoint() = aPos;
                            if( !GotoFtnAnchor() )
                                bRet = sal_False;
                        }
                        if( bRet )
                            rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
                    }
                    else if ( 0 != ( pTxtAttr = pTxtNd->GetTxtAttrForCharAt(
                        aPos.nContent.GetIndex(), RES_TXTATR_FTN )) )
                    {
                        bRet = sal_True;
                        if( bSetCrsr )
                        {
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            pCurCrsr->GetPoint()->nNode = *((SwTxtFtn*)pTxtAttr)->GetStartNode();
                            SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
                                &pCurCrsr->GetPoint()->nNode,
                                sal_True, !IsReadOnlyAvailable() );

                            if( pCNd )
                            {
                                pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
                                if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
                                    nsSwCursorSelOverFlags::SELOVER_TOGGLE ))
                                    bRet = sal_False;
                                else
                                    UpdateCrsr();
                            }
                            else
                                bRet = sal_False;
                        }

                        if( bRet )
                        {
                            rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_FTN;
                            rCntntAtPos.pFndTxtAttr = pTxtAttr;
                            rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();

                            if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                                pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
                        }
                    }
                }

                if( !bRet
                    && ( SwContentAtPos::SW_TOXMARK | SwContentAtPos::SW_REFMARK ) & rCntntAtPos.eCntntAtPos
                    && !aTmpState.bFtnNoInfo )
                {
                    pTxtAttr = 0;
                    if( SwContentAtPos::SW_TOXMARK & rCntntAtPos.eCntntAtPos )
                    {
                        ::std::vector<SwTxtAttr *> const marks(
                            pTxtNd->GetTxtAttrsAt(
                               aPos.nContent.GetIndex(), RES_TXTATR_TOXMARK));
                        if (marks.size())
                        {   // hmm... can only return 1 here
                            pTxtAttr = *marks.begin();
                        }
                    }

                    if( !pTxtAttr &&
                        SwContentAtPos::SW_REFMARK & rCntntAtPos.eCntntAtPos )
                    {
                        ::std::vector<SwTxtAttr *> const marks(
                            pTxtNd->GetTxtAttrsAt(
                               aPos.nContent.GetIndex(), RES_TXTATR_REFMARK));
                        if (marks.size())
                        {   // hmm... can only return 1 here
                            pTxtAttr = *marks.begin();
                        }
                    }

                    if( pTxtAttr )
                    {
                        bRet = sal_True;
                        if( bSetCrsr )
                        {
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            pCurCrsr->DeleteMark();
                            *pCurCrsr->GetPoint() = aPos;
                            if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION | nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
                                bRet = sal_False;
                            else
                                UpdateCrsr();
                        }

                        if( bRet )
                        {
                            const xub_StrLen* pEnd = pTxtAttr->End();
                            if( pEnd )
                                rCntntAtPos.sStr =
                                    pTxtNd->GetExpandTxt( *pTxtAttr->GetStart(), *pEnd - *pTxtAttr->GetStart() );
                            else if( RES_TXTATR_TOXMARK == pTxtAttr->Which())
                                rCntntAtPos.sStr =
                                    pTxtAttr->GetTOXMark().GetAlternativeText();

                            rCntntAtPos.eCntntAtPos =
                                RES_TXTATR_TOXMARK == pTxtAttr->Which()
                                ? SwContentAtPos::SW_TOXMARK
                                : SwContentAtPos::SW_REFMARK;
                            rCntntAtPos.pFndTxtAttr = pTxtAttr;
                            rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();

                            if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                                pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
                        }
                    }
                }

                if ( !bRet
                     && SwContentAtPos::SW_INETATTR & rCntntAtPos.eCntntAtPos
                     && !aTmpState.bFtnNoInfo )
                {
                    pTxtAttr = pTxtNd->GetTxtAttrAt(
                            aPos.nContent.GetIndex(), RES_TXTATR_INETFMT);
                    // nur INetAttrs mit URLs "erkennen"
                    if( pTxtAttr && pTxtAttr->GetINetFmt().GetValue().Len() )
                    {
                        bRet = sal_True;
                        if( bSetCrsr )
                        {
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
                            pCurCrsr->DeleteMark();
                            *pCurCrsr->GetPoint() = aPos;
                            if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
                                nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
                                bRet = sal_False;
                            else
                                UpdateCrsr();
                        }
                        if( bRet )
                        {
                            rCntntAtPos.sStr = pTxtNd->GetExpandTxt(
                                *pTxtAttr->GetStart(),
                                *pTxtAttr->GetEnd() - *pTxtAttr->GetStart() );

                            rCntntAtPos.aFnd.pAttr = &pTxtAttr->GetAttr();
                            rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_INETATTR;
                            rCntntAtPos.pFndTxtAttr = pTxtAttr;

                            if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                                pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
                        }
                    }
                }

                if( !bRet && SwContentAtPos::SW_REDLINE & rCntntAtPos.eCntntAtPos )
                {
                    const SwRedline* pRedl = GetDoc()->GetRedline(aPos, NULL);
                    if( pRedl )
                    {
                        rCntntAtPos.aFnd.pRedl = pRedl;
                        rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_REDLINE;
                        rCntntAtPos.pFndTxtAttr = 0;
                        bRet = sal_True;

                        if( pFldRect && 0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt ) ) )
                            pFrm->GetCharRect( *pFldRect, aPos, &aTmpState );
                    }
                }
            }

            if( !bRet
                 && ( SwContentAtPos::SW_TABLEBOXFML & rCntntAtPos.eCntntAtPos
#ifdef DBG_UTIL
                      || SwContentAtPos::SW_TABLEBOXVALUE & rCntntAtPos.eCntntAtPos
#endif
                ) )
            {
                const SwTableNode* pTblNd;
                const SwTableBox* pBox;
                const SwStartNode* pSttNd = pTxtNd->FindTableBoxStartNode();
                const SfxPoolItem* pItem;
                if( pSttNd && 0 != ( pTblNd = pTxtNd->FindTableNode()) &&
                    0 != ( pBox = pTblNd->GetTable().GetTblBox(
                    pSttNd->GetIndex() )) &&
#ifdef DBG_UTIL
                    ( SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
                    RES_BOXATR_FORMULA, sal_False, &pItem )	||
                    SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
                    RES_BOXATR_VALUE, sal_False, &pItem ))
#else
                    SFX_ITEM_SET == pBox->GetFrmFmt()->GetItemState(
                    RES_BOXATR_FORMULA, sal_False, &pItem )
#endif
                    )
                {
                    SwFrm* pF = pTxtNd->getLayoutFrm( GetLayout(), &aPt );
                    if( pF )
                    {
                        // dann aber den CellFrame
                        pFrm = (SwCntntFrm*)pF;
                        while( pF && !pF->IsCellFrm() )
                            pF = pF->GetUpper();
                    }

                    // es wurde ein
                    if( aTmpState.bPosCorr )
                    {
                        if( pF && !pF->Frm().IsInside( aPt ))
                            pF = 0;
                    }
                    else if( !pF )
                        pF = pFrm;

                    if( pF )			// nur dann ist es gueltig!!
                    {
                        // erzeuge aus der internen (fuer CORE)
                        // die externe (fuer UI) Formel
                        rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXFML;
#ifdef DBG_UTIL
                        if( RES_BOXATR_VALUE == pItem->Which() )
                            rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_TABLEBOXVALUE;
                        else
#endif
                            ((SwTblBoxFormula*)pItem)->PtrToBoxNm( &pTblNd->GetTable() );

                        bRet = sal_True;
                        if( bSetCrsr )
                        {
                            SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
                            SwCrsrSaveState aSaveState( *pCurCrsr );
                            *pCurCrsr->GetPoint() = aPos;
                            if( pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
                                nsSwCursorSelOverFlags::SELOVER_TOGGLE) )
                                bRet = sal_False;
                            else
                                UpdateCrsr();
                        }

                        if( bRet )
                        {
                            if( pFldRect )
                            {
                                *pFldRect = pF->Prt();
                                *pFldRect += pF->Frm().Pos();
                            }
                            rCntntAtPos.pFndTxtAttr = 0;
                            rCntntAtPos.aFnd.pAttr = pItem;
                        }
                    }
                }
            }

#ifdef DBG_UTIL
            if( !bRet && SwContentAtPos::SW_CURR_ATTRS & rCntntAtPos.eCntntAtPos )
            {
                xub_StrLen n = aPos.nContent.GetIndex();
                SfxItemSet aSet( GetDoc()->GetAttrPool(), POOLATTR_BEGIN,
                    POOLATTR_END - 1 );
                if( pTxtNd->GetpSwpHints() )
                {
                    for( sal_uInt16 i = 0; i < pTxtNd->GetSwpHints().Count(); ++i )
                    {
                        const SwTxtAttr* pHt = pTxtNd->GetSwpHints()[i];
                        xub_StrLen nAttrStart = *pHt->GetStart();
                        if( nAttrStart > n ) 		// ueber den Bereich hinaus
                            break;

                        if( 0 != pHt->End() && (
                            ( nAttrStart < n &&
                            ( pHt->DontExpand() ? n < *pHt->End()
                            : n <= *pHt->End() )) ||
                            ( n == nAttrStart &&
                            ( nAttrStart == *pHt->End() || !n ))) )
                        {
                            aSet.Put( pHt->GetAttr() );
                        }
                    }
                    if( pTxtNd->HasSwAttrSet() &&
                        pTxtNd->GetpSwAttrSet()->Count() )
                    {
                        SfxItemSet aFmtSet( pTxtNd->GetSwAttrSet() );
                        // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
                        aFmtSet.Differentiate( aSet );
                        // jetzt alle zusammen "mergen"
                        aSet.Put( aFmtSet );
                    }
                }
                else
                    pTxtNd->SwCntntNode::GetAttr( aSet );

                rCntntAtPos.sStr.AssignAscii(
                    RTL_CONSTASCII_STRINGPARAM( "Pos: (" ));
                rCntntAtPos.sStr += String::CreateFromInt32( aPos.nNode.GetIndex());
                rCntntAtPos.sStr += ':';
                rCntntAtPos.sStr += String::CreateFromInt32( aPos.nContent.GetIndex());
                rCntntAtPos.sStr += ')';
                rCntntAtPos.sStr.AppendAscii(
                    RTL_CONSTASCII_STRINGPARAM( "\nAbs.Vorl.: " ));
                rCntntAtPos.sStr += pTxtNd->GetFmtColl()->GetName();
                if( pTxtNd->GetCondFmtColl() )
                    rCntntAtPos.sStr.AppendAscii(
                    RTL_CONSTASCII_STRINGPARAM( "\nBed.Vorl.: " ))
                    += pTxtNd->GetCondFmtColl()->GetName();

                if( aSet.Count() )
                {
                    String sAttrs;
                    SfxItemIter aIter( aSet );
                    const SfxPoolItem* pItem = aIter.FirstItem();
                    while( sal_True )
                    {
                        if( !IsInvalidItem( pItem ))
                        {
                            String aStr;
                            GetDoc()->GetAttrPool().GetPresentation( *pItem,
                                SFX_ITEM_PRESENTATION_COMPLETE,
                                SFX_MAPUNIT_CM, aStr );
                            if( sAttrs.Len() )
                                sAttrs.AppendAscii(
                                RTL_CONSTASCII_STRINGPARAM( ", " ));
                            sAttrs += aStr;
                        }
                        if( aIter.IsAtEnd() )
                            break;
                        pItem = aIter.NextItem();
                    }
                    if( sAttrs.Len() )
                    {
                        if( rCntntAtPos.sStr.Len() )
                            rCntntAtPos.sStr += '\n';
                        rCntntAtPos.sStr.AppendAscii(
                            RTL_CONSTASCII_STRINGPARAM( "Attr: " ) )
                            += sAttrs;
                    }
                }
                bRet = sal_True;
                rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_CURR_ATTRS;
            }
#endif
        }
    }

    if( !bRet )
    {
        rCntntAtPos.eCntntAtPos = SwContentAtPos::SW_NOTHING;
        rCntntAtPos.aFnd.pFld = 0;
    }
    return bRet;
}

const SwPostItField* SwCrsrShell::GetPostItFieldAtCursor() const
{
    const SwPostItField* pPostItFld = 0;

    if ( !IsTableMode() )
    {
        const SwPosition* pCursorPos = _GetCrsr()->GetPoint();
        const SwTxtNode* pTxtNd = pCursorPos->nNode.GetNode().GetTxtNode();
        if ( pTxtNd )
        {
            SwTxtAttr* pTxtAttr = pTxtNd->GetFldTxtAttrAt( pCursorPos->nContent.GetIndex() );
            const SwField* pFld = pTxtAttr != NULL ? pTxtAttr->GetFmtFld().GetField() : 0;
            if ( pFld && pFld->Which()== RES_POSTITFLD )
            {
                pPostItFld = static_cast<const SwPostItField*>(pFld);
            }
        }
    }

    return pPostItFld;
}

// befindet sich der Node in einem geschuetzten Bereich?
sal_Bool SwContentAtPos::IsInProtectSect() const
{
	const SwTxtNode* pNd = 0;
	if( pFndTxtAttr )
	{
		switch( eCntntAtPos )
		{
		case SW_FIELD:
		case SW_CLICKFIELD:
			pNd = ((SwTxtFld*)pFndTxtAttr)->GetpTxtNode();
			break;

		case SW_FTN:
			pNd = &((SwTxtFtn*)pFndTxtAttr)->GetTxtNode();
			break;

		case SW_INETATTR:
			pNd = ((SwTxtINetFmt*)pFndTxtAttr)->GetpTxtNode();
			break;

		default:
			break;
		}
	}

	const SwCntntFrm* pFrm;
	return pNd && ( pNd->IsInProtectSect() ||
					( 0 != ( pFrm = pNd->getLayoutFrm( pNd->GetDoc()->GetCurrentLayout(), 0,0,sal_False)) &&
						pFrm->IsProtected() ));
}

bool SwContentAtPos::IsInRTLText()const
{
    bool bRet = false;
    const SwTxtNode* pNd = 0;
    if (pFndTxtAttr && (eCntntAtPos == SW_FTN))
    {
        const SwTxtFtn* pTxtFtn = static_cast<const SwTxtFtn*>(pFndTxtAttr);
        if(pTxtFtn->GetStartNode())
        {
            SwStartNode* pSttNd = pTxtFtn->GetStartNode()->GetNode().GetStartNode();
            SwPaM aTemp( *pSttNd );
            aTemp.Move(fnMoveForward, fnGoNode);
            SwCntntNode* pCntntNode = aTemp.GetCntntNode();
            if(pCntntNode && pCntntNode->IsTxtNode())
                pNd = static_cast<SwTxtNode*>(pCntntNode);
        }
    }
    if(pNd)
    {
        SwIterator<SwTxtFrm,SwTxtNode> aIter(*pNd);
        SwTxtFrm* pTmpFrm = aIter.First();
        while( pTmpFrm )
        {
                if ( !pTmpFrm->IsFollow())
                {
                    bRet = pTmpFrm->IsRightToLeft();
                    break;
                }
            pTmpFrm = aIter.Next();
        }
    }
    return bRet;
}


sal_Bool SwCrsrShell::SelectTxt( const xub_StrLen nStart,
                                 const xub_StrLen nEnd )
{
    SET_CURR_SHELL( this );
    sal_Bool bRet = sal_False;

    SwCallLink aLk( *this );
    SwCrsrSaveState aSaveState( *pCurCrsr );

    SwPosition& rPos = *pCurCrsr->GetPoint();
    pCurCrsr->DeleteMark();
    rPos.nContent = nStart;
    pCurCrsr->SetMark();
    rPos.nContent = nEnd;

    if( !pCurCrsr->IsSelOvr() )
    {
        UpdateCrsr();
        bRet = sal_True;
    }

    return bRet;
}


sal_Bool SwCrsrShell::SelectTxtAttr( sal_uInt16 nWhich,
                                     sal_Bool bExpand,
                                     const SwTxtAttr* pTxtAttr )
{
    SET_CURR_SHELL( this );
    sal_Bool bRet = sal_False;

    if( !IsTableMode() )
    {
        if( !pTxtAttr )
        {
            SwPosition& rPos = *pCurCrsr->GetPoint();
            SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
            pTxtAttr = (pTxtNd)
                ? pTxtNd->GetTxtAttrAt(rPos.nContent.GetIndex(),
                        static_cast<RES_TXTATR>(nWhich),
                        (bExpand) ? SwTxtNode::EXPAND : SwTxtNode::DEFAULT)
                : 0;
        }

        if( pTxtAttr )
        {
            const xub_StrLen* pEnd = pTxtAttr->End();
            bRet = SelectTxt( *pTxtAttr->GetStart(), ( pEnd ? *pEnd : *pTxtAttr->GetStart() + 1 ) );
        }
    }
    return bRet;
}


sal_Bool SwCrsrShell::GotoINetAttr( const SwTxtINetFmt& rAttr )
{
	sal_Bool bRet = sal_False;
	if( rAttr.GetpTxtNode() )
	{
		SwCursor* pCrsr = getShellCrsr( true );

		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCrsr );

		pCrsr->GetPoint()->nNode = *rAttr.GetpTxtNode();
		pCrsr->GetPoint()->nContent.Assign( (SwTxtNode*)rAttr.GetpTxtNode(),
											*rAttr.GetStart() );
		bRet = !pCrsr->IsSelOvr();
		if( bRet )
			UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
	}
	return bRet;
}


const SwFmtINetFmt* SwCrsrShell::FindINetAttr( const String& rName ) const
{
	return pDoc->FindINetAttr( rName );
}

sal_Bool SwCrsrShell::GetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode,
                                SwRect& rRect, sal_Int16& rOrient )
{

	SET_CURR_SHELL( this );
	sal_Bool bRet = sal_False;

    if (!IsTableMode() && !HasSelection()
        && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
    {
		Point aPt( rPt );
		SwPosition aPos( *pCurCrsr->GetPoint() );

		SwFillCrsrPos aFPos( eFillMode );
		SwCrsrMoveState aTmpState( &aFPos );

		if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) &&
			!aPos.nNode.GetNode().IsProtect())
		{
			// Start-Position im geschuetzten Bereich?
			rRect = aFPos.aCrsr;
			rOrient = aFPos.eOrient;
			bRet = sal_True;
		}
	}
	return bRet;
}

sal_Bool SwCrsrShell::SetShadowCrsrPos( const Point& rPt, SwFillMode eFillMode )
{
	SET_CURR_SHELL( this );
	sal_Bool bRet = sal_False;

    if (!IsTableMode() && !HasSelection()
        && GetDoc()->GetIDocumentUndoRedo().DoesUndo())
	{
		Point aPt( rPt );
		SwPosition aPos( *pCurCrsr->GetPoint() );

		SwFillCrsrPos aFPos( eFillMode );
		SwCrsrMoveState aTmpState( &aFPos );

		if( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState ) )
		{
			SwCallLink aLk( *this );        // Crsr-Moves ueberwachen
			StartAction();

			SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
            SwUndoId nUndoId = UNDO_INS_FROM_SHADOWCRSR;
			// Werden nur die Absatzattribute Adjust oder LRSpace gesetzt,
			// dann sollte der naechste Aufruf die NICHT wieder entfernen.
			if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt &&
				( FILL_INDENT == aFPos.eMode ||
                  ( text::HoriOrientation::NONE != aFPos.eOrient &&
					0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) &&
				pCNd && pCNd->Len() )
                nUndoId = UNDO_EMPTY;

            GetDoc()->GetIDocumentUndoRedo().StartUndo( nUndoId, NULL );

			SwTxtFmtColl* pNextFmt = 0;
			SwTxtNode* pTNd = pCNd->GetTxtNode();
			if( pTNd )
				pNextFmt = &pTNd->GetTxtColl()->GetNextTxtFmtColl();

			const SwSectionNode* pSectNd = pCNd->FindSectionNode();
			if( pSectNd && aFPos.nParaCnt )
			{
				SwNodeIndex aEnd( aPos.nNode, 1 );
				while( aEnd.GetNode().IsEndNode() &&
						(const SwNode*)&aEnd.GetNode() !=
						pSectNd->EndOfSectionNode() )
					aEnd++;

				if( aEnd.GetNode().IsEndNode() &&
					pCNd->Len() == aPos.nContent.GetIndex() )
					aPos.nNode = *pSectNd->EndOfSectionNode();
			}

			for( sal_uInt16 n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n )
			{
				GetDoc()->AppendTxtNode( aPos );
				if( !n && pNextFmt )
				{
					*pCurCrsr->GetPoint() = aPos;
                    GetDoc()->SetTxtFmtColl( *pCurCrsr, pNextFmt, false );
					//JP 04.11.97: erstmal keine Folgevorlage der
					//				Folgevorlage beachten
					// pNextFmt = pNextFmt->GetNextTxtFmtColl();
				}
				if( n < aFPos.nColumnCnt )
				{
					*pCurCrsr->GetPoint() = aPos;
                    GetDoc()->InsertPoolItem( *pCurCrsr,
                            SvxFmtBreakItem( SVX_BREAK_COLUMN_BEFORE, RES_BREAK ), 0);
				}
			}

			*pCurCrsr->GetPoint() = aPos;
			switch( aFPos.eMode )
			{
			case FILL_INDENT:
				if( 0 != (pCNd = aPos.nNode.GetNode().GetCntntNode() ))
				{
					SfxItemSet aSet( GetDoc()->GetAttrPool(),
									RES_LR_SPACE, RES_LR_SPACE,
									RES_PARATR_ADJUST, RES_PARATR_ADJUST,
									0 );
					SvxLRSpaceItem aLR( (SvxLRSpaceItem&)
										pCNd->GetAttr( RES_LR_SPACE ) );
					aLR.SetTxtLeft( aFPos.nTabCnt );
					aLR.SetTxtFirstLineOfst( 0 );
					aSet.Put( aLR );

					const SvxAdjustItem& rAdj = (SvxAdjustItem&)pCNd->
										GetAttr( RES_PARATR_ADJUST );
					if( SVX_ADJUST_LEFT != rAdj.GetAdjust() )
                        aSet.Put( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );

                    GetDoc()->InsertItemSet( *pCurCrsr, aSet, 0 );
                }
				else {
					ASSERT( !this, "wo ist mein CntntNode?" );
                }
				break;

			case FILL_TAB:
			case FILL_SPACE:
				{
					String sInsert;
					if( aFPos.nTabCnt )
						sInsert.Fill( aFPos.nTabCnt, '\t' );
					if( aFPos.nSpaceCnt )
					{
						String sSpace;
						sSpace.Fill( aFPos.nSpaceCnt );
						sInsert += sSpace;
					}
					if( sInsert.Len() )
                    {
                        GetDoc()->InsertString( *pCurCrsr, sInsert );
                    }
				}
				// kein break - Ausrichtung muss noch gesetzt werden
			case FILL_MARGIN:
                if( text::HoriOrientation::NONE != aFPos.eOrient )
				{
                    SvxAdjustItem aAdj( SVX_ADJUST_LEFT, RES_PARATR_ADJUST );
					switch( aFPos.eOrient )
					{
                    case text::HoriOrientation::CENTER:
						aAdj.SetAdjust( SVX_ADJUST_CENTER );
						break;
                    case text::HoriOrientation::RIGHT:
						aAdj.SetAdjust( SVX_ADJUST_RIGHT );
						break;
					default:
						break;
					}
                    GetDoc()->InsertPoolItem( *pCurCrsr, aAdj, 0 );
				}
				break;
			}

            GetDoc()->GetIDocumentUndoRedo().EndUndo( nUndoId, NULL );
			EndAction();

			bRet = sal_True;
		}
	}
	return bRet;
}

const SwRedline* SwCrsrShell::SelNextRedline()
{
	const SwRedline* pFnd = 0;
	if( !IsTableMode() )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCurCrsr );

		pFnd = GetDoc()->SelNextRedline( *pCurCrsr );
		if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
			UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
		else
			pFnd = 0;
	}
	return pFnd;
}

const SwRedline* SwCrsrShell::SelPrevRedline()
{
	const SwRedline* pFnd = 0;
	if( !IsTableMode() )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
		SwCrsrSaveState aSaveState( *pCurCrsr );

		pFnd = GetDoc()->SelPrevRedline( *pCurCrsr );
		if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
			UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
		else
			pFnd = 0;
	}
	return pFnd;
}

const SwRedline* SwCrsrShell::_GotoRedline( sal_uInt16 nArrPos, sal_Bool bSelect )
{
	const SwRedline* pFnd = 0;
	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
	SwCrsrSaveState aSaveState( *pCurCrsr );

	pFnd = GetDoc()->GetRedlineTbl()[ nArrPos ];
	if( pFnd )
	{
		*pCurCrsr->GetPoint() = *pFnd->Start();

		SwCntntNode* pCNd;
		SwNodeIndex* pIdx = &pCurCrsr->GetPoint()->nNode;
		if( !pIdx->GetNode().IsCntntNode() &&
			0 != ( pCNd = GetDoc()->GetNodes().GoNextSection( pIdx,
									sal_True, IsReadOnlyAvailable() )) )
		{
			if( *pIdx <= pFnd->End()->nNode )
				pCurCrsr->GetPoint()->nContent.Assign( pCNd, 0 );
			else
				pFnd = 0;
		}

		if( pFnd && bSelect )
		{
			pCurCrsr->SetMark();
			if( nsRedlineType_t::REDLINE_FMTCOLL == pFnd->GetType() )
			{
				pCNd = pIdx->GetNode().GetCntntNode();
				pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
				pCurCrsr->GetMark()->nContent.Assign( pCNd, 0 );
			}
			else
				*pCurCrsr->GetPoint() = *pFnd->End();

			pIdx = &pCurCrsr->GetPoint()->nNode;
			if( !pIdx->GetNode().IsCntntNode() &&
				0 != ( pCNd = GetDoc()->GetNodes().GoPrevSection( pIdx,
											sal_True, IsReadOnlyAvailable() )) )
			{
				if( *pIdx >= pCurCrsr->GetMark()->nNode )
					pCurCrsr->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
				else
					pFnd = 0;
			}
		}

		if( !pFnd )
		{
			pCurCrsr->DeleteMark();
			pCurCrsr->RestoreSavePos();
		}
		else if( bSelect && *pCurCrsr->GetMark() == *pCurCrsr->GetPoint() )
			pCurCrsr->DeleteMark();

		if( pFnd && !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
			UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE
						| SwCrsrShell::READONLY );
		else
		{
			pFnd = 0;
			if( bSelect )
				pCurCrsr->DeleteMark();
		}
	}
	return pFnd;
}

const SwRedline* SwCrsrShell::GotoRedline( sal_uInt16 nArrPos, sal_Bool bSelect )
{
	const SwRedline* pFnd = 0;
	if( !IsTableMode() )
	{
		SET_CURR_SHELL( this );

		const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
		const SwRedline* pTmp = rTbl[ nArrPos ];
		sal_uInt16 nSeqNo = pTmp->GetSeqNo();
		if( nSeqNo && bSelect )
		{
			sal_Bool bCheck = sal_False;
			int nLoopCnt = 2;
			sal_uInt16 nArrSavPos = nArrPos;

			do {
				pTmp = _GotoRedline( nArrPos, sal_True );

				if( !pFnd )
					pFnd = pTmp;

				if( pTmp && bCheck )
				{
					// checke auf Ueberlappungen. Das kann durch
					// FmtColl-Redlines kommen, die auf den gesamten Absatz
					// aus gedehnt werden.

                    SwPaM* pCur = pCurCrsr;
                    SwPaM* pNextPam = (SwPaM*)pCur->GetNext();
					SwPosition* pCStt = pCur->Start(), *pCEnd = pCur->End();
                    while( pCur != pNextPam )
					{
                        const SwPosition *pNStt = pNextPam->Start(),
                                         *pNEnd = pNextPam->End();

						sal_Bool bDel = sal_True;
						switch( ::ComparePosition( *pCStt, *pCEnd,
												   *pNStt, *pNEnd ))
						{
						case POS_INSIDE:	// Pos1 liegt vollstaendig in Pos2
							if( !pCur->HasMark() )
							{
								pCur->SetMark();
								*pCur->GetMark() = *pNStt;
							}
							else
								*pCStt = *pNStt;
							*pCEnd = *pNEnd;
							break;

						case POS_OUTSIDE:	// Pos2 liegt vollstaendig in Pos1
						case POS_EQUAL:		// Pos1 ist genauso gross wie Pos2
							break;

						case POS_OVERLAP_BEFORE:		// Pos1 ueberlappt Pos2 am Anfang
							if( !pCur->HasMark() )
								pCur->SetMark();
							*pCEnd = *pNEnd;
							break;
						case POS_OVERLAP_BEHIND: 		// Pos1 ueberlappt Pos2 am Ende
							if( !pCur->HasMark() )
							{
								pCur->SetMark();
								*pCur->GetMark() = *pNStt;
							}
							else
								*pCStt = *pNStt;
							break;

						default:
							bDel = sal_False;
						}

						if( bDel )
						{
							// den brauchen wir nicht mehr
                            SwPaM* pPrevPam = (SwPaM*)pNextPam->GetPrev();
                            delete pNextPam;
                            pNextPam = pPrevPam;
						}
                        pNextPam = (SwPaM*)pNextPam->GetNext();
					}
				}

				sal_uInt16 nFndPos = 2 == nLoopCnt
									? rTbl.FindNextOfSeqNo( nArrPos )
									: rTbl.FindPrevOfSeqNo( nArrPos );
				if( USHRT_MAX != nFndPos ||
					( 0 != ( --nLoopCnt ) && USHRT_MAX != (
							nFndPos = rTbl.FindPrevOfSeqNo( nArrSavPos ))) )
				{
					if( pTmp )
					{
						// neuen Cursor erzeugen
						CreateCrsr();
						bCheck = sal_True;
					}
					nArrPos = nFndPos;
				}
				else
					nLoopCnt = 0;

			} while( nLoopCnt );
		}
		else
			pFnd = _GotoRedline( nArrPos, bSelect );
	}
	return pFnd;
}


sal_Bool SwCrsrShell::SelectNxtPrvHyperlink( sal_Bool bNext )
{
	SwNodes& rNds = GetDoc()->GetNodes();
	const SwNode* pBodyEndNd = &rNds.GetEndOfContent();
    const SwNode* pBodySttNd = pBodyEndNd->StartOfSectionNode();
	sal_uLong nBodySttNdIdx = pBodySttNd->GetIndex();
	Point aPt;

	_SetGetExpFld aCmpPos( SwPosition( bNext ? *pBodyEndNd : *pBodySttNd ) );
	_SetGetExpFld aCurPos( bNext ? *pCurCrsr->End() : *pCurCrsr->Start() );
	if( aCurPos.GetNode() < nBodySttNdIdx )
	{
		const SwCntntNode* pCNd = aCurPos.GetNodeFromCntnt()->GetCntntNode();
		SwCntntFrm* pFrm;
		if( pCNd && 0 != ( pFrm = pCNd->getLayoutFrm( GetLayout(), &aPt )) )
			aCurPos.SetBodyPos( *pFrm );
	}

	// check first all the hyperlink fields
	{
		const SwTxtNode* pTxtNd;
		const SwCharFmts* pFmts = GetDoc()->GetCharFmts();
		for( sal_uInt16 n = pFmts->Count(); 1 < n; )
		{
			SwIterator<SwTxtINetFmt,SwCharFmt> aIter(*(*pFmts)[--n]);

			for( SwTxtINetFmt* pFnd = aIter.First(); pFnd; pFnd = aIter.Next() )
				if( 0 != ( pTxtNd = pFnd->GetpTxtNode()) &&
					pTxtNd->GetNodes().IsDocNodes() )
				{
					SwTxtINetFmt& rAttr = *pFnd;
					SwPosition aTmpPos( *pTxtNd );
					_SetGetExpFld aPos( aTmpPos.nNode, rAttr );
					SwCntntFrm* pFrm;
					if( pTxtNd->GetIndex() < nBodySttNdIdx &&
						0 != ( pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt )) )
						aPos.SetBodyPos( *pFrm );

					if( bNext
						? ( aPos < aCmpPos && aCurPos < aPos )
						: ( aCmpPos < aPos && aPos < aCurPos ))
					{
						String sTxt( pTxtNd->GetExpandTxt( *rAttr.GetStart(),
										*rAttr.GetEnd() - *rAttr.GetStart() ) );

						sTxt.EraseAllChars( 0x0a );
						sTxt.EraseLeadingChars().EraseTrailingChars();

						if( sTxt.Len() )
							aCmpPos = aPos;
					}
				}
		}
	}
	// then check all the Flys with a URL or imapge map
	{
		const SwSpzFrmFmts* pFmts = GetDoc()->GetSpzFrmFmts();
		for( sal_uInt16 n = 0, nEnd = pFmts->Count(); n < nEnd; ++n )
		{
			SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)(*pFmts)[ n ];
			const SwFmtURL& rURLItem = pFmt->GetURL();
			if( rURLItem.GetMap() || rURLItem.GetURL().Len() )
			{
				SwFlyFrm* pFly = pFmt->GetFrm( &aPt, sal_False );
				SwPosition aTmpPos( *pBodySttNd );
				if( pFly &&
					GetBodyTxtNode( *GetDoc(), aTmpPos, *pFly->GetLower() ) )
				{
					_SetGetExpFld aPos( *pFmt, &aTmpPos );

					if( bNext
							? ( aPos < aCmpPos && aCurPos < aPos )
							: ( aCmpPos < aPos && aPos < aCurPos ))
						aCmpPos = aPos;
				}
			}
		}
	}

	// found any URL ?
	sal_Bool bRet = sal_False;
	const SwTxtINetFmt* pFndAttr = aCmpPos.GetINetFmt();
	const SwFlyFrmFmt* pFndFmt = aCmpPos.GetFlyFmt();
	if( pFndAttr || pFndFmt )
	{
		SET_CURR_SHELL( this );
		SwCallLink aLk( *this );

		// find a text attribute ?
		if( pFndAttr )
		{
			SwCrsrSaveState aSaveState( *pCurCrsr );

			aCmpPos.GetPosOfContent( *pCurCrsr->GetPoint() );
			pCurCrsr->DeleteMark();
			pCurCrsr->SetMark();
			pCurCrsr->GetPoint()->nContent = *pFndAttr->End();

			if( !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr() )
			{
				UpdateCrsr( SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|
									SwCrsrShell::READONLY );
				bRet = sal_True;
			}
		}
		// find a draw object ?
		else if( RES_DRAWFRMFMT == pFndFmt->Which() )
		{
			const SdrObject* pSObj = pFndFmt->FindSdrObject();
			((SwFEShell*)this)->SelectObj( pSObj->GetCurrentBoundRect().Center() );
			MakeSelVisible();
			bRet = sal_True;
		}
		else		// then is it a fly
		{
			SwFlyFrm* pFly = pFndFmt->GetFrm(&aPt, sal_False );
			if( pFly )
			{
				((SwFEShell*)this)->SelectFlyFrm( *pFly, sal_True );
				MakeSelVisible();
				bRet = sal_True;
			}
		}
	}
	return bRet;
}