os/boardsupport/emulator/emulatorbsp/specific/gui.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // wins\specific\gui.cpp
    15 // 
    16 //
    17 #define WINVER 0x0500
    18 
    19 #include "gui.h"
    20 #include <emulator.h>
    21 #include <assp.h>
    22 #include <kernel/kern_priv.h>
    23 #include <kernel/kpower.h>
    24 #include "variant.h"
    25 #include "resource.h"
    26 #include "winsgui.h"
    27 #include "display_chan.h"
    28 #include "pixelformats.h"
    29 #include "multitouch.h"
    30 
    31 #include "monitors.h"
    32 
    33 //Define these so that emulator generates varying values for gce stride and offset.
    34 //By default in emulator, stride is exactly right for display resolution and offset is zero
    35 //Setting these will identify code which incorrectly calculates these factors instead of requesting them
    36 //Note that multiples of 4 bytes are preferred for various reasons.
    37 //[3/5/07 The Secure presentation burffer ignores stride extra because it uses a windows bitmap header to render.]
    38 // #define TEST_GCE_VARIABLE_STRIDE_EXTRA	16		 	//This constant is added to each mode's scanline length in bytes. It may cause a break if enabled because the iDisplayBufferOffset is not being set
    39 // #define TEST_GCE_VARIABLE_START_EXTRA	16			//A multiple of this is added to each mode's start address in bytes
    40 // #define ASSYMETRIC_SQUARE_STRIDE						//If this is defined and the width==height the the stride will not be the same!
    41 
    42 enum  
    43 	{
    44 		KMaskModeNum=0x0FFFFFFF,
    45 		KMaskModeFlag8=0x80000000,
    46 		KMaskModeFlag4=0x40000000,
    47 		KMaskModeFlag2=0x20000000,
    48 		KMaskModeFlag1=0x10000000,
    49 		
    50 		KModeFlagFlipped=KMaskModeFlag8,
    51 		
    52 	};
    53 enum  
    54 	{
    55 		KMaskScreenNum=0x0FFF,
    56 		KMaskScreenFlag8=0x8000,
    57 		KMaskScreenFlag4=0x4000,
    58 		KMaskScreenFlag2=0x2000,
    59 		KMaskScreenFlag1=0x1000,
    60 		
    61 		KScreenFlagSecure=KMaskScreenFlag8,
    62 		
    63 	};
    64 const TInt KMaxDisplayColors=16777216;
    65 const TInt KMaxDisplayContrast=1;
    66 
    67 static TEmulatorFlip* CurrentFlipState=NULL;
    68 static TInt CurrentConfiguration = 0;
    69 static TInt SavedFlipMessage = 0;
    70 
    71 DWinsUi *systemIni=NULL;
    72 DMasterIni* masterIni;
    73 
    74 DMultiTouch* TheMultiTouch;
    75 static HWND TheControlWin;
    76 static HWND* TheChildWin=NULL;
    77 static HWND* TheWin=NULL;
    78 static HWND hwndStatus; // To display the X,Y,Z information of each mouse
    79 static TInt VirtualKeyPressed = EStdKeyNull;
    80 static HBITMAP* TheScreenBitmap=NULL;
    81 static TUint LedMask;
    82 static TBool WsSwitchOnScreen;
    83 
    84 const char * DefaultWindowTitle = "Symbian OS Emulator";
    85 
    86 #ifdef __VC32__
    87 
    88 #ifdef _DEBUG
    89 const char * VersionText = " - wins udeb";
    90 #else
    91 const char * VersionText = " - wins urel";
    92 #endif
    93 
    94 #else
    95 #ifdef __CW32__
    96 
    97 #ifdef _DEBUG
    98 const char * VersionText = " - winscw udeb";
    99 #else
   100 const char * VersionText = " - winscw urel";
   101 #endif
   102 
   103 #else
   104 //not winscw or wins!
   105 #ifdef _DEBUG
   106 const char * VersionText = " - unknown udeb";
   107 #else
   108 const char * VersionText = " - unknown urel");
   109 #endif
   110 
   111 #endif
   112 #endif
   113 
   114 void Inactive();
   115 void Active();
   116 void DrawLeds();
   117 void UpdateModifiers(); 
   118 TInt DisplayHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2);
   119 LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd);
   120 
   121 GLDEF_C const char* skipws(const char* aPtr)
   122 	{
   123 	while (isspace(*aPtr))
   124 		++aPtr;
   125 	return aPtr;
   126 	}
   127 
   128 GLDEF_C const char* skiptok(const char* aPtr)
   129 	{
   130 	while (isalnum(*aPtr))
   131 		++aPtr;
   132 	return aPtr;
   133 	}
   134 
   135 GLDEF_C TInt CompareI(const TDesC8& aLhs, const TDesC8& aRhs)
   136 //
   137 // Case insensitive comparison of descriptors
   138 // (TDesC::CompareF not available to kernel side code)
   139 //
   140 	{
   141 	TInt ll = aLhs.Length();
   142 	TInt rl = aRhs.Length();
   143 	TInt len = Min(ll, rl);
   144 	TInt k = _strnicmp((const char*)aLhs.Ptr(), (const char*)aRhs.Ptr(), len);
   145 	return k != 0 ? k : ll - rl;
   146 	}
   147 
   148 GLDEF_C TInt MultiProperty(TInt (*aHandler)(TAny* aObj, const char*), TAny* aPtr, const char* aProperty)
   149 	{
   150 	const char* value = Property::GetString(aProperty);
   151 	if (!value)
   152 		return KErrNone;
   153 	for (;;)
   154 		{
   155 		TInt r = aHandler(aPtr, value);
   156 		if (r != KErrNone)
   157 			return r;
   158 		const char* ev = strchr(value, ';');
   159 		if (!ev)
   160 			break;
   161 		value = ev + 1;
   162 		}
   163 	return KErrNone;
   164 	}
   165 
   166 class DWinsGuiPowerHandler : public DPowerHandler
   167 	{
   168 public: // from DPowerHandler
   169 	void PowerDown(TPowerState);
   170 	void PowerUp();
   171 public:
   172 	static DWinsGuiPowerHandler* New();
   173 	void ScreenOn();
   174 	void ScreenOff();
   175 	void ScreenOn(TInt aScreen);
   176 	void ScreenOff(TInt aScreen);
   177 public:
   178 	DWinsGuiPowerHandler();
   179 	TBool ProcessEvent(const TRawEvent* aEvent);
   180 	TBool ProcessEventDfc(const TRawEvent* aEvent);
   181 	TBool	iStandby;
   182 	};
   183 
   184 static DWinsGuiPowerHandler* WinsGuiPowerHandler;
   185 
   186 _LIT(KWinsGuiName, "WinsGui");
   187 
   188 DWinsGuiPowerHandler* DWinsGuiPowerHandler::New()
   189 	{
   190 	DWinsGuiPowerHandler* self = new DWinsGuiPowerHandler();
   191 	if (!self)
   192 		return NULL;
   193 	self->Add();
   194 
   195 	return self;
   196 	}
   197 
   198 DWinsGuiPowerHandler::DWinsGuiPowerHandler() : DPowerHandler(KWinsGuiName)
   199 	{
   200 	}
   201 
   202 void DWinsGuiPowerHandler::ScreenOff()
   203 	{
   204 	for(TInt ix=0;ix<systemIni->iScreens.Count();ix++)
   205 		ScreenOff(ix);
   206 	}
   207 
   208 void DWinsGuiPowerHandler::ScreenOn()
   209 	{
   210 	for(TInt ix=0;ix<systemIni->iScreens.Count();ix++)
   211 		ScreenOn(ix);
   212 	}
   213 
   214 void DWinsGuiPowerHandler::ScreenOff(TInt aScreen)
   215 	{
   216 	PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, FALSE, NULL);
   217 	systemIni->iScreens[aScreen]->iScreenOff = ETrue;
   218 	}
   219 
   220 void DWinsGuiPowerHandler::ScreenOn(TInt aScreen)
   221 	{
   222 	PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, TRUE, NULL);
   223 	systemIni->iScreens[aScreen]->iScreenOff = EFalse;
   224 	}
   225 
   226 void DWinsGuiPowerHandler::PowerDown(TPowerState aState)
   227 	{
   228 	if (aState == EPwStandby)
   229 		iStandby = ETrue;
   230 	ScreenOff();
   231 	PowerDownDone();
   232 	}
   233 
   234 
   235 void DWinsGuiPowerHandler::PowerUp()
   236 	{
   237 	iStandby = EFalse;
   238 	ScreenOn();
   239 	PowerUpDone();
   240 	}
   241 
   242 // called in the interrupt context
   243 TBool DWinsGuiPowerHandler::ProcessEvent(const TRawEvent* aEvent)
   244 	{
   245 	if (!iStandby)
   246 		// Pass through 
   247 		return EFalse;
   248 
   249 	if ((aEvent->Type() == TRawEvent::EKeyDown))
   250 			{
   251 			Wins::Self() -> AssertWakeupSignal();
   252 			}
   253 	
   254 	// Ignore
   255 	return ETrue;
   256 	}
   257 
   258 // called in DFC
   259 TBool DWinsGuiPowerHandler::ProcessEventDfc(const TRawEvent* aEvent)
   260 	{
   261 	if (aEvent->Type() == TRawEvent::EKeyDown)
   262 		{
   263 		Wins::Self() -> WakeupEvent();
   264 		if (aEvent->ScanCode() == EStdKeyF5)
   265 			{
   266 			// Simulate a media change interrupt (media removed)
   267 			Wins::MediaChangeCallBack();
   268 			*Wins::MediaDoorOpenPtr()=ETrue;
   269 			// Ignore
   270 			return ETrue;
   271 			}
   272 		if (aEvent->ScanCode() == EStdKeyF8)
   273 			{
   274 			TRawEvent v;
   275 			v.Set(TRawEvent::ECaseClose);
   276 			Kern::AddEvent(v);
   277 			// Ignore
   278 			return ETrue;
   279 			}
   280 		if (aEvent->ScanCode() == EStdKeyF8)
   281 			{
   282 			TRawEvent v;
   283 			v.Set(TRawEvent::ECaseClose);
   284 			Kern::AddEvent(v);
   285 			// Ignore
   286 			return ETrue;
   287 			}
   288 		if (aEvent->ScanCode() == EStdKeyOff)
   289 			{
   290 			// Pass through
   291 			return EFalse;
   292 			}
   293 		if (aEvent->ScanCode() == EStdKeyF10)
   294 			{
   295 			TRawEvent v;
   296 			v.Set(TRawEvent::ESwitchOff);
   297 			Kern::AddEvent(v);
   298 			// Ignore
   299 			return ETrue;
   300 			}
   301 		if (aEvent->ScanCode() == EStdKeyF11)
   302 			{
   303 			TRawEvent v;
   304 			v.Set(TRawEvent::ECaseOpen);
   305 			Kern::AddEvent(v);
   306 			// Ignore
   307 			return ETrue;
   308 			}
   309 		}
   310 	else if (aEvent->Type() == TRawEvent::EKeyUp)
   311 		{
   312 		if (aEvent->ScanCode() == EStdKeyF10)
   313 			// Ignore
   314 			return ETrue;
   315 
   316 		if (aEvent->ScanCode() == EStdKeyF5)
   317 			{
   318 			// Simulate a media change interrupt (media Present)
   319 			*Wins::MediaDoorOpenPtr()=EFalse;
   320 			return ETrue;
   321 			}
   322 		}
   323 
   324 	// Path through
   325 	return EFalse;
   326 	}
   327 
   328 class EventQ
   329 	{
   330 	enum {ESize = 16};
   331 public:
   332 	EventQ();
   333 	void Add(const TRawEvent& aEvent);
   334 private:
   335 	static void Dfc(TAny* aPtr);
   336 	void Empty();
   337 private:
   338 	TDfc iDfc;
   339 	TRawEvent* iTail;
   340 	TRawEvent iQ[ESize];
   341 	};
   342 
   343 EventQ::EventQ()
   344 	:iDfc(&EventQ::Dfc, this, Kern::DfcQue0(), 6), iTail(iQ)
   345 	{}
   346 
   347 
   348 void EventQ::Add(const TRawEvent& aEvent)
   349 	{
   350 	StartOfInterrupt();	
   351 	if (WinsGuiPowerHandler->ProcessEvent(&aEvent)) 
   352 		{
   353 		EndOfInterrupt();
   354 		return;
   355 		}
   356 
   357 	TRawEvent* pE = iTail;
   358 	if (pE != &iQ[ESize])
   359 		{
   360 		*pE = aEvent;
   361 		iTail = pE + 1;
   362 		if (pE == iQ)
   363 			iDfc.Add();
   364 		}
   365 	EndOfInterrupt();
   366 	}
   367 
   368 void EventQ::Dfc(TAny* aPtr)
   369 	{
   370 	static_cast<EventQ*>(aPtr)->Empty();
   371 	}
   372 
   373 void EventQ::Empty()
   374 //
   375 // Called in the DFC
   376 //
   377 	{
   378 	TInt irq;
   379 	TRawEvent* pE = iQ;
   380 	for (;;)
   381 		{
   382 		if (!WinsGuiPowerHandler->ProcessEventDfc(pE)) 
   383 			Kern::AddEvent(*pE);
   384 		++pE;
   385 		irq = NKern::DisableAllInterrupts();
   386 		if (pE == iTail)
   387 			break;
   388 		NKern::RestoreInterrupts(irq);
   389 		}
   390 	iTail = iQ;
   391 	NKern::RestoreInterrupts(irq);
   392 	}
   393 
   394 LOCAL_D EventQ TheEventQ;
   395 
   396 // Virtual keys
   397 
   398 
   399 VirtualKey::VirtualKey(const TInt aCommandData, const TEmulCommand aCommand) : iCommand(aCommand), iData(aCommandData)
   400 	{
   401 	}
   402 
   403 TBool VKRect::Contains(TInt aX, TInt aY) const
   404 	{
   405 	return (aX >= iLeft && aX < iRight && aY >= iTop && aY < iBottom);
   406 	}
   407 
   408 VKRect::VKRect(const TInt aCommandData, const TEmulCommand aCommand, TInt aX, TInt aY, TInt aWidth, TInt aHeight) :
   409 	VirtualKey(aCommandData, aCommand)
   410 	{
   411 	iLeft = aX;
   412 	iTop = aY;
   413 	iRight = aX + aWidth;
   414 	iBottom = aY + aHeight;
   415 	}
   416 
   417 
   418 
   419 void VKRect::Draw(HDC aHdc,COLORREF aColor) const
   420 	{
   421 	HPEN pen;
   422 	pen=CreatePen(PS_SOLID, 2, aColor);
   423 	SelectObject(aHdc, pen);
   424 	POINT point;
   425 
   426 	MoveToEx(aHdc, (int)iLeft, (int)iTop, &point);
   427 	LineTo(aHdc, (int)iLeft, (int)iBottom);
   428 	LineTo(aHdc, (int)iRight, (int)iBottom);
   429 	LineTo(aHdc, (int)iRight, (int)iTop);
   430 	LineTo(aHdc, (int)iLeft, (int)iTop);
   431 	}
   432 
   433 
   434 KeyCombination::KeyCombination(const TInt aCommandData, TEmulCommand aCommand):
   435 	iData(aCommandData),
   436 	iCommand(aCommand)
   437 {
   438 	for (TInt i=0;i<KMaxHotKeyCombinationLength;i++) 
   439 		{
   440 		iCombination[i]=EStdKeyNull;
   441 		}
   442 }
   443 
   444 TBool KeyCombination::CheckCombinationPressed()
   445 {
   446 	for (TInt j=0;(j<KMaxHotKeyCombinationLength && iCombination[j]!=0);j++)
   447 		{
   448 		if (GetAsyncKeyState(MapVirtualKey(iCombination[j],1))>=0)//if at least one key is not pressed, we return false
   449 			return EFalse;				
   450 		}
   451 	return ETrue;	
   452 }
   453 
   454 TBool KeyCombination::AddKey(TStdScanCode aKey)
   455 {
   456 	TInt i;
   457 	for (i=0;i<KMaxHotKeyCombinationLength;i++) 
   458 		{
   459 		if (iCombination[i]==EStdKeyNull) 
   460 			break;
   461 		}
   462 	if (KMaxHotKeyCombinationLength==i)
   463 		return EFalse;
   464 	else		
   465 		iCombination[i]=aKey;	
   466 
   467 	return ETrue;
   468 }
   469 
   470 
   471 DScreenProperties::DScreenProperties()
   472 	{
   473 	memset(this,0,sizeof(DScreenProperties));
   474 	iColorDepth=KDefaultColorDepth;
   475 	
   476 	iViewport = TViewport(this);
   477 	}
   478 
   479 
   480 LOCAL_C TInt MaskGceOnly(TInt aModeBits)
   481 	{	   //All HAL modes are now reported. The GCE may refuse to register the surfaces.
   482 	return aModeBits&KEmulModes;	//previous useful settings: //(KEmulPixPerLong2|KEmulPixPerLong1);	//|KEmulPixPerLong4;
   483 	}
   484 	
   485 LOCAL_C TInt BitsForSingleMode(TInt aModeColor)
   486 	{	//only 1 bit should be set in aModeColor
   487 	switch (aModeColor)
   488 		{
   489 		case KEmulGray2:	return 1;	
   490 		case KEmulGray4:	return 2;	
   491 		case KEmulGray16:	return 4;
   492 		case KEmulGray256:	return 8;
   493 		case KEmulColor16:	return 4;
   494 		case KEmulColor256:	return 8;
   495 		case KEmulColor4K:	return 12;
   496 		case KEmulColor64K:	return 16;
   497 		case KEmulColor16M:	return 24;
   498 		default:	return 32;
   499 		}
   500 	
   501 	}
   502 
   503 DScreenProperties::~DScreenProperties() 
   504 	{
   505 	}
   506 
   507 TWindowState DScreenProperties::GetWindowState()
   508 	{
   509 	TWindowState state;
   510 	state.iWinPlace = iWinPlace;
   511 	state.iFlipstate = iScreenRotation;
   512 	state.iXoffset = iViewport.GetViewportOffsetX();
   513 	state.iYoffset = iViewport.GetViewportOffsetY();
   514 	return state;
   515 	}
   516 	
   517 TInt DScreenProperties::SetupProperties(TInt aConf, TInt aScreen)
   518 	{
   519 	char property[50];
   520 
   521 	// Calculate maximum dimensions
   522 	TInt configurations = Property::GetInt("ConfigCount", 0);
   523 	if (configurations == 0)
   524 		return KErrGeneral;
   525 
   526 	TInt count, screenWidth, screenHeight, physicalScreenWidth, physicalScreenHeight;
   527 	for (count = 0; count < configurations; ++count)
   528 		{
   529 		wsprintfA(property, "Configuration[%d][%d]ScreenWidth", count, aScreen);
   530 		screenWidth = Property::GetInt(property, KScreenWidth);
   531 		screenWidth = (screenWidth + 3) & ~3;
   532 		if (screenWidth > iMaxScreenWidth)
   533 			iMaxScreenWidth = screenWidth;
   534 		wsprintfA(property, "Configuration[%d][%d]ScreenHeight", count, aScreen);
   535 		screenHeight = Property::GetInt(property, KScreenHeight);
   536 		screenHeight = (screenHeight + 3) & ~3;
   537 		if (screenHeight > iMaxScreenHeight)
   538 			iMaxScreenHeight = screenHeight;
   539 //
   540 		wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth", count, aScreen);
   541 		physicalScreenWidth = Property::GetInt(property);
   542 		if (physicalScreenWidth > iMaxPhysicalScreenWidth)
   543 			iMaxPhysicalScreenWidth = physicalScreenWidth;
   544 		wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight", count, aScreen);
   545 		physicalScreenHeight = Property::GetInt(property);
   546 		if (physicalScreenHeight > iMaxPhysicalScreenHeight)
   547 			iMaxPhysicalScreenHeight = physicalScreenHeight;
   548 		}
   549 
   550 	// Read figures for current configuration
   551 	TInt givenWidth, givenHeight;
   552 	wsprintfA(property, "Configuration[%d][%d]ScreenWidth",aConf,aScreen);
   553 	givenWidth = Property::GetInt(property, KScreenWidth);
   554 	iScreenWidth = (givenWidth + 3) & ~3;
   555 	wsprintfA(property, "Configuration[%d][%d]ScreenHeight",aConf,aScreen);
   556 	givenHeight = Property::GetInt(property, KScreenHeight);
   557 	iScreenHeight = (givenHeight + 3) & ~3;
   558 	// Width of screen should be multiple number of 4 pixels.
   559 	if (givenWidth & 3 || givenHeight & 3)
   560 		{
   561 		Kern::Printf("Width and Height of Screen should be multiple number of 4 pixels.\n"
   562 				"\tWidth of screen[%d] set to: %d\n\tHeight of screen[%d] set to: %d", 
   563 				aScreen, iScreenWidth, aScreen, iScreenHeight);
   564 		}
   565 
   566 //
   567 	wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth",aConf,aScreen);
   568 	iPhysicalScreenWidth = Property::GetInt(property);
   569 	wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight",aConf,aScreen);
   570 	iPhysicalScreenHeight = Property::GetInt(property);
   571 //
   572 	wsprintfA(property, "Configuration[%d][%d]ScreenOffsetX",aConf,aScreen);
   573 	iScreenOffsetX = Property::GetInt(property, KScreenOffsetX);
   574 	wsprintfA(property, "Configuration[%d][%d]ScreenOffsetY",aConf,aScreen);
   575 	iScreenOffsetY = Property::GetInt(property, KScreenOffsetY);
   576 	
   577 	wsprintfA(property, "Configuration[%d][%d]CompositionBuffers",aConf,aScreen);
   578 	iCompositionBuffers = Property::GetInt(property, KCompositionBuffers);
   579 
   580 	wsprintfA(property, "Configuration[%d][%d]RefreshRateHz",aConf,aScreen);
   581 	iRefreshRateHz = Property::GetInt(property, KRefreshRateHz);
   582 
   583 
   584 	wsprintfA(property, "Configuration[%d][%d]ColorDepth",aConf,aScreen);
   585 	const char* colors = Property::GetString(property);
   586 	if (colors)
   587 		{
   588 		TUint colorDepth=0;
   589 		const char* end = colors;
   590 		for (;;)
   591 			{
   592 			const char* beg = skipws(end);
   593 			if(*beg==';')
   594 				break;
   595 			if (!*beg)
   596 				break;
   597 			end	= skiptok(beg);
   598 			if (_strnicmp("Gray2",beg,end-beg) == 0)
   599 				{
   600 				colorDepth|=KEmulGray2|KEmulIsBitMask;
   601 				}
   602 			else if (_strnicmp("Gray4",beg,end-beg) == 0)
   603 				{
   604 				colorDepth|=KEmulGray4|KEmulIsBitMask;
   605 				}
   606 			else if (_strnicmp("Gray16",beg,end-beg) == 0)
   607 				{
   608 				colorDepth|=KEmulGray16|KEmulIsBitMask;
   609 				}
   610 			else if (_strnicmp("Gray256",beg,end-beg) == 0)
   611 				{
   612 				colorDepth|=KEmulGray256|KEmulIsBitMask;
   613 				}
   614 			else if (_strnicmp("Color16",beg,end-beg) == 0)
   615 				{
   616 				colorDepth|=KEmulColor16|KEmulIsBitMask;
   617 				}
   618 			else if (_strnicmp("Color256",beg,end-beg) == 0)
   619 				{
   620 				colorDepth|=KEmulColor256|KEmulIsBitMask;
   621 				}
   622 			else if (_strnicmp("Color4K",beg,end-beg) == 0)
   623 				{
   624 				colorDepth|=KEmulColor4K|KEmulIsBitMask;
   625 				}
   626 			else if (_strnicmp("Color64K",beg,end-beg) == 0)
   627 				{
   628 				colorDepth|=KEmulColor64K|KEmulIsBitMask;
   629 				}
   630 			else if (_strnicmp("Color16M",beg,end-beg) == 0)
   631 				{
   632 				colorDepth|=KEmulColor16M|KEmulIsBitMask;
   633 				}
   634 			else
   635 				return KErrArgument;
   636 			}
   637 		iColorDepth = colorDepth;
   638 		
   639 		}
   640 	//multiple mode support is currently only for GCE. 
   641 	//I fill this array in before knowing if GCE will be instanced.
   642 	if (iColorDepth&KEmulIsBitMask)
   643 		{
   644 		//iModeDepths is only used by GCE
   645 		TInt colorDepth=MaskGceOnly(iColorDepth);
   646 		TInt setMode=0;
   647 		for (TInt i=1;i!=KEmulIsBitMask;i+=i)
   648 			if (colorDepth&i)
   649 				iModeDepths[setMode++]=BitsForSingleMode(i);
   650 		iMaxModes= setMode;	
   651 		iModeDepths[setMode++]=0;	//a bit width of 0 is illegal	
   652 		}
   653 	else
   654 		{
   655 		iModeDepths[0]=iColorDepth;
   656 		iMaxModes=1;
   657 		iModeDepths[1]=0;	//a bit width of 0 is illegal
   658 		}
   659 
   660 	wsprintfA(property, "Configuration[%d][%d]FasciaBitmap",aConf,aScreen);
   661 	const char* fascia = Property::GetString(property);
   662 	if (fascia)
   663 		{
   664 		TInt len = strlen(fascia);
   665 		//the path may have quotes at the start and end
   666 		//need to work out if this is an absolute or relative path
   667 		if (fascia[0] == '\"')
   668 			{
   669 			++fascia;
   670 			--len;
   671 			if (--len > 0 && fascia[len-1] == '\"')
   672 				--len;
   673 			}
   674 		char* p = iFasciaFileName;
   675 		if (fascia[0] != '\\' && (len < 3 || fascia[1] != ':'))
   676 			{
   677 			//relative path
   678 			strcpy(p, Property::GetString("EmulatorDataPath"));
   679 			p += strlen(p);
   680 			}
   681 		memcpy(p, fascia, len);
   682 		p[len] = '\0';
   683 		}
   684 	else
   685 		{
   686 		// default to machine name
   687 		strcpy(iFasciaFileName, Property::GetString("EmulatorDataPath"));
   688 		strcat(iFasciaFileName, Property::GetString("MachineName"));
   689 		strcat(iFasciaFileName, ".bmp");
   690 		}
   691 	return KErrNone;
   692 	}
   693 
   694 TViewport::TViewport() 
   695 	:iScreenProps(NULL),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0)
   696 	{
   697 	}
   698 
   699 TViewport::TViewport(DScreenProperties* aScreenProps)
   700 	:iScreenProps(aScreenProps),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0)
   701 	{	
   702 	}	
   703 TViewport::~TViewport()
   704 	{
   705 	}
   706 	
   707 
   708 /**
   709 Changes the logical position of the viewport within the input area
   710 of the emulator screen. The method may adjust the position so that
   711 the viewport stays within the input area.
   712 @param aPosition The new Y position of the top left hand corner of the viewport.
   713 @param aHwnd The window associated with the viewport
   714 */
   715 void TViewport::ScrollToY(TInt aPosition, HWND aHwnd)
   716 	{
   717 
   718 	SCROLLINFO scrollinfo;
   719 	scrollinfo.cbSize=sizeof(scrollinfo);
   720 
   721 	//save for later
   722 	scrollinfo.fMask=SIF_POS;
   723 	GetScrollInfo(aHwnd, SB_VERT, &scrollinfo);
   724 	TInt oldY=scrollinfo.nPos;
   725 
   726 	if(aPosition<0)
   727 	{
   728 		scrollinfo.nPos = 0;
   729 	}
   730 	else if( (aPosition+GetViewportHeight())>GetMaxHeight())
   731 	{
   732 		scrollinfo.nPos = max(0,GetMaxHeight() - GetViewportHeight() );
   733 	}
   734 	else
   735 	{
   736 		scrollinfo.nPos=aPosition;
   737 	}
   738 
   739 	SetViewportOffsetY(scrollinfo.nPos);
   740 	scrollinfo.fMask=SIF_POS;
   741 	SetScrollInfo(aHwnd,SB_VERT, &scrollinfo, TRUE );
   742 	ScrollWindowEx(aHwnd, 0, oldY-scrollinfo.nPos, 0, 0, NULL, NULL, SW_INVALIDATE);
   743 	
   744 	UpdateChildPos(aHwnd);
   745 	}
   746 	
   747 /**
   748 As for ScrollToY but for the X direction
   749 */
   750 void TViewport::ScrollToX(TInt aPosition, HWND aHwnd)
   751 	{
   752 	SCROLLINFO scrollinfo;
   753 	scrollinfo.cbSize=sizeof(scrollinfo);
   754 	
   755 	//save for later
   756 	scrollinfo.fMask=SIF_POS;
   757 	GetScrollInfo(aHwnd, SB_HORZ, &scrollinfo);
   758 	TInt oldX=scrollinfo.nPos;
   759 
   760 	if(aPosition<0)
   761 	{
   762 		scrollinfo.nPos = 0;
   763 	}
   764 	else if( (aPosition+GetViewportWidth())>GetMaxWidth())
   765 	{
   766 		scrollinfo.nPos = max(0,GetMaxWidth() - GetViewportWidth() );
   767 	}
   768 	else
   769 	{
   770 		scrollinfo.nPos=aPosition;
   771 	}
   772 
   773 	SetViewportOffsetX(scrollinfo.nPos);
   774 	scrollinfo.fMask=SIF_POS;
   775 	SetScrollInfo(aHwnd,SB_HORZ, &scrollinfo, TRUE );
   776 	ScrollWindowEx(aHwnd, oldX-scrollinfo.nPos, 0, 0, 0, NULL, NULL, SW_INVALIDATE);
   777 
   778 	UpdateChildPos(aHwnd);
   779 	}
   780 	
   781 //Forward declaration
   782 LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin);
   783 
   784 /**
   785 Move the child window to it's correct position.
   786 
   787 @param aHwnd The HWND of the parent window
   788 */
   789 void TViewport::UpdateChildPos(HWND aHwnd)
   790 	{
   791 	TInt screenNumber = ::ScreenFromHWND(aHwnd,TheWin);
   792 	HWND childWin = TheChildWin[screenNumber];
   793 
   794 	switch (iScreenProps->iScreenRotation)
   795 		{
   796 		case EEmulatorFlipRestore:
   797 			MoveWindow(
   798 				childWin,
   799 				iScreenProps->iScreenOffsetX - GetViewportOffsetX(),
   800 				iScreenProps->iScreenOffsetY - GetViewportOffsetY(),
   801 				iScreenProps->iScreenWidth,
   802 				iScreenProps->iScreenHeight,
   803 				TRUE
   804 				);
   805 			break;
   806 		case EEmulatorFlipInvert:
   807 			MoveWindow(
   808 				childWin,
   809 				iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth) - GetViewportOffsetX(),
   810 				iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetY(),
   811 				iScreenProps->iScreenWidth,
   812 				iScreenProps->iScreenHeight,
   813 				TRUE
   814 				);
   815 			break;
   816 		case EEmulatorFlipLeft:
   817 			MoveWindow(
   818 				childWin,
   819 				iScreenProps->iScreenOffsetY - GetViewportOffsetX(),
   820 				iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth)- GetViewportOffsetY(),
   821 				iScreenProps->iScreenHeight,
   822 				iScreenProps->iScreenWidth,
   823 				TRUE
   824 				);
   825 			break;
   826 		case EEmulatorFlipRight:
   827 			MoveWindow(
   828 				childWin,
   829 				iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetX(),
   830 				iScreenProps->iScreenOffsetX - GetViewportOffsetY(),
   831 				iScreenProps->iScreenHeight,
   832 				iScreenProps->iScreenWidth,
   833 				TRUE
   834 				);
   835 			break;
   836 		}
   837 
   838 	}
   839 	
   840 /**
   841 Update the range of the horizontal scrollbar,
   842 to take account of the current viewport width.
   843 
   844 @param aHwnd The window to be updated
   845 */
   846 void TViewport::UpdateScrollBarH(HWND aHwnd)
   847 	{
   848 
   849 	SCROLLINFO scrollinfoHor;
   850 	scrollinfoHor.cbSize=sizeof(scrollinfoHor);
   851 	scrollinfoHor.fMask=SIF_RANGE|SIF_PAGE;
   852 	scrollinfoHor.nMin=0;
   853 	scrollinfoHor.nMax= GetMaxWidth()-1;
   854 	
   855 	
   856 	TInt newPage = GetViewportWidth() ;
   857 	TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image.
   858 	if ( newPage>= scrollinfoHor.nMax -GetSystemMetrics(SM_CXVSCROLL)
   859 		&& newPage < scrollinfoHor.nMax+1)
   860 		{
   861 		redraw=ETrue;
   862 		newPage=GetMaxWidth();
   863 
   864 		}
   865 	scrollinfoHor.nPage= newPage;
   866 
   867 	SetScrollInfo(aHwnd,SB_HORZ, &scrollinfoHor, TRUE );
   868 	if(redraw)
   869 		{
   870 		ScrollToX(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar
   871 		InvalidateRect(aHwnd, NULL, TRUE);
   872 		}
   873 	}
   874 	
   875 /**
   876 Update the range of the vertical scrollbar,
   877 to take account of the current viewport width.
   878 
   879 @param aHwnd The window to be updated
   880 */	
   881 void TViewport::UpdateScrollBarV(HWND aHwnd)
   882 	{
   883 	SCROLLINFO scrollinfoVer;
   884 	scrollinfoVer.cbSize=sizeof(scrollinfoVer);
   885 	scrollinfoVer.fMask=SIF_RANGE|SIF_PAGE;
   886 	scrollinfoVer.nMin=0;
   887 	scrollinfoVer.nMax= GetMaxHeight()-1;
   888 	
   889 	TInt newPage = GetViewportHeight() ;
   890 	TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image.
   891 	if ( newPage>= scrollinfoVer.nMax -GetSystemMetrics(SM_CYHSCROLL)
   892 		&& newPage < scrollinfoVer.nMax+1)
   893 		{
   894 		redraw=ETrue;
   895 		newPage=GetMaxHeight();
   896 		}
   897 	scrollinfoVer.nPage= newPage;
   898 
   899 	SetScrollInfo(aHwnd,SB_VERT, &scrollinfoVer, TRUE );
   900 	if(redraw)
   901 		{
   902 		ScrollToY(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar
   903 		InvalidateRect(aHwnd, NULL, TRUE);
   904 		}
   905 	}
   906 
   907 /**
   908 Returns the max width for the viewport window (non-client area) so that it
   909 may be bounded. Takes account of scrollbar.
   910 
   911 @return Max width
   912 */	
   913 TInt TViewport::GetMaxWindowWidth() const
   914 	{
   915 	
   916 	RECT rect = {0,0,0,0};
   917 	
   918 	switch(iScreenProps->iScreenRotation)
   919 		{
   920 		case EEmulatorFlipRestore:
   921 		case EEmulatorFlipInvert:
   922 			{
   923 			rect.right=iScreenProps->iXYInputWidth;
   924 			rect.bottom=iScreenProps->iXYInputHeight;
   925 			break;
   926 			}
   927 		case EEmulatorFlipLeft:
   928 		case EEmulatorFlipRight:
   929 			{
   930 			rect.right=iScreenProps->iXYInputHeight;
   931 			rect.bottom=iScreenProps->iXYInputWidth;
   932 			break;
   933 			}
   934 		}
   935 	AdjustWindowRect(//take account of window decorations
   936 		&rect,
   937 		KWinStyle,
   938 		FALSE
   939 		);
   940 	
   941 	
   942 	return (rect.right-rect.left);
   943 	}
   944 	
   945 /**
   946 Returns the max height for the viewport window (non-client area) so that it
   947 may be bounded. Takes account of scrollbar.
   948 
   949 @return Max height
   950 */
   951 TInt TViewport::GetMaxWindowHeight() const
   952 	{
   953 	
   954 	RECT rect ={0,0,0,0};
   955 
   956 	switch(iScreenProps->iScreenRotation)
   957 		{
   958 		case EEmulatorFlipRestore:
   959 		case EEmulatorFlipInvert:
   960 			{
   961 			rect.right=iScreenProps->iXYInputWidth;
   962 			rect.bottom=iScreenProps->iXYInputHeight;
   963 			break;
   964 			}
   965 		case EEmulatorFlipLeft:
   966 		case EEmulatorFlipRight:
   967 			{
   968 			rect.right=iScreenProps->iXYInputHeight;
   969 			rect.bottom=iScreenProps->iXYInputWidth;
   970 			break;
   971 			}
   972 		}
   973 	AdjustWindowRect(//take account of window decorations
   974 		&rect,
   975 		KWinStyle,
   976 		FALSE
   977 		);
   978 	return (rect.bottom-rect.top);
   979 	}
   980 
   981 /**
   982 Returns the maximum width for the viewport (client area only).
   983 Allowing for the orientation of the emulator.
   984 
   985 @return Max width
   986 */
   987 TInt TViewport::GetMaxWidth() const
   988 	{
   989 	TInt width=0;
   990 	switch(iScreenProps->iScreenRotation)
   991 		{
   992 		case EEmulatorFlipRestore:
   993 		case EEmulatorFlipInvert:
   994 			{
   995 			width = iScreenProps->iXYInputWidth;
   996 			break;
   997 			}
   998 		case EEmulatorFlipLeft:
   999 		case EEmulatorFlipRight:
  1000 			{
  1001 			width = iScreenProps->iXYInputHeight;
  1002 			break;
  1003 			}
  1004 		}
  1005 	
  1006 	return width;
  1007 	}
  1008 
  1009 /**
  1010 Returns the maximum height for the viewport (client area only).
  1011 Allowing for the orientation of the emulator.
  1012 
  1013 @return Max height
  1014 */
  1015 TInt TViewport::GetMaxHeight() const
  1016 	{
  1017 	TInt height=0;
  1018 	switch(iScreenProps->iScreenRotation)
  1019 		{
  1020 		case EEmulatorFlipRestore:
  1021 		case EEmulatorFlipInvert:
  1022 			{
  1023 			height = iScreenProps->iXYInputHeight;
  1024 			break;
  1025 			}
  1026 		case EEmulatorFlipLeft:
  1027 		case EEmulatorFlipRight:
  1028 			{
  1029 			height =  iScreenProps->iXYInputWidth;
  1030 			break;
  1031 			}
  1032 		}
  1033 	
  1034 	return height;
  1035 	
  1036 	}
  1037 
  1038 /**
  1039 Sets the X offset of the viewport from the edge of the input area
  1040 @param aOffset The X offset
  1041 */
  1042 void TViewport::SetViewportOffsetX(TInt aOffset)
  1043 	{
  1044 	iViewportOffsetX = aOffset;
  1045 	}
  1046 
  1047 /**
  1048 Sets the Y offset of the viewport from the edge of the input area
  1049 @param aOffset The Y offset
  1050 */
  1051 void TViewport::SetViewportOffsetY(TInt aOffset)
  1052 	{
  1053 	iViewportOffsetY = aOffset;
  1054 	}
  1055 
  1056 TInt TViewport::GetViewportOffsetX() const
  1057 	{
  1058 	return iViewportOffsetX;	
  1059 	}
  1060 TInt TViewport::GetViewportOffsetY() const
  1061 	{
  1062 	return iViewportOffsetY;
  1063 	}
  1064 	
  1065 /**
  1066 Sets the viewport width, this is equal to the width
  1067 of the window's client area
  1068 @param aWidth The width
  1069 */
  1070 void TViewport::SetViewportWidth(TInt aWidth)
  1071 	{
  1072 	iViewportWidth=aWidth;
  1073 	}
  1074 
  1075 /**
  1076 Sets the viewport height, this is equal to the height
  1077 of the window's client area
  1078 @param aHeight The height
  1079 */
  1080 void TViewport::SetViewportHeight(TInt aHeight)
  1081 	{
  1082 	iViewportHeight=aHeight;
  1083 	}
  1084 
  1085 TInt TViewport::GetViewportWidth() const
  1086 	{
  1087 	return iViewportWidth;
  1088 	}
  1089 TInt TViewport::GetViewportHeight() const
  1090 	{
  1091 	return iViewportHeight;
  1092 	}
  1093 
  1094 // the UI class
  1095 
  1096 DWinsUi::DWinsUi()
  1097 	:iVirtualKeys(10),
  1098 	iControlHotKeys(10)
  1099 	{}
  1100 
  1101 /// Returns the current mode's depth. Remember current mode is never set!
  1102 TUint DWinsUi::ColorDepth(TInt aScreenNumber)
  1103 	{
  1104 	TVideoInfoV01 info;
  1105 	VideoInfo(aScreenNumber, info);
  1106 	return info.iBitsPerPixel;
  1107 	}
  1108 
  1109 TInt DWinsUi::SetFlip(TEmulatorFlip aFlip, TInt aScreenNumber)
  1110 	{
  1111 	if(TUint(aScreenNumber)>=TUint(systemIni->iScreens.Count()))
  1112 		return KErrArgument;
  1113 	int r1 = PostMessageA(TheChildWin[aScreenNumber],WM_FLIP_MESSAGE,(TUint)aFlip,NULL);
  1114 	return r1 ? KErrNone : KErrGeneral;
  1115 	}
  1116 
  1117 void DWinsUi::Info(TVariantInfoV01& aInfo)
  1118 	{
  1119 	aInfo.iLedCapabilities=0x3;
  1120 	}
  1121 
  1122 HWND DWinsUi::HWnd()
  1123 	{
  1124 	return TheControlWin;
  1125 	}
  1126 
  1127 TInt DWinsUi::SetupProperties(TInt aId)
  1128 	
  1129 //
  1130 // load UI settings from the emulator properties
  1131 //
  1132 	{
  1133 	//setup the screens
  1134 	TInt screens = Property::GetInt("[screens]", 1);
  1135  
  1136  	for (TInt x = 0; x < screens; ++x)
  1137  		{
  1138  		DScreenProperties * pScr = new DScreenProperties();
  1139  		if (!pScr)
  1140  			return KErrNoMemory;
  1141  		
  1142  		TInt ret = pScr->SetupProperties(aId,x);
  1143  		if (KErrNone == ret)
  1144  			ret = iScreens.Append(pScr);
  1145  
  1146  		if (KErrNone != ret)
  1147  			{
  1148  			delete pScr;
  1149  			return ret;
  1150  			}
  1151  		}
  1152 //
  1153 	char property[50];
  1154 	wsprintfA(property, "Configuration[%d]LedSize",aId);
  1155 	iLedSize = Property::GetInt(property, KLedSize);
  1156 	wsprintfA(property, "Configuration[%d]LedArrangeVertically",aId);
  1157 	iLedVertical = Property::GetBool(property, KLedVertical);
  1158 	wsprintfA(property, "Configuration[%d]LedArrangeHorizontally",aId);
  1159 	if (Property::GetBool(property))
  1160 		iLedVertical = EFalse;
  1161 	wsprintfA(property, "Configuration[%d]LedOffsetX",aId);
  1162 	iLedOffsetX = Property::GetInt(property, KLedLeft);
  1163 	wsprintfA(property, "Configuration[%d]LedOffsetY",aId);
  1164 	iLedOffsetY = Property::GetInt(property, KLedTop);
  1165 	wsprintfA(property, "Configuration[%d]LedGap",aId);
  1166 	iLedGap = Property::GetInt(property, KLedGap);
  1167 //
  1168 	wsprintfA(property, "Configuration[%d]PointerType",aId);
  1169 	const char* pointer = Property::GetString(property, "Pen");
  1170 	if (_stricmp(pointer, "None") == 0)
  1171 		{
  1172 		iPointerType=_S8("NONE");
  1173 		iXYInputType=EXYInputNone;
  1174 		}
  1175 	else if (_stricmp(pointer,"Pen") == 0)
  1176 		{
  1177 		iPointerType=_S8("PEN");
  1178 		iXYInputType=EXYInputPointer;
  1179 		}
  1180 	else if (_stricmp(pointer,"Mouse") == 0)
  1181 		{
  1182 		iPointerType=_S8("MOUSE");
  1183 		iXYInputType=EXYInputMouse;
  1184 		}
  1185 	else if (_stricmp(pointer,"Delta-Mouse") == 0)
  1186 		{
  1187 		iPointerType=_S8("MOUSE");
  1188 		iXYInputType=EXYInputDeltaMouse;
  1189 		}
  1190 	else
  1191 		return KErrArgument;
  1192 //
  1193 	wsprintfA(property, "Configuration[%d]DigitizerOffsetX",aId);
  1194 	iDigitizerOffsetX = Property::GetInt(property, -iScreens[0]->iScreenOffsetX);
  1195 	wsprintfA(property, "Configuration[%d]DigitizerOffsetY",aId);
  1196 	iDigitizerOffsetY = Property::GetInt(property, -iScreens[0]->iScreenOffsetY);
  1197 	wsprintfA(property, "Configuration[%d]DigitizerWidth",aId);
  1198 	iDigitizerWidth = Property::GetInt(property,-1);
  1199 	wsprintfA(property, "Configuration[%d]DigitizerHeight",aId);
  1200 	iDigitizerHeight = Property::GetInt(property,-1);
  1201 	wsprintfA(property, "Configuration[%d]DisableDigitizer",aId);
  1202 	iDigitizerEnabled = !Property::GetBool(property);
  1203 //	To enable the multitouch 
  1204 	wsprintfA(property, "EnableMultiTouch");
  1205 	iMultiTouchEnabled = Property::GetBool(property,EFalse);
  1206 	wsprintfA(property, "SYMBIAN_BASE_USE_GCE");
  1207 	iGCEEnabled = Property::GetBool(property,EFalse);
  1208 	wsprintfA(property, "MultiTouchProximityStep");
  1209 	iMultiTouchProximityStep = Property::GetInt(property,-1);
  1210 	wsprintfA(property, "MultiTouchPressureStep");
  1211 	iMultiTouchPressureStep = Property::GetInt(property,-1);
  1212 //
  1213 	strcpy(iSysIniFileName, Property::GetString("EmulatorDataPath"));
  1214 	strcat(iSysIniFileName, "emulator\\");
  1215 	if (!Emulator::CreateAllDirectories(iSysIniFileName))
  1216 		return Emulator::LastError();
  1217 	strcat(iSysIniFileName, Property::GetString("MachineName"));
  1218 	strcat(iSysIniFileName, ".sys.ini");
  1219 //
  1220 	TInt r = iKeyboard.Init(aId);
  1221 	if (r != KErrNone)
  1222 		return r;
  1223 
  1224 	wsprintfA(property, "Configuration[%d]VirtualKey",aId);
  1225 	r = MultiProperty(&DWinsUi::DoDefineVirtualKey, this, property);
  1226 	if (r != KErrNone)
  1227 		return r;
  1228 //
  1229 
  1230 	wsprintfA(property, "Configuration[%d]NoVersionInfo",aId);
  1231 	iDisplayVersionInfo = !Property::GetBool(property);
  1232 	
  1233 	wsprintfA(property, "Configuration[%d]WindowTitle",aId);
  1234 	const char * p = Property::GetString(property);
  1235 	if (p && (strlen(p) <= KMaxNameSize))
  1236 		strcpy(iWindowTitle, p);
  1237 	else
  1238 		strcpy(iWindowTitle, DefaultWindowTitle);
  1239 
  1240 	if (iDisplayVersionInfo)
  1241 		{
  1242 		TInt wtLen = strlen(iWindowTitle);
  1243 		TInt vtLen = strlen(VersionText);
  1244 		if ((wtLen + vtLen) > KMaxNameSize)
  1245 			iWindowTitle[KMaxNameSize-vtLen] = '\0';
  1246 		strcat(iWindowTitle, VersionText);
  1247 		}
  1248 
  1249 	wsprintfA(property, "Configuration[%d]OnActivation",aId);
  1250 	pointer = Property::GetString(property);	
  1251 	//example	OnActivation 270 EKeyScreenDimension1
  1252 	//params are rotation(int) and key(string)
  1253 	if (pointer)
  1254 		{
  1255 		char * next;
  1256 	
  1257 		//skip any white space
  1258 		const char* beg = skipws(pointer);
  1259 		
  1260 		//get the number
  1261 		long rotation = strtol(beg, &next, 0);
  1262 		if (next == beg)
  1263 			return KErrArgument;
  1264 
  1265 		switch (rotation)
  1266 			{
  1267 			case 0:
  1268 				iScreens[0]->iScreenRotation = EEmulatorFlipRestore;
  1269 				break;
  1270 			case 90:
  1271 				iScreens[0]->iScreenRotation = EEmulatorFlipRight;
  1272 				break;
  1273 			case 180:
  1274 				iScreens[0]->iScreenRotation = EEmulatorFlipInvert;
  1275 				break;
  1276 			case 270:
  1277 				iScreens[0]->iScreenRotation = EEmulatorFlipLeft;
  1278 				break;
  1279 			default:
  1280 				r = KErrArgument;
  1281 			}
  1282 		if (r != KErrNone)
  1283 			return r;
  1284 		
  1285 		beg = skipws(next);
  1286 		
  1287 		//beg should now point to the keycode
  1288 		TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, strlen(beg)));
  1289 		if (key == KErrNotFound)
  1290 			return key;
  1291 		iInitialFlipMsg = key;
  1292 		}
  1293 
  1294 	//EmulatorControl messages are a bit like virtual keys
  1295 	wsprintfA(property, "Configuration[%d]EmulatorControl",aId);
  1296 	r = MultiProperty(&DWinsUi::DoDefineEmulatorControl, this, property);
  1297 	if (r != KErrNone)
  1298 		return r;
  1299 
  1300 	wsprintfA(property, "Configuration[%d]EmulatorControlHotKey",aId);
  1301 	r = MultiProperty(&DWinsUi::DoDefineEmulatorControlHotKey, this, property);
  1302 	if (r != KErrNone)
  1303 		return r;
  1304 	
  1305 	return KErrNone;
  1306 	}
  1307 
  1308 TInt DWinsUi::NumberOfScreens()
  1309 	{
  1310 	return iScreens.Count();
  1311 	}
  1312 
  1313 /**
  1314 Return the highest bit depth from an emulator mode mask.
  1315 @param aModeMask	A bitwise combination of KEmul... display mode mask values.
  1316 @return A color depth in bits per pixel.
  1317 */
  1318 LOCAL_C TInt MaximumBitDepthFromMask(TInt aModeMask)
  1319 	{
  1320 	// Choose the highest bits per pixel based on the display mode mask.
  1321 	if (aModeMask & KEmulColor16M)
  1322 		{
  1323 		return 24;
  1324 		}
  1325 	if (aModeMask & KEmulColor64K)
  1326 		{
  1327 		return 16;
  1328 		}
  1329 	if (aModeMask & KEmulColor4K)
  1330 		{
  1331 		return 12;
  1332 		}
  1333 
  1334 	// Lower bit depths are not supported, so use the default
  1335 	return 24;
  1336 	}
  1337 
  1338 
  1339 /**
  1340 Return the TDisplayRotation corresponding to the given TEmulatorFlip.
  1341 @param aFlip	A screen rotation as a TEmulatorFlip.
  1342 @return The screen rotation as a TDisplayRotation.
  1343 */
  1344 LOCAL_C RDisplayChannel::TDisplayRotation FlipToDisplayRotation(TEmulatorFlip aFlip)
  1345 	{
  1346 	switch (aFlip)
  1347 		{
  1348 		case EEmulatorFlipLeft:
  1349 			return RDisplayChannel::ERotation90CW;
  1350 		case EEmulatorFlipInvert:
  1351 			return RDisplayChannel::ERotation180;
  1352 		case EEmulatorFlipRight:
  1353 			return RDisplayChannel::ERotation270CW;
  1354 		}
  1355 	return RDisplayChannel::ERotationNormal;
  1356 	}
  1357 
  1358 
  1359 TInt DWinsUi::SetDisplayChannel(TInt aScreenNumber, DDisplayChannel* aDisplay)
  1360 	{
  1361 	return systemIni->SetDisplayChannelImpl(aScreenNumber,aDisplay);
  1362 	}
  1363 
  1364 
  1365 TInt DWinsUi::SetDisplayChannelImpl(TInt aScreenNumber, DDisplayChannel* aDisplay)
  1366 	{
  1367 	if (TUint(aScreenNumber) >= TUint(NumberOfScreens()))
  1368 		{
  1369 		// Screen number is either negative or too big.
  1370 		return KErrArgument;
  1371 		}
  1372 
  1373 	TInt r = KErrNone;
  1374 	HWND hWnd = TheChildWin[aScreenNumber];
  1375 	TBufferSet& buffer = masterIni->iBufferSet[aScreenNumber];
  1376 	
  1377 	if (aDisplay)
  1378 		{
  1379 		// Display driver connecting
  1380 		DScreenProperties* screen = iScreens[aScreenNumber];
  1381 		RDisplayChannel::TDisplayInfo info;
  1382 
  1383 		TInt pixelBytes = 2;
  1384 		info.iBitsPerPixel = MaximumBitDepthFromMask(screen->iColorDepth);
  1385 
  1386 		switch (info.iBitsPerPixel)
  1387 			{
  1388 			case 12:	// XRGB4444
  1389 				info.iPixelFormat = EUidPixelFormatXRGB_4444;
  1390 				break;
  1391 			case 16:	// RGB565
  1392 				info.iPixelFormat = EUidPixelFormatRGB_565;
  1393 				break;
  1394 			default:
  1395 				// Force anything else to packed RGB888
  1396 				pixelBytes = 4;
  1397 				info.iBitsPerPixel = 24;
  1398 				info.iPixelFormat = EUidPixelFormatXRGB_8888;
  1399 				break;
  1400 			}
  1401 
  1402 		TInt width = screen->iMaxScreenWidth;
  1403 		TInt height = screen->iMaxScreenHeight;
  1404 
  1405 		info.iRefreshRateHz = screen->iRefreshRateHz;
  1406 		info.iAvailableRotations = RDisplayChannel::ERotationNormal | RDisplayChannel::ERotation90CW |
  1407 									RDisplayChannel::ERotation180 | RDisplayChannel::ERotation270CW;
  1408 		info.iNormal.iWidth = width;
  1409 		info.iNormal.iHeight = height;
  1410 		// Windows requires rounding up to 4-bytes words
  1411 		info.iNormal.iOffsetBetweenLines = _ALIGN_UP(width * pixelBytes, 4);
  1412 		info.iFlipped.iWidth = height;
  1413 		info.iFlipped.iHeight = width;
  1414 		// Windows requires rounding up to 4-bytes words
  1415 		info.iFlipped.iOffsetBetweenLines = _ALIGN_UP(height * pixelBytes, 4);
  1416 	
  1417 		TInt maxSize=0;	 
  1418 		//ensure legacy buffer is large enough for all supported modes.
  1419 		//It would be a very strange setup for the max size to not be the max bpp,
  1420 		//but we don't know which mode is max bpp anyway!
  1421 		TVideoInfoV01 videoInfo;
  1422 		for (TInt mode=0,maxMode=screen->iMaxModes;mode<maxMode;mode++)
  1423 			{
  1424 			if (systemIni->VideoInfoForDisplayDriver(aScreenNumber,mode, videoInfo))	//can't actually fail currently
  1425 				{
  1426 				TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iHeight;
  1427 				if (dwSize>maxSize)
  1428 					maxSize=dwSize;
  1429 				}
  1430 			else
  1431 				{
  1432 				Fault(EGuiVideoInfoUnavailable);
  1433 				}
  1434 			//rotated mode may use more RAM?? Height may be >Width or may not be a multiple of stride quantum
  1435 			if (systemIni->VideoInfoForDisplayDriver(aScreenNumber,mode|KModeFlagFlipped, videoInfo))	//can't actually fail currently
  1436 				{
  1437 				TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iWidth;
  1438 				if (dwSize>maxSize)
  1439 					{
  1440 					maxSize=dwSize;
  1441 					}
  1442 				}
  1443 			else
  1444 				{
  1445 				Fault(EGuiVideoInfoUnavailable);
  1446 				}
  1447 			}
  1448 
  1449 		masterIni->iMaxSizeInBytes = maxSize;
  1450 		if (__e32_atomic_add_ord32(&buffer.iDisplayDriverCount, 1) == 0)
  1451 			{
  1452 			// First driver to connect, allocate frame buffers.
  1453 			// +1 frame buffer is ui legacy buffer at [0], so does need to take account of stride and offset
  1454 			r = masterIni->AllocateFrameBuffers(aScreenNumber, screen->iCompositionBuffers + 1, maxSize);
  1455 			}
  1456 
  1457 		if (r == KErrNone)
  1458 			{
  1459 			buffer.iScreenBuffer.iDisplayBufferOffset = 0;
  1460 			masterIni->iBufferSet[aScreenNumber].iDisplayChannel = aDisplay;
  1461 			masterIni->InitBitmapHeader(*screen, &buffer.iInfo);
  1462 			masterIni->InitBufferFormat(*screen, buffer.iBufferFormat);
  1463 			if(systemIni->VideoInfoForDisplayDriver(aScreenNumber,screen->iCurrentMode, videoInfo, ETrue))
  1464 				{
  1465 					r = aDisplay->Initialize(info,
  1466 											 FlipToDisplayRotation(screen->iScreenRotation),
  1467 											 hWnd, buffer.iScreenBuffer.iFrameBuffers,
  1468 											 buffer.iScreenBuffer.iMemChunks,
  1469 											 buffer.iDsaBuffer,
  1470 						                     videoInfo.iSizeInPixels,videoInfo.iSizeInTwips,
  1471 						                     masterIni->iSupportedPixelFormatTable,
  1472 						                     masterIni->iSupportedPixelFormatTableSize,
  1473 						                     buffer.iBufferFormat);
  1474 				}
  1475 			else
  1476 				{
  1477 				Fault(EGuiVideoInfoUnavailable);
  1478 				}
  1479 			}
  1480 
  1481 		if (r != KErrNone && __e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1)
  1482 			{
  1483 			// Release any that were allocated
  1484 			masterIni->ReleaseFrameBuffers(aScreenNumber);
  1485 			}
  1486 		}
  1487 	else
  1488 		{
  1489 		// Display driver disconnected
  1490 		if (__e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1)
  1491 			{
  1492 			// All drivers disconnected, deallocate memory.
  1493 			masterIni->ReleaseFrameBuffers(aScreenNumber);
  1494 			}
  1495 		}
  1496 
  1497 	return r;
  1498 	}
  1499 
  1500 
  1501 void DWinsUi::SetVirtualKey(const TBool aProcessing, const TInt aCommandData, const TEmulCommand aCommand)
  1502 	{
  1503 	iProcessingVirtualKey = aProcessing;
  1504 	iFakedVirtualKey = aCommandData;
  1505 	iVirtualKeyCommand = aCommand;
  1506 	}
  1507 
  1508 TBool DWinsUi::WasVirtualKey(TInt& aCommandData, TEmulCommand& aCommand)
  1509 	{
  1510 	if (iProcessingVirtualKey)
  1511 		{
  1512 
  1513 		aCommandData = iFakedVirtualKey;
  1514 		aCommand = iVirtualKeyCommand;
  1515 		}
  1516 	return iProcessingVirtualKey;
  1517 	}
  1518 
  1519 
  1520 TInt DWinsUi::DoDefineEmulatorControl(TAny* aPtr, const char* aValue)
  1521 	{
  1522 	return static_cast<DWinsUi*>(aPtr)->DefineEmulatorControl(aValue);
  1523 	}
  1524 
  1525 
  1526 TInt DWinsUi::DefineEmulatorControl(const char* aValue)
  1527 	{
  1528 
  1529 	//example EmulatorControl SelectConfig 2 rect 223,640 29,22
  1530 	//example EmulatorControl NextConfig rect 223,640 29,22
  1531 	const char* beg = skipws(aValue);
  1532 	const char* end = skiptok(beg);
  1533 	TInt err = KErrNone;
  1534 	
  1535 	TEmulCommand command = ENoCommand;
  1536 	TInt data = 0;
  1537 	if (_strnicmp(beg, "SelectConfig", end-beg) == 0)
  1538 		{
  1539 		//get the int param which is the config to switch to
  1540 		beg = end;
  1541 		char * e;
  1542 		data = strtol(beg, &e,0);
  1543 		if (beg == e)
  1544 			err = KErrArgument;
  1545 		end = e;
  1546 		command = ESelectConfig;
  1547 		}
  1548 	else if(_strnicmp(beg, "NextConfig", end-beg) == 0)
  1549 
  1550 		{
  1551 		command = ENextConfig;
  1552 		}
  1553 	else
  1554 		err = KErrArgument;
  1555 
  1556 	if (err != KErrNone)
  1557 		return err;
  1558 	
  1559 	//get the shape
  1560 	beg = skipws(end);
  1561 	end = skiptok(beg);
  1562 	if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0)
  1563 		return KErrArgument;
  1564 		
  1565 	// get the parameters
  1566 	beg = skipws(end);
  1567 	char* end2;
  1568 	TInt x = strtol(beg, &end2, 10);
  1569 	if (beg == end2 || *end2++ != ',')
  1570 		return KErrArgument;
  1571 	beg = end2;
  1572 	TInt y = strtol(beg, &end2, 10);
  1573 	if (beg == end2)
  1574 		return KErrArgument;
  1575 	beg = skipws(end2);
  1576 	TInt w = strtol(beg, &end2, 10);
  1577 	if (beg == end2 || *end2++ != ',')
  1578 		return KErrArgument;
  1579 	beg = end2;
  1580 	TInt h = strtol(beg, &end2, 10);
  1581 	if (beg == end2)
  1582 		return KErrArgument;
  1583 	
  1584 	VKRect* pRect = new VKRect(data, command, x, y, w, h);
  1585 	if (!pRect)
  1586 		return KErrNoMemory;
  1587 	return iVirtualKeys.Append(pRect);
  1588 
  1589 	}
  1590 
  1591 
  1592 TInt DWinsUi::DoDefineVirtualKey(TAny* aPtr, const char* aValue)
  1593 	{
  1594 	return static_cast<DWinsUi*>(aPtr)->DefineVirtualKey(aValue);
  1595 	}
  1596 
  1597 TInt DWinsUi::DefineVirtualKey(const char* aValue)
  1598 	{
  1599 	// Get the key to map
  1600 	const char* beg = skipws(aValue);
  1601 	const char* end = skiptok(beg);
  1602 	TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, end-beg));
  1603 	if (key == KErrNotFound)
  1604 		return key;
  1605 
  1606 	//get the shape
  1607 	beg = skipws(end);
  1608 	end = skiptok(beg);
  1609 	if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0)
  1610 		return KErrArgument;
  1611 		
  1612 	// get the parameters
  1613 	beg = skipws(end);
  1614 	char* end2;
  1615 	TInt x = strtol(beg, &end2, 10);
  1616 	if (beg == end2 || *end2++ != ',')
  1617 		return KErrArgument;
  1618 	beg = end2;
  1619 	TInt y = strtol(beg, &end2, 10);
  1620 	if (beg == end2)
  1621 		return KErrArgument;
  1622 	beg = skipws(end2);
  1623 	TInt w = strtol(beg, &end2, 10);
  1624 	if (beg == end2 || *end2++ != ',')
  1625 		return KErrArgument;
  1626 	beg = end2;
  1627 	TInt h = strtol(beg, &end2, 10);
  1628 	if (beg == end2)
  1629 		return KErrArgument;
  1630 	
  1631 	VKRect* pRect = new VKRect(key, EKey, x, y, w, h);
  1632 	if (!pRect)
  1633 		return KErrNoMemory;
  1634 	return iVirtualKeys.Append(pRect);
  1635 	}
  1636 
  1637 
  1638 LOCAL_C TInt readBitmapInfo(PBITMAPINFOHEADER aHeader, const char* aFileName)
  1639 	{
  1640 	PBITMAPFILEHEADER pbmfh=NULL;
  1641 	PBITMAPINFOHEADER pbmih=NULL;
  1642 	TInt bfOffBits;
  1643 
  1644 	HANDLE fh=CreateFileA(aFileName,GENERIC_READ,NULL,NULL,OPEN_EXISTING,NULL,NULL);
  1645 	if (!fh || fh==INVALID_HANDLE_VALUE)
  1646 		return KErrNotFound;
  1647 
  1648 	TInt r=KErrNone;
  1649 
  1650 	// read in the bitmap file header.  save the offset to bits.
  1651 	pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER));
  1652 	if (pbmfh==NULL)
  1653 		{
  1654 		r=KErrNotFound;
  1655         goto exit;
  1656 		}
  1657 	DWORD bytesRead;
  1658 	ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER), &bytesRead, NULL);
  1659 	bfOffBits=pbmfh->bfOffBits;
  1660 
  1661 	// read in the bitmap info header and the color table right after it.
  1662 	pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER));
  1663 	if (pbmih==NULL)
  1664 		{
  1665 		r=KErrNotFound;
  1666         goto exit;
  1667 		}
  1668 	ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL);
  1669 	*aHeader=*pbmih;
  1670 exit:
  1671 	LocalFree(LocalHandle ((LPSTR)pbmih));
  1672 	LocalFree(LocalHandle ((LPSTR)pbmfh));
  1673 	CloseHandle(fh);
  1674 	return r;
  1675 	}
  1676 
  1677 HBITMAP readBitmap(HDC aHdc, const char* aFileName)
  1678 //
  1679 // reads a BMP file from disk and returns a HBITMAP
  1680 //
  1681 	{
  1682 	HBITMAP hbm=NULL;
  1683 	PBITMAPFILEHEADER pbmfh=NULL;
  1684 	PBITMAPINFOHEADER pbmih=NULL;
  1685 	TUint8 *pBits=NULL;
  1686 	TInt bfOffBits;
  1687 	TInt nbytes;
  1688 
  1689 	HANDLE fh=CreateFileA(aFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);
  1690 	if (!fh || fh==INVALID_HANDLE_VALUE)
  1691 		return NULL;
  1692 
  1693 	nbytes=GetFileSize((HANDLE)fh, NULL);
  1694 	// read in the bitmap file header.  save the offset to bits.
  1695 	pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER));
  1696 	if (pbmfh==NULL)
  1697         goto exit;
  1698 	DWORD bytesRead;
  1699 	ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER),&bytesRead,NULL);
  1700 	bfOffBits=pbmfh->bfOffBits;
  1701 
  1702 	// read in the bitmap info header and the color table right after it.
  1703 	pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER));
  1704 	if (pbmih==NULL)
  1705         goto exit;
  1706 	ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL);
  1707 
  1708 	// finally read in the bit data.
  1709 	pBits = (PBYTE)LocalAlloc (LPTR, (nbytes - bfOffBits));
  1710 	if (pBits==NULL)
  1711         goto exit;
  1712 	ReadFile(fh, (LPVOID)pBits, nbytes-bfOffBits,&bytesRead,NULL);
  1713 		
  1714 	hbm=CreateDIBitmap(aHdc, pbmih, CBM_INIT, pBits,(PBITMAPINFO) pbmih, DIB_RGB_COLORS);
  1715 exit:
  1716 	LocalFree(LocalHandle ((LPSTR)pBits));
  1717 	LocalFree(LocalHandle ((LPSTR)pbmih));
  1718 	LocalFree(LocalHandle ((LPSTR)pbmfh));
  1719 	CloseHandle(fh);
  1720 	return hbm;
  1721 	}
  1722 
  1723 void LoadFasciaBitmap(TInt aScreen)
  1724 	{
  1725 	HDC hdc=GetDC(TheWin[aScreen]);
  1726 	RECT windowRect = {0};
  1727 	windowRect.right=systemIni->iScreens[aScreen]->iXYInputWidth;
  1728 	windowRect.bottom=systemIni->iScreens[aScreen]->iXYInputHeight;
  1729 	HBITMAP screenBitmap=readBitmap(hdc, systemIni->iScreens[aScreen]->iFasciaFileName);
  1730 	if (screenBitmap==NULL)
  1731 		{
  1732 		screenBitmap=CreateCompatibleBitmap(hdc, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top);
  1733 		HDC hdcMem=CreateCompatibleDC(hdc);
  1734 		SelectObject(hdcMem, screenBitmap);
  1735 		PatBlt(hdcMem, 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, BLACKNESS);
  1736 		DeleteDC(hdcMem);
  1737 		}
  1738 	__ASSERT_ALWAYS(screenBitmap!=NULL,Fault(EGuiCreateBitmap));
  1739 	TheScreenBitmap[aScreen]=screenBitmap;
  1740 
  1741 	DrawLeds();
  1742 
  1743 	ReleaseDC(TheWin[aScreen], hdc);
  1744 	}
  1745 TBool DWinsUi::MultiTouchEnabled() const
  1746 	{
  1747 	return iMultiTouchEnabled;
  1748 	}
  1749 
  1750 TBool DWinsUi::GCEEnabled() const
  1751 	{
  1752 	return iGCEEnabled;
  1753 	}
  1754 
  1755 TInt DWinsUi::MultiTouchProximityStep() const
  1756 	{
  1757 	return iMultiTouchProximityStep;
  1758 	}
  1759 
  1760 TInt DWinsUi::MultiTouchPressureStep() const
  1761 	{
  1762 	return iMultiTouchPressureStep;
  1763 	}
  1764 
  1765 TBool DWinsUi::OnDigitizer(TInt aX, TInt aY) const
  1766 	{
  1767 	if (!iDigitizerEnabled)
  1768 		return EFalse;
  1769 	switch(CurrentFlipState[0])
  1770 		{
  1771 		case EEmulatorFlipRestore:
  1772 			{
  1773 			aX -= iDigitizerOffsetX;
  1774 			aY -= iDigitizerOffsetY;
  1775 			break;
  1776 			}
  1777 		case EEmulatorFlipInvert:
  1778 			{
  1779 			aX -= systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth;
  1780 			aY -= systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight;
  1781 			break;
  1782 			}
  1783 		case EEmulatorFlipRight:
  1784 			{
  1785 			TInt oldY = aY;
  1786 			aY = aX - (systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight);
  1787 			aX = oldY - iDigitizerOffsetX;
  1788 			break;
  1789 			}
  1790 		case EEmulatorFlipLeft:
  1791 			{
  1792 			TInt oldY = aY;
  1793 			aY = aX - iDigitizerOffsetY;
  1794 			aX = oldY - (systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth);
  1795 			break;
  1796 			}
  1797 		}
  1798 	return (TUint(aX) < TUint(iDigitizerWidth) && TUint(aY) < TUint(iDigitizerHeight));
  1799 	}
  1800 
  1801 LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos)
  1802 //
  1803 // Add a mouse event.
  1804 //
  1805 	{
  1806 	if (systemIni->OnDigitizer(aXpos, aYpos))
  1807 		{
  1808 		TRawEvent v;
  1809 		v.Set(aType,aXpos,aYpos);
  1810 		TheEventQ.Add(v);
  1811 		}
  1812 	}
  1813 
  1814 LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos,TInt aZpos, TInt aPointerId=0)
  1815 //
  1816 // Add a multitouch mouse event.
  1817 //
  1818 	{
  1819 	if (systemIni->OnDigitizer(aXpos, aYpos))
  1820 		{
  1821 		TRawEvent v;
  1822 		v.Set(aType,aXpos,aYpos, aZpos);
  1823 		v.SetPointerNumber(static_cast<const TUint8>(aPointerId));
  1824 		TheEventQ.Add(v);
  1825 		}
  1826 	}
  1827 LOCAL_C void addKeyEvent(TRawEvent::TType aType,TInt aKey)
  1828 	{
  1829 	TRawEvent v;
  1830 	v.Set(aType, aKey);
  1831 	TheEventQ.Add(v);
  1832 	}
  1833 
  1834 
  1835 LOCAL_C void SwitchConfiguration(TInt aData, TBool aSendFlipKey = ETrue)
  1836 	{
  1837 	if (aData < 0 || aData >= masterIni->iSystemInis.Count())
  1838 		return;
  1839 
  1840 	CurrentConfiguration = aData;
  1841 	systemIni = masterIni->iSystemInis[aData];
  1842 	
  1843 	//get the correct fascia bitmaps
  1844 	TInt screens=systemIni->iScreens.Count();
  1845 	TInt i;
  1846 	TUint disabledWinType=ENormalResolution;
  1847 	for(i=0;i<screens;i++)
  1848 		{
  1849 		DeleteObject(TheScreenBitmap[i]);
  1850 		LoadFasciaBitmap(i);
  1851 		if (masterIni->iBufferSet[i].iDisplayState!=ENormalResolution)
  1852 			{
  1853 			disabledWinType=masterIni->iBufferSet[i].iDisplayState;
  1854 			}
  1855 		}
  1856 	
  1857 	//update the window title
  1858 	if (disabledWinType!=ENormalResolution && disabledWinType < 4)	//hardwired 4 because the code below is hardwired
  1859 		{	//string may be multi-part indexed by disable type, or it may not
  1860 		CHAR* firstsemi=strchr(systemIni->iWindowTitle,';');
  1861 		CHAR* secondsemi=NULL;
  1862 		if (firstsemi)
  1863 			{
  1864 			secondsemi=strchr(firstsemi+1,';');
  1865 			}
  1866 		if (firstsemi&&secondsemi)
  1867 			{
  1868 			*firstsemi='\0';
  1869 			*secondsemi='\0';
  1870 			char* ptr[4]={0,systemIni->iWindowTitle,firstsemi+1,secondsemi+1};
  1871 			SetWindowTextA(TheControlWin, ptr[disabledWinType]);
  1872 			*firstsemi=';';
  1873 			*secondsemi=';';
  1874 			}
  1875 		else
  1876 			{
  1877 			SetWindowTextA(TheControlWin, systemIni->iWindowTitle);
  1878 			}
  1879 		
  1880 		}
  1881 	else
  1882 		{
  1883 		SetWindowTextA(TheControlWin, systemIni->iWindowTitle);
  1884 		}
  1885 	//resize and repaint the current window anyway.
  1886 	//the text window server doesn't respond to orientation messages
  1887 	for(i=0;i<screens;i++)
  1888 		{
  1889 		InvalidateRect(TheWin[i], NULL, false);
  1890 		SendMessage(TheWin[i], WM_FLIP_MESSAGE, systemIni->iScreens[i]->iScreenRotation,0);
  1891 		}
  1892 
  1893 	//pass on the orientation key to the windows server
  1894 	if (aSendFlipKey)
  1895 		{
  1896 		if (!WinsGuiPowerHandler->iStandby)
  1897 			{
  1898 			addKeyEvent(TRawEvent::EKeyDown, systemIni->iInitialFlipMsg);
  1899 			addKeyEvent(TRawEvent::EKeyUp, systemIni->iInitialFlipMsg);
  1900 			}
  1901 		else
  1902 			{
  1903 			//remember the flip message so we can send it to the window server when we come out of standby
  1904 			SavedFlipMessage = systemIni->iInitialFlipMsg;
  1905 			}
  1906 		}
  1907 	}
  1908 /**
  1909 Sets the specified screen to the given width and height, if available.
  1910 
  1911 The configurations are searched to find a match, taking the display state into
  1912 account. If no configuration is available, the request is ignored.
  1913 
  1914 @param aScreenNumber	the screen index
  1915 @param aWidth 			the desired width
  1916 @param aHeight			the desired height
  1917 **/
  1918 void DMasterIni::SetDisplaySize(TInt aDisplayNumber, TInt aWidth, TInt aHeight)
  1919 	{
  1920 	TInt displayCount = iBufferSet.Count();
  1921 
  1922 	if (aDisplayNumber < 0 || aDisplayNumber >= displayCount)
  1923 		{
  1924 		// Invalid screen number, discard.
  1925 		return;
  1926 		}
  1927 
  1928 	if (iBufferSet[aDisplayNumber].iDisplayState != ENormalResolution)
  1929 		{
  1930 		// No (non-zero) resolutions available, discard.
  1931 		return;
  1932 		}
  1933 
  1934 	TInt count = iSystemInis.Count();
  1935 	TInt index;
  1936 	for (index = 0; index < count; index++)
  1937 		{
  1938 		DWinsUi* newIni = masterIni->iSystemInis[index];
  1939 		DScreenProperties* newProps = newIni->iScreens[aDisplayNumber];
  1940 
  1941 		if (newProps->iScreenWidth == aWidth && newProps->iScreenHeight == aHeight)
  1942 			{
  1943 			// Found a potential match. Check other screens match their current size.
  1944 			if (newIni == systemIni)
  1945 				{
  1946 				// Current configuration, already in use. Nothing to do.
  1947 				break;
  1948 				}
  1949 			
  1950 			TInt display;
  1951 			for (display = 0; display < displayCount; display++)
  1952 				{
  1953 				if (display == aDisplayNumber)
  1954 					{
  1955 					// No need to check the display we are changing
  1956 					continue;
  1957 					}
  1958 
  1959 				DScreenProperties* currentPropsN = systemIni->iScreens[display];
  1960 				DScreenProperties* newPropsN = newIni->iScreens[display];
  1961 				
  1962 				if (newPropsN->iScreenWidth != currentPropsN->iScreenWidth ||
  1963 						newPropsN->iScreenHeight != currentPropsN->iScreenHeight)
  1964 					{
  1965 					// Resolution mismatch, try next configuration.
  1966 					break;
  1967 					}
  1968 				}
  1969 			
  1970 			if (display == displayCount)
  1971 				{
  1972 				// Match found, switch to this configuration and stop. Force
  1973 				// rotation to the same as the current rotation.
  1974 				newProps->iScreenRotation = systemIni->iScreens[aDisplayNumber]->iScreenRotation;
  1975 				SwitchConfiguration(index);
  1976 				break;
  1977 				}
  1978 			}
  1979 		}
  1980 	}
  1981 
  1982 
  1983 void DMasterIni::SetBufferFormat(TInt aDisplayNumber, TUint aAggregateSize, RDisplayChannel::TPixelFormat aPixelFormat)
  1984 	{
  1985 	TInt displayCount = iBufferSet.Count();
  1986 
  1987 	if (aDisplayNumber < 0 || aDisplayNumber >= displayCount)
  1988 		{
  1989 		// Invalid screen number, discard.
  1990 		return;
  1991 		}
  1992 	
  1993 	LPBITMAPV4HEADER info = &iBufferSet[aDisplayNumber].iInfo;
  1994 	
  1995 	// update the bitmap header taking in consideration the new pixel format
  1996 	switch (aPixelFormat)
  1997 		{
  1998 		case EUidPixelFormatXRGB_4444:
  1999 		case EUidPixelFormatARGB_4444:
  2000 			info->bV4BitCount=16;
  2001 			info->bV4V4Compression = BI_BITFIELDS;
  2002 			info->bV4RedMask   = 0x0F00;
  2003 			info->bV4GreenMask = 0x00F0;
  2004 			info->bV4BlueMask  = 0x000F;
  2005 			break;
  2006 		case EUidPixelFormatRGB_565:
  2007 			info->bV4BitCount=16;
  2008 			info->bV4V4Compression = BI_BITFIELDS;
  2009 			info->bV4RedMask   = 0xF800;
  2010 			info->bV4GreenMask = 0x07E0;
  2011 			info->bV4BlueMask  = 0x001F;
  2012 			break;
  2013 		case EUidPixelFormatXRGB_8888:	// Really 32bpp, but top 8 unused
  2014 		case EUidPixelFormatARGB_8888:
  2015 		case EUidPixelFormatARGB_8888_PRE:
  2016 			info->bV4BitCount=32;
  2017 			info->bV4V4Compression = BI_RGB;
  2018 			// Mask is implicit for BI_RGB compression
  2019 			break;
  2020 		default:
  2021 			// We got an error, it seems. Let's ignore the message
  2022 			return;
  2023 		}
  2024 	iBufferSet[aDisplayNumber].iBufferFormat.iPixelFormat = aPixelFormat;
  2025 	
  2026 	// taking advantage of limiting the width and size to KMaxTInt16
  2027 	TInt width = aAggregateSize & 0x0000ffff;
  2028 	TInt height = (aAggregateSize >> 16) & 0x0000ffff;
  2029 
  2030 	// let's deal with the new size just received
  2031 	iBufferSet[aDisplayNumber].iBufferFormat.iSize.iWidth = width;
  2032 	iBufferSet[aDisplayNumber].iBufferFormat.iSize.iHeight = height;
  2033 	
  2034 	// update the bitmap header, taking in consideration the rotation
  2035 	switch (CurrentFlipState[aDisplayNumber])
  2036 		{
  2037 		case EEmulatorFlipRestore:
  2038 		case EEmulatorFlipInvert:
  2039 			info->bV4Width = width;
  2040 			info->bV4Height = -height;
  2041 			break;
  2042 		case EEmulatorFlipLeft:
  2043 		case EEmulatorFlipRight:
  2044 			info->bV4Width = height;
  2045 			info->bV4Height = -width;
  2046 			break;
  2047 		}
  2048 	// finally, update the image size
  2049 	SetImageSize(aDisplayNumber);
  2050 	}
  2051 
  2052 void DMasterIni::SetImageSize(TInt aScreenNumber)
  2053 	{
  2054 	TInt displayCount = iBufferSet.Count();
  2055 
  2056 	if (aScreenNumber >= 0 && aScreenNumber < displayCount)
  2057 		{
  2058 		LPBITMAPV4HEADER info = &iBufferSet[aScreenNumber].iInfo;
  2059 		TInt bpp = _ALIGN_UP(info->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32
  2060 		TInt widthInBpp = info->bV4Width * bpp;
  2061 		//rounding to 32 bits (4 octets) and converting, then, bits to octets;
  2062 		TInt scanLineInBytes = _ALIGN_UP(widthInBpp, 32) >> 3;
  2063 		// info->bV4Height is negative or zero
  2064 		info->bV4SizeImage = -info->bV4Height * scanLineInBytes;
  2065 		}
  2066 	}
  2067 
  2068 LOCAL_C void NextConfiguration()
  2069 	{
  2070 	TInt config = CurrentConfiguration;
  2071 	if (++config == masterIni->iSystemInis.Count())
  2072 		config = 0;
  2073 	SwitchConfiguration(config);
  2074 	}
  2075 
  2076 
  2077 
  2078 LOCAL_C TBool ProcessedByEmulatorKey(TInt aScanCode, HWND hWnd,TUint message,TUint wParam,TUint lParam)
  2079 	{
  2080 
  2081 	TBool rVal = EFalse;
  2082 	rVal = ETrue;
  2083 	for (TInt i=0;i<systemIni->iControlHotKeys.Count();i++)//check key combinations
  2084 		{
  2085 		if (systemIni->iControlHotKeys[i]->CheckCombinationPressed()) 
  2086 			{				
  2087 			switch (systemIni->iControlHotKeys[i]->iCommand)
  2088 				{
  2089 				
  2090 				case ENextConfig:
  2091 					NextConfiguration();
  2092 					break;
  2093 		
  2094 				case ESelectConfig:
  2095 					SwitchConfiguration(systemIni->iControlHotKeys[i]->iData);
  2096 					break;
  2097 							
  2098 				}
  2099 			return ETrue;
  2100 			}
  2101 		}
  2102 	switch (aScanCode)
  2103 	{
  2104 	
  2105 	case EStdKeyF4:
  2106 		{
  2107 		// Simulate a change of media card
  2108 		TInt irq = NKern::DisableAllInterrupts();
  2109 		if (*Wins::MediaDoorOpenPtr())
  2110 			{
  2111 			*Wins::CurrentPBusDevicePtr() += 1;
  2112 			if (*Wins::CurrentPBusDevicePtr() == 2)
  2113 				{
  2114 				*Wins::CurrentPBusDevicePtr() = -1;
  2115 				}
  2116 			}
  2117 		NKern::RestoreInterrupts(irq);
  2118 		
  2119 		// pass on to the windows system so that if
  2120 		// Alt-F4 is pressed the window will close
  2121 		if (hWnd)
  2122 			DefWindowProcA(hWnd,message,wParam,lParam);
  2123 		break;
  2124 		}
  2125 
  2126 	default:
  2127 		rVal = EFalse;
  2128 		break;
  2129 	}
  2130 	return rVal;
  2131 	}
  2132 
  2133 LOCAL_C void MultiChildWndPointer(TUint aMessage,TInt aXpos,TInt aYpos, TInt aZ, TInt aPointerId)
  2134 //
  2135 // Handle a multi-touch pointer event in the Symbian OS screen window 
  2136 //
  2137 	{
  2138 	TRawEvent::TType eventType=TRawEvent::ENone;
  2139 	CHAR buf[50];
  2140 	
  2141 	if (aZ <= TheMultiTouch->iZMaxRange) //negative
  2142 		{
  2143 		eventType = TRawEvent::EPointer3DOutOfRange;
  2144 		wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("Out Of Range"));
  2145 		SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf));					
  2146 		}
  2147 	else 
  2148 		{
  2149 		wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("%d: %d,%d,%d"), aPointerId, aXpos,aYpos,aZ);
  2150 		SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf));					
  2151 		switch (aMessage)
  2152 	    	{
  2153 			case WM_MOUSEMOVE:
  2154 				{
  2155 				eventType=TRawEvent::EPointerMove;
  2156 				break;
  2157 				}
  2158 			case WM_LBUTTONDOWN:
  2159 				{
  2160 				SetCapture(TheChildWin[0]);
  2161 				eventType = TRawEvent::EButton1Down;
  2162 				}
  2163 				break;
  2164 			case WM_LBUTTONUP:
  2165 				{
  2166 				ReleaseCapture();
  2167 				eventType = TRawEvent::EButton1Up;
  2168 				break;
  2169 				}
  2170 			case WM_RBUTTONDOWN:
  2171 				{
  2172 				eventType = TRawEvent::EButton3Down;
  2173 				break;
  2174 				}
  2175 			case WM_RBUTTONUP:
  2176 				{
  2177 				eventType = TRawEvent::EButton3Up;
  2178 				break;
  2179 				}
  2180 			case WM_MOUSEWHEEL:
  2181 				{
  2182 				eventType = TRawEvent::EPointerMove;
  2183 				break;
  2184 				}
  2185 			default:
  2186 				return;
  2187 			}
  2188 		}
  2189 
  2190 	if (!WinsGuiPowerHandler->iStandby)
  2191 		{
  2192 		addMouseEvent(eventType, aXpos, aYpos, aZ, aPointerId);
  2193 		}
  2194 	}
  2195 
  2196 LOCAL_C void ChildWndPointer(TUint message,TInt aXpos,TInt aYpos)
  2197 //
  2198 // Handle a pointer event in the Symbian OS screen window
  2199 //
  2200 	{
  2201 	// Enable the multitouch if the cursor is inside the main client window
  2202 	if (DMultiTouch::iMultiTouchCreated)
  2203 		{
  2204 		RECT client;
  2205 		WINDOWINFO info;
  2206 		GetWindowInfo(TheChildWin[0], &info);
  2207 		POINT pt = {aXpos+(TInt)info.rcClient.left, aYpos+(TInt)info.rcClient.top};
  2208 		if (GetWindowRect(TheChildWin[0], &client) &&
  2209 				(PtInRect(&client,pt)!=NULL) && !DMultiTouch::iMultiTouchTempEnabled)	// within the window
  2210 			{
  2211 			if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled())
  2212 				{
  2213 				if(TheMultiTouch->Register())	// Register successfully
  2214 					{
  2215 					DMultiTouch::iMultiTouchTempEnabled = TRUE;
  2216 					//Show the status bars at the bottom of the emulator
  2217 					SetWindowPos(hwndStatus,0,0,0,0,0,SWP_SHOWWINDOW);
  2218 					SetFocus(TheWin[0]);
  2219 					SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512)));
  2220 					}
  2221 				}
  2222 			}
  2223 		}
  2224 	TRawEvent::TType eventType=TRawEvent::ENone;
  2225 	switch (message)
  2226     	{
  2227 	case WM_MOUSEMOVE:
  2228 		eventType=TRawEvent::EPointerMove;
  2229 		break;
  2230 	case WM_LBUTTONDOWN:
  2231 		{
  2232 		SetCapture(TheChildWin[0]);
  2233 		eventType=TRawEvent::EButton1Down;
  2234 		}
  2235 		break;
  2236 	case WM_LBUTTONUP:
  2237 		ReleaseCapture();
  2238 		eventType=TRawEvent::EButton1Up;
  2239 		break;
  2240 	case WM_RBUTTONDOWN:
  2241 		eventType=TRawEvent::EButton3Down;
  2242 		break;
  2243 	case WM_RBUTTONUP:
  2244 		eventType=TRawEvent::EButton3Up;
  2245 		break;
  2246 	case WM_MBUTTONDOWN:
  2247 		eventType=TRawEvent::EButton2Down;
  2248 		break;
  2249 	case WM_MBUTTONUP:
  2250 		eventType=TRawEvent::EButton2Up;
  2251 		break;
  2252 		}
  2253 	if (!WinsGuiPowerHandler->iStandby)
  2254 		{
  2255 		addMouseEvent(eventType, aXpos, aYpos);
  2256 		}
  2257 	}
  2258 
  2259 LOCAL_C void FrameWndPointer(TUint message,TInt aXpos,TInt aYpos, TInt aScreenNumber, TInt aPointerId = 0)
  2260 //
  2261 // Handle a frame wnd pointer event.
  2262 //
  2263 	{
  2264 	static bool	processingScreenOn=FALSE;
  2265 	TEmulCommand command = ENoCommand;
  2266 	TInt commandData = 0;
  2267 	TBool mouseEvent = ETrue;
  2268 	
  2269 	TRawEvent::TType eventType=TRawEvent::ENone;
  2270 	
  2271 	TViewport& viewport = systemIni->iScreens[aScreenNumber]->iViewport;
  2272 	aXpos += viewport.GetViewportOffsetX(); // make mouse-coords relative to fascia edge even if window is scrolled
  2273 	aYpos += viewport.GetViewportOffsetY();
  2274 	
  2275 	switch (message)
  2276     	{
  2277 	case WM_MOUSEMOVE:
  2278 		{
  2279 		TInt newX, newY;
  2280 		systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY);
  2281 
  2282 		if (aPointerId == 0)
  2283 			{ // only system pointer changes shape
  2284 		if (systemIni->GetVirtualKey(command, newX, newY) >= 0)
  2285 			{
  2286 			HMODULE hmodule = GetModuleHandleA("winsgui.dll");
  2287 			SetCursor(LoadCursorA((HINSTANCE)hmodule,MAKEINTRESOURCEA(OVERKEY)));		//hand cursor
  2288 			}
  2289 		else
  2290 			SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512))); //ICD_ARROW
  2291 				}
  2292 
  2293 		eventType=TRawEvent::EPointerMove;
  2294 		
  2295 		}
  2296 		break;
  2297 	case WM_LBUTTONDOWN:
  2298 		{
  2299 		SetCapture(TheWin[0]);
  2300 		//check the configuration
  2301 		TInt newX, newY;
  2302 		
  2303 		//if the emulator screen is rotated, rotate/flip the current mouse cursor position
  2304 		//so it can be checked to see if it is in a key region.
  2305 		systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY);
  2306 		commandData = systemIni->GetVirtualKey(command, newX, newY);
  2307 		
  2308 		if (commandData >= 0)
  2309 			{
  2310 			eventType=TRawEvent::EKeyDown;
  2311 			mouseEvent = EFalse;
  2312 			systemIni->SetVirtualKey(ETrue, commandData, command);
  2313 			}
  2314 		else
  2315 			eventType=TRawEvent::EButton1Down;
  2316 		}
  2317 		break;
  2318 	case WM_LBUTTONUP:
  2319 		ReleaseCapture();
  2320 		if (processingScreenOn)
  2321 			{
  2322 			// ignore button up - button down was switching things on
  2323 			processingScreenOn=FALSE;
  2324 			return;
  2325 			}
  2326 		if (systemIni->WasVirtualKey(commandData, command))
  2327 			{
  2328 			eventType=TRawEvent::EKeyUp;
  2329 			mouseEvent = EFalse;
  2330 			systemIni->SetVirtualKey(EFalse, EStdKeyNull, ENoCommand);
  2331 			}
  2332 		else
  2333 			eventType=TRawEvent::EButton1Up;
  2334 		break;
  2335 	case WM_RBUTTONDOWN:
  2336 		eventType=TRawEvent::EButton3Down;
  2337 		break;
  2338 	case WM_RBUTTONUP:
  2339 		eventType=TRawEvent::EButton3Up;
  2340 		break;
  2341 	case WM_MBUTTONDOWN:
  2342 		eventType=TRawEvent::EButton2Down;
  2343 		break;
  2344 	case WM_MBUTTONUP:
  2345 		eventType=TRawEvent::EButton2Up;
  2346 		break;
  2347 		}
  2348 	if (mouseEvent)
  2349 		{
  2350 		
  2351 		if (!WinsGuiPowerHandler->iStandby)
  2352 			{
  2353 			/*
  2354 			mouse events are relative to the child window position
  2355 			and are clipped to the digitzer region in addMouseEvent
  2356 			so all the mouse clicks are passed on here after being translated 
  2357 			to the child window coordinate system (under the current rotation)
  2358 			*/
  2359 			TInt newX, newY;
  2360 			switch (CurrentFlipState[0])
  2361 				{
  2362 				case EEmulatorFlipRestore:
  2363 				default:
  2364 					newX = aXpos - systemIni->iScreens[0]->iScreenOffsetX;
  2365 					newY = aYpos - systemIni->iScreens[0]->iScreenOffsetY;
  2366 					break;
  2367 				case EEmulatorFlipInvert:
  2368 					newX = aXpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX);
  2369 					newY = aYpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY);
  2370 					break;
  2371 				case EEmulatorFlipLeft:
  2372 					newX = aXpos - systemIni->iScreens[0]->iScreenOffsetY;
  2373 					newY = aYpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX);
  2374 					break;	
  2375 				case EEmulatorFlipRight:
  2376 					newX = aXpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY);
  2377 					newY = aYpos - systemIni->iScreens[0]->iScreenOffsetX;
  2378 					break;
  2379 				}
  2380 			addMouseEvent(eventType, newX, newY);
  2381 			}
  2382 		}
  2383 	else if ((((message == WM_LBUTTONDOWN && command == EKey) && !ProcessedByEmulatorKey((TUint8)commandData,0,0,0,0)))
  2384 			|| (message == WM_LBUTTONUP))
  2385 		{
  2386 			switch (command)
  2387 			{
  2388 			case EKey:
  2389 				if (!WinsGuiPowerHandler->iStandby)
  2390 					addKeyEvent(eventType, (TUint8)commandData);
  2391 				break;
  2392 
  2393 			case ENextConfig:
  2394 				NextConfiguration();
  2395 				break;
  2396 			
  2397 			case ESelectConfig:
  2398 				SwitchConfiguration(commandData);
  2399 				break;
  2400 			}
  2401 		}
  2402 	}
  2403 
  2404 LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin)
  2405 	{
  2406 	TInt screens=systemIni->iScreens.Count();
  2407 	TInt r=-1;
  2408 	for(TInt i=0;i<screens;i++)
  2409 		{
  2410 		if(pWin[i]==aHwnd)
  2411 			{
  2412 			r=i;
  2413 			break;
  2414 			}
  2415 		}
  2416 	return r;
  2417 	}
  2418 void MultiTouchWndPointer(TUint message,TInt aXpos,TInt aYpos, TInt aZ, TInt aPointerId)
  2419 	{
  2420 	WINDOWINFO info;
  2421 	info.cbSize = sizeof(WINDOWINFO);
  2422 	if (GetWindowInfo(TheWin[0], &info))
  2423 		{
  2424 		POINT pt = {aXpos,aYpos};
  2425 		if (PtInRect(&info.rcWindow,pt))
  2426 			{
  2427 			RECT client;
  2428 			if (GetWindowRect(TheChildWin[0], &client) && PtInRect(&client,pt))	// within the window
  2429 				{
  2430 				MultiChildWndPointer(message, aXpos-client.left, aYpos-client.top, aZ, aPointerId);
  2431 				}
  2432 			else  
  2433 				{		
  2434 				//	Disable the multitouch if the cursor is outside the application window
  2435 				if (DMultiTouch::iMultiTouchTempEnabled)	// within the window
  2436 					{
  2437 					DMultiTouch::iMultiTouchTempEnabled = FALSE;
  2438 					if(TheMultiTouch->UnRegister())
  2439 						{
  2440 						SetWindowPos(hwndStatus,0,0,0,0,0,SWP_HIDEWINDOW);
  2441 						}
  2442 					}
  2443 				FrameWndPointer(message, aXpos-info.rcClient.left, aYpos-info.rcClient.top, 0, aPointerId);	
  2444 				}
  2445 			}
  2446 		}
  2447 	}
  2448 
  2449 LOCAL_C DScreenProperties* ScreenPropsFromHWND(HWND aHwnd, HWND* pWin)
  2450 	{
  2451 	TInt screenNumber =  ScreenFromHWND(aHwnd, pWin);
  2452 	
  2453 	if(screenNumber >=0)
  2454 		{
  2455 		return systemIni->iScreens[screenNumber];
  2456 		}
  2457 	return NULL;
  2458 
  2459 	}
  2460 
  2461 
  2462 TInt APIENTRY childWinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam)
  2463 //
  2464 // The child window function.
  2465 //
  2466 	{
  2467 	TInt screenNumber = 0;
  2468 	TRawEvent v;
  2469     switch (message)
  2470     	{
  2471 	case WM_FLIP_MESSAGE: // pass the flip message onto the parent window
  2472 		{
  2473 		screenNumber =ScreenFromHWND(hWnd,TheChildWin);
  2474 		if(TUint(screenNumber) < TUint(systemIni->iScreens.Count()))
  2475 			PostMessageA(TheWin[screenNumber],WM_FLIP_MESSAGE,wParam,NULL);
  2476 		break;
  2477 		}
  2478 	case WM_LBUTTONDOWN:
  2479 	case WM_LBUTTONUP:
  2480 	case WM_MOUSEMOVE:
  2481 	case WM_RBUTTONDOWN:
  2482 	case WM_RBUTTONUP:
  2483 	case WM_MBUTTONDOWN:
  2484 	case WM_MBUTTONUP:
  2485 		{
  2486 		if (DMultiTouch::iMultiTouchTempEnabled)
  2487 			{
  2488 			DMultiTouch::iMultiTouchTempEnabled = FALSE;
  2489 			}
  2490 		screenNumber=ScreenFromHWND(hWnd,TheChildWin);
  2491 		if(screenNumber==0)
  2492 			{
  2493 			ChildWndPointer(message,(TInt16)(lParam&0xFFFF),(TInt16)((lParam>>16)&0xFFFF));
  2494 			}
  2495 		break;
  2496 		}
  2497     case WM_PAINT:
  2498 		if (!PaintWindowFromBuffer(hWnd))
  2499 			{
  2500 			// Original behaviour
  2501 			ValidateRect(hWnd,NULL);
  2502 			v.Set(TRawEvent::ERedraw);
  2503 			TheEventQ.Add(v);
  2504 			}
  2505         break;
  2506     case WM_ACTIVATE:
  2507 	case WM_SYSKEYDOWN:
  2508 	case WM_KEYDOWN:
  2509 	case WM_SYSKEYUP:
  2510 	case WM_KEYUP:
  2511 		Fault(EGuiChildWinProc);
  2512 		break;
  2513     case WM_DESTROY:
  2514 		break;
  2515 
  2516 	case WM_CHAR:
  2517 	case WM_SYSCHAR:
  2518 	case WM_DEADCHAR:
  2519 	case WM_SYSDEADCHAR:
  2520         break;
  2521 
  2522 	case WMU_SET_DISPLAY_BUFFER:
  2523 		screenNumber = ScreenFromHWND(hWnd, TheChildWin);
  2524 		if (TUint(screenNumber) < TUint(systemIni->iScreens.Count()))
  2525 			{
  2526 			masterIni->iBufferSet[screenNumber].iDisplayBuffer = (LPVOID)lParam;
  2527 			}
  2528 		break;
  2529 	case WMU_SET_DISPLAY_SIZE:
  2530 		screenNumber = ScreenFromHWND(hWnd, TheChildWin);
  2531 		masterIni->SetDisplaySize(screenNumber, wParam, lParam);
  2532 		break;
  2533 		
  2534 	case WMU_SET_BUFFER_FORMAT:
  2535 		screenNumber = ScreenFromHWND(hWnd, TheChildWin);
  2536 		masterIni->SetBufferFormat(screenNumber, wParam, (RDisplayChannel::TPixelFormat) lParam);
  2537 		break;
  2538 		
  2539  	default:
  2540         return(DefWindowProcA(hWnd,message,wParam,lParam));
  2541 	    }
  2542     return(FALSE);
  2543 	}
  2544 
  2545 
  2546 LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd)
  2547 	{
  2548 	TInt screenNumber = ScreenFromHWND(hWnd,TheChildWin);
  2549 	if (TUint(screenNumber) >= TUint(masterIni->iBufferSet.Count()))
  2550 		{
  2551 		return EFalse;
  2552 		}
  2553 
  2554 	LPVOID displayBuffer = masterIni->iBufferSet[screenNumber].iDisplayBuffer;
  2555 	if (!displayBuffer)
  2556 		{
  2557 		return EFalse;
  2558 		}
  2559 
  2560 	TInt   frameOffset = masterIni->iBufferSet[screenNumber].iScreenBuffer.iDisplayBufferOffset;
  2561 	displayBuffer=LPVOID(frameOffset+(char*)displayBuffer);
  2562 
  2563 	PAINTSTRUCT ps;
  2564 	BeginPaint(hWnd, &ps);
  2565 
  2566 	// Paint directly from the buffer to the window
  2567 	LPBITMAPINFO info = (LPBITMAPINFO)&masterIni->iBufferSet[screenNumber].iInfo;
  2568 	WORD width = (WORD)info->bmiHeader.biWidth;
  2569 	WORD height = (WORD)-info->bmiHeader.biHeight;	// stored -ve in info
  2570 	SetDIBitsToDevice(ps.hdc,
  2571 						0, 0, 	// Dst X, Y
  2572 						width, height,	// Src W, H
  2573 						0, 0,	// Src X, Y
  2574 						0,		// Src offset to first line
  2575 						height,	// Src lines available
  2576 						displayBuffer,	// Src pointer to pixels
  2577 						info,			// Src info
  2578 						DIB_RGB_COLORS);
  2579 
  2580 	EndPaint(hWnd, &ps);
  2581 
  2582 	return TRUE;
  2583 	}
  2584 
  2585 
  2586 LOCAL_C void CalcTextPos(TInt aScreen, TInt& aX, TInt& aY)
  2587 	{
  2588 	switch (CurrentFlipState[aScreen])
  2589 		{
  2590 	case EEmulatorFlipInvert:
  2591 		aX = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth);
  2592 		aY = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight);
  2593 		break;
  2594 	case EEmulatorFlipLeft:
  2595 		aX = systemIni->iScreens[aScreen]->iScreenOffsetY;
  2596 		aY = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth);
  2597 		break;
  2598 	case EEmulatorFlipRight:
  2599 		aX = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight);
  2600 		aY = systemIni->iScreens[aScreen]->iScreenOffsetX;
  2601 		break;
  2602 	case EEmulatorFlipRestore:
  2603 	default:
  2604 		aX = systemIni->iScreens[aScreen]->iScreenOffsetX;
  2605 		aY = systemIni->iScreens[aScreen]->iScreenOffsetY;
  2606 	break;
  2607 		}
  2608 	//subtract viewport offset here
  2609 	aX -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetX();
  2610 	aY -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetY();
  2611 	}
  2612 
  2613 TInt APIENTRY ctrlwinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam)
  2614 //
  2615 // The control window function
  2616 //
  2617 	{
  2618 	switch(message)
  2619 	{
  2620 		case WM_SYSCOMMAND:
  2621 			{
  2622 				switch(wParam)
  2623 				{
  2624 					case 1:
  2625 						{
  2626 						NextConfiguration();
  2627 						return 0;
  2628 						}
  2629 					case SC_MINIMIZE:
  2630 					case SC_RESTORE:
  2631 						{
  2632 						if (wParam == SC_RESTORE) 
  2633 							Active();
  2634 						for(TInt ix=0;ix<systemIni->iScreens.Count();ix++)
  2635 							{
  2636 							SendMessage(TheWin[ix],message,wParam,lParam);
  2637 							}
  2638 						if (wParam == SC_MINIMIZE) 
  2639 							Inactive();
  2640 						}			
  2641 				}
  2642 				return(DefWindowProcA(hWnd,message,wParam,lParam));
  2643 			}
  2644 		case WM_CLOSE: // tell all emulator screen windows to close
  2645 			{
  2646 			for(TInt i=0;i<systemIni->iScreens.Count();i++)
  2647 				{
  2648 				DestroyWindow(TheWin[i]);
  2649 				}
  2650 			DestroyWindow(hWnd);
  2651 			break;
  2652 			}
  2653 		case WM_DESTROY:
  2654 			{
  2655 			// save the main window position information
  2656 			HANDLE hSysIni;
  2657 			hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
  2658 			DScreenProperties* screenProps;
  2659 			if (hSysIni != INVALID_HANDLE_VALUE)
  2660 				{
  2661 				DWORD numWritten;
  2662 				//write an identifier into file so that program can avoid loading old version
  2663 				WriteFile(hSysIni, &KDatFileVersion, sizeof(TInt), &numWritten, 0);
  2664 				
  2665 				//record current configuration at start of file.
  2666 				WriteFile(hSysIni, &CurrentConfiguration, sizeof(TInt), &numWritten, 0);
  2667 				
  2668 				//Write out the state for each window.
  2669 				for(TInt i=0;i<systemIni->iScreens.Count();i++)
  2670 					{
  2671 					screenProps= systemIni->iScreens[i];
  2672 					
  2673 					TWindowState winState= screenProps->GetWindowState();
  2674 					WriteFile(hSysIni, &winState, sizeof(TWindowState), &numWritten, 0);
  2675 					
  2676 					
  2677 					}
  2678 				}
  2679 			CloseHandle(hSysIni);
  2680 
  2681 			PostQuitMessage(KErrNone);
  2682 			break;
  2683 			}
  2684 		case WM_INPUT:
  2685 			{
  2686 			if (!DMultiTouch::iMultiTouchTempEnabled)
  2687 				{
  2688 				for(TInt ix=0;ix<systemIni->iScreens.Count();ix++)
  2689 					{
  2690 					DMultiTouch::iMultiTouchTempEnabled = TRUE;
  2691 
  2692 					SendMessage(TheWin[ix],message,wParam,lParam);
  2693 					}
  2694 				}
  2695 			else if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled())
  2696 				{
  2697 			   	TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[0]);	
  2698 				}
  2699 			else
  2700 				{
  2701 				Fault(EGuiInvalidMultiTouch);
  2702 				}
  2703 		   	break;
  2704 			}	
  2705 		default:
  2706 			return(DefWindowProcA(hWnd,message,wParam,lParam));
  2707 	}
  2708 	return(FALSE);
  2709 	}
  2710 
  2711 TInt APIENTRY winProc(HWND hWnd,TUint message,TUint wParam,TUint lParam)
  2712 //
  2713 // The border window function.
  2714 //
  2715 	{
  2716 
  2717 	TRawEvent v;
  2718 	
  2719 	switch (message)
  2720     	{
  2721 		case WM_GETMINMAXINFO:
  2722 			{
  2723 			DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  2724 			if(screenProps == NULL)
  2725 				{
  2726 				return DefWindowProcA(hWnd, message, wParam, lParam);
  2727 				}
  2728 						
  2729 			MINMAXINFO* minMaxInfo = reinterpret_cast<MINMAXINFO*>(lParam);
  2730 			minMaxInfo->ptMaxTrackSize.x = screenProps->iViewport.GetMaxWindowWidth();
  2731 			minMaxInfo->ptMaxTrackSize.y = screenProps->iViewport.GetMaxWindowHeight();
  2732 
  2733 			minMaxInfo->ptMaxSize.x = minMaxInfo->ptMaxTrackSize.x;
  2734 			minMaxInfo->ptMaxSize.y = minMaxInfo->ptMaxTrackSize.y;
  2735 			DefWindowProcA(hWnd, message, wParam, lParam);
  2736 			
  2737 			break;
  2738 			}
  2739 	   
  2740     	    		
  2741  	    	
  2742     	case WM_SIZE:
  2743     		{
  2744     		DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  2745 			if(screenProps == NULL)
  2746 				{
  2747 				return DefWindowProcA(hWnd, message, wParam, lParam);
  2748 				}
  2749     		TViewport& viewport = screenProps->iViewport;
  2750     		//update size of viewport
  2751     		viewport.SetViewportWidth(LOWORD(lParam));
  2752     		viewport.SetViewportHeight(HIWORD(lParam));
  2753     		
  2754     		
  2755 			//If resize goes beyond boundary of emulator then scroll to compensate
  2756 			TInt ox = viewport.GetViewportOffsetX();
  2757     		TInt xs = ox + LOWORD(lParam) - viewport.GetMaxWidth();
  2758     		if (xs>0) 
  2759     			{    			
  2760     			viewport.ScrollToX(ox-xs, hWnd);
  2761     			}
  2762     		
  2763     		TInt oy = viewport.GetViewportOffsetY();
  2764     		TInt ys = oy + HIWORD(lParam) - viewport.GetMaxHeight();
  2765     		if (ys>0) 
  2766     			{    			
  2767     			viewport.ScrollToY(oy-ys, hWnd);
  2768     			}
  2769     	
  2770     		//Adjust ranges of scroll bars
  2771     	   	viewport.UpdateScrollBarH(hWnd);
  2772     		viewport.UpdateScrollBarV(hWnd);
  2773     		    		
  2774     		
  2775     		
  2776     		break;    		
  2777     		}
  2778     	case WM_HSCROLL:
  2779     		{
  2780     		DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  2781 			if(screenProps == NULL)
  2782 				{
  2783 				return DefWindowProcA(hWnd, message, wParam, lParam);
  2784 				}
  2785     		TViewport& viewport = screenProps->iViewport;
  2786     		
  2787     		switch (LOWORD(wParam)) 
  2788     			{
  2789     			case SB_THUMBTRACK:
  2790     				{
  2791     				viewport.ScrollToX(HIWORD(wParam),hWnd);
  2792     				break;
  2793     				}
  2794 				case SB_PAGELEFT:
  2795 					{
  2796 					viewport.ScrollToX(viewport.GetViewportOffsetX() - viewport.GetViewportWidth(), hWnd );
  2797 					break;
  2798 					}
  2799 				case SB_PAGERIGHT:
  2800 					{
  2801 					viewport.ScrollToX(viewport.GetViewportOffsetX() + viewport.GetViewportWidth() , hWnd);
  2802 					break;
  2803 					}
  2804 				case SB_LINEUP:
  2805 					{
  2806 					viewport.ScrollToX(viewport.GetViewportOffsetX() - 1, hWnd);
  2807 					break;
  2808 					}
  2809 				case SB_LINEDOWN:
  2810 					{
  2811 					viewport.ScrollToX(viewport.GetViewportOffsetX() + 1, hWnd);
  2812 					break;
  2813 					}
  2814     			
  2815     			}
  2816     		   		
  2817    
  2818     		break;
  2819     		}
  2820     	
  2821     	case WM_VSCROLL:
  2822     		{
  2823     		DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  2824 			if(screenProps == NULL)
  2825 				{
  2826 				return DefWindowProcA(hWnd, message, wParam, lParam);
  2827 				}
  2828     		TViewport& viewport = screenProps->iViewport;
  2829     		
  2830 			
  2831 			switch (LOWORD(wParam)) 
  2832     			{
  2833     			case SB_THUMBTRACK:
  2834     				{
  2835     				viewport.ScrollToY(HIWORD(wParam), hWnd);
  2836     				break;
  2837     				}
  2838 				case SB_PAGELEFT:
  2839 					{
  2840 					viewport.ScrollToY(viewport.GetViewportOffsetY() - viewport.GetViewportHeight() , hWnd);
  2841 					break;
  2842 					}
  2843 				case SB_PAGERIGHT:
  2844 					{
  2845 					viewport.ScrollToY(viewport.GetViewportOffsetY() + viewport.GetViewportHeight(), hWnd );
  2846 					break;
  2847 					}
  2848 				case SB_LINEUP:
  2849 					{
  2850 					viewport.ScrollToY(viewport.GetViewportOffsetY() - 1, hWnd);
  2851 					break;
  2852 					}
  2853 				case SB_LINEDOWN:
  2854 					{
  2855 					viewport.ScrollToY(viewport.GetViewportOffsetY() + 1, hWnd);
  2856 					break;
  2857 					}
  2858     			
  2859     			}
  2860     		
  2861     		break;
  2862     		
  2863     		}
  2864     	
  2865     	 		
  2866 		case WM_FLIP_MESSAGE:
  2867 			{
  2868 			DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  2869 			if(screenProps == NULL)
  2870 				{
  2871 				return DefWindowProcA(hWnd, message, wParam, lParam);
  2872 
  2873 				}
  2874 			
  2875 			TViewport& viewport = screenProps->iViewport;
  2876 			RECT windowRect={0,0,0,0};
  2877 			GetClientRect(hWnd, &windowRect);
  2878 			
  2879 			TInt screenNumber=ScreenFromHWND(hWnd,TheWin);
  2880 			if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count()))
  2881 				break;
  2882 			PBITMAPV4HEADER info = &masterIni->iBufferSet[screenNumber].iInfo;
  2883 			CurrentFlipState[screenNumber]=(TEmulatorFlip)wParam;
  2884 			TBufferSet* bufferSet = &masterIni->iBufferSet[screenNumber];
  2885 			switch (CurrentFlipState[screenNumber])
  2886 				{
  2887 				case EEmulatorFlipRestore:
  2888 				case EEmulatorFlipInvert:
  2889 					windowRect.right=systemIni->iScreens[screenNumber]->iXYInputWidth;
  2890 					windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputHeight;
  2891 					info->bV4Width = bufferSet->iBufferFormat.iSize.iWidth;
  2892 					info->bV4Height = -bufferSet->iBufferFormat.iSize.iHeight;
  2893 					break;
  2894 				case EEmulatorFlipLeft:
  2895 				case EEmulatorFlipRight:
  2896 					windowRect.right=systemIni->iScreens[screenNumber]->iXYInputHeight;
  2897 					windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputWidth;
  2898 					info->bV4Width = bufferSet->iBufferFormat.iSize.iHeight;
  2899 					info->bV4Height = -bufferSet->iBufferFormat.iSize.iWidth;
  2900 					break;
  2901 				}
  2902 			AdjustWindowRect(&windowRect,KWinStyle,FALSE);
  2903     		
  2904     		
  2905 			viewport.ScrollToX(0, hWnd);
  2906 			viewport.ScrollToY(0, hWnd);
  2907 
  2908 			
  2909 			screenProps->iScreenRotation = (TEmulatorFlip)wParam; 
  2910 			
  2911 						
  2912 			RECT currentWindowRect;
  2913 			GetWindowRect(hWnd,&currentWindowRect);
  2914 			InvalidateRect(hWnd,NULL,FALSE);
  2915 			MoveWindow(
  2916 				TheWin[screenNumber],
  2917 				max(currentWindowRect.left,0), // so the window doesn't disappear off the screen
  2918 				max(currentWindowRect.top,0),
  2919 				windowRect.right-windowRect.left,
  2920 				windowRect.bottom-windowRect.top,
  2921 				TRUE
  2922 				);
  2923 			// move the child window
  2924 			screenProps->iViewport.UpdateChildPos(hWnd);
  2925 			
  2926 			viewport.UpdateScrollBarH(hWnd);
  2927     		viewport.UpdateScrollBarV(hWnd);
  2928 
  2929 			InvalidateRect(hWnd,NULL,TRUE);
  2930 			UpdateWindow(hWnd);
  2931 			
  2932 			break;
  2933 			}
  2934 		case WM_SYSKEYDOWN:
  2935 		case WM_KEYDOWN:
  2936 			if (!(HIWORD(lParam)&KF_REPEAT))
  2937 				{
  2938 				
  2939 				
  2940 				TUint scanCode=DWinsKeyboard::ScanCodeToStandardKey(HIWORD(lParam));
  2941 				TUint newScanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam));
  2942 				MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()};
  2943 				TranslateMessage(&msg);
  2944 				TUint charCode=0;
  2945 				// look in the message queue to get character associated with keypress
  2946 				// so long as the control, shift and alt keys aren't depressed
  2947 				if (!(HIBYTE(GetKeyState(VK_CONTROL)) && HIBYTE(GetKeyState(VK_MENU)) && HIBYTE(GetKeyState(VK_SHIFT))))
  2948 					if (PeekMessageA(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE) &&
  2949 						scanCode == newScanCode) //no remapping
  2950 						charCode=msg.wParam;
  2951 				// Pass the character as the HIWORD of the Epoc scan code
  2952 				
  2953 				scanCode = newScanCode;
  2954 				v.Set(TRawEvent::EKeyDown,(charCode<<16)|scanCode);
  2955 				if (!ProcessedByEmulatorKey(scanCode,hWnd,message,wParam,lParam))
  2956    					TheEventQ.Add(v);
  2957 				
  2958 				}
  2959 			break;
  2960 		case WM_TIMER:
  2961 			break;
  2962 		case WM_EMUL_POWER_ON:
  2963 			{
  2964 			TInt screenNumber=ScreenFromHWND(hWnd,TheWin);
  2965 			if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count()))
  2966 				break;
  2967 //			HWND win = systemIni->iSecureDisplay ? TheSecureChildWin : TheChildWin;
  2968 			HWND win = TheChildWin[screenNumber];
  2969 			if (wParam==TRUE)
  2970 				{
  2971 				ShowWindow(win, SW_HIDE);
  2972 				ShowWindow(win, SW_SHOWNORMAL);
  2973 				if (SavedFlipMessage)
  2974 					{
  2975 					addKeyEvent(TRawEvent::EKeyDown, SavedFlipMessage);
  2976 					addKeyEvent(TRawEvent::EKeyUp, SavedFlipMessage);
  2977 					SavedFlipMessage = 0;
  2978 					}
  2979 				}
  2980 			else
  2981 				{
  2982 				ShowWindow(win, SW_SHOWNORMAL);
  2983 				ShowWindow(win, SW_HIDE);
  2984 				}
  2985 			}
  2986 			break;
  2987 		case WM_SYSKEYUP:
  2988 		case WM_KEYUP:
  2989 			{
  2990 			//get the key code, this will pick up if it has been remapped or not.
  2991 			TUint scanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam));
  2992 	   /*
  2993 		* We could do this to support generation of special characters using Alt+KeyPadNum
  2994 		* combinations, but we would need to find a way to suppress the generation of
  2995 		* home/end scancodes etc., so leave it for the moment.
  2996 					MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()};
  2997 					TranslateMessage(&msg);
  2998 					TUint charCode=0;
  2999 					// look in the message queue to get character associated with keypress
  3000 					if (PeekMessageU()(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE))
  3001 						charCode=msg.wParam;
  3002 					// Pass the character as the HIWORD of the Epoc scan code
  3003 					v.Set(TRawEvent::EKeyUp,(charCode<<16)|scanCode);
  3004 		*/
  3005 					v.Set(TRawEvent::EKeyUp,scanCode);
  3006 	    			TheEventQ.Add(v);
  3007 			break;
  3008 			}
  3009 		case WM_MOUSEMOVE:
  3010 		case WM_LBUTTONDOWN:
  3011 		case WM_LBUTTONUP:
  3012 		case WM_RBUTTONDOWN:
  3013 		case WM_RBUTTONUP:
  3014 		case WM_MBUTTONDOWN:
  3015 		case WM_MBUTTONUP:
  3016 				{
  3017 				//only handle mouse clicks on screen 0
  3018 				TInt xpos=((TInt16)(lParam&0xffff));
  3019 				TInt ypos = (TInt16)((lParam>>16)&0xFFFF);
  3020 				if (DMultiTouch::iMultiTouchTempEnabled)
  3021 					{
  3022 					MultiChildWndPointer(message,xpos,ypos,0,0);
  3023 					DMultiTouch::iMultiTouchTempEnabled = FALSE;				
  3024 					}
  3025 				else
  3026 					{
  3027 					TInt screenNumber=ScreenFromHWND(hWnd,TheWin);
  3028 					if(screenNumber!=0)
  3029 						break;
  3030 					FrameWndPointer(message,xpos,ypos,screenNumber);
  3031 					}
  3032 				break;
  3033 				}
  3034 		case WM_PAINT:
  3035 			{
  3036 			DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  3037 			if(screenProps == NULL)
  3038 				{
  3039 				return DefWindowProcA(hWnd, message, wParam, lParam);
  3040 				}
  3041     		TViewport& viewport = screenProps->iViewport;
  3042     		TInt screenNumber=ScreenFromHWND(hWnd,TheWin);
  3043 
  3044 			PAINTSTRUCT p;
  3045 
  3046 			BeginPaint(hWnd,&p);
  3047 	   		HDC hdcBits;
  3048 			BITMAP bm;
  3049     		hdcBits=CreateCompatibleDC(p.hdc);
  3050 			GetObjectA(TheScreenBitmap[screenNumber],sizeof(BITMAP),&bm);
  3051     		SelectObject(hdcBits,TheScreenBitmap[screenNumber]);
  3052 		
  3053 			RECT windowRect;
  3054 			GetClientRect(TheWin[screenNumber],&windowRect);
  3055 			
  3056 			viewport.SetViewportHeight(windowRect.bottom);
  3057 			viewport.SetViewportWidth(windowRect.right);
  3058 			
  3059 			
  3060 			switch (CurrentFlipState[screenNumber])
  3061 				{
  3062 				case EEmulatorFlipRestore:
  3063 					{
  3064 					BitBlt(p.hdc,0,0,windowRect.right,windowRect.bottom,hdcBits,
  3065 						viewport.GetViewportOffsetX(),viewport.GetViewportOffsetY(),SRCCOPY);
  3066 					break;
  3067 					}
  3068 				case EEmulatorFlipInvert:
  3069 					{
  3070 					TInt sourceX = screenProps->iXYInputWidth - viewport.GetViewportWidth() - viewport.GetViewportOffsetX();
  3071 					if(sourceX<0)
  3072 						sourceX=0;
  3073 					TInt sourceY = screenProps->iXYInputHeight - viewport.GetViewportHeight() - viewport.GetViewportOffsetY();
  3074 					if(sourceY<0)
  3075 						sourceY=0;
  3076 					TInt sourceWidth = viewport.GetMaxWidth()-sourceX - viewport.GetViewportOffsetX();
  3077 					TInt sourceHeight = viewport.GetMaxHeight()-sourceY - viewport.GetViewportOffsetY();
  3078 					
  3079 					//when inverted it is necessary to translate the image by 1 pixel up and to the left,
  3080 					//to avoid a glitch when scrolling using ScrollWindowEx()
  3081 					POINT arrayPoints[3]={
  3082 						{sourceWidth-1,sourceHeight-1},
  3083 						{-1,sourceHeight-1},
  3084 						{sourceWidth-1,-1}
  3085 						};
  3086 					PlgBlt(p.hdc,arrayPoints,hdcBits,sourceX,sourceY,sourceWidth,sourceHeight,NULL,NULL,NULL);
  3087 					break;
  3088 					}
  3089 				case EEmulatorFlipLeft:
  3090 					{
  3091 					TInt offsetX = screenProps->iXYInputWidth- viewport.GetViewportHeight()  - viewport.GetViewportOffsetY(); 	
  3092 					TInt offsetY = viewport.GetViewportOffsetX(); 	
  3093 		
  3094 					POINT arrayPoints[3]={{0,windowRect.bottom},{0,0},{windowRect.right,windowRect.bottom}};
  3095 					PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL);
  3096 					break;
  3097 					}
  3098 				case EEmulatorFlipRight:
  3099 					{
  3100 					TInt offsetX = viewport.GetViewportOffsetY(); 
  3101 					TInt offsetY = screenProps->iXYInputHeight - viewport.GetViewportWidth() - viewport.GetViewportOffsetX(); 	
  3102 									
  3103 					POINT arrayPoints[3]={{windowRect.right,0},{windowRect.right,windowRect.bottom},{0,0}};
  3104 					PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL);
  3105 					break;
  3106 					}
  3107 				}
  3108 
  3109 			
  3110 			DeleteDC(hdcBits);
  3111 			if (WinsGuiPowerHandler->iStandby)
  3112 				{
  3113 				TInt x,y;
  3114 				CalcTextPos(screenNumber, x, y);
  3115 				TextOutA(p.hdc, x, y, "Standby", 7);
  3116 				}
  3117 			else if (systemIni->iScreens[screenNumber]->iScreenOff)
  3118 				{
  3119 				TInt x,y;
  3120 				CalcTextPos(screenNumber, x, y);
  3121 				TextOutA(p.hdc, x, y, "Screen Off", 10);
  3122 				}
  3123  			EndPaint(hWnd,&p);
  3124 			break;
  3125 			}
  3126 		case WM_ACTIVATE:
  3127 			//Added so that change in modifier keys can be detected without sending
  3128 			//EActive/EInActive to wserv as it results in switching the timers
  3129    			if((wParam & 0xffff)!= WA_INACTIVE)
  3130    				UpdateModifiers();
  3131 			break;
  3132 		case WM_CHAR:
  3133 		case WM_SYSCHAR:
  3134 		case WM_DEADCHAR:
  3135 		case WM_SYSDEADCHAR:
  3136 			break;
  3137 		case WM_CLOSE: //pass on message to control window, it will then destroy all e,ulator windows
  3138 			SendMessage(TheControlWin,WM_CLOSE, NULL, NULL);
  3139 			break;
  3140 		case WM_DESTROY:
  3141 			{
  3142 			DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin);
  3143 			if(screenProps == NULL)
  3144 				{
  3145 				return DefWindowProcA(hWnd, message, wParam, lParam);
  3146 				}
  3147     					
  3148 			// save window's position information
  3149 			screenProps->iWinPlace.length = sizeof(WINDOWPLACEMENT);
  3150 			GetWindowPlacement(hWnd, &screenProps->iWinPlace);
  3151 			
  3152 			break;
  3153 			}
  3154 		case WM_INPUT:
  3155 			{
  3156 			if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled())
  3157 				{
  3158 				TInt screenNumber=ScreenFromHWND(hWnd,TheWin);
  3159 				if(screenNumber==0)
  3160 					{
  3161 					TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[screenNumber]);	
  3162 					}
  3163 				}
  3164 			else
  3165 				{
  3166 				Fault(EGuiInvalidMultiTouch);
  3167 				}
  3168 		   	break;
  3169 			}
  3170 		default:
  3171 	        return(DefWindowProcA(hWnd,message,wParam,lParam));
  3172 	    }
  3173     return(FALSE);
  3174 	
  3175 	}
  3176 
  3177 void SetStatusBarFont(HWND& aStatusBar)
  3178 	{
  3179 	int statwidths[] = {100,200,300,400,500,600,700,800};
  3180 	SendMessage(aStatusBar, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths);
  3181 	HFONT hOrigFont = (HFONT) SendMessage(aStatusBar, WM_GETFONT, 0, 0);
  3182 	SetProp(aStatusBar, TEXT("PROP_ORIGINAL_FONT"), (HANDLE) hOrigFont);
  3183 	LOGFONT lf;
  3184 	GetObject(hOrigFont, sizeof(lf), &lf);
  3185 	lf.lfHeight = (long)(lf.lfHeight / 1.5);
  3186 	lf.lfWeight = FW_NORMAL;
  3187 	HFONT hFont = CreateFontIndirect(&lf);
  3188 	SetProp(aStatusBar, TEXT("PROP_ITALIC_FONT"), (HANDLE) hFont);
  3189 	hFont = (HFONT) GetProp(hwndStatus, TEXT("PROP_ITALIC_FONT"));
  3190 	SendMessage(aStatusBar, WM_SETFONT, (WPARAM) hFont, FALSE);
  3191 	}
  3192 
  3193 DWORD WINAPI KernelWindowThread(LPVOID aArg)
  3194 //
  3195 // The kernel window thread.
  3196 //
  3197 	{
  3198 	HMODULE hmodule = GetModuleHandleA("winsgui.dll");
  3199 	__ASSERT_ALWAYS(hmodule!=NULL,Fault(EGuiGetModuleHandle));
  3200 
  3201 	WNDCLASSA w;
  3202 	memclr(&w, sizeof(WNDCLASSA));
  3203    	w.style=CS_OWNDC|CS_VREDRAW|CS_HREDRAW;
  3204    	w.lpfnWndProc=(WNDPROC)ctrlwinProc;
  3205    	w.hInstance=(HINSTANCE)aArg;
  3206    	w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON));
  3207    	w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
  3208    	w.lpszClassName="E32KernelControlWindow";
  3209 	
  3210 	ATOM a=RegisterClassA(&w);
  3211 	__ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow));
  3212 
  3213 	RECT ctlrwindowRect={0,0,270,0};
  3214 	AdjustWindowRect(&ctlrwindowRect,KControlWinStyle,FALSE);
  3215 	TInt ctrlwindowWidth=ctlrwindowRect.right-ctlrwindowRect.left;
  3216 	TInt ctrlwindowHeight=ctlrwindowRect.bottom-ctlrwindowRect.top;
  3217 
  3218     TheControlWin=CreateWindowA(
  3219 		"E32KernelControlWindow",
  3220 		systemIni->iWindowTitle,
  3221 		KInvisibleControlWinStyle,
  3222 		KWinPosX,
  3223 		KWinPosY,
  3224 		ctrlwindowWidth,
  3225 		ctrlwindowHeight,
  3226 		(HWND)NULL,
  3227 		NULL,
  3228 		(HINSTANCE)aArg,
  3229 		(LPSTR)NULL
  3230 		);
  3231 	__ASSERT_ALWAYS(TheControlWin!=NULL,Fault(EGuiKernelWindowCreate));
  3232 
  3233 	memclr(&w, sizeof(WNDCLASSA));
  3234    	w.style=CS_OWNDC;
  3235    	w.lpfnWndProc=(WNDPROC)winProc;
  3236    	w.hInstance=(HINSTANCE)aArg;
  3237    	w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON));
  3238    	w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
  3239    	w.lpszClassName="E32KernelWindow";
  3240 
  3241 	a=RegisterClassA(&w);
  3242 	__ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow));
  3243 
  3244 	memclr(&w, sizeof(WNDCLASSA));
  3245 	w.style=CS_OWNDC;
  3246 	w.lpfnWndProc=(WNDPROC)childWinProc;
  3247 	w.hInstance=(HINSTANCE)aArg;
  3248 	w.hCursor=LoadCursorA(NULL,MAKEINTRESOURCEA(32512)); //ICD_ARROW
  3249 	w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
  3250 	w.lpszMenuName=NULL;
  3251 	w.lpszClassName="E32KernelChildWindow";
  3252 	a=RegisterClassA(&w);
  3253 	__ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterChildWindow));
  3254 
  3255 	if (masterIni && masterIni->iSystemInis.Count() > 1)	
  3256 		{
  3257 		//add Configuration Items to the system menu if there's > 1 config
  3258 		HMENU hMenu = GetSystemMenu(TheControlWin, FALSE);
  3259 		InsertMenu(hMenu,5, MF_BYPOSITION|MF_SEPARATOR,0,NULL);
  3260 		InsertMenuA(hMenu,6, MF_BYPOSITION|MF_STRING, 1, "Next Config...");
  3261 		}
  3262 	
  3263 	ShowWindow(TheControlWin,SW_SHOWDEFAULT);
  3264 	UpdateWindow(TheControlWin);
  3265 
  3266 	//Create frame windows and child windows
  3267 	for(TInt screen=0;screen<systemIni->iScreens.Count();screen++)
  3268 		{
  3269 	
  3270 		RECT windowRect={0,0,systemIni->iScreens[screen]->iXYInputWidth,systemIni->iScreens[screen]->iXYInputHeight};
  3271 		AdjustWindowRect(&windowRect,KWinStyle,FALSE);
  3272 		TInt windowWidth=windowRect.right-windowRect.left;
  3273 		TInt windowHeight=windowRect.bottom-windowRect.top;
  3274     
  3275 		CHAR title[20];
  3276 		wsprintfA(title, "Screen %d", screen);
  3277 
  3278 		TheWin[screen]=CreateWindowA(
  3279 			"E32KernelWindow",
  3280 			title,
  3281 			KInvisibleWinStyle,
  3282 			KWinPosX,
  3283 			KWinPosY,
  3284 			windowWidth,
  3285 			windowHeight,
  3286 			(HWND)NULL,
  3287 			NULL,
  3288 			(HINSTANCE)aArg,
  3289 			(LPSTR)NULL
  3290 			);
  3291 		__ASSERT_ALWAYS(TheWin[screen]!=NULL,Fault(EGuiKernelWindowCreate));
  3292 		
  3293 		LoadFasciaBitmap(screen);
  3294 
  3295 		TheChildWin[screen]=CreateWindowA(
  3296 			"E32KernelChildWindow",
  3297 			"",
  3298 			WS_CHILDWINDOW|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
  3299 			systemIni->iScreens[screen]->iScreenOffsetX,
  3300 			systemIni->iScreens[screen]->iScreenOffsetY,
  3301 			systemIni->iScreens[screen]->iScreenWidth,
  3302 			systemIni->iScreens[screen]->iScreenHeight,
  3303 			TheWin[screen],
  3304 			NULL,
  3305 			(HINSTANCE)aArg,
  3306 			(LPSTR)NULL
  3307 			);
  3308 		__ASSERT_ALWAYS(TheChildWin[screen]!=NULL,Fault(EGuiKernelChildWindowCreate));
  3309 		
  3310 		// Create status bars
  3311 		if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled())
  3312 			{
  3313 			HMODULE hmodComCtl = LoadLibrary(TEXT("comctl32.dll"));
  3314 			typedef int (WINAPI* FNINITCC)();
  3315 			FNINITCC pfnInitCommonControls = GetProcAddress(hmodComCtl, "InitCommonControls");
  3316 			pfnInitCommonControls();
  3317 			hwndStatus = CreateWindowExA(0, STATUSCLASSNAMEA, NULL,
  3318 								WS_CHILD | WS_VISIBLE | CCS_BOTTOM ,
  3319 									0,0,0,0,
  3320 									TheWin[0], NULL, GetModuleHandle(NULL), NULL);                 
  3321 			SetStatusBarFont(hwndStatus);
  3322 			SetWindowPos(hwndStatus,NULL, 0,0,0,0,SWP_HIDEWINDOW);
  3323 			}
  3324 		}
  3325 	
  3326 	//Restore window data from ini file if it exists. 
  3327 	HANDLE hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
  3328 	TBool success=(hSysIni != INVALID_HANDLE_VALUE) ? ETrue : EFalse;
  3329 	
  3330 	DWORD numRead;
  3331 	TInt fileVersion=0;
  3332 	if(success) 
  3333 		{
  3334 		ReadFile(hSysIni, &fileVersion, sizeof(TInt), &numRead, 0);
  3335 		}
  3336 	
  3337 	//Check we are using a dat file created by this version of the program.
  3338 	if(success && (fileVersion==KDatFileVersion) )
  3339 		{
  3340 				
  3341 		TInt savedConfiguration=0; //set this to default configuration
  3342 				
  3343 		if(ReadFile(hSysIni, &savedConfiguration, sizeof(TInt), &numRead, 0) && (numRead>0) )
  3344 			{
  3345 			//Don't restore the saved configuration, see INC114502.
  3346 			//This could be reenabled in future as an optional operation
  3347 			//dependent on an entry in the epoc.ini file.
  3348 
  3349 			//SwitchConfiguration(savedConfiguration);
  3350 			}
  3351 	
  3352 		//restore each window to saved state
  3353 		for(TInt screen=0;screen<systemIni->iScreens.Count();screen++)
  3354 			{
  3355 		
  3356 			//	If the .ini file was opened, get the saved settings for the windows position the last time
  3357 			//	this emulator was run, if any, and move the window accordingly.
  3358 			
  3359 			TWindowState savedState;
  3360 			
  3361 			TBool stateLoaded = ReadFile(hSysIni, &savedState, sizeof(TWindowState), &numRead, 0) && (numRead>0);
  3362 			 			
  3363 			if (stateLoaded)
  3364 				{				
  3365 				//only allow window to be restored to 
  3366 				//maximized or normal mode,
  3367 				//this prevents it being restored in minimized mode
  3368 				//or others.
  3369 				if(savedState.iWinPlace.showCmd != SW_MAXIMIZE)
  3370 						savedState.iWinPlace.showCmd= SW_NORMAL;
  3371 				
  3372 				//if starting in same configuration and/or rotation as last time emulator was run
  3373 				//it makes sense to restore scroll offset, window position,
  3374 				//and dimensions, if not, only restore position and window (ie. maximized/normal) state.
  3375 				if(savedConfiguration == CurrentConfiguration &&
  3376 					savedState.iFlipstate == CurrentFlipState[screen])
  3377 					{
  3378 					//Restore window placement
  3379 					SetWindowPlacement(TheWin[screen], &savedState.iWinPlace);
  3380 					
  3381 					TViewport& viewport = systemIni->iScreens[screen]->iViewport;
  3382 								
  3383 					viewport.ScrollToX(savedState.iXoffset, TheWin[screen]);
  3384 					viewport.ScrollToY(savedState.iYoffset, TheWin[screen]);
  3385 					}
  3386 				else
  3387 					{
  3388 					
  3389 					RECT oldRect;
  3390 					GetWindowRect(TheWin[screen], &oldRect);
  3391 					//save default window dimensions
  3392 					TInt width=oldRect.right-oldRect.left;
  3393 					TInt height=oldRect.bottom - oldRect.top;
  3394 
  3395 					//restore position and window state from file
  3396 					SetWindowPlacement(TheWin[screen], &savedState.iWinPlace);
  3397 					
  3398 					RECT currentRect;
  3399 					GetWindowRect(TheWin[screen], &currentRect);
  3400 					//keep default size.
  3401 					MoveWindow(TheWin[screen],currentRect.left, currentRect.top, width, height, TRUE);
  3402 					
  3403 					}
  3404 
  3405 
  3406 				// Check that enough of the recorded window position is visible on the screen
  3407 
  3408 				TBool enoughVisible = false;
  3409 
  3410 				// vague values for ensuring we have enough of the window title bar to grab
  3411 				// if the window is partly off screen 
  3412 				const TInt KTitleBarGrabX=80;
  3413 				const TInt KTitleBarGrabY=50;
  3414 
  3415 				//inspect dimensions of the window to be restored.
  3416 				RECT savedRect;
  3417 				GetWindowRect(TheWin[screen], &savedRect);
  3418 
  3419 				SystemMonitors monitors;
  3420 
  3421 				if (monitors.Count() == 1)		/* Original algorithm */
  3422 					{
  3423 					RECT rcIntersect, rcScreen;
  3424 
  3425 					SetRect(&rcScreen, KTitleBarGrabX, savedRect.bottom-savedRect.top,
  3426 						GetSystemMetrics(SM_CXSCREEN)-KTitleBarGrabX, GetSystemMetrics(SM_CYSCREEN)-KTitleBarGrabY);
  3427 
  3428 					enoughVisible = IntersectRect(&rcIntersect, &savedRect, &rcScreen);
  3429 					}
  3430 				else							/* > 1 monitor; do it differently */
  3431 					{
  3432 					RECT cornerBox1, cornerBox2;
  3433 
  3434 					// The top-left corner box
  3435 					SetRect(&cornerBox1, savedRect.left, savedRect.top,
  3436 						savedRect.left + KTitleBarGrabX, savedRect.top + KTitleBarGrabY);
  3437 
  3438 					// The top-right corner box
  3439 					SetRect(&cornerBox2, savedRect.right - KTitleBarGrabX, savedRect.top,
  3440 						savedRect.right, savedRect.top + KTitleBarGrabY);
  3441 
  3442 					// Require one of these rectangles to be all on one monitor
  3443 					enoughVisible = monitors.RectAllOnOne(cornerBox1) || monitors.RectAllOnOne(cornerBox2);
  3444 					}
  3445 
  3446 				if (!enoughVisible)
  3447 					{
  3448 					SetWindowPos(TheWin[screen], HWND_TOP, 0,0,0,0, SWP_NOSIZE);
  3449 					}
  3450 
  3451 				}
  3452 			else //if there was no stored info for this screen
  3453 				{
  3454 				ShowWindow(TheWin[screen],SW_MAXIMIZE);
  3455 				}
  3456 			}
  3457 		}
  3458 	else
  3459 		{
  3460 		//use default configuration and make windows visible
  3461 		SwitchConfiguration(CurrentConfiguration);
  3462 		for(TInt screen=0;screen<systemIni->iScreens.Count();screen++)
  3463 			{
  3464 			ShowWindow(TheWin[screen],SW_MAXIMIZE);
  3465 			UpdateWindow(TheWin[screen]);
  3466 			}
  3467 		}
  3468 
  3469 	//close file if it was opened	
  3470 	if(success) 
  3471 		{
  3472 		CloseHandle(hSysIni);
  3473 		}
  3474 		
  3475 			
  3476 	if (systemIni->iInitialFlipMsg != 0)
  3477 		{
  3478 		addKeyEvent(TRawEvent::EKeyDown,systemIni->iInitialFlipMsg);
  3479 		addKeyEvent(TRawEvent::EKeyUp,systemIni->iInitialFlipMsg);
  3480 		}
  3481 
  3482 	SetFocus(TheWin[0]);
  3483 
  3484 	MSG m;
  3485 	while (GetMessageA(&m,NULL,0,0))
  3486     	{
  3487         DispatchMessageA(&m);
  3488 	    }
  3489 	
  3490 	ExitProcess(m.wParam);
  3491 	return 0;
  3492 	}
  3493 
  3494 SystemMonitors::SystemMonitors(void)
  3495 	{
  3496 	TInt n;
  3497 
  3498 	iCount = 1;
  3499 	iHaveMultiMonFunctions = false;
  3500 
  3501 	if ((n = GetSystemMetrics(SM_CMONITORS)) <= 1)
  3502 		{
  3503 		return;
  3504 		}
  3505 
  3506 	HMODULE huser32 = GetModuleHandleA("user32.dll");
  3507 
  3508 	// Get pointers to the APIs we want
  3509 	if (huser32 == NULL ||
  3510 		(ipMonitorFromRect =
  3511 		(HMONITOR (WINAPI *)(LPCRECT lprcScreenCoords, UINT uFlags))
  3512 		GetProcAddress(huser32, "MonitorFromRect")) == NULL ||
  3513 		(ipGetMonitorInfo =
  3514 		(BOOL (WINAPI *)(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo))
  3515 		GetProcAddress(huser32, "GetMonitorInfoA")) == NULL)
  3516 		{
  3517 		return;
  3518 		}
  3519 
  3520 	iCount = n;
  3521 	iHaveMultiMonFunctions = true;
  3522 	}
  3523 
  3524 TBool SystemMonitors::RectAllOnOne(RECT& rect)
  3525 	{
  3526 	HMONITOR monitor = MonitorFromRect(rect);
  3527 	if (monitor == NULL)
  3528 		{
  3529 		return false;
  3530 		}
  3531 
  3532 	MONITORINFO monInfo;
  3533 	monInfo.cbSize = sizeof(MONITORINFO);
  3534 
  3535 	if (! GetMonitorInfo(monitor, &monInfo))
  3536 		{
  3537 		return false;
  3538 		}
  3539 
  3540 	RECT overlap;
  3541 
  3542 	if (IntersectRect(&overlap, &rect, &monInfo.rcWork) &&
  3543 		EqualRect(&overlap, &rect))
  3544 		{
  3545 		return true;
  3546 		}
  3547 
  3548 	return false;
  3549 	}
  3550 
  3551 HMONITOR SystemMonitors::MonitorFromRect(const RECT& rect, UINT flags)
  3552 	{
  3553 	if (! iHaveMultiMonFunctions)
  3554 		{
  3555 		return NULL;
  3556 		}
  3557 
  3558 	return (*ipMonitorFromRect)(&rect, flags);
  3559 	}
  3560 
  3561 TBool SystemMonitors::GetMonitorInfo(HMONITOR monitor, LPMONITORINFO pMonInfo)
  3562 	{
  3563 	if (! iHaveMultiMonFunctions)
  3564 		{
  3565 		return false;
  3566 		}
  3567 
  3568 	return (*ipGetMonitorInfo)(monitor, pMonInfo);
  3569 	}
  3570 
  3571 void DrawLeds()
  3572 	{
  3573 	HDC winDC = GetDC(TheWin[0]);
  3574 	HDC hdcBits;
  3575 	hdcBits=CreateCompatibleDC(winDC);
  3576 	SelectObject(hdcBits,TheScreenBitmap[0]);
  3577 	HPEN pen=CreatePen(PS_SOLID,0,RGB(0,0,0));
  3578 	SelectObject(hdcBits,pen);
  3579 	HBRUSH brush;
  3580 	LOGBRUSH redbrush={BS_SOLID, RGB(0xff,0,0)};
  3581 	LOGBRUSH greenbrush={BS_SOLID, RGB(0,0xff,0)};
  3582 	LOGBRUSH blackbrush={BS_SOLID, RGB(0,0,0)};
  3583 	// red
  3584 	if (LedMask & KLedMaskRed1)
  3585 		brush=CreateBrushIndirect(&redbrush);
  3586 	else
  3587 		brush=CreateBrushIndirect(&blackbrush);
  3588 	SelectObject(hdcBits,brush);
  3589 	DWinsUi *ini=systemIni;
  3590 	Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY, ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize);
  3591 	DeleteObject(brush);
  3592 	// green
  3593 	if (LedMask & KLedMaskGreen1)
  3594 		brush=CreateBrushIndirect(&greenbrush);
  3595 	else
  3596 		brush=CreateBrushIndirect(&blackbrush);
  3597 	SelectObject(hdcBits,brush);
  3598 	if (ini->iLedVertical)
  3599 		Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap,
  3600 		ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize);
  3601 	else
  3602 		Ellipse(hdcBits, ini->iLedOffsetX+ini->iLedSize+ini->iLedGap, ini->iLedOffsetY,
  3603 		ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize);
  3604 	DeleteObject(brush);
  3605 	DeleteObject(pen);
  3606 	DeleteDC(hdcBits);
  3607 	ReleaseDC(TheWin[0], winDC);
  3608 	if (ini->iLedVertical)
  3609 		{
  3610 		RECT r={ini->iLedOffsetX,
  3611 			ini->iLedOffsetY,
  3612 			ini->iLedOffsetX+ini->iLedSize,
  3613 			ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize};
  3614 		InvalidateRect(TheWin[0], &r, FALSE);
  3615 		}
  3616 	else
  3617 		{
  3618 		RECT r={ini->iLedOffsetX,
  3619 			ini->iLedOffsetY,
  3620 			ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize,
  3621 			ini->iLedOffsetY+ini->iLedSize};
  3622 		InvalidateRect(TheWin[0], &r, FALSE);
  3623 		}
  3624 	}
  3625 
  3626 void DWinsUi::ScreenInfo(TScreenInfoV01& aInfo)
  3627 //
  3628 // Return screen 0 info to the window server.
  3629 //
  3630 	{
  3631 	aInfo.iWindowHandleValid=ETrue;
  3632 	aInfo.iWindowHandle=TheChildWin[0];
  3633 	aInfo.iScreenAddressValid=EFalse;
  3634 	aInfo.iScreenAddress=NULL;
  3635 	aInfo.iScreenSize.iWidth = iScreens[0]->iMaxScreenWidth;
  3636 	aInfo.iScreenSize.iHeight = iScreens[0]->iMaxScreenHeight;
  3637 	}
  3638 	
  3639 	
  3640 TBool DWinsUi::VideoInfo(TInt aScreenNumber, TVideoInfoV01& aInfo)
  3641 	{
  3642 	return VideoInfo(aScreenNumber,iScreens[aScreenNumber&KMaskScreenNum]->iCurrentMode,aInfo);
  3643 	}
  3644 	
  3645 /// Could fail if flip mode is not supported
  3646 TBool DWinsUi::VideoInfo(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo)
  3647 	{
  3648 	aScreenNumber &= KMaskScreenNum;
  3649 	if (aScreenNumber>=iScreens.Count())
  3650 		return EFalse;
  3651 	if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aScreenNumber].iDisplayDriverCount > 0)
  3652 		{
  3653 			return VideoInfoForDisplayDriver(aScreenNumber,aModeNumber,aInfo);
  3654 		}
  3655 	else
  3656 		{
  3657 		if ((aModeNumber&KMaskModeNum)>=1)
  3658 			return EFalse;	//non-gce emulator doesn't support changing the mode number.
  3659 		DScreenProperties* screenProperties=iScreens[aScreenNumber];
  3660 		aInfo.iSizeInPixels.iWidth = screenProperties->iMaxScreenWidth;
  3661 		aInfo.iSizeInPixels.iHeight = screenProperties->iMaxScreenHeight;
  3662 		aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ? screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX);
  3663 		aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY);
  3664 		aInfo.iIsMono = EFalse;
  3665 		aInfo.iIsPalettized = EFalse;
  3666 		aInfo.iDisplayMode=screenProperties->iCurrentMode;
  3667 		aInfo.iIsPixelOrderRGB = ETrue;
  3668 		aInfo.iIsPixelOrderLandscape=ETrue;
  3669 
  3670 		aInfo.iVideoAddress =  (TInt)TheChildWin[aScreenNumber];
  3671 		aInfo.iBitsPerPixel = screenProperties->iColorDepth;
  3672 		aInfo.iOffsetToFirstPixel=0;
  3673 		aInfo.iOffsetBetweenLines=0;
  3674 		}
  3675 	return ETrue;	
  3676 	}
  3677 
  3678 /** Could fail if flip mode is not supported.
  3679  Note that this method is inteneded to be called directly to parameterise the setting up of the display driver,
  3680  so it must survive absense of the display driver installation!
  3681 **/
  3682  
  3683 TBool DWinsUi::VideoInfoForDisplayDriver(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo,  TBool aRealWidthAndHeight)
  3684 	{
  3685 	aScreenNumber &= KMaskScreenNum;
  3686 	DScreenProperties* screenProperties = iScreens[aScreenNumber];
  3687 	if ((aModeNumber&KMaskModeNum) >= screenProperties->iMaxModes)
  3688 		{
  3689 		return EFalse;
  3690 		}
  3691 		
  3692 	aInfo.iSizeInPixels.iWidth = aRealWidthAndHeight ? screenProperties->iScreenWidth : screenProperties->iMaxScreenWidth;
  3693 	aInfo.iSizeInPixels.iHeight = aRealWidthAndHeight ? screenProperties->iScreenHeight : screenProperties->iMaxScreenHeight;
  3694 	
  3695 	if (aRealWidthAndHeight==EFalse)
  3696 		{
  3697 		aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ?	screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX);
  3698 		aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY);
  3699 		}
  3700 	else
  3701 		{
  3702 		aInfo.iSizeInTwips.iWidth = screenProperties->iPhysicalScreenWidth ? screenProperties->iPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX);
  3703 		aInfo.iSizeInTwips.iHeight = screenProperties->iPhysicalScreenHeight ? screenProperties->iPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY);
  3704 		}
  3705 	
  3706 	aInfo.iIsMono = EFalse;
  3707 	aInfo.iIsPalettized = EFalse;
  3708 	aInfo.iDisplayMode=screenProperties->iCurrentMode;
  3709 	aInfo.iIsPixelOrderRGB = ETrue;
  3710 	aInfo.iIsPixelOrderLandscape=ETrue;
  3711 	
  3712 	// Set memory to iVideoAddress to NULL to trigger the HAL code into querying the video address
  3713 	// separately
  3714 	aInfo.iVideoAddress = NULL;
  3715 
  3716 	TInt bpp=screenProperties->iModeDepths[aModeNumber&KMaskModeNum];												
  3717 	aInfo.iBitsPerPixel=bpp;
  3718 	if (bpp>8)
  3719 		{
  3720 		bpp=(bpp+15)&-16;	//12 & 16 --> 16 ; 24 & 32 --> 32
  3721 		}
  3722 	
  3723 	aInfo.iOffsetToFirstPixel=0;
  3724 #ifdef TEST_GCE_VARIABLE_START_EXTRA
  3725 	aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*(1+aModeNumber&KMaskScreenModeNum);
  3726 	if ((aModeNumber& KModeFlagFlipped)
  3727 		{
  3728 #ifndef ASSYMETRIC_SQUARE_STRIDE		
  3729 		if (aInfo.iSizeInPixels.iWidth!=aInfo.iSizeInPixels.iHeight)
  3730 #endif
  3731 			aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*KEmulMaxNumModes;	
  3732 		}
  3733 #endif
  3734 	if (aModeNumber& KModeFlagFlipped)
  3735 		{
  3736 		// we calculate the number of bytes per scanline that MUST be a multiple of 32 bits word (alignment)
  3737 		// screenProperties->iMaxScreenHeight * bpp represnts the number of bits per scanline
  3738 		// +31 is the ceiling
  3739 		// we shift right (>>3) because there are 8 bits/byte
  3740 		// we mask with ~3 because we are intrested in the octet value
  3741 		aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenHeight * bpp + 31) >> 3) & ~3;
  3742 		}
  3743 	else
  3744 		{
  3745 		// please see the comment above
  3746 		aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenWidth * bpp + 31) >> 3) & ~3;
  3747 		}
  3748 #ifdef  TEST_GCE_VARIABLE_STRIDE_EXTRA
  3749 	aInfo.iOffsetBetweenLines+=TEST_GCE_VARIABLE_STRIDE_EXTRA;
  3750 #endif	
  3751 
  3752 	return ETrue;	
  3753 	}
  3754 
  3755 TInt DMasterIni::DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
  3756 	{
  3757 	return masterIni->HalFunction((TInt)aPtr,aFunction,a1,a2);
  3758 	}
  3759 
  3760 
  3761 TInt DMasterIni::HalFunction(TInt aDeviceNumber, TInt aFunction, TAny* a1, TAny* a2)
  3762 	{
  3763 	if (TUint(aDeviceNumber) >= TUint(systemIni->iScreens.Count()))
  3764 		return KErrArgument;
  3765 	
  3766 	TInt mode;
  3767 	TInt maxMode=1;
  3768 	TInt r=KErrNone;
  3769 	switch(aFunction)
  3770 		{
  3771 		case EDisplayHalScreenInfo:
  3772 			{
  3773 			TPckgBuf<TScreenInfoV01> vPckg;
  3774 			systemIni->ScreenInfo(vPckg());
  3775 			Kern::InfoCopy(*(TDes8*)a1,vPckg);
  3776 			break;
  3777 			}
  3778 		case EDisplayHalWsRegisterSwitchOnScreenHandling:
  3779 			WsSwitchOnScreen=(TBool)a1;
  3780 			break;
  3781 		case EDisplayHalSetState:
  3782 			{
  3783 			if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState")))
  3784 				return KErrPermissionDenied;
  3785 			if ((TBool)a1)
  3786 				WinsGuiPowerHandler->ScreenOn(aDeviceNumber);
  3787 			else
  3788 				WinsGuiPowerHandler->ScreenOff(aDeviceNumber);
  3789 			}
  3790 			break;
  3791 
  3792 		case EDisplayHalState:
  3793 			*(TInt*)a1=!systemIni->iScreens[aDeviceNumber]->iScreenOff;
  3794 			break;
  3795 		case EDisplayHalWsSwitchOnScreen:
  3796 			WinsGuiPowerHandler->ScreenOn();
  3797 			break;
  3798 		case EDisplayHalMaxDisplayContrast:
  3799 			kumemput32(a1,&KMaxDisplayContrast,sizeof(KMaxDisplayContrast));
  3800 			break;
  3801 		case EDisplayHalDisplayContrast:
  3802 			kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iDisplayContrast,sizeof(systemIni->iScreens[aDeviceNumber]->iDisplayContrast));
  3803 			break;
  3804 		case EDisplayHalSetDisplayContrast:
  3805 			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayContrast")))
  3806 				return KErrPermissionDenied;
  3807 			if (TUint(a1) <= TUint(KMaxDisplayContrast))
  3808 				systemIni->iScreens[aDeviceNumber]->iDisplayContrast = TInt(a1);
  3809 			else
  3810 				r = KErrArgument;
  3811 			break;
  3812 		case EDisplayHalBacklightOn:
  3813 			{
  3814 			TBool c = EFalse;
  3815 			kumemput32(a1,&c,sizeof(TBool));
  3816 			}
  3817 			break;
  3818 		
  3819 		case EDisplayHalCurrentModeInfo:
  3820 			{
  3821 			//a1 has ptr to buffer for results
  3822 			TPckgBuf<TVideoInfoV01> vPckg;
  3823 			if (systemIni->VideoInfo(aDeviceNumber, vPckg()))
  3824 				Kern::InfoCopy(*(TDes8*)a1,vPckg);
  3825 			else
  3826 				r=KErrNotSupported;
  3827 			}
  3828 			break;
  3829 
  3830 		case EDisplayHalSpecifiedModeInfo:
  3831 			{
  3832 			kumemget32(&mode, a1, sizeof(mode));
  3833 			TPckgBuf<TVideoInfoV01> vPckg;
  3834 			if (!systemIni->VideoInfo(aDeviceNumber, mode, vPckg()))
  3835 				return KErrArgument;
  3836 			Kern::InfoCopy(*(TDes8*)a2, vPckg);
  3837 			}
  3838 			break;
  3839 
  3840 		case EDisplayHalSetMode:
  3841 // 			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode")))
  3842 // 				return KErrPermissionDenied;
  3843 
  3844 			//Note that at present the HAL mode does not apparently get set when the CFbsScreenDevice requires a different mode.
  3845 			//At least in the emulator and default h4 implementation...
  3846 			
  3847 			mode=KMaskModeNum&(TInt) a1;
  3848 			maxMode=1;
  3849 			//can't avoid this behaviour change test against gce loaded 
  3850 			if (masterIni->iBufferSet.Count() &&  masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0)
  3851 				maxMode=systemIni->iScreens[aDeviceNumber]->iMaxModes;
  3852 			if (mode >=maxMode || mode<0)
  3853 				{
  3854 				r = KErrArgument;
  3855 				break;
  3856 				}
  3857 			//Harmless/Pointless in vanilla wins mode.
  3858 			systemIni->iScreens[aDeviceNumber]->iCurrentMode=mode;
  3859 			
  3860 			break;
  3861 		
  3862 		case EDisplayHalMode:
  3863 			{
  3864 			//This is always 0 in non-gce emulator
  3865 			kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iCurrentMode,sizeof(systemIni->iScreens[aDeviceNumber]->iCurrentMode));
  3866 			}
  3867 			break;
  3868 
  3869 		case EDisplayHalModeCount:
  3870 			{
  3871 			//Need to actually count them here!
  3872 			//GCE will ignore modes<=8
  3873 			TInt encodedMode=1;
  3874 			if (masterIni->iBufferSet.Count() &&  masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0)
  3875 				encodedMode=systemIni->iScreens[aDeviceNumber]->iMaxModes;
  3876 			kumemput32(a1,&encodedMode,sizeof(encodedMode));
  3877 			}
  3878 			break;
  3879 
  3880 		case EDisplayHalColors:
  3881 			{
  3882 			TInt deepestMode=0;
  3883 			if (masterIni->iBufferSet.Count()==0 ||  masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0)
  3884 				{
  3885 				deepestMode = KMaxDisplayColors;  	//I could try and work it out, but this is what used to happen!
  3886 				}
  3887 			else
  3888 				{
  3889 				TInt maxBpp=0;
  3890 				for (TInt i=0,maxI=systemIni->iScreens[aDeviceNumber]->iMaxModes;i<maxI;i++)	
  3891 					if (systemIni->iScreens[aDeviceNumber]->iModeDepths[i]>maxBpp)
  3892 						maxBpp=systemIni->iScreens[aDeviceNumber]->iModeDepths[i];
  3893 				deepestMode= 1<<maxBpp;
  3894 				}
  3895 
  3896 			kumemput32(a1,&deepestMode,sizeof(deepestMode));
  3897 			}
  3898 			break;
  3899 		case EDisplayHalGetDisplayMemoryHandle:
  3900 			{
  3901 			TInt val = 0;
  3902 			TInt passedIn = 0;
  3903 			kumemget32(&passedIn, a1, sizeof(TInt));
  3904 			if (passedIn != -1)	//not from a getall
  3905 				{
  3906 				NKern::ThreadEnterCS();
  3907 				if (!(masterIni->iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 ))
  3908 					{
  3909 						r = masterIni->DisplayMemoryHandle(aDeviceNumber, val); 
  3910 					}
  3911 				else
  3912 					{
  3913 					r = KErrArgument;
  3914 					}
  3915 				NKern::ThreadLeaveCS();
  3916 				}
  3917 			kumemput32(a1, &val, sizeof(TInt));
  3918 
  3919 			}
  3920 			break;
  3921 
  3922 		case EDisplayHalGetDisplayMemoryAddress:
  3923 			{
  3924 			TInt val = 0;
  3925 			TInt passedIn = 0;
  3926 			kumemget32(&passedIn, a1, sizeof(TInt));
  3927 			if (passedIn != -1)	//not from a getall
  3928 				{
  3929 				if (!(masterIni->iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 ))
  3930 					{
  3931 					r = masterIni->DisplayMemoryAddress(aDeviceNumber, val);
  3932 					}
  3933 				else
  3934 					{
  3935 					r = KErrArgument;
  3936 					}
  3937 				}
  3938 			kumemput32(a1, &val, sizeof(TInt));
  3939 			}
  3940 			break;
  3941 
  3942 		case EDisplayHalNumberOfResolutions:
  3943 			{
  3944 			r = NumberOfResolutions(aDeviceNumber, a1, a2);
  3945 			}
  3946 			break;
  3947 		case EDisplayHalSpecificScreenInfo:
  3948 			{
  3949 			r = SpecificScreenInfo(aDeviceNumber, a1, a2);
  3950 			}
  3951 			break;
  3952 		case EDisplayHalCurrentScreenInfo:
  3953 			{
  3954 			r = CurrentScreenInfo(aDeviceNumber, a1, a2);			
  3955 			}
  3956 			break;
  3957 		case EDisplayHalSetDisplayState:
  3958 			{
  3959 			//increase the spinner at both beginning and end of resetting the display state
  3960 			NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount);
  3961 			kumemget32(&iBufferSet[aDeviceNumber].iDisplayState, a1, sizeof(TInt));
  3962 
  3963 			switch(iBufferSet[aDeviceNumber].iDisplayState)
  3964 				{
  3965 				case ENoResolution:
  3966 				case EDisconnect:
  3967 				case ESingleResolution:
  3968 					// the fascia effect of 0x0 resolution
  3969 					SetDisplaySize(aDeviceNumber, 0, 0);
  3970 					break;
  3971 				}
  3972 
  3973 			NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount);
  3974 			}
  3975 			break;
  3976 		case EDisplayHalGetStateSpinner:
  3977 			{
  3978 			kumemput32(a1,&iBufferSet[aDeviceNumber].iStateChangeCount,
  3979 					sizeof(iBufferSet[aDeviceNumber].iStateChangeCount));
  3980 			}
  3981 			break;
  3982 		default:
  3983 			r=KErrNotSupported;
  3984 			break;
  3985 		}
  3986 	return r;
  3987 	}
  3988 
  3989 TInt DMasterIni::NumberOfResolutions(TInt aDeviceNumber, TAny* a1, TAny* a2)
  3990 	{
  3991 	TInt numberOfConfigs;
  3992 	switch(iBufferSet[aDeviceNumber].iDisplayState)
  3993 		{
  3994 		case ENoResolution:
  3995 			{
  3996 			numberOfConfigs = 0;
  3997 			}
  3998 			break;
  3999 		case EDisconnect:
  4000 			{
  4001 			return KErrDisconnected;
  4002 			}
  4003 			break;
  4004 		case ESingleResolution:
  4005 			{
  4006 			numberOfConfigs = 1;
  4007 			}
  4008 			break;
  4009 		case ENormalResolution:
  4010 		default:
  4011 			{
  4012 			numberOfConfigs = iSystemInis.Count();
  4013 			if (numberOfConfigs > 1)
  4014 				{
  4015 				TVideoInfoV01 info1;
  4016 				TVideoInfoV01 info2;
  4017 				iSystemInis[0]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info1, ETrue);
  4018 				iSystemInis[1]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info2, ETrue);
  4019 				if (info1.iSizeInPixels.iWidth == info2.iSizeInPixels.iWidth &&
  4020 						info1.iSizeInPixels.iHeight == info2.iSizeInPixels.iHeight)
  4021 					{
  4022 					numberOfConfigs = 1;	//It looks like all resolutions for this device are the same
  4023 					}
  4024 				}
  4025 			}
  4026 		}
  4027 	kumemput32(a1,&numberOfConfigs,sizeof(numberOfConfigs));
  4028 	if(a2)
  4029 		{
  4030 		kumemput32(a2,&(iBufferSet[aDeviceNumber].iStateChangeCount),sizeof(iBufferSet[aDeviceNumber].iStateChangeCount));
  4031 		}
  4032 	return KErrNone;
  4033 	}
  4034 
  4035 TInt DMasterIni::SpecificScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* a2)
  4036 	{
  4037 	TInt config;
  4038 	switch(iBufferSet[aDeviceNumber].iDisplayState)
  4039 		{
  4040 		case ENoResolution: //Do Nothing
  4041 			break;
  4042 		case EDisconnect:
  4043 			{
  4044 			return KErrDisconnected;
  4045 			}
  4046 			break;
  4047 		case ESingleResolution: //fill (0,0) as the only element in resolution array
  4048 			{
  4049 			if(*(TInt*)a1 == 0)
  4050 				{
  4051 				TVideoInfoV01 info;
  4052 				info.iSizeInPixels.iHeight = 0;
  4053 				info.iSizeInPixels.iWidth = 0;
  4054 				info.iSizeInTwips.iHeight = 0;
  4055 				info.iSizeInTwips.iWidth = 0;
  4056 				TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info));
  4057 				Kern::InfoCopy(*(TDes8*)a2, infoPtr);
  4058 				}
  4059 			}
  4060 			break;
  4061 		case ENormalResolution:
  4062 		default:
  4063 			{
  4064 			kumemget32(&config, a1, sizeof(config));
  4065 			TPckgBuf<TVideoInfoV01> vPckg;
  4066 			iSystemInis[config]->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue);
  4067 			Kern::InfoCopy(*(TDes8*)a2,vPckg);
  4068 			}
  4069 		}
  4070 	return KErrNone;
  4071 	}
  4072 
  4073 TInt DMasterIni::CurrentScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* /*a2*/)
  4074 	{
  4075 	switch(iBufferSet[aDeviceNumber].iDisplayState)
  4076 		{
  4077 		case ENoResolution: //Do Nothing
  4078 			break;
  4079 		case EDisconnect:
  4080 			{
  4081 			return KErrDisconnected;
  4082 			}
  4083 			break;
  4084 		case ESingleResolution: //fill (0,0)
  4085 			{
  4086 			TVideoInfoV01 info;
  4087 			info.iSizeInPixels.iHeight = 0;
  4088 			info.iSizeInPixels.iWidth = 0;
  4089 			info.iSizeInTwips.iHeight = 0;
  4090 			info.iSizeInTwips.iWidth = 0;
  4091 			TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info));
  4092 			Kern::InfoCopy(*(TDes8*)a1, infoPtr);
  4093 			}
  4094 			break;
  4095 		case ENormalResolution:
  4096 		default:
  4097 			{
  4098 			TPckgBuf<TVideoInfoV01> vPckg;
  4099 			systemIni->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue);
  4100 			Kern::InfoCopy(*(TDes8*)a1,vPckg);
  4101 			}
  4102 		}
  4103 	return KErrNone;
  4104 	}
  4105 
  4106 TInt DMasterIni::DoXYHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2)
  4107 	{
  4108 	return static_cast<DMasterIni*>(aThis)->XYHalFunction(aFunction,a1,a2);
  4109 	}
  4110 
  4111 TInt DMasterIni::XYHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/)
  4112 	{
  4113 	TInt r=KErrNone;
  4114 	switch(aFunction)
  4115 		{
  4116 		case EDigitiserHalXYInfo:
  4117 			{
  4118 			if(systemIni->iXYInputType==EXYInputPointer)
  4119 				{
  4120 				TPckgBuf<TDigitiserInfoV01> vPckg;
  4121 				TDigitiserInfoV01& xyinfo=vPckg();
  4122 				xyinfo.iDigitiserSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX);		
  4123 				xyinfo.iDigitiserSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY);
  4124 				xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX;
  4125 				xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY;
  4126 				Kern::InfoCopy(*(TDes8*)a1,vPckg);
  4127 				}
  4128 			else
  4129 				r=KErrNotSupported;
  4130 			}
  4131 			break;
  4132 		default:
  4133 			r=KErrNotSupported;
  4134 			break;
  4135 		}
  4136 	return r;
  4137 	}
  4138 
  4139 TInt DMasterIni::DoMouseHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2)
  4140 	{
  4141 	return static_cast<DMasterIni*>(aThis)->MouseHalFunction(aFunction,a1,a2);
  4142 	}
  4143 
  4144 TInt DMasterIni::MouseHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/)
  4145 	{
  4146 	TInt r=KErrNone;
  4147 	switch(aFunction)
  4148 		{
  4149 		case EMouseHalMouseInfo:
  4150 			{
  4151 			if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse)
  4152 				{
  4153 				TPckgBuf<TMouseInfoV01> vPckg;
  4154 				TMouseInfoV01& xyinfo=vPckg();
  4155 				xyinfo.iMouseButtons=2;
  4156 				xyinfo.iMouseAreaSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX);		
  4157 				xyinfo.iMouseAreaSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY);
  4158 				xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX;
  4159 				xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY;
  4160 				Kern::InfoCopy(*(TDes8*)a1,vPckg);
  4161 				}
  4162 			else
  4163 				r=KErrNotSupported;
  4164 			}
  4165 			break;
  4166 		default:
  4167 			r=KErrNotSupported;
  4168 			break;
  4169 		}
  4170 	return r;
  4171 	}
  4172 
  4173 TInt DMasterIni::DoKbdHalFunction(TAny* /*aThis*/, TInt aFunction, TAny* /*a1*/, TAny* /*a2*/)
  4174 	{
  4175 	// don't actually do anything, just enough to report a Keyboard is present
  4176 	TInt r=KErrNone;
  4177 	if(aFunction!=EKeyboardHalKeyboardInfo)
  4178 		r=KErrNotSupported;
  4179 	return r;
  4180 	}
  4181 
  4182 void Inactive()
  4183 //
  4184 // Window has been minimised.
  4185 //
  4186     {
  4187 
  4188 	TRawEvent v;
  4189 	v.Set(TRawEvent::EInactive);
  4190     TheEventQ.Add(v);
  4191     }
  4192 
  4193 void UpdateModifiers()
  4194 //Updates the modifier key states and sends an event to wserv about the 
  4195 //change in state
  4196 	{
  4197 	TRawEvent v;
  4198 	TInt modifiers=0;
  4199     if(GetKeyState(VK_SCROLL)&1)
  4200         modifiers|=EModifierScrollLock;
  4201     if(GetKeyState(VK_NUMLOCK)&1)
  4202         modifiers|=EModifierNumLock;
  4203     if(GetKeyState(VK_CAPITAL)&1)
  4204         modifiers|=EModifierCapsLock;
  4205     v.Set(TRawEvent::EUpdateModifiers,modifiers);
  4206     TheEventQ.Add(v);
  4207 	}
  4208 	
  4209 void Active()
  4210 //
  4211 // Window has been restored.
  4212 // Update the toggling modifiers, reset any others
  4213 //
  4214     {
  4215 	TRawEvent v;
  4216     UpdateModifiers();
  4217     v.Set(TRawEvent::EActive);
  4218     TheEventQ.Add(v);
  4219     }
  4220 
  4221 
  4222 void ClearScreen()
  4223     {
  4224 
  4225     }
  4226 
  4227 
  4228 TInt DWinsUi::GetVirtualKey(TEmulCommand& aCommand, TInt aX, TInt aY)
  4229 	{
  4230 	//if the point is in the list of shapes, set the key and return true
  4231 	for (TInt keyCount = iVirtualKeys.Count(); --keyCount >= 0; )
  4232 		{
  4233 		const VirtualKey& vk = *iVirtualKeys[keyCount];
  4234 		if (vk.Contains(aX, aY))
  4235 			{
  4236 			aCommand = vk.Command();
  4237 			return vk.Value();
  4238 			}
  4239 		}
  4240 	return -1;
  4241 	}
  4242 
  4243 void DWinsUi::TranslateMouseCoords(const TEmulatorFlip aFlipState, const TInt aX, const TInt aY, const TInt aRegionWidth, const TInt aRegionHeight, TInt& aNewX, TInt& aNewY)
  4244 	{
  4245 	switch (aFlipState)
  4246 		{
  4247 		case EEmulatorFlipRestore:
  4248 			aNewX = aX;
  4249 			aNewY = aY;
  4250 			break;
  4251 		
  4252 		case EEmulatorFlipInvert:
  4253 			aNewX = aRegionWidth - aX;
  4254 			aNewY = aRegionHeight - aY;
  4255 			break;
  4256 		
  4257 		case EEmulatorFlipLeft:
  4258 			aNewX = aRegionWidth - aY;
  4259 			aNewY = aX;
  4260 			break;
  4261 
  4262 		case EEmulatorFlipRight:
  4263 			aNewX = aY;
  4264 			aNewY = aRegionHeight - aX;
  4265 			break;
  4266 		}
  4267 	}
  4268 
  4269 
  4270 TBool DWinsUi::OnScreen(TInt aScreen, TInt ax, TInt ay) const
  4271 //
  4272 // Checks if a point within the Emulator window is on the screen
  4273 //
  4274 	{
  4275 	return (TUint(ax) < TUint(systemIni->iScreens[aScreen]->iScreenWidth) && TUint(ay) < TUint(systemIni->iScreens[aScreen]->iScreenHeight));
  4276 	}
  4277 
  4278 TInt DWinsUi::Create(TInt aId)
  4279 	{
  4280 	TInt r = SetupProperties(aId);
  4281 	if (r != KErrNone)
  4282 		return r;
  4283 	TInt screen;
  4284 	DScreenProperties* currentScreen = NULL;
  4285 	for(screen=0;screen<iScreens.Count();screen++)
  4286 		{
  4287 		BITMAPINFOHEADER bitmapinfo;
  4288 		currentScreen = iScreens[screen];
  4289 		if (readBitmapInfo(&bitmapinfo, currentScreen->iFasciaFileName) == KErrNone)
  4290 			{
  4291 			currentScreen->iXYInputWidth=bitmapinfo.biWidth;
  4292 			currentScreen->iXYInputHeight=bitmapinfo.biHeight;
  4293 			}
  4294 		currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,currentScreen->iScreenWidth+currentScreen->iScreenOffsetX);
  4295 		currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,currentScreen->iScreenHeight+currentScreen->iScreenOffsetY);
  4296 		}
  4297 
  4298 	currentScreen = iScreens[0];
  4299 	//note digitizer offsets are relative to EPOC screen 0
  4300 	if (-1 == iDigitizerWidth)
  4301 		iDigitizerWidth = currentScreen->iXYInputWidth - 
  4302 			(currentScreen->iScreenOffsetX + iDigitizerOffsetX);
  4303 	else
  4304 		currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,iDigitizerWidth);
  4305 
  4306 	if (-1 == iDigitizerHeight)
  4307 		iDigitizerHeight = currentScreen->iXYInputHeight - 
  4308 			(currentScreen->iScreenOffsetY + iDigitizerOffsetY);
  4309 	else
  4310 		currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,iDigitizerHeight);
  4311 
  4312 	return r;
  4313 	}
  4314 
  4315 const RDisplayChannel::TPixelFormat DMasterIni::iSupportedPixelFormatTable[] =
  4316 	{
  4317 		EUidPixelFormatXRGB_8888,
  4318 		EUidPixelFormatARGB_8888,
  4319 		EUidPixelFormatARGB_8888_PRE,
  4320 		EUidPixelFormatXRGB_4444,
  4321 		EUidPixelFormatARGB_4444,
  4322 		EUidPixelFormatRGB_565 
  4323 	};
  4324 
  4325 const TInt DMasterIni::iSupportedPixelFormatTableSize = static_cast<TInt>(sizeof(iSupportedPixelFormatTable)/
  4326 		                                                                  sizeof(iSupportedPixelFormatTable[0]));
  4327 
  4328 void DMasterIni::InitBufferFormat(DScreenProperties& aScreenProperties, RDisplayChannel::TBufferFormat& aBufferFormat)
  4329 	{
  4330 	TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth);
  4331 	
  4332 	aBufferFormat.iSize.iWidth = aScreenProperties.iMaxScreenWidth;
  4333 	aBufferFormat.iSize.iHeight = aScreenProperties.iMaxScreenHeight;
  4334 	switch (bitsPerPixel)
  4335 		{
  4336 	case 12:	// XRGB4444
  4337 		aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_4444;
  4338 		break;
  4339 	case 16:	// RGB565
  4340 		aBufferFormat.iPixelFormat = EUidPixelFormatRGB_565;
  4341 			break;
  4342 	case 24:	// Really 32bpp, but top 8 unused
  4343 	case 32:	// While 32bpp, top 8 will not be used
  4344 	default:
  4345 		aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_8888;
  4346 			break;
  4347 		}
  4348 	}
  4349 
  4350 TInt DMasterIni::Create()
  4351 	{
  4352 	TInt configurations = Property::GetInt("ConfigCount", 0);
  4353 	if (configurations == 0)
  4354 		return KErrGeneral;
  4355 
  4356 	// the pixel formats table is, at present, configuration independent
  4357 	TInt count;
  4358 	TInt r = KErrNone;
  4359 	for (count = 0; count < configurations && r == KErrNone; ++count)
  4360 		{
  4361 		DWinsUi* dwi = new DWinsUi;
  4362 		if (dwi)
  4363 			r = dwi->Create(count);
  4364 
  4365 		if (r == KErrNone)
  4366 			iSystemInis.Append(dwi);
  4367 		}
  4368 	if (r != KErrNone)
  4369 		return r;
  4370 
  4371 	systemIni = masterIni->iSystemInis[0];
  4372 
  4373 	WinsGuiPowerHandler = DWinsGuiPowerHandler::New();
  4374 	if (!WinsGuiPowerHandler)
  4375 		return KErrNoMemory;
  4376 
  4377 	TheWin=new HWND[systemIni->iScreens.Count()];
  4378 	TheChildWin=new HWND[systemIni->iScreens.Count()];
  4379 	TheScreenBitmap=new HBITMAP[systemIni->iScreens.Count()];
  4380 	CurrentFlipState=new TEmulatorFlip[systemIni->iScreens.Count()];
  4381 
  4382 	if(!TheWin || !TheChildWin || !TheScreenBitmap || !CurrentFlipState)
  4383 		return KErrNoMemory;
  4384 	memset(CurrentFlipState,EEmulatorFlipRestore,systemIni->iScreens.Count());
  4385 
  4386 	TBufferSet buffer;
  4387 	buffer.iDisplayDriverCount = 0;
  4388 	buffer.iDisplayState = ENormalResolution;
  4389 	buffer.iDisplayBuffer = 0;
  4390 	buffer.iDisplayChannel = NULL;
  4391 
  4392 
  4393 	TInt i;
  4394 	for(i=0;i<systemIni->iScreens.Count();i++)
  4395 		{
  4396 		DScreenProperties *pScr = systemIni->iScreens[i];
  4397 
  4398 		masterIni->InitBitmapHeader(*pScr, &buffer.iInfo);
  4399 		masterIni->InitBufferFormat(*pScr, buffer.iBufferFormat);
  4400 
  4401 		r = masterIni->iBufferSet.Append(buffer);
  4402 		if (r != KErrNone)
  4403 			return r;
  4404 		}
  4405 
  4406 	if (CreateWin32Thread(EThreadEvent, &KernelWindowThread, NULL, ETrue) == NULL)
  4407 		return KErrGeneral;
  4408 
  4409 	for(i=0;i<systemIni->iScreens.Count();i++)
  4410 		{
  4411 		r = Kern::AddHalEntry(EHalGroupDisplay,&DoHalFunction,(TAny*)i,i);
  4412 		if (r != KErrNone)
  4413 			return r;
  4414 		}
  4415 
  4416 	// should really come from Keyboard driver, but not doing it now...
  4417 	r = Kern::AddHalEntry(EHalGroupKeyboard,&DoKbdHalFunction,this);
  4418 	if (r != KErrNone)
  4419 		return r;
  4420 
  4421 	if(systemIni->iXYInputType==EXYInputPointer)
  4422 		{
  4423 		r = Kern::AddHalEntry(EHalGroupDigitiser,&DoXYHalFunction,this);
  4424 		if (r != KErrNone)
  4425 			return r;
  4426 		}
  4427 	else if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse)
  4428 		{
  4429 		r = Kern::AddHalEntry(EHalGroupMouse,&DoMouseHalFunction,this);
  4430 		if (r != KErrNone)
  4431 			return r;
  4432 		}
  4433 
  4434 	return r;
  4435 	}
  4436 
  4437 void DMasterIni::InitBitmapHeader(DScreenProperties& aScreenProperties, LPBITMAPV4HEADER aInfo)
  4438 	{
  4439 	TInt width = aScreenProperties.iMaxScreenWidth; 
  4440 	TInt height = aScreenProperties.iMaxScreenHeight;
  4441 	TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth);
  4442 
  4443 	memset(aInfo, 0, sizeof(BITMAPV4HEADER));
  4444 
  4445 	switch (bitsPerPixel)
  4446 		{
  4447 	case 12:	// XRGB4444
  4448 			aInfo->bV4BitCount = 16;
  4449 			aInfo->bV4V4Compression = BI_BITFIELDS;
  4450 			aInfo->bV4RedMask   = 0x0F00;
  4451 			aInfo->bV4GreenMask = 0x00F0;
  4452 			aInfo->bV4BlueMask  = 0x000F;
  4453 			break;
  4454 	case 16:	// RGB565
  4455 			aInfo->bV4BitCount = 16;
  4456 			aInfo->bV4V4Compression = BI_BITFIELDS;
  4457 			aInfo->bV4RedMask   = 0xF800;
  4458 			aInfo->bV4GreenMask = 0x07E0;
  4459 			aInfo->bV4BlueMask  = 0x001F;
  4460 			break;
  4461 	case 24:	// Really 32bpp, but top 8 unused
  4462 	case 32:	// While 32bpp, top 8 will not be used
  4463 	default:
  4464 			aInfo->bV4BitCount = 32;
  4465 			aInfo->bV4V4Compression = BI_RGB;
  4466 			// Mask is implicit for BI_RGB compression
  4467 			break;
  4468 		}
  4469 	
  4470 	aInfo->bV4Size = sizeof(BITMAPV4HEADER);
  4471 	aInfo->bV4Width = width;
  4472 	aInfo->bV4Height = -height;	// Bitmap runs top to bottom
  4473 	aInfo->bV4Planes = 1;
  4474 	
  4475 	TInt bpp = _ALIGN_UP(aInfo->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32
  4476 	TInt widthInPixel = aInfo->bV4Width * bpp;
  4477 	//rounding to 32 bits (4 octets) and converting, then, bits to octets;
  4478 	TInt scanLineInBytes = _ALIGN_UP(widthInPixel, 32) >> 3; 
  4479 	aInfo->bV4SizeImage = -aInfo->bV4Height * scanLineInBytes;
  4480 
  4481 	// Set color space as uncalibrated. All other members are then ignored.
  4482 #if defined(LCS_DEVICE_RGB)
  4483 	aInfo->bV4CSType = LCS_DEVICE_RGB;
  4484 #elif defined(LCS_sRGB)
  4485 	aInfo->bV4CSType = LCS_sRGB;
  4486 #endif
  4487 	}
  4488 
  4489 // Helper function that allocates a single frame buffer. 
  4490 static TInt AllocateOneFrameBuffer(TInt aSize, TScreenBuffer &aScreenBuffer)
  4491 	{
  4492     // Open shared chunk to the composition framebuffer
  4493 	DChunk* chunk = 0;
  4494 	// round to page size
  4495 	if (aSize <= 0)
  4496 		return KErrArgument;
  4497 	TUint round = Kern::RoundToPageSize(aSize);
  4498 	TLinAddr chunkKernelAddr = 0;
  4499 	TUint32 physicalAddress = 0;
  4500 	TUint32 chunkMapAttr = 0;
  4501 
  4502 	// create shared chunk
  4503 	NKern::ThreadEnterCS();
  4504 
  4505 	TChunkCreateInfo info;
  4506 	info.iType = TChunkCreateInfo::ESharedKernelMultiple;
  4507 	info.iMaxSize = round;
  4508 	info.iMapAttr = 0;
  4509 	info.iOwnsMemory = ETrue;
  4510 	info.iDestroyedDfc = 0;
  4511 
  4512 	TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr);
  4513 	if (r == KErrNone)
  4514 		{
  4515 		// map our chunk to specific 
  4516 		r = Kern::ChunkCommitContiguous(chunk, 0, aSize, physicalAddress);
  4517 		if (r != KErrNone)
  4518 			{
  4519 			Kern::ChunkClose(chunk);
  4520 			}
  4521 		}
  4522 
  4523 	if (r == KErrNone)
  4524 		{
  4525 		TBufferAddressA* bufferAddress = new TBufferAddressA;
  4526 		if (!bufferAddress)
  4527 			{
  4528 			r = KErrNoMemory;
  4529 			}
  4530 		else 
  4531 			{
  4532 			bufferAddress->iAddress = (TAny*)chunkKernelAddr;
  4533 			bufferAddress->iChunk = chunk;
  4534 
  4535 			if ((r = aScreenBuffer.iFrameBuffers.Append(bufferAddress->iAddress)) == KErrNone)
  4536 				{
  4537 				r = aScreenBuffer.iMemChunks.Append(bufferAddress);
  4538 				}
  4539 			}
  4540 		}
  4541 	if (r != KErrNone)
  4542 		{
  4543 		Kern::ChunkClose(chunk);
  4544 		}
  4545 	NKern::ThreadLeaveCS();
  4546 	return KErrNone;
  4547 	}
  4548 
  4549 TInt DMasterIni::AllocateFrameBuffers(TInt aScreenNumber, TInt aCount, TInt aSize)
  4550 	{
  4551 	while (aCount--)
  4552 		{
  4553 		TInt r = AllocateOneFrameBuffer(aSize, masterIni->iBufferSet[aScreenNumber].iScreenBuffer);
  4554 		if (r != KErrNone)
  4555 			{
  4556 			return r;
  4557 			}
  4558 		}
  4559 	return KErrNone;
  4560 	}
  4561 
  4562 void DMasterIni::ReleaseFrameBuffers(TInt aScreenNumber)
  4563 	{
  4564 	RPointerArray<TAny>& frameBuffers = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iFrameBuffers;
  4565 	RPointerArray<TBufferAddressA>& memChunks = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iMemChunks;
  4566 	RPointerArray<TBufferAddressA>& dsaChunks = masterIni->iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks;
  4567 
  4568    	NKern::ThreadEnterCS();
  4569 	TInt index;
  4570 	TInt count = memChunks.Count();
  4571 	for (index = 0; index < count; index++)
  4572 		{
  4573 		Kern::ChunkClose(memChunks[index]->iChunk);
  4574 		}
  4575 	count = dsaChunks.Count();
  4576 	for (index = 0; index < count; index++)
  4577 		{
  4578 		Kern::ChunkClose(dsaChunks[index]->iChunk);
  4579 		}
  4580 	NKern::ThreadLeaveCS();
  4581 	
  4582 	frameBuffers.Reset();
  4583 	memChunks.Reset();
  4584 	dsaChunks.Reset();
  4585 	}
  4586 
  4587 
  4588 TProcessAddrEntry::TProcessAddrEntry(DProcess *aProcess, TUint8* aAddress): 
  4589 	iProcess(aProcess), iAddress(aAddress)
  4590 	{
  4591 	}
  4592 
  4593 
  4594 /**
  4595 Contruct a Shared Chunk cleanup object which will be used to clean up 
  4596 after the process/address table entry. 
  4597 */
  4598 TChunkCleanup::TChunkCleanup(DProcess* aProcess, TInt aScreenNumber)
  4599     : TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0)
  4600     , iProcess(aProcess)
  4601     , iScreenNumber(aScreenNumber)
  4602     , iIndex(-1)
  4603     {}
  4604 
  4605 /**
  4606 Cancel the action of the cleanup object.
  4607 */
  4608 void TChunkCleanup::Cancel()
  4609     {
  4610     // Clear iProcess which means that when the DFC gets queued on chunk destruction
  4611     // our ChunkDestroyed method will do nothing other than cleanup itself.
  4612     iProcess = NULL;
  4613     }
  4614 
  4615 /**
  4616 Callback function called when the DFC runs, i.e. when a chunk is destroyed.
  4617 */
  4618 void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf)
  4619     {
  4620     DProcess* process = aSelf->iProcess;
  4621     TInt screenNumber = aSelf->iScreenNumber;
  4622     TUint index = aSelf->iIndex;
  4623     // If we haven't been Cancelled...
  4624     if(process && index != -1)
  4625         {
  4626     	if (masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess == process)
  4627     		{
  4628     		masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess = 0;
  4629     		}
  4630     	else
  4631     		{
  4632     		__KTRACE_OPT(KEXTENSION,Kern::Printf("Oops! Someone has messed up our process index!"));
  4633     		}
  4634         }
  4635 
  4636     // We've finished so now delete ourself
  4637     delete aSelf;
  4638     }
  4639 
  4640 
  4641 TInt DMasterIni::DisplayMemoryHandle(TInt aScreenNumber, TInt& aHandle)
  4642 	{
  4643 	if (iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks.Count() == 0)
  4644 		{	
  4645 		int r;
  4646 		r = AllocateOneFrameBuffer(iMaxSizeInBytes, iBufferSet[aScreenNumber].iDsaBuffer);
  4647 		if (KErrNone != r)
  4648 			{
  4649 			return r;
  4650 			}
  4651 		__ASSERT_DEBUG(iBufferSet[aScreenNumber].iDisplayChannel, Fault(EGuiNoDisplayChannel));
  4652 		iBufferSet[aScreenNumber].iDisplayChannel->SetLegacyBuffer(iBufferSet[aScreenNumber].iDsaBuffer.iFrameBuffers[0]);
  4653 		}
  4654 	
  4655 	aHandle = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), 
  4656 			iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks[0]->iChunk);
  4657 	
  4658 	if (aHandle < 0)
  4659 		{
  4660 		return aHandle;
  4661 		}
  4662 	
  4663 	return KErrNone;
  4664 	}
  4665 
  4666 
  4667 
  4668 // Find the address of the display memory. 
  4669 TInt DMasterIni::DisplayMemoryAddress(TInt aScreenNumber, TInt& aAddress)
  4670 	{
  4671 	TBufferSet &bufferSet = iBufferSet[aScreenNumber]; 
  4672 	DProcess *process = &Kern::CurrentProcess();
  4673 	TInt firstFree = -1;
  4674 	NKern::FMWait(&iLock);
  4675 	TUint count = bufferSet.iProcAddrTable.Count();
  4676 	for(TUint i = 0; i < count; ++i)
  4677 		{
  4678 		DProcess *curProcess = bufferSet.iProcAddrTable[i].iProcess;
  4679 		if (curProcess == process)
  4680 			{
  4681 			aAddress = reinterpret_cast<TInt>(bufferSet.iProcAddrTable[i].iAddress);
  4682 			NKern::FMSignal(&iLock);
  4683 			return KErrNone;
  4684 			}
  4685 		if (curProcess == 0 && firstFree == -1)
  4686 			{
  4687 			firstFree = i;
  4688 			}
  4689 		}
  4690 	NKern::FMSignal(&iLock);
  4691 	// If we get here, we couldn't find the process in the iProcAddrTable. 
  4692 	// Create a new Process Address entry. 
  4693 	// Step 1
  4694 	// Create a dummy chunk so that we can detect when the process dies, 
  4695 	// give a handle to the user [but don't actually let the process KNOW what the handle is
  4696 	// so the user process can't do anything silly with the chunk]. Close our side of the
  4697 	// chunk to make sure there is only one reference to it. 
  4698 	DChunk* chunk = 0;
  4699 	// find page size for one page. 
  4700 	TUint round = Kern::RoundToPageSize(1);
  4701 	TLinAddr chunkKernelAddr = 0;
  4702 	TUint32 chunkMapAttr = 0;
  4703 	
  4704 	// create shared chunk
  4705 	NKern::ThreadEnterCS();
  4706 	// Cleanup object, used to issue a DFC when the chunk is closed (and 
  4707 	// as the handle of the chunk is not given to the process, it can only
  4708 	// be closed when the process terminates!)
  4709 	TChunkCleanup *cleanup = new TChunkCleanup(process, aScreenNumber);
  4710 	if (!cleanup)
  4711 		{
  4712 		NKern::ThreadLeaveCS();
  4713 		return KErrNoMemory;
  4714 		}
  4715 
  4716 	TChunkCreateInfo info;
  4717 	info.iType = TChunkCreateInfo::ESharedKernelMultiple;
  4718 	info.iMaxSize = round;
  4719 	info.iMapAttr = 0;
  4720 	info.iOwnsMemory = ETrue;
  4721 	info.iDestroyedDfc = cleanup;
  4722 
  4723 	TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr);
  4724 	
  4725 	if (r != KErrNone)
  4726 		{
  4727 		delete cleanup;
  4728 		NKern::ThreadLeaveCS();
  4729 		return r;
  4730 		}
  4731 	
  4732 	
  4733 	// Create a new handle for the user thread. 
  4734     r = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), chunk);
  4735 	Kern::ChunkClose(chunk);
  4736 	if (r <= 0)
  4737 		{
  4738 		NKern::ThreadLeaveCS();
  4739 		return r;
  4740 		}
  4741 
  4742 	// Step 2
  4743 	// Create a second handle for the chunk to the DSA buffer.
  4744 	// First part: Make sure there is a DisplayMemoryHandle;
  4745 	TInt handle = 0;
  4746 	r = DisplayMemoryHandle(aScreenNumber, handle); 
  4747 	if (r != KErrNone)
  4748 		{
  4749 		Kern::ChunkClose(chunk);
  4750 		NKern::ThreadLeaveCS();
  4751 		return r;
  4752 		}
  4753 	
  4754 	DChunk *dsaChunk = bufferSet.iDsaBuffer.iMemChunks[0]->iChunk;
  4755 	
  4756 	// Step 3
  4757 	// Get the base addrss and insert into table. 
  4758 	TUint8* baseAddress = Kern::ChunkUserBase(dsaChunk, &Kern::CurrentThread());
  4759 	NKern::FMWait(&iLock);
  4760 	// Optimistically, the place we found earlier in the table is still free.
  4761 	if (firstFree != -1 && bufferSet.iProcAddrTable[firstFree].iProcess != 0)
  4762 		{
  4763 		// If not, we go find another one.
  4764 		firstFree = -1;
  4765 		TUint count = bufferSet.iProcAddrTable.Count();
  4766 		for(TUint i = 0; i < count; ++i)
  4767 			{
  4768 			if (bufferSet.iProcAddrTable[i].iProcess == 0)
  4769 				{
  4770 				firstFree = i;
  4771 				break;
  4772 				}
  4773 			}
  4774 		}
  4775 	// Check if there is a free entry - if so, re-use it. 
  4776 	if (firstFree != -1)
  4777 		{
  4778 		bufferSet.iProcAddrTable[firstFree].iProcess = process;
  4779 		bufferSet.iProcAddrTable[firstFree].iAddress = baseAddress;
  4780 		cleanup->SetIndex(firstFree);
  4781 		NKern::FMSignal(&iLock);
  4782 		}
  4783 	else
  4784 		{
  4785 		// No free entry. Append it to the list. 
  4786 		NKern::FMSignal(&iLock);
  4787 		TProcessAddrEntry entry(process, baseAddress);
  4788 		r = bufferSet.iProcAddrTable.Append(entry);
  4789 		if (r != KErrNone)
  4790 			{
  4791 			Kern::ChunkClose(chunk);
  4792 			NKern::ThreadLeaveCS();
  4793 			return r;
  4794 			}
  4795 		// We added it at the end - so we start from the back and check for the 
  4796 		// process, as some other process COULD have added one after us, so we 
  4797 		// can't just use the count for index!
  4798 		TUint index;
  4799 		for(index = bufferSet.iProcAddrTable.Count()-1; index; --index)
  4800 			{
  4801 			if (bufferSet.iProcAddrTable[index].iProcess == process 
  4802 					&& bufferSet.iProcAddrTable[index].iAddress != baseAddress)
  4803 				{
  4804 				break;
  4805 				}
  4806 			}
  4807 		cleanup->SetIndex(index);
  4808 		}
  4809 	aAddress = reinterpret_cast<TInt>(baseAddress);
  4810 
  4811 	NKern::ThreadLeaveCS();
  4812 	return KErrNone;
  4813 	}
  4814 
  4815 EXPORT_C TInt WinsGui::CurrentConfiguration()
  4816 	{
  4817 	return ::CurrentConfiguration;
  4818 	}
  4819 
  4820 GLDEF_C void Fault(TGuiPanic aPanic)
  4821 	{
  4822 	Kern::Fault("WINS-UI",aPanic);
  4823 	}
  4824 
  4825 DECLARE_STANDARD_EXTENSION()
  4826 	{
  4827 	__KTRACE_OPT(KEXTENSION,Kern::Printf("Starting Emulator GUI"));
  4828 
  4829 	// if NoGui property == true do nothing
  4830 	if (Property::GetBool("NoGui",EFalse))
  4831 		return KErrNone;
  4832 
  4833 	// create keyboard driver
  4834 	TInt r=KErrNoMemory;
  4835 	masterIni = new DMasterIni;
  4836 	if (masterIni)
  4837 		{
  4838 		r = masterIni->Create();
  4839 		if (r!= KErrNone)
  4840 			{
  4841 			return r;
  4842 			}
  4843 		}
  4844 	
  4845 	DMultiTouch::iMultiTouchSupported = DMultiTouch::Init();
  4846 
  4847 	// Create multitouch when necessary
  4848 	if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled() && DMultiTouch::iMultiTouchSupported)
  4849 		{
  4850 		TheMultiTouch = new DMultiTouch(systemIni->MultiTouchProximityStep(),systemIni->MultiTouchPressureStep());
  4851 		if(!TheMultiTouch)
  4852 			{
  4853 			r = KErrNoMemory;
  4854 			__KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));
  4855 			return r;
  4856 			}
  4857 		DMultiTouch::iMultiTouchCreated = TRUE;
  4858 		}
  4859 
  4860 	__KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));
  4861 	return r;
  4862 	}
  4863 
  4864 TInt DWinsUi::DoDefineEmulatorControlHotKey(TAny* aPtr, const char* aValue)
  4865 	{
  4866 	return static_cast<DWinsUi*>(aPtr)->DefineEmulatorControlHotKey(aValue);
  4867 	}
  4868 
  4869 
  4870 TInt DWinsUi::DefineEmulatorControlHotKey(const char* aValue)
  4871 	{
  4872 	const char* beg = skipws(aValue);
  4873 	const char* end = skiptok(beg);
  4874 	TInt err = KErrNone;
  4875 	
  4876 	TEmulCommand command = ENoCommand;
  4877 	TInt data = 0;
  4878 	if (_strnicmp(beg, "SelectConfig", end-beg) == 0)
  4879 		{
  4880 		//get the int param which is the config to switch to
  4881 		beg = end;
  4882 		char * e;
  4883 		data = strtol(beg, &e,0);
  4884 		if (beg == e)
  4885 			err = KErrArgument;
  4886 		end = e;
  4887 		command = ESelectConfig;
  4888 		}
  4889 	else if(_strnicmp(beg, "NextConfig", end-beg) == 0)
  4890 		{
  4891 		command = ENextConfig;
  4892 		}
  4893 	else
  4894 		{
  4895 		err = KErrArgument;
  4896 		}
  4897 	if (err != KErrNone)
  4898 		return err;
  4899 	
  4900 	// get the keys	
  4901 	KeyCombination* pCombination = new KeyCombination(data, command);
  4902 	if (!pCombination)
  4903 		return KErrNoMemory;	
  4904 	
  4905 	beg = skipws(end);
  4906 	const char* end2;	
  4907 	for (TInt i=0;i<KMaxHotKeyCombinationLength;i++)
  4908 		{
  4909 		TInt key=KErrNotFound;		
  4910 		end2 = skiptok(beg);
  4911 		TPtrC8 name((const TUint8*)beg, end2-beg);
  4912 		if ((key=iKeyboard.GetScanCode(name))!=KErrNotFound)
  4913 			pCombination->AddKey((TStdScanCode)key);
  4914 		
  4915 		if (beg == end2 || *end2++ != ',') 
  4916 			break;		
  4917 		beg = end2;
  4918 		}
  4919 	return iControlHotKeys.Append(pCombination);
  4920 	}