(imenu--cleanup): Set alist to its default just once, at the beginning.
[emacs.git] / src / w32inevt.c
blob47c2ca55b647a9cdf1d137190be5978a86f823fa
1 /* Input event support for Windows NT port of GNU Emacs.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
9 version.
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
25 #include "config.h"
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <windows.h>
31 #include "lisp.h"
32 #include "frame.h"
33 #include "blockinput.h"
34 #include "termhooks.h"
36 /* stdin, from ntterm */
37 extern HANDLE keyboard_handle;
39 /* Indicate mouse motion, from keyboard.c */
40 extern int mouse_moved;
42 /* Info for last mouse motion */
43 static COORD movement_pos;
44 static DWORD movement_time;
46 /* from keyboard.c */
47 extern void reinvoke_input_signal (void);
49 /* from dispnew.c */
50 extern int change_frame_size (FRAME_PTR, int, int, int, int);
52 /* Event queue */
53 #define EVENT_QUEUE_SIZE 50
54 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
55 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
57 static int
58 fill_queue (BOOL block)
60 BOOL rc;
61 DWORD events_waiting;
63 if (queue_ptr < queue_end)
64 return queue_end-queue_ptr;
66 if (!block)
68 /* Check to see if there are some events to read before we try
69 because we can't block. */
70 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
71 return -1;
72 if (events_waiting == 0)
73 return 0;
76 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
77 &events_waiting);
78 if (!rc)
79 return -1;
80 queue_ptr = event_queue;
81 queue_end = event_queue + events_waiting;
82 return (int) events_waiting;
85 /* In a generic, multi-frame world this should take a console handle
86 and return the frame for it
88 Right now, there's only one frame so return it. */
89 static FRAME_PTR
90 get_frame (void)
92 return selected_frame;
95 #ifdef MULTI_FRAME
96 #define SET_FRAME(o, f) XSETFRAME (o, f)
97 #else
98 #define SET_FRAME(o, f) ((o) = Qnil)
99 #endif
101 /* Translate console modifiers to emacs modifiers. */
102 static int
103 nt_kbd_mods_to_emacs (DWORD mods)
105 return ((mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) ?
106 meta_modifier : 0) |
107 ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) ?
108 ctrl_modifier : 0) |
109 ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) ?
110 shift_modifier : 0);
113 /* Map virtual key codes into:
114 -1 - Ignore this key
115 -2 - ASCII char
116 Other - Map non-ASCII keys into X keysyms so that they are looked up
117 correctly in keyboard.c
119 Return, escape and tab are mapped to ASCII rather than coming back
120 as non-ASCII to be more compatible with old-style keyboard support. */
122 static int map_virt_key[256] =
125 -1, /* VK_LBUTTON */
126 -1, /* VK_RBUTTON */
127 0x69, /* VK_CANCEL */
128 -1, /* VK_MBUTTON */
129 -1, -1, -1,
130 8, /* VK_BACK */
131 -2, /* VK_TAB */
132 -1, -1,
133 11, /* VK_CLEAR */
134 -2, /* VK_RETURN */
135 -1, -1,
136 -1, /* VK_SHIFT */
137 -1, /* VK_CONTROL */
138 -1, /* VK_MENU */
139 0x13, /* VK_PAUSE */
140 -1, /* VK_CAPITAL */
141 -1, -1, -1, -1, -1, -1,
142 -2, /* VK_ESCAPE */
143 -1, -1, -1, -1,
144 -2, /* VK_SPACE */
145 0x55, /* VK_PRIOR */
146 0x56, /* VK_NEXT */
147 0x57, /* VK_END */
148 0x50, /* VK_HOME */
149 0x51, /* VK_LEFT */
150 0x52, /* VK_UP */
151 0x53, /* VK_RIGHT */
152 0x54, /* VK_DOWN */
153 0x60, /* VK_SELECT */
154 0x61, /* VK_PRINT */
155 0x62, /* VK_EXECUTE */
156 -1, /* VK_SNAPSHOT */
157 0x63, /* VK_INSERT */
158 0xff, /* VK_DELETE */
159 0x6a, /* VK_HELP */
160 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
161 -1, -1, -1, -1, -1, -1, -1,
162 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
163 -2, -2, -2, -2, -2, -2, -2, -2,
164 -2, -2, -2, -2, -2, -2, -2, -2,
165 -2, -2,
166 -1, -1, -1, -1, -1,
167 0xb0, /* VK_NUMPAD0 */
168 0xb1, /* VK_NUMPAD1 */
169 0xb2, /* VK_NUMPAD2 */
170 0xb3, /* VK_NUMPAD3 */
171 0xb4, /* VK_NUMPAD4 */
172 0xb5, /* VK_NUMPAD5 */
173 0xb6, /* VK_NUMPAD6 */
174 0xb7, /* VK_NUMPAD7 */
175 0xb8, /* VK_NUMPAD8 */
176 0xb9, /* VK_NUMPAD9 */
177 0xaa, /* VK_MULTIPLY */
178 0xab, /* VK_ADD */
179 0xac, /* VK_SEPARATOR */
180 0xad, /* VK_SUBTRACT */
181 0xae, /* VK_DECIMAL */
182 0xaf, /* VK_DIVIDE */
183 0xbe, /* VK_F1 */
184 0xbf, /* VK_F2 */
185 0xc0, /* VK_F3 */
186 0xc1, /* VK_F4 */
187 0xc2, /* VK_F5 */
188 0xc3, /* VK_F6 */
189 0xc4, /* VK_F7 */
190 0xc5, /* VK_F8 */
191 0xc6, /* VK_F9 */
192 0xc7, /* VK_F10 */
193 0xc8, /* VK_F11 */
194 0xc9, /* VK_F12 */
195 0xca, /* VK_F13 */
196 0xcb, /* VK_F14 */
197 0xcc, /* VK_F15 */
198 0xcd, /* VK_F16 */
199 0xce, /* VK_F17 */
200 0xcf, /* VK_F18 */
201 0xd0, /* VK_F19 */
202 0xd1, /* VK_F20 */
203 0xd2, /* VK_F21 */
204 0xd3, /* VK_F22 */
205 0xd4, /* VK_F23 */
206 0xd5, /* VK_F24 */
207 -1, -1, -1, -1, -1, -1, -1, -1,
208 0x7f, /* VK_NUMLOCK */
209 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
210 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
211 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
212 -2, /* ; */
213 -2, /* = */
214 -2, /* , */
215 -2, /* \ */
216 -2, /* . */
217 -2, /* / */
218 -2, /* ` */
219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
220 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
221 -2, /* [ */
222 -2, /* - */
223 -2, /* ] */
224 -2, /* ' */
225 -1, /* 0xdf */
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xef */
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
230 static int
231 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev)
233 int map;
235 /* Skip key-up events. */
236 if (event->bKeyDown == FALSE)
237 return 0;
239 if (event->wVirtualKeyCode > 0xff)
241 printf ("Unknown key code %d\n", event->wVirtualKeyCode);
242 return 0;
245 /* BUGBUG - Ignores the repeat count
246 It's questionable whether we want to obey the repeat count anyway
247 since keys usually aren't repeated unless key events back up in
248 the queue. If they're backing up then we don't generally want
249 to honor them later since that leads to significant slop in
250 cursor motion when the system is under heavy load. */
252 map = map_virt_key[event->wVirtualKeyCode];
253 if (map == -1)
255 return 0;
257 else if (map == -2)
259 /* ASCII */
260 emacs_ev->kind = ascii_keystroke;
261 XSETINT (emacs_ev->code, event->uChar.AsciiChar);
263 else
265 /* non-ASCII */
266 emacs_ev->kind = non_ascii_keystroke;
268 * make_lispy_event () now requires non-ascii codes to have
269 * the full X keysym values (2nd byte is 0xff). add it on.
271 map |= 0xff00;
272 XSETINT (emacs_ev->code, map);
274 SET_FRAME (emacs_ev->frame_or_window, get_frame ());
275 emacs_ev->modifiers = nt_kbd_mods_to_emacs (event->dwControlKeyState);
276 emacs_ev->timestamp = GetTickCount ();
277 return 1;
280 /* Mouse position hook. */
281 void
282 win32_mouse_position (FRAME_PTR *f,
283 Lisp_Object *bar_window,
284 enum scroll_bar_part *part,
285 Lisp_Object *x,
286 Lisp_Object *y,
287 unsigned long *time)
289 BLOCK_INPUT;
291 *f = get_frame ();
292 *bar_window = Qnil;
293 *part = 0;
294 mouse_moved = 0;
296 *x = movement_pos.X;
297 *y = movement_pos.Y;
298 *time = movement_time;
300 UNBLOCK_INPUT;
303 /* Remember mouse motion and notify emacs. */
304 static void
305 mouse_moved_to (int x, int y)
307 /* If we're in the same place, ignore it */
308 if (x != movement_pos.X || y != movement_pos.Y)
310 mouse_moved = 1;
311 movement_pos.X = x;
312 movement_pos.Y = y;
313 movement_time = GetTickCount ();
317 /* Consoles return button bits in a strange order:
318 least significant - Leftmost button
319 next - Rightmost button
320 next - Leftmost+1
321 next - Leftmost+2...
323 Assume emacs likes three button mice, so
324 Left == 0
325 Middle == 1
326 Right == 2
327 Others increase from there. */
329 static int emacs_button_translation[NUM_MOUSE_BUTTONS] =
331 0, 2, 1, 3, 4,
334 static int
335 do_mouse_event (MOUSE_EVENT_RECORD *event,
336 struct input_event *emacs_ev)
338 static DWORD button_state = 0;
339 DWORD but_change, mask;
340 int i;
342 if (event->dwEventFlags == MOUSE_MOVED)
344 /* For movement events we just note that the mouse has moved
345 so that emacs will generate drag events. */
346 mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y);
347 return 0;
350 /* It looks like the console code sends us a mouse event with
351 dwButtonState == 0 when a window is activated. Ignore this case. */
352 if (event->dwButtonState == button_state)
353 return 0;
355 emacs_ev->kind = mouse_click;
357 /* Find out what button has changed state since the last button event. */
358 but_change = button_state ^ event->dwButtonState;
359 mask = 1;
360 for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1)
361 if (but_change & mask)
363 XSETINT (emacs_ev->code, emacs_button_translation[i]);
364 break;
367 /* If the changed button is out of emacs' range (highly unlikely)
368 ignore this event. */
369 if (i == NUM_MOUSE_BUTTONS)
370 return 0;
372 button_state = event->dwButtonState;
373 emacs_ev->timestamp = GetTickCount ();
374 emacs_ev->modifiers = nt_kbd_mods_to_emacs (event->dwControlKeyState) |
375 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
377 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
378 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
379 SET_FRAME (emacs_ev->frame_or_window, get_frame ());
381 return 1;
384 static void
385 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
387 FRAME_PTR f = get_frame ();
389 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
390 SET_FRAME_GARBAGED (f);
393 int
394 win32_read_socket (int sd, struct input_event *bufp, int numchars,
395 int waitp, int expected)
397 BOOL no_events = TRUE;
398 int nev, ret = 0, add;
400 if (interrupt_input_blocked)
402 interrupt_input_pending = 1;
403 return -1;
406 interrupt_input_pending = 0;
407 BLOCK_INPUT;
409 for (;;)
411 nev = fill_queue (waitp != 0);
412 if (nev <= 0)
414 /* If nev == -1, there was some kind of error
415 If nev == 0 then waitp must be zero and no events were available
416 so return. */
417 UNBLOCK_INPUT;
418 return nev;
421 while (nev > 0 && numchars > 0)
423 switch (queue_ptr->EventType)
425 case KEY_EVENT:
426 add = key_event (&queue_ptr->Event.KeyEvent, bufp);
427 bufp += add;
428 ret += add;
429 numchars -= add;
430 break;
432 case MOUSE_EVENT:
433 add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
434 bufp += add;
435 ret += add;
436 numchars -= add;
437 break;
439 case WINDOW_BUFFER_SIZE_EVENT:
440 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
441 break;
443 case MENU_EVENT:
444 case FOCUS_EVENT:
445 /* Internal event types, ignored. */
446 break;
449 queue_ptr++;
450 nev--;
453 if (ret > 0 || expected == 0)
454 break;
457 UNBLOCK_INPUT;
458 return ret;