// RTEXTED.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <txtrich.h>
#include <s32file.h>
#include <f32file.h>
#include <apgdoor.h>
#include <coemain.h>
#include <coeutils.h>
#include <eikenv.h>
#include <coecntrl.h>
#include <basched.h>
#include <eikappui.h>
#include <e32keys.h>
#include <eikedwin.h>
#include <eikedwob.h>
#include <eikedwin.hrh>
#include <eikrted.h>
#include <eiktbar.h>
#include <eikcfdlg.h>
#include <eikcmds.hrh>
#include <eikpprob.h>
#include <eikprtdg.h>
#include <eikprtpv.h>
#include <prnsetup.h>
#include <frmprint.h>
#include <frmvis.h>
#include <eikproc.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <eikirda.h>
#include <eikchkbx.h>
#include <eikmfne.h>
#include <eikbtpan.h>
#include <eiktxtut.h>
#include <eiklabel.h>
#include <rtexted.rsg>
#include <eikon.rsg>
#include <eikon.mbg>
#include "rtexted.hrh"
#include <eikdialg.hrh>

#if defined(_UNICODE)
const TUid KUidSimpleApp={426};
#else
const TUid KUidSimpleApp={226};
#endif

const TInt KZoomStateOne=750;
const TInt KZoomStateTwo=TZoomFactor::EZoomOneToOne;
const TInt KZoomStateThree=1688;
const TInt KZoomStateFour=2000;

//
//CSetPreferencesDialog
//

class CSetPreferencesDialog : public CEikDialog
	{
public:
	CSetPreferencesDialog(TNonPrintingCharVisibility& aVisibility);
private:										   
	~CSetPreferencesDialog();
	void PreLayoutDynInitL();
	TBool OkToExitL(TInt aButtonId);
private:
	TNonPrintingCharVisibility* iVisibility;
	};

//
// CSimpleDocument
//

class CSimpleDocument : public CEikDocument, public MPictureFactory, public MRichTextStoreResolver
	{
public:
	static CSimpleDocument* NewL(CEikApplication& aApp);
	~CSimpleDocument();
public:
	CSimpleDocument(CEikApplication& aApp): CEikDocument(aApp) { }
	void DoNewFileL(const TFileName& aFileName);
	void DoOpenFileL(const TFileName& aFileName);
	void DoSaveToNewFileL(const TFileName& aNewFileName);
	TBool DoSaveToCurrentFileL();
	TBool FileNameExists(const TFileName& aFileName)const;
	void StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const;
	void RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic);
	CRichText* Text()const  {return iRichText;}
	void NewDocumentL();
private:
	void ConstructL();
private: // from MPictureFactory
	void NewPictureL(TPictureHeader& aHdr,const CStreamStore& aDeferredPictureStore) const;
private: // from MRichTextStoreResolver
	const CStreamStore& StreamStoreL(TInt aPos) const;
private: // from CEikDocument
	CEikAppUi* CreateAppUiL();
private:
	CRichText* iRichText;
	CParaFormatLayer* iParaFormatLayer;
	CCharFormatLayer* iCharFormatLayer;
	};


//
// class CSimpleAppUi
//

class CSimpleAppUi : public CEikAppUi, public MCoeControlObserver, public MEikEdwinObserver, public MPrintPreviewDialogObserver, public MFieldNumPagesInfo, public MFieldFileNameInfo
    {
public:
    ~CSimpleAppUi();
    void ConstructL();
	TInt UpdateFieldFileName(TPtr& aValueText) const;
	TInt UpdateFieldNumPages() const;
private: // framework
	TInt NumberOfPagesInDoc() const;
	void HandleCommandL(TInt aCommand);
	void HandleModelChangeL();
	TBool ProcessCommandParametersL(TApaCommand aCommand, TFileName& aDocumentName, const TDesC& aTail);
	void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType);
	void HandleEdwinEventL(CEikEdwin* aEdwin,TEdwinEvent aEventType);
	void OpenFileL(const TDesC& aFileName);
	void CreateFileL(const TDesC& aFileName);
private:
	void ResetViewL();
	void CmdFileNewL();
	void CmdFileOpenL();
	void CmdFileSaveL();
	void CmdFileTextImportL();
	TBool DoFileSaveL();
	void CmdFileSaveAsL();
	void RunPreviewDialogL();
	void DoOpenFileL(const TFileName& aFileName);
//	void RunPaginateDepenedentDialogs(TInt aCommand);
	void RunPageSetupDialogL();
	void AlterButtonState(TInt aFontFlag);
	void UpdateToolBarButtons();
	void UpdateToolBarAndBandL(TInt aCommand);
	void RunSetPreferencesDialogL();
	void CreateEdwinL();
	void CmdIrSendL();
	void CmdIrReceiveL();
	void ZoomL(TInt aZoomCmd);
	//from public MPrintPreviewDialogObserver
	TBool PageSetupChangedL(CPrintSetup* aPrintSetup, TInt& aNumPagesInDoc);
	TBool RunPrintRangeDialogL(CPrintSetup* aPrintSetup, TInt& aNumPagesInDoc);
	void TestReadOnlyL(TInt aCommand);
private:	
	void RunPrintDialogL();
	TBool RunPaginationDialogL();
private:
	CEikRichTextEditor* iRichEd;
	CRichText* iRichText;
	CPrintSetup* iPrintSetup;
	CTextPageRegionPrinter* iPrint;
	CArrayFix<TInt>* iCharsPerPage;
	CBufFlat* iBuf;
	TZoomFactor iAppZoom;
	TPrintParameters iPrintParameters;
	TBool iDocumentChanged;
    };

CSimpleAppUi::~CSimpleAppUi()
    {
	delete iCharsPerPage;
	delete iPrint;
	delete iPrintSetup;
	delete iRichEd;
	delete iBuf;
    }

TInt CSimpleAppUi::UpdateFieldFileName(TPtr& aValueText) const
// Set aValueText with the current document filename only. // (No path or extension).
	{
	TParse parser;

	User::LeaveIfError(parser.Set(iEikonEnv->Process()->MainDocFileName(),NULL,NULL));
	if (parser.Name().Length()>aValueText.MaxLength())
		return parser.Name().Length();
	aValueText=parser.Name();
	return 0;
	}


TInt CSimpleAppUi::UpdateFieldNumPages() const
	{
	return NumberOfPagesInDoc();
	}

TBool CSimpleAppUi::PageSetupChangedL(CPrintSetup* aPrintSetup,TInt& aNumPagesInDoc)
	{
	iPrint->SetPageMarginsInTwips(aPrintSetup->iPageMarginsInTwips.iMargins);
	iPrint->SetPageSpecInTwips(aPrintSetup->PrinterDevice()->CurrentPageSpecInTwips());
	iDocumentChanged=ETrue;
	if (RunPaginationDialogL())
		return ETrue;
	aNumPagesInDoc=iCharsPerPage->Count();
	return EFalse;
	}

TBool CSimpleAppUi::RunPrintRangeDialogL(CPrintSetup* aPrintSetup, TInt& aNumPagesInDoc)
	{	
	TUid olduid=aPrintSetup->PrinterDevice()->Model().iUid;
	TUid uid=olduid;
	CEikDialog* dialog=new(ELeave) CEikPrintRangeDialog(iPrintParameters,aPrintSetup,uid);
	if (dialog->ExecuteLD(R_EIK_DIALOG_PRINT_RANGE_SETUP))
		{
		if (olduid!=uid)	
			{
			aPrintSetup->CreatePrinterDeviceL(uid,iEikonEnv->FsSession());
			iPrint->SetPrinterDevice(aPrintSetup->PrinterDevice());
			iDocumentChanged=ETrue;
			if (RunPaginationDialogL())
				return ETrue;
			}
		}
	aNumPagesInDoc=iCharsPerPage->Count();
	iPrintSetup->FreeModelList();
	return EFalse; //no cancellation
	}

void CSimpleAppUi::RunPageSetupDialogL()
	{
	TBool cancel=EFalse;
	if (iDocumentChanged)
		cancel=RunPaginationDialogL();
	if (cancel)
		return;
	CEikPageSetupDialog* dialog=new(ELeave) CEikPageSetupDialog(iPrintSetup);
	if (dialog->ExecuteLD(R_EIK_DIALOG_PAGE_SPEC))
		{
		iPrint->SetPageMarginsInTwips(iPrintSetup->iPageMarginsInTwips.iMargins);
		iPrint->SetPageSpecInTwips(iPrintSetup->PrinterDevice()->CurrentPageSpecInTwips());
		iDocumentChanged=ETrue;
		}
	}

void CSimpleAppUi::RunPreviewDialogL()
	{
	TBool cancel=EFalse;
	if (iDocumentChanged)
		cancel=RunPaginationDialogL();
	if (cancel)
		return;
	TInt totalNumPages=iCharsPerPage->Count();
	iPrint->SetPrintPreview(ETrue);
	
	CEikPrintPreviewDialog* dialog=new(ELeave) CEikPrintPreviewDialog(*iPrintSetup,*iPrint,totalNumPages,this,4);
	if (dialog->ExecuteLD(R_EIK_DIALOG_PRINT_PREVIEW))
		{
		iPrint->SetPrintPreview(EFalse);
		CEikDialog* dialog=new(ELeave) CEikPrintProgressDialog(iPrintSetup,iPrint,iPrintParameters);
		dialog->ExecuteLD(R_EIK_DIALOG_PRINT_PROGRESS);
		}
	iPrintSetup->FreeModelList();
	}

void CSimpleAppUi::RunPrintDialogL()
	{
	TBool cancel=EFalse;
	if (iDocumentChanged)
		cancel=RunPaginationDialogL();
	if (cancel)
		return;
	TUid olduid=iPrintSetup->PrinterDevice()->Model().iUid; 	
	TUid uid=olduid;
	CEikDialog* rangedialog=new(ELeave) CEikPrintRangeDialog(iPrintParameters,iPrintSetup,uid,ETrue);
	if (rangedialog->ExecuteLD(R_EIK_DIALOG_PRINT_RANGE_SETUP))
		{
		if (olduid!=uid)
			{
			iPrintSetup->CreatePrinterDeviceL(uid,iEikonEnv->FsSession());
			iPrint->SetPrinterDevice(iPrintSetup->PrinterDevice());
			iDocumentChanged=ETrue;
			}
		}
	else
		return;
	if (iDocumentChanged)
		cancel=RunPaginationDialogL();
	if (cancel)
		return;
	//progress
	iPrint->SetPrintPreview(EFalse);
	CEikDialog* dialog=new(ELeave) CEikPrintProgressDialog(iPrintSetup,iPrint,iPrintParameters);
	dialog->ExecuteLD(R_EIK_DIALOG_PRINT_PROGRESS);
	iPrintSetup->FreeModelList();
	}

TBool CSimpleAppUi::RunPaginationDialogL()
	{
	const TBool cancel=iRichEd->RunPaginateDialogL(iPrintSetup,iCharsPerPage);
	if (!cancel)
		{
		iPrintParameters.iFirstPage=0;
		iPrintParameters.iLastPage=iCharsPerPage->Count()-1;
		iDocumentChanged=EFalse;
		}
	return cancel;
	}

TInt CSimpleAppUi::NumberOfPagesInDoc() const
	{
	return (iCharsPerPage->Count());
	}

TBool CSimpleAppUi::ProcessCommandParametersL(TApaCommand aCommand,TFileName& aDocumentName,const TDesC& /*aTail*/)
	{
	return CEikAppUi::ProcessCommandParametersL(aCommand,aDocumentName);
	}

void CSimpleAppUi::HandleModelChangeL()
	{
	iRichText=((CSimpleDocument*)iDocument)->Text();
	ResetViewL();
	if (!(iDocument->AppFileMode()&EFileWrite))
		{
		iRichEd->SetReadOnly(ETrue);
		iEikonEnv->InfoMsg(R_RTEXTED_READONLY);
		}
	}

void CSimpleAppUi::ConstructL()
    {
    BaseConstructL();
	iRichText=((CSimpleDocument*)iDocument)->Text();
	CreateEdwinL();
	AddToStackL(iRichEd);

	iPrintSetup=iEikonEnv->NewDefaultPrintSetupL();
	iPrintSetup->Header()->SetFileNameInfo(*this); 
	iPrintSetup->Header()->SetNumPagesInfo(*this); 
	iPrintSetup->Footer()->SetFileNameInfo(*this); 
	iPrintSetup->Footer()->SetNumPagesInfo(*this); 

	iPrint=CTextPageRegionPrinter::NewL(iRichText,iPrintSetup->PrinterDevice());
	iCharsPerPage=new(ELeave) CArrayFixFlat<TInt>(5);
	iPrint->SetPageList(iCharsPerPage);	
	iPrintParameters.iFirstPage=0;
	iPrintParameters.iNumCopies=1;	  
	iPrint->SetFirstPageOfDoc(0);
	iPrint->SetPageMarginsInTwips(iPrintSetup->iPageMarginsInTwips.iMargins);
	iPrint->SetPageSpecInTwips(iPrintSetup->PrinterDevice()->CurrentPageSpecInTwips());
    }

void CSimpleAppUi::TestReadOnlyL(TInt aCommand)
	{
	switch (aCommand)
		{
	case EEikCmdFileSave:
	case EEikCmdFontBold:
	case EEikCmdFontItalic:
	case EEikCmdFontUnderline:
	case EEikCmdEditCopy:
	case EEikCmdEditPaste:
	case EEikCmdFontChange:
	case EEikCmdInsertSymbol:
	case ETrtCmdInsertObject:
	case EEikCmdSearchReplace:
	case EEikCmdParaAlign:
	case EEikCmdParaBorder:
	case EEikCmdParaSpacing:
	case EEikCmdParaIndent:
	case EEikCmdParaTabs:
	case EEikCmdIrdaReceive:
	case ETrtCmdPreferences:
		if (iRichEd->IsReadOnly())
			{
			iEikonEnv->InfoMsg(R_RTEXTED_READONLY);
			CBaActiveScheduler::LeaveNoAlert();
			}
		break;
	default:
		; // do nothing
		}
	}

void CSimpleAppUi::HandleCommandL(TInt aCommand)
	{
	TestReadOnlyL(aCommand);
	switch (aCommand)
		{
	case EEikCmdExit:
		((CSimpleDocument*)iDocument)->DoSaveToCurrentFileL();
		CBaActiveScheduler::Exit();
	case EEikCmdFileNew:
		CmdFileNewL();
        break;
	case EEikCmdFileOpen:
		CmdFileOpenL();
		break;
	case EEikCmdFileSaveAs:
		CmdFileSaveAsL();
		break;
	case EEikCmdFileSave:
		CmdFileSaveL();
		break;
	case EEikCmdFileImport:
		CmdFileTextImportL();
		break;
	case EEikCmdFontBold:
		AlterButtonState(CEikGlobalTextEditor::EBold);
		break;
	case EEikCmdFontItalic:
		AlterButtonState(CEikGlobalTextEditor::EItalic);
		break;
	case EEikCmdFontUnderline:
		AlterButtonState(CEikGlobalTextEditor::EUnderline);
		break;
	case EEikCmdEditCut:
	    iRichEd->ClipboardL(CEikEdwin::ECut);
		break;
	case EEikCmdEditCopy:
	    iRichEd->ClipboardL(CEikEdwin::ECopy);
		break;
	case EEikCmdEditPaste:
	    iRichEd->ClipboardL(CEikEdwin::EPaste);
		break;
	case EEikCmdFontChange:
		iRichEd->RunFontDialogL();
		break;
	case EEikCmdInsertSymbol:
		iRichEd->RunCharMapDialogL();
		break;
	case ETrtCmdInsertObject:
		iRichEd->InsertObjectL(CEikRichTextEditor::EGlassIfPossible);
		break;
	case EEikCmdSearchFind:
		iRichEd->RunFindDialogL();
		break;
	case EEikCmdSearchFindAgain:
		iRichEd->RunFindAgainDialogL();
		break;
	case EEikCmdSearchReplace:
		iRichEd->RunReplaceDialogL();
		break;
	case EEikCmdTrtPrintPageSetup:
		RunPageSetupDialogL();
		break;
	case EEikCmdPrintSetup:
		{
		TBool cancel=EFalse;
		if (iDocumentChanged)
			cancel=RunPaginationDialogL();
		if (cancel)
			break;
		TInt pages=iCharsPerPage->Count();
		RunPrintRangeDialogL(iPrintSetup,pages);
		break;
		}
	case EEikCmdPrintPreview:
		RunPreviewDialogL();
		break;
	case EEikCmdPrintPrint:
		RunPrintDialogL();
		break;
	case EEikCmdPrintPaginate:
		RunPaginationDialogL();
		break;
	case EEikCmdParaAlign:
	case EEikCmdParaBorder:
	case EEikCmdParaSpacing:
		iRichEd->RunParaDialogsL(aCommand);
		break;
	case EEikCmdParaTabs:
	case EEikCmdParaIndent:
		{
		TInt width=iPrintSetup->PrinterDevice()->CurrentPageSpecInTwips().iPortraitPageSize.iWidth;
		if (iPrintSetup->PrinterDevice()->CurrentPageSpecInTwips().iOrientation)
			width=iPrintSetup->PrinterDevice()->CurrentPageSpecInTwips().iPortraitPageSize.iHeight;
		width-=(iPrintSetup->iPageMarginsInTwips.iMargins.iLeft+iPrintSetup->iPageMarginsInTwips.iMargins.iRight);
		if (aCommand==EEikCmdParaTabs)
			iRichEd->RunTabsDialogL(width);
		else
			iRichEd->RunIndentsDialogL(width);
		break;
		}
	case EEikCmdIrdaSend:
		CmdIrSendL();
		break;
	case EEikCmdIrdaReceive:
		CmdIrReceiveL();
		break;
	case ETrtCmdToolBand:
	case ETrtCmdToolBar:
		UpdateToolBarAndBandL(aCommand);
		break;
	case EEikCmdZoomIn:
	case EEikCmdZoomOut:
		ZoomL(aCommand);
		break;
	case ETrtCmdPreferences:
		RunSetPreferencesDialogL();
		break;
		}
	}

void CSimpleAppUi::OpenFileL(const TDesC& aFileName)
	{
	STATIC_CAST(CSimpleDocument*,iDocument)->DoSaveToCurrentFileL();
	STATIC_CAST(CSimpleDocument*,iDocument)->DoOpenFileL(aFileName);
	ResetViewL();
	}

void CSimpleAppUi::CreateFileL(const TDesC& aFileName)
	{
	STATIC_CAST(CSimpleDocument*,iDocument)->DoSaveToCurrentFileL();
	STATIC_CAST(CSimpleDocument*,iDocument)->DoNewFileL(aFileName);
	ResetViewL();
	}
	
void CSimpleAppUi::ZoomL(TInt aZoomCmd)
	{
	TInt zoomFactor=iAppZoom.ZoomFactor();
	switch(zoomFactor)
		{
	case KZoomStateOne:
		zoomFactor=(aZoomCmd==EEikCmdZoomIn)? KZoomStateTwo : KZoomStateFour;
		break;
	case KZoomStateTwo:
		zoomFactor=(aZoomCmd==EEikCmdZoomIn)? KZoomStateThree : KZoomStateOne;
		break;
	case KZoomStateThree:
		zoomFactor=(aZoomCmd==EEikCmdZoomIn)? KZoomStateFour : KZoomStateTwo;
		break;
	case KZoomStateFour:
		zoomFactor=(aZoomCmd==EEikCmdZoomIn)? KZoomStateOne : KZoomStateThree;
		break;
	default:
		zoomFactor=KZoomStateTwo;
		}
	iAppZoom.SetZoomFactor(zoomFactor);
	iRichEd->NotifyNewFormatL();
	iRichEd->UpdateScrollBarsL();
	}


void CSimpleAppUi::UpdateToolBarAndBandL(TInt aCommand)
	{
	if (aCommand==ETrtCmdToolBand)
		{
		TBool bandVisible=(iToolBand->IsVisible())? 0 :1 ;
		iToolBand->MakeVisible(bandVisible);
		}
	else if (aCommand==ETrtCmdToolBar)
		{
		TBool barVisible=(iToolBar->IsVisible())? 0 :1 ;
		iToolBar->MakeVisible(barVisible);
		}
/*
	if (iToolBand->IsVisible())
		{
		TRect rect=ClientRect();
		rect.iTl.iY=0;
		iToolBand->SetBoundingRectL(rect);	
		iToolBand->DrawNow();
		}
*/
	iRichEd->SetRectL(ClientRect());
	}
													   
void CSimpleAppUi::CreateEdwinL()
	{
	CGraphicsDevice* device=iCoeEnv->ScreenDevice();
	
	CCharFormatLayer* layer=(CONST_CAST(CCharFormatLayer*,iRichText->GlobalCharFormatLayer()));
	TCharFormat charFormat;
	TCharFormatMask charMask;
	layer->Sense(charFormat,charMask);
	charFormat.iFontSpec.iTypeface.SetAttributes(EikFontUtils::TypefaceAttributes(*device,charFormat.iFontSpec.iTypeface.iName));
	charMask.SetAttrib(EAttFontTypeface);
	layer->SetL(charFormat,charMask);
	iRichText->SetGlobalCharFormat(layer);

	iAppZoom.SetGraphicsDeviceMap(device);
	iRichEd=new(ELeave) CEikRichTextEditor();
	iRichEd->ConstructL(NULL,0,0,EEikEdwinOwnsWindow|EEikEdwinInclusiveSizeFixed|
								EEikEdwinKeepDocument|EEikEdwinUserSuppliedText|
								EEikEdwinLineCursor|EEikEdwinAlwaysShowSelection);
	iRichEd->SetObserver(this);
	iRichEd->SetZoomFactorL(&iAppZoom);
	iRichEd->SetEdwinObserver(this);
	iRichEd->CreateScrollBarFrameL();
	iRichEd->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOn);
	iRichEd->SetDefaultIconicDoorSize(TSize(150,150));
	iRichEd->SetDocumentContentL(*iRichText,CEikEdwin::EUseText);
	iRichEd->SetRectL(ClientRect());
	iRichEd->ActivateL();
	iRichEd->SetFocus(ETrue);
	}

void CSimpleAppUi::HandleControlEventL(CCoeControl* /*aControl*/,TCoeEvent aEventType)
	{
	if (aEventType==EEventStateChanged)
		{
		iDocumentChanged=ETrue;
		iDocument->SetChanged(ETrue);
		}
	}

void CSimpleAppUi::HandleEdwinEventL(CEikEdwin* aEdwin,TEdwinEvent /*aEventType*/)
	{
	if (aEdwin==iRichEd)
		UpdateToolBarButtons();
	}

void CSimpleAppUi::AlterButtonState(TInt aFontFlag)
	{
	iRichEd->BoldItalicUnderlineEventL(aFontFlag); 
	UpdateToolBarButtons();
	}

void CSimpleAppUi::UpdateToolBarButtons()
	{
	CEikButtonBase::TState buttonState;
	TCharFormat charFormat;
	TCharFormatMask charUndeterminedMask;
	const TCursorSelection selection=iRichEd->Selection();
	iRichEd->RichText()->GetCharFormat(charFormat,charUndeterminedMask,selection.LowerPos(),selection.Length());

	CEikButtonBase* bold=((CEikButtonBase*)iToolBar->ControlById(EEikCmdFontBold));
	buttonState=bold->State();

	CEikButtonBase::TState boldButtonState=((charFormat.iFontSpec.iFontStyle.StrokeWeight()==EStrokeWeightBold)? CEikButtonBase::ESet : CEikButtonBase::EClear);
	if (buttonState!=boldButtonState)
		{
		bold->SetState(boldButtonState);
		bold->DrawNow();
		}

	CEikButtonBase* italic=((CEikButtonBase*)iToolBar->ControlById(EEikCmdFontItalic));
  	buttonState=italic->State();
	CEikButtonBase::TState italicButtonState=((charFormat.iFontSpec.iFontStyle.Posture()==EPostureItalic)? CEikButtonBase::ESet : CEikButtonBase::EClear);
	if (buttonState!=italicButtonState)
		{
		italic->SetState(italicButtonState);
		italic->DrawNow();
		}
	CEikButtonBase* underline=((CEikButtonBase*)iToolBar->ControlById(EEikCmdFontUnderline));
  	buttonState=underline->State();
	CEikButtonBase::TState underlineButtonState=((charFormat.iFontPresentation.iUnderline==EUnderlineOn)? CEikButtonBase::ESet : CEikButtonBase::EClear);
	if (buttonState!=underlineButtonState)
		{
		underline->SetState(underlineButtonState);
		underline->DrawNow();
		}																	   
	}

void CSimpleAppUi::RunSetPreferencesDialogL()
	{
	TNonPrintingCharVisibility visibility=iRichEd->TextLayout()->NonPrintingCharsVisibility();
	CSetPreferencesDialog* dialog=new(ELeave) CSetPreferencesDialog(visibility);
	if (dialog->ExecuteLD(R_RTEXTED_DIALOG_SETPREFERENCES))
		{
		iRichEd->TextLayout()->SetNonPrintingCharsVisibility(visibility);
		iRichEd->NotifyNewFormatL();
		}
	}
					
void CSimpleAppUi::ResetViewL()
	{
	iRichText=STATIC_CAST(CSimpleDocument*,iDocument)->Text();
	iRichEd->SetDocumentContentL(*iRichText,CEikEdwin::EUseText);
	iAppZoom.SetZoomFactor(TZoomFactor::EZoomOneToOne);
	iDocumentChanged=ETrue;
	iRichEd->NotifyNewFormatL();
	iPrint->SetDocument(iRichText);
	iPrintParameters.iFirstPage=0;
	iPrint->SetFirstPageOfDoc(0);
	iPrintParameters.iNumCopies=1;
	}

void CSimpleAppUi::CmdFileNewL()
	{
	DoFileSaveL();
	TFileName fileName=iEikonEnv->Process()->MainDocFolder();
	CEikDialog* dialog=new(ELeave) CEikFileSaveAsDialog(&fileName,NULL,R_RTEXTED_CREATE_NEW_FILE);
	if (dialog->ExecuteLD(R_EIK_DIALOG_FILE_SAVEAS))
		{
		ConeUtils::EnsurePathExistsL(fileName);
		((CSimpleDocument*)iDocument)->DoNewFileL(fileName);
		iEikonEnv->UpdateTaskNameL();
		iRichText=((CSimpleDocument*)iDocument)->Text();
		ResetViewL();
		}
	}

void CSimpleAppUi::CmdFileOpenL()
	{
	DoFileSaveL();
	TFileName fileName=iEikonEnv->Process()->MainDocFileName();
	CEikFileOpenDialog* dialog=new(ELeave) CEikFileOpenDialog(&fileName);
	dialog->RestrictToNativeDocumentFiles();
	if (dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
		{
		((CSimpleDocument*)iDocument)->DoOpenFileL(fileName);
		iEikonEnv->UpdateTaskNameL();
		iRichText=((CSimpleDocument*)iDocument)->Text();
		ResetViewL();
		}
	}

void CSimpleAppUi::CmdFileSaveAsL()
	{
	TFileName fileName=iEikonEnv->Process()->MainDocFolder();
	CEikDialog* dialog=new(ELeave) CEikFileSaveAsDialog(&fileName,NULL,NULL);
	if (dialog->ExecuteLD(R_EIK_DIALOG_FILE_SAVEAS))
		{
		ConeUtils::EnsurePathExistsL(fileName);
		if (((CSimpleDocument*)iDocument)->FileNameExists(fileName))
			{
			CmdFileSaveL();
			return;
			}
		TEntry entry;
		if (!iEikonEnv->FsSession().Entry(fileName,entry))
			User::LeaveIfError(iEikonEnv->FsSession().Delete(fileName));
		((CSimpleDocument*)iDocument)->DoSaveToNewFileL(fileName);
		iEikonEnv->UpdateTaskNameL();
		iEikonEnv->InfoMsg(_L("File saved"));
		}
	}
  
TBool CSimpleAppUi::DoFileSaveL()
	{
	return ((CSimpleDocument*)iDocument)->DoSaveToCurrentFileL();
	}

void CSimpleAppUi::CmdFileSaveL()
	{
	if (DoFileSaveL())
		iEikonEnv->InfoMsg(_L("File saved"));
	else
		iEikonEnv->InfoMsg(_L("Nothing to save"));
	}

void CSimpleAppUi::CmdFileTextImportL()
	{
    TFileName filename=_L("Z:\\SYSTEM\\TEST\\*");
    CEikFileOpenDialog* dialog=new(ELeave) CEikFileOpenDialog(&filename,R_RTEXTED_TEXT_IMPORT_DIALOG_TITLE);
	dialog->SetShowSystem(ETrue);
    if (dialog->ExecuteLD(R_EIK_DIALOG_FILE_OPEN))
		{
		iCoeEnv->WsSession().Flush();
		iRichEd->InsertFromTextFileL(filename,CPlainText::EOrganiseByParagraph);
		iDocument->SetChanged(ETrue);
		}
	}

void CSimpleAppUi::CmdIrSendL()
	{
	iRichEd->SendDataOverIrL();
	}

void CSimpleAppUi::CmdIrReceiveL()
	{
	iRichEd->ReceiveDataOverIrL();
	}

//
// CSimpleDocument
//

CSimpleDocument* CSimpleDocument::NewL(CEikApplication& aApp)
	{
	CSimpleDocument* self=new(ELeave) CSimpleDocument(aApp);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop();
	return self;
	}

void CSimpleDocument::ConstructL()
	{
    TCharFormatMask defaultCharFormatMask;
    TCharFormat defaultCharFormat(_L("Arial"),178); // !! should seed by some other means
	defaultCharFormatMask.SetAttrib(EAttFontTypeface);
	defaultCharFormatMask.SetAttrib(EAttFontHeight);

	iParaFormatLayer=CParaFormatLayer::NewL();
	iCharFormatLayer=CCharFormatLayer::NewL(defaultCharFormat,defaultCharFormatMask);
	iRichText=CRichText::NewL(iParaFormatLayer,iCharFormatLayer,CEditableText::ESegmentedStorage,5);
	iRichText->SetPictureFactory(this,NULL);  // rich text callbacks
	}

CSimpleDocument::~CSimpleDocument()
	{
	delete iRichText;
	delete iCharFormatLayer;
	delete iParaFormatLayer;
	}				

void CSimpleDocument::NewPictureL(TPictureHeader& aHdr,const CStreamStore& aDeferredPictureStore) const
	{
	TApaPictureFactory factory(Process());
	factory.NewPictureL(aHdr,aDeferredPictureStore);
	}

const CStreamStore& CSimpleDocument::StreamStoreL(TInt /*aPos*/) const
	{
	return *EditStore();
	}

void CSimpleDocument::DoNewFileL(const TFileName& aFileName)
	{
	CFileStore* store=CDirectFileStore::ReplaceLC(Process()->FsSession(),aFileName,EFileShareExclusive);
	TUidType fileUid(KDirectFileStoreLayoutUid,KUidAppDllDoc,Application()->AppDllUid());
	store->SetTypeL(fileUid);
	CStreamDictionary* streamDic=CStreamDictionary::NewL();
	CleanupStack::PushL(streamDic);
	Process()->WriteRootStreamL(*store,*streamDic,*Application());
	store->CommitL();
	CleanupStack::PopAndDestroy(); // streamDic
	NewDocumentL();
	CleanupStack::Pop();  // store
	//
	delete((CEikProcess*)Process())->MainStore();  // remove the [original] store
	((CEikProcess*)Process())->SetMainStore(store);  // set the new file store as the main one.
	Process()->SetMainDocFileName(aFileName);
	SetChanged(EFalse);
	}
										  
void CSimpleDocument::DoOpenFileL(const TFileName& aFileName)
	{
	CFileStore* store=NULL;
	CStreamDictionary* dic=CApaProcess::ReadRootStreamLC(Process()->FsSession(),store,aFileName,EFileShareExclusive|EFileWrite);
	CleanupStack::PushL(store);
	RestoreL(*store,*dic);
	CleanupStack::Pop();  // store
	CleanupStack::PopAndDestroy();  // dictionary
	//
	delete((CEikProcess*)Process())->MainStore();  // remove the [original] store
	((CEikProcess*)Process())->SetMainStore(store);  // set the new file store as the main one.
	Process()->SetMainDocFileName(aFileName);
	SetChanged(EFalse);
	}

void CSimpleDocument::DoSaveToNewFileL(const TFileName& aNewFileName)
	{
	((CEikProcess*)Process())->SaveToDirectFileStoreL(this,&aNewFileName); // writes root stream
	SetChanged(EFalse);
	}

TBool CSimpleDocument::DoSaveToCurrentFileL()
	{
	if (!(HasChanged() || iRichText->HasChanged()))
		return EFalse;
	SaveL();
	return ETrue;
	}

void CSimpleDocument::NewDocumentL()
	{
	iRichText->Reset();
	}

void CSimpleDocument::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
	{
	CRichText* text=CRichText::NewL(iParaFormatLayer,iCharFormatLayer);
	CleanupStack::PushL(text);
	text->SetPictureFactory(this,this);  // rich text callbacks
	TStreamId id=aStreamDic.At(KUidSimpleApp);
	text->RestoreL(aStore,id);
	iEditStore=CONST_CAST(CStreamStore*,&aStore);
    CleanupStack::Pop();
	delete iRichText;
	iRichText=text;
	}

void CSimpleDocument::StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const
	{
	TStreamId id=iRichText->StoreL(aStore);
	aStreamDic.AssignL(KUidSimpleApp,id);
	}

TBool CSimpleDocument::FileNameExists(const TFileName& aFileName)const
	{
	return (aFileName==Process()->MainDocFileName());
	}

CEikAppUi* CSimpleDocument::CreateAppUiL()
	{
    return(new(ELeave) CSimpleAppUi);
	}


//
// CSimpleApplication
//

class CSimpleApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};


TUid CSimpleApplication::AppDllUid() const
	{
	return(KUidSimpleApp);
	}

CApaDocument* CSimpleApplication::CreateDocumentL()
	{
	return CSimpleDocument::NewL(*this);
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CSimpleApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}

//
//	CSetPreferencesDialog
//

CSetPreferencesDialog::CSetPreferencesDialog(TNonPrintingCharVisibility& aVisibility)
	{
	iVisibility=&aVisibility;
	iEikonEnv->SetBusy(ETrue); // just to test the busy behavior
	}

CSetPreferencesDialog::~CSetPreferencesDialog()
	{
	iEikonEnv->SetBusy(EFalse); // just to test the busy behavior
	}

void CSetPreferencesDialog::PreLayoutDynInitL()
	{
	CEikButtonBase::TState button=CEikButtonBase::EClear;
	//tabs
	button=(iVisibility->TabsVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;	
	SetCheckBoxState(ECidTab,button);
	//spaces
	button=(iVisibility->SpacesVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidSpaces,button);
	//paragraph ends
	button=(iVisibility->ParagraphDelimitersVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidParaEnds,button);
	//hyphens
	button=(iVisibility->NonBreakingHyphensVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidHyphens,button);
	//line breaks
	button=(iVisibility->LineBreaksVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidForcedLineBreaks,button);
	//page breaks
	button=(iVisibility->PageBreaksVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidPageBreaks,button);
	//nonbreaking spaces
	button=(iVisibility->NonBreakingSpacesVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidNonBreakingSpace,button);
	//soft hyphens
	button=(iVisibility->PotentialHyphensVisible())?CEikButtonBase::ESet : CEikButtonBase::EClear;		
	SetCheckBoxState(ECidNonBreakingHyphen,button);
	}

TBool CSetPreferencesDialog::OkToExitL(TInt /*aButtonId*/)
	{
	CEikButtonBase::TState button=CEikButtonBase::EClear;
	TBool visible;
	//tabs
	button=CheckBoxState(ECidTab);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetTabsVisible(visible);
	//spaces
	button=CheckBoxState(ECidSpaces);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetSpacesVisible(visible);
	//paragraph ends
	button=CheckBoxState(ECidParaEnds);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetParagraphDelimitersVisible(visible);
	//hyphens
	button=CheckBoxState(ECidHyphens);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetNonBreakingHyphensVisible(visible);
	//line breaks
	button=CheckBoxState(ECidForcedLineBreaks);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetLineBreaksVisible(visible);
	//page breaks
	button=CheckBoxState(ECidPageBreaks);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetPageBreaksVisible(visible);
	//nonbreaking spaces
	button=CheckBoxState(ECidNonBreakingSpace);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetNonBreakingSpacesVisible(visible);
	//soft hyphens
	button=CheckBoxState(ECidNonBreakingHyphen);
	visible=button? CEikButtonBase::ESet : CEikButtonBase::EClear; 
	iVisibility->SetNonBreakingHyphensVisible(visible);
	return ETrue;
	}
