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 }