pdckbd.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /* PDCurses */
  2. #include "pdcwin.h"
  3. /* These variables are used to store information about the next
  4. Input Event. */
  5. static INPUT_RECORD save_ip;
  6. static MOUSE_STATUS old_mouse_status;
  7. static DWORD event_count = 0;
  8. static SHORT left_key;
  9. static int key_count = 0;
  10. static int save_press = 0;
  11. #define KEV save_ip.Event.KeyEvent
  12. #define MEV save_ip.Event.MouseEvent
  13. #define REV save_ip.Event.WindowBufferSizeEvent
  14. /************************************************************************
  15. * Table for key code translation of function keys in keypad mode *
  16. * These values are for strict IBM keyboard compatibles only *
  17. ************************************************************************/
  18. typedef struct
  19. {
  20. unsigned short normal;
  21. unsigned short shift;
  22. unsigned short control;
  23. unsigned short alt;
  24. unsigned short extended;
  25. } KPTAB;
  26. static KPTAB kptab[] =
  27. {
  28. {0, 0, 0, 0, 0 }, /* 0 */
  29. {0, 0, 0, 0, 0 }, /* 1 VK_LBUTTON */
  30. {0, 0, 0, 0, 0 }, /* 2 VK_RBUTTON */
  31. {0, 0, 0, 0, 0 }, /* 3 VK_CANCEL */
  32. {0, 0, 0, 0, 0 }, /* 4 VK_MBUTTON */
  33. {0, 0, 0, 0, 0 }, /* 5 */
  34. {0, 0, 0, 0, 0 }, /* 6 */
  35. {0, 0, 0, 0, 0 }, /* 7 */
  36. {0x08, 0x08, 0x7F, ALT_BKSP, 0 }, /* 8 VK_BACK */
  37. {0x09, KEY_BTAB, CTL_TAB, ALT_TAB, 999 }, /* 9 VK_TAB */
  38. {0, 0, 0, 0, 0 }, /* 10 */
  39. {0, 0, 0, 0, 0 }, /* 11 */
  40. {KEY_B2, 0x35, CTL_PAD5, ALT_PAD5, 0 }, /* 12 VK_CLEAR */
  41. {0x0D, 0x0D, CTL_ENTER, ALT_ENTER, 1 }, /* 13 VK_RETURN */
  42. {0, 0, 0, 0, 0 }, /* 14 */
  43. {0, 0, 0, 0, 0 }, /* 15 */
  44. {0, 0, 0, 0, 0 }, /* 16 VK_SHIFT HANDLED SEPARATELY */
  45. {0, 0, 0, 0, 0 }, /* 17 VK_CONTROL HANDLED SEPARATELY */
  46. {0, 0, 0, 0, 0 }, /* 18 VK_MENU HANDLED SEPARATELY */
  47. {0, 0, 0, 0, 0 }, /* 19 VK_PAUSE */
  48. {0, 0, 0, 0, 0 }, /* 20 VK_CAPITAL HANDLED SEPARATELY */
  49. {0, 0, 0, 0, 0 }, /* 21 VK_HANGUL */
  50. {0, 0, 0, 0, 0 }, /* 22 */
  51. {0, 0, 0, 0, 0 }, /* 23 VK_JUNJA */
  52. {0, 0, 0, 0, 0 }, /* 24 VK_FINAL */
  53. {0, 0, 0, 0, 0 }, /* 25 VK_HANJA */
  54. {0, 0, 0, 0, 0 }, /* 26 */
  55. {0x1B, 0x1B, 0x1B, ALT_ESC, 0 }, /* 27 VK_ESCAPE */
  56. {0, 0, 0, 0, 0 }, /* 28 VK_CONVERT */
  57. {0, 0, 0, 0, 0 }, /* 29 VK_NONCONVERT */
  58. {0, 0, 0, 0, 0 }, /* 30 VK_ACCEPT */
  59. {0, 0, 0, 0, 0 }, /* 31 VK_MODECHANGE */
  60. {0x20, 0x20, 0x20, 0x20, 0 }, /* 32 VK_SPACE */
  61. {KEY_A3, 0x39, CTL_PAD9, ALT_PAD9, 3 }, /* 33 VK_PRIOR */
  62. {KEY_C3, 0x33, CTL_PAD3, ALT_PAD3, 4 }, /* 34 VK_NEXT */
  63. {KEY_C1, 0x31, CTL_PAD1, ALT_PAD1, 5 }, /* 35 VK_END */
  64. {KEY_A1, 0x37, CTL_PAD7, ALT_PAD7, 6 }, /* 36 VK_HOME */
  65. {KEY_B1, 0x34, CTL_PAD4, ALT_PAD4, 7 }, /* 37 VK_LEFT */
  66. {KEY_A2, 0x38, CTL_PAD8, ALT_PAD8, 8 }, /* 38 VK_UP */
  67. {KEY_B3, 0x36, CTL_PAD6, ALT_PAD6, 9 }, /* 39 VK_RIGHT */
  68. {KEY_C2, 0x32, CTL_PAD2, ALT_PAD2, 10 }, /* 40 VK_DOWN */
  69. {0, 0, 0, 0, 0 }, /* 41 VK_SELECT */
  70. {0, 0, 0, 0, 0 }, /* 42 VK_PRINT */
  71. {0, 0, 0, 0, 0 }, /* 43 VK_EXECUTE */
  72. {0, 0, 0, 0, 0 }, /* 44 VK_SNAPSHOT*/
  73. {PAD0, 0x30, CTL_PAD0, ALT_PAD0, 11 }, /* 45 VK_INSERT */
  74. {PADSTOP, 0x2E, CTL_PADSTOP, ALT_PADSTOP,12 }, /* 46 VK_DELETE */
  75. {0, 0, 0, 0, 0 }, /* 47 VK_HELP */
  76. {0x30, 0x29, 0, ALT_0, 0 }, /* 48 */
  77. {0x31, 0x21, 0, ALT_1, 0 }, /* 49 */
  78. {0x32, 0x40, 0, ALT_2, 0 }, /* 50 */
  79. {0x33, 0x23, 0, ALT_3, 0 }, /* 51 */
  80. {0x34, 0x24, 0, ALT_4, 0 }, /* 52 */
  81. {0x35, 0x25, 0, ALT_5, 0 }, /* 53 */
  82. {0x36, 0x5E, 0, ALT_6, 0 }, /* 54 */
  83. {0x37, 0x26, 0, ALT_7, 0 }, /* 55 */
  84. {0x38, 0x2A, 0, ALT_8, 0 }, /* 56 */
  85. {0x39, 0x28, 0, ALT_9, 0 }, /* 57 */
  86. {0, 0, 0, 0, 0 }, /* 58 */
  87. {0, 0, 0, 0, 0 }, /* 59 */
  88. {0, 0, 0, 0, 0 }, /* 60 */
  89. {0, 0, 0, 0, 0 }, /* 61 */
  90. {0, 0, 0, 0, 0 }, /* 62 */
  91. {0, 0, 0, 0, 0 }, /* 63 */
  92. {0, 0, 0, 0, 0 }, /* 64 */
  93. {0x61, 0x41, 0x01, ALT_A, 0 }, /* 65 */
  94. {0x62, 0x42, 0x02, ALT_B, 0 }, /* 66 */
  95. {0x63, 0x43, 0x03, ALT_C, 0 }, /* 67 */
  96. {0x64, 0x44, 0x04, ALT_D, 0 }, /* 68 */
  97. {0x65, 0x45, 0x05, ALT_E, 0 }, /* 69 */
  98. {0x66, 0x46, 0x06, ALT_F, 0 }, /* 70 */
  99. {0x67, 0x47, 0x07, ALT_G, 0 }, /* 71 */
  100. {0x68, 0x48, 0x08, ALT_H, 0 }, /* 72 */
  101. {0x69, 0x49, 0x09, ALT_I, 0 }, /* 73 */
  102. {0x6A, 0x4A, 0x0A, ALT_J, 0 }, /* 74 */
  103. {0x6B, 0x4B, 0x0B, ALT_K, 0 }, /* 75 */
  104. {0x6C, 0x4C, 0x0C, ALT_L, 0 }, /* 76 */
  105. {0x6D, 0x4D, 0x0D, ALT_M, 0 }, /* 77 */
  106. {0x6E, 0x4E, 0x0E, ALT_N, 0 }, /* 78 */
  107. {0x6F, 0x4F, 0x0F, ALT_O, 0 }, /* 79 */
  108. {0x70, 0x50, 0x10, ALT_P, 0 }, /* 80 */
  109. {0x71, 0x51, 0x11, ALT_Q, 0 }, /* 81 */
  110. {0x72, 0x52, 0x12, ALT_R, 0 }, /* 82 */
  111. {0x73, 0x53, 0x13, ALT_S, 0 }, /* 83 */
  112. {0x74, 0x54, 0x14, ALT_T, 0 }, /* 84 */
  113. {0x75, 0x55, 0x15, ALT_U, 0 }, /* 85 */
  114. {0x76, 0x56, 0x16, ALT_V, 0 }, /* 86 */
  115. {0x77, 0x57, 0x17, ALT_W, 0 }, /* 87 */
  116. {0x78, 0x58, 0x18, ALT_X, 0 }, /* 88 */
  117. {0x79, 0x59, 0x19, ALT_Y, 0 }, /* 89 */
  118. {0x7A, 0x5A, 0x1A, ALT_Z, 0 }, /* 90 */
  119. {0, 0, 0, 0, 0 }, /* 91 VK_LWIN */
  120. {0, 0, 0, 0, 0 }, /* 92 VK_RWIN */
  121. {0, 0, 0, 0, 0 }, /* 93 VK_APPS */
  122. {0, 0, 0, 0, 0 }, /* 94 */
  123. {0, 0, 0, 0, 0 }, /* 95 */
  124. {0x30, 0, CTL_PAD0, ALT_PAD0, 0 }, /* 96 VK_NUMPAD0 */
  125. {0x31, 0, CTL_PAD1, ALT_PAD1, 0 }, /* 97 VK_NUMPAD1 */
  126. {0x32, 0, CTL_PAD2, ALT_PAD2, 0 }, /* 98 VK_NUMPAD2 */
  127. {0x33, 0, CTL_PAD3, ALT_PAD3, 0 }, /* 99 VK_NUMPAD3 */
  128. {0x34, 0, CTL_PAD4, ALT_PAD4, 0 }, /* 100 VK_NUMPAD4 */
  129. {0x35, 0, CTL_PAD5, ALT_PAD5, 0 }, /* 101 VK_NUMPAD5 */
  130. {0x36, 0, CTL_PAD6, ALT_PAD6, 0 }, /* 102 VK_NUMPAD6 */
  131. {0x37, 0, CTL_PAD7, ALT_PAD7, 0 }, /* 103 VK_NUMPAD7 */
  132. {0x38, 0, CTL_PAD8, ALT_PAD8, 0 }, /* 104 VK_NUMPAD8 */
  133. {0x39, 0, CTL_PAD9, ALT_PAD9, 0 }, /* 105 VK_NUMPAD9 */
  134. {PADSTAR, SHF_PADSTAR,CTL_PADSTAR, ALT_PADSTAR,999 }, /* 106 VK_MULTIPLY*/
  135. {PADPLUS, SHF_PADPLUS,CTL_PADPLUS, ALT_PADPLUS,999 }, /* 107 VK_ADD */
  136. {0, 0, 0, 0, 0 }, /* 108 VK_SEPARATOR */
  137. {PADMINUS, SHF_PADMINUS,CTL_PADMINUS,ALT_PADMINUS,999}, /* 109 VK_SUBTRACT*/
  138. {0x2E, 0, CTL_PADSTOP, ALT_PADSTOP,0 }, /* 110 VK_DECIMAL */
  139. {PADSLASH, SHF_PADSLASH,CTL_PADSLASH,ALT_PADSLASH,2 }, /* 111 VK_DIVIDE */
  140. {KEY_F(1), KEY_F(13), KEY_F(25), KEY_F(37), 0 }, /* 112 VK_F1 */
  141. {KEY_F(2), KEY_F(14), KEY_F(26), KEY_F(38), 0 }, /* 113 VK_F2 */
  142. {KEY_F(3), KEY_F(15), KEY_F(27), KEY_F(39), 0 }, /* 114 VK_F3 */
  143. {KEY_F(4), KEY_F(16), KEY_F(28), KEY_F(40), 0 }, /* 115 VK_F4 */
  144. {KEY_F(5), KEY_F(17), KEY_F(29), KEY_F(41), 0 }, /* 116 VK_F5 */
  145. {KEY_F(6), KEY_F(18), KEY_F(30), KEY_F(42), 0 }, /* 117 VK_F6 */
  146. {KEY_F(7), KEY_F(19), KEY_F(31), KEY_F(43), 0 }, /* 118 VK_F7 */
  147. {KEY_F(8), KEY_F(20), KEY_F(32), KEY_F(44), 0 }, /* 119 VK_F8 */
  148. {KEY_F(9), KEY_F(21), KEY_F(33), KEY_F(45), 0 }, /* 120 VK_F9 */
  149. {KEY_F(10), KEY_F(22), KEY_F(34), KEY_F(46), 0 }, /* 121 VK_F10 */
  150. {KEY_F(11), KEY_F(23), KEY_F(35), KEY_F(47), 0 }, /* 122 VK_F11 */
  151. {KEY_F(12), KEY_F(24), KEY_F(36), KEY_F(48), 0 }, /* 123 VK_F12 */
  152. /* 124 through 218 */
  153. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  154. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  155. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  156. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  157. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  158. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  159. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  160. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  161. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  162. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  163. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  164. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  165. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  166. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  167. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  168. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  169. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  170. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  171. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  172. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  173. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  174. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  175. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  176. {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
  177. {0x5B, 0x7B, 0x1B, ALT_LBRACKET,0 }, /* 219 */
  178. {0x5C, 0x7C, 0x1C, ALT_BSLASH, 0 }, /* 220 */
  179. {0x5D, 0x7D, 0x1D, ALT_RBRACKET,0 }, /* 221 */
  180. {0, 0, 0x27, ALT_FQUOTE, 0 }, /* 222 */
  181. {0, 0, 0, 0, 0 }, /* 223 */
  182. {0, 0, 0, 0, 0 }, /* 224 */
  183. {0, 0, 0, 0, 0 }, /* 225 */
  184. {0, 0, 0, 0, 0 }, /* 226 */
  185. {0, 0, 0, 0, 0 }, /* 227 */
  186. {0, 0, 0, 0, 0 }, /* 228 */
  187. {0, 0, 0, 0, 0 }, /* 229 */
  188. {0, 0, 0, 0, 0 }, /* 230 */
  189. {0, 0, 0, 0, 0 }, /* 231 */
  190. {0, 0, 0, 0, 0 }, /* 232 */
  191. {0, 0, 0, 0, 0 }, /* 233 */
  192. {0, 0, 0, 0, 0 }, /* 234 */
  193. {0, 0, 0, 0, 0 }, /* 235 */
  194. {0, 0, 0, 0, 0 }, /* 236 */
  195. {0, 0, 0, 0, 0 }, /* 237 */
  196. {0, 0, 0, 0, 0 }, /* 238 */
  197. {0, 0, 0, 0, 0 }, /* 239 */
  198. {0, 0, 0, 0, 0 }, /* 240 */
  199. {0, 0, 0, 0, 0 }, /* 241 */
  200. {0, 0, 0, 0, 0 }, /* 242 */
  201. {0, 0, 0, 0, 0 }, /* 243 */
  202. {0, 0, 0, 0, 0 }, /* 244 */
  203. {0, 0, 0, 0, 0 }, /* 245 */
  204. {0, 0, 0, 0, 0 }, /* 246 */
  205. {0, 0, 0, 0, 0 }, /* 247 */
  206. {0, 0, 0, 0, 0 }, /* 248 */
  207. {0, 0, 0, 0, 0 }, /* 249 */
  208. {0, 0, 0, 0, 0 }, /* 250 */
  209. {0, 0, 0, 0, 0 }, /* 251 */
  210. {0, 0, 0, 0, 0 }, /* 252 */
  211. {0, 0, 0, 0, 0 }, /* 253 */
  212. {0, 0, 0, 0, 0 }, /* 254 */
  213. {0, 0, 0, 0, 0 } /* 255 */
  214. };
  215. static KPTAB ext_kptab[] =
  216. {
  217. {0, 0, 0, 0, }, /* MUST BE EMPTY */
  218. {PADENTER, SHF_PADENTER, CTL_PADENTER, ALT_PADENTER}, /* 13 */
  219. {PADSLASH, SHF_PADSLASH, CTL_PADSLASH, ALT_PADSLASH}, /* 111 */
  220. {KEY_PPAGE, KEY_SPREVIOUS, CTL_PGUP, ALT_PGUP }, /* 33 */
  221. {KEY_NPAGE, KEY_SNEXT, CTL_PGDN, ALT_PGDN }, /* 34 */
  222. {KEY_END, KEY_SEND, CTL_END, ALT_END }, /* 35 */
  223. {KEY_HOME, KEY_SHOME, CTL_HOME, ALT_HOME }, /* 36 */
  224. {KEY_LEFT, KEY_SLEFT, CTL_LEFT, ALT_LEFT }, /* 37 */
  225. {KEY_UP, KEY_SUP, CTL_UP, ALT_UP }, /* 38 */
  226. {KEY_RIGHT, KEY_SRIGHT, CTL_RIGHT, ALT_RIGHT }, /* 39 */
  227. {KEY_DOWN, KEY_SDOWN, CTL_DOWN, ALT_DOWN }, /* 40 */
  228. {KEY_IC, KEY_SIC, CTL_INS, ALT_INS }, /* 45 */
  229. {KEY_DC, KEY_SDC, CTL_DEL, ALT_DEL }, /* 46 */
  230. {PADSLASH, SHF_PADSLASH, CTL_PADSLASH, ALT_PADSLASH}, /* 191 */
  231. };
  232. /* End of kptab[] */
  233. void PDC_set_keyboard_binary(bool on)
  234. {
  235. DWORD mode;
  236. PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
  237. GetConsoleMode(pdc_con_in, &mode);
  238. SetConsoleMode(pdc_con_in, !on ? (mode | ENABLE_PROCESSED_INPUT) :
  239. (mode & ~ENABLE_PROCESSED_INPUT));
  240. }
  241. /* check if a key or mouse event is waiting */
  242. bool PDC_check_key(void)
  243. {
  244. if (key_count > 0)
  245. return TRUE;
  246. GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
  247. return (event_count != 0);
  248. }
  249. /* _get_key_count returns 0 if save_ip doesn't contain an event which
  250. should be passed back to the user. This function filters "useless"
  251. events.
  252. The function returns the number of keys waiting. This may be > 1
  253. if the repetition of real keys pressed so far are > 1.
  254. Returns 0 on NUMLOCK, CAPSLOCK, SCROLLLOCK.
  255. Returns 1 for SHIFT, ALT, CTRL only if no other key has been pressed
  256. in between, and SP->return_key_modifiers is set; these are returned
  257. on keyup.
  258. Normal keys are returned on keydown only. The number of repetitions
  259. are returned. Dead keys (diacritics) are omitted. See below for a
  260. description.
  261. */
  262. static int _get_key_count(void)
  263. {
  264. int num_keys = 0, vk;
  265. PDC_LOG(("_get_key_count() - called\n"));
  266. vk = KEV.wVirtualKeyCode;
  267. if (KEV.bKeyDown)
  268. {
  269. /* key down */
  270. save_press = 0;
  271. if (vk == VK_CAPITAL || vk == VK_NUMLOCK || vk == VK_SCROLL)
  272. {
  273. /* throw away these modifiers */
  274. }
  275. else if (vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU)
  276. {
  277. /* These keys are returned on keyup only. */
  278. save_press = vk;
  279. switch (vk)
  280. {
  281. case VK_SHIFT:
  282. left_key = GetKeyState(VK_LSHIFT);
  283. break;
  284. case VK_CONTROL:
  285. left_key = GetKeyState(VK_LCONTROL);
  286. break;
  287. case VK_MENU:
  288. left_key = GetKeyState(VK_LMENU);
  289. }
  290. }
  291. else
  292. {
  293. /* Check for diacritics. These are dead keys. Some locales
  294. have modified characters like umlaut-a, which is an "a"
  295. with two dots on it. In some locales you have to press a
  296. special key (the dead key) immediately followed by the
  297. "a" to get a composed umlaut-a. The special key may have
  298. a normal meaning with different modifiers. */
  299. if (KEV.uChar.UnicodeChar || !(MapVirtualKey(vk, 2) & 0x80000000))
  300. num_keys = KEV.wRepeatCount;
  301. }
  302. }
  303. else
  304. {
  305. /* key up */
  306. /* Only modifier keys or the results of ALT-numpad entry are
  307. returned on keyup */
  308. if ((vk == VK_MENU && KEV.uChar.UnicodeChar) ||
  309. ((vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU) &&
  310. vk == save_press))
  311. {
  312. save_press = 0;
  313. num_keys = 1;
  314. }
  315. }
  316. PDC_LOG(("_get_key_count() - returning: num_keys %d\n", num_keys));
  317. return num_keys;
  318. }
  319. /* _process_key_event returns -1 if the key in save_ip should be
  320. ignored. Otherwise it returns the keycode which should be returned
  321. by PDC_get_key(). save_ip must be a key event.
  322. CTRL-ALT support has been disabled, when is it emitted plainly? */
  323. static int _process_key_event(void)
  324. {
  325. int key =
  326. #ifdef PDC_WIDE
  327. KEV.uChar.UnicodeChar;
  328. #else
  329. KEV.uChar.AsciiChar;
  330. #endif
  331. WORD vk = KEV.wVirtualKeyCode;
  332. DWORD state = KEV.dwControlKeyState;
  333. int idx;
  334. BOOL enhanced;
  335. SP->key_code = TRUE;
  336. /* Save the key modifiers. Do this first to allow to detect e.g. a
  337. pressed CTRL key after a hit of NUMLOCK. */
  338. if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
  339. SP->key_modifiers |= PDC_KEY_MODIFIER_ALT;
  340. if (state & SHIFT_PRESSED)
  341. SP->key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
  342. if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
  343. SP->key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
  344. if (state & NUMLOCK_ON)
  345. SP->key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
  346. /* Handle modifier keys hit by themselves */
  347. switch (vk)
  348. {
  349. case VK_SHIFT: /* shift */
  350. if (!SP->return_key_modifiers)
  351. return -1;
  352. return (left_key & 0x8000) ? KEY_SHIFT_L : KEY_SHIFT_R;
  353. case VK_CONTROL: /* control */
  354. if (!SP->return_key_modifiers)
  355. return -1;
  356. return (left_key & 0x8000) ? KEY_CONTROL_L : KEY_CONTROL_R;
  357. case VK_MENU: /* alt */
  358. if (!key)
  359. {
  360. if (!SP->return_key_modifiers)
  361. return -1;
  362. return (left_key & 0x8000) ? KEY_ALT_L : KEY_ALT_R;
  363. }
  364. }
  365. /* The system may emit Ascii or Unicode characters depending on
  366. whether ReadConsoleInputA or ReadConsoleInputW is used.
  367. Normally, if key != 0 then the system did the translation
  368. successfully. But this is not true for LEFT_ALT (different to
  369. RIGHT_ALT). In case of LEFT_ALT we can get key != 0. So
  370. check for this first. */
  371. if (key && ( !(state & LEFT_ALT_PRESSED) ||
  372. (state & RIGHT_ALT_PRESSED) ))
  373. {
  374. /* This code should catch all keys returning a printable
  375. character. Characters above 0x7F should be returned as
  376. positive codes. */
  377. if (kptab[vk].extended == 0)
  378. {
  379. SP->key_code = FALSE;
  380. return key;
  381. }
  382. }
  383. /* This case happens if a functional key has been entered. */
  384. if ((state & ENHANCED_KEY) && (kptab[vk].extended != 999))
  385. {
  386. enhanced = TRUE;
  387. idx = kptab[vk].extended;
  388. }
  389. else
  390. {
  391. enhanced = FALSE;
  392. idx = vk;
  393. }
  394. if (state & SHIFT_PRESSED)
  395. key = enhanced ? ext_kptab[idx].shift : kptab[idx].shift;
  396. else if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
  397. key = enhanced ? ext_kptab[idx].control : kptab[idx].control;
  398. else if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
  399. key = enhanced ? ext_kptab[idx].alt : kptab[idx].alt;
  400. else
  401. key = enhanced ? ext_kptab[idx].normal : kptab[idx].normal;
  402. if (key < KEY_CODE_YES)
  403. SP->key_code = FALSE;
  404. return key;
  405. }
  406. static int _process_mouse_event(void)
  407. {
  408. static const DWORD button_mask[] = {1, 4, 2};
  409. short action, shift_flags = 0;
  410. int i;
  411. save_press = 0;
  412. SP->key_code = TRUE;
  413. memset(&SP->mouse_status, 0, sizeof(MOUSE_STATUS));
  414. /* Handle scroll wheel */
  415. if (MEV.dwEventFlags == 4)
  416. {
  417. SP->mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
  418. PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;
  419. SP->mouse_status.x = -1;
  420. SP->mouse_status.y = -1;
  421. memset(&old_mouse_status, 0, sizeof(old_mouse_status));
  422. return KEY_MOUSE;
  423. }
  424. if (MEV.dwEventFlags == 8)
  425. {
  426. SP->mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
  427. PDC_MOUSE_WHEEL_RIGHT : PDC_MOUSE_WHEEL_LEFT;
  428. SP->mouse_status.x = -1;
  429. SP->mouse_status.y = -1;
  430. memset(&old_mouse_status, 0, sizeof(old_mouse_status));
  431. return KEY_MOUSE;
  432. }
  433. action = (MEV.dwEventFlags == 2) ? BUTTON_DOUBLE_CLICKED :
  434. ((MEV.dwEventFlags == 1) ? BUTTON_MOVED : BUTTON_PRESSED);
  435. for (i = 0; i < 3; i++)
  436. SP->mouse_status.button[i] =
  437. (MEV.dwButtonState & button_mask[i]) ? action : 0;
  438. if (action == BUTTON_PRESSED && MEV.dwButtonState & 7 && SP->mouse_wait)
  439. {
  440. /* Check for a click -- a PRESS followed immediately by a release */
  441. if (!event_count)
  442. {
  443. napms(SP->mouse_wait);
  444. GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
  445. }
  446. if (event_count)
  447. {
  448. INPUT_RECORD ip;
  449. DWORD count;
  450. bool have_click = FALSE;
  451. PeekConsoleInput(pdc_con_in, &ip, 1, &count);
  452. for (i = 0; i < 3; i++)
  453. {
  454. if (SP->mouse_status.button[i] == BUTTON_PRESSED &&
  455. !(ip.Event.MouseEvent.dwButtonState & button_mask[i]))
  456. {
  457. SP->mouse_status.button[i] = BUTTON_CLICKED;
  458. have_click = TRUE;
  459. }
  460. }
  461. /* If a click was found, throw out the event */
  462. if (have_click)
  463. ReadConsoleInput(pdc_con_in, &ip, 1, &count);
  464. }
  465. }
  466. SP->mouse_status.x = MEV.dwMousePosition.X;
  467. SP->mouse_status.y = MEV.dwMousePosition.Y;
  468. SP->mouse_status.changes = 0;
  469. for (i = 0; i < 3; i++)
  470. {
  471. if (old_mouse_status.button[i] != SP->mouse_status.button[i])
  472. SP->mouse_status.changes |= (1 << i);
  473. if (SP->mouse_status.button[i] == BUTTON_MOVED)
  474. {
  475. /* Discard non-moved "moves" */
  476. if (SP->mouse_status.x == old_mouse_status.x &&
  477. SP->mouse_status.y == old_mouse_status.y)
  478. return -1;
  479. /* Motion events always flag the button as changed */
  480. SP->mouse_status.changes |= (1 << i);
  481. SP->mouse_status.changes |= PDC_MOUSE_MOVED;
  482. break;
  483. }
  484. }
  485. old_mouse_status = SP->mouse_status;
  486. /* Treat click events as release events for comparison purposes */
  487. for (i = 0; i < 3; i++)
  488. {
  489. if (old_mouse_status.button[i] == BUTTON_CLICKED ||
  490. old_mouse_status.button[i] == BUTTON_DOUBLE_CLICKED)
  491. old_mouse_status.button[i] = BUTTON_RELEASED;
  492. }
  493. /* Check for SHIFT/CONTROL/ALT */
  494. if (MEV.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
  495. shift_flags |= BUTTON_ALT;
  496. if (MEV.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
  497. shift_flags |= BUTTON_CONTROL;
  498. if (MEV.dwControlKeyState & SHIFT_PRESSED)
  499. shift_flags |= BUTTON_SHIFT;
  500. if (shift_flags)
  501. {
  502. for (i = 0; i < 3; i++)
  503. {
  504. if (SP->mouse_status.changes & (1 << i))
  505. SP->mouse_status.button[i] |= shift_flags;
  506. }
  507. }
  508. return KEY_MOUSE;
  509. }
  510. /* return the next available key or mouse event */
  511. int PDC_get_key(void)
  512. {
  513. SP->key_modifiers = 0L;
  514. if (!key_count)
  515. {
  516. DWORD count;
  517. ReadConsoleInput(pdc_con_in, &save_ip, 1, &count);
  518. event_count--;
  519. if (save_ip.EventType == MOUSE_EVENT ||
  520. save_ip.EventType == WINDOW_BUFFER_SIZE_EVENT)
  521. key_count = 1;
  522. else if (save_ip.EventType == KEY_EVENT)
  523. key_count = _get_key_count();
  524. }
  525. if (key_count)
  526. {
  527. key_count--;
  528. switch (save_ip.EventType)
  529. {
  530. case KEY_EVENT:
  531. return _process_key_event();
  532. case MOUSE_EVENT:
  533. return _process_mouse_event();
  534. case WINDOW_BUFFER_SIZE_EVENT:
  535. if (REV.dwSize.Y != LINES || REV.dwSize.X != COLS)
  536. {
  537. if (!SP->resized)
  538. {
  539. SP->resized = TRUE;
  540. SP->key_code = TRUE;
  541. return KEY_RESIZE;
  542. }
  543. }
  544. }
  545. }
  546. return -1;
  547. }
  548. /* discard any pending keyboard or mouse input -- this is the core
  549. routine for flushinp() */
  550. void PDC_flushinp(void)
  551. {
  552. PDC_LOG(("PDC_flushinp() - called\n"));
  553. FlushConsoleInputBuffer(pdc_con_in);
  554. }
  555. bool PDC_has_mouse(void)
  556. {
  557. return TRUE;
  558. }
  559. int PDC_mouse_set(void)
  560. {
  561. DWORD mode;
  562. /* If turning on mouse input: Set ENABLE_MOUSE_INPUT, and clear
  563. all other flags, except processed input mode;
  564. If turning off the mouse: Set QuickEdit Mode to the status it
  565. had on startup, and clear all other flags, except etc. */
  566. GetConsoleMode(pdc_con_in, &mode);
  567. mode = (mode & 1) | 0x0088;
  568. SetConsoleMode(pdc_con_in, mode | (SP->_trap_mbe ?
  569. ENABLE_MOUSE_INPUT : pdc_quick_edit));
  570. memset(&old_mouse_status, 0, sizeof(old_mouse_status));
  571. return OK;
  572. }
  573. int PDC_modifiers_set(void)
  574. {
  575. return OK;
  576. }