+
+ /* If a key is pressed and AltGr is not active */
+ if (key_down && (keystate[VK_RMENU] & 0x80) == 0 && !compose_state) {
+ /* Okay, prepare for most alts then ... */
+ if (left_alt)
+ *p++ = '\033';
+
+ /* Lets see if it's a pattern we know all about ... */
+ if (wParam == VK_PRIOR && shift_state == 1) {
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
+ return 0;
+ }
+ if (wParam == VK_NEXT && shift_state == 1) {
+ SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
+ return 0;
+ }
+ if (wParam == VK_INSERT && shift_state == 1) {
+ term_do_paste();
+ return 0;
+ }
+ if (left_alt && wParam == VK_F4 && cfg.alt_f4) {
+ return -1;
+ }
+ if (left_alt && wParam == VK_SPACE && cfg.alt_space) {
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
+ return -1;
+ }
+ if (left_alt && wParam == VK_RETURN && cfg.fullscreenonaltenter) {
+ flip_full_screen();
+ return -1;
+ }
+ /* Control-Numlock for app-keypad mode switch */
+ if (wParam == VK_PAUSE && shift_state == 2) {
+ app_keypad_keys ^= 1;
+ return 0;
+ }
+
+ /* Nethack keypad */
+ if (cfg.nethack_keypad && !left_alt) {
+ switch (wParam) {
+ case VK_NUMPAD1:
+ *p++ = shift_state ? 'B' : 'b';
+ return p - output;
+ case VK_NUMPAD2:
+ *p++ = shift_state ? 'J' : 'j';
+ return p - output;
+ case VK_NUMPAD3:
+ *p++ = shift_state ? 'N' : 'n';
+ return p - output;
+ case VK_NUMPAD4:
+ *p++ = shift_state ? 'H' : 'h';
+ return p - output;
+ case VK_NUMPAD5:
+ *p++ = shift_state ? '.' : '.';
+ return p - output;
+ case VK_NUMPAD6:
+ *p++ = shift_state ? 'L' : 'l';
+ return p - output;
+ case VK_NUMPAD7:
+ *p++ = shift_state ? 'Y' : 'y';
+ return p - output;
+ case VK_NUMPAD8:
+ *p++ = shift_state ? 'K' : 'k';
+ return p - output;
+ case VK_NUMPAD9:
+ *p++ = shift_state ? 'U' : 'u';
+ return p - output;
+ }
+ }
+
+ /* Application Keypad */
+ if (!left_alt) {
+ int xkey = 0;
+
+ if (cfg.funky_type == 3 ||
+ (cfg.funky_type <= 1 &&
+ app_keypad_keys && !cfg.no_applic_k)) switch (wParam) {
+ case VK_EXECUTE:
+ xkey = 'P';
+ break;
+ case VK_DIVIDE:
+ xkey = 'Q';
+ break;
+ case VK_MULTIPLY:
+ xkey = 'R';
+ break;
+ case VK_SUBTRACT:
+ xkey = 'S';
+ break;
+ }
+ if (app_keypad_keys && !cfg.no_applic_k)
+ switch (wParam) {
+ case VK_NUMPAD0:
+ xkey = 'p';
+ break;
+ case VK_NUMPAD1:
+ xkey = 'q';
+ break;
+ case VK_NUMPAD2:
+ xkey = 'r';
+ break;
+ case VK_NUMPAD3:
+ xkey = 's';
+ break;
+ case VK_NUMPAD4:
+ xkey = 't';
+ break;
+ case VK_NUMPAD5:
+ xkey = 'u';
+ break;
+ case VK_NUMPAD6:
+ xkey = 'v';
+ break;
+ case VK_NUMPAD7:
+ xkey = 'w';
+ break;
+ case VK_NUMPAD8:
+ xkey = 'x';
+ break;
+ case VK_NUMPAD9:
+ xkey = 'y';
+ break;
+
+ case VK_DECIMAL:
+ xkey = 'n';
+ break;
+ case VK_ADD:
+ if (cfg.funky_type == 2) {
+ if (shift_state)
+ xkey = 'l';
+ else
+ xkey = 'k';
+ } else if (shift_state)
+ xkey = 'm';
+ else
+ xkey = 'l';
+ break;
+
+ case VK_DIVIDE:
+ if (cfg.funky_type == 2)
+ xkey = 'o';
+ break;
+ case VK_MULTIPLY:
+ if (cfg.funky_type == 2)
+ xkey = 'j';
+ break;
+ case VK_SUBTRACT:
+ if (cfg.funky_type == 2)
+ xkey = 'm';
+ break;
+
+ case VK_RETURN:
+ if (HIWORD(lParam) & KF_EXTENDED)
+ xkey = 'M';
+ break;
+ }
+ if (xkey) {
+ if (vt52_mode) {
+ if (xkey >= 'P' && xkey <= 'S')
+ p += sprintf((char *) p, "\x1B%c", xkey);
+ else
+ p += sprintf((char *) p, "\x1B?%c", xkey);
+ } else
+ p += sprintf((char *) p, "\x1BO%c", xkey);
+ return p - output;
+ }
+ }
+
+ if (wParam == VK_BACK && shift_state == 0) { /* Backspace */
+ *p++ = (cfg.bksp_is_delete ? 0x7F : 0x08);
+ *p++ = 0;
+ return -2;
+ }
+ if (wParam == VK_TAB && shift_state == 1) { /* Shift tab */
+ *p++ = 0x1B;
+ *p++ = '[';
+ *p++ = 'Z';
+ return p - output;
+ }
+ if (wParam == VK_SPACE && shift_state == 2) { /* Ctrl-Space */
+ *p++ = 0;
+ return p - output;
+ }
+ if (wParam == VK_SPACE && shift_state == 3) { /* Ctrl-Shift-Space */
+ *p++ = 160;
+ return p - output;
+ }
+ if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */
+ *p++ = 3;
+ *p++ = 0;
+ return -2;
+ }
+ if (wParam == VK_PAUSE) { /* Break/Pause */
+ *p++ = 26;
+ *p++ = 0;
+ return -2;
+ }
+ /* Control-2 to Control-8 are special */
+ if (shift_state == 2 && wParam >= '2' && wParam <= '8') {
+ *p++ = "\000\033\034\035\036\037\177"[wParam - '2'];
+ return p - output;
+ }
+ if (shift_state == 2 && wParam == 0xBD) {
+ *p++ = 0x1F;
+ return p - output;
+ }
+ if (shift_state == 2 && wParam == 0xDF) {
+ *p++ = 0x1C;
+ return p - output;
+ }
+ if (shift_state == 0 && wParam == VK_RETURN && cr_lf_return) {
+ *p++ = '\r';
+ *p++ = '\n';
+ return p - output;
+ }
+
+ /*
+ * Next, all the keys that do tilde codes. (ESC '[' nn '~',
+ * for integer decimal nn.)
+ *
+ * We also deal with the weird ones here. Linux VCs replace F1
+ * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
+ * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
+ * respectively.
+ */
+ code = 0;
+ switch (wParam) {
+ case VK_F1:
+ code = (keystate[VK_SHIFT] & 0x80 ? 23 : 11);
+ break;
+ case VK_F2:
+ code = (keystate[VK_SHIFT] & 0x80 ? 24 : 12);
+ break;
+ case VK_F3:
+ code = (keystate[VK_SHIFT] & 0x80 ? 25 : 13);
+ break;
+ case VK_F4:
+ code = (keystate[VK_SHIFT] & 0x80 ? 26 : 14);
+ break;
+ case VK_F5:
+ code = (keystate[VK_SHIFT] & 0x80 ? 28 : 15);
+ break;
+ case VK_F6:
+ code = (keystate[VK_SHIFT] & 0x80 ? 29 : 17);
+ break;
+ case VK_F7:
+ code = (keystate[VK_SHIFT] & 0x80 ? 31 : 18);
+ break;
+ case VK_F8:
+ code = (keystate[VK_SHIFT] & 0x80 ? 32 : 19);
+ break;
+ case VK_F9:
+ code = (keystate[VK_SHIFT] & 0x80 ? 33 : 20);
+ break;
+ case VK_F10:
+ code = (keystate[VK_SHIFT] & 0x80 ? 34 : 21);
+ break;
+ case VK_F11:
+ code = 23;
+ break;
+ case VK_F12:
+ code = 24;
+ break;
+ case VK_F13:
+ code = 25;
+ break;
+ case VK_F14:
+ code = 26;
+ break;
+ case VK_F15:
+ code = 28;
+ break;
+ case VK_F16:
+ code = 29;
+ break;
+ case VK_F17:
+ code = 31;
+ break;
+ case VK_F18:
+ code = 32;
+ break;
+ case VK_F19:
+ code = 33;
+ break;
+ case VK_F20:
+ code = 34;
+ break;
+ }
+ if ((shift_state&2) == 0) switch (wParam) {
+ case VK_HOME:
+ code = 1;
+ break;
+ case VK_INSERT:
+ code = 2;
+ break;
+ case VK_DELETE:
+ code = 3;
+ break;
+ case VK_END:
+ code = 4;
+ break;
+ case VK_PRIOR:
+ code = 5;
+ break;
+ case VK_NEXT:
+ code = 6;
+ break;
+ }
+ /* Reorder edit keys to physical order */
+ if (cfg.funky_type == 3 && code <= 6)
+ code = "\0\2\1\4\5\3\6"[code];
+
+ if (vt52_mode && code > 0 && code <= 6) {
+ p += sprintf((char *) p, "\x1B%c", " HLMEIG"[code]);
+ return p - output;
+ }
+
+ if (cfg.funky_type == 5 && /* SCO function keys */
+ code >= 11 && code <= 34) {
+ char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
+ int index = 0;
+ switch (wParam) {
+ case VK_F1: index = 0; break;
+ case VK_F2: index = 1; break;
+ case VK_F3: index = 2; break;
+ case VK_F4: index = 3; break;
+ case VK_F5: index = 4; break;
+ case VK_F6: index = 5; break;
+ case VK_F7: index = 6; break;
+ case VK_F8: index = 7; break;
+ case VK_F9: index = 8; break;
+ case VK_F10: index = 9; break;
+ case VK_F11: index = 10; break;
+ case VK_F12: index = 11; break;
+ }
+ if (keystate[VK_SHIFT] & 0x80) index += 12;
+ if (keystate[VK_CONTROL] & 0x80) index += 24;
+ p += sprintf((char *) p, "\x1B[%c", codes[index]);
+ return p - output;
+ }
+ if (cfg.funky_type == 5 && /* SCO small keypad */
+ code >= 1 && code <= 6) {
+ char codes[] = "HL.FIG";
+ if (code == 3) {
+ *p++ = '\x7F';
+ } else {
+ p += sprintf((char *) p, "\x1B[%c", codes[code-1]);
+ }
+ return p - output;
+ }
+ if ((vt52_mode || cfg.funky_type == 4) && code >= 11 && code <= 24) {
+ int offt = 0;
+ if (code > 15)
+ offt++;
+ if (code > 21)
+ offt++;
+ if (vt52_mode)
+ p += sprintf((char *) p, "\x1B%c", code + 'P' - 11 - offt);
+ else
+ p +=
+ sprintf((char *) p, "\x1BO%c", code + 'P' - 11 - offt);
+ return p - output;
+ }
+ if (cfg.funky_type == 1 && code >= 11 && code <= 15) {
+ p += sprintf((char *) p, "\x1B[[%c", code + 'A' - 11);
+ return p - output;
+ }
+ if (cfg.funky_type == 2 && code >= 11 && code <= 14) {
+ if (vt52_mode)
+ p += sprintf((char *) p, "\x1B%c", code + 'P' - 11);
+ else
+ p += sprintf((char *) p, "\x1BO%c", code + 'P' - 11);
+ return p - output;
+ }
+ if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
+ p += sprintf((char *) p, code == 1 ? "\x1B[H" : "\x1BOw");
+ return p - output;
+ }
+ if (code) {
+ p += sprintf((char *) p, "\x1B[%d~", code);
+ return p - output;
+ }
+
+ /*
+ * Now the remaining keys (arrows and Keypad 5. Keypad 5 for
+ * some reason seems to send VK_CLEAR to Windows...).
+ */
+ {
+ char xkey = 0;
+ switch (wParam) {
+ case VK_UP:
+ xkey = 'A';
+ break;
+ case VK_DOWN:
+ xkey = 'B';
+ break;
+ case VK_RIGHT:
+ xkey = 'C';
+ break;
+ case VK_LEFT:
+ xkey = 'D';
+ break;
+ case VK_CLEAR:
+ xkey = 'G';
+ break;
+ }
+ if (xkey) {
+ if (vt52_mode)
+ p += sprintf((char *) p, "\x1B%c", xkey);
+ else {
+ int app_flg = (app_cursor_keys && !cfg.no_applic_c);
+ /* VT100 & VT102 manuals both state the app cursor keys
+ * only work if the app keypad is on.
+ */
+ if (!app_keypad_keys)
+ app_flg = 0;
+ /* Useful mapping of Ctrl-arrows */
+ if (shift_state == 2)
+ app_flg = !app_flg;
+
+ if (app_flg)
+ p += sprintf((char *) p, "\x1BO%c", xkey);
+ else
+ p += sprintf((char *) p, "\x1B[%c", xkey);
+ }
+ return p - output;
+ }
+ }
+
+ /*
+ * Finally, deal with Return ourselves. (Win95 seems to
+ * foul it up when Alt is pressed, for some reason.)
+ */
+ if (wParam == VK_RETURN) { /* Return */
+ *p++ = 0x0D;
+ *p++ = 0;
+ return -2;
+ }
+
+ if (left_alt && wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9)
+ alt_sum = alt_sum * 10 + wParam - VK_NUMPAD0;
+ else
+ alt_sum = 0;