#ifdef HAVE_MSG_SELECT
extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
extern SELECT_TYPE process_only_mask, tty_only_mask;
+SELECT_TYPE zero_mask;
extern int signal_event_pipe_initialized;
int windows_fd;
#endif
{
ResetEvent (str->ov.hEvent);
-
- if (WriteFile ((HANDLE)str->s, data, size, NULL, &str->ov)
+
+ /* Docs indicate that 4th parameter to WriteFile can be NULL since this is
+ * an overlapped operation. This fails on Win95 with winsock 1.x so we
+ * supply a spare address which is ignored by Win95 anyway. Sheesh. */
+ if (WriteFile ((HANDLE)str->s, data, size, (LPDWORD)&str->buffer, &str->ov)
|| GetLastError() == ERROR_IO_PENDING)
str->pending_p = 1;
else
EMACS_TIME_TO_SELECT_TIME (sometime, select_time_to_block);
pointer_to_this = &select_time_to_block;
}
+
+ /* select() is slow and buggy so if we don't have any processes
+ just wait as normal */
+ if (memcmp (&process_only_mask, &zero_mask, sizeof(SELECT_TYPE))==0)
+ {
+ /* Now try getting a message or process event */
+ active = MsgWaitForMultipleObjects (0, mswindows_waitable_handles,
+ FALSE, badly_p ? INFINITE : 0,
+ QS_ALLINPUT);
+
+ if (active == WAIT_TIMEOUT)
+ {
+ /* No luck trying - just return what we've already got */
+ return;
+ }
+ else if (active == WAIT_OBJECT_0)
+ {
+ /* Got your message, thanks */
+ mswindows_drain_windows_queue ();
+ continue;
+ }
+ }
+
active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
if (active == 0)
mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt));
break;
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ /* See Win95 comment under WM_KEYDOWN */
+ {
+ BYTE keymap[256];
+
+ if (wParam == VK_CONTROL)
+ {
+ GetKeyboardState (keymap);
+ keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80;
+ SetKeyboardState (keymap);
+ }
+ else if (wParam == VK_MENU)
+ {
+ GetKeyboardState (keymap);
+ keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80;
+ SetKeyboardState (keymap);
+ }
+ };
+ goto defproc;
+
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
+ /* In some locales the right-hand Alt key is labelled AltGr. This key
+ * should produce alternative charcaters when combined with another key.
+ * eg on a German keyboard pressing AltGr+q should produce '@'.
+ * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if
+ * TranslateMessage() is called with *any* combination of Ctrl+Alt down,
+ * it translates as if AltGr were down.
+ * We get round this by removing all modifiers from the keymap before
+ * calling TranslateMessage() unless AltGr is *really* down. */
{
BYTE keymap[256];
int has_AltGr = mswindows_current_layout_has_AltGr ();
GetKeyboardState (keymap);
mods = mswindows_modifier_state (keymap, has_AltGr);
- /* Handle those keys that TranslateMessage won't generate a WM_CHAR for */
+ /* Handle those keys for which TranslateMessage won't generate a WM_CHAR */
if (!NILP (keysym = mswindows_key_to_emacs_keysym(wParam, mods)))
mswindows_enqueue_keypress_event (hwnd, keysym, mods);
else
int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
BYTE keymap_orig[256];
MSG msg = { hwnd, message, wParam, lParam, GetMessageTime(), (GetMessagePos()) };
+
+ /* GetKeyboardState() does not work as documented on Win95. We have
+ * to loosely track Left and Right modifiers on behalf of the OS,
+ * without screwing up Windows NT which tracks them properly. */
+ if (wParam == VK_CONTROL)
+ keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
+ else if (wParam == VK_MENU)
+ keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] |= 0x80;
+
memcpy (keymap_orig, keymap, 256);
/* Remove shift modifier from an ascii character */
mods &= ~MOD_SHIFT;
- /* Clear control and alt modifiers out of the keymap */
+ /* Clear control and alt modifiers unless AltGr is pressed */
keymap [VK_RCONTROL] = 0;
keymap [VK_LMENU] = 0;
if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) || !(keymap [VK_RMENU] & 0x80))
}
SetKeyboardState (keymap);
- /* Have some WM_[SYS]CHARS in the queue */
+ /* Maybe generate some WM_[SYS]CHARs in the queue */
TranslateMessage (&msg);
while (PeekMessage (&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)
windows_fd = open("/dev/windows", O_RDONLY | O_NONBLOCK, 0);
assert (windows_fd>=0);
FD_SET (windows_fd, &input_wait_mask);
- /* for some reason I get blocks on the signal event pipe, which is
- bad...
- signal_event_pipe_initialized = 0; */
+ FD_ZERO(&zero_mask);
#endif
event_stream = mswindows_event_stream;