// APGWGNAM.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "apgwgnam.h"
#include "apgstd.h"
#include "apgtask.h"

const TInt KUidBufLength=8;
const TInt KMinWindowGroupNameLength=5/*delimiters+status)*/+KUidBufLength;
const TInt KMaxWindowGroupNameLength=KMinWindowGroupNameLength+2*KMaxFileName;
const TInt KMaxSearchStringLength=KMaxFileName+6/* 3*delim+3*wild */;
typedef TBuf<KMaxSearchStringLength> TApaSearchString;

EXPORT_C CApaWindowGroupName::~CApaWindowGroupName()
	//
	// d'tor
	//
	{	   
	delete iBuf;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::New(const RWsSession& aWsSession, HBufC* aWgName)
	//
	// non leaving static initializer from full name - takes ownership
	// ONLY TO BE USED WITH A VALID (i.e existing) WINDOW GROUP NAME
	//
	{
	CApaWindowGroupName* This=NULL;
	if (aWgName)
		{
		This=new CApaWindowGroupName(aWsSession);
		if (This)
			{
			This->iBuf=aWgName;
			This->GetStatusFromName();
			}
		}
	else
		Panic(EPanicNullWindowGroupName);
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewL(const RWsSession& aWsSession)
	//
	// static initializer for blank window group name
	//
	{
	CApaWindowGroupName* This=NewLC(aWsSession);
	CleanupStack::Pop();
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewL(const RWsSession& aWsSession, TInt aWgId)
	//
	// static initializer for existing window group name given by aWgId
	//
	{
	CApaWindowGroupName* This=NewLC(aWsSession, aWgId);
	CleanupStack::Pop();
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewL(const RWsSession& aWsSession, const TDesC& aWgName)
	//
	// static initializer from full name
	// ONLY TO BE USED WITH A VALID (i.e existing) WINDOW GROUP NAME
	//
	{
	CApaWindowGroupName* This=NewLC(aWsSession, aWgName);
	CleanupStack::Pop();
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewLC(const RWsSession& aWsSession)
	//
	// static initializer for blank window group name
	//
	{
	CApaWindowGroupName* This=new(ELeave) CApaWindowGroupName(aWsSession);
	CleanupStack::PushL(This);
	This->DefaultConstructL();
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewLC(const RWsSession& aWsSession, TInt aWgId)
	//
	// static initializer for existing window group name given by aWgId
	//
	{
	CApaWindowGroupName* This=new(ELeave) CApaWindowGroupName(aWsSession);
	CleanupStack::PushL(This);
	This->ConstructFromWgIdL(aWgId);
	return This;
	}

EXPORT_C CApaWindowGroupName* CApaWindowGroupName::NewLC(const RWsSession& aWsSession, const TDesC& aWgName)
	//
	// static initializer from full name
	// ONLY TO BE USED WITH A VALID (i.e existing) WINDOW GROUP NAME
	//
	{
	CApaWindowGroupName* This=new(ELeave) CApaWindowGroupName(aWsSession);
	CleanupStack::PushL(This);
	This->iBuf=aWgName.AllocL();
	This->GetStatusFromName();
	return This;
	}

CApaWindowGroupName::CApaWindowGroupName(const RWsSession& aWsSession) 
	: iWsSession(aWsSession)
	//
	// private c'tor 
	//
	{
	}


void CApaWindowGroupName::DefaultConstructL()
	{
	iStatus=0;
	TBuf<ELast+KUidBufLength> defaultWgName;
	for (TInt i=EEndStatus; i<=ELast; i++)
		{
		defaultWgName.Append(0);
		if (i==EEndStatus)
			{
			TBuf<KUidBufLength> uidBuf;
			uidBuf.SetLength(KUidBufLength);
			uidBuf.Fill('0');
			defaultWgName.Append(uidBuf);
			}
		}
	iBuf=HBufC::NewL(KMinWindowGroupNameLength);
	TPtr des=iBuf->Des();
	des.Format(_L("%02x%S"), iStatus, &defaultWgName);
	}	

EXPORT_C void CApaWindowGroupName::ConstructFromWgIdL(TInt aWgId)
	//
	// Allocate and format iBuf according to existing name given by aWgId
	//
	{
	delete iBuf;
	iBuf=NULL;
	if (aWgId>0)
		{
		TBuf<KMaxWindowGroupNameLength> name;
		((RWsSession&)iWsSession).GetWindowGroupNameFromIdentifier(aWgId, name);
		if (name.Length()==0) // name not set
			DefaultConstructL();
		else
			{
			iBuf=name.AllocL();
			GetStatusFromName();
			}
		}
	else
		DefaultConstructL();
	}

EXPORT_C void CApaWindowGroupName::SetWindowGroupNameL(const TDesC& aWgName)
	//
	// Set a new name
	//
	{
	delete iBuf;
	iBuf=NULL;
	iBuf=aWgName.AllocL();
	GetStatusFromName();
	}

EXPORT_C void CApaWindowGroupName::SetWindowGroupName(HBufC* aWgName)
	//
	// Set a new name - takes ownership
	//
	{
	if (aWgName)
		{
		delete iBuf;
		iBuf=aWgName;
		GetStatusFromName();
		}
	else
		Panic(EPanicNullWindowGroupName);
	}

EXPORT_C void CApaWindowGroupName::FindByAppUid(TUid aAppUid, RWsSession& aWsSession, TInt& aPrevWgId)
	//
	// static - Searches for running apps matching aAppUid and updates aPrevWgId
	//
	{
	TBuf<20> match=_L("*");	// status
	match.Append(0);
	TBuf<8> uidBuf;
	uidBuf.Num(aAppUid.iUid, EHex);
	match.Append(uidBuf);  // uid
	match.Append(0);
	match.Append('*');	// caption
	match.Append(0);	
	match.Append('*');	// docname
	aPrevWgId=aWsSession.FindWindowGroupIdentifier(aPrevWgId, match, 0);
	}

EXPORT_C void CApaWindowGroupName::FindByCaption(const TDesC& aCaption, RWsSession& aWsSession, TInt& aPrevWgId)
	//
	// static - Searches for running apps matching aCaption and updates aPrevWgId
	//
	{
	TApaSearchString match=_L("*"); // status
	match.Append(0);
	match.Append('*'); // uid
	match.Append(0);
	match.Append(aCaption);	 // caption
	match.Append(0);
	match.Append('*'); //doc name
	aPrevWgId=aWsSession.FindWindowGroupIdentifier(aPrevWgId, match, 0);
	}

EXPORT_C void CApaWindowGroupName::FindByDocName(const TDesC& aDocName, RWsSession& aWsSession, TInt& aPrevWgId)
	{
	//
	// static - Searches for running apps matching aDocName and updates aPrevWgId
	//
	TApaSearchString match=_L("*"); // status
	match.Append(0);
	match.Append('*'); // uid
	match.Append(0);
	match.Append('*'); // caption
	match.Append(0);
	match.Append(aDocName);
	aPrevWgId=aWsSession.FindWindowGroupIdentifier(aPrevWgId, match, 0);
	}

EXPORT_C void CApaWindowGroupName::SetBusy(TBool aBusy)
	{
	iStatus&=(~EBusy);
	if (aBusy)
		iStatus|=EBusy;
	WriteStatusToName();
	}

EXPORT_C TBool CApaWindowGroupName::IsBusy() const
	{
	return iStatus&EBusy;
	}

EXPORT_C void CApaWindowGroupName::SetSystem(TBool aSystem)
	{
	iStatus&=(~ESystem);
	if (aSystem)
		iStatus|=ESystem;
	WriteStatusToName();
	}

EXPORT_C TBool CApaWindowGroupName::IsSystem() const
	{
	return iStatus&ESystem;
	}

EXPORT_C void CApaWindowGroupName::SetDocNameIsAFile(TBool aDocNameIsAFile)
	{
	iStatus&=(~EDocNameNotAFile);
	if (!aDocNameIsAFile)
		iStatus|=EDocNameNotAFile;
	WriteStatusToName();
	}

EXPORT_C TBool CApaWindowGroupName::DocNameIsAFile() const
	{
	return !(iStatus&EDocNameNotAFile);
	}

EXPORT_C void CApaWindowGroupName::SetRespondsToShutdownEvent(TBool aRespondsToShutdownEvent)
	{
	iStatus&=(~EDoesNotRespondToShutdownEvent);
	if (!aRespondsToShutdownEvent)
		iStatus|=EDoesNotRespondToShutdownEvent;
	WriteStatusToName();
	}

EXPORT_C TBool CApaWindowGroupName::RespondsToShutdownEvent() const
	{
	return !(iStatus&EDoesNotRespondToShutdownEvent);
	}

EXPORT_C void CApaWindowGroupName::SetRespondsToSwitchFilesEvent(TBool aRespondsToSwitchFilesEvent)
	{
	iStatus&=(~EDoesNotRespondToSwitchFilesEvent);
	if (!aRespondsToSwitchFilesEvent)
		iStatus|=EDoesNotRespondToSwitchFilesEvent;
	WriteStatusToName();
	}

EXPORT_C TBool CApaWindowGroupName::RespondsToSwitchFilesEvent() const
	{
	return !(iStatus&EDoesNotRespondToSwitchFilesEvent);
	}

EXPORT_C void CApaWindowGroupName::SetAppUid(TUid aAppUid)
	{
	TInt start=FindDelimiter(EEndStatus);
	if (start>0)
		{
		start++;
		TInt end=FindDelimiter(EEndUid);
		if (end>0)
			{
			TBuf<KUidBufLength> uidBuf;
			uidBuf.Num(aAppUid.iUid, EHex);
			TPtr des=iBuf->Des();
			des.Replace(start, end-start, uidBuf);
			}
		}
	}

EXPORT_C TUid CApaWindowGroupName::AppUid() const
	{
	TUid uid=TUid::Null();
	TUint32 val=0;
	TInt start=FindDelimiter(EEndStatus);
	if (start>0)
		{
		start++;
		TInt end=FindDelimiter(EEndUid);
		if (end>0)
			{
			TBuf<KUidBufLength> uidBuf=iBuf->Mid(start, end-start);
			TLex lex(uidBuf);
			lex.Val(val, EHex);	// !! error code
			}
		}
	uid.iUid=val;
	return uid;
	}

EXPORT_C void CApaWindowGroupName::SetCaptionL(const TDesC& aCaption)
	{	 
	TInt start=FindDelimiter(EEndUid);
	if (start>0)
		{
		start++;
		TInt end=FindDelimiter(EEndCaption);
		if (end>0)
			{
			TInt length=end-start;
			ReAllocIfNecessaryL(aCaption.Length()-length);
			TPtr des=iBuf->Des();
			des.Replace(start, length, aCaption);
			}
		}
	}

EXPORT_C TPtrC CApaWindowGroupName::Caption() const
	{
	TInt start=FindDelimiter(EEndUid);
	if (start>0)
		{
		start++;
		TInt end=FindDelimiter(EEndCaption);
		if (end>0)
			return iBuf->Mid(start, end-start);
		}
	return TPtrC(); // error
	}

EXPORT_C void CApaWindowGroupName::SetDocNameL(const TDesC& aDocName)
	{
	TInt start=FindDelimiter(EEndCaption);
	if (start>0)
		{
		start++;
		TInt end=iBuf->Length();
		if (end>0)
			{
			TInt length=end-start;
			ReAllocIfNecessaryL(aDocName.Length()-length);
			TPtr des=iBuf->Des();
			des.Replace(start, length, aDocName);
			}
		}
	}

EXPORT_C TPtrC CApaWindowGroupName::DocName() const
	{
	TInt start=FindDelimiter(EEndCaption);
	if (start>0)
		{
		start++;
		TInt end=iBuf->Length();
		if (end>0)
			return iBuf->Mid(start, end-start);
		}
	return TPtrC(); // error
	}

EXPORT_C TInt CApaWindowGroupName::SetWindowGroupName(RWindowGroup& aGroupWin) const
	//
	// Set aGroupWin's name to the current name in iBuf (returns WServ error code)
	//
	{
	return aGroupWin.SetName(*iBuf);
	}

EXPORT_C TPtrC CApaWindowGroupName::WindowGroupName() const
	{
	return *iBuf;
	}

void CApaWindowGroupName::WriteStatusToName()
	//
	// replaces two digit hex number at front of iBuf by iStatus 
	//
	{
	TBuf<2> status;
	status.Format(_L("%02x"), iStatus);
	TPtr des=iBuf->Des();
	des.Replace(0,2,status);
	}

void CApaWindowGroupName::GetStatusFromName()
	//
	// Extracts the two digit hex number at front of iBuf into iStatus 
	//
	{
	TBuf<2> status=iBuf->Left(2);
	TLex lex(status);
	lex.Val(iStatus, EHex);
	}

TInt CApaWindowGroupName::FindDelimiter(TApaDelimiter aDelim) const
	//
	// returns the pos of aDelim or KErrNotFound
	//
	{
	TInt pos=-1;
	TInt length=iBuf->Length();
	for (TInt i=0; i<aDelim; i++)
		{
		TInt nextPos=(iBuf->Right(length-pos-1)).Locate(0);
		if (nextPos<0)
			return KErrNotFound;
		pos=pos+nextPos+1;
		}
	return pos;
	}

void CApaWindowGroupName::ReAllocIfNecessaryL(TInt aExtraLengthReqd)
	//
	// Reallocates iBuf if currentLength+extraLength<totalLength
	//
	{
	TInt existing=iBuf->Length();
	TInt total=existing+aExtraLengthReqd;
	if (total>iBuf->Des().MaxLength())
		iBuf=iBuf->ReAllocL(total);
	}

