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