/* ** Command & Conquer Red Alert(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** * * * Project Name : Westwood Keyboard Library * * * * File Name : KEYBOARD.CPP * * * * Programmer : Philip W. Gorrow * * * * Start Date : 10/16/95 * * * * Last Update : October 17, 1995 [PWG] * * * *---------------------------------------------------------------------------------------------* * Functions: * * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] * * WWKeyboardClass::Get -- Logic to get a metakey from the buffer * * WWKeyboardClass::Check -- Checks to see if a key is in the buffer * * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer * * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer * * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels * * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels * * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "keyboard.h" /*********************************************************************************************** * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class * * * * INPUT: none * * * * OUTPUT: none * * * * HISTORY: * * 10/16/1995 PWG : Created. * *=============================================================================================*/ WWKeyboardClass::WWKeyboardClass(void) { // // Initialize the keyboard remap table for our system (note it would be bad if someone // switched keyboard modes after this happened. // memset(VKRemap, 0, 2048); memset(AsciiRemap, 0, 256); for (short lp = 1; lp < 255; lp ++) { int vk_key = VkKeyScan(lp); if (vk_key > 0 && vk_key < 2048) { AsciiRemap[vk_key] = lp; VKRemap[vk_key] = vk_key & 0xFF; } } // // Build a remap table of the different keys which are affected by the caps lock and // the num lock. // memset(ToggleKeys, 0, 256); for (lp = 0; lp < 255; lp++ ) { if (isalpha(lp) && isupper(lp)) { ToggleKeys[lp] = 1; } if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) { ToggleKeys[lp] = 2; } } // // Our buffer should start devoid of keys. // memset(Buffer, 0, 256); Head = 0; Tail = 0; // // There should be no starting queued mouse events for us to have to worry // about. // MouseQX = 0; MouseQY = 0; } /*********************************************************************************************** * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer * * * * INPUT: none * * * * OUTPUT: int - the key value that was pulled from buffer (includes bits) * * * * * WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated * * * * HISTORY: * * 10/17/1995 PWG : Created. * *=============================================================================================*/ int WWKeyboardClass::Buff_Get(void) { while (!Check()) {} // wait for key in buffer int temp = Buffer[Head]; // get key out of the buffer int newhead = Head; // save off head for manipulation if (Is_Mouse_Key(temp)) { // if key is a mouse then MouseQX = Buffer[Head+1]; // get the x and y pos MouseQY = Buffer[Head+2]; // from the buffer newhead += 3; // adjust head forward } else { newhead += 1; // adjust head forward } newhead &= 255; Head = newhead; return(temp); } BOOL WWKeyboardClass::Is_Mouse_Key(int key) { key &= 0xFF; return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON); } /*********************************************************************************************** * WWKeyboardClass::Check -- Checks to see if a key is in the buffer * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 10/16/1995 PWG : Created. * *=============================================================================================*/ BOOL WWKeyboardClass::Check(void) { unsigned short temp; // store temp holding spot for key if (Head == Tail) return(FALSE); // if no keys in buff then get out temp = Buffer[Head]; // get key out of the buffer return(temp); // send it back to main program } /*********************************************************************************************** * WWKeyboardClass::Get -- Logic to get a metakey from the buffer * * * * INPUT: none * * * * OUTPUT: int - the meta key taken from the buffer. * * * * WARNINGS: This routine will not return until a keypress is received * * * * HISTORY: * * 10/16/1995 PWG : Created. * *=============================================================================================*/ int WWKeyboardClass::Get(void) { int temp,bits; // store temp holding spot for key while (!Check()) {} // wait for key in buffer temp = Buff_Get(); // get key from the buffer bits = temp & 0xFF00; // save of keyboard bits if (!(bits & WWKEY_VK_BIT)) { // if its not a virtual key temp = AsciiRemap[temp&0x1FF] | bits; // convert to ascii equivalent } return(temp); // return the key that we pulled out } /*********************************************************************************************** * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] * * * * INPUT: int - the key to insert into the buffer * * * * OUTPUT: bool - true if key is sucessfuly inserted. * * * * WARNINGS: none * * * * HISTORY: * * 10/16/1995 PWG : Created. * *=============================================================================================*/ BOOL WWKeyboardClass::Put(int key) { int temp = (Tail + 1) & 255; if (temp != Head) { Buffer[Tail] = key; // // Critical Line // Tail = temp; return(TRUE); } return(FALSE); } /*********************************************************************************************** * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer * * * * INPUT: * * * * OUTPUT: * * * * WARNINGS: * * * * HISTORY: * * 10/16/1995 PWG : Created. * *=============================================================================================*/ WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl) { int bits = 0; // // Get the status of all of the different keyboard modifiers. Note, only pay attention // to numlock and caps lock if we are dealing with a key that is affected by them. // int shift = (GetKeyState(VK_SHIFT) & 0xFF00) != 0; int ctrl = (GetKeyState(VK_CONTROL) & 0xFF00) != 0; int alt = (GetKeyState(VK_MENU) & 0xFF00) != 0; int caps = ((GetKeyState(VK_CAPITAL) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 1); int nums = ((GetKeyState(VK_NUMLOCK) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 2); // // Set the proper bits for whatever the key we got is. // if (shift || caps || nums) { bits |= WWKEY_SHIFT_BIT; } if (ctrl) { bits |= WWKEY_CTRL_BIT; } if (alt) { bits |= WWKEY_ALT_BIT; } if (!AsciiRemap[vk_key|bits]) { bits |= WWKEY_VK_BIT; } if (release) { bits |= WWKEY_RLS_BIT; } if (dbl) { bits |= WWKEY_DBL_BIT; } // // Finally use the put command to enter the key into the keyboard // system. // return(Put(vk_key|bits)); } VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl) { shift = (key & WWKEY_SHIFT_BIT) != 0; ctrl = (key & WWKEY_CTRL_BIT) != 0; alt = (key & WWKEY_ALT_BIT) != 0; rls = (key & WWKEY_RLS_BIT) != 0; dbl = (key & WWKEY_DBL_BIT) != 0; key = (key & 0xFF); } #pragma argsused void WWKeyboardClass::Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam) { switch (message) { case WM_SYSKEYDOWN: case WM_KEYDOWN: Put_Key_Message(wParam); break; case WM_SYSKEYUP: case WM_KEYUP: Put_Key_Message(wParam, TRUE); break; case WM_LBUTTONDOWN: Put_Key_Message(VK_LBUTTON); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_LBUTTONUP: Put_Key_Message(VK_LBUTTON, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_LBUTTONDBLCLK: Put_Key_Message(VK_LBUTTON, TRUE, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_MBUTTONDOWN: Put_Key_Message(VK_MBUTTON); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_MBUTTONUP: Put_Key_Message(VK_MBUTTON, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_MBUTTONDBLCLK: Put_Key_Message(VK_MBUTTON, TRUE, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_RBUTTONDOWN: Put_Key_Message(VK_RBUTTON); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_RBUTTONUP: Put_Key_Message(VK_RBUTTON, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; case WM_RBUTTONDBLCLK: Put_Key_Message(VK_RBUTTON, TRUE, TRUE); Put(LOWORD(lParam)); Put(HIWORD(lParam)); break; } } /*********************************************************************************************** * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels * * * * INPUT: none * * * * OUTPUT: int - returns the mouses current x position in pixels * * * * HISTORY: * * 10/17/1995 PWG : Created. * *=============================================================================================*/ int WWKeyboardClass::Get_Mouse_X(void) { POINT pt; GetCursorPos(&pt); return(pt.x); } void WWKeyboardClass::Clear(void) { Head = Tail; } /*********************************************************************************************** * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels * * * * INPUT: none * * * * OUTPUT: int - returns the mouses current y position in pixels * * * * HISTORY: * * 10/17/1995 PWG : Created. * *=============================================================================================*/ int WWKeyboardClass::Get_Mouse_Y(void) { POINT pt; GetCursorPos(&pt); return(pt.y); } /*********************************************************************************************** * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars * * * * INPUT: int &x - variable to return the mouses x position in pixels * * int &y - variable to return the mouses y position in pixels * * * * OUTPUT: none - output is via reference variables * * * * HISTORY: * * 10/17/1995 PWG : Created. * *=============================================================================================*/ void WWKeyboardClass::Get_Mouse_XY(int &x, int &y) { POINT pt; GetCursorPos(&pt); x = pt.x; y = pt.y; }