KEYBOARD.CPP 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. * *
  20. * Project Name : Westwood Keyboard Library *
  21. * *
  22. * File Name : KEYBOARD.CPP *
  23. * *
  24. * Programmer : Philip W. Gorrow *
  25. * *
  26. * Start Date : 10/16/95 *
  27. * *
  28. * Last Update : October 17, 1995 [PWG] *
  29. * *
  30. *---------------------------------------------------------------------------------------------*
  31. * Functions: *
  32. * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
  33. * WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
  34. * WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
  35. * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
  36. * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
  37. * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
  38. * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
  39. * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
  40. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  41. #include "keyboard.h"
  42. /***********************************************************************************************
  43. * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class *
  44. * *
  45. * INPUT: none *
  46. * *
  47. * OUTPUT: none *
  48. * *
  49. * HISTORY: *
  50. * 10/16/1995 PWG : Created. *
  51. *=============================================================================================*/
  52. WWKeyboardClass::WWKeyboardClass(void)
  53. {
  54. //
  55. // Initialize the keyboard remap table for our system (note it would be bad if someone
  56. // switched keyboard modes after this happened.
  57. //
  58. memset(VKRemap, 0, 2048);
  59. memset(AsciiRemap, 0, 256);
  60. for (short lp = 1; lp < 255; lp ++) {
  61. int vk_key = VkKeyScan(lp);
  62. if (vk_key > 0 && vk_key < 2048) {
  63. AsciiRemap[vk_key] = lp;
  64. VKRemap[vk_key] = vk_key & 0xFF;
  65. }
  66. }
  67. //
  68. // Build a remap table of the different keys which are affected by the caps lock and
  69. // the num lock.
  70. //
  71. memset(ToggleKeys, 0, 256);
  72. for (lp = 0; lp < 255; lp++ ) {
  73. if (isalpha(lp) && isupper(lp)) {
  74. ToggleKeys[lp] = 1;
  75. }
  76. if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {
  77. ToggleKeys[lp] = 2;
  78. }
  79. }
  80. //
  81. // Our buffer should start devoid of keys.
  82. //
  83. memset(Buffer, 0, 256);
  84. Head = 0;
  85. Tail = 0;
  86. //
  87. // There should be no starting queued mouse events for us to have to worry
  88. // about.
  89. //
  90. MouseQX = 0;
  91. MouseQY = 0;
  92. }
  93. /***********************************************************************************************
  94. * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
  95. * *
  96. * INPUT: none *
  97. * *
  98. * OUTPUT: int - the key value that was pulled from buffer (includes bits) * *
  99. * *
  100. * WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated *
  101. * *
  102. * HISTORY: *
  103. * 10/17/1995 PWG : Created. *
  104. *=============================================================================================*/
  105. int WWKeyboardClass::Buff_Get(void)
  106. {
  107. while (!Check()) {} // wait for key in buffer
  108. int temp = Buffer[Head]; // get key out of the buffer
  109. int newhead = Head; // save off head for manipulation
  110. if (Is_Mouse_Key(temp)) { // if key is a mouse then
  111. MouseQX = Buffer[Head+1]; // get the x and y pos
  112. MouseQY = Buffer[Head+2]; // from the buffer
  113. newhead += 3; // adjust head forward
  114. } else {
  115. newhead += 1; // adjust head forward
  116. }
  117. newhead &= 255;
  118. Head = newhead;
  119. return(temp);
  120. }
  121. BOOL WWKeyboardClass::Is_Mouse_Key(int key)
  122. {
  123. key &= 0xFF;
  124. return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
  125. }
  126. /***********************************************************************************************
  127. * WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
  128. * *
  129. * INPUT: *
  130. * *
  131. * OUTPUT: *
  132. * *
  133. * WARNINGS: *
  134. * *
  135. * HISTORY: *
  136. * 10/16/1995 PWG : Created. *
  137. *=============================================================================================*/
  138. BOOL WWKeyboardClass::Check(void)
  139. {
  140. unsigned short temp; // store temp holding spot for key
  141. if (Head == Tail) return(FALSE); // if no keys in buff then get out
  142. temp = Buffer[Head]; // get key out of the buffer
  143. return(temp); // send it back to main program
  144. }
  145. /***********************************************************************************************
  146. * WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
  147. * *
  148. * INPUT: none *
  149. * *
  150. * OUTPUT: int - the meta key taken from the buffer. *
  151. * *
  152. * WARNINGS: This routine will not return until a keypress is received *
  153. * *
  154. * HISTORY: *
  155. * 10/16/1995 PWG : Created. *
  156. *=============================================================================================*/
  157. int WWKeyboardClass::Get(void)
  158. {
  159. int temp,bits; // store temp holding spot for key
  160. while (!Check()) {} // wait for key in buffer
  161. temp = Buff_Get(); // get key from the buffer
  162. bits = temp & 0xFF00; // save of keyboard bits
  163. if (!(bits & WWKEY_VK_BIT)) { // if its not a virtual key
  164. temp = AsciiRemap[temp&0x1FF] | bits; // convert to ascii equivalent
  165. }
  166. return(temp); // return the key that we pulled out
  167. }
  168. /***********************************************************************************************
  169. * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
  170. * *
  171. * INPUT: int - the key to insert into the buffer *
  172. * *
  173. * OUTPUT: bool - true if key is sucessfuly inserted. *
  174. * *
  175. * WARNINGS: none *
  176. * *
  177. * HISTORY: *
  178. * 10/16/1995 PWG : Created. *
  179. *=============================================================================================*/
  180. BOOL WWKeyboardClass::Put(int key)
  181. {
  182. int temp = (Tail + 1) & 255;
  183. if (temp != Head)
  184. {
  185. Buffer[Tail] = key;
  186. //
  187. // Critical Line
  188. //
  189. Tail = temp;
  190. return(TRUE);
  191. }
  192. return(FALSE);
  193. }
  194. /***********************************************************************************************
  195. * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
  196. * *
  197. * INPUT: *
  198. * *
  199. * OUTPUT: *
  200. * *
  201. * WARNINGS: *
  202. * *
  203. * HISTORY: *
  204. * 10/16/1995 PWG : Created. *
  205. *=============================================================================================*/
  206. WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)
  207. {
  208. int bits = 0;
  209. //
  210. // Get the status of all of the different keyboard modifiers. Note, only pay attention
  211. // to numlock and caps lock if we are dealing with a key that is affected by them.
  212. //
  213. int shift = (GetKeyState(VK_SHIFT) & 0xFF00) != 0;
  214. int ctrl = (GetKeyState(VK_CONTROL) & 0xFF00) != 0;
  215. int alt = (GetKeyState(VK_MENU) & 0xFF00) != 0;
  216. int caps = ((GetKeyState(VK_CAPITAL) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 1);
  217. int nums = ((GetKeyState(VK_NUMLOCK) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 2);
  218. //
  219. // Set the proper bits for whatever the key we got is.
  220. //
  221. if (shift || caps || nums) {
  222. bits |= WWKEY_SHIFT_BIT;
  223. }
  224. if (ctrl) {
  225. bits |= WWKEY_CTRL_BIT;
  226. }
  227. if (alt) {
  228. bits |= WWKEY_ALT_BIT;
  229. }
  230. if (!AsciiRemap[vk_key|bits]) {
  231. bits |= WWKEY_VK_BIT;
  232. }
  233. if (release) {
  234. bits |= WWKEY_RLS_BIT;
  235. }
  236. if (dbl) {
  237. bits |= WWKEY_DBL_BIT;
  238. }
  239. //
  240. // Finally use the put command to enter the key into the keyboard
  241. // system.
  242. //
  243. return(Put(vk_key|bits));
  244. }
  245. VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)
  246. {
  247. shift = (key & WWKEY_SHIFT_BIT) != 0;
  248. ctrl = (key & WWKEY_CTRL_BIT) != 0;
  249. alt = (key & WWKEY_ALT_BIT) != 0;
  250. rls = (key & WWKEY_RLS_BIT) != 0;
  251. dbl = (key & WWKEY_DBL_BIT) != 0;
  252. key = (key & 0xFF);
  253. }
  254. #pragma argsused
  255. void WWKeyboardClass::Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam)
  256. {
  257. switch (message) {
  258. case WM_SYSKEYDOWN:
  259. case WM_KEYDOWN:
  260. Put_Key_Message(wParam);
  261. break;
  262. case WM_SYSKEYUP:
  263. case WM_KEYUP:
  264. Put_Key_Message(wParam, TRUE);
  265. break;
  266. case WM_LBUTTONDOWN:
  267. Put_Key_Message(VK_LBUTTON);
  268. Put(LOWORD(lParam));
  269. Put(HIWORD(lParam));
  270. break;
  271. case WM_LBUTTONUP:
  272. Put_Key_Message(VK_LBUTTON, TRUE);
  273. Put(LOWORD(lParam));
  274. Put(HIWORD(lParam));
  275. break;
  276. case WM_LBUTTONDBLCLK:
  277. Put_Key_Message(VK_LBUTTON, TRUE, TRUE);
  278. Put(LOWORD(lParam));
  279. Put(HIWORD(lParam));
  280. break;
  281. case WM_MBUTTONDOWN:
  282. Put_Key_Message(VK_MBUTTON);
  283. Put(LOWORD(lParam));
  284. Put(HIWORD(lParam));
  285. break;
  286. case WM_MBUTTONUP:
  287. Put_Key_Message(VK_MBUTTON, TRUE);
  288. Put(LOWORD(lParam));
  289. Put(HIWORD(lParam));
  290. break;
  291. case WM_MBUTTONDBLCLK:
  292. Put_Key_Message(VK_MBUTTON, TRUE, TRUE);
  293. Put(LOWORD(lParam));
  294. Put(HIWORD(lParam));
  295. break;
  296. case WM_RBUTTONDOWN:
  297. Put_Key_Message(VK_RBUTTON);
  298. Put(LOWORD(lParam));
  299. Put(HIWORD(lParam));
  300. break;
  301. case WM_RBUTTONUP:
  302. Put_Key_Message(VK_RBUTTON, TRUE);
  303. Put(LOWORD(lParam));
  304. Put(HIWORD(lParam));
  305. break;
  306. case WM_RBUTTONDBLCLK:
  307. Put_Key_Message(VK_RBUTTON, TRUE, TRUE);
  308. Put(LOWORD(lParam));
  309. Put(HIWORD(lParam));
  310. break;
  311. }
  312. }
  313. /***********************************************************************************************
  314. * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
  315. * *
  316. * INPUT: none *
  317. * *
  318. * OUTPUT: int - returns the mouses current x position in pixels *
  319. * *
  320. * HISTORY: *
  321. * 10/17/1995 PWG : Created. *
  322. *=============================================================================================*/
  323. int WWKeyboardClass::Get_Mouse_X(void)
  324. {
  325. POINT pt;
  326. GetCursorPos(&pt);
  327. return(pt.x);
  328. }
  329. void WWKeyboardClass::Clear(void)
  330. {
  331. Head = Tail;
  332. }
  333. /***********************************************************************************************
  334. * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
  335. * *
  336. * INPUT: none *
  337. * *
  338. * OUTPUT: int - returns the mouses current y position in pixels *
  339. * *
  340. * HISTORY: *
  341. * 10/17/1995 PWG : Created. *
  342. *=============================================================================================*/
  343. int WWKeyboardClass::Get_Mouse_Y(void)
  344. {
  345. POINT pt;
  346. GetCursorPos(&pt);
  347. return(pt.y);
  348. }
  349. /***********************************************************************************************
  350. * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
  351. * *
  352. * INPUT: int &x - variable to return the mouses x position in pixels *
  353. * int &y - variable to return the mouses y position in pixels *
  354. * *
  355. * OUTPUT: none - output is via reference variables *
  356. * *
  357. * HISTORY: *
  358. * 10/17/1995 PWG : Created. *
  359. *=============================================================================================*/
  360. void WWKeyboardClass::Get_Mouse_XY(int &x, int &y)
  361. {
  362. POINT pt;
  363. GetCursorPos(&pt);
  364. x = pt.x;
  365. y = pt.y;
  366. }