1 /* Public Domain Curses */
2 
3 #include "pdcwin.h"
4 
5 /*man-start**************************************************************
6 
7 pdckbd
8 ------
9 
10 ### Synopsis
11 
12     unsigned long PDC_get_input_fd(void);
13 
14 ### Description
15 
16    PDC_get_input_fd() returns the file descriptor that PDCurses
17    reads its input from. It can be used for select().
18 
19 ### Portability
20                              X/Open    BSD    SYS V
21     PDC_get_input_fd            -       -       -
22 
23 **man-end****************************************************************/
24 
25 unsigned long pdc_key_modifiers = 0L;
26 
27 /* These variables are used to store information about the next
28    Input Event. */
29 
30 static INPUT_RECORD save_ip;
31 static MOUSE_STATUS old_mouse_status;
32 static DWORD event_count = 0;
33 static SHORT left_key;
34 static int key_count = 0;
35 static int save_press = 0;
36 
37 #define KEV save_ip.Event.KeyEvent
38 #define MEV save_ip.Event.MouseEvent
39 
40 /************************************************************************
41  *    Table for key code translation of function keys in keypad mode    *
42  *    These values are for strict IBM keyboard compatibles only         *
43  ************************************************************************/
44 
45 typedef struct
46 {
47     unsigned short normal;
48     unsigned short shift;
49     unsigned short control;
50     unsigned short alt;
51     unsigned short extended;
52 } KPTAB;
53 
54 static KPTAB kptab[] =
55 {
56    {0,          0,         0,           0,          0   }, /* 0  */
57    {0,          0,         0,           0,          0   }, /* 1   VK_LBUTTON */
58    {0,          0,         0,           0,          0   }, /* 2   VK_RBUTTON */
59    {CTL_PAUSE,  0,         0,           0,          0   }, /* 3   VK_CANCEL  */
60    {0,          0,         0,           0,          0   }, /* 4   VK_MBUTTON */
61    {0,          0,         0,           0,          0   }, /* 5   */
62    {0,          0,         0,           0,          0   }, /* 6   */
63    {0,          0,         0,           0,          0   }, /* 7   */
64    {0x08,       0x08,      0x7F,        ALT_BKSP,   0   }, /* 8   VK_BACK    */
65    {0x09,       KEY_BTAB,  CTL_TAB,     ALT_TAB,    999 }, /* 9   VK_TAB     */
66    {0,          0,         0,           0,          0   }, /* 10  */
67    {0,          0,         0,           0,          0   }, /* 11  */
68    {KEY_B2,     0x35,      CTL_PAD5,    ALT_PAD5,   0   }, /* 12  VK_CLEAR   */
69    {0x0D,       0x0D,      CTL_ENTER,   ALT_ENTER,  1   }, /* 13  VK_RETURN  */
70    {0,          0,         0,           0,          0   }, /* 14  */
71    {0,          0,         0,           0,          0   }, /* 15  */
72    {0,          0,         0,           0,          0   }, /* 16  VK_SHIFT   HANDLED SEPARATELY */
73    {0,          0,         0,           0,          0   }, /* 17  VK_CONTROL HANDLED SEPARATELY */
74    {0,          0,         0,           0,          0   }, /* 18  VK_MENU    HANDLED SEPARATELY */
75    {KEY_PAUSE,  KEY_SPAUSE,CTL_PAUSE,   0,          0   }, /* 19  VK_PAUSE   */
76    {0,          0,         0,           0,          0   }, /* 20  VK_CAPITAL HANDLED SEPARATELY */
77    {0,          0,         0,           0,          0   }, /* 21  VK_HANGUL  */
78    {0,          0,         0,           0,          0   }, /* 22  */
79    {0,          0,         0,           0,          0   }, /* 23  VK_JUNJA   */
80    {0,          0,         0,           0,          0   }, /* 24  VK_FINAL   */
81    {0,          0,         0,           0,          0   }, /* 25  VK_HANJA   */
82    {0,          0,         0,           0,          0   }, /* 26  */
83    {0x1B,       0x1B,      0x1B,        ALT_ESC,    0   }, /* 27  VK_ESCAPE  */
84    {0,          0,         0,           0,          0   }, /* 28  VK_CONVERT */
85    {0,          0,         0,           0,          0   }, /* 29  VK_NONCONVERT */
86    {0,          0,         0,           0,          0   }, /* 30  VK_ACCEPT  */
87    {0,          0,         0,           0,          0   }, /* 31  VK_MODECHANGE */
88    {0x20,       0x20,      0x20,        0x20,       0   }, /* 32  VK_SPACE   */
89    {KEY_A3,     0x39,      CTL_PAD9,    ALT_PAD9,   3   }, /* 33  VK_PRIOR   */
90    {KEY_C3,     0x33,      CTL_PAD3,    ALT_PAD3,   4   }, /* 34  VK_NEXT    */
91    {KEY_C1,     0x31,      CTL_PAD1,    ALT_PAD1,   5   }, /* 35  VK_END     */
92    {KEY_A1,     0x37,      CTL_PAD7,    ALT_PAD7,   6   }, /* 36  VK_HOME    */
93    {KEY_B1,     0x34,      CTL_PAD4,    ALT_PAD4,   7   }, /* 37  VK_LEFT    */
94    {KEY_A2,     0x38,      CTL_PAD8,    ALT_PAD8,   8   }, /* 38  VK_UP      */
95    {KEY_B3,     0x36,      CTL_PAD6,    ALT_PAD6,   9   }, /* 39  VK_RIGHT   */
96    {KEY_C2,     0x32,      CTL_PAD2,    ALT_PAD2,   10  }, /* 40  VK_DOWN    */
97    {0,          0,         0,           0,          0   }, /* 41  VK_SELECT  */
98    {0,          0,         0,           0,          0   }, /* 42  VK_PRINT   */
99    {0,          0,         0,           0,          0   }, /* 43  VK_EXECUTE */
100    {KEY_PRINTSCREEN, 0,    0,       ALT_PRINTSCREEN, 0  }, /* 44  VK_SNAPSHOT*/
101    {PAD0,       0x30,      CTL_PAD0,    ALT_PAD0,   11  }, /* 45  VK_INSERT  */
102    {PADSTOP,    0x2E,      CTL_PADSTOP, ALT_PADSTOP,12  }, /* 46  VK_DELETE  */
103    {0,          0,         0,           0,          0   }, /* 47  VK_HELP    */
104    {0x30,       0x29,      CTL_0,       ALT_0,      0   }, /* 48  */
105    {0x31,       0x21,      CTL_1,       ALT_1,      0   }, /* 49  */
106    {0x32,       0x40,      CTL_2,       ALT_2,      0   }, /* 50  */
107    {0x33,       0x23,      CTL_3,       ALT_3,      0   }, /* 51  */
108    {0x34,       0x24,      CTL_4,       ALT_4,      0   }, /* 52  */
109    {0x35,       0x25,      CTL_5,       ALT_5,      0   }, /* 53  */
110    {0x36,       0x5E,      CTL_6,       ALT_6,      0   }, /* 54  */
111    {0x37,       0x26,      CTL_7,       ALT_7,      0   }, /* 55  */
112    {0x38,       0x2A,      CTL_8,       ALT_8,      0   }, /* 56  */
113    {0x39,       0x28,      CTL_9,       ALT_9,      0   }, /* 57  */
114    {0,          0,         0,           0,          0   }, /* 58  */
115    {0,          0,         0,           0,          0   }, /* 59  */
116    {0,          0,         0,           0,          0   }, /* 60  */
117    {0,          0,         0,           0,          0   }, /* 61  */
118    {0,          0,         0,           0,          0   }, /* 62  */
119    {0,          0,         0,           0,          0   }, /* 63  */
120    {0,          0,         0,           0,          0   }, /* 64  */
121    {0x61,       0x41,      0x01,        ALT_A,      0   }, /* 65  */
122    {0x62,       0x42,      0x02,        ALT_B,      0   }, /* 66  */
123    {0x63,       0x43,      0x03,        ALT_C,      0   }, /* 67  */
124    {0x64,       0x44,      0x04,        ALT_D,      0   }, /* 68  */
125    {0x65,       0x45,      0x05,        ALT_E,      0   }, /* 69  */
126    {0x66,       0x46,      0x06,        ALT_F,      0   }, /* 70  */
127    {0x67,       0x47,      0x07,        ALT_G,      0   }, /* 71  */
128    {0x68,       0x48,      0x08,        ALT_H,      0   }, /* 72  */
129    {0x69,       0x49,      0x09,        ALT_I,      0   }, /* 73  */
130    {0x6A,       0x4A,      0x0A,        ALT_J,      0   }, /* 74  */
131    {0x6B,       0x4B,      0x0B,        ALT_K,      0   }, /* 75  */
132    {0x6C,       0x4C,      0x0C,        ALT_L,      0   }, /* 76  */
133    {0x6D,       0x4D,      0x0D,        ALT_M,      0   }, /* 77  */
134    {0x6E,       0x4E,      0x0E,        ALT_N,      0   }, /* 78  */
135    {0x6F,       0x4F,      0x0F,        ALT_O,      0   }, /* 79  */
136    {0x70,       0x50,      0x10,        ALT_P,      0   }, /* 80  */
137    {0x71,       0x51,      0x11,        ALT_Q,      0   }, /* 81  */
138    {0x72,       0x52,      0x12,        ALT_R,      0   }, /* 82  */
139    {0x73,       0x53,      0x13,        ALT_S,      0   }, /* 83  */
140    {0x74,       0x54,      0x14,        ALT_T,      0   }, /* 84  */
141    {0x75,       0x55,      0x15,        ALT_U,      0   }, /* 85  */
142    {0x76,       0x56,      0x16,        ALT_V,      0   }, /* 86  */
143    {0x77,       0x57,      0x17,        ALT_W,      0   }, /* 87  */
144    {0x78,       0x58,      0x18,        ALT_X,      0   }, /* 88  */
145    {0x79,       0x59,      0x19,        ALT_Y,      0   }, /* 89  */
146    {0x7A,       0x5A,      0x1A,        ALT_Z,      0   }, /* 90  */
147    {0,          0,         0,           0,          0   }, /* 91  VK_LWIN    */
148    {0,          0,         0,           0,          0   }, /* 92  VK_RWIN    */
149    {KEY_APPS,   KEY_SAPPS, CTL_APPS,    ALT_APPS,   13  }, /* 93  VK_APPS    */
150    {0,          0,         0,           0,          0   }, /* 94  */
151    {0,          0,         0,           0,          0   }, /* 95  */
152    {0x30,       0,         CTL_PAD0,    ALT_PAD0,   0   }, /* 96  VK_NUMPAD0 */
153    {0x31,       0,         CTL_PAD1,    ALT_PAD1,   0   }, /* 97  VK_NUMPAD1 */
154    {0x32,       0,         CTL_PAD2,    ALT_PAD2,   0   }, /* 98  VK_NUMPAD2 */
155    {0x33,       0,         CTL_PAD3,    ALT_PAD3,   0   }, /* 99  VK_NUMPAD3 */
156    {0x34,       0,         CTL_PAD4,    ALT_PAD4,   0   }, /* 100 VK_NUMPAD4 */
157    {0x35,       0,         CTL_PAD5,    ALT_PAD5,   0   }, /* 101 VK_NUMPAD5 */
158    {0x36,       0,         CTL_PAD6,    ALT_PAD6,   0   }, /* 102 VK_NUMPAD6 */
159    {0x37,       0,         CTL_PAD7,    ALT_PAD7,   0   }, /* 103 VK_NUMPAD7 */
160    {0x38,       0,         CTL_PAD8,    ALT_PAD8,   0   }, /* 104 VK_NUMPAD8 */
161    {0x39,       0,         CTL_PAD9,    ALT_PAD9,   0   }, /* 105 VK_NUMPAD9 */
162    {PADSTAR,   SHF_PADSTAR,CTL_PADSTAR, ALT_PADSTAR,999 }, /* 106 VK_MULTIPLY*/
163    {PADPLUS,   SHF_PADPLUS,CTL_PADPLUS, ALT_PADPLUS,999 }, /* 107 VK_ADD     */
164    {0,          0,         0,           0,          0   }, /* 108 VK_SEPARATOR     */
165    {PADMINUS, SHF_PADMINUS,CTL_PADMINUS,ALT_PADMINUS,999}, /* 109 VK_SUBTRACT*/
166    {0x2E,       0,         CTL_PADSTOP, ALT_PADSTOP,0   }, /* 110 VK_DECIMAL */
167    {PADSLASH,  SHF_PADSLASH,CTL_PADSLASH,ALT_PADSLASH,2 }, /* 111 VK_DIVIDE  */
168    {KEY_F(1),   KEY_F(13), KEY_F(25),   KEY_F(37),  0   }, /* 112 VK_F1      */
169    {KEY_F(2),   KEY_F(14), KEY_F(26),   KEY_F(38),  0   }, /* 113 VK_F2      */
170    {KEY_F(3),   KEY_F(15), KEY_F(27),   KEY_F(39),  0   }, /* 114 VK_F3      */
171    {KEY_F(4),   KEY_F(16), KEY_F(28),   KEY_F(40),  0   }, /* 115 VK_F4      */
172    {KEY_F(5),   KEY_F(17), KEY_F(29),   KEY_F(41),  0   }, /* 116 VK_F5      */
173    {KEY_F(6),   KEY_F(18), KEY_F(30),   KEY_F(42),  0   }, /* 117 VK_F6      */
174    {KEY_F(7),   KEY_F(19), KEY_F(31),   KEY_F(43),  0   }, /* 118 VK_F7      */
175    {KEY_F(8),   KEY_F(20), KEY_F(32),   KEY_F(44),  0   }, /* 119 VK_F8      */
176    {KEY_F(9),   KEY_F(21), KEY_F(33),   KEY_F(45),  0   }, /* 120 VK_F9      */
177    {KEY_F(10),  KEY_F(22), KEY_F(34),   KEY_F(46),  0   }, /* 121 VK_F10     */
178    {KEY_F(11),  KEY_F(23), KEY_F(35),   KEY_F(47),  0   }, /* 122 VK_F11     */
179    {KEY_F(12),  KEY_F(24), KEY_F(36),   KEY_F(48),  0   }, /* 123 VK_F12     */
180 
181    /* 124 through 218 */
182 
183     {0, 0, 0, 0, 0},  /* 124 VK_F13 */
184     {0, 0, 0, 0, 0},  /* 125 VK_F14 */
185     {0, 0, 0, 0, 0},  /* 126 VK_F15 */
186     {0, 0, 0, 0, 0},  /* 127 VK_F16 */
187     {0, 0, 0, 0, 0},  /* 128 VK_F17 */
188     {0, 0, 0, 0, 0},  /* 129 VK_F18 */
189     {0, 0, 0, 0, 0},  /* 130 VK_F19 */
190     {0, 0, 0, 0, 0},  /* 131 VK_F20 */
191     {0, 0, 0, 0, 0},  /* 132 VK_F21 */
192     {0, 0, 0, 0, 0},  /* 133 VK_F22 */
193     {0, 0, 0, 0, 0},  /* 134 VK_F23 */
194     {0, 0, 0, 0, 0},  /* 135 VK_F24 */
195     {0, 0, 0, 0, 0},  /* 136 unassigned */
196     {0, 0, 0, 0, 0},  /* 137 unassigned */
197     {0, 0, 0, 0, 0},  /* 138 unassigned */
198     {0, 0, 0, 0, 0},  /* 139 unassigned */
199     {0, 0, 0, 0, 0},  /* 140 unassigned */
200     {0, 0, 0, 0, 0},  /* 141 unassigned */
201     {0, 0, 0, 0, 0},  /* 142 unassigned */
202     {0, 0, 0, 0, 0},  /* 143 unassigned */
203     {0, 0, 0, 0, 0},  /* 144 VK_NUMLOCK */
204     {KEY_SCROLLLOCK, 0, 0, ALT_SCROLLLOCK, 0},    /* 145 VKSCROLL */
205     {0, 0, 0, 0, 0},  /* 146 OEM specific */
206     {0, 0, 0, 0, 0},  /* 147 OEM specific */
207     {0, 0, 0, 0, 0},  /* 148 OEM specific */
208     {0, 0, 0, 0, 0},  /* 149 OEM specific */
209     {0, 0, 0, 0, 0},  /* 150 OEM specific */
210     {0, 0, 0, 0, 0},  /* 151 Unassigned */
211     {0, 0, 0, 0, 0},  /* 152 Unassigned */
212     {0, 0, 0, 0, 0},  /* 153 Unassigned */
213     {0, 0, 0, 0, 0},  /* 154 Unassigned */
214     {0, 0, 0, 0, 0},  /* 155 Unassigned */
215     {0, 0, 0, 0, 0},  /* 156 Unassigned */
216     {0, 0, 0, 0, 0},  /* 157 Unassigned */
217     {0, 0, 0, 0, 0},  /* 158 Unassigned */
218     {0, 0, 0, 0, 0},  /* 159 Unassigned */
219     {0, 0, 0, 0, 0},  /* 160 VK_LSHIFT */
220     {0, 0, 0, 0, 0},  /* 161 VK_RSHIFT */
221     {0, 0, 0, 0, 0},  /* 162 VK_LCONTROL */
222     {0, 0, 0, 0, 0},  /* 163 VK_RCONTROL */
223     {0, 0, 0, 0, 0},  /* 164 VK_LMENU */
224     {0, 0, 0, 0, 0},  /* 165 VK_RMENU */
225     {0, 0, 0, 0, 14},  /* 166 VK_BROWSER_BACK        */
226     {0, 0, 0, 0, 15},  /* 167 VK_BROWSER_FORWARD     */
227     {0, 0, 0, 0, 16},  /* 168 VK_BROWSER_REFRESH     */
228     {0, 0, 0, 0, 17},  /* 169 VK_BROWSER_STOP        */
229     {0, 0, 0, 0, 18},  /* 170 VK_BROWSER_SEARCH      */
230     {0, 0, 0, 0, 19},  /* 171 VK_BROWSER_FAVORITES   */
231     {0, 0, 0, 0, 20},  /* 172 VK_BROWSER_HOME        */
232     {0, 0, 0, 0, 21},  /* 173 VK_VOLUME_MUTE         */
233     {0, 0, 0, 0, 22},  /* 174 VK_VOLUME_DOWN         */
234     {0, 0, 0, 0, 23},  /* 175 VK_VOLUME_UP           */
235     {0, 0, 0, 0, 24},  /* 176 VK_MEDIA_NEXT_TRACK    */
236     {0, 0, 0, 0, 25},  /* 177 VK_MEDIA_PREV_TRACK    */
237     {0, 0, 0, 0, 26},  /* 178 VK_MEDIA_STOP          */
238     {0, 0, 0, 0, 27},  /* 179 VK_MEDIA_PLAY_PAUSE    */
239     {0, 0, 0, 0, 28},  /* 180 VK_LAUNCH_MAIL         */
240     {0, 0, 0, 0, 29},  /* 181 VK_LAUNCH_MEDIA_SELECT */
241     {0, 0, 0, 0, 30},  /* 182 VK_LAUNCH_APP1         */
242     {0, 0, 0, 0, 31},  /* 183 VK_LAUNCH_APP2         */
243     {0, 0, 0, 0, 0},  /* 184 Reserved */
244     {0, 0, 0, 0, 0},  /* 185 Reserved */
245     {';', ':', CTL_SEMICOLON, ALT_SEMICOLON, 0},  /* 186 VK_OEM_1      */
246     {'=', '+', CTL_EQUAL,     ALT_EQUAL,     0},  /* 187 VK_OEM_PLUS   */
247     {',', '<', CTL_COMMA,     ALT_COMMA,     0},  /* 188 VK_OEM_COMMA  */
248     {'-', '_', CTL_MINUS,     ALT_MINUS,     0},  /* 189 VK_OEM_MINUS  */
249     {'.', '>', CTL_STOP,      ALT_STOP,      0},  /* 190 VK_OEM_PERIOD */
250     {'/', '?', CTL_FSLASH,    ALT_FSLASH,    0},  /* 191 VK_OEM_2      */
251     {'`', '~', CTL_BQUOTE,    ALT_BQUOTE,    0},  /* 192 VK_OEM_3      */
252     {0, 0, 0, 0, 0},  /* 193 */
253     {0, 0, 0, 0, 0},  /* 194 */
254     {0, 0, 0, 0, 0},  /* 195 */
255     {0, 0, 0, 0, 0},  /* 196 */
256     {0, 0, 0, 0, 0},  /* 197 */
257     {0, 0, 0, 0, 0},  /* 198 */
258     {0, 0, 0, 0, 0},  /* 199 */
259     {0, 0, 0, 0, 0},  /* 200 */
260     {0, 0, 0, 0, 0},  /* 201 */
261     {0, 0, 0, 0, 0},  /* 202 */
262     {0, 0, 0, 0, 0},  /* 203 */
263     {0, 0, 0, 0, 0},  /* 204 */
264     {0, 0, 0, 0, 0},  /* 205 */
265     {0, 0, 0, 0, 0},  /* 206 */
266     {0, 0, 0, 0, 0},  /* 207 */
267     {0, 0, 0, 0, 0},  /* 208 */
268     {0, 0, 0, 0, 0},  /* 209 */
269     {0, 0, 0, 0, 0},  /* 210 */
270     {0, 0, 0, 0, 0},  /* 211 */
271     {0, 0, 0, 0, 0},  /* 212 */
272     {0, 0, 0, 0, 0},  /* 213 */
273     {0, 0, 0, 0, 0},  /* 214 */
274     {0, 0, 0, 0, 0},  /* 215 */
275     {0, 0, 0, 0, 0},  /* 216 */
276     {0, 0, 0, 0, 0},  /* 217 */
277     {0, 0, 0, 0, 0},  /* 218 */
278    {0x5B,       0x7B,      0x1B,        ALT_LBRACKET,0  }, /* 219 VK_OEM_4 */
279    {0x5C,       0x7C,      0x1C,        ALT_BSLASH, 0   }, /* 220 VK_OEM_5 */
280    {0x5D,       0x7D,      0x1D,        ALT_RBRACKET,0  }, /* 221 VK_OEM_6 */
281    {'\'',       '"',       0x27,        ALT_FQUOTE, 0   }, /* 222 VK_OEM_7 */
282    {0,          0,         0,           0,          0   }, /* 223 VK_OEM_8 */
283    {0,          0,         0,           0,          0   }, /* 224 */
284    {0,          0,         0,           0,          0   }  /* 225 */
285 };
286 
287 static const KPTAB ext_kptab[] =
288 {
289    {0,          0,              0,              0,          }, /*  0  MUST BE EMPTY */
290    {PADENTER,   SHF_PADENTER,   CTL_PADENTER,   ALT_PADENTER}, /*  1  13 */
291    {PADSLASH,   SHF_PADSLASH,   CTL_PADSLASH,   ALT_PADSLASH}, /*  2 111 */
292    {KEY_PPAGE,  KEY_SPREVIOUS,  CTL_PGUP,       ALT_PGUP    }, /*  3  33 */
293    {KEY_NPAGE,  KEY_SNEXT,      CTL_PGDN,       ALT_PGDN    }, /*  4  34 */
294    {KEY_END,    KEY_SEND,       CTL_END,        ALT_END     }, /*  5  35 */
295    {KEY_HOME,   KEY_SHOME,      CTL_HOME,       ALT_HOME    }, /*  6  36 */
296    {KEY_LEFT,   KEY_SLEFT,      CTL_LEFT,       ALT_LEFT    }, /*  7  37 */
297    {KEY_UP,     KEY_SUP,        CTL_UP,         ALT_UP      }, /*  8  38 */
298    {KEY_RIGHT,  KEY_SRIGHT,     CTL_RIGHT,      ALT_RIGHT   }, /*  9  39 */
299    {KEY_DOWN,   KEY_SDOWN,      CTL_DOWN,       ALT_DOWN    }, /* 10  40 */
300    {KEY_IC,     KEY_SIC,        CTL_INS,        ALT_INS     }, /* 11  45 */
301    {KEY_DC,     KEY_SDC,        CTL_DEL,        ALT_DEL     }, /* 12  46 */
302    {KEY_APPS,   KEY_SAPPS     , CTL_APPS,       ALT_APPS    }, /* 13  93  VK_APPS    */
303    {KEY_BROWSER_BACK, KEY_SBROWSER_BACK, KEY_CBROWSER_BACK, KEY_ABROWSER_BACK, }, /* 14 166 VK_BROWSER_BACK        */
304    {KEY_BROWSER_FWD,  KEY_SBROWSER_FWD,  KEY_CBROWSER_FWD,  KEY_ABROWSER_FWD,  }, /* 15 167 VK_BROWSER_FORWARD     */
305    {KEY_BROWSER_REF,  KEY_SBROWSER_REF,  KEY_CBROWSER_REF,  KEY_ABROWSER_REF,  }, /* 16 168 VK_BROWSER_REFRESH     */
306    {KEY_BROWSER_STOP, KEY_SBROWSER_STOP, KEY_CBROWSER_STOP, KEY_ABROWSER_STOP, }, /* 17 169 VK_BROWSER_STOP        */
307    {KEY_SEARCH,       KEY_SSEARCH,       KEY_CSEARCH,       KEY_ASEARCH,       }, /* 18 170 VK_BROWSER_SEARCH      */
308    {KEY_FAVORITES,    KEY_SFAVORITES,    KEY_CFAVORITES,    KEY_AFAVORITES,    }, /* 19 171 VK_BROWSER_FAVORITES   */
309    {KEY_BROWSER_HOME, KEY_SBROWSER_HOME, KEY_CBROWSER_HOME, KEY_ABROWSER_HOME, }, /* 20 172 VK_BROWSER_HOME        */
310    {KEY_VOLUME_MUTE,  KEY_SVOLUME_MUTE,  KEY_CVOLUME_MUTE,  KEY_AVOLUME_MUTE,  }, /* 21 173 VK_VOLUME_MUTE         */
311    {KEY_VOLUME_DOWN,  KEY_SVOLUME_DOWN,  KEY_CVOLUME_DOWN,  KEY_AVOLUME_DOWN,  }, /* 22 174 VK_VOLUME_DOWN         */
312    {KEY_VOLUME_UP,    KEY_SVOLUME_UP,    KEY_CVOLUME_UP,    KEY_AVOLUME_UP,    }, /* 23 175 VK_VOLUME_UP           */
313    {KEY_NEXT_TRACK,   KEY_SNEXT_TRACK,   KEY_CNEXT_TRACK,   KEY_ANEXT_TRACK,   }, /* 24 176 VK_MEDIA_NEXT_TRACK    */
314    {KEY_PREV_TRACK,   KEY_SPREV_TRACK,   KEY_CPREV_TRACK,   KEY_APREV_TRACK,   }, /* 25 177 VK_MEDIA_PREV_TRACK    */
315    {KEY_MEDIA_STOP,   KEY_SMEDIA_STOP,   KEY_CMEDIA_STOP,   KEY_AMEDIA_STOP,   }, /* 26 178 VK_MEDIA_STOP          */
316    {KEY_PLAY_PAUSE,   KEY_SPLAY_PAUSE,   KEY_CPLAY_PAUSE,   KEY_APLAY_PAUSE,   }, /* 27 179 VK_MEDIA_PLAY_PAUSE    */
317    {KEY_LAUNCH_MAIL,  KEY_SLAUNCH_MAIL,  KEY_CLAUNCH_MAIL,  KEY_ALAUNCH_MAIL,  }, /* 28 180 VK_LAUNCH_MAIL         */
318    {KEY_MEDIA_SELECT, KEY_SMEDIA_SELECT, KEY_CMEDIA_SELECT, KEY_AMEDIA_SELECT, }, /* 29 181 VK_LAUNCH_MEDIA_SELECT */
319    {KEY_LAUNCH_APP1,  KEY_SLAUNCH_APP1,  KEY_CLAUNCH_APP1,  KEY_ALAUNCH_APP1,  }, /* 30 182 VK_LAUNCH_APP1         */
320    {KEY_LAUNCH_APP2,  KEY_SLAUNCH_APP2,  KEY_CLAUNCH_APP2,  KEY_ALAUNCH_APP2,  }, /* 31 183 VK_LAUNCH_APP2         */
321 };
322 
323 /* End of kptab[] */
324 
PDC_get_input_fd(void)325 unsigned long PDC_get_input_fd(void)
326 {
327     PDC_LOG(("PDC_get_input_fd() - called\n"));
328 
329     return 0L;
330 }
331 
PDC_set_keyboard_binary(bool on)332 void PDC_set_keyboard_binary(bool on)
333 {
334     PDC_LOG(("PDC_set_keyboard_binary() - called\n"));
335 }
336 
337 /* check if a key or mouse event is waiting */
338 
PDC_check_key(void)339 bool PDC_check_key(void)
340 {
341     if (key_count > 0)
342         return TRUE;
343 
344     GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
345 
346     return (event_count != 0);
347 }
348 
349 /* _get_key_count returns 0 if save_ip doesn't contain an event which
350    should be passed back to the user. This function filters "useless"
351    events.
352 
353    The function returns the number of keys waiting. This may be > 1
354    if the repetition of real keys pressed so far are > 1.
355 
356    Returns 0 on NUMLOCK, CAPSLOCK, SCROLLLOCK.
357 
358    Returns 1 for SHIFT, ALT, CTRL only if no other key has been pressed
359    in between, and SP->return_key_modifiers is set; these are returned
360    on keyup.
361 
362    Normal keys are returned on keydown only. The number of repetitions
363    are returned. Dead keys (diacritics) are omitted. See below for a
364    description.
365 */
366 
_get_key_count(void)367 static int _get_key_count(void)
368 {
369     int num_keys = 0, vk;
370 
371     PDC_LOG(("_get_key_count() - called\n"));
372 
373     vk = KEV.wVirtualKeyCode;
374 
375     if (KEV.bKeyDown)
376     {
377         /* key down */
378 
379         save_press = 0;
380 
381         if (vk == VK_CAPITAL || vk == VK_NUMLOCK || vk == VK_SCROLL)
382         {
383             /* throw away these modifiers */
384         }
385         else if (vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU)
386         {
387             /* These keys are returned on keyup only. */
388 
389             save_press = vk;
390             switch (vk)
391             {
392             case VK_SHIFT:
393                 left_key = GetKeyState(VK_LSHIFT);
394                 break;
395             case VK_CONTROL:
396                 left_key = GetKeyState(VK_LCONTROL);
397                 break;
398             case VK_MENU:
399                 left_key = GetKeyState(VK_LMENU);
400             }
401         }
402         else
403         {
404             /* Check for diacritics. These are dead keys. Some locales
405                have modified characters like umlaut-a, which is an "a"
406                with two dots on it. In some locales you have to press a
407                special key (the dead key) immediately followed by the
408                "a" to get a composed umlaut-a. The special key may have
409                a normal meaning with different modifiers. */
410 
411             if (KEV.uChar.UnicodeChar || !(MapVirtualKey(vk, 2) & 0x80000000))
412                 num_keys = KEV.wRepeatCount;
413         }
414     }
415     else
416     {
417         /* key up */
418 
419         /* Only modifier keys or the results of ALT-numpad entry are
420            returned on keyup */
421 
422         if ((vk == VK_MENU && KEV.uChar.UnicodeChar) ||
423            ((vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU) &&
424              vk == save_press))
425         {
426             save_press = 0;
427             num_keys = 1;
428         }
429     }
430 
431     PDC_LOG(("_get_key_count() - returning: num_keys %d\n", num_keys));
432 
433     return num_keys;
434 }
435 
436 /* _process_key_event returns -1 if the key in save_ip should be
437    ignored. Otherwise it returns the keycode which should be returned
438    by PDC_get_key(). save_ip must be a key event.
439 
440    CTRL-ALT support has been disabled, when is it emitted plainly?  */
441 
_process_key_event(void)442 static int _process_key_event(void)
443 {
444     int key = (unsigned short)KEV.uChar.UnicodeChar;
445     WORD vk = KEV.wVirtualKeyCode;
446     DWORD state = KEV.dwControlKeyState;
447 
448     int idx;
449     BOOL enhanced;
450 
451     SP->key_code = TRUE;
452 
453     /* Save the key modifiers if required. Do this first to allow to
454        detect e.g. a pressed CTRL key after a hit of NUMLOCK. */
455 
456     if (SP->save_key_modifiers)
457     {
458         if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
459             pdc_key_modifiers |= PDC_KEY_MODIFIER_ALT;
460 
461         if (state & SHIFT_PRESSED)
462             pdc_key_modifiers |= PDC_KEY_MODIFIER_SHIFT;
463 
464         if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
465             pdc_key_modifiers |= PDC_KEY_MODIFIER_CONTROL;
466 
467         if (state & NUMLOCK_ON)
468             pdc_key_modifiers |= PDC_KEY_MODIFIER_NUMLOCK;
469     }
470 
471     /* Handle modifier keys hit by themselves */
472 
473     switch (vk)
474     {
475     case VK_SHIFT: /* shift */
476         if (!SP->return_key_modifiers)
477             return -1;
478 
479         return (left_key & 0x8000) ? KEY_SHIFT_L : KEY_SHIFT_R;
480 
481     case VK_CONTROL: /* control */
482         if (!SP->return_key_modifiers)
483             return -1;
484 
485         return (left_key & 0x8000) ? KEY_CONTROL_L : KEY_CONTROL_R;
486 
487     case VK_MENU: /* alt */
488         if (!key)
489         {
490             if (!SP->return_key_modifiers)
491                 return -1;
492 
493             return (left_key & 0x8000) ? KEY_ALT_L : KEY_ALT_R;
494         }
495     }
496 
497     /* The system may emit Ascii or Unicode characters depending on
498        whether ReadConsoleInputA or ReadConsoleInputW is used.
499 
500        Normally, if key != 0 then the system did the translation
501        successfully. But this is not true for LEFT_ALT (different to
502        RIGHT_ALT). In case of LEFT_ALT we can get key != 0. So
503        check for this first. */
504 
505     if (key && ( !(state & LEFT_ALT_PRESSED) ||
506         (state & RIGHT_ALT_PRESSED) ))
507     {
508         /* This code should catch all keys returning a printable
509            character. Characters above 0x7F should be returned as
510            positive codes. */
511 
512         if (kptab[vk].extended == 0)
513         {
514             SP->key_code = FALSE;
515             return key;
516         }
517     }
518 
519     /* This case happens if a functional key has been entered. */
520 
521     if ((state & ENHANCED_KEY) && (kptab[vk].extended != 999))
522     {
523         enhanced = TRUE;
524         idx = kptab[vk].extended;
525     }
526     else
527     {
528         enhanced = FALSE;
529         idx = vk;
530     }
531 
532     if (state & SHIFT_PRESSED)
533         key = enhanced ? ext_kptab[idx].shift : kptab[idx].shift;
534 
535     else if (state & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
536         key = enhanced ? ext_kptab[idx].control : kptab[idx].control;
537 
538     else if (state & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
539         key = enhanced ? ext_kptab[idx].alt : kptab[idx].alt;
540 
541     else
542         key = enhanced ? ext_kptab[idx].normal : kptab[idx].normal;
543 
544     if (key < KEY_CODE_YES)
545         SP->key_code = FALSE;
546 
547     return key;
548 }
549 
_process_mouse_event(void)550 static int _process_mouse_event(void)
551 {
552     static const DWORD button_mask[] = {1, 4, 2};
553     short action, shift_flags = 0;
554     int i;
555 
556     save_press = 0;
557     SP->key_code = TRUE;
558 
559     memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS));
560 
561     /* Handle scroll wheel */
562 
563     if (MEV.dwEventFlags == 4)
564     {
565         pdc_mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
566             PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;
567 
568         pdc_mouse_status.x = -1;
569         pdc_mouse_status.y = -1;
570 
571         memset(&old_mouse_status, 0, sizeof(old_mouse_status));
572 
573         return KEY_MOUSE;
574     }
575 
576     if (MEV.dwEventFlags == 8)
577     {
578         pdc_mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
579             PDC_MOUSE_WHEEL_RIGHT : PDC_MOUSE_WHEEL_LEFT;
580 
581         pdc_mouse_status.x = -1;
582         pdc_mouse_status.y = -1;
583 
584         memset(&old_mouse_status, 0, sizeof(old_mouse_status));
585 
586         return KEY_MOUSE;
587     }
588 
589     action = (MEV.dwEventFlags == 2) ? BUTTON_DOUBLE_CLICKED :
590             ((MEV.dwEventFlags == 1) ? BUTTON_MOVED : BUTTON_PRESSED);
591 
592     for (i = 0; i < 3; i++)
593         pdc_mouse_status.button[i] =
594             (MEV.dwButtonState & button_mask[i]) ? action : 0;
595 
596     if (action == BUTTON_PRESSED && MEV.dwButtonState & 7 && SP->mouse_wait)
597     {
598         /* Check for a click -- a PRESS followed immediately by a release */
599 
600         if (!event_count)
601         {
602             napms(SP->mouse_wait);
603 
604             GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
605         }
606 
607         if (event_count)
608         {
609             INPUT_RECORD ip;
610             DWORD count;
611             bool have_click = FALSE;
612 
613             PeekConsoleInput(pdc_con_in, &ip, 1, &count);
614 
615             for (i = 0; i < 3; i++)
616             {
617                 if (pdc_mouse_status.button[i] == BUTTON_PRESSED &&
618                     !(ip.Event.MouseEvent.dwButtonState & button_mask[i]))
619                 {
620                     pdc_mouse_status.button[i] = BUTTON_CLICKED;
621                     have_click = TRUE;
622                 }
623             }
624 
625             /* If a click was found, throw out the event */
626 
627             if (have_click)
628                 ReadConsoleInput(pdc_con_in, &ip, 1, &count);
629         }
630     }
631 
632     pdc_mouse_status.x = MEV.dwMousePosition.X;
633     pdc_mouse_status.y = MEV.dwMousePosition.Y;
634 
635     pdc_mouse_status.changes = 0;
636 
637     for (i = 0; i < 3; i++)
638     {
639         if (old_mouse_status.button[i] != pdc_mouse_status.button[i])
640             pdc_mouse_status.changes |= (1 << i);
641 
642         if (pdc_mouse_status.button[i] == BUTTON_MOVED)
643         {
644             /* Discard non-moved "moves" */
645 
646             if (pdc_mouse_status.x == old_mouse_status.x &&
647                 pdc_mouse_status.y == old_mouse_status.y)
648                 return -1;
649 
650             /* Motion events always flag the button as changed */
651 
652             pdc_mouse_status.changes |= (1 << i);
653             pdc_mouse_status.changes |= PDC_MOUSE_MOVED;
654             break;
655         }
656     }
657 
658     old_mouse_status = pdc_mouse_status;
659 
660     /* Treat click events as release events for comparison purposes */
661 
662     for (i = 0; i < 3; i++)
663     {
664         if (old_mouse_status.button[i] == BUTTON_CLICKED ||
665             old_mouse_status.button[i] == BUTTON_DOUBLE_CLICKED)
666             old_mouse_status.button[i] = BUTTON_RELEASED;
667     }
668 
669     /* Check for SHIFT/CONTROL/ALT */
670 
671     if (MEV.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
672         shift_flags |= BUTTON_ALT;
673 
674     if (MEV.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
675         shift_flags |= BUTTON_CONTROL;
676 
677     if (MEV.dwControlKeyState & SHIFT_PRESSED)
678         shift_flags |= BUTTON_SHIFT;
679 
680     if (shift_flags)
681     {
682         for (i = 0; i < 3; i++)
683         {
684             if (pdc_mouse_status.changes & (1 << i))
685                 pdc_mouse_status.button[i] |= shift_flags;
686         }
687     }
688 
689     return KEY_MOUSE;
690 }
691 
692 /* return the next available key or mouse event */
693 
PDC_get_key(void)694 int PDC_get_key(void)
695 {
696     pdc_key_modifiers = 0L;
697 
698     if (!key_count)
699     {
700         DWORD count;
701 
702         ReadConsoleInput(pdc_con_in, &save_ip, 1, &count);
703         event_count--;
704 
705         if (save_ip.EventType == MOUSE_EVENT)
706             key_count = 1;
707         else if (save_ip.EventType == KEY_EVENT)
708             key_count = _get_key_count();
709     }
710 
711     if (key_count)
712     {
713         key_count--;
714 
715         switch (save_ip.EventType)
716         {
717         case KEY_EVENT:
718             return _process_key_event();
719 
720         case MOUSE_EVENT:
721             return _process_mouse_event();
722         }
723     }
724 
725     return -1;
726 }
727 
728 /* discard any pending keyboard or mouse input -- this is the core
729    routine for flushinp() */
730 
PDC_flushinp(void)731 void PDC_flushinp(void)
732 {
733     PDC_LOG(("PDC_flushinp() - called\n"));
734 
735     FlushConsoleInputBuffer(pdc_con_in);
736 }
737 
PDC_mouse_set(void)738 int PDC_mouse_set(void)
739 {
740     /* If turning on mouse input: Set ENABLE_MOUSE_INPUT, and clear
741        all other flags, including the extended flags;
742        If turning off the mouse: Set QuickEdit Mode to the status it
743        had on startup, and clear all other flags */
744 
745     SetConsoleMode(pdc_con_in, SP->_trap_mbe ?
746                    (ENABLE_MOUSE_INPUT|0x0080) : (pdc_quick_edit|0x0080));
747 
748     memset(&old_mouse_status, 0, sizeof(old_mouse_status));
749 
750     return OK;
751 }
752 
PDC_modifiers_set(void)753 int PDC_modifiers_set(void)
754 {
755     return OK;
756 }
757 
758