#include "pch.hpp"
//===========================================================================//
// File:	 WinProc.cpp													 //
// Project:  GameOS					                                         //
// Contents: WinProc routines												 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "WinProc.hpp"
#include "Globals.hpp"
#include "Windows.hpp"
#include "DXRasterizer.hpp"
#include "ErrorHandler.hpp"
#include "ControlManager.hpp"
#include "Texture Manager.hpp"
#include "Debugger.hpp"
#include "3DRasterizer.hpp"
#include "DirectX.hpp"

extern bool ChangingModes;
extern DWORD LastWMDown;		// Last WM_KEYDOWN message scan code
extern DWORD SpecialRender;		// In a special debugger mode
bool ControlDown=0;				// Control key is currently down
bool WindowsPause=0;
extern DWORD DebuggerMouse;
extern DWORD gPrintScreen;
extern DWORD gCaptureScreen;
extern DWORD GlobalGotoFullScreen;
extern DWORD GlobalGotoWindowMode;

HCURSOR ArrowCursor;
DWORD HitScrollLock=0;


extern DWORD g_DDstate;
extern bool g_DDperformFlip;

extern ControlManagerDataStruct g_CMData;
extern LPARAM ProcessIMEMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool * trapped );
extern void SetExtended( BYTE vk, BOOL bState );
extern DWORD gNumLockMode;
extern DWORD gCapLockMode;
extern DWORD gScrollLockMode;

// hyun begin
void (__stdcall *g_pfnRIO_ButtonEvent)(BYTE* by) = NULL;
// hyun end
//

//
// Update the windows cursor
//
UINT LastlParam=0;

void UpdateCursor()
{
	if( (gActive && gGotFocus) && !ProcessingError && (LOWORD(LastlParam)==HTCLIENT || Environment.fullScreen) )
	{
		if( (gHardwareMouse || DebuggerMouse) && 0==Environment.fullScreen && 0==(Compatibility3D&BadMouse) )
		{
			SetCursor(ArrowCursor);
		}
		else
		{
			SetCursor(0);
		}
	}
	else
	{
		SetCursor(ArrowCursor);
	}
}

LRESULT CALLBACK GameOSWinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
//
// Early out frequent messages
//
	if(	uMsg==WM_NCHITTEST ||
		uMsg==WM_MOUSEMOVE )
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
//
// Handle mouse message first (happens often)
//
	if(	uMsg==WM_SETCURSOR )
	{
		if( Platform!=Platform_Game )
			return DefWindowProc(hWnd, uMsg, wParam, lParam);
//
// Always off during fullscreen or over client
//
		LastlParam=lParam;
		UpdateCursor();
		return 1;
	}
//
// SPEW messages
//
	#ifdef _ARMOR
		char *MessageInfo=GetWindowsMessage(uMsg,wParam,lParam);
		if( MessageInfo )
			SPEW(( GROUP_WINDOWSMESSAGES, MessageInfo ));
	#endif
	
	switch( uMsg )
	{
		// hyun
		case WM_USER + 100:
		{
			// hyun begin
			if (g_pfnRIO_ButtonEvent) {
				(*g_pfnRIO_ButtonEvent)((BYTE*)&lParam);
			}
			// hyun end
		}
		break;
//
// Handle display changes, update window
//
	case WM_SYSCOLORCHANGE:
	case WM_DISPLAYCHANGE:
	{
		if( 0==(Compatibility3D&SlowDisplayModeChange) && !ChangingModes)
		{
			DoUpdateWindow=1;
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - WM_SYSCOLORCHANGE or WM_DISPLAYCHANGE" ));
		}
	}
	break;
//
///////////////////////////////////////////////////////////////////////
// Paint message - clear it and use default (Do not update display!) //
///////////////////////////////////////////////////////////////////////
//
	case WM_PAINT:
	{
		if( !InUpdateRenderers && (g_DDstate==1) && g_DDperformFlip && !Environment.fullScreen && (status==Running || status==GameInit) )
		{
			if( FrontBufferSurface )
			{
				RECT Window;
				Window.left=clientToScreen.x;
				Window.right=clientToScreen.x+Environment.screenWidth;
				Window.top=clientToScreen.y;
				Window.bottom=clientToScreen.y+Environment.screenHeight;
				if( Environment.fullScreen )
				{
					Window.left=0;
					Window.right=Environment.screenWidth;
					Window.top=0;
					Window.bottom=Environment.screenHeight;
				}
				AllowFail=1;
				SafeFPU();
				wBlt( FrontBufferSurface, &Window, BackBufferSurface, NULL, DDBLT_WAIT, NULL );
				GameOSFPU();
				AllowFail=0;
			}
			else
			{
				PAINTSTRUCT ps;
				HDC DestHDC=BeginPaint (hWnd, &ps);
				HDC SourceDC;
				wGetDC( BackBufferSurface, &SourceDC );
				if( DesktopBpp==8 )
				{
					SetStretchBltMode( DestHDC, HALFTONE );
					StretchBlt( DestHDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SRCCOPY );
				}
				else
				{
					BitBlt( DestHDC, 0, 0, Environment.screenWidth, Environment.screenHeight, SourceDC, 0, 0, SRCCOPY );
				}
				wReleaseDC( BackBufferSurface, SourceDC );
				EndPaint (hWnd, &ps);
				return 0;
			}
		}		
//
// Clear PAINT region (so WM_PAINT is not received again).
//
		ValidateRect( hWnd, NULL );
		return 0;
	}
	break;
//
//
//
	case WM_SYSCOMMAND:
	{
		if( (wParam&0xfff0)==SC_KEYMENU )										// Diable ALT key menu
			return 0;
		if( (wParam&0xfff0)==SC_SCREENSAVE || (wParam&0xfff0)==SC_MONITORPOWER)	// Disable screensavers
			return 0;
		if( (wParam&0xfff0)==SC_RESTORE )
		{
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - WM_SYSCOMMAND - SC_RESTORE" ));
			if( Environment.fullScreen )
			{
				DoUpdateWindow=1;
				GlobalGotoFullScreen=1;
			}
			else
			{
				DoUpdateWindow=1;
				GlobalGotoWindowMode=1;
			}
			break;
		}
		if( (wParam&0xfff0)==SC_MAXIMIZE )
		{
			if( !Environment.fullScreen && !ProcessingError )
			{
				SPEW(( GROUP_DIRECTDRAW, "Mode change requested - WM_SYSCOMMAND - SC_MAXIMIZE" ));
				DoUpdateWindow=1;
				GlobalGotoFullScreen=1;
			}
			return 0;
		}
		if( (wParam&0xfff0)==SC_CLOSE )
		{
			WindowClosed=1;
			return 0;
		}
		if( Environment.fullScreen )
		{
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - WM_SYSCOMMAND - other" ));
			DoUpdateWindow=1;
			GlobalGotoWindowMode=1;
		}
	}
	break;
//
// Check for 'system keys' released - keys pressed with ALT
//
	case WM_SYSKEYUP:
	{
		if( wParam==VK_RETURN )				// Alt Enter - don't show application the upcode
			return 0;
		DoKeyReleased( wParam );
	}
	break;
//
// Check for 'system keys' pressed - keys pressed with ALT
//
	case WM_SYSKEYDOWN:
	{
//
// Check for special ALT keys
//
		if( wParam==VK_RETURN )				// Alt Enter
		{
			if( !ProcessingError )
			{
				SPEW(( GROUP_DIRECTDRAW, "Mode change requested - Alt Enter" ));
				if( Environment.fullScreen )
				{
					DoUpdateWindow=1;
					GlobalGotoWindowMode=1;
				}
				else
				{
					DoUpdateWindow=1;
					GlobalGotoFullScreen=1;
				}
				return 0;
			}
		}
		#ifdef LAB_ONLY
		if( wParam==VK_SCROLL )				// Alt Scroll Lock triggers debugger
		{
			if( Environment.fullScreen )
			{
				EnterWindowMode();
			}
			_asm int 3;
			return 0;
		}
		#endif
//
// Store WM_KEYDOWN scan code until a WM_CHAR arrives (or another WM_KEYDOWN)
//
		DealWithKey( wParam, lParam );
	}
	break;
//
//
//
	case WM_SYSCHAR:
	{
		if(wParam==VK_F10)
		{
			return(0);
		}
		if(wParam==VK_RETURN)
			break;
	}
	break;
//
//
//
	case WM_ACTIVATE:
	{
		gActive = ( ((wParam&0xffff)==WA_ACTIVE) || ((wParam&0xffff)==WA_CLICKACTIVE) );
		if( 0==(wParam&0xffff0000) && gActive )
		{
			CMAcquireControls();
		}
		if( Environment.fullScreen && (wParam&0xffff)==WA_INACTIVE )
		{
			ClipCursor( NULL );
		}
	}
	break;
//
// Right click when on task bar
//
	case WM_ENTERMENULOOP:
	{
		WindowsPause=1;
	}
	break;
//
// Get window position
//
	case WM_WINDOWPOSCHANGING:
	{
		if( ChangingModes )
			break;
		if( !Environment.fullScreen )
		{
			LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
			if( 0==(lpwp->flags&SWP_NOMOVE) )
			{
				WINDOWPLACEMENT wp;
				wp.length=sizeof(WINDOWPLACEMENT);
				GetWindowPlacement( hWindow, &wp );
				if( wp.showCmd==SW_SHOWNORMAL )			// make sure not minimized
				{
					WindowStartX=lpwp->x;
					WindowStartY=lpwp->y;
				}
				break;
			}
		}
		break;
	}
//
// Out of menu loop
//
	case WM_EXITMENULOOP:
	{
		WindowsPause=0;
	}
	break;
//
//
//
	case WM_ACTIVATEAPP:
	{
		if( !IsIconic(hWindow) && wParam )
		{
			CMAcquireControls();
		}
	}
	break;
//
//
//
	case WM_KILLFOCUS:
	{
		gGotFocus=0;
		CMUnacquireControls();
	}
	break;
//
//
//
	case WM_SETFOCUS:
	{
		gGotFocus=1;
		CMAcquireControls();
	}
	break;
//
//
//
	case WM_MOVE:
	{
		int x=(short)LOWORD(lParam);
		int y=(short)HIWORD(lParam);
		clientToScreen.x = 0;
		clientToScreen.y = 0;
		ClientToScreen(hWnd,&clientToScreen);
	}
	break;
//
// Allow background erasure during creation, not during running
//
	case WM_ERASEBKGND:
	{
		if( Platform!=Platform_Game || status==Uninitialized ) 
		{
			ValidateRect( hWnd, NULL );								// Stop inital WM_PAINT message being sent (Saw problems on a Voodoo3)
			break;
		}
		return 1;
	}
	break;
//
// Mouse messages
//
	case WM_LBUTTONDOWN:
		DealWithKey( 1, 0 );
		break;		
	case WM_LBUTTONUP:
		DoKeyReleased( 1 );
		break;		
	case WM_RBUTTONDOWN:
		DealWithKey( 2, 0 );
		break;		
	case WM_RBUTTONUP:
		DoKeyReleased( 2 );
		break;		
	case WM_MBUTTONDOWN:
		DealWithKey( 3, 0 );
		break;		
	case WM_MBUTTONUP:
		DoKeyReleased( 3 );
		break;		
//
// Deal with 5 button mice
//
	case 0x20b:						// WM_XBUTTONDOWN
		DealWithKey( HIWORD(wParam)+3, 0 );
		break;		
	case 0x20c:						// WM_XBUTTONUP
		DoKeyReleased( HIWORD(wParam)+3 );
		break;		

//
// Keyboard key pressed
//
	case WM_KEYDOWN:
	{
//
// Deal with constant keys
//
		switch(wParam)
		{
			#if 0   // SetExtended is causing problems (on 98)
			case VK_NUMLOCK:
				if (gNumLockMode !=2)
					SetExtended(VK_NUMLOCK, gNumLockMode);
				break;
			case VK_CAPITAL:
				if (gCapLockMode !=2)
					SetExtended(VK_CAPITAL, gCapLockMode);
				break;
			#endif
//
// Scroll Lock - bring up exception handler
//
			case VK_SCROLL:
			#ifndef LAB_ONLY
			#if 0   // SetExtended is causing problems (on 98)
				if (gScrollLockMode !=2)
					SetExtended(VK_SCROLL, gScrollLockMode);
				else
			#endif
				{
					HitScrollLock=1;
					PAUSE(( "Scroll Lock pressed" ));
					HitScrollLock=0;
					return 0;
				}
				break;
			#else
				HitScrollLock=1;
				PAUSE(( "Scroll Lock pressed" ));
				HitScrollLock=0;
				return 0;
			#endif
//			
// Control Break and Control Backspace removed in release mode
//
			#ifdef LAB_ONLY
				case VK_CONTROL:
					ControlDown=1;
					break;
				case VK_BACK:
					if( ControlDown )
					{
						gFrameGraph ^= 1;							// Control Backspace - framegraph
						return 0;
					}
					break;
				case VK_PAUSE:
				case VK_CANCEL:
					if( ControlDown )
					{
						DebuggerActive^=1;							// Control PAUSE - debugger
						if( !DebuggerActive )
							EndRenderMode();
					}
					break;
			#endif
		}
//
// Store WM_KEYDOWN scan code until a WM_CHAR arrives (or another WM_KEYDOWN)
//
		#ifdef LAB_ONLY
			if( wParam!=3 )
		#endif		
		DealWithKey( wParam, lParam );
// 
// Normally F4 - Switch between window/full screen
//
		if( Environment.Key_FullScreen && !ProcessingError && wParam==Environment.Key_FullScreen )
		{
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - F4" ));
			if( Environment.fullScreen )
			{
				DoUpdateWindow=1;
				GlobalGotoWindowMode=1;
			}
			else
			{
				DoUpdateWindow=1;
				GlobalGotoFullScreen=1;
			}
			break;
		}
//
// Normally F5 - Rotate between full screen 3D devices
//
		if( Environment.Key_SwitchMonitors && !ProcessingError && wParam==Environment.Key_SwitchMonitors )
		{
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - F5" ));
			if( Environment.fullScreen )
			{
				Environment.FullScreenDevice++;
				if( Environment.FullScreenDevice >= NumDevices )
					Environment.FullScreenDevice=0;
				DoUpdateWindow=1;
				GlobalGotoFullScreen=1;
			}
			else
			{
				DoUpdateWindow=1;
				GlobalGotoFullScreen=1;
			}
			break;
		}
//
// Normally ESC - switch between full screen and window mode
//
		if( Environment.Key_Exit && !ProcessingError && wParam==Environment.Key_Exit )
		{
			SPEW(( GROUP_DIRECTDRAW, "Mode change requested - Esc" ));
			if(Environment.fullScreen)
			{
				DoUpdateWindow=1;
				GlobalGotoWindowMode=1;
			}
			else
			{
				WindowClosed=1;
			}
			break;
		}
	}
	break;
//
// Keyboard key released
//
	case WM_KEYUP:
	{
		#ifdef LAB_ONLY
			if( wParam!=3 )
		#endif		
		DoKeyReleased( wParam );
		if( VK_CONTROL==wParam )
			ControlDown=0;
		if( VK_SNAPSHOT==wParam && gPrintScreen )
			gCaptureScreen=1;
	}
	break;
//
//
//
	case WM_CHAR:
	{
//
// Ignore control backspace and control break (so framegraph toggle or debugger toggle does not effect app)
//
		#ifdef LAB_ONLY
		if( wParam==127 || (wParam==3 && lParam==21364737) )
			return 0;
		#endif

//
// Store key and last WM_KEYDOWN scan code
//
		if( DebuggerActive )
		{
			if( ((dbKeyPressed+1)&255)!=dbKeyCurrent )
			{
				dbKeyBoardBuffer[dbKeyPressed] = LastWMDown + wParam;
				dbKeyPressed=(dbKeyPressed+1)&255;
			}
		}
		if( !DebuggerActive || (DebuggerActive && gControlsActive && !gStopSystem) )
		{
			AddKeyEvent(LastWMDown + wParam);
		}
		LastWMDown=0;
		return 0;
	}
	break;
//
// If anyone tries to close the window, always terminate the game
// 
	case WM_CLOSE:
	{
		WindowClosed=1;
		return 0;
	}
//
//
//
	default:
	{
//
// Do IME messages
//
	
		bool bTrapped = false;
		LPARAM val = ProcessIMEMessages(  hWnd,  uMsg,  wParam,  lParam, & bTrapped );
		if (bTrapped)
			return val;
		break;
	}
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}




