uifw/AvKon/src/AknLayoutConfig.cpp
changeset 0 2f259fa3e83a
child 9 0aa5fbdfbc30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/AknLayoutConfig.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,806 @@
+/*
+* Copyright (c) 2005 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:  Layout configuration data retrieval and access
+*
+*/
+
+
+#include "AknLayoutConfig.h"
+#include <eikenv.h>
+#include <AknPanic.h>
+#include <aknpriv.rsg>
+#include <barsread.h>
+#include <barsc2.h>
+#include "AknLib.h"
+#include <AknLayoutConsts.h>
+#include "AknLayoutConfigInternal.h"
+#include <CdlTypes.h>
+#include <AknCapServerClient.h>
+
+NONSHARABLE_CLASS(CAknLayoutConfigWsiniParser) : public CBase
+	{
+public:
+	static void GetConfigL(SAknLayoutConfig& aConfig, 
+						   RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+						   RArray<SHardwareStateInfo>& aHardwareStateArray);
+
+private:
+	CAknLayoutConfigWsiniParser(SAknLayoutConfig& aConfig, 
+								RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+								RArray<SHardwareStateInfo>& aHardwareStateArray);
+	~CAknLayoutConfigWsiniParser();
+	void GetConfigL();
+	HBufC* GetWsiniLC();
+	void ParseWsiniL(const TDesC& aWsini);
+	void ParseLineL(const TText* aKwStart, const TText* aKwEnd, const TText* aLineEnd);
+
+	SHardwareStateInfo& HardwareStateL(TInt aStateNumber);
+	SAknScreenModeInfo& ScreenModeL(TInt aScreenMode);
+	TInt ParseIntL(TPtrC& aLine);
+	TInt ParseKeycodeL(TPtrC& aLine);
+	TAknPrivSoftkeyLocation ParseSoftkeyLocationL(TPtrC& aLine);
+	TInt ScreenStyleHash(TPtrC& aLine);
+
+private:
+#define WSINI_PARSE_FUNC(name) static void Call##name(CAknLayoutConfigWsiniParser* aSelf, TPtrC& aLine) { aSelf->name(aLine); } void name(TPtrC& aLine);
+	WSINI_PARSE_FUNC(HardwareStateKeycodeL)
+	WSINI_PARSE_FUNC(HardwareStateScreenModeL)
+	WSINI_PARSE_FUNC(HardwareStateAltScreenModeL)
+	WSINI_PARSE_FUNC(ScreenModeSoftkeyLocationL)
+	WSINI_PARSE_FUNC(ScreenModeStyleNameL)
+
+private:
+	struct SParseEntry
+		{
+		const TText16* iKeyword;
+		TInt iKeywordLen;
+		void (*iFunc)(CAknLayoutConfigWsiniParser* aSelf, TPtrC& aLine);
+		};
+	static const SParseEntry iParseTable[];
+
+private:
+	SAknLayoutConfig& iConfig;
+	RArray<SAknScreenModeInfo>& iScreenInfoArray;
+	RArray<SHardwareStateInfo>& iHardwareStateArray;
+	};
+
+//
+// CAknLayoutConfig::TScreenMode
+//
+EXPORT_C const TPixelsTwipsAndRotation& CAknLayoutConfig::TScreenMode::PixelsTwipsAndRotation() const
+	{
+	return iInfo.iPixelsTwipsAndRotation;
+	}
+
+CAknLayoutConfig::TScreenMode::TScreenMode(const SAknScreenModeInfo& aInfo)
+: TAknScreenMode(aInfo)
+	{
+	}
+
+EXPORT_C TAknPrivSoftkeyLocation CAknLayoutConfig::TScreenMode::SoftkeyLocation() const
+	{
+	return iInfo.iSoftkeyLocation;
+	}
+
+EXPORT_C TInt CAknLayoutConfig::TScreenMode::ScreenStyleHash() const
+	{
+	return iInfo.iScreenStyleHash;
+	}
+
+
+//
+// CAknLayoutConfig::TScreenModeArray
+//
+EXPORT_C CAknLayoutConfig::TScreenMode CAknLayoutConfig::TScreenModeArray::At(TInt aIndex) const
+	{
+	__ASSERT_ALWAYS(0 <= aIndex && aIndex < iInfo.iNumScreenModes, Panic(EAknPanicLayoutConfigBadScreenModeIndex));
+	return TScreenMode(iInfo.iScreenModes[aIndex]);
+	}
+
+EXPORT_C CAknLayoutConfig::TScreenMode CAknLayoutConfig::TScreenModeArray::Find(TInt aModeNumber) const
+	{
+	for (TInt ii=0; ii<iInfo.iNumScreenModes; ii++)
+		{
+		if (iInfo.iScreenModes[ii].iModeNumber == aModeNumber)
+			return TScreenMode(iInfo.iScreenModes[ii]);
+		}
+	return TScreenMode(iInfo.iScreenModes[0]);
+	}
+
+CAknLayoutConfig::TScreenModeArray::TScreenModeArray(const SAknLayoutConfig& aInfo)
+: TAknScreenModes(aInfo)
+	{
+	}
+
+
+//
+// CAknLayoutConfig::THardwareState
+//
+EXPORT_C TInt CAknLayoutConfig::THardwareState::StateNumber() const
+	{
+	return iInfo.iStateNum;
+	}
+
+EXPORT_C TInt CAknLayoutConfig::THardwareState::KeyCode() const
+	{
+	return iInfo.iKeyCode;
+	}
+
+EXPORT_C TInt CAknLayoutConfig::THardwareState::ScreenMode() const
+	{
+	return iInfo.iScreenMode;
+	}
+
+EXPORT_C TInt CAknLayoutConfig::THardwareState::AlternateScreenMode() const
+	{
+	return iInfo.iAltScreenMode;
+	}
+
+CAknLayoutConfig::THardwareState::THardwareState(const SHardwareStateInfo& aInfo)
+: iInfo(aInfo)
+	{
+	}
+
+
+//
+// CAknLayoutConfig::THardwareStateArray
+//
+EXPORT_C TInt CAknLayoutConfig::THardwareStateArray::Count() const
+	{
+	return iInfo.iNumHardwareStates;
+	}
+
+EXPORT_C CAknLayoutConfig::THardwareState CAknLayoutConfig::THardwareStateArray::At(TInt aIndex) const
+	{
+	__ASSERT_ALWAYS(0 <= aIndex && aIndex < iInfo.iNumHardwareStates, Panic(EAknPanicLayoutConfigBadHardwareStateIndex));
+	return THardwareState(iInfo.iHardwareStates[aIndex]);
+	}
+
+EXPORT_C CAknLayoutConfig::THardwareState CAknLayoutConfig::THardwareStateArray::Find(TInt aStateNumber) const
+	{
+	for (TInt ii=0; ii<iInfo.iNumHardwareStates; ii++)
+		{
+		if (iInfo.iHardwareStates[ii].iStateNum == aStateNumber)
+			return THardwareState(iInfo.iHardwareStates[ii]);
+		}
+	return THardwareState(iInfo.iHardwareStates[0]);
+	}
+
+CAknLayoutConfig::THardwareStateArray::THardwareStateArray(const SAknLayoutConfig& aInfo)
+: iInfo(aInfo)
+	{
+	}
+
+
+//
+// CAknLayoutConfig
+//
+EXPORT_C CAknLayoutConfig::TScreenModeArray CAknLayoutConfig::ScreenModes() const
+	{
+	return TScreenModeArray(*iData);
+	}
+
+EXPORT_C CAknLayoutConfig::THardwareStateArray CAknLayoutConfig::HardwareStates() const
+	{
+	return THardwareStateArray(*iData);
+	}
+
+CAknLayoutConfig::CAknLayoutConfig()
+	{
+	}
+
+CAknLayoutConfig::~CAknLayoutConfig()
+	{
+	delete iBuf;
+	}
+
+EXPORT_C CAknLayoutConfig* CAknLayoutConfig::NewL()
+	{
+	CAknLayoutConfig* self = new(ELeave) CAknLayoutConfig;
+	CleanupStack::PushL(self);
+
+	RAknUiServer aknUiServer;
+	CleanupClosePushL(aknUiServer);
+	User::LeaveIfError(aknUiServer.Connect());
+	HBufC8* configBuf = aknUiServer.GetPackedConfigL();
+	CleanupStack::PopAndDestroy(&aknUiServer);
+
+	// ownership of configBuf immediately transferred to self
+	self->ConstructL(configBuf);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+#define UNPACK_CHECK(b) __ASSERT_ALWAYS(b, Panic(EAknPanicLayoutConfigUnpackFail))
+
+void CAknLayoutConfig::ConstructL(HBufC8* aBuf)
+	{
+	iBuf = aBuf;
+	
+	// unpack & validate data
+	TInt size = iBuf->Size();
+	// basic structure
+	UNPACK_CHECK(size >= sizeof(SAknLayoutConfig));
+	iData = (SAknLayoutConfig*)iBuf->Ptr();
+
+	// check total size
+	UNPACK_CHECK(
+		size == 
+		(
+			sizeof(SAknLayoutConfig) + 
+			(iData->iNumScreenModes * sizeof(SAknScreenModeInfo)) +
+			(iData->iNumHardwareStates * sizeof(SHardwareStateInfo))
+		));
+
+	// check and unpack screen modes, iScreenModes is an offset before unpacking
+	UNPACK_CHECK((TUint32)iData->iScreenModes == sizeof(SAknLayoutConfig));
+	iData->iScreenModes = (SAknScreenModeInfo*)((TUint8*)iData + (TUint32)iData->iScreenModes);
+	
+	// check iNumScreenModes (we've already checked it fits in size)
+	UNPACK_CHECK(iData->iNumScreenModes >= 0);
+
+	// check and unpack hardware states, iHardwareStates is an offset before unpacking
+	UNPACK_CHECK((TUint32)iData->iHardwareStates == (sizeof(SAknLayoutConfig) + sizeof(SAknScreenModeInfo)*iData->iNumScreenModes));
+	iData->iHardwareStates = (SHardwareStateInfo*)((TUint8*)iData + (TUint32)iData->iHardwareStates);
+
+	// check iNumHardwareStates (we've already checked it fits in size)
+	UNPACK_CHECK(iData->iNumHardwareStates >= 0);
+	}
+
+HBufC8* CAknLayoutConfig::CreatePackedBufL()
+	{
+	// set up structures to collect the config info
+	SAknLayoutConfig config = { 0, NULL, 0, NULL };
+	
+	RArray<SAknScreenModeInfo> screenInfoArray;
+	CleanupClosePushL(screenInfoArray);
+	
+	RArray<SHardwareStateInfo> hardwareStateArray;
+	CleanupClosePushL(hardwareStateArray);
+
+	// get the config info
+	TRAP_IGNORE(GetConfigL(config, screenInfoArray, hardwareStateArray));
+	
+	// calculate how much space is needed for the config info
+	TInt screenModesSize = sizeof(SAknScreenModeInfo) * screenInfoArray.Count();
+	TInt hardwareStatesSize = sizeof(SHardwareStateInfo) * hardwareStateArray.Count();
+	TInt bufSize = sizeof(SAknLayoutConfig) + screenModesSize + hardwareStatesSize;
+	
+	// create the buffer space
+	HBufC8* buf = HBufC8::NewLC(bufSize);
+	TPtr8 des(buf->Des());
+	
+	// pack the info for transport
+	config.iScreenModes = (SAknScreenModeInfo*)sizeof(SAknLayoutConfig);
+	config.iHardwareStates = (SHardwareStateInfo*)(sizeof(SAknLayoutConfig) + screenModesSize);
+	
+	// put the info into the buffer
+	des.Append(TPckgC<SAknLayoutConfig>(config));
+	if (screenModesSize)
+		des.Append(TPtrC8((TText8*)&screenInfoArray[0], screenModesSize));
+	if (hardwareStatesSize)
+		des.Append(TPtrC8((TText8*)&hardwareStateArray[0], hardwareStatesSize));
+	
+	// tidy up and return
+	CleanupStack::Pop(buf);
+	CleanupStack::PopAndDestroy(2); // hardwareStateArray and screenInfoArray
+	
+	return buf;
+	}
+
+#ifdef _DEBUG
+void DebugLayoutConfigLeaves(TAny*)
+	{
+	User::Panic(_L("LayoutConfigLeave"), 0);
+	}
+#endif
+
+void CAknLayoutConfig::GetConfigL(SAknLayoutConfig& aConfig, 
+								  RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+								  RArray<SHardwareStateInfo>& aHardwareStateArray)
+	{
+#ifdef _DEBUG
+	CleanupStack::PushL(TCleanupItem(DebugLayoutConfigLeaves, 0));
+#endif
+
+	CEikonEnv* eikonEnv = CEikonEnv::Static();
+	CResourceFile* resFile = CResourceFile::NewLC(eikonEnv->FsSession(), CAknLibrary::PrivateResourceFile(), 0, 0);
+	resFile->ConfirmSignatureL();
+	
+	TAknPrivSoftkeyLocation landscapeSofkey = GetLandscapeSoftkeyLocationFromAknPrivL(resFile);
+	GetScreenModesFromWservL(aConfig, aScreenInfoArray, landscapeSofkey);
+
+	CAknLayoutConfigWsiniParser::GetConfigL(aConfig, aScreenInfoArray, aHardwareStateArray);
+	if (aHardwareStateArray.Count() == 0)
+		{
+		// got no info from wsini, so look up AknPriv
+		GetScreenMapFromAknPrivL(resFile, aScreenInfoArray, aHardwareStateArray);
+		GetKeyMapFromAknPrivL(resFile, aHardwareStateArray);
+		}
+	aConfig.iNumHardwareStates = aHardwareStateArray.Count();
+
+	CleanupStack::PopAndDestroy(resFile);
+	
+#ifdef _DEBUG
+	CleanupStack::Pop(); 	// TCleanupItem(DebugLayoutConfigLeaves, 0)
+#endif
+	}
+
+void CAknLayoutConfig::GetScreenMapFromAknPrivL(CResourceFile* aResFile,
+												RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+											    RArray<SHardwareStateInfo>& aHardwareStateArray)
+	{
+	// get state screen map
+#if defined(__WINS__)
+    TInt screenMapResource = R_AKNPRIV_HARDWARE_STATE_SCREEN_MAP_EMUL;
+#else
+    TInt screenMapResource = R_AKNPRIV_HARDWARE_STATE_SCREEN_MAP;
+#endif
+
+	// open the resource table for the hardware state <-> screen map
+	TResourceReader reader;
+	reader.SetBuffer(aResFile->AllocReadLC(screenMapResource));
+
+	// Read the entires
+	TInt numScreenModes = aScreenInfoArray.Count();
+	TInt count = reader.ReadInt16();
+	aHardwareStateArray.ReserveL(count);
+	for (TInt ii=0; ii<count; ii++)
+		{
+		SHardwareStateInfo hwInfo;
+		Mem::FillZ(&hwInfo, sizeof(hwInfo));
+		
+		hwInfo.iStateNum = reader.ReadInt16();
+		
+		TInt width = reader.ReadInt16();
+		TInt height = reader.ReadInt16();
+		TSize size(width, height);
+		CFbsBitGc::TGraphicsOrientation rotation = static_cast<CFbsBitGc::TGraphicsOrientation>(reader.ReadInt16());
+		CFbsBitGc::TGraphicsOrientation altRotation = static_cast<CFbsBitGc::TGraphicsOrientation>(reader.ReadInt16());
+		TSize altSize(height, width);
+		if ((rotation % CFbsBitGc::EGraphicsOrientationRotated180) == 
+			(altRotation % CFbsBitGc::EGraphicsOrientationRotated180))
+			altSize = size;
+		
+		// find a matching screen number
+		for (TInt jj=0; jj<numScreenModes; jj++)
+			{
+			SAknScreenModeInfo& screenMode = aScreenInfoArray[jj];
+			if (screenMode.iPixelsTwipsAndRotation.iPixelSize == size && screenMode.iPixelsTwipsAndRotation.iRotation == rotation)
+				hwInfo.iScreenMode = screenMode.iModeNumber;
+			if (screenMode.iPixelsTwipsAndRotation.iPixelSize == altSize && screenMode.iPixelsTwipsAndRotation.iRotation == altRotation)
+				hwInfo.iAltScreenMode = screenMode.iModeNumber;
+			}
+			
+		aHardwareStateArray.AppendL(hwInfo);
+		}
+
+	CleanupStack::PopAndDestroy(); // reader's HBufC
+	}
+	
+void CAknLayoutConfig::GetKeyMapFromAknPrivL(CResourceFile* aResFile,
+											 RArray<SHardwareStateInfo>& aHardwareStateArray)
+	{
+	// get the state key map
+#if defined(__WINS__)
+    TInt hwMapResource = R_AKNPRIV_HARDWARE_STATE_KEY_MAP_EMUL;
+#else
+    TInt hwMapResource = R_AKNPRIV_HARDWARE_STATE_KEY_MAP;
+#endif
+
+	TResourceReader reader;
+	reader.SetBuffer(aResFile->AllocReadLC(hwMapResource));
+
+    TInt count = reader.ReadInt16();
+    for (TInt ii=0; ii<count; ii++)
+        {
+        TInt key = (TUint32)reader.ReadUint16();
+        TInt state = reader.ReadInt16();
+		for (TInt jj=0; jj<aHardwareStateArray.Count(); jj++)
+			{
+			SHardwareStateInfo& hwInfo = aHardwareStateArray[jj];
+			if (hwInfo.iStateNum == state)
+				hwInfo.iKeyCode = key;
+			}
+        }
+
+    CleanupStack::PopAndDestroy(); // reader's HBufC
+	}
+
+TAknPrivSoftkeyLocation CAknLayoutConfig::GetLandscapeSoftkeyLocationFromAknPrivL(CResourceFile* aResFile)
+	{
+#if defined(__WINS__)
+    TInt skResource = R_AKNPRIV_SOFTKEY_LOCATION_LANDSCAPE_ROTATED90_EMUL;
+#else
+    TInt skResource = R_AKNPRIV_SOFTKEY_LOCATION_LANDSCAPE_ROTATED90;
+#endif
+
+	TResourceReader reader;
+	reader.SetBuffer(aResFile->AllocReadLC(skResource));
+	TAknPrivSoftkeyLocation softKeyLocation = (TAknPrivSoftkeyLocation)reader.ReadInt16();
+
+    CleanupStack::PopAndDestroy(); // reader's HBufC
+    
+    return softKeyLocation;
+	}
+
+TBool IsLandscape(const TSize& aSize)
+	{
+	return aSize.iWidth > aSize.iHeight;
+	}
+
+void CAknLayoutConfig::GetScreenModesFromWservL(SAknLayoutConfig& aConfig,
+												RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+												TAknPrivSoftkeyLocation aLandscapeSoftkeyLocation)
+	{
+	CEikonEnv* eikonEnv = CEikonEnv::Static();
+	CWsScreenDevice* dev = eikonEnv->ScreenDevice();
+
+	TInt numScreenModes = dev->NumScreenModes();
+	aConfig.iNumScreenModes = numScreenModes;
+	aScreenInfoArray.ReserveL(numScreenModes);
+	for (TInt ii=0; ii<numScreenModes; ii++)
+		{
+		SAknScreenModeInfo screenMode;
+		screenMode.iModeNumber = ii;
+		screenMode.iScreenStyleHash = 0;
+		dev->GetScreenModeSizeAndRotation(ii, screenMode.iPixelsTwipsAndRotation);
+		if (IsLandscape(screenMode.iPixelsTwipsAndRotation.iPixelSize))
+			{
+			screenMode.iSoftkeyLocation = aLandscapeSoftkeyLocation;
+	        // side-swapping logic moved from CAknEnv::StatusPaneResIdForCurrentLayout
+	        if (screenMode.iPixelsTwipsAndRotation.iRotation == CFbsBitGc::EGraphicsOrientationRotated270)
+	            {
+	            if (aLandscapeSoftkeyLocation == EAknPrivSoftkeyLocationRight)
+	                screenMode.iSoftkeyLocation = EAknPrivSoftkeyLocationLeft;
+	            else if (aLandscapeSoftkeyLocation == EAknPrivSoftkeyLocationLeft)
+	                screenMode.iSoftkeyLocation = EAknPrivSoftkeyLocationRight;
+	            }
+			}
+		else
+			{
+			screenMode.iSoftkeyLocation = EAknPrivSoftkeyLocationBottom;
+			}
+    	screenMode.iDisplayMode = dev->GetScreenModeDisplayMode(ii);
+		aScreenInfoArray.AppendL(screenMode);
+		}
+	}
+
+//
+// CAknLayoutConfigWsiniParser
+//
+#define WSINI_PARSE_ENTRY(keyword, func) { _S(keyword), sizeof(keyword)-1, &CAknLayoutConfigWsiniParser::Call##func }
+const CAknLayoutConfigWsiniParser::SParseEntry CAknLayoutConfigWsiniParser::iParseTable[] = 
+	{
+	WSINI_PARSE_ENTRY("S60_HWSTATE_KEYCODE", HardwareStateKeycodeL),		//S60_HWSTATE_KEYCODEn <KeyCode>
+	WSINI_PARSE_ENTRY("S60_HWSTATE_SCREENMODE", HardwareStateScreenModeL),		//S60_HWSTATE_SCREENMODEn <ScreenModeNumber>
+	WSINI_PARSE_ENTRY("S60_HWSTATE_ALT_SCREENMODE", HardwareStateAltScreenModeL),		//S60_HWSTATE_ALT_SCREENMODEn <ScreenModeNumber>
+	WSINI_PARSE_ENTRY("S60_SCR_SOFTKEY_LOCATION", ScreenModeSoftkeyLocationL),		//S60_SCR_SOFTKEY_LOCATIONn <Location>
+	WSINI_PARSE_ENTRY("S60_SCR_STYLE_NAME", ScreenModeStyleNameL),		//S60_SCR_STYLE_NAMEn <ScreenStyleName>
+	};
+
+void CAknLayoutConfigWsiniParser::GetConfigL(SAknLayoutConfig& aConfig, 
+											 RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+											 RArray<SHardwareStateInfo>& aHardwareStateArray)
+	{
+	CAknLayoutConfigWsiniParser* self = new(ELeave) CAknLayoutConfigWsiniParser(aConfig, aScreenInfoArray, aHardwareStateArray);
+	CleanupStack::PushL(self);
+	self->GetConfigL();
+	CleanupStack::PopAndDestroy();
+	}
+
+CAknLayoutConfigWsiniParser::CAknLayoutConfigWsiniParser(SAknLayoutConfig& aConfig, 
+														 RArray<SAknScreenModeInfo>& aScreenInfoArray, 
+														 RArray<SHardwareStateInfo>& aHardwareStateArray)
+: iConfig(aConfig), iScreenInfoArray(aScreenInfoArray), iHardwareStateArray(aHardwareStateArray)	
+	{
+	}
+	
+CAknLayoutConfigWsiniParser::~CAknLayoutConfigWsiniParser()
+	{
+	}
+	
+void CAknLayoutConfigWsiniParser::GetConfigL()
+	{
+	HBufC* wsini = GetWsiniLC();
+	ParseWsiniL(*wsini);
+	CleanupStack::PopAndDestroy(wsini);
+	}
+
+void CAknLayoutConfigWsiniParser::HardwareStateKeycodeL(TPtrC& aLine)
+	{
+	//S60_HWSTATE_KEYCODEn <KeyCode>
+	TInt stateNumber = ParseIntL(aLine);
+	TInt keyCode = ParseKeycodeL(aLine);
+	HardwareStateL(stateNumber).iKeyCode = keyCode;
+	}
+
+void CAknLayoutConfigWsiniParser::HardwareStateScreenModeL(TPtrC& aLine)
+	{
+	//S60_HWSTATE_SCREENMODEn <ScreenModeNumber>
+	TInt stateNumber = ParseIntL(aLine);
+	TInt modeNumber = ParseIntL(aLine) - 1;		// -1 to translate between wsini & CWsScreenDevice mode numbers
+	HardwareStateL(stateNumber).iScreenMode = modeNumber;
+	}
+
+void CAknLayoutConfigWsiniParser::HardwareStateAltScreenModeL(TPtrC& aLine)
+	{
+	//S60_HWSTATE_ALT_SCREENMODEn <ScreenModeNumber>
+	TInt stateNumber = ParseIntL(aLine);
+	TInt modeNumber = ParseIntL(aLine) - 1;		// -1 to translate between wsini & CWsScreenDevice mode numbers
+	HardwareStateL(stateNumber).iAltScreenMode = modeNumber;
+	}
+
+void CAknLayoutConfigWsiniParser::ScreenModeSoftkeyLocationL(TPtrC& aLine)
+	{
+	//S60_SCR_SOFTKEY_LOCATIONn <Location>
+	TInt modeNumber = ParseIntL(aLine) - 1;		// -1 to translate between wsini & CWsScreenDevice mode numbers
+	TAknPrivSoftkeyLocation location = ParseSoftkeyLocationL(aLine);
+	ScreenModeL(modeNumber).iSoftkeyLocation = location;
+	}
+
+void CAknLayoutConfigWsiniParser::ScreenModeStyleNameL(TPtrC& aLine)
+	{
+	//S60_SCR_STYLE_NAMEn <ScreenStyleName>
+	TInt modeNumber = ParseIntL(aLine) - 1;		// -1 to translate between wsini & CWsScreenDevice mode numbers
+	TInt hash = ScreenStyleHash(aLine);
+	ScreenModeL(modeNumber).iScreenStyleHash = hash;
+	}
+
+HBufC* CAknLayoutConfigWsiniParser::GetWsiniLC()
+	{
+	RFs& fs = CEikonEnv::Static()->FsSession();
+	_LIT(KWsini, "z:\\system\\data\\wsini.ini");
+	TEntry wsiniEntry;
+	User::LeaveIfError(fs.Entry(KWsini, wsiniEntry));
+	
+	HBufC* wsiniText = HBufC::NewLC((wsiniEntry.iSize+1)/2);	// +1 /2 to round up and convert file size to UTF-16 character size
+	TPtr wsiniPtr = wsiniText->Des();
+	TPtr8 wsiniPtr8((TText8*)wsiniPtr.Ptr(), 0, wsiniPtr.MaxLength()*2);
+
+	RFile wsiniFile;
+	User::LeaveIfError(wsiniFile.Open(fs, KWsini, EFileRead | EFileShareReadersOnly));
+	CleanupClosePushL(wsiniFile);
+	
+	User::LeaveIfError(wsiniFile.Read(wsiniPtr8, wsiniEntry.iSize));
+	wsiniPtr.SetLength(wsiniPtr8.Length()/2);
+	
+	CleanupStack::PopAndDestroy(&wsiniFile);
+	
+	return wsiniText;
+	}
+
+inline TBool IsDigit(TText aChar)
+	{
+	return ('0' <= aChar && aChar <= '9');
+	}
+	
+inline TBool IsKeywordChar(TText aChar)
+	{
+	return ('A' <= aChar && aChar <= 'Z') ||
+		   IsDigit(aChar) ||
+		   aChar == '_';
+	}
+
+inline TBool IsEndOfLine(TText aChar)
+	{
+	return aChar == '\r' || aChar == '\n';
+	}
+	
+void CAknLayoutConfigWsiniParser::ParseWsiniL(const TDesC& aWsini)
+	{
+	if (!aWsini.Length())
+		return;
+	
+	const TText* pChar = aWsini.Ptr();
+	const TText* end = pChar + aWsini.Length();
+	if (*pChar == 0xFEFF || *pChar == 0xFFFE)
+		pChar++; 	// Skip, but otherwise ignore, the UTF-16 byte ordering marker (this is how it works in wserv)
+
+	while (pChar != end)
+		{
+		// mark start of line
+		const TText* kwStart = pChar;
+		
+		// find end of keyword (including digits)
+		while (pChar != end && IsKeywordChar(*pChar))
+			++pChar;
+
+		// mark end of keyword (including digits)
+		const TText* kwEnd = pChar;
+		
+		// count back to remove digits
+		while (kwEnd != kwStart && IsDigit(*(kwEnd-1)))
+			--kwEnd;
+		
+		// find end of line
+		while (pChar != end && !IsEndOfLine(*pChar))
+			++pChar;
+		
+		// parse the line
+		ParseLineL(kwStart, kwEnd, pChar);
+
+		// find start of next line
+		while (pChar != end && IsEndOfLine(*pChar))
+			++pChar;
+		}
+	}
+
+void CAknLayoutConfigWsiniParser::ParseLineL(const TText* aKwStart, const TText* aKwEnd, const TText* aLineEnd)
+	{
+	if (aKwEnd == aKwStart)
+		return;
+	
+	TPtrC kw(aKwStart, aKwEnd-aKwStart);
+	TPtrC rest(aKwEnd, aLineEnd-aKwEnd);
+	
+	TInt targetCount = sizeof(iParseTable)/sizeof(SParseEntry);
+	for (TInt ii=0; ii<targetCount; ii++)
+		{
+		const SParseEntry& parseEntry = iParseTable[ii];
+		TPtrC header(parseEntry.iKeyword, parseEntry.iKeywordLen);
+		if (kw == header)
+			{
+			(*parseEntry.iFunc)(this, rest);
+			break;
+			}
+		}
+	}
+
+SHardwareStateInfo& CAknLayoutConfigWsiniParser::HardwareStateL(TInt aStateNumber)
+	{
+	TInt count = iHardwareStateArray.Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		if (iHardwareStateArray[ii].iStateNum == aStateNumber)
+			return iHardwareStateArray[ii];
+		}
+		
+	// not found, create a new one
+	SHardwareStateInfo newInfo = { aStateNumber, 0, 0, 0 };
+	iHardwareStateArray.AppendL(newInfo);
+	return iHardwareStateArray[count];
+	}
+
+SAknScreenModeInfo& CAknLayoutConfigWsiniParser::ScreenModeL(TInt aModeNumber)
+	{
+	TInt count = iScreenInfoArray.Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		if (iScreenInfoArray[ii].iModeNumber == aModeNumber)
+			return iScreenInfoArray[ii];
+		}
+	
+	// we failed to find the screen mode.
+	User::Leave(KErrNotFound);
+	return iScreenInfoArray[0];	// dummy return, will never get here.
+	}
+
+TInt CAknLayoutConfigWsiniParser::ParseIntL(TPtrC& aLine)
+	{
+	TLex lex(aLine);
+	lex.SkipSpace();
+	TInt num;
+	User::LeaveIfError(lex.Val(num));
+	aLine.Set(lex.Remainder());
+	return num;
+	}
+
+struct SKeyTranslation
+    {
+    const TDesC* iName;
+    TInt iBase;
+    TInt iRangeStart;
+    TInt iRangeEnd;
+    };
+
+_LIT(KKeyNameApp, "EKeyApplication");
+_LIT(KKeyNameDev, "EKeyDevice");
+
+const SKeyTranslation KKeyTranslationTable[] =
+    {
+        {
+        LIT_AS_DESC_PTR(KKeyNameApp),
+        EKeyApplication0,
+        0x0,
+        0xf
+        },
+        {
+        LIT_AS_DESC_PTR(KKeyNameDev),
+        EKeyDevice0,
+        0x0,
+        0xf
+        },
+        {
+        LIT_AS_DESC_PTR(KKeyNameApp),
+        EKeyApplication10,
+        0x10,
+        0x1f
+        },
+        {
+        LIT_AS_DESC_PTR(KKeyNameDev),
+        EKeyDevice10,
+        0x10,
+        0x1f
+        }
+    };
+
+TInt CAknLayoutConfigWsiniParser::ParseKeycodeL(TPtrC& aLine)
+	{
+	TLex lex(aLine);
+	lex.SkipSpace();
+	aLine.Set(lex.Remainder());
+	
+	TUint key;
+    // look in the translation table for a KeyNameXX match
+	TInt count = sizeof(KKeyTranslationTable)/sizeof(SKeyTranslation);
+	for (TInt ii = 0; ii < count; ii++)
+	    {
+	    const SKeyTranslation& trans = KKeyTranslationTable[ii];
+	    const TDesC& name = *trans.iName;
+	    TInt len = name.Length();
+	    if (aLine.Length() > len && aLine.Left(len) == name)
+	        {
+	        lex.Assign(aLine.Mid(len));
+    	    if (lex.Val(key, EHex) == KErrNone && trans.iRangeStart <= key && key <= trans.iRangeEnd)
+    	        {
+            	aLine.Set(lex.Remainder());
+    	        return trans.iBase + key - trans.iRangeStart;
+    	        }
+	        }
+	    }
+	
+	if (aLine.Length())
+		{
+		// use the character
+		key = aLine[0];
+		aLine.Set(aLine.Mid(1));
+		return key;
+		}
+
+	User::Leave(KErrCorrupt);
+	return 0;
+	}
+
+TAknPrivSoftkeyLocation CAknLayoutConfigWsiniParser::ParseSoftkeyLocationL(TPtrC& aLine)
+	{
+	TAknPrivSoftkeyLocation location = EAknPrivSoftkeyLocationBottom;
+	TLex lex(aLine);
+	lex.SkipSpace();
+	TPtrC token = lex.NextToken();
+	if (token == _L("right"))
+		location = EAknPrivSoftkeyLocationRight;
+	else if (token == _L("left"))
+		location = EAknPrivSoftkeyLocationLeft;
+	aLine.Set(lex.Remainder());
+	return location;
+	}
+
+TInt CAknLayoutConfigWsiniParser::ScreenStyleHash(TPtrC& aLine)
+	{
+	TInt hash = 0;
+	TLex lex(aLine);
+	TPtrC name = lex.NextToken();
+	const TText* pChar = name.Ptr();
+	const TText* end = pChar + name.Length();
+	
+	// calculate the hash
+	for (; pChar != end; ++pChar)
+		{
+		hash *= KAknLayoutScreenStyleNameHashMult;
+		hash += *pChar;
+		}
+
+	return hash;
+	}