/**************************************************************
 * 
 * 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_editeng.hxx"

#include <vcl/wrkwin.hxx>
#include <vcl/dialog.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>

#include <eertfpar.hxx>
#include <impedit.hxx>
#include <svl/intitem.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/flditem.hxx>

#include <svtools/rtftoken.h>

// alle Werte auf default; wird nach einlesen der Bitmap aufgerufen !
void SvxRTFPictureType::ResetValues()
{	// setze alle Werte RTF-Defaults
	eStyle = RTF_BITMAP;
	nMode = HEX_MODE;
	nType = nGoalWidth = nGoalHeight = 0;
	nWidth = nHeight = nWidthBytes = 0;
	uPicLen = 0;
	nBitsPerPixel = nPlanes = 1;
	nScalX = nScalY = 100;		// Skalierung in Prozent
	nCropT = nCropB = nCropL = nCropR = 0;
    aPropertyPairs.clear();
}

ImportInfo::ImportInfo( ImportState eSt, SvParser* pPrsrs, const ESelection& rSel )
	: aSelection( rSel )
{
	pParser 	= pPrsrs,
	eState		= eSt;

	nToken 		= 0;
	nTokenValue	= 0;
	pAttrs 		= NULL;
}

ImportInfo::~ImportInfo()
{
}

EditRTFParser::EditRTFParser( SvStream& rIn, EditSelection aSel, SfxItemPool& rAttrPool, ImpEditEngine* pImpEE  )
	: SvxRTFParser( rAttrPool, rIn, 0 ), aRTFMapMode( MAP_TWIP )
{

	pImpEditEngine	= pImpEE;
	aCurSel 		= aSel;
	eDestCharSet	= RTL_TEXTENCODING_DONTKNOW;
	nDefFont		= 0;
	nDefTab			= 0;
	nLastAction		= 0;
	nDefFontHeight	= 0;

	SetInsPos( EditPosition( pImpEditEngine, &aCurSel ) );

	// Umwandeln der Twips-Werte...
	SetCalcValue( sal_True );
	SetChkStyleAttr( pImpEE->GetStatus().DoImportRTFStyleSheets() );
	SetNewDoc( sal_False );		// damit die Pool-Defaults nicht
							// ueberschrieben werden...
	aEditMapMode = MapMode( pImpEE->GetRefDevice()->GetMapMode().GetMapUnit() );
}

EditRTFParser::~EditRTFParser()
{
}

SvParserState __EXPORT EditRTFParser::CallParser()
{
	DBG_ASSERT( !aCurSel.HasRange(), "Selection bei CallParser!" );
	// Den Teil, in den importiert wird, vom Rest abtrennen.
	// Diese Mimik sollte fuer alle Imports verwendet werden.
	// aStart1PaM: Letzte Position vor dem importierten Inhalt
	// aEnd1PaM: Erste Position nach dem importierten Inhalt
	// aStart2PaM: Erste Position des importierten Inhaltes
	// aEnd2PaM: Letzte Position des importierten Inhaltes
	EditPaM aStart1PaM( aCurSel.Min().GetNode(), aCurSel.Min().GetIndex() );
	aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
	EditPaM aStart2PaM = aCurSel.Min();
	// Sinnvoll oder nicht?:
	aStart2PaM.GetNode()->GetContentAttribs().GetItems().ClearItem();
    AddRTFDefaultValues( aStart2PaM, aStart2PaM );
	EditPaM aEnd1PaM( pImpEditEngine->ImpInsertParaBreak( aCurSel.Max() ) );
	// aCurCel zeigt jetzt auf den Zwischenraum

	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_START, this, pImpEditEngine->CreateESel( aCurSel ) );
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}

	SvParserState _eState = SvxRTFParser::CallParser();

	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_END, this, pImpEditEngine->CreateESel( aCurSel ) );
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}

	if ( nLastAction == ACTION_INSERTPARABRK )
	{
		ContentNode* pCurNode = aCurSel.Max().GetNode();
		sal_uInt16 nPara = pImpEditEngine->GetEditDoc().GetPos( pCurNode );
		ContentNode* pPrevNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara-1 );
		DBG_ASSERT( pPrevNode, "Ungueltiges RTF-Dokument ?!" );
		EditSelection aSel;
		aSel.Min() = EditPaM( pPrevNode, pPrevNode->Len() );
		aSel.Max() = EditPaM( pCurNode, 0 );
		aCurSel.Max() = pImpEditEngine->ImpDeleteSelection( aSel );
	}
	EditPaM aEnd2PaM( aCurSel.Max() );
    //AddRTFDefaultValues( aStart2PaM, aEnd2PaM );
	sal_Bool bOnlyOnePara = ( aEnd2PaM.GetNode() == aStart2PaM.GetNode() );
	// Den Brocken wieder einfuegen...
	// Problem: Absatzattribute duerfen ggf. nicht uebernommen werden
	// => Zeichenattribute machen.

	sal_Bool bSpecialBackward = aStart1PaM.GetNode()->Len() ? sal_False : sal_True;
	if ( bOnlyOnePara || aStart1PaM.GetNode()->Len() )
		pImpEditEngine->ParaAttribsToCharAttribs( aStart2PaM.GetNode() );
	aCurSel.Min() = pImpEditEngine->ImpConnectParagraphs(
		aStart1PaM.GetNode(), aStart2PaM.GetNode(), bSpecialBackward );
	bSpecialBackward = aEnd1PaM.GetNode()->Len() ? sal_True : sal_False;
	// wenn bOnlyOnePara, dann ist der Node beim Connect verschwunden.
	if ( !bOnlyOnePara && aEnd1PaM.GetNode()->Len() )
		pImpEditEngine->ParaAttribsToCharAttribs( aEnd2PaM.GetNode() );
	aCurSel.Max() = pImpEditEngine->ImpConnectParagraphs(
		( bOnlyOnePara ? aStart1PaM.GetNode() : aEnd2PaM.GetNode() ),
			aEnd1PaM.GetNode(), bSpecialBackward );

	return _eState;
}

void EditRTFParser::AddRTFDefaultValues( const EditPaM& rStart, const EditPaM& rEnd )
{
	// Problem: DefFont und DefFontHeight
	Size aSz( 12, 0 );
	MapMode aPntMode( MAP_POINT );
	MapMode _aEditMapMode( pImpEditEngine->GetRefDevice()->GetMapMode().GetMapUnit() );
	aSz = pImpEditEngine->GetRefDevice()->LogicToLogic( aSz, &aPntMode, &_aEditMapMode );
	SvxFontHeightItem aFontHeightItem( aSz.Width(), 100, EE_CHAR_FONTHEIGHT );
	Font aDefFont( GetDefFont() );
	SvxFontItem aFontItem( aDefFont.GetFamily(), aDefFont.GetName(),
					aDefFont.GetStyleName(), aDefFont.GetPitch(), aDefFont.GetCharSet(), EE_CHAR_FONTINFO );

	sal_uInt16 nStartPara = pImpEditEngine->GetEditDoc().GetPos( rStart.GetNode() );
	sal_uInt16 nEndPara = pImpEditEngine->GetEditDoc().GetPos( rEnd.GetNode() );
	for ( sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++ )
	{
		ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( nPara );
		DBG_ASSERT( pNode, "AddRTFDefaultValues - Kein Absatz ?!" );
		if ( !pNode->GetContentAttribs().HasItem( EE_CHAR_FONTINFO ) )
			pNode->GetContentAttribs().GetItems().Put( aFontItem );
		if ( !pNode->GetContentAttribs().HasItem( EE_CHAR_FONTHEIGHT ) )
			pNode->GetContentAttribs().GetItems().Put( aFontHeightItem );
	}
}

void __EXPORT EditRTFParser::NextToken( int nToken )
{
	switch( nToken )
	{
		case RTF_DEFF:
		{
			nDefFont = sal_uInt16(nTokenValue);
		}
		break;
		case RTF_DEFTAB:
		{
			nDefTab = sal_uInt16(nTokenValue);
		}
		break;
		case RTF_CELL:
		{
			aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
		}
		break;
		case RTF_LINE:
		{
			aCurSel = pImpEditEngine->InsertLineBreak( aCurSel );
		}
		break;
		case RTF_FIELD:
		{
			ReadField();
		}
		break;
		case RTF_PGDSCTBL: // #i29453# ignore \*\pgdsctbl destination
        case RTF_LISTTEXT:
        {
            SkipGroup();
        }
        break;
		default:
		{
			SvxRTFParser::NextToken( nToken );
			if ( nToken == RTF_STYLESHEET )
				CreateStyleSheets();
		}
		break;
	}
	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_NEXTTOKEN, this, pImpEditEngine->CreateESel( aCurSel ) );
		aImportInfo.nToken = nToken;
		aImportInfo.nTokenValue = short(nTokenValue);
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}
}

void __EXPORT EditRTFParser::UnknownAttrToken( int nToken, SfxItemSet* )
{
	// fuer Tokens, die im ReadAttr nicht ausgewertet werden
	// Eigentlich nur fuer Calc (RTFTokenHdl), damit RTF_INTBL
	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_UNKNOWNATTR, this, pImpEditEngine->CreateESel( aCurSel ) );
		aImportInfo.nToken = nToken;
		aImportInfo.nTokenValue = short(nTokenValue);
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}
}

void __EXPORT EditRTFParser::InsertText()
{
	String aText( aToken );
	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_INSERTTEXT, this, pImpEditEngine->CreateESel( aCurSel ) );
		aImportInfo.aText = aText;
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}
	aCurSel = pImpEditEngine->ImpInsertText( aCurSel, aText );
	nLastAction = ACTION_INSERTTEXT;
}

void __EXPORT EditRTFParser::InsertPara()
{
	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		ImportInfo aImportInfo( RTFIMP_INSERTPARA, this, pImpEditEngine->CreateESel( aCurSel ) );
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}
	aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
	nLastAction = ACTION_INSERTPARABRK;
}

void __EXPORT EditRTFParser::MovePos( int bForward )
{
	if( bForward )
        aCurSel = pImpEditEngine->CursorRight( aCurSel.Max(), ::com::sun::star::i18n::CharacterIteratorMode::SKIPCHARACTER );
	else
		aCurSel = pImpEditEngine->CursorLeft( aCurSel.Max(), ::com::sun::star::i18n::CharacterIteratorMode::SKIPCHARACTER );
}

void __EXPORT EditRTFParser::SetEndPrevPara( SvxNodeIdx*& rpNodePos,
									sal_uInt16& rCntPos )
{
	//    Gewollt ist: von der aktuellen Einfuegeposition den vorherigen
	//              Absatz bestimmen und von dem das Ende setzen.
	//              Dadurch wird "\pard" immer auf den richtigen Absatz
	//              angewendet.

	ContentNode* pN = aCurSel.Max().GetNode();
	sal_uInt16 nCurPara = pImpEditEngine->GetEditDoc().GetPos( pN );
	DBG_ASSERT( nCurPara != 0, "Absatz gleich 0: SetEnfPrevPara" );
	if ( nCurPara )
		nCurPara--;
	ContentNode* pPrevNode = pImpEditEngine->GetEditDoc().SaveGetObject( nCurPara );
	DBG_ASSERT( pPrevNode, "pPrevNode = 0!" );
	rpNodePos = new EditNodeIdx( pImpEditEngine, pPrevNode );
	rCntPos = pPrevNode->Len();
}

int __EXPORT EditRTFParser::IsEndPara( SvxNodeIdx* pNd, sal_uInt16 nCnt ) const
{
	return ( nCnt == ( ((EditNodeIdx*)pNd)->GetNode()->Len()) );
}

void __EXPORT EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet )
{
	ContentNode* pSttNode = ((EditNodeIdx&)rSet.GetSttNode()).GetNode();
	ContentNode* pEndNode = ((EditNodeIdx&)rSet.GetEndNode()).GetNode();

	EditPaM aStartPaM( pSttNode, rSet.GetSttCnt() );
	EditPaM aEndPaM( pEndNode, rSet.GetEndCnt() );

	// ggf. noch das Escapemant-Item umbiegen:
	const SfxPoolItem* pItem;

	// #i66167# adapt font heights to destination MapUnit if necessary
	const MapUnit eDestUnit	= ( MapUnit )( pImpEditEngine->GetEditDoc().GetItemPool().GetMetric(0) );
	const MapUnit eSrcUnit	= aRTFMapMode.GetMapUnit();
	if (eDestUnit != eSrcUnit)
	{
		sal_uInt16 aFntHeightIems[3] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL };
		for (int i = 0; i < 2; ++i)
		{
			if (SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( aFntHeightIems[i], sal_False, &pItem ))
			{
				sal_uInt32 nHeight	= ((SvxFontHeightItem*)pItem)->GetHeight();
				long nNewHeight;
				nNewHeight = pImpEditEngine->GetRefDevice()->LogicToLogic( (long)nHeight, eSrcUnit, eDestUnit );

				SvxFontHeightItem aFntHeightItem( nNewHeight, ((SvxFontHeightItem*)pItem)->GetProp(), aFntHeightIems[i] );
				rSet.GetAttrSet().Put( aFntHeightItem );
			}
		}
	}

	if( SFX_ITEM_SET == rSet.GetAttrSet().GetItemState( EE_CHAR_ESCAPEMENT, sal_False, &pItem ))
	{
		// die richtige
		long nEsc = ((SvxEscapementItem*)pItem)->GetEsc();

		if( ( DFLT_ESC_AUTO_SUPER != nEsc ) && ( DFLT_ESC_AUTO_SUB != nEsc ) )
		{
			nEsc *= 10;	//HalPoints => Twips wurde in RTFITEM.CXX unterschlagen!
			SvxFont aFont;
			pImpEditEngine->SeekCursor( aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont );
			nEsc = nEsc * 100 / aFont.GetSize().Height();

			SvxEscapementItem aEscItem( (short) nEsc, ((SvxEscapementItem*)pItem)->GetProp(), EE_CHAR_ESCAPEMENT );
			rSet.GetAttrSet().Put( aEscItem );
		}
	}

	if ( pImpEditEngine->aImportHdl.IsSet() )
	{
		EditSelection aSel( aStartPaM, aEndPaM );
		ImportInfo aImportInfo( RTFIMP_SETATTR, this, pImpEditEngine->CreateESel( aSel ) );
		aImportInfo.pAttrs = &rSet;
		pImpEditEngine->aImportHdl.Call( &aImportInfo );
	}

	ContentNode* pSN = aStartPaM.GetNode();
	ContentNode* pEN = aEndPaM.GetNode();
	sal_uInt16 nStartNode = pImpEditEngine->GetEditDoc().GetPos( pSN );
	sal_uInt16 nEndNode = pImpEditEngine->GetEditDoc().GetPos( pEN );
	sal_Int16 nOutlLevel = 0xff;

	if ( rSet.StyleNo() && pImpEditEngine->GetStyleSheetPool() && pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
	{
		SvxRTFStyleType* pS = GetStyleTbl().Get( rSet.StyleNo() );
		DBG_ASSERT( pS, "Vorlage in RTF nicht definiert!" );
		if ( pS )
		{
			pImpEditEngine->SetStyleSheet( EditSelection( aStartPaM, aEndPaM ), (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( pS->sName, SFX_STYLE_FAMILY_ALL ) );
			nOutlLevel = pS->nOutlineNo;
		}
	}

	// Wenn ein Attribut von 0 bis aktuelle Absatzlaenge geht,
	// soll es ein Absatz-Attribut sein!

	// Achtung: Selektion kann ueber mehrere Absaetze gehen.
	// Alle vollstaendigen Absaetze sind Absatzattribute...
	for ( sal_uInt16 z = nStartNode+1; z < nEndNode; z++ )
	{
		DBG_ASSERT( pImpEditEngine->GetEditDoc().SaveGetObject( z ), "Node existiert noch nicht(RTF)" );
		pImpEditEngine->SetParaAttribs( z, rSet.GetAttrSet() );
	}

	if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
	{
		// Den Rest des StartNodes...
		if ( aStartPaM.GetIndex() == 0 )
			pImpEditEngine->SetParaAttribs( nStartNode, rSet.GetAttrSet() );
		else
			pImpEditEngine->SetAttribs( EditSelection( aStartPaM, EditPaM( aStartPaM.GetNode(), aStartPaM.GetNode()->Len() ) ), rSet.GetAttrSet() );

		// Den Anfang des EndNodes....
		if ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() )
			pImpEditEngine->SetParaAttribs( nEndNode, rSet.GetAttrSet() );
		else
			pImpEditEngine->SetAttribs( EditSelection( EditPaM( aEndPaM.GetNode(), 0 ), aEndPaM ), rSet.GetAttrSet() );
	}
	else
	{
		if ( ( aStartPaM.GetIndex() == 0 ) && ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() ) )
        {
            // #96298# When settings char attribs as para attribs, we must merge with existing attribs, not overwrite the ItemSet!
            SfxItemSet aAttrs = pImpEditEngine->GetParaAttribs( nStartNode );
            aAttrs.Put( rSet.GetAttrSet() );
			pImpEditEngine->SetParaAttribs( nStartNode, aAttrs );
        }
		else
        {
			pImpEditEngine->SetAttribs( EditSelection( aStartPaM, aEndPaM ), rSet.GetAttrSet() );
        }
	}

	// OutlLevel...
	if ( nOutlLevel != 0xff )
	{
		for ( sal_uInt16 n = nStartNode; n <= nEndNode; n++ ) 
		{
			ContentNode* pNode = pImpEditEngine->GetEditDoc().SaveGetObject( n );
			pNode->GetContentAttribs().GetItems().Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nOutlLevel ) );
		}
	}
}

SvxRTFStyleType* EditRTFParser::FindStyleSheet( const XubString& rName )
{
	SvxRTFStyleType* pS = GetStyleTbl().First();
	while ( pS && ( pS->sName != rName ) )
		pS = GetStyleTbl().Next();

	return pS;
}

SfxStyleSheet* EditRTFParser::CreateStyleSheet( SvxRTFStyleType* pRTFStyle )
{
	// Prueffen, ob so eine Vorlage existiert....
	// dann wird sie auch nicht geaendert!
	SfxStyleSheet* pStyle = (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( pRTFStyle->sName, SFX_STYLE_FAMILY_ALL );
	if ( pStyle )
		return pStyle;
	
	String aName( pRTFStyle->sName );
	String aParent;
	if ( pRTFStyle->nBasedOn )
	{
		SvxRTFStyleType* pS = GetStyleTbl().Get( pRTFStyle->nBasedOn );
		if ( pS && ( pS !=pRTFStyle ) )
			aParent = pS->sName;
	}

	pStyle = (SfxStyleSheet*) &pImpEditEngine->GetStyleSheetPool()->Make( aName, SFX_STYLE_FAMILY_PARA );

	// 1) Items konvertieren und uebernehmen...
	ConvertAndPutItems( pStyle->GetItemSet(), pRTFStyle->aAttrSet );

	// 2) Solange Parent nicht im Pool, auch diesen kreieren...
	if ( aParent.Len() && ( aParent != aName ) )
	{
		SfxStyleSheet* pS = (SfxStyleSheet*)pImpEditEngine->GetStyleSheetPool()->Find( aParent, SFX_STYLE_FAMILY_ALL );
		if ( !pS )
		{
			// Wenn nirgendwo gefunden, aus RTF erzeugen...
			SvxRTFStyleType* _pRTFStyle = FindStyleSheet( aParent );
			if ( _pRTFStyle )
				pS = CreateStyleSheet( _pRTFStyle );
		}
		// 2b) ItemSet mit Parent verknuepfen...
		if ( pS )
			pStyle->GetItemSet().SetParent( &pS->GetItemSet() );
	}
	return pStyle;
}

void EditRTFParser::CreateStyleSheets()
{
	// der SvxRTFParser hat jetzt die Vorlagen erzeugt...
	if ( pImpEditEngine->GetStyleSheetPool() && pImpEditEngine->GetStatus().DoImportRTFStyleSheets() ) 
	{
		SvxRTFStyleType* pRTFStyle = GetStyleTbl().First();
		while ( pRTFStyle )
		{
			CreateStyleSheet( pRTFStyle );

			pRTFStyle = GetStyleTbl().Next();
		}
	}
}

void __EXPORT EditRTFParser::CalcValue()
{
    const MapUnit eDestUnit = static_cast< MapUnit >( aEditMapMode.GetMapUnit() );
    const MapUnit eSrcUnit  = aRTFMapMode.GetMapUnit();
    if (eDestUnit != eSrcUnit)
        nTokenValue = OutputDevice::LogicToLogic( (long)nTokenValue, eSrcUnit, eDestUnit );
}

void EditRTFParser::ReadField()
{
	// Aus SwRTFParser::ReadField()
	int _nOpenBrakets = 1;		// die erste wurde schon vorher erkannt
	sal_Bool bFldInst = sal_False;
	sal_Bool bFldRslt = sal_False;
	String aFldInst;
	String aFldRslt;

	while( _nOpenBrakets && IsParserWorking() )
	{
		switch( GetNextToken() )
		{
			case '}':
			{
				_nOpenBrakets--;
				if ( _nOpenBrakets == 1 )
				{
					bFldInst = sal_False;
					bFldRslt = sal_False;
				}
			}
			break;

			case '{':			_nOpenBrakets++;
								break;

			case RTF_FIELD:		SkipGroup();
								break;

			case RTF_FLDINST:	bFldInst = sal_True;
								break;

			case RTF_FLDRSLT:	bFldRslt = sal_True;
								break;

			case RTF_TEXTTOKEN:
			{
				if ( bFldInst )
					aFldInst += aToken;
				else if ( bFldRslt )
					aFldRslt += aToken;
			}
			break;
		}
	}
	if ( aFldInst.Len() )
	{
		String aHyperLinkMarker( RTL_CONSTASCII_USTRINGPARAM( "HYPERLINK " ) );
		if ( aFldInst.CompareIgnoreCaseToAscii( aHyperLinkMarker, aHyperLinkMarker.Len() ) == COMPARE_EQUAL )
		{
			aFldInst.Erase( 0, aHyperLinkMarker.Len() );
			aFldInst.EraseLeadingChars();
			aFldInst.EraseTrailingChars();
			aFldInst.Erase( 0, 1 );	// "
			aFldInst.Erase( aFldInst.Len()-1, 1 );	// "

			if ( !aFldRslt.Len() )
				aFldRslt = aFldInst;

			SvxFieldItem aField( SvxURLField( aFldInst, aFldRslt, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD  );
			aCurSel = pImpEditEngine->InsertField( aCurSel, aField );
			pImpEditEngine->UpdateFields();
			nLastAction = ACTION_INSERTTEXT;
		}
	}

	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
}

void EditRTFParser::SkipGroup()
{
	int _nOpenBrakets = 1;		// die erste wurde schon vorher erkannt

    while( _nOpenBrakets && IsParserWorking() )
	{
		switch( GetNextToken() )
		{
			case '}':
			{
				_nOpenBrakets--;
			}
			break;

			case '{':			
            {
                _nOpenBrakets++;
            }
			break;
		}
	}

	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
}

sal_uLong __EXPORT EditNodeIdx::GetIdx() const
{
	return pImpEditEngine->GetEditDoc().GetPos( pNode );
}

SvxNodeIdx* __EXPORT EditNodeIdx::Clone() const
{
	return new EditNodeIdx( pImpEditEngine, pNode );
}

SvxPosition* __EXPORT EditPosition::Clone() const
{
	return new EditPosition( pImpEditEngine, pCurSel );
}

SvxNodeIdx* __EXPORT EditPosition::MakeNodeIdx() const
{
	return new EditNodeIdx( pImpEditEngine, pCurSel->Max().GetNode() );
}

sal_uLong __EXPORT EditPosition::GetNodeIdx() const
{
	ContentNode* pN = pCurSel->Max().GetNode();
	return pImpEditEngine->GetEditDoc().GetPos( pN );
}

sal_uInt16 __EXPORT EditPosition::GetCntIdx() const
{
	return pCurSel->Max().GetIndex();
}
