From dbfb67c5de9cdb117da6a688bbaeeea87c7578c9 Mon Sep 17 00:00:00 2001 From: Stephen Adams Date: Tue, 20 Jan 1998 18:40:57 +0000 Subject: [PATCH] Changes for International keyboards on win32 systems. ntscreen changed to work better with international keyboards. The changes peek into the event queue to see how the key presses have been translated into characters. Modifiers are also tracked to enable them to be detected in parallel with keyboard translations (so that modifier chords like C-M- are detected). Characters now have 16 bits of character code (instead of 7) to allow 8-bit ISO latin and Unicode characters. Strings are still based on 8-bit characters. Runtime changed to allow these `wide' characters to be written and read e.g. #\ Edwin modes changed to treat characters in the range 128-255 as normal alphabetic characters (to enable accented characters). --- v7/src/edwin/calias.scm | 67 +++--- v7/src/edwin/modefs.scm | 14 +- v7/src/microcode/ntscreen.c | 397 +++++++++++++++++++++++------------- v7/src/microcode/ntscreen.h | 36 ++-- v7/src/microcode/object.h | 8 +- v7/src/runtime/char.scm | 22 +- v8/src/microcode/object.h | 6 +- 7 files changed, 332 insertions(+), 218 deletions(-) diff --git a/v7/src/edwin/calias.scm b/v7/src/edwin/calias.scm index 7be173080..be7155684 100644 --- a/v7/src/edwin/calias.scm +++ b/v7/src/edwin/calias.scm @@ -1,8 +1,8 @@ ;;; -*-Scheme-*- ;;; -;;; $Id: calias.scm,v 1.16 1995/04/13 23:26:00 cph Exp $ +;;; $Id: calias.scm,v 1.17 1998/01/20 18:40:34 adams Exp $ ;;; -;;; Copyright (c) 1986, 1989-95 Massachusetts Institute of Technology +;;; Copyright (c) 1986, 1989-1998 Massachusetts Institute of Technology ;;; ;;; This material was developed by the Scheme project at the ;;; Massachusetts Institute of Technology, Department of @@ -136,38 +136,37 @@ (cond ((char? key) (let ((code (char-code key)) (bits (char-bits key))) - (let ((prefix - (lambda (bits suffix) - (if (zero? bits) - suffix - (string-append "M-" suffix))))) - (let ((process-code - (lambda (bits) - (cond ((< #x20 code #x7F) - (prefix bits (string (ascii->char code)))) - ((= code #x09) (prefix bits "TAB")) - ((= code #x0A) (prefix bits "LFD")) - ((= code #x0D) (prefix bits "RET")) - ((= code #x1B) (prefix bits "ESC")) - ((= code #x20) (prefix bits "SPC")) - ((= code #x7F) (prefix bits "DEL")) - (else - (string-append - (if (zero? bits) "C-" "C-M-") - (string - (ascii->char - (+ code - (if (<= #x01 code #x1A) - #x60 - #x40)))))))))) - (cond ((< bits 2) - (process-code bits)) - ((and handle-prefixes? (< bits 4)) - (string-append (if (= 2 bits) "C-^ " "C-z ") - (process-code 0))) - (else - (char->name (unmap-alias-key key)))))))) - ((special-key? key) + (define (prefix bits suffix) + (if (zero? bits) + suffix + (string-append "M-" suffix))) + (define (process-code bits) + (cond ((or (< #x20 code #x7F) ; 7-bit ASCII visible characters + (> code #x7F)) ; 8-bit ISO characters + (prefix bits (string (ascii->char code)))) + ((= code #x09) (prefix bits "TAB")) + ((= code #x0A) (prefix bits "LFD")) + ((= code #x0D) (prefix bits "RET")) + ((= code #x1B) (prefix bits "ESC")) + ((= code #x20) (prefix bits "SPC")) + ((= code #x7F) (prefix bits "DEL")) + (else + (string-append + (if (zero? bits) "C-" "C-M-") + (string + (ascii->char + (+ code + (if (<= #x01 code #x1A) + #x60 ; C-a .. C-z + #x40)))))))) ; C-@, C-] etc + (cond ((< bits 2) ; no bits or Meta only + (process-code bits)) + ((and handle-prefixes? (< bits 4)) + (string-append (if (= 2 bits) "C-^ " "C-z ") + (process-code 0))) + (else + (char->name (unmap-alias-key key)))))) + ((special-key? key) (special-key/name key)) (else (error "emacs-key-name: Unknown key type" key)))) diff --git a/v7/src/edwin/modefs.scm b/v7/src/edwin/modefs.scm index 909746eec..9f7d7b77b 100644 --- a/v7/src/edwin/modefs.scm +++ b/v7/src/edwin/modefs.scm @@ -1,8 +1,8 @@ ;;; -*-Scheme-*- ;;; -;;; $Id: modefs.scm,v 1.150 1996/04/23 23:09:44 cph Exp $ +;;; $Id: modefs.scm,v 1.151 1998/01/20 18:40:46 adams Exp $ ;;; -;;; Copyright (c) 1985, 1989-96 Massachusetts Institute of Technology +;;; Copyright (c) 1985, 1989-1998 Massachusetts Institute of Technology ;;; ;;; This material was developed by the Scheme project at the ;;; Massachusetts Institute of Technology, Department of @@ -64,7 +64,11 @@ Most other major modes are defined by comparison to this one.") (define initial-buffer-name "*scheme*") -(define-key 'fundamental char-set:graphic 'self-insert-command) +;; The extra range allows international keyboards to insert 8-bit characters +(define char-set:self-insert-keys + (char-set-union char-set:graphic (ascii-range->char-set 128 255))) + +(define-key 'fundamental char-set:self-insert-keys 'self-insert-command) (define-key 'fundamental char-set:numeric 'auto-digit-argument) (define-key 'fundamental #\- 'auto-negative-argument) (define-key 'fundamental #\rubout 'delete-backward-char) @@ -74,7 +78,7 @@ Most other major modes are defined by comparison to this one.") Like Fundamental mode, but no self-inserting characters. Digits and - are bound to prefix argument commands.") -(define-key 'read-only char-set:graphic 'undefined) +(define-key 'read-only char-set:self-insert-keys 'undefined) (define-key 'read-only char-set:numeric 'digit-argument) (define-key 'read-only #\- 'negative-argument) (define-key 'read-only '(#\c-x #\c-q) 'no-toggle-read-only) @@ -83,7 +87,7 @@ Digits and - are bound to prefix argument commands.") "Major mode for read-only buffers. Like Fundamental mode, but no self-inserting characters.") -(define-key 'read-only-noarg char-set:graphic 'undefined) +(define-key 'read-only-noarg char-set:self-insert-keys 'undefined) (define-key 'read-only-noarg '(#\c-x #\c-q) 'no-toggle-read-only) (define-key 'fundamental #\c-space 'set-mark-command) diff --git a/v7/src/microcode/ntscreen.c b/v7/src/microcode/ntscreen.c index 0a60c54ac..3bbb49442 100644 --- a/v7/src/microcode/ntscreen.c +++ b/v7/src/microcode/ntscreen.c @@ -1,8 +1,8 @@ /* -*-C-*- -$Id: ntscreen.c,v 1.31 1997/11/29 04:37:25 cph Exp $ +$Id: ntscreen.c,v 1.32 1998/01/20 18:40:13 adams Exp $ -Copyright (c) 1993-97 Massachusetts Institute of Technology +Copyright (c) 1993-1998 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and @@ -161,8 +161,11 @@ static BOOL ScrollScreenHorz (HWND, WORD, WORD); static BOOL ScrollScreenVert (HWND, WORD, WORD); static BOOL SizeScreen (HWND, WORD, WORD); static BOOL handle_window_pos_changing (HWND, LPWINDOWPOS); -static VOID ProcessScreenCharacter (HWND, int, DWORD); +//static VOID ProcessScreenCharacter (HWND, int, DWORD); +static VOID reset_modifiers (); +static void record_modifier_transition (WPARAM, LPARAM, BOOL); static BOOL Process_KeyDown (HWND, UINT, WPARAM, LPARAM); +static BOOL Process_KeyUp (HWND, UINT, WPARAM, LPARAM); static VOID ProcessMouseButton (HWND, UINT, UINT, LONG, BOOL); static VOID ProcessCloseMessage (SCREEN); static BOOL WriteScreenBlock (HWND, LPSTR, int); @@ -190,7 +193,7 @@ extern LRESULT ScreenCommand_ChooseFont (HWND, WORD); extern LRESULT ScreenCommand_ChooseBackColor (HWND, WORD); static SCREEN_EVENT * alloc_event (SCREEN, SCREEN_EVENT_TYPE); -static int GetControlKeyState (void); +static int GetModifiers(void); //void *xmalloc (int size); //void xfree (void*); @@ -679,6 +682,7 @@ ScreenWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SYSKEYDOWN: case WM_KEYDOWN: + record_modifier_transition (wParam, lParam, TRUE); if (IsIconic (hWnd)) goto use_default; if (Process_KeyDown (hWnd, uMsg, wParam, lParam)) goto use_default; @@ -695,7 +699,12 @@ ScreenWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SYSKEYUP: case WM_KEYUP: + record_modifier_transition (wParam, lParam, FALSE); if (IsIconic (hWnd)) goto use_default; + if (Process_KeyUp (hWnd, uMsg, wParam, lParam)) + goto use_default; + else + return 0L; #if 1 return (1L); #ifdef WINDOWSLOSES @@ -720,13 +729,14 @@ ScreenWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SYSCHAR: case WM_CHAR: if (IsIconic (hWnd)) goto use_default; - ProcessScreenCharacter (hWnd, - LOBYTE (LOWORD(wParam)), - (DWORD) lParam); +// ProcessScreenCharacter (hWnd, +// LOBYTE (LOWORD(wParam)), +// (DWORD) lParam); break ; case WM_SETFOCUS: SetScreenFocus (hWnd); + reset_modifiers (); goto use_default; case WM_KILLFOCUS: @@ -1852,63 +1862,112 @@ flush_typeahead (SCREEN screen) } //--------------------------------------------------------------------------- -// + +/* Reportedly, GetKeyState ans MapVirtualKey on Windows 95 do not +actually distinguish between left and right keys as advertized. We +track the left and right control and alt keys ourselves. This is +necessary for detecting `double meta' key presses on keyboards where +AltGr is used to get an ordinary character. For example, on the +Swiss-French keyboard, @ is obtained from AltGr-2. To complicate +things, the AltGr key is represented as having both left control and +right alt keys pressed. To generate M-@ on this keyboard we check for +both alt keys being pressed. */ + //--------------------------------------------------------------------------- -#define KEYDATA_ALT_BIT 0x20000000 +#define MOD_LCONTROL 0 +#define MOD_RCONTROL 1 +#define MOD_LMENU 2 +#define MOD_RMENU 3 -static int -GetControlKeyState(void) +static BOOL modifiers[4] = {FALSE, FALSE, FALSE, FALSE}; + +static VOID +reset_modifiers () { - return - ( (((GetKeyState (VK_MENU)) < 0) ? SCREEN_ALT_PRESSED : 0) - | (((GetKeyState (VK_CONTROL)) < 0) ? SCREEN_CTRL_PRESSED : 0) - | (((GetKeyState (VK_SHIFT)) < 0) ? SCREEN_SHIFT_PRESSED : 0) - | (((GetKeyState (VK_NUMLOCK)) & 1) ? SCREEN_NUMLOCK_ON : 0) - | (((GetKeyState (VK_SCROLL)) & 1) ? SCREEN_SCROLLLOCK_ON : 0) - | (((GetKeyState (VK_CAPITAL)) & 1) ? SCREEN_CAPSLOCK_ON : 0)); + // This is used when we regain focus, since we cannot regenerate the modifier + // state. + modifiers[0] = modifiers[1] = modifiers[2] = modifiers[3] = FALSE; } -static VOID _fastcall -make_key_event (SCREEN screen, int ch, int vk_code, DWORD lKeyData) -{ - SCREEN_EVENT *event; +static BOOL +test_modifier (int vk) +{ + switch (vk) { + case VK_LCONTROL: return modifiers[MOD_LCONTROL]; + case VK_RCONTROL: return modifiers[MOD_RCONTROL]; + case VK_LMENU: return modifiers[MOD_LMENU]; + case VK_RMENU: return modifiers[MOD_RMENU]; + default: return GetKeyState (vk) < 0; + } +} - if ((screen->mode_flags & SCREEN_MODE_VK_KEYS) == 0 && ch == -1) +static void +record_modifier_transition (WPARAM wParam, LPARAM lParam, BOOL updown) +{ + int i; + switch (wParam) { + default: return; - - event = alloc_event (screen, SCREEN_EVENT_TYPE_KEY); - if (event) { - event->event.key.repeat_count = lKeyData & 0xffff; - event->event.key.virtual_keycode = vk_code; - event->event.key.virtual_scancode = (lKeyData >> 16) & 0xff; - event->event.key.ch = ch; - event->event.key.control_key_state = GetControlKeyState(); + case VK_MENU: + i = (lParam & 0x1000000) ? MOD_RMENU : MOD_LMENU; + break; + case VK_CONTROL: + i = (lParam & 0x1000000) ? MOD_RCONTROL : MOD_LCONTROL; + break; } + modifiers[i] = updown; } -// We learn which scan codes are for keys that we process ourselves and -// hence do not want to accept as WM_CHARS from Transalate Message +static int +GetPlainModifiers() +{ + int mods = 0; + if (test_modifier (VK_SHIFT)) mods |= SCREEN_SHIFT_PRESSED; + if (test_modifier (VK_CAPITAL)) mods |= SCREEN_CAPSLOCK_ON; + if (test_modifier (VK_LCONTROL)) mods |= SCREEN_LEFT_CONTROL_PRESSED; + if (test_modifier (VK_RCONTROL)) mods |= SCREEN_RIGHT_CONTROL_PRESSED; + if (test_modifier (VK_LMENU)) mods |= SCREEN_LEFT_ALT_PRESSED; + if (test_modifier (VK_RMENU)) mods |= SCREEN_RIGHT_ALT_PRESSED; -BOOL scan_codes_to_avoid[256] = {0}; + if (mods & (SCREEN_RIGHT_ALT_PRESSED | SCREEN_LEFT_ALT_PRESSED)) + mods |= SCREEN_ALT_PRESSED; -//--------------------------------------------------------------------------- -// VOID ProcessScreenCharacter (HWND hWnd, int ch, DWORD lKeyData) -//--------------------------------------------------------------------------- + if (mods & (SCREEN_RIGHT_CONTROL_PRESSED | SCREEN_LEFT_CONTROL_PRESSED)) + mods |= SCREEN_CONTROL_PRESSED; -static VOID -ProcessScreenCharacter (HWND hWnd, int ch, DWORD lKeyData) + return mods; +} + +static int +GetModifiers(void) { - // Process a WM_CHAR or WM_SYSCHAR character - SCREEN screen = GETSCREEN (hWnd); - - if (NULL == screen) - return; - + int mods = + GetPlainModifiers() & ~ (SCREEN_ALT_PRESSED | SCREEN_CONTROL_PRESSED); + + // If AltGr pressed, remove it. + if (mods & (SCREEN_RIGHT_ALT_PRESSED | SCREEN_LEFT_CONTROL_PRESSED) + == (SCREEN_RIGHT_ALT_PRESSED | SCREEN_LEFT_CONTROL_PRESSED)) + mods &= ~ (SCREEN_RIGHT_ALT_PRESSED | SCREEN_LEFT_CONTROL_PRESSED); + + if (mods & (SCREEN_RIGHT_ALT_PRESSED | SCREEN_LEFT_ALT_PRESSED)) + mods |= SCREEN_ALT_PRESSED; + + if (mods & (SCREEN_RIGHT_CONTROL_PRESSED | SCREEN_LEFT_CONTROL_PRESSED)) + mods |= SCREEN_CONTROL_PRESSED; + + return mods; +} + +static VOID _fastcall +make_key_event (SCREEN screen, int ch, int vk_code, DWORD lKeyData, int CCstate) +{ + SCREEN_EVENT *event; + // check for bindings: - { + if (CCstate == 0) { int i; - for (i=0; in_bindings; i++) + for (i = 0; i < screen->n_bindings; i++) if (screen->bindings[i].key == ch) { if (SendMessage (screen->hWnd, @@ -1921,122 +1980,172 @@ ProcessScreenCharacter (HWND hWnd, int ch, DWORD lKeyData) } } - // exclude characters that TranslateMessage produces but we handle - // differently in order to get all those wonderful control-shift-meta - // things + if ((screen->mode_flags & SCREEN_MODE_VK_KEYS) == 0 && ch == -1) + return; - if (scan_codes_to_avoid[(lKeyData >> 16) & 0xff]) - return; + event = alloc_event (screen, SCREEN_EVENT_TYPE_KEY); + if (event) { + event->event.key.repeat_count = 1; + event->event.key.virtual_keycode = vk_code; + event->event.key.virtual_scancode = (lKeyData >> 16) & 0xff; + event->event.key.ch = ch; + event->event.key.control_key_state = CCstate; - switch (ch) { - case -1: - return; - } +#if 0 + { + static HWND disp = NULL; + static char prevline2[50] = {0}; + static char prevline1[50] = {0}; + char line[50], buf[100], name[20]; + if (disp==NULL) + disp = CreateWindowEx(WS_EX_TOPMOST, "STATIC", "", + WS_VISIBLE | SS_LEFT | SS_NOPREFIX, + 0, 0, 130, 20+3*20, + 0, 0, ghInstance, 0); + if (ch==-1) + sprintf(name, "VK_x%02X", vk_code); + else if (' ' < ch && ch < ASCII_DEL) + sprintf(name, "%c", ch); + else if (ch>127) + sprintf(name, "code x%02X %c", ch, ch); + else if (ch==' ') + sprintf(name, "Space"); + else + sprintf(name, "code x%02X", ch); + sprintf(line, "%s%s%s%s", + (CCstate & SCREEN_ALT_PRESSED) ? "M-" : "", + (CCstate & SCREEN_CONTROL_PRESSED) ? "C-" : "", + (CCstate & SCREEN_SHIFT_PRESSED) ? "S-" : "", + name); + sprintf(buf,"%s\r\n%s\r\n%s", prevline2, prevline1, line); + strcpy (prevline2, prevline1); + strcpy (prevline1, line); + SetWindowText (disp, buf); + } +#endif + } +} - make_key_event (screen, ch, 0, lKeyData); +static BOOL +Translate_vk_to_tty_char (SCREEN screen, int vk, LPARAM lParam) +{ + // Tranlate to default Emacs-oid key bindings to make console + // edwin happy + int ch = -1; + switch (vk) { + case VK_UP: ch = ASCII_CONTROLIFY('P'); break; + case VK_DOWN: ch = ASCII_CONTROLIFY('N'); break; + case VK_LEFT: ch = ASCII_CONTROLIFY('B'); break; + case VK_RIGHT: ch = ASCII_CONTROLIFY('F'); break; + case VK_PRIOR: + make_key_event (screen, 'V', 0, lParam, SCREEN_ALT_PRESSED); + return TRUE; + case VK_NEXT: ch = ASCII_CONTROLIFY('V'); break; + case VK_DELETE: ch = ASCII_DEL; break; + } + if (ch != -1) + make_key_event (screen, ch, 0, lParam, 0); + return TRUE; } static BOOL Process_KeyDown (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - // processing for non-ascii VKs - // Assume msg = WM_KEYDOWN or WM_SYSKEYDOWN - // returns flag to say if DefWindowProc should be called. SCREEN screen = GETSCREEN (hWnd); - BOOL default_ok = TRUE; int scan_code = (lParam >> 16) & 0xff; + int extended_key = (lParam & 0x1000000); + int vk = wParam; - switch (wParam) { - case VK_BACK: - make_key_event (screen, ASCII_DEL, 0, lParam); - scan_codes_to_avoid[scan_code] = TRUE; - return TRUE; + MSG message; + BOOL found_wm_chars = FALSE; - case VK_SPACE: - make_key_event (screen, ' ', 0, lParam); - scan_codes_to_avoid[scan_code] = TRUE; + // If Alt is pressed and the key is from the keypad, we are in the middle + // of and ALT+numbers sequence. We will get the char when Alt is released. + if (msg == WM_SYSKEYDOWN) { + if (VK_NUMPAD0 <= vk && vk <= VK_NUMPAD9) return TRUE; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - // This is very naughty. We should figure out how to allow the - // keyboard to produce the correct keys according to the keyboard - // layout. - if (GetKeyState(VK_SHIFT)<0) - make_key_event (screen, ")!@#$%^&*("[wParam-'0'], 0, lParam); - else - make_key_event (screen, wParam, 0, lParam); - scan_codes_to_avoid[scan_code] = TRUE; + if (!extended_key && + (vk == VK_HOME || vk == VK_UP || vk == VK_PRIOR || + vk == VK_LEFT || vk == VK_RIGHT || + vk == VK_END || vk == VK_DOWN || vk == VK_NEXT || + vk == VK_INSERT)) return TRUE; + } - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': - case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': - case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': - case 'V': case 'W': case 'X': case 'Y': case 'Z': - { - // This is very naughty. We should figure out how to allow the - // keyboard to produce the correct keys according to the keyboard - // layout. - int shift = ((GetKeyState(VK_SHIFT)>>15) ^ GetKeyState(VK_CAPITAL)) & 1; - int control = GetKeyState(VK_CONTROL) < 0; - int alt = GetKeyState(VK_MENU) < 0; - - if (control) - make_key_event (screen, wParam-64, 0, lParam); - else if (shift) - make_key_event (screen, wParam, 0, lParam); - else - make_key_event (screen, wParam+32, 0, lParam); - scan_codes_to_avoid[scan_code] = TRUE; + if (vk == VK_LSHIFT || vk == VK_RSHIFT || vk == VK_SHIFT || + vk == VK_LMENU || vk == VK_RMENU || vk == VK_MENU || + vk == VK_LCONTROL || vk == VK_RCONTROL || vk == VK_CONTROL || + vk == VK_CAPITAL || vk == VK_NUMLOCK || vk == VK_SCROLL) { + return TRUE; + } + + while (PeekMessage (&message, hWnd, WM_CHAR, WM_CHAR, PM_REMOVE) || + PeekMessage (&message, hWnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) { + int mods = GetPlainModifiers(); + int event_mods = 0; + if (vk == VK_BACK && message.wParam == 8) + message.wParam = ASCII_DEL; + if (vk == VK_SPACE && (mods & SCREEN_CONTROL_PRESSED)) + event_mods |= SCREEN_CONTROL_PRESSED; + if (msg == WM_SYSKEYDOWN || + ((mods & SCREEN_LEFT_ALT_PRESSED) && (mods & SCREEN_RIGHT_ALT_PRESSED))) + event_mods |= SCREEN_ALT_PRESSED; + make_key_event (screen, message.wParam, 0, lParam, event_mods); + found_wm_chars = TRUE; + } + if (found_wm_chars) + return TRUE; + + if (vk == VK_LEFT || vk == VK_RIGHT || vk == VK_UP || vk == VK_DOWN || + vk == VK_HOME || vk == VK_END || vk == VK_PRIOR || vk == VK_NEXT || + vk == VK_INSERT || vk == VK_DELETE || (vk >= VK_F1 && vk <= VK_F24)) { + if (screen->mode_flags & SCREEN_MODE_VK_KEYS) { + make_key_event (screen, -1, vk, lParam, GetModifiers()); return TRUE; + } else { + return Translate_vk_to_tty_char (screen, vk, lParam); } + } - case VK_F1: - case VK_F2: - case VK_F3: - case VK_F4: - case VK_F5: - case VK_F6: - case VK_F7: - case VK_F8: - case VK_F9: - case VK_F10: - case VK_F11: - case VK_F12: - case VK_UP: - case VK_DOWN: - case VK_LEFT: - case VK_RIGHT: - case VK_INSERT: - case VK_DELETE: - case VK_HOME: - case VK_END: - case VK_PRIOR: - case VK_NEXT: - if (screen->mode_flags & SCREEN_MODE_VK_KEYS) - make_key_event (screen, -1, wParam, lParam); - else { - int ch; - switch (wParam) { - // Tranlate to default Emacs-oid key bindings to make console - // edwin happy - default: ch = -1; break; - case VK_UP: ch = ASCII_CONTROLIFY('P'); break; - case VK_DOWN: ch = ASCII_CONTROLIFY('N'); break; - case VK_LEFT: ch = ASCII_CONTROLIFY('B'); break; - case VK_RIGHT: ch = ASCII_CONTROLIFY('F'); break; - case VK_PRIOR: ch = ASCII_METAFY('V'); break; - case VK_NEXT: ch = ASCII_CONTROLIFY('V'); break; - case VK_DELETE: ch = ASCII_DEL; break; - } - if (ch != -1) - make_key_event (screen, ch, 0, lParam); - } - return TRUE; + // At this point the keypress didnt generate a character because it + // doesn't understand the combination of modifiers, or the character + // could be a dead character. - default: - return TRUE; + if (PeekMessage (&message, hWnd, WM_DEADCHAR, WM_DEADCHAR, PM_REMOVE) || + PeekMessage (&message, hWnd, WM_SYSDEADCHAR, WM_SYSDEADCHAR, PM_REMOVE)) { + return TRUE; + } + + if (('A' <= vk && vk <= 'Z') || + ('0' <= vk && vk <= '9') || + (vk == VK_SPACE)) { + make_key_event (screen, vk, 0, lParam, GetPlainModifiers()); + return TRUE; + } + + return TRUE; +} + +static BOOL +Process_KeyUp (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SCREEN screen = GETSCREEN (hWnd); + int vk = wParam; + + // Releasing ALT might give us an ALT+numbers character. + if (vk == VK_MENU) { + MSG message; + BOOL found_wm_chars = FALSE; + while (PeekMessage (&message, hWnd, WM_CHAR, WM_CHAR, PM_REMOVE) || + PeekMessage (&message, hWnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) { + make_key_event (screen, message.wParam, 0, lParam, 0); + found_wm_chars = TRUE; } + if (found_wm_chars) + return TRUE; + return FALSE; // Don't activate the system menu! + } + return TRUE; } static VOID @@ -2049,7 +2158,7 @@ ProcessCloseMessage (SCREEN screen) static VOID ProcessMouseButton (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, - BOOL up) + BOOL up) { SCREEN screen = GETSCREEN (hWnd) ; SCREEN_EVENT * event ; diff --git a/v7/src/microcode/ntscreen.h b/v7/src/microcode/ntscreen.h index 84640622c..33d7ec194 100644 --- a/v7/src/microcode/ntscreen.h +++ b/v7/src/microcode/ntscreen.h @@ -1,8 +1,8 @@ /* -*-C-*- -$Id: ntscreen.h,v 1.15 1997/05/17 06:59:56 cph Exp $ +$Id: ntscreen.h,v 1.16 1998/01/20 18:39:45 adams Exp $ -Copyright (c) 1993-97 Massachusetts Institute of Technology +Copyright (c) 1993-1998 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and @@ -92,25 +92,19 @@ typedef struct { int key_down : 1; } SCREEN_KEY_EVENT_RECORD; -// control_key_state flags - -//#define SCREEN_RIGHT_ALT_PRESSED 0x0001 // the right alt key is pressed. -//#define SCREEN_LEFT_ALT_PRESSED 0x0002 // the left alt key is pressed. -//#define SCREEN_RIGHT_CTRL_PRESSED 0x0004 // the right ctrl key is pressed. -//#define SCREEN_LEFT_CTRL_PRESSED 0x0008 // the left ctrl key is pressed. -//#define SCREEN_SHIFT_PRESSED 0x0010 // the shift key is pressed. -//#define SCREEN_NUMLOCK_ON 0x0020 // the numlock light is on. -//#define SCREEN_SCROLLLOCK_ON 0x0040 // the scrolllock light is on. -//#define SCREEN_CAPSLOCK_ON 0x0080 // the capslock light is on. -//#define SCREEN_ENHANCED_KEY 0x0100 // the key is enhanced. -//#define SCREEN_ALT_KEY_PRESSED 0x0200 // Any alt key pressed - -#define SCREEN_ALT_PRESSED 0x0001 // An alt key is pressed. -#define SCREEN_CTRL_PRESSED 0x0002 // a ctrl key is pressed. -#define SCREEN_SHIFT_PRESSED 0x0004 // a shift key is pressed. -#define SCREEN_NUMLOCK_ON 0x0020 // the numlock light is on. -#define SCREEN_SCROLLLOCK_ON 0x0040 // the scrolllock light is on. -#define SCREEN_CAPSLOCK_ON 0x0080 // the capslock light is on. +// control_key_state flags. Only used for effective modifiers (i.e. +// not set when already incorporated into a character translation. + +#define SCREEN_ALT_PRESSED 0x0001 // An Alt key is pressed. +#define SCREEN_CONTROL_PRESSED 0x0002 // a Ctrl key is pressed. +#define SCREEN_SHIFT_PRESSED 0x0004 // a Shift key is pressed. +#define SCREEN_CAPSLOCK_ON 0x0008 +#define SCREEN_LEFT_CONTROL_PRESSED 0x0010 +#define SCREEN_RIGHT_CONTROL_PRESSED 0x0020 +#define SCREEN_LEFT_ALT_PRESSED 0x0040 +#define SCREEN_RIGHT_ALT_PRESSED 0x0080 +#define SCREEN_NUMLOCK_ON 0x0100 + #define SCREEN_ANY_ALT_KEY_MASK SCREEN_ALT_PRESSED diff --git a/v7/src/microcode/object.h b/v7/src/microcode/object.h index dbbb297a7..97d3dceac 100644 --- a/v7/src/microcode/object.h +++ b/v7/src/microcode/object.h @@ -1,8 +1,8 @@ /* -*-C-*- -$Id: object.h,v 9.47 1997/07/15 22:06:24 adams Exp $ +$Id: object.h,v 9.48 1998/01/20 18:40:57 adams Exp $ -Copyright (c) 1987-95 Massachusetts Institute of Technology +Copyright (c) 1987-1998 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and @@ -355,9 +355,9 @@ extern SCHEME_OBJECT * memory_base; /* Character Operations */ #define ASCII_LENGTH CHAR_BIT /* CHAR_BIT in config.h - 8 for unix */ -#define CODE_LENGTH 7 +#define CODE_LENGTH 16 #define BITS_LENGTH 5 -#define MIT_ASCII_LENGTH 12 +#define MIT_ASCII_LENGTH 21 #define CHAR_BITS_META 01 #define CHAR_BITS_CONTROL 02 diff --git a/v7/src/runtime/char.scm b/v7/src/runtime/char.scm index b107b972c..112c8b934 100644 --- a/v7/src/runtime/char.scm +++ b/v7/src/runtime/char.scm @@ -1,8 +1,8 @@ #| -*-Scheme-*- -$Id: char.scm,v 14.7 1997/10/15 03:20:42 adams Exp $ +$Id: char.scm,v 14.8 1998/01/20 18:40:24 adams Exp $ -Copyright (c) 1988-97 Massachusetts Institute of Technology +Copyright (c) 1988-1998 Massachusetts Institute of Technology This material was developed by the Scheme project at the Massachusetts Institute of Technology, Department of Electrical Engineering and @@ -38,7 +38,8 @@ MIT in each case. |# (declare (usual-integrations)) (define-primitives - char? make-char char-code char-bits char->integer integer->char char->ascii + (char? 1) + make-char char-code char-bits char->integer integer->char char->ascii char-ascii? ascii->char char-upcase char-downcase) (define-integrable char-code-limit #x80) @@ -169,8 +170,15 @@ MIT in each case. |# (if (substring-ci=? string start end "Newline" 0 7) (char-code char:newline) (or (-map-> named-codes string start end) + (numeric-name->code string start end) (error "Unknown character name" (substring string start end))))) +(define (numeric-name->code string start end) + (and (> (- end start) 6) + (substring-ci=? string start (+ start 5) "" 0 1) + (string->number (substring string (+ start 5) (- end 1)) 10))) + (define (char->name char #!optional slashify?) (if (default-object? slashify?) (set! slashify? false)) (define (loop weight bits) @@ -187,16 +195,16 @@ MIT in each case. |# ((char-graphic? base-char) (string base-char)) (else - (string-append "string code 10) ">"))))) (let ((qr (integer-divide bits 2))) (let ((rest (loop (fix:* weight 2) (integer-divide-quotient qr)))) (if (fix:= 0 (integer-divide-remainder qr)) rest (string-append (or (<-map- named-bits weight) - (string-append "string weight 10) ">")) "-" rest)))))) diff --git a/v8/src/microcode/object.h b/v8/src/microcode/object.h index a66aabdba..c471510b6 100644 --- a/v8/src/microcode/object.h +++ b/v8/src/microcode/object.h @@ -1,6 +1,6 @@ /* -*-C-*- -$Id: object.h,v 9.47 1995/09/18 22:32:56 cph Exp $ +$Id: object.h,v 9.48 1998/01/20 18:39:35 adams Exp $ Copyright (c) 1987-95 Massachusetts Institute of Technology @@ -386,9 +386,9 @@ extern SCHEME_OBJECT * memory_base; /* Character Operations */ #define ASCII_LENGTH CHAR_BIT /* CHAR_BIT in config.h - 8 for unix */ -#define CODE_LENGTH 7 +#define CODE_LENGTH 16 #define BITS_LENGTH 5 -#define MIT_ASCII_LENGTH 12 +#define MIT_ASCII_LENGTH 21 #define CHAR_BITS_META 01 #define CHAR_BITS_CONTROL 02 -- 2.25.1