uifw/eikctl/src/EIKRTED.CPP
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/eikctl/src/EIKRTED.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,892 @@
+/*
+* Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <s32mem.h>
+#include <s32file.h>
+#include <txtrich.h>
+#include <basched.h>
+#include <apparc.h>
+#include <apgdoor.h>
+#include <apacln.h>
+#include <clock.h>
+#include <eikrted.h>
+#include <eikenv.h>
+#include <eikappui.h>
+#include <eikembal.h>
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <eikdoc.h>
+#else
+#include <eikdoc.h>
+#include <uikon/eikdefaulticondefs.h>
+#include <uikon/eikenvinterface.h>
+#endif
+#include <eikproc.h>
+#include <eikon.hrh>
+#include <eikpanic.h>
+#include <eikedwin.pan>
+#include <eikctl.rsg>
+#include <eikcoctl.rsg>
+
+#include <AknTasHook.h>
+GLDEF_C void Panic(TEikEdwinPanic aPanic)
+	{
+	_LIT(KPanicCat,"EIKON-EDWIN");
+	User::Panic(KPanicCat,aPanic);
+	}
+
+//
+// class CEikParserManager
+//
+
+const TInt KParseScanDelay	=750000; // 0.75s
+const TInt KNullStartPos	=-1;
+
+NONSHARABLE_CLASS(CEikParserManager) : public CBase, public MEikEdwinObserver
+	{
+public:
+	static CEikParserManager* NewL(CEikRichTextEditor& aEditor);
+	~CEikParserManager();
+public:
+	void SetParserObserver(MEikRichTextEditorParserObserver* aObserver);
+	void Start(TInt aStartPos,TInt aLength);
+private:
+	CEikParserManager(CEikRichTextEditor& aEditor);
+	void ConstructL();
+	void Start();
+	void StartTimer();
+	void Reset();
+	static TInt ParseTextCallbackL(TAny* aSelf);
+	void ParseTextL();
+private: // from MEikEdwinObserver
+	void HandleEdwinEventL(CEikEdwin* aEdwin,TEdwinEvent aEventType);
+private:
+	CPeriodic* iTimer;
+	CEikRichTextEditor& iEditor;
+	MEikRichTextEditorParserObserver* iParserObserver;
+	TInt iStartPos; // start of changed area
+	TInt iLength; // length of changed area
+	MParser* iParser;
+	TInt iTagStart; // start of tag cursor is over
+	TInt iTagLength; // length of tag cursor is over
+	TBool iStateChanged;
+	TBool iParseWholeText;
+
+public: // new methods
+	void ForceFullParseL();
+
+	};
+
+CEikParserManager* CEikParserManager::NewL(CEikRichTextEditor& aEditor)
+	{ // static
+	CEikParserManager* self=new(ELeave) CEikParserManager(aEditor);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+CEikParserManager::~CEikParserManager()
+	{
+	if (iTimer)
+		iTimer->Cancel();
+	delete iTimer;
+	}
+
+void CEikParserManager::SetParserObserver(MEikRichTextEditorParserObserver* aObserver)
+	{
+	iParserObserver=aObserver;
+	}
+
+void CEikParserManager::Start(TInt aStartPos,TInt aLength)
+	{
+	if (iStartPos==KNullStartPos)
+		iStartPos=aStartPos;
+	else
+		iStartPos=Min(iStartPos,aStartPos);
+	if (iLength==0 || aLength>=0)
+		iLength=Max(iLength,aLength);
+	else // aLength<0
+		iLength=Max(iLength+aLength,0);
+	iStateChanged=ETrue;
+	StartTimer();
+	}
+
+CEikParserManager::CEikParserManager(CEikRichTextEditor& aEditor)
+	: iEditor(aEditor)
+	{
+	Reset();
+	}
+
+void CEikParserManager::ConstructL()
+	{
+	iTimer=CPeriodic::NewL(CActive::EPriorityStandard);
+	iEditor.AddEdwinObserverL(this);
+	}
+
+void CEikParserManager::Start()
+	{
+	StartTimer();
+	}
+
+void CEikParserManager::StartTimer()
+	{
+	if (iTimer->IsActive())
+		iTimer->Cancel();
+	iTimer->Start(KParseScanDelay,KParseScanDelay,TCallBack(ParseTextCallbackL,this));
+	}
+
+void CEikParserManager::Reset()
+	{
+	iStartPos=KNullStartPos;
+	iLength=0;
+	}
+
+TInt CEikParserManager::ParseTextCallbackL(TAny* aSelf)
+	{ // static
+	REINTERPRET_CAST(CEikParserManager*,aSelf)->ParseTextL();
+	return 0;
+	}
+
+void CEikParserManager::ParseTextL()
+	{
+	TInt startPos=iStartPos;
+	TInt length=iLength;
+	Reset();
+	iTimer->Cancel();
+	const TBool foundParser=(iStateChanged && iEditor.RichText()->ParseText(startPos,length,iParseWholeText));
+	iStateChanged=EFalse;
+	MParser* parser=iParser;
+	TInt tagStart=iTagStart;
+	TInt tagLength=iTagLength;
+	TInt err=KErrNone;
+	TBool overNewTag=EFalse;
+	if (iEditor.RichText()->CursorOverTag(iEditor.CursorPos(),parser,tagStart,tagLength))
+		{
+		// are we over a new tag?  Update members if so
+		if ((TInt)parser!=(TInt)iParser || tagStart!=iTagStart || tagLength!=iTagLength)
+			{
+			overNewTag=ETrue;
+			iParser=parser;
+			if (iTagStart!=KNullStartPos)
+				{
+				TRAP(err,iEditor.TextView()->HandleRangeFormatChangeL(TCursorSelection(iTagStart,iTagStart+iTagLength),ETrue));
+				}
+			iTagStart=tagStart;
+			iTagLength=tagLength;
+			// the tag may be drawn differently when the cursor is over it
+			TRAP(err,iEditor.TextView()->HandleRangeFormatChangeL(TCursorSelection(tagStart,tagStart+tagLength),ETrue));
+			}
+		}
+	else
+		{
+		if (iParser)
+			{
+			overNewTag=ETrue; // if iParser!=NULL, we used to be over a tag and are now over a null one
+			// the tag may be drawn differently now the cursor isn't over it
+			TRAP(err,iEditor.TextView()->HandleRangeFormatChangeL(TCursorSelection(iTagStart,iTagStart+iTagLength),ETrue));
+			}
+		iParser=NULL;
+		iTagStart=KNullStartPos;
+		iTagLength=0;
+		}
+	if (foundParser && (startPos!=tagStart || length!=tagLength))
+		{
+		// newly identified parser is different from the one the cursor is over so...
+		// change the text format for the parser also
+		TRAPD(err2,iEditor.TextView()->HandleRangeFormatChangeL(TCursorSelection(startPos,startPos+length),ETrue));
+		if (err==KErrNone)
+			err=err2;
+		}
+	if (overNewTag && iParserObserver)
+		{
+		if (iParser)
+			{
+			iParserObserver->HandleCursorOverParserL(iParser->CreateDoItText(*(iEditor.RichText()),startPos,length));
+			}
+		else
+			{
+			TBuf<4> nullText(KNullDesC);
+			iParserObserver->HandleCursorOverParserL(nullText);
+			}
+		}
+	User::LeaveIfError(err);
+	}
+
+void CEikParserManager::HandleEdwinEventL(CEikEdwin* aEdwin,TEdwinEvent aEventType)
+	{
+	if ((TInt)aEdwin==(TInt)&iEditor && aEventType==MEikEdwinObserver::EEventNavigation)
+		Start();
+	}
+
+void CEikParserManager::ForceFullParseL()
+	{
+	iParseWholeText = ETrue;
+	iStateChanged = ETrue;
+	ParseTextL();
+	iParseWholeText = EFalse;
+	}
+//
+// class CEikRichTextEditor
+//
+
+EXPORT_C CEikRichTextEditor::CEikRichTextEditor()
+	{
+	iEdwinUserFlags=EAllowPictures|EAllowUndo;
+	iEdwinInternalFlags=ERichText;
+	iDefaultIconicDoorSize=KDefaultIconicDoorSize;
+	AKNTASHOOK_ADD( this, "CEikRichTextEditor" );
+	}
+
+EXPORT_C CEikRichTextEditor::CEikRichTextEditor(const TGulBorder& aBorder)
+	: CEikGlobalTextEditor(aBorder)
+	{
+	iEdwinUserFlags=EAllowPictures|EAllowUndo;
+	iEdwinInternalFlags=ERichText;
+	iDefaultIconicDoorSize=KDefaultIconicDoorSize;
+	AKNTASHOOK_ADD( this, "CEikRichTextEditor" );
+	}
+
+EXPORT_C CEikRichTextEditor::~CEikRichTextEditor()
+	{
+	AKNTASHOOK_REMOVE();
+	CRichText* text=RichText();
+	if (text)
+	{
+		text->SetEditObserver(NULL);
+		}
+	delete iEmbeddedDocUpdate;
+	if (iEmbeddedDoc.iPicture.IsPtr())
+		delete iEmbeddedDoc.iPicture.AsPtr();
+	delete iParserManager;
+	}
+
+EXPORT_C void CEikRichTextEditor::ConstructL(const CCoeControl* aParent,TInt aNumberOfLines,TInt aTextLimit,
+											 TInt aEdwinFlags,TInt aFontControlFlags,TInt aFontNameFlags)
+	{
+	CEikGlobalTextEditor::ConstructL(aParent,aNumberOfLines,aTextLimit,aEdwinFlags,aFontControlFlags,aFontNameFlags);
+	CommonConstructL();
+	}
+
+EXPORT_C void CEikRichTextEditor::ConstructFromResourceL(TResourceReader& aReader)
+	{
+	CEikGlobalTextEditor::ConstructFromResourceL(aReader);
+	CommonConstructL();
+	}
+
+void CEikRichTextEditor::CommonConstructL()
+	{
+	iEmbeddedDocUpdate=CIdle::NewL(EActivePriorityWsEvents+1);
+	if (!(iEdwinUserFlags&ENoTextParsers))
+		iParserManager=CEikParserManager::NewL(*this);
+	}
+
+EXPORT_C void CEikRichTextEditor::Draw(const TRect& aRect) const
+	{
+	CEikEdwin::Draw(aRect);
+	}
+
+EXPORT_C TKeyResponse CEikRichTextEditor::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+	{
+	if (aType!=EEventKey)
+		return EKeyWasNotConsumed;
+	if (iEdwinUserFlags&EDisplayOnly)
+		return EKeyWasConsumed;
+	const TInt code=aKeyEvent.iCode;
+	if ((code==EKeySpace || code==EKeyEnter) && CheckForObjectL())
+		return EKeyWasConsumed;
+	const TInt modifiers=aKeyEvent.iModifiers;
+	if (modifiers&EModifierCtrl)
+		{
+		TBool consumed=ETrue;
+		TBuf<24> buf;
+		if (aKeyEvent.iModifiers&EModifierShift)
+			iCoeEnv->ReadResource(buf,R_EIK_EDWIN_SHIFT_CTRL_HOTKEYS);
+		else
+			iCoeEnv->ReadResource(buf,R_EIK_EDWIN_CTRL_HOTKEYS);
+		const TInt pos=buf.Locate(TChar(code+'a'-1));
+		switch (pos)
+			{
+		case EHotKeyInsertObject:
+			CheckNotReadOnlyL();
+			if (!(iEdwinUserFlags&EAllowPictures))
+				iEikonEnv->LeaveWithInfoMsg(R_EIK_TBUF_CANNOT_INSERT_OBJECTS);
+			InsertObjectL(EGlassIfPossible);
+			break;
+		case EHotKeyEditObject:
+			CheckNotReadOnlyL();
+			if (!(iEdwinUserFlags&EAllowPictures))
+				return EKeyWasConsumed;
+			ReEditObjectL();
+			break;
+		case EHotKeyFormatObject:
+			CheckNotReadOnlyL();
+			if (!(iEdwinUserFlags&EAllowPictures))
+				return EKeyWasConsumed;
+			EditPictureFormatL();
+			break;
+		default:
+			consumed=EFalse;
+			}
+		if (consumed)
+			return EKeyWasConsumed;
+		}
+	TKeyResponse response=CEikGlobalTextEditor::OfferKeyEventL(aKeyEvent,aType);
+	UpdateButtonGroup();
+	return response;
+	}
+
+EXPORT_C void CEikRichTextEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+	{
+	CEikEdwin::HandlePointerEventL(aPointerEvent);
+	}
+
+EXPORT_C void* CEikRichTextEditor::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+EXPORT_C void CEikRichTextEditor::ActivateL()
+	{
+	SetTextObserver(*RichText());
+	const TInt docLength=iText->DocumentLength();
+	if( iParserManager )
+		iParserManager->Start(0,docLength);
+	UpdatePictureFormatL(0,docLength);
+	UpdatePictureSizeL(0,docLength);
+	CEikGlobalTextEditor::ActivateL();
+	}
+	
+EXPORT_C void CEikRichTextEditor::HandleTextPastedL(TInt aStartPos,TInt& aLength)
+	{
+	UpdatePictureFormatL(aStartPos,aLength);
+	UpdatePictureSizeL(aStartPos,aLength);
+	}
+	
+EXPORT_C void CEikRichTextEditor::NotifyExit(TExitMode aMode)
+	{
+	if (aMode==MApaEmbeddedDocObserver::EEmpty)
+		{
+		if (iEdwinInternalFlags&EReEditingObject)
+			iEmbeddedDocUpdate->Start(TCallBack(CEikRichTextEditor::TryDeleteEmbeddedDocL, this));
+		else
+			iEmbeddedDocUpdate->Start(TCallBack(CEikRichTextEditor::DeleteEmbeddedDoc, this));
+		}
+	else if (aMode==MApaEmbeddedDocObserver::ENoChanges)
+		{
+		if (iEdwinInternalFlags&EReEditingObject)
+			iEmbeddedDoc=TPictureHeader();
+		else // apps should call back with EEmpty in this case
+			iEmbeddedDocUpdate->Start(TCallBack(CEikRichTextEditor::DeleteEmbeddedDoc, this));
+		}
+	else
+		{
+		if (iEdwinInternalFlags&EReEditingObject)
+			iEmbeddedDocUpdate->Start(TCallBack(CEikRichTextEditor::UpdateEmbeddedDocL, this));
+		else
+			iEmbeddedDocUpdate->Start(TCallBack(CEikRichTextEditor::InsertEmbeddedDocL, this));
+		}
+	}
+
+TInt CEikRichTextEditor::TryDeleteEmbeddedDocL(TAny *aThis)
+	{ // static
+	CEikRichTextEditor* editor=REINTERPRET_CAST(CEikRichTextEditor*,aThis);
+	editor->iEdwinInternalFlags&=~EReEditingObject;
+	if (!(CEikonEnv::Static()->QueryWinL(R_EIK_TBUF_DEL_EMPTY_OBJECT_CONFIRM_1,R_EIK_TBUF_DEL_EMPTY_OBJECT_CONFIRM_2)))
+		editor->iTextView->HandleRangeFormatChangeL(editor->Selection(),EFalse);
+	else
+		{
+		TInt docPos;
+		TRect rect;
+		editor->iTextView->IsPictureFrameSelected(rect,docPos);
+		TBool changed=EFalse;
+		editor->DeleteL(changed,TCursorSelection(docPos,docPos+1),ETrue);
+		editor->iTextView->SetPendingSelection(TCursorSelection(docPos,docPos));
+		editor->iTextView->HandleInsertDeleteL(TCursorSelection(docPos,docPos),1,changed);
+		editor->UpdateScrollBarsL();
+		if (changed)
+			editor->ReportEdwinEventL(MEikEdwinObserver::EEventFormatChanged);
+		}
+	editor->ReportEventL(MCoeControlObserver::EEventStateChanged);
+	editor->UpdateScrollBarsL();
+	return 0;
+	}
+
+TInt CEikRichTextEditor::DeleteEmbeddedDoc(TAny *aThis)
+	{ // static
+	CEikRichTextEditor* editor=REINTERPRET_CAST(CEikRichTextEditor*,aThis);
+	if (editor->iEmbeddedDoc.iPicture.IsPtr())
+		delete editor->iEmbeddedDoc.iPicture.AsPtr();
+	editor->iEmbeddedDoc=TPictureHeader();
+	return 0;
+	}
+
+TInt CEikRichTextEditor::InsertEmbeddedDocL(TAny *aThis)
+	{ // static
+	CEikRichTextEditor* editor=REINTERPRET_CAST(CEikRichTextEditor*,aThis);
+	TInt err=KErrNone;
+	if (editor->iEdwinUserFlags&EShowAllPicturesAsIconic)
+		{
+		TRAPD(err,STATIC_CAST(CApaDoor*,editor->iEmbeddedDoc.iPicture.AsPtr())->SetFormatToTemporaryIconL());
+		if (err)
+			goto errorCheck;
+		}
+	TRAP(err,editor->InsertPictureL(editor->iEmbeddedDoc));
+errorCheck:
+	editor->iEmbeddedDoc=TPictureHeader();
+	User::LeaveIfError(err);
+	return 0;
+	}
+
+TInt CEikRichTextEditor::UpdateEmbeddedDocL(TAny* aThis)
+	{ // static
+	CEikRichTextEditor* editor=REINTERPRET_CAST(CEikRichTextEditor*,aThis);
+	editor->iEdwinInternalFlags&=~EReEditingObject;
+	editor->iText->SetHasChanged(ETrue);
+	editor->iTextView->HandleRangeFormatChangeL(editor->Selection(),EFalse);
+	editor->ReportEventL(MCoeControlObserver::EEventStateChanged);
+	editor->UpdateScrollBarsL();
+	return 0;
+	}
+
+EXPORT_C void CEikRichTextEditor::CopyDocumentContentL(CGlobalText& aInText,CGlobalText& aOutText)
+	{
+	__ASSERT_DEBUG(&aInText,Panic(EEikPanicNullPointer));
+	__ASSERT_DEBUG(&aOutText,Panic(EEikPanicNullPointer));
+	aOutText.Reset();
+	aOutText.SetFieldFactory(CONST_CAST(MTextFieldFactory*,aInText.FieldFactory()));
+	((CRichText&)aInText).DetachFromStoreL(CPicture::EDetachFull);
+	iBufStore=CBufStore::NewLC(4096);
+	((CRichText&)aOutText).SetPictureFactory(iEikonEnv->PictureFactory(),this);
+	TStreamId streamId=aInText.StoreL(*iBufStore);
+	aOutText.RestoreL(*iBufStore,streamId);
+	((CRichText&)aOutText).DetachFromStoreL(CPicture::EDetachFull);
+	RStoreWriteStream paraWriteStream;
+	TStreamId paraStreamId=paraWriteStream.CreateLC(*iBufStore);
+	(aInText.GlobalParaFormatLayer())->ExternalizeL(paraWriteStream);
+	CleanupStack::PopAndDestroy(); // paraStreamId
+	RStoreReadStream paraReadStream;
+	paraReadStream.OpenLC(*iBufStore,paraStreamId);
+	((CParaFormatLayer*)(aOutText.GlobalParaFormatLayer()))->InternalizeL(paraReadStream);
+	CleanupStack::PopAndDestroy(); // paraReadStream
+	RStoreWriteStream charWriteStream;
+	TStreamId charStreamId=charWriteStream.CreateLC(*iBufStore);
+	(aInText.GlobalCharFormatLayer())->ExternalizeL(charWriteStream);
+	CleanupStack::PopAndDestroy(); // charStreamId
+	RStoreReadStream charReadStream;
+	charReadStream.OpenLC(*iBufStore,charStreamId);
+	((CCharFormatLayer*)(aOutText.GlobalCharFormatLayer()))->InternalizeL(charReadStream);
+	CleanupStack::PopAndDestroy(2); // iBufStore and charReadStream
+	iBufStore=NULL;
+	}
+
+EXPORT_C const CStreamStore& CEikRichTextEditor::StreamStoreL(TInt /*aPos*/) const
+	{
+	return *iBufStore;
+	}
+
+EXPORT_C void CEikRichTextEditor::NewPictureL(TPictureHeader& aHdr,const CStreamStore& aDeferredPictureStore)const
+	{
+	iEikonEnv->PictureFactory()->NewPictureL(aHdr,aDeferredPictureStore);
+	}
+
+EXPORT_C void CEikRichTextEditor::EditObserver(TInt aStartEdit,TInt aEditLength)
+	{
+	if (iParserManager)
+		iParserManager->Start(aStartEdit,aEditLength);
+	CEikEdwin::EditObserver(aStartEdit,aEditLength);
+	}
+
+EXPORT_C CRichText* CEikRichTextEditor::RichText() const
+	{
+	return (CRichText*)iText;
+	}
+
+void CEikRichTextEditor::InsertPictureL(const TPictureHeader& aPictureHeader)
+	{
+	__ASSERT_DEBUG(iText,Panic(EEikPanicEdwinNoText));
+	__ASSERT_DEBUG(iTextView,Panic(EEikPanicEdwinNoView));
+	TBool formatHasChanged=EFalse;
+	TCursorSelection selection=iTextView->Selection();
+	const TInt selLength=selection.Length();
+	const TInt oldLength=iText->DocumentLength();
+	TRAPD(err,DoInsertPictureL(formatHasChanged,aPictureHeader));
+	if (err!=KErrNone)
+		{
+		delete aPictureHeader.iPicture.AsPtr();
+		ClearUndo();
+		}
+	if (selLength==0)
+		{
+		ClearUndo();
+		if (err==KErrNone)
+			iTextView->HandleCharEditL(CTextLayout::EFCharacterInsert);
+		}
+	else
+		{
+		const TInt lower=selection.LowerPos();
+		selection=TCursorSelection(lower,(err==KErrNone? lower+1 : lower));
+		if (err==KErrNone)
+			SetUndoableText(selection);
+		if (err==KErrNone || oldLength>iText->DocumentLength())
+			iTextView->HandleInsertDeleteL(selection,selLength,formatHasChanged);
+		}
+	User::LeaveIfError(err);
+	ReportEventL(MCoeControlObserver::EEventStateChanged);
+	UpdateScrollBarsL();
+	if (iText->DocumentLength()==UpperFullFormattingLength()+1)
+		SetAmountToFormatL();
+	}
+
+void CEikRichTextEditor::DoInsertPictureL(TBool& aFormatHasChanged,const TPictureHeader& aPictureHeader)
+	{
+	TCursorSelection selection=iTextView->Selection();
+	const TInt selLength=selection.Length();
+	if (selLength)
+		{
+		iTextView->CancelSelectionL();
+		SetCursorPosL(selection.LowerPos(),EFalse);
+		DeleteL(aFormatHasChanged,selection);
+		}
+	else if (iTextLimit && TextLength()>=iTextLimit)
+		{
+		CEikonEnv::Beep();
+		iEikonEnv->LeaveWithInfoMsg(R_EIK_TBUF_MAX_CHARACTERS_REACHED);
+		}
+	STATIC_CAST(CRichText*,iText)->InsertL(CursorPos(),aPictureHeader);
+	}
+
+void CEikRichTextEditor::RoomForObjectL()
+	{
+	if (iTextLimit && TextLength()>=iTextLimit)
+		{
+		CEikonEnv::Beep();
+		iEikonEnv->InfoMsg(R_EIK_TBUF_MAX_CHARACTERS_REACHED);
+		CBaActiveScheduler::LeaveNoAlert();
+		}
+	}
+
+EXPORT_C void CEikRichTextEditor::InsertObjectL(TObjectFormat aFormat)
+	{
+	RoomForObjectL();
+	CEikEmbeddableAppList* list=new(ELeave) CEikEmbeddableAppList;
+	CleanupStack::PushL(list);
+	list->ConstructL();
+	TInt count=list->Count();
+	if (!count)
+		iEikonEnv->InfoMsg(R_EIK_NO_EMBEDDABLE_APPS_FOUND);
+	else
+		{
+		ASSERT(iEikonEnv->CDlgDialogFactory());
+		TInt choice=0;
+		if(iEikonEnv->CDlgDialogFactory()->RunInsertObjectDlgLD(list, choice))
+			{
+			if (!OkToDeleteSelectionL())
+				{
+				CleanupStack::PopAndDestroy(); // list
+				return;
+				}
+			CEikDocument* newDoc=list->CreateEmbeddedDocumentL(choice,iEikonEnv->Process());
+			TApaDocCleanupItem cleanup(iEikonEnv->Process(),newDoc);
+			CleanupStack::PushL(cleanup);
+			newDoc->NewDocumentL();
+			CleanupStack::Pop(); // cleanup
+			InsertObjectL(newDoc,aFormat);
+			}
+		}
+	CleanupStack::PopAndDestroy(); // list
+	}
+
+EXPORT_C void CEikRichTextEditor::InsertObjectL()
+	{
+	InsertObjectL(EGlassIfPossible);
+	}
+
+EXPORT_C void CEikRichTextEditor::InsertObjectL(const TDesC& /*aAppDllName*/,TUid aAppDllUid,TObjectFormat aFormat)
+	{
+	RoomForObjectL();
+	if (!OkToDeleteSelectionL())
+		return;
+	CApaDocument* newDoc=NULL;
+	TRAPD(err,newDoc=iEikonEnv->Process()->AddNewDocumentL(aAppDllUid));
+	if (err==KErrNotFound)
+		iEikonEnv->LeaveWithInfoMsg(R_EIK_EMBEDDED_GENERIC_APP_NOT_FOUND);
+	else if (err!=KErrNone)
+		User::Leave(err);
+	TApaDocCleanupItem cleanup(iEikonEnv->Process(),newDoc);
+	CleanupStack::PushL(cleanup);
+	newDoc->NewDocumentL();
+	CleanupStack::Pop();
+	InsertObjectL(newDoc,aFormat);
+	}
+
+void CEikRichTextEditor::InsertObjectL(CApaDocument* aDoc,TObjectFormat aFormat)
+	{
+	iEmbeddedDoc.iPictureType=KUidPictureTypeDoor;
+	iEmbeddedDoc.iPicture=CApaDoor::NewL(iEikonEnv->FsSession(),*aDoc,iDefaultIconicDoorSize); // takes ownership of newDoc
+	// can it draw as glass? change format if so
+	if (aFormat==EGlassIfPossible)
+		{
+		TRAP_IGNORE(STATIC_CAST(CApaDoor*,iEmbeddedDoc.iPicture.AsPtr())->SetFormatToGlassL());
+		}
+	aDoc->EditL(this);
+	}
+
+EXPORT_C void CEikRichTextEditor::InsertObjectL(TUid aPictureType,CBase* aData)
+	{
+	MEikPictureFactory* factory=iEikonEnv->ExtendedPictureFactory(aPictureType);
+	if (factory==NULL)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	TPictureHeader pic=factory->InsertL(aPictureType,aData);
+	InsertPictureL(pic);
+	}
+
+EXPORT_C TBool CEikRichTextEditor::CheckForObjectL()
+	{
+	TRect frameRect;
+	TInt docPos;
+	if (!iTextView->IsPictureFrameSelected(frameRect,docPos))
+		return EFalse;
+	const TPictureHeader header=((CRichText*)iText)->PictureHeader(docPos);
+	if (header.iPictureType==KNullUid)
+		return EFalse;
+	// stop multiple pointer events launching the same apps several times ???
+	iCoeEnv->WsSession().PurgePointerEvents();
+	DoReEditObjectL(docPos);
+	return ETrue;
+	}
+
+EXPORT_C void CEikRichTextEditor::ReEditObjectL()
+	{
+	const TInt pos=ObjectCursorPos();
+	if (pos!=KErrNotFound)
+		DoReEditObjectL(pos);
+	}
+
+EXPORT_C TInt CEikRichTextEditor::ObjectCursorPos() const
+	{
+	if (SelectionLength()>1)
+		{
+		iEikonEnv->InfoMsg(R_EIK_REGION_SELECTED);
+		return KErrNotFound;
+		}
+	TRect frameRect;
+	TInt docPos;
+	if (iTextView->IsPictureFrameSelected(frameRect,docPos))
+		{
+		TPictureHeader header=STATIC_CAST(CRichText*,iText)->PictureHeader(docPos);
+		if (header.iPictureType!=KNullUid)
+			return docPos;
+		}
+	iEikonEnv->InfoMsg(R_EIK_NO_OBJECT_PRESENT); // no embedded object found
+	return KErrNotFound;
+	}
+
+void CEikRichTextEditor::DoReEditObjectL(TInt aDocPos)
+	{
+	TPictureHeader header=RichText()->PictureHeader(aDocPos);
+	if (header.iPictureType==KUidPictureTypeDoor)
+	{
+	CApaDoor* door=NULL;
+	CApaDocument* embeddedDoc=NULL;
+	GetEmbeddedAppL(door,embeddedDoc,aDocPos);
+	iEdwinInternalFlags|=EReEditingObject;
+	embeddedDoc->EditL(this,IsReadOnly());
+		}
+	else
+		{
+		MEikPictureFactory* factory=iEikonEnv->ExtendedPictureFactory(header.iPictureType);
+		if (factory==NULL)
+			{
+			User::Leave(KErrNotSupported);
+			}
+		factory->EditL(header,IsReadOnly());
+		}
+	}
+
+EXPORT_C void CEikRichTextEditor::EditPictureFormatL()
+	{
+	const TInt docPos=ObjectCursorPos();
+	if (docPos==KErrNotFound)
+		return;
+	CApaDoor* door=NULL;
+	CApaDocument* embeddedDoc=NULL;
+	GetEmbeddedAppL(door,embeddedDoc,docPos);
+	// if the doc can display as glass open the full dialog
+	CApaDocument::TCapability capability=embeddedDoc->Capability();
+	MEikCDlgDialogFactory* cdlgDialogFactory = iEikonEnv->CDlgDialogFactory();
+	ASSERT(cdlgDialogFactory);
+	if (capability.CanDrawGlass())
+		{
+		if(cdlgDialogFactory->RunFormatObjectDlgLD(*door, *embeddedDoc, iDefaultIconicDoorSize))
+			{
+			iText->SetHasChanged(ETrue);
+			iTextView->HandleRangeFormatChangeL(iTextView->Selection(),EFalse);
+			UpdateScrollBarsL();
+			ReportEventL(MCoeControlObserver::EEventStateChanged);
+			// update the picture size in the header when this becomes possible (post B4 etext)
+			}
+		}
+	else
+		{// otherwise open the little dialog that does nothing...
+		cdlgDialogFactory->RunObjectInfoDlgLD(*(door->Caption()));
+		}
+	}
+
+
+EXPORT_C void CEikRichTextEditor::PictureFormatChangedL()
+	{
+	iText->SetHasChanged(ETrue);
+	iTextView->HandleRangeFormatChangeL(iTextView->Selection(),EFalse);
+	UpdateScrollBarsL();
+	// update the picture size in the header when this becomes possible (post B4 etext)
+	ReportEventL(MCoeControlObserver::EEventStateChanged);
+	}
+
+EXPORT_C void CEikRichTextEditor::GetEmbeddedAppL(CApaDoor*& aDoor,CApaDocument*& aDoc,TInt aDocPos)
+	{
+	aDoor=STATIC_CAST(CApaDoor*,RichText()->PictureHandleL(aDocPos));
+	TRAPD(err,aDoc=aDoor->DocumentL(ETrue)); // always prompt for password
+	if (err==KErrNotFound)
+		{
+		TBuf<80> buf;
+		iCoeEnv->ReadResource(buf,R_EIK_EMBEDDED_APP_NOT_FOUND);
+		TBuf<128> caption=*aDoor->Caption();
+		TextUtils::TruncateToNumChars(caption,RMessageWindow::EMaxTextLength-32); // resource is no longer than 32 chars
+		HBufC* message=HBufC::NewLC(caption.Length()+buf.Length());
+		TPtr ptr=message->Des();
+		ptr.Format(buf,&caption);
+		iEikonEnv->InfoMsg(*message);
+		CleanupStack::PopAndDestroy(); // message
+		CBaActiveScheduler::LeaveNoAlert();
+		}
+	User::LeaveIfError(err);
+	}
+
+EXPORT_C void CEikRichTextEditor::UpdatePictureFormatL()
+	{
+	UpdatePictureFormatL(0,iText->DocumentLength());
+	}
+
+EXPORT_C void CEikRichTextEditor::UpdatePictureFormatL(TInt aStartPos,TInt aLength)
+	{
+	TInt count=iText->ComponentInfo().iPictureCount;
+	if (~iEdwinUserFlags&EShowAllPicturesAsIconic || count==0)
+		return;
+	const TInt endPos=aStartPos+aLength;
+	for (TInt ii=aStartPos;ii<endPos;ii++)
+		{
+		if (count==0)
+			return;
+		CApaDoor* door=STATIC_CAST(CApaDoor*,RichText()->PictureHandleL(ii));
+		if (door)
+			{
+			door->SetFormatToTemporaryIconL();
+			--count;
+			}
+		}
+	}
+
+EXPORT_C void CEikRichTextEditor::SetDefaultIconicDoorSize(const TSize& aSize)
+	{
+	iDefaultIconicDoorSize=aSize;
+	}
+
+EXPORT_C const TSize& CEikRichTextEditor::DefaultIconicDoorSize() const
+	{
+	return iDefaultIconicDoorSize;
+	}
+
+EXPORT_C void CEikRichTextEditor::UpdatePictureSizeL()
+	{
+	UpdatePictureSizeL(0,iText->DocumentLength());
+	}
+
+EXPORT_C void CEikRichTextEditor::UpdatePictureSizeL(TInt aStartPos,TInt aLength)
+	{
+	TInt count=iText->ComponentInfo().iPictureCount;
+	const TInt endPos=aStartPos+aLength;
+	for (TInt ii=aStartPos;ii<endPos;ii++)
+		{
+		if (count==0)
+			return;
+		CApaDoor* door=STATIC_CAST(CApaDoor*,RichText()->PictureHandleL(ii));
+		if (door)
+			{
+			if (door->Format()!=CApaDoorBase::EGlassDoor)
+				door->SetSizeInTwips(iDefaultIconicDoorSize);
+			else
+				{
+				door->SetFormatToTemporaryIconL(ETrue);
+				door->SetSizeInTwips(iDefaultIconicDoorSize);
+				door->SetFormatToTemporaryIconL(EFalse);
+				}
+			--count;
+			}
+		}
+	}
+
+EXPORT_C void CEikRichTextEditor::SetParserObserver(MEikRichTextEditorParserObserver* aObserver)
+	{
+	if (iParserManager)
+		iParserManager->SetParserObserver(aObserver);
+	}
+
+EXPORT_C void CEikRichTextEditor::SetPhoneNumberGrouping( TBool aEnable )
+    {
+    if ( aEnable )
+    	iEdwinInternalFlags|=EPhoneNumberGrouping;
+    else
+    	iEdwinInternalFlags&=(~EPhoneNumberGrouping);
+    }
+
+void CEikRichTextEditor::SetTextObserver(CRichText& aText)
+	{
+	aText.SetEditObserver(this);
+	}
+
+/**
+ * Writes the internal state of the control and its components to aStream.
+ * Does nothing in release mode.
+ * Designed to be overidden and base called by subclasses.
+ *
+ * @internal
+ * @since App-Framework_6.1
+ */
+#ifndef _DEBUG
+EXPORT_C void CEikRichTextEditor::WriteInternalStateL(RWriteStream&) const
+	{}
+#else
+EXPORT_C void CEikRichTextEditor::WriteInternalStateL(RWriteStream& aWriteStream) const
+	{
+	CEikGlobalTextEditor::WriteInternalStateL(aWriteStream);
+	}
+#endif
+
+EXPORT_C void CEikRichTextEditor::Reserved_2()
+	{}
+
+EXPORT_C void CEikRichTextEditor::Reserved_3()
+	{}
+
+EXPORT_C void CEikRichTextEditor::RefreshParsersL()
+	{
+	if (iParserManager)
+		iParserManager->ForceFullParseL();
+	}