// EIKDEBUG.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikenv.h>
#include <eikappui.h>
#include <eikmfne.h>
#include <eikdebug.h>
#include <eikpriv.hrh>
#include <eikon.rsg>

#include <s32file.h>

// The dial dialog preferences UID incremented by 1
const TUid KEikDebugPreferencesUID={268435815};

//
//	class CEikDebugPreferences
//

EXPORT_C CEikDebugPreferences* CEikDebugPreferences::NewLC()
	{
	CEikDebugPreferences* self=new(ELeave) CEikDebugPreferences();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CEikDebugPreferences::CEikDebugPreferences()
:	iDebugKeysOn(EFalse), iVersion(0)
	{
	}

EXPORT_C CEikDebugPreferences::~CEikDebugPreferences()
	{
	}

void CEikDebugPreferences::ConstructL()
	{
	}

EXPORT_C void CEikDebugPreferences::RestoreL()
	{
	CDictionaryStore* iniFile=CDictionaryFileStore::SystemLC(CEikonEnv::Static()->FsSession());
	if (iniFile->IsPresentL(KEikDebugPreferencesUID))
		{
		RDictionaryReadStream stream;
		stream.OpenLC(*iniFile,KEikDebugPreferencesUID);
		InternalizeL(stream);
		CleanupStack::PopAndDestroy(); // stream
		}
	CleanupStack::PopAndDestroy(); //iniFile
	}

EXPORT_C void CEikDebugPreferences::StoreL()
	{
	CDictionaryStore* iniFile=CDictionaryFileStore::SystemLC(CEikonEnv::Static()->FsSession());
	
	RDictionaryWriteStream stream;
	stream.AssignLC(*iniFile,KEikDebugPreferencesUID);
	ExternalizeL(stream);
	stream.CommitL();
	CleanupStack::PopAndDestroy(); // stream

	iniFile->CommitL();
	CleanupStack::PopAndDestroy(); //iniFile
	}

void CEikDebugPreferences::ExternalizeL(RWriteStream& aStream) const
	{
	aStream.WriteInt16L(CEikonEnv::Version().iBuild);
	aStream.WriteInt8L((TInt)iDebugKeysOn);
	}

void CEikDebugPreferences::InternalizeL(RReadStream& aStream)
	{
	iVersion = aStream.ReadInt16L();
	iDebugKeysOn = (TBool)aStream.ReadInt8L();
	}

//
//	class CEikDebugWin
//

class CEikDebugWin : public CCoeControl
    {
public:
    void ConstructL();
private:
	void Draw(const TRect& aRect) const;
    };

void CEikDebugWin::Draw(const TRect& aRect) const
	{
	CGraphicsContext& gc=SystemGc();
	gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	SystemGc().DrawRect(aRect);
	}
	
void CEikDebugWin::ConstructL()
    {
    CreateWindowL();
    SetExtentToWholeScreenL();
    Window().SetBackgroundColor(KRgbGray);
    ActivateL();
    DrawNow();
    iCoeEnv->Flush(300000);
    }

//
// class CEikHeapFailDialog
//

class CEikHeapFailDialog : public CEikDialog
	{
public:
	enum TFailType {EHeapFailOff,EFailRandom,EFailDeterministic,EFailFileError};
	inline CEikHeapFailDialog(TInt* aHeapFailRate,TInt* aFailType,TInt* aWservHeapFailRate,TInt* aWservFailType,TInt* aFileFailRate,TInt* aFileFailChbx) :iHeapFailRate(aHeapFailRate),iFailType(aFailType),iWservHeapFailRate(aWservHeapFailRate),iWservFailType(aWservFailType),iFileFailRate(aFileFailRate),iFileFailChbx(aFileFailChbx) {}
private: // from CEikDialog
	void PreLayoutDynInitL();
	TBool OkToExitL(TInt aKeyCode);
private:
	TInt* iHeapFailRate;
	TInt* iFailType;
	TInt* iWservHeapFailRate;
	TInt* iWservFailType;
	TInt* iFileFailRate;
	TInt* iFileFailChbx;
	};

void CEikHeapFailDialog::PreLayoutDynInitL()
	{
	SetNumberEditorValue(EEikCidHeapFailRate,*iHeapFailRate);
	SetNumberEditorValue(EEikCidWservHeapFailRate,*iWservHeapFailRate);
	SetNumberEditorValue(EEikCidFileFailRate,*iFileFailRate);
	CEikButtonBase::TState checkBoxState=CEikButtonBase::EClear;
	if (*iFileFailChbx)
		checkBoxState=CEikButtonBase::ESet;
	SetCheckBoxState(EEikCidFileFailChbx,checkBoxState);

	TInt butId=0;
	switch (*iFailType)
		{
		case EHeapFailOff:			butId = EEikCidHeapFailOff; break;
		case EFailRandom:			butId = EEikCidHeapFailTypeBackRandom; break;
		case EFailDeterministic:	butId = EEikCidHeapFailTypeBackDeterministic; break;
		}
	SetHorOptionButListCurrentSet(EEikCidHeapFailTypeBack,butId);
	switch (*iWservFailType)
		{
		case EHeapFailOff:			butId = EEikCidWservHeapFailOff; break;
		case EFailRandom:			butId = EEikCidWservHeapFailTypeBackRandom; break;
		case EFailDeterministic:	butId = EEikCidWservHeapFailTypeBackDeterministic; break;
		}
	SetHorOptionButListCurrentSet(EEikCidWservHeapFailTypeBack,butId);
	}

TBool CEikHeapFailDialog::OkToExitL(TInt)
	{
	*iHeapFailRate=NumberEditorValue(EEikCidHeapFailRate);
	*iWservHeapFailRate=NumberEditorValue(EEikCidWservHeapFailRate);
	*iFileFailRate=NumberEditorValue(EEikCidFileFailRate);
	TInt butId = HorOptionButListCurrentSet(EEikCidHeapFailTypeBack);
	TInt wservButId = HorOptionButListCurrentSet(EEikCidWservHeapFailTypeBack);
	TBuf<84> msg;
	RWsSession& wsSession=iEikonEnv->WsSession();
	switch (butId)
		{
		case EEikCidHeapFailOff:
			{
			msg.Append(_L("Heap failure off "));
			*iFailType=EHeapFailOff;
			__UHEAP_SETFAIL(RHeap::ENone,*iHeapFailRate);
			break;
			} 
		case EEikCidHeapFailTypeBackRandom:
			{
			msg.Append(_L("Setting random heap failure "));
			*iFailType=EFailRandom;
			__UHEAP_SETFAIL(RHeap::ERandom,*iHeapFailRate);
			break;
			} 
		case EEikCidHeapFailTypeBackDeterministic:
			{
			msg.Append(_L("Setting deterministic heap failure "));
			*iFailType=EFailDeterministic;
			__UHEAP_SETFAIL(RHeap::EDeterministic,*iHeapFailRate);
			break;
			}
		default: return EFalse;
		}
	switch (wservButId)
		{
		case EEikCidWservHeapFailOff:
			{
			*iWservFailType=EHeapFailOff;
			wsSession.HeapSetFail(RHeap::ENone,*iHeapFailRate);
			break;
			} 
		case EEikCidWservHeapFailTypeBackRandom:
			{
			*iWservFailType=EFailRandom;
			wsSession.HeapSetFail(RHeap::ERandom,*iHeapFailRate);
			break;
			} 
		case EEikCidWservHeapFailTypeBackDeterministic:
			{
			*iWservFailType=EFailDeterministic;
			wsSession.HeapSetFail(RHeap::EDeterministic,*iHeapFailRate);
			break;
			}
		default: return EFalse;
		}
	*iFileFailChbx=EFalse;
	CEikButtonBase::TState checkBoxState = CheckBoxState(EEikCidFileFailChbx);
	if (checkBoxState == CEikButtonBase::ESet)
		{
		msg.Append(_L("and file failure on"));
		*iFileFailChbx=ETrue;
#if defined(_DEBUG)
		TInt KFileFailError=-9999;
		iCoeEnv->FsSession().SetErrorCondition(KFileFailError,*iFileFailRate);
#endif
		}
	else
		{
		msg.Append(_L("and file failure off"));
#if defined(_DEBUG)
		TInt KFsNoErrRate=1000000;
		iCoeEnv->FsSession().SetErrorCondition(KErrNone,KFsNoErrRate);
#endif
		}
	iEikonEnv->InfoMsg(msg);
	return ETrue;
	}

//
// class CEikDebugKeys
//

void CEikDebugKeys::ConstructL()
    {
    CCoeAppUi* appUi=iEikonEnv->EikAppUi();
    appUi->AddToStackL(this,ECoeStackPriorityEnvironmentFilter,ECoeStackFlagRefusesFocus|ECoeStackFlagOwnershipTransfered|ECoeStackFlagSharable);
	iHeapFailRate=500;
	iFailType=CEikHeapFailDialog::EHeapFailOff;
	iWservHeapFailRate=500;
	iWservFailType=CEikHeapFailDialog::EHeapFailOff;
	iFileFailRate=5;
	iFileFailChbx=EFalse;
    }

TKeyResponse CEikDebugKeys::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    if (aType!=EEventKey || ((aKeyEvent.iModifiers&EAllStdModifiers)!=EAllStdModifiers))
        return(EKeyWasNotConsumed);
	TInt code=aKeyEvent.iCode;
    if (code<CTRL('a') || code>CTRL('z'))
        return(EKeyWasNotConsumed);
    switch (code)
        {
    case CTRL('a'):
        iEikonEnv->AllocInfoMsg();
        break;
	case CTRL('b'):
        iEikonEnv->FservAllocInfoMsg();
		break;
	case CTRL('c'):
        iEikonEnv->WservAllocInfoMsg();
		break;
	case CTRL('f'):
		iEikonEnv->InfoMsg(_L("Enabling Wserv auto-flush"));
		iEikonEnv->WsSession().SetAutoFlush(ETrue);
		break;
	case CTRL('g'):
		iEikonEnv->WsSession().SetAutoFlush(EFalse);
		iEikonEnv->InfoMsg(_L("Wserv auto-flush disabled"));
		break;
	case CTRL('m'):
		{
		CEikDialog* dialog=new(ELeave) CEikDialog;
		dialog->ExecuteLD(R_EIK_DIALOG_MOVEME);
		//iEikonEnv->InfoWinL(_L("Move me!"),TPtrC());
		break;
		}
	case CTRL('p'):
		__UHEAP_RESET;
		(new(ELeave) CEikHeapFailDialog(&iHeapFailRate,&iFailType,&iWservHeapFailRate,&iWservFailType,&iFileFailRate,&iFileFailChbx))->ExecuteLD(R_EIK_DIALOG_HEAP_FAIL);
		break;
	case CTRL('q'):
		__UHEAP_RESET;
		iEikonEnv->InfoMsg(_L("Heap failure mode reset"));
		break;
	case CTRL('r'):
		{
		CEikDebugWin* win=new(ELeave) CEikDebugWin;
		CleanupStack::PushL(win);
		win->ConstructL();
		CleanupStack::PopAndDestroy();
		break;
		}
	case CTRL('t'):
		iEikonEnv->DisplayTaskList();
		break;
	case CTRL('v'):
		if (iVerbose)
			{
			iVerbose=EFalse;
			iEikonEnv->InfoMsg(_L("Verbose info messages disabled"));
			}
		else
			{
			iVerbose=ETrue;
			iEikonEnv->InfoMsg(_L("Verbose info messages enabled"));
			}
		iEikonEnv->SetVerboseInfoReporting(iVerbose);
		break;
	case CTRL('y'):
		{
		iEikonEnv->InfoMsg(_L("Mounting system as X:"));
		RFs& fs=iEikonEnv->FsSession();
		User::LeaveIfError(fs.AddFileSystem(_L("EFAT")));
		fs.MountFileSystem(_L("Fat"),EDriveX);
		RFormat format;
		TInt count;
		User::LeaveIfError(format.Open(fs,_L("X:"),EHighDensity,count));
		while (count)
			format.Next(count);
		format.Close();
		}
		break;
	case CTRL('z'):
		{
		RWsSession& wS=iEikonEnv->WsSession();
		TInt wgId=wS.GetFocusWindowGroup();
		TWsEvent wsEvent;
		TKeyEvent event;
		iEikonEnv->InfoMsg(_L("Sending ASCII chars A-J as repeated keypresses to app"));
		for (TInt i=65; i<75; i++)
			{
			event.iCode=i;
			*(wsEvent.Key())=event;
			wsEvent.SetType(EEventKey);
			wsEvent.SetTimeNow();
			wS.SendEventToWindowGroup(wgId, wsEvent);
			}
		}
		break;
      	}
    return(EKeyWasConsumed);
    }
