CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

KEYBOARD.CPP (16658B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header:   F:\projects\c&c0\vcs\code\conquer.cpv   4.74   23 Sep 1996 12:36:00   JOE_BOSTIC  $ */
     17 /***********************************************************************************************
     18  *                                                                                             *
     19  *                 Project Name : Westwood Keyboard Library                                    *
     20  *                                                                                             *
     21  *                    File Name : KEYBOARD.CPP                                                 *
     22  *                                                                                             *
     23  *                   Programmer : Philip W. Gorrow                                             *
     24  *                                                                                             *
     25  *                   Start Date : 10/16/95                                                     *
     26  *                                                                                             *
     27  *                  Last Update : September 24, 1996 [JLB]                                     *
     28  *                                                                                             *
     29  *---------------------------------------------------------------------------------------------*
     30  * Functions:                                                                                  *
     31  *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *
     32  *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *
     33  *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *
     34  *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *
     35  *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *
     36  *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *
     37  *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *
     38  *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *
     39  *   Check_Key -- compatability routine for old 32 bit library                                 *
     40  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     41 
     42 #include "keyboard.h"
     43 
     44 #include	"monoc.h"
     45 
     46 //void Message_Loop(void);
     47 
     48 WWKeyboardClass * _Kbd = NULL;
     49 
     50 
     51 #define	ARRAY_SIZE(x)		int(sizeof(x)/sizeof(x[0]))
     52 
     53 
     54 /***********************************************************************************************
     55  * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *
     56  *                                                                                             *
     57  * INPUT:		none							                                                        *
     58  *                                                                                             *
     59  * OUTPUT:     none							                                                        *
     60  *                                                                                             *
     61  * HISTORY:                                                                                    *
     62  *   10/16/1995 PWG : Created.                                                                 *
     63  *=============================================================================================*/
     64 WWKeyboardClass::WWKeyboardClass(void) :
     65 	MouseQX(0),
     66 	MouseQY(0),
     67 	Head(0),
     68 	Tail(0)
     69 //	MState(0),
     70 //	Conditional(0),
     71 //	CurrentCursor(0)
     72 {
     73 	_Kbd = this;
     74 
     75 	memset(KeyState, '\0', sizeof(KeyState));
     76 }
     77 
     78 
     79 /***********************************************************************************************
     80  * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *
     81  *                                                                                             *
     82  * INPUT:		none                                                        						  *
     83  *                                                                                             *
     84  * OUTPUT:     int		- the key value that was pulled from buffer (includes bits)				  *                                                                                *
     85  *                                                                                             *
     86  * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *
     87  *                                                                                             *
     88  * HISTORY:                                                                                    *
     89  *   10/17/1995 PWG : Created.                                                                 *
     90  *=============================================================================================*/
     91 unsigned short WWKeyboardClass::Buff_Get(void)
     92 {
     93 	while (!Check()) {}										// wait for key in buffer
     94 
     95 	unsigned short temp = Fetch_Element();
     96 	if (Is_Mouse_Key(temp)) {
     97 		MouseQX = Fetch_Element();
     98 		MouseQY = Fetch_Element();
     99 	}
    100 	return(temp);
    101 }
    102 
    103 
    104 bool WWKeyboardClass::Is_Mouse_Key(unsigned short key)
    105 {
    106 	key &= 0xFF;
    107 	return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
    108 }
    109 
    110 
    111 /***********************************************************************************************
    112  * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *
    113  *                                                                                             *
    114  * INPUT:                                                                                      *
    115  *                                                                                             *
    116  * OUTPUT:                                                                                     *
    117  *                                                                                             *
    118  * WARNINGS:                                                                                   *
    119  *                                                                                             *
    120  * HISTORY:                                                                                    *
    121  *   10/16/1995 PWG : Created.                                                                 *
    122  *   09/24/1996 JLB : Converted to new style keyboard system.                                  *
    123  *=============================================================================================*/
    124 unsigned short WWKeyboardClass::Check(void) const
    125 {
    126 	((WWKeyboardClass *)this)->Fill_Buffer_From_System();
    127 	if (Is_Buffer_Empty()) return(false);
    128 	return(Peek_Element());
    129 }
    130 
    131 
    132 /***********************************************************************************************
    133  * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *
    134  *                                                                                             *
    135  * INPUT:		none                                                        						  *
    136  *                                                                                             *
    137  * OUTPUT:     int		- the meta key taken from the buffer.											  *
    138  *                                                                                             *
    139  * WARNINGS:	This routine will not return until a keypress is received							  *
    140  *                                                                                             *
    141  * HISTORY:                                                                                    *
    142  *   10/16/1995 PWG : Created.                                                                 *
    143  *=============================================================================================*/
    144 unsigned short WWKeyboardClass::Get(void)
    145 {
    146 	while (!Check()) {}								// wait for key in buffer
    147 	return (Buff_Get());
    148 }
    149 
    150 
    151 /***********************************************************************************************
    152  * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *
    153  *                                                                                             *
    154  * INPUT:		int	 	- the key to insert into the buffer          								  *
    155  *                                                                                             *
    156  * OUTPUT:     bool		- true if key is sucessfuly inserted.							              *
    157  *                                                                                             *
    158  * WARNINGS:   none							                                                        *
    159  *                                                                                             *
    160  * HISTORY:                                                                                    *
    161  *   10/16/1995 PWG : Created.                                                                 *
    162  *=============================================================================================*/
    163 bool WWKeyboardClass::Put(unsigned short key)
    164 {
    165 	if (!Is_Buffer_Full()) {
    166 		Put_Element(key);
    167 		return(true);
    168 	}
    169 	return(false);
    170 }
    171 
    172 
    173 /***********************************************************************************************
    174  * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *
    175  *                                                                                             *
    176  * INPUT:                                                                                      *
    177  *                                                                                             *
    178  * OUTPUT:                                                                                     *
    179  *                                                                                             *
    180  * WARNINGS:                                                                                   *
    181  *                                                                                             *
    182  * HISTORY:                                                                                    *
    183  *   10/16/1995 PWG : Created.                                                                 *
    184  *=============================================================================================*/
    185 bool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release)
    186 {
    187 	//
    188 	// Get the status of all of the different keyboard modifiers.  Note, only pay attention
    189 	// to numlock and caps lock if we are dealing with a key that is affected by them.  Note
    190 	// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this
    191 	// would be incompatible with the dos version.
    192 	//
    193 	if (!Is_Mouse_Key(vk_key)) {
    194 		if (((GetKeyState(VK_SHIFT) & 0x8000) != 0) ||
    195 			((GetKeyState(VK_CAPITAL) & 0x0008) != 0) ||
    196 			((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) {
    197 
    198 			vk_key |= WWKEY_SHIFT_BIT;
    199 		}
    200 		if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {
    201 			vk_key |= WWKEY_CTRL_BIT;
    202 		}
    203 		if ((GetKeyState(VK_MENU) & 0x8000) != 0) {
    204 			vk_key |= WWKEY_ALT_BIT;
    205 		}
    206 	}
    207 
    208 	if (release) {
    209 		vk_key |= WWKEY_RLS_BIT;
    210 	}
    211 
    212 	//
    213 	// Finally use the put command to enter the key into the keyboard
    214 	// system.
    215 	//
    216 	return(Put(vk_key));
    217 
    218 
    219 
    220 }
    221 
    222 #pragma warning (disable : 4065)
    223 char WWKeyboardClass::To_ASCII(unsigned short key)
    224 {
    225 	/*
    226 	**	Released keys never translate into an ASCII value.
    227 	*/
    228 	if (key & WWKEY_RLS_BIT) {
    229 		return('\0');
    230 	}
    231 
    232 	/*
    233 	**	Set the KeyState buffer to reflect the shift bits stored in the key value.
    234 	*/
    235 	if (key & WWKEY_SHIFT_BIT) {
    236 		KeyState[VK_SHIFT] = 0x80;
    237 	}
    238 	if (key & WWKEY_CTRL_BIT) {
    239 		KeyState[VK_CONTROL] = 0x80;
    240 	}
    241 	if (key & WWKEY_ALT_BIT) {
    242 		KeyState[VK_MENU] = 0x80;
    243 	}
    244 
    245 	/*
    246 	**	Ask windows to translate the key into an ASCII equivalent.
    247 	*/
    248 	char buffer[10];
    249 	int result = 1;
    250 	int scancode = 0;
    251 	char override = '\0';
    252 
    253 	switch (key & 0xFF) {
    254 //		case KN_RETURN:
    255 //			override = KA_RETURN;
    256 //			break;
    257 
    258 //		case KN_BACKSPACE:
    259 //			override = KA_BACKSPACE;
    260 //			break;
    261 
    262 		default:
    263 			scancode = MapVirtualKey(key & 0xFF, 0);
    264 			result = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0);
    265 			break;
    266 	}
    267 
    268 	/*
    269 	**	Restore the KeyState buffer back to pristine condition.
    270 	*/
    271 	if (key & WWKEY_SHIFT_BIT) {
    272 		KeyState[VK_SHIFT] = 0;
    273 	}
    274 	if (key & WWKEY_CTRL_BIT) {
    275 		KeyState[VK_CONTROL] = 0;
    276 	}
    277 	if (key & WWKEY_ALT_BIT) {
    278 		KeyState[VK_MENU] = 0;
    279 	}
    280 
    281 	/*
    282 	**	If Windows could not perform the translation as expected, then
    283 	**	return with a null ASCII value.
    284 	*/
    285 	if (result != 1) {
    286 		return('\0');
    287 	}
    288 
    289 	if (override != 0) {
    290 		return(override);
    291 	}
    292 
    293 	return(buffer[0]);
    294 }
    295 
    296 
    297 bool WWKeyboardClass::Down(unsigned short key)
    298 {
    299 	return(GetAsyncKeyState(key & 0xFF) == 0 ? false : true);
    300 }
    301 
    302 
    303 extern "C" {
    304 	void __cdecl Stop_Execution (void);
    305 }
    306 
    307 
    308 
    309 unsigned short WWKeyboardClass::Fetch_Element(void)
    310 {
    311 	unsigned short val = 0;
    312 	if (Head != Tail) {
    313 		val = Buffer[Head];
    314 
    315 		Head = (Head + 1) % ARRAY_SIZE(Buffer);
    316 	}
    317 	return(val);
    318 }
    319 
    320 
    321 unsigned short WWKeyboardClass::Peek_Element(void) const
    322 {
    323 	if (!Is_Buffer_Empty()) {
    324 		return(Buffer[Head]);
    325 	}
    326 	return(0);
    327 }
    328 
    329 
    330 bool WWKeyboardClass::Put_Element(unsigned short val)
    331 {
    332 	if (!Is_Buffer_Full()) {
    333 		int temp = (Tail+1) % ARRAY_SIZE(Buffer);
    334 		Buffer[Tail] = val;
    335 		Tail = temp;
    336 		return(true);
    337 	}
    338 	return(false);
    339 }
    340 
    341 
    342 bool WWKeyboardClass::Is_Buffer_Full(void) const
    343 {
    344 	if ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) {
    345 		return(true);
    346 	}
    347 	return(false);
    348 }
    349 
    350 
    351 bool WWKeyboardClass::Is_Buffer_Empty(void) const
    352 {
    353 	if (Head == Tail) {
    354 		return(true);
    355 	}
    356 	return(false);
    357 }
    358 
    359 
    360 void WWKeyboardClass::Fill_Buffer_From_System(void)
    361 {
    362 	if (!Is_Buffer_Full()) {
    363 		MSG	msg;
    364 		while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
    365 		  	if (!GetMessage( &msg, NULL, 0, 0 )) {
    366 				return;
    367 			}
    368 			TranslateMessage(&msg);
    369 			DispatchMessage(&msg);
    370 		}
    371 	}
    372 }
    373 
    374 
    375 void WWKeyboardClass::Clear(void)
    376 {
    377 	Head = Tail;
    378 }
    379 
    380 
    381 void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)
    382 {
    383 	switch (message) {
    384 		case WM_SYSKEYDOWN:
    385 		case WM_KEYDOWN:
    386 			if ( wParam==VK_SCROLL ){
    387 				Stop_Execution();
    388 			} else {
    389 				Put_Key_Message((unsigned short)wParam);
    390 			}
    391 			break;
    392 
    393 		case WM_SYSKEYUP:
    394 		case WM_KEYUP:
    395 			Put_Key_Message((unsigned short)wParam, true);
    396 			break;
    397 
    398 		case WM_LBUTTONDOWN:
    399 			Put_Key_Message(VK_LBUTTON);
    400 			Put(LOWORD(lParam));
    401 			Put(HIWORD(lParam));
    402 			break;
    403 
    404 		case WM_LBUTTONUP:
    405 			Put_Key_Message(VK_LBUTTON, true);
    406 			Put(LOWORD(lParam));
    407 			Put(HIWORD(lParam));
    408 			break;
    409 
    410 		case WM_LBUTTONDBLCLK:
    411 			Put_Key_Message(VK_LBUTTON, true);
    412 			Put(LOWORD(lParam));
    413 			Put(HIWORD(lParam));
    414 			Put_Key_Message(VK_LBUTTON, true);
    415 			Put(LOWORD(lParam));
    416 			Put(HIWORD(lParam));
    417 			break;
    418 
    419 		case WM_MBUTTONDOWN:
    420 			Put_Key_Message(VK_MBUTTON);
    421 			Put(LOWORD(lParam));
    422 			Put(HIWORD(lParam));
    423 			break;
    424 
    425 		case WM_MBUTTONUP:
    426 			Put_Key_Message(VK_MBUTTON, true);
    427 			Put(LOWORD(lParam));
    428 			Put(HIWORD(lParam));
    429 			break;
    430 
    431 		case WM_MBUTTONDBLCLK:
    432 			Put_Key_Message(VK_MBUTTON, true);
    433 			Put(LOWORD(lParam));
    434 			Put(HIWORD(lParam));
    435 			Put_Key_Message(VK_MBUTTON, true);
    436 			Put(LOWORD(lParam));
    437 			Put(HIWORD(lParam));
    438 			break;
    439 
    440 		case WM_RBUTTONDOWN:
    441 			Put_Key_Message(VK_RBUTTON);
    442 			Put(LOWORD(lParam));
    443 			Put(HIWORD(lParam));
    444 			break;
    445 
    446 		case WM_RBUTTONUP:
    447 			Put_Key_Message(VK_RBUTTON, true);
    448 			Put(LOWORD(lParam));
    449 			Put(HIWORD(lParam));
    450 			break;
    451 
    452 		case WM_RBUTTONDBLCLK:
    453 			Put_Key_Message(VK_RBUTTON, true);
    454 			Put(LOWORD(lParam));
    455 			Put(HIWORD(lParam));
    456 			Put_Key_Message(VK_RBUTTON, true);
    457 			Put(LOWORD(lParam));
    458 			Put(HIWORD(lParam));
    459 			break;
    460 
    461 //		case WM_MOUSEMOVE:
    462 //			if (CurrentCursor)
    463 //				SetCursor(CurrentCursor);
    464 //			break;
    465 	}
    466 }