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



#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <svx/svdpool.hxx>
#include <svx/svdobj.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editobj.hxx>
#include <editeng/flditem.hxx>
#include <svx/unomid.hxx>
#include <editeng/unoprnms.hxx>
#include <editeng/unofored.hxx>
#include <rtl/uuid.h>
#include <vcl/virdev.hxx>
#include <com/sun/star/awt/FontSlant.hpp>

#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <editeng/unoipset.hxx>
#include "textuno.hxx"
#include "fielduno.hxx"
#include "servuno.hxx"
#include "editsrc.hxx"
#include "docsh.hxx"
#include "editutil.hxx"
#include "unoguard.hxx"
#include "miscuno.hxx"
#include "cellsuno.hxx"
#include "hints.hxx"
#include "patattr.hxx"
#include "cell.hxx"
#include "docfunc.hxx"
#include "scmod.hxx"

using namespace com::sun::star;

//------------------------------------------------------------------------

const SvxItemPropertySet * lcl_GetHdFtPropertySet()
{
    static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] =
	{
		SVX_UNOEDIT_CHAR_PROPERTIES,
		SVX_UNOEDIT_FONT_PROPERTIES,
		SVX_UNOEDIT_PARA_PROPERTIES,
		SVX_UNOEDIT_NUMBERING_PROPERTIE,	// for completeness of service ParagraphProperties
        {0,0,0,0,0,0}
	};
	static sal_Bool bTwipsSet = sal_False;

	if (!bTwipsSet)
	{
		//	modify PropertyMap to include CONVERT_TWIPS flag for font height
		//	(headers/footers are in twips)

        SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl;
		while (pEntry->pName)
		{
			if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT ||
				   pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK ||
				   pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) &&
				 pEntry->nMemberId == MID_FONTHEIGHT )
			{
				pEntry->nMemberId |= CONVERT_TWIPS;
			}

			++pEntry;
		}
		bTwipsSet = sal_True;
	}
    static SvxItemPropertySet aHdFtPropertySet_Impl( aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
	return &aHdFtPropertySet_Impl;
}

//------------------------------------------------------------------------

SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" )
SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" )

//------------------------------------------------------------------------

ScHeaderFooterContentObj::ScHeaderFooterContentObj( const EditTextObject* pLeft,
													const EditTextObject* pCenter,
													const EditTextObject* pRight ) :
	pLeftText	( NULL ),
	pCenterText	( NULL ),
	pRightText	( NULL )
{
	if ( pLeft )
		pLeftText	= pLeft->Clone();
	if ( pCenter )
		pCenterText	= pCenter->Clone();
	if ( pRight )
		pRightText	= pRight->Clone();
}

ScHeaderFooterContentObj::~ScHeaderFooterContentObj()
{
	delete pLeftText;
	delete pCenterText;
	delete pRightText;
}

void ScHeaderFooterContentObj::AddListener( SfxListener& rListener )
{
	rListener.StartListening( aBC );
}

void ScHeaderFooterContentObj::RemoveListener( SfxListener& rListener )
{
	rListener.EndListening( aBC );
}

void ScHeaderFooterContentObj::UpdateText( sal_uInt16 nPart, EditEngine& rSource )
{
	EditTextObject* pNew = rSource.CreateTextObject();
	switch (nPart)
	{
		case SC_HDFT_LEFT:
			delete pLeftText;
			pLeftText = pNew;
			break;
		case SC_HDFT_CENTER:
			delete pCenterText;
			pCenterText = pNew;
			break;
		default:				// SC_HDFT_RIGHT
			delete pRightText;
			pRightText = pNew;
			break;
	}

	aBC.Broadcast( ScHeaderFooterChangedHint( nPart ) );
}

// XHeaderFooterContent

uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText()
												throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT );
}

uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText()
												throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER );
}

uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText()
												throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return new ScHeaderFooterTextObj( *this, SC_HDFT_RIGHT );
}

// XUnoTunnel

sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething(
				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
{
	if ( rId.getLength() == 16 &&
          0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
									rId.getConstArray(), 16 ) )
	{
        return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
	}
	return 0;
}

// static
const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId()
{
	static uno::Sequence<sal_Int8> * pSeq = 0;
	if( !pSeq )
	{
		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
		if( !pSeq )
		{
			static uno::Sequence< sal_Int8 > aSeq( 16 );
			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
			pSeq = &aSeq;
		}
	}
	return *pSeq;
}

// static
ScHeaderFooterContentObj* ScHeaderFooterContentObj::getImplementation(
								const uno::Reference<sheet::XHeaderFooterContent> xObj )
{
	ScHeaderFooterContentObj* pRet = NULL;
	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
	if (xUT.is())
        pRet = reinterpret_cast<ScHeaderFooterContentObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
	return pRet;
}


//------------------------------------------------------------------------

ScHeaderFooterTextData::ScHeaderFooterTextData( ScHeaderFooterContentObj& rContent,
													sal_uInt16 nP ) :
	rContentObj( rContent ),
	nPart( nP ),
	pEditEngine( NULL ),
	pForwarder( NULL ),
	bDataValid( sal_False ),
	bInUpdate( sal_False )
{
	rContentObj.acquire();				// must not go away
	rContentObj.AddListener( *this );
}

ScHeaderFooterTextData::~ScHeaderFooterTextData()
{
	ScUnoGuard aGuard;		//	needed for EditEngine dtor

	rContentObj.RemoveListener( *this );

	delete pForwarder;
	delete pEditEngine;

	rContentObj.release();
}

void ScHeaderFooterTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
	if ( rHint.ISA( ScHeaderFooterChangedHint ) )
	{
		if ( ((const ScHeaderFooterChangedHint&)rHint).GetPart() == nPart )
		{
			if (!bInUpdate)				// not for own updates
				bDataValid = sal_False;		// text has to be fetched again
		}
	}
}

SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder()
{
	if (!pEditEngine)
	{
		SfxItemPool* pEnginePool = EditEngine::CreatePool();
		pEnginePool->FreezeIdRanges();
		ScHeaderEditEngine* pHdrEngine = new ScHeaderEditEngine( pEnginePool, sal_True );

		pHdrEngine->EnableUndo( sal_False );
		pHdrEngine->SetRefMapMode( MAP_TWIP );

		//	default font must be set, independently of document
		//	-> use global pool from module

		SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
		const ScPatternAttr& rPattern = (const ScPatternAttr&)SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN);
		rPattern.FillEditItemSet( &aDefaults );
		//	FillEditItemSet adjusts font height to 1/100th mm,
		//	but for header/footer twips is needed, as in the PatternAttr:
		aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
		aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
		aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
		pHdrEngine->SetDefaults( aDefaults );

		ScHeaderFieldData aData;
		ScHeaderFooterTextObj::FillDummyFieldData( aData );
		pHdrEngine->SetData( aData );

		pEditEngine = pHdrEngine;
		pForwarder = new SvxEditEngineForwarder(*pEditEngine);
	}

	if (bDataValid)
		return pForwarder;

	const EditTextObject* pData;
	if (nPart == SC_HDFT_LEFT)
		pData = rContentObj.GetLeftEditObject();
	else if (nPart == SC_HDFT_CENTER)
		pData = rContentObj.GetCenterEditObject();
	else
		pData = rContentObj.GetRightEditObject();

	if (pData)
		pEditEngine->SetText(*pData);

	bDataValid = sal_True;
	return pForwarder;
}

void ScHeaderFooterTextData::UpdateData()
{
	if ( pEditEngine )
	{
		bInUpdate = sal_True;	// don't reset bDataValid during UpdateText

		rContentObj.UpdateText( nPart, *pEditEngine );

		bInUpdate = sal_False;
	}
}

//------------------------------------------------------------------------

ScHeaderFooterTextObj::ScHeaderFooterTextObj( ScHeaderFooterContentObj& rContent,
												sal_uInt16 nP ) :
	aTextData( rContent, nP ),
	pUnoText( NULL )
{
	//	ScHeaderFooterTextData acquires rContent
	//	pUnoText is created on demand (getString/setString work without it)
}

void ScHeaderFooterTextObj::CreateUnoText_Impl()
{
	if ( !pUnoText )
	{
		//	can't be aggregated because getString/setString is handled here
		ScSharedHeaderFooterEditSource aEditSource( &aTextData );
		pUnoText = new SvxUnoText( &aEditSource, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>() );
		pUnoText->acquire();
	}
}

ScHeaderFooterTextObj::~ScHeaderFooterTextObj()
{
	if (pUnoText)
		pUnoText->release();
}

const SvxUnoText& ScHeaderFooterTextObj::GetUnoText()
{
	if (!pUnoText)
		CreateUnoText_Impl();
	return *pUnoText;
}

// XText

uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor()
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return new ScHeaderFooterTextCursor( *this );
}

uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange(
									const uno::Reference<text::XTextRange>& aTextPosition )
													throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->createTextCursorByRange(aTextPosition);
	//!	wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar
}

void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData )	// static
{
	String aDummy(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "???" )));
	rData.aTitle		= aDummy;
	rData.aLongDocName	= aDummy;
	rData.aShortDocName	= aDummy;
	rData.aTabName		= aDummy;
	rData.nPageNo		= 1;
	rData.nTotalPages	= 99;
}

rtl::OUString SAL_CALL ScHeaderFooterTextObj::getString() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	rtl::OUString aRet;
	const EditTextObject* pData;

	sal_uInt16 nPart = aTextData.GetPart();
	ScHeaderFooterContentObj& rContentObj = aTextData.GetContentObj();

	if (nPart == SC_HDFT_LEFT)
		pData = rContentObj.GetLeftEditObject();
	else if (nPart == SC_HDFT_CENTER)
		pData = rContentObj.GetCenterEditObject();
	else
		pData = rContentObj.GetRightEditObject();
	if (pData)
	{
		// for pure text, no font info is needed in pool defaults
		ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );

		ScHeaderFieldData aData;
		FillDummyFieldData( aData );
		aEditEngine.SetData( aData );

		aEditEngine.SetText(*pData);
		aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine );
	}
	return aRet;
}

void SAL_CALL ScHeaderFooterTextObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	String aString(aText);

	// for pure text, no font info is needed in pool defaults
	ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );
	aEditEngine.SetText( aString );

	aTextData.GetContentObj().UpdateText( aTextData.GetPart(), aEditEngine );
}

void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange,
											const rtl::OUString& aString, sal_Bool bAbsorb )
								throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	pUnoText->insertString( xRange, aString, bAbsorb );
}

void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter(
											const uno::Reference<text::XTextRange>& xRange,
											sal_Int16 nControlCharacter, sal_Bool bAbsorb )
								throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	pUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
}

void SAL_CALL ScHeaderFooterTextObj::insertTextContent(
											const uno::Reference<text::XTextRange >& xRange,
											const uno::Reference<text::XTextContent >& xContent,
											sal_Bool bAbsorb )
								throw(lang::IllegalArgumentException, uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if ( xContent.is() && xRange.is() )
	{
		ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );

		SvxUnoTextRangeBase* pTextRange =
			ScHeaderFooterTextCursor::getImplementation( xRange );

#if 0
		if (!pTextRange)
			pTextRange = (SvxUnoTextRange*)xRange->getImplementation(
											SvxUnoTextRange_getReflection() );
		//!	bei SvxUnoTextRange testen, ob in passendem Objekt !!!
#endif

		if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange )
		{
			SvxEditSource* pEditSource = pTextRange->GetEditSource();
			ESelection aSelection(pTextRange->GetSelection());

			if (!bAbsorb)
			{
				//	don't replace -> append at end
				aSelection.Adjust();
				aSelection.nStartPara = aSelection.nEndPara;
				aSelection.nStartPos  = aSelection.nEndPos;
			}

			SvxFieldItem aItem(pHeaderField->CreateFieldItem());

			SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
			pForwarder->QuickInsertField( aItem, aSelection );
			pEditSource->UpdateData();

			//	neue Selektion: ein Zeichen
			aSelection.Adjust();
			aSelection.nEndPara = aSelection.nStartPara;
			aSelection.nEndPos = aSelection.nStartPos + 1;
			pHeaderField->InitDoc( &aTextData.GetContentObj(), aTextData.GetPart(), aSelection );

			//	#91431# for bAbsorb=sal_False, the new selection must be behind the inserted content
			//	(the xml filter relies on this)
			if (!bAbsorb)
				aSelection.nStartPos = aSelection.nEndPos;

			pTextRange->SetSelection( aSelection );

			return;
		}
	}

	if (!pUnoText)
		CreateUnoText_Impl();
	pUnoText->insertTextContent( xRange, xContent, bAbsorb );
}

void SAL_CALL ScHeaderFooterTextObj::removeTextContent(
											const uno::Reference<text::XTextContent>& xContent )
								throw(container::NoSuchElementException, uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if ( xContent.is() )
	{
		ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );
		if ( pHeaderField && pHeaderField->IsInserted() )
		{
			//!	Testen, ob das Feld in dieser Zelle ist
			pHeaderField->DeleteField();
			return;
		}
	}
	if (!pUnoText)
		CreateUnoText_Impl();
	pUnoText->removeTextContent( xContent );
}

uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->getText();
}

uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->getStart();
}

uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->getEnd();
}

// XTextFieldsSupplier

uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields()
												throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	// all fields
	return new ScHeaderFieldsObj( &aTextData.GetContentObj(), aTextData.GetPart(), SC_SERVICE_INVALID );
}

uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters()
												throw(uno::RuntimeException)
{
	//	sowas gibts nicht im Calc (?)
	return NULL;
}

// XTextRangeMover

void SAL_CALL ScHeaderFooterTextObj::moveTextRange(
										const uno::Reference<text::XTextRange>& xRange,
										sal_Int16 nParagraphs )
										throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	pUnoText->moveTextRange( xRange, nParagraphs );
}

// XEnumerationAccess

uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration()
												throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->createEnumeration();
}

// XElementAccess

uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->getElementType();
}

sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	if (!pUnoText)
		CreateUnoText_Impl();
	return pUnoText->hasElements();
}

//------------------------------------------------------------------------

ScCellTextCursor::ScCellTextCursor(const ScCellTextCursor& rOther) :
	SvxUnoTextCursor( rOther ),
	rTextObj( rOther.rTextObj )
{
	rTextObj.acquire();
}

ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) :
	SvxUnoTextCursor( rText.GetUnoText() ),
	rTextObj( rText )
{
	rTextObj.acquire();
}

ScCellTextCursor::~ScCellTextCursor() throw()
{
	rTextObj.release();
}

// SvxUnoTextCursor methods reimplemented here to return the right objects:

uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return &rTextObj;
}

uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

    ScCellTextCursor* pNew = new ScCellTextCursor( *this );
	uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nEndPara = aNewSel.nStartPara;
	aNewSel.nEndPos  = aNewSel.nStartPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

    ScCellTextCursor* pNew = new ScCellTextCursor( *this );
    uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nStartPara = aNewSel.nEndPara;
	aNewSel.nStartPos  = aNewSel.nEndPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

// XUnoTunnel

sal_Int64 SAL_CALL ScCellTextCursor::getSomething(
				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
{
	if ( rId.getLength() == 16 &&
          0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
									rId.getConstArray(), 16 ) )
	{
        return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
	}
	return SvxUnoTextCursor::getSomething( rId );
}

// static
const uno::Sequence<sal_Int8>& ScCellTextCursor::getUnoTunnelId()
{
	static uno::Sequence<sal_Int8> * pSeq = 0;
	if( !pSeq )
	{
		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
		if( !pSeq )
		{
			static uno::Sequence< sal_Int8 > aSeq( 16 );
			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
			pSeq = &aSeq;
		}
	}
	return *pSeq;
}

// static
ScCellTextCursor* ScCellTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
{
	ScCellTextCursor* pRet = NULL;
	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
	if (xUT.is())
        pRet = reinterpret_cast<ScCellTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
	return pRet;
}

//------------------------------------------------------------------------

ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(const ScHeaderFooterTextCursor& rOther) :
	SvxUnoTextCursor( rOther ),
	rTextObj( rOther.rTextObj )
{
	rTextObj.acquire();
}

ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(ScHeaderFooterTextObj& rText) :
	SvxUnoTextCursor( rText.GetUnoText() ),
	rTextObj( rText )
{
	rTextObj.acquire();
}

ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw()
{
	rTextObj.release();
}

// SvxUnoTextCursor methods reimplemented here to return the right objects:

uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return &rTextObj;
}

uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

    ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
    uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nEndPara = aNewSel.nStartPara;
	aNewSel.nEndPos  = aNewSel.nStartPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

    ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
	uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nStartPara = aNewSel.nEndPara;
	aNewSel.nStartPos  = aNewSel.nEndPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

// XUnoTunnel

sal_Int64 SAL_CALL ScHeaderFooterTextCursor::getSomething(
				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
{
	if ( rId.getLength() == 16 &&
          0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
									rId.getConstArray(), 16 ) )
	{
        return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
	}
	return SvxUnoTextCursor::getSomething( rId );
}

// static
const uno::Sequence<sal_Int8>& ScHeaderFooterTextCursor::getUnoTunnelId()
{
	static uno::Sequence<sal_Int8> * pSeq = 0;
	if( !pSeq )
	{
		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
		if( !pSeq )
		{
			static uno::Sequence< sal_Int8 > aSeq( 16 );
			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
			pSeq = &aSeq;
		}
	}
	return *pSeq;
}

// static
ScHeaderFooterTextCursor* ScHeaderFooterTextCursor::getImplementation(
								const uno::Reference<uno::XInterface> xObj )
{
	ScHeaderFooterTextCursor* pRet = NULL;
	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
	if (xUT.is())
        pRet = reinterpret_cast<ScHeaderFooterTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
	return pRet;
}

//------------------------------------------------------------------------

ScDrawTextCursor::ScDrawTextCursor(const ScDrawTextCursor& rOther) :
	SvxUnoTextCursor( rOther ),
	xParentText( rOther.xParentText )
{
}

ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent,
									const SvxUnoTextBase& rText ) :
	SvxUnoTextCursor( rText ),
	xParentText( xParent )

{
}

ScDrawTextCursor::~ScDrawTextCursor() throw()
{
}

// SvxUnoTextCursor methods reimplemented here to return the right objects:

uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;
	return xParentText;
}

uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

	ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
    uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nEndPara = aNewSel.nStartPara;
	aNewSel.nEndPos  = aNewSel.nStartPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() throw(uno::RuntimeException)
{
	ScUnoGuard aGuard;

	//!	use other object for range than cursor?

	ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
    uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );

	ESelection aNewSel(GetSelection());
	aNewSel.nStartPara = aNewSel.nEndPara;
	aNewSel.nStartPos  = aNewSel.nEndPos;
	pNew->SetSelection( aNewSel );

	return xRange;
}

// XUnoTunnel

sal_Int64 SAL_CALL ScDrawTextCursor::getSomething(
                const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
{
    if ( rId.getLength() == 16 &&
          0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
                                    rId.getConstArray(), 16 ) )
    {
        return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
    }
    return SvxUnoTextCursor::getSomething( rId );
}

// static
const uno::Sequence<sal_Int8>& ScDrawTextCursor::getUnoTunnelId()
{
    static uno::Sequence<sal_Int8> * pSeq = 0;
    if( !pSeq )
    {
        osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
        if( !pSeq )
        {
            static uno::Sequence< sal_Int8 > aSeq( 16 );
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
            pSeq = &aSeq;
        }
    }
    return *pSeq;
}

// static
ScDrawTextCursor* ScDrawTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
{
    ScDrawTextCursor* pRet = NULL;
    uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
    if (xUT.is())
        pRet = reinterpret_cast<ScDrawTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
    return pRet;
}

//------------------------------------------------------------------------

ScSimpleEditSourceHelper::ScSimpleEditSourceHelper()
{
	SfxItemPool* pEnginePool = EditEngine::CreatePool();
	pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
	pEnginePool->FreezeIdRanges();

	pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );		// TRUE: become owner of pool
	pForwarder = new SvxEditEngineForwarder( *pEditEngine );
	pOriginalSource = new ScSimpleEditSource( pForwarder );
}

ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper()
{
	ScUnoGuard aGuard;		//	needed for EditEngine dtor

	delete pOriginalSource;
	delete pForwarder;
	delete pEditEngine;
}

ScEditEngineTextObj::ScEditEngineTextObj() :
	SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
{
}

ScEditEngineTextObj::~ScEditEngineTextObj() throw()
{
}

void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject )
{
	GetEditEngine()->SetText( rTextObject );

	ESelection aSel;
	::GetSelection( aSel, GetEditSource()->GetTextForwarder() );
	SetSelection( aSel );
}

EditTextObject* ScEditEngineTextObj::CreateTextObject()
{
	return GetEditEngine()->CreateTextObject();
}

//------------------------------------------------------------------------

ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) :
	pDocShell( pDocSh ),
	aCellPos( rP ),
	pEditEngine( NULL ),
	pForwarder( NULL ),
	pOriginalSource( NULL ),
	bDataValid( sal_False ),
	bInUpdate( sal_False ),
	bDirty( sal_False ),
	bDoUpdate( sal_True )
{
	if (pDocShell)
		pDocShell->GetDocument()->AddUnoObject(*this);
}

ScCellTextData::~ScCellTextData()
{
	ScUnoGuard aGuard;		//	needed for EditEngine dtor

	if (pDocShell)
	{
		pDocShell->GetDocument()->RemoveUnoObject(*this);
		pDocShell->GetDocument()->DisposeFieldEditEngine(pEditEngine);
	}
	else
		delete pEditEngine;

	delete pForwarder;

	delete pOriginalSource;
}

ScSharedCellEditSource* ScCellTextData::GetOriginalSource()
{
	if (!pOriginalSource)
		pOriginalSource = new ScSharedCellEditSource( this );
	return pOriginalSource;
}

void ScCellTextData::GetCellText(const ScAddress& rCellPos, String& rText)
{
	if (pDocShell)
	{
		ScDocument* pDoc = pDocShell->GetDocument();
		pDoc->GetInputString( rCellPos.Col(), rCellPos.Row(), rCellPos.Tab(), rText );
    }
}

SvxTextForwarder* ScCellTextData::GetTextForwarder()
{
	if (!pEditEngine)
	{
		if ( pDocShell )
		{
			ScDocument* pDoc = pDocShell->GetDocument();
			pEditEngine = pDoc->CreateFieldEditEngine();
		}
		else
		{
			SfxItemPool* pEnginePool = EditEngine::CreatePool();
			pEnginePool->FreezeIdRanges();
			pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );
		}
		//	currently, GetPortions doesn't work if UpdateMode is sal_False,
		//	this will be fixed (in EditEngine) by src600
//		pEditEngine->SetUpdateMode( sal_False );
		pEditEngine->EnableUndo( sal_False );
		if (pDocShell)
			pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
		else
			pEditEngine->SetRefMapMode( MAP_100TH_MM );
		pForwarder = new SvxEditEngineForwarder(*pEditEngine);
	}

	if (bDataValid)
		return pForwarder;

	String aText;

	if (pDocShell)
	{
		ScDocument* pDoc = pDocShell->GetDocument();

		SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() );
        if( const ScPatternAttr* pPattern =
                pDoc->GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
        {
            pPattern->FillEditItemSet( &aDefaults );
            pPattern->FillEditParaItems( &aDefaults );  // including alignment etc. (for reading)
        }

		const ScBaseCell* pCell = pDoc->GetCell( aCellPos );
		if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT )
			pEditEngine->SetTextNewDefaults( *((const ScEditCell*)pCell)->GetData(), aDefaults );
		else
		{
			GetCellText( aCellPos, aText );
			if (aText.Len())
				pEditEngine->SetTextNewDefaults( aText, aDefaults );
			else
				pEditEngine->SetDefaults(aDefaults);
		}
	}

	bDataValid = sal_True;
	return pForwarder;
}

void ScCellTextData::UpdateData()
{
	if ( bDoUpdate )
	{
		DBG_ASSERT(pEditEngine != NULL, "no EditEngine for UpdateData()");
		if ( pDocShell && pEditEngine )
		{
			//	during the own UpdateData call, bDataValid must not be reset,
			//	or things like attributes after the text would be lost
			//	(are not stored in the cell)

			bInUpdate = sal_True;	// prevents bDataValid from being reset

			ScDocFunc aFunc(*pDocShell);
			aFunc.PutData( aCellPos, *pEditEngine, sal_False, sal_True );	// always as text

			bInUpdate = sal_False;
			bDirty = sal_False;
		}
	}
	else
		bDirty = sal_True;
}

void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
	if ( rHint.ISA( ScUpdateRefHint ) )
	{
//        const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;

		//!	Ref-Update
	}
	else if ( rHint.ISA( SfxSimpleHint ) )
	{
		sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId();
		if ( nId == SFX_HINT_DYING )
		{
			pDocShell = NULL;						// invalid now

			DELETEZ( pForwarder );
			DELETEZ( pEditEngine );		// EditEngine uses document's pool
		}
		else if ( nId == SFX_HINT_DATACHANGED )
		{
			if (!bInUpdate)							// not for own UpdateData calls
				bDataValid = sal_False;					// text has to be read from the cell again
		}
	}
}

ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) :
	ScCellTextData( pDocSh, rP ),
	SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
{
}

ScCellTextObj::~ScCellTextObj() throw()
{
}
