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 }