CnC_Remastered_Collection

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

KEYBOARD.CPP (19409B)


      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 /***********************************************************************************************
     17  *                                                                                             *
     18  *                 Project Name : Westwood Keyboard Library                                    *
     19  *                                                                                             *
     20  *                    File Name : KEYBOARD.CPP                                                 *
     21  *                                                                                             *
     22  *                   Programmer : Philip W. Gorrow                                             *
     23  *                                                                                             *
     24  *                   Start Date : 10/16/95                                                     *
     25  *                                                                                             *
     26  *                  Last Update : October 26, 1995   []                    *
     27  *                                                                                             *
     28  *---------------------------------------------------------------------------------------------*
     29  * Functions:                                                                                  *
     30  *   WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                         *
     31  *   WWKeyboardClass::Get -- Logic to get a metakey from the buffer                            *
     32  *   WWKeyboardClass::Check -- Checks to see if a key is in the buffer                         *
     33  *   WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer    *
     34  *   WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer               *
     35  *   WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels           *
     36  *   WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels           *
     37  *   WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars       *
     38  *   Check_Key -- compatability routine for old 32 bit library             *
     39  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     40 
     41 #include "keyboard.h"
     42 #include "timer.h"
     43 #include "mono.h"
     44 
     45 void Message_Loop(void);
     46 
     47 WWKeyboardClass *_Kbd;
     48 
     49 /***********************************************************************************************
     50  * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class                *
     51  *                                                                                             *
     52  * INPUT:		none							                                                        *
     53  *                                                                                             *
     54  * OUTPUT:     none							                                                        *
     55  *                                                                                             *
     56  * HISTORY:                                                                                    *
     57  *   10/16/1995 PWG : Created.                                                                 *
     58  *=============================================================================================*/
     59 WWKeyboardClass::WWKeyboardClass(void)
     60 {
     61 	_Kbd = this;
     62 	//
     63 	// Initialize the keyboard remap table for our system (note it would be bad if someone
     64 	// switched keyboard modes after this happened.
     65 	//
     66 	memset(VKRemap, 0, 256);
     67 	memset(AsciiRemap, 0, 2048);
     68 	short lp;
     69 	for (lp = 31; lp < 255; lp ++) {
     70 		if (isprint(lp)) {
     71 			int vk_key = VkKeyScan((unsigned char)lp);
     72 			if (vk_key > 0 && vk_key < 2048) {
     73 				AsciiRemap[vk_key] = (unsigned char)lp;
     74 				VKRemap[lp] 	 = (unsigned char)(vk_key & 0xFF);
     75 			}
     76 		}
     77 	}
     78 
     79 	//
     80 	// Build a remap table of the different keys which are affected by the caps lock and
     81 	// the num lock.
     82 	//
     83 	memset(ToggleKeys, 0, 256);
     84 	for (lp = 0; lp < 255; lp++ ) {
     85 		if (isalpha(lp) && isupper(lp)) {
     86 			ToggleKeys[lp] = 1;
     87 		}
     88 		if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {
     89 			ToggleKeys[lp] = 2;
     90 		}
     91 	}
     92 
     93 	//
     94 	// Our buffer should start devoid of keys.
     95 	//
     96 	memset(Buffer, 0, 256);
     97 	Head				= 0;
     98 	Tail				= 0;
     99 
    100 	//
    101 	// There should be no starting queued mouse events for us to have to worry
    102 	// about.
    103 	//
    104 	MouseQX			= 0;
    105 	MouseQY			= 0;
    106 	MState			= 0;
    107 	Conditional		= 0;
    108 	CurrentCursor	= NULL;
    109 }
    110 
    111 /***********************************************************************************************
    112  * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer                 *
    113  *                                                                                             *
    114  * INPUT:		none                                                        						  *
    115  *                                                                                             *
    116  * OUTPUT:     int		- the key value that was pulled from buffer (includes bits)				  *                                                                                *
    117  *                                                                                             *
    118  * WARNINGS:   If the key was a mouse event MouseQX and MouseQY will be updated                *
    119  *                                                                                             *
    120  * HISTORY:                                                                                    *
    121  *   10/17/1995 PWG : Created.                                                                 *
    122  *=============================================================================================*/
    123 int WWKeyboardClass::Buff_Get(void)
    124 {
    125 	while (!Check()) {}										// wait for key in buffer
    126 	int 	temp		= Buffer[Head];						// get key out of the buffer
    127 	int   newhead	= Head;									// save off head for manipulation
    128 	if (Is_Mouse_Key(temp)) {								// if key is a mouse then
    129 		MouseQX	= Buffer[(Head + 1) & 255];			//		get the x and y pos
    130 		MouseQY	= Buffer[(Head + 2) & 255];			//		from the buffer
    131 		newhead += 3;		  									//		adjust head forward
    132 	} else {
    133 		newhead += 1;		  									//		adjust head forward
    134 	}
    135 	newhead	&= 255;
    136 	Head		 = newhead;
    137 	return(temp);
    138 }
    139 
    140 BOOL WWKeyboardClass::Is_Mouse_Key(int key)
    141 {
    142 	key &= 0xFF;
    143 	return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
    144 }
    145 
    146 
    147 /***********************************************************************************************
    148  * WWKeyboardClass::Check -- Checks to see if a key is in the buffer                           *
    149  *                                                                                             *
    150  * INPUT:                                                                                      *
    151  *                                                                                             *
    152  * OUTPUT:                                                                                     *
    153  *                                                                                             *
    154  * WARNINGS:                                                                                   *
    155  *                                                                                             *
    156  * HISTORY:                                                                                    *
    157  *   10/16/1995 PWG : Created.                                                                 *
    158  *=============================================================================================*/
    159 BOOL WWKeyboardClass::Check(void)
    160 {
    161 	Message_Loop();
    162 	unsigned short temp;											// store temp holding spot for key
    163 	if (Head == Tail) return(FALSE);							// if no keys in buff then get out
    164 	temp = Buffer[Head];											// get key out of the buffer
    165 	return(temp);													// send it back to main program
    166 }
    167 
    168 /***********************************************************************************************
    169  * WWKeyboardClass::Get -- Logic to get a metakey from the buffer                              *
    170  *                                                                                             *
    171  * INPUT:		none                                                        						  *
    172  *                                                                                             *
    173  * OUTPUT:     int		- the meta key taken from the buffer.											  *
    174  *                                                                                             *
    175  * WARNINGS:	This routine will not return until a keypress is received							  *
    176  *                                                                                             *
    177  * HISTORY:                                                                                    *
    178  *   10/16/1995 PWG : Created.                                                                 *
    179  *=============================================================================================*/
    180 int WWKeyboardClass::Get(void)
    181 {
    182 	int temp,bits;										// store temp holding spot for key
    183 
    184 	while (!Check()) {}								// wait for key in buffer
    185 	temp = Buff_Get();								// get key from the buffer
    186 
    187 	bits = temp & 0xFF00;							// save of keyboard bits
    188 
    189 	if (!(bits & WWKEY_VK_BIT)) {					// if its not a virtual key
    190 		temp = AsciiRemap[temp&0x1FF] | bits;	//   convert to ascii equivalent
    191 	}
    192 	return(temp);							// return the key that we pulled out
    193 }
    194 
    195 /***********************************************************************************************
    196  * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer]                           *
    197  *                                                                                             *
    198  * INPUT:		int	 	- the key to insert into the buffer          								  *
    199  *                                                                                             *
    200  * OUTPUT:     bool		- true if key is sucessfuly inserted.							              *
    201  *                                                                                             *
    202  * WARNINGS:   none							                                                        *
    203  *                                                                                             *
    204  * HISTORY:                                                                                    *
    205  *   10/16/1995 PWG : Created.                                                                 *
    206  *=============================================================================================*/
    207 BOOL WWKeyboardClass::Put(int key)
    208 {
    209 	int	temp		= (Tail + 1) & 255;
    210 	if (temp != Head)
    211 	{
    212 		Buffer[Tail]	= (short)key;
    213 
    214 		//
    215 		// Critical Line
    216 		//
    217 		Tail				= temp;
    218 		return(TRUE);
    219 	}
    220 	return(FALSE);
    221 }
    222 /***********************************************************************************************
    223  * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer      *
    224  *                                                                                             *
    225  * INPUT:                                                                                      *
    226  *                                                                                             *
    227  * OUTPUT:                                                                                     *
    228  *                                                                                             *
    229  * WARNINGS:                                                                                   *
    230  *                                                                                             *
    231  * HISTORY:                                                                                    *
    232  *   10/16/1995 PWG : Created.                                                                 *
    233  *=============================================================================================*/
    234 BOOL WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)
    235 {
    236 	int bits = 0;
    237 	//
    238 	// Get the status of all of the different keyboard modifiers.  Note, only pay attention
    239 	// to numlock and caps lock if we are dealing with a key that is affected by them.  Note
    240 	// that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this
    241 	// would be incompatible with the dos version.
    242 	//
    243 	if (vk_key != VK_LBUTTON && vk_key != VK_MBUTTON && vk_key != VK_RBUTTON) 	{
    244 		int	shift		= (GetKeyState(VK_SHIFT) & 0xFF00) 		!= 0;
    245 		int	ctrl 		= (GetKeyState(VK_CONTROL) & 0xFF00) 	!= 0;
    246 		int	alt 		= (GetKeyState(VK_MENU) & 0xFF00) 		!= 0;
    247 		int	caps		= ((GetKeyState(VK_CAPITAL) & 0x00FF) 	!= 0) && (ToggleKeys[vk_key] == 1);
    248 		int	nums		= ((GetKeyState(VK_NUMLOCK) & 0x00FF) 	!= 0) && (ToggleKeys[vk_key] == 2);
    249 
    250 		//
    251 		// Set the proper bits for whatever the key we got is.
    252 		//
    253 		if (shift || caps || nums) {
    254 			bits |= WWKEY_SHIFT_BIT;
    255 		}
    256 		if (ctrl) {
    257 			bits |= WWKEY_CTRL_BIT;
    258 		}
    259 		if (alt) {
    260 			bits |= WWKEY_ALT_BIT;
    261 		}
    262 		}
    263 	if (!AsciiRemap[vk_key|bits]) {
    264 		bits |= WWKEY_VK_BIT;
    265 	}
    266 	if (release) {
    267 		bits |= WWKEY_RLS_BIT;
    268 	}
    269 	if (dbl) {
    270 		bits |= WWKEY_DBL_BIT;
    271 	}
    272 	//
    273 	// Finally use the put command to enter the key into the keyboard
    274 	// system.
    275 	//
    276 	return(Put(vk_key|bits));
    277 }
    278 
    279 void WWKeyboardClass::Clear(void)
    280 {
    281 	Head = Tail;
    282 }
    283 
    284 int WWKeyboardClass::To_ASCII(int key)
    285 {
    286 	if ( key && WWKEY_RLS_BIT)
    287 	  return(KN_NONE);
    288 	return(key);
    289 }
    290 
    291 int WWKeyboardClass::Down(int key)
    292 {
    293 	return(GetAsyncKeyState(key&0xFF));
    294 }
    295 
    296 VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)
    297 {
    298 	shift = (key & WWKEY_SHIFT_BIT)	!= 0;
    299 	ctrl	= (key & WWKEY_CTRL_BIT)	!= 0;
    300 	alt	= (key & WWKEY_ALT_BIT)		!= 0;
    301 	rls	= (key & WWKEY_RLS_BIT)		!= 0;
    302 	dbl	= (key & WWKEY_DBL_BIT)		!= 0;
    303 	key	= (key & 0xFF);
    304 
    305 }
    306 
    307 
    308 extern "C" {
    309 	void __cdecl Stop_Execution (void);
    310 }
    311 
    312 //#pragma off(unreferenced)
    313 void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)
    314 {
    315 	return;
    316 #if (0)	//   ST - 12/20/2018 11:27AM
    317 	switch (message) {
    318 		case WM_SYSKEYDOWN:
    319 		case WM_KEYDOWN:
    320 			if ( wParam==VK_SCROLL ){
    321 				Stop_Execution();
    322 			} else {
    323 				Put_Key_Message(wParam);
    324 			}
    325 			break;
    326 
    327 		case WM_SYSKEYUP:
    328 		case WM_KEYUP:
    329 			Put_Key_Message(wParam, TRUE);
    330 			break;
    331 
    332 		case WM_LBUTTONDOWN:
    333 			Put_Key_Message(VK_LBUTTON);
    334 			Put(LOWORD(lParam));
    335 			Put(HIWORD(lParam));
    336 			break;
    337 
    338 		case WM_LBUTTONUP:
    339 			Put_Key_Message(VK_LBUTTON, TRUE);
    340 			Put(LOWORD(lParam));
    341 			Put(HIWORD(lParam));
    342 			break;
    343 
    344 		case WM_LBUTTONDBLCLK:
    345 			Put_Key_Message(VK_LBUTTON, TRUE, TRUE);
    346 			Put(LOWORD(lParam));
    347 			Put(HIWORD(lParam));
    348 			break;
    349 
    350 		case WM_MBUTTONDOWN:
    351 			Put_Key_Message(VK_MBUTTON);
    352 			Put(LOWORD(lParam));
    353 			Put(HIWORD(lParam));
    354 			break;
    355 
    356 		case WM_MBUTTONUP:
    357 			Put_Key_Message(VK_MBUTTON, TRUE);
    358 			Put(LOWORD(lParam));
    359 			Put(HIWORD(lParam));
    360 			break;
    361 
    362 		case WM_MBUTTONDBLCLK:
    363 			Put_Key_Message(VK_MBUTTON, TRUE, TRUE);
    364 			Put(LOWORD(lParam));
    365 			Put(HIWORD(lParam));
    366 			break;
    367 
    368 		case WM_RBUTTONDOWN:
    369 			Put_Key_Message(VK_RBUTTON);
    370 			Put(LOWORD(lParam));
    371 			Put(HIWORD(lParam));
    372 			break;
    373 
    374 		case WM_RBUTTONUP:
    375 			Put_Key_Message(VK_RBUTTON, TRUE);
    376 			Put(LOWORD(lParam));
    377 			Put(HIWORD(lParam));
    378 			break;
    379 
    380 		case WM_RBUTTONDBLCLK:
    381 			Put_Key_Message(VK_RBUTTON, TRUE, TRUE);
    382 			Put(LOWORD(lParam));
    383 			Put(HIWORD(lParam));
    384 			break;
    385 		case WM_MOUSEMOVE:
    386 			if (CurrentCursor)
    387 				SetCursor(CurrentCursor);
    388 			break;
    389 	}
    390 #endif
    391 }
    392 //#pragma on(unreferenced)
    393 
    394 
    395 
    396 
    397 void Message_Loop(void)
    398 {
    399 
    400 	MSG	msg;
    401 
    402 	while (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
    403 	  	if( !GetMessage( &msg, NULL, 0, 0 ) ){
    404 			return;
    405 		}
    406 		TranslateMessage(&msg);
    407 		DispatchMessage(&msg);
    408 	}
    409 
    410 
    411 
    412 
    413 }
    414 
    415 
    416 
    417 /***************************************************************************
    418  * CHECK_KEY -- compatability routine for old 32 bit library               *
    419  *                                                                         *
    420  * This routine checks to see if there is a key in the keyboard buffer     *
    421  * and returns it to the sender if there is.  It does not remove the key	*
    422  * from the buffer.																			*
    423  *                                                                         *
    424  * INPUT:		none                                                        *
    425  *                                                                         *
    426  * OUTPUT:     The key that was pressed.                                   *
    427  *                                                                         *
    428  * WARNINGS:   You must declare a WWKeyboardClass object before calling    *
    429  *					this routine.																*
    430  *                                                                         *
    431  * HISTORY:                                                                *
    432  *   10/26/1995     : Created.                                             *
    433  *=========================================================================*/
    434 int Check_Key(void)
    435 {
    436 	if (!_Kbd) return(KA_NONE);
    437 	return(_Kbd->Check() & ~WWKEY_SHIFT_BIT);
    438 }
    439 
    440 void Clear_KeyBuffer(void)
    441 {
    442 	if (!_Kbd) return;
    443 	_Kbd->Clear();
    444 }
    445 
    446 int Check_Key_Num(void)
    447 {
    448 	if (!_Kbd) return(KN_NONE);
    449 	int key		= _Kbd->Check();
    450 	int flags	= key & 0xFF00;
    451 	key		   = key & 0x00FF;
    452 
    453 	if (isupper(key)) {
    454 		key = tolower(key);
    455 		if ( !(flags & WWKEY_VK_BIT) ) {
    456 			flags |= WWKEY_SHIFT_BIT;
    457 		}
    458 	}
    459 
    460 	return(key | flags);
    461 }
    462 
    463 int Get_Key_Num(void)
    464 {
    465 	if (!_Kbd) return(KN_NONE);
    466 	int key		= _Kbd->Get();
    467 	int flags	= key & 0xFF00;
    468 	key		   = key & 0x00FF;
    469 
    470 	if (isupper(key)) {
    471 		key = tolower(key);
    472 		if ( !(flags & WWKEY_VK_BIT) ) {
    473 			flags |= WWKEY_SHIFT_BIT;
    474 		}
    475 	}
    476 	return(key | flags);
    477 }
    478 
    479 int KN_To_KA(int key)
    480 {
    481 	if ( key & WWKEY_RLS_BIT) {
    482 		return(KA_NONE);
    483 	}
    484 	if (!(key & WWKEY_VK_BIT)) {
    485 		int flags = key & 0xFF00;
    486 		key		 = key & 0x00FF;
    487 		if (flags & WWKEY_SHIFT_BIT) {
    488 			key		= toupper(key);
    489 			flags	  &= ~WWKEY_SHIFT_BIT;
    490 		}
    491 	}else{
    492 		/*
    493 		** If its a numeric keypad key then fix it up
    494 		*/
    495 		if ((key & 0xff) >=VK_NUMPAD0 && (key & 0xff) <=VK_NUMPAD9){
    496 			key = (key & 0xff) - VK_NUMPAD0 + KA_0;
    497 		}
    498 	}
    499 	return(key);
    500 }
    501 
    502 int KN_To_VK(int key)
    503 {
    504 	if (!_Kbd) return(KN_NONE);
    505 	if ( key & WWKEY_RLS_BIT) {
    506 		return(VK_NONE);
    507 	}
    508 
    509 	int flags = key & 0xFF00;
    510 	if (!(flags & WWKEY_VK_BIT)) {
    511 		key 		 = _Kbd->VKRemap[key & 0x00FF] | flags;
    512 	}
    513 	key &= ~WWKEY_VK_BIT;
    514 	return(key);
    515 }
    516 
    517 int Key_Down(int key)
    518 {
    519 	if (!_Kbd) return(FALSE);
    520 	return(_Kbd->Down(key));
    521 }
    522 
    523 int Get_Key(void)
    524 {
    525 	int retval;
    526 
    527 	if (!_Kbd) return(KN_NONE);
    528 	retval = _Kbd->Get() & ~WWKEY_SHIFT_BIT;
    529 	if (retval & WWKEY_RLS_BIT) {
    530 		retval = KN_NONE;
    531 	}
    532 	return(retval);
    533 }