if (ret) {  keystate[VK_NUMLOCK] = 0; SetKeyboardState (keystate); GetKeyboardState (keystate); } switch ( (lParam >> 16) & 0x1FF ) { case 0x145: p += sprintf((char *)p, "\x1BOP"); return p - output; case 0x135: p += sprintf((char *)p, "\x1BOQ"); return p - output; case 0x037: p += sprintf((char *)p, "\x1BOR"); return p - output; case 0x047: p += sprintf((char *)p, "\x1BOw"); return p - output; case 0x048: p += sprintf((char *)p, "\x1BOx"); return p - output; case 0x049: p += sprintf((char *)p, "\x1BOy"); return p - output; case 0x04A: p += sprintf((char *)p, "\x1BOS"); return p - output; case 0x04B: p += sprintf((char *)p, "\x1BOt"); return p - output; case 0x04C: p += sprintf((char *)p, "\x1BOu"); return p - output; case 0x04D: p += sprintf((char *)p, "\x1BOv"); return p - output; case 0x04E:  p += sprintf((char *)p, (ret && (keystate[VK_SHIFT] & 0x80)) ? "\x1BOm" : "\x1BOl"); return p - output; case 0x04F: p += sprintf((char *)p, "\x1BOq"); return p - output; case 0x050: p += sprintf((char *)p, "\x1BOr"); return p - output; case 0x051: p += sprintf((char *)p, "\x1BOs"); return p - output; case 0x052: p += sprintf((char *)p, "\x1BOp"); return p - output; case 0x053: p += sprintf((char *)p, "\x1BOn"); return p - output; case 0x11C: p += sprintf((char *)p, "\x1BOM"); return p - output; } }   if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_TAB) { *p++ = 0x1B;                    *p++ = '['; *p++ = 'Z'; return p - output; }   if (cancel_alt) { keystate[VK_MENU] = keystate[VK_RMENU]; keystate[VK_LMENU] = 0; }   if (ret) { WORD chr; int r;
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; 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; } 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) { 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; }   { 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 if (app_cursor_keys) p += sprintf((char *)p, "\x1BO%c", xkey); else p += sprintf((char *)p, "\x1B[%c", xkey); return p - output; } } }   {
static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {    unsigned char *p = output;    BYTE keystate[256];    int ret, code;    int cancel_alt = FALSE;    /*     * Get hold of the keyboard state, because we'll need it a few     * times shortly.     */    ret = GetKeyboardState(keystate);    /*      * Record that we pressed key so the scroll window can be reset, but     * be careful to avoid Shift-UP/Down     */    if( wParam != VK_SHIFT && wParam != VK_PRIOR && wParam != VK_NEXT ) {        seen_key_event = 1;     }    /*      * Windows does not always want to distinguish left and right     * Alt or Control keys. Thus we keep track of them ourselves.     * See also the WM_KEYUP handler.     */    if (wParam == VK_MENU) {        if (lParam & 0x1000000) keystate[VK_RMENU] = 0x80;        else keystate[VK_LMENU] = 0x80;        SetKeyboardState (keystate);        return 0;    }    if (wParam == VK_CONTROL) {        if (lParam & 0x1000000) keystate[VK_RCONTROL] = 0x80;        else keystate[VK_LCONTROL] = 0x80;        SetKeyboardState (keystate);        return 0;    }    /*     * Prepend ESC, and cancel ALT, if ALT was pressed at the time     * and it wasn't AltGr.     */    if (lParam & 0x20000000 && (keystate[VK_LMENU] & 0x80)) {        *p++ = 0x1B;        cancel_alt = TRUE;    }    /*     * NetHack keypad mode. This may conflict with Shift-PgUp/PgDn,     * so we do it first.     */    if (cfg.nethack_keypad) {	int shift = keystate[VK_SHIFT] & 0x80;        /*         * NB the shifted versions only work with numlock off.         */	switch ( (lParam >> 16) & 0x1FF ) {	  case 0x047: *p++ = shift ? 'Y' : 'y'; return p - output;	  case 0x048: *p++ = shift ? 'K' : 'k'; return p - output;	  case 0x049: *p++ = shift ? 'U' : 'u'; return p - output;	  case 0x04B: *p++ = shift ? 'H' : 'h'; return p - output;	  case 0x04C: *p++ = '.'; return p - output;	  case 0x04D: *p++ = shift ? 'L' : 'l'; return p - output;	  case 0x04F: *p++ = shift ? 'B' : 'b'; return p - output;	  case 0x050: *p++ = shift ? 'J' : 'j'; return p - output;	  case 0x051: *p++ = shift ? 'N' : 'n'; return p - output;	  case 0x053: *p++ = '.'; return p - output;	}    }    /*     * Shift-PgUp, Shift-PgDn, and Alt-F4 all produce window     * events: we'll deal with those now.     */    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_PRIOR) {	SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0);	return 0;    }    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_NEXT) {	SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);	return 0;    }    if ((lParam & 0x20000000) && wParam == VK_F4 && cfg.alt_f4) {	return -1;    }    if ((lParam & 0x20000000) && wParam == VK_SPACE && cfg.alt_space) {	SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);	return -1;    }    /*     * In general, the strategy is to see what the Windows keymap     * translation has to say for itself, and then process function     * keys and suchlike ourselves if that fails. But first we must     * deal with the small number of special cases which the     * Windows keymap translator thinks it can do but gets wrong.     *     * First special case: we might want the Backspace key to send     * 0x7F not 0x08.     */    if (wParam == VK_BACK) {	*p++ = (cfg.bksp_is_delete ? 0x7F : 0x08);	return p - output;    }    /*     * Control-Space should send ^@ (0x00), not Space.     */    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == VK_SPACE) {	*p++ = 0x00;	return p - output;    }    if (app_keypad_keys) {	/*	 * If we're in applications keypad mode, we have to process it	 * before char-map translation, because it will pre-empt lots	 * of stuff, even if NumLock is off.	 */	if (ret) {	    /*	     * Hack to ensure NumLock doesn't interfere with	     * perception of Shift for Keypad Plus. I don't pretend	     * to understand this, but it seems to work as is.	     * Leave it alone, or die.	     */	    keystate[VK_NUMLOCK] = 0;	    SetKeyboardState (keystate);	    GetKeyboardState (keystate);	}	switch ( (lParam >> 16) & 0x1FF ) {	  case 0x145: p += sprintf((char *)p, "\x1BOP"); return p - output;	  case 0x135: p += sprintf((char *)p, "\x1BOQ"); return p - output;	  case 0x037: p += sprintf((char *)p, "\x1BOR"); return p - output;	  case 0x047: p += sprintf((char *)p, "\x1BOw"); return p - output;	  case 0x048: p += sprintf((char *)p, "\x1BOx"); return p - output;	  case 0x049: p += sprintf((char *)p, "\x1BOy"); return p - output;	  case 0x04A: p += sprintf((char *)p, "\x1BOS"); return p - output;	  case 0x04B: p += sprintf((char *)p, "\x1BOt"); return p - output;	  case 0x04C: p += sprintf((char *)p, "\x1BOu"); return p - output;	  case 0x04D: p += sprintf((char *)p, "\x1BOv"); return p - output;	  case 0x04E: /* keypad + is ^[Ol, but ^[Om with Shift */	    p += sprintf((char *)p,			 (ret && (keystate[VK_SHIFT] & 0x80)) ?			 "\x1BOm" : "\x1BOl");	    return p - output;	  case 0x04F: p += sprintf((char *)p, "\x1BOq"); return p - output;	  case 0x050: p += sprintf((char *)p, "\x1BOr"); return p - output;	  case 0x051: p += sprintf((char *)p, "\x1BOs"); return p - output;	  case 0x052: p += sprintf((char *)p, "\x1BOp"); return p - output;	  case 0x053: p += sprintf((char *)p, "\x1BOn"); return p - output;	  case 0x11C: p += sprintf((char *)p, "\x1BOM"); return p - output;	}    }    /*     * Shift-Tab should send ESC [ Z.     */    if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_TAB) {        *p++ = 0x1B;                   /* ESC */        *p++ = '[';        *p++ = 'Z';	return p - output;    }    /*     * Before doing Windows charmap translation, remove LeftALT     * from the keymap, since its sole effect should be to prepend     * ESC, which we've already done. Note that removal of LeftALT     * has to happen _after_ the above call to SetKeyboardState, or     * dire things will befall.     */    if (cancel_alt) {        keystate[VK_MENU] = keystate[VK_RMENU];        keystate[VK_LMENU] = 0;    }    /*     * Attempt the Windows char-map translation.     */    if (ret) {	WORD chr;	int r;	BOOL capsOn=keystate[VK_CAPITAL] !=0;	/* helg: clear CAPS LOCK state if caps lock switches to cyrillic */	if(cfg.xlat_capslockcyr)	    keystate[VK_CAPITAL] = 0;	r = ToAscii (wParam, (lParam >> 16) & 0xFF,		     keystate, &chr, 0);	if(capsOn)	    chr = xlat_latkbd2win((unsigned char)(chr & 0xFF));	if (r == 1) {	    *p++ = xlat_kbd2tty((unsigned char)(chr & 0xFF));	    return p - output;	}    }    /*     * OK, we haven't had a key code from the keymap translation.     * We'll try our various special cases and function keys, and     * then give up. (There's nothing wrong with giving up:     * Scrollock, Pause/Break, and of course the various buckybit     * keys all produce KEYDOWN events that we really _do_ want to     * ignore.)     */    /*     * Control-2 should return ^@ (0x00), Control-6 should return     * ^^ (0x1E), and Control-Minus should return ^_ (0x1F). Since     * the DOS keyboard handling did it, and we have nothing better     * to do with the key combo in question, we'll also map     * Control-Backquote to ^\ (0x1C).     *     * In addition a real VT100 maps Ctrl-3/4/5/7 and 8.     */    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '2') {	*p++ = 0x00;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '3') {	*p++ = 0x1B;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '4') {	*p++ = 0x1C;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '5') {	*p++ = 0x1D;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '6') {	*p++ = 0x1E;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '7') {	*p++ = 0x1F;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == '8') {	*p++ = 0x7F;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == 0xBD) {	*p++ = 0x1F;	return p - output;    }    if (ret && (keystate[VK_CONTROL] & 0x80) && wParam == 0xDF) {	*p++ = 0x1C;	return p - output;    }    /*     * First, 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_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;    }    if (cfg.linux_funkeys && code >= 11 && code <= 15) {	p += sprintf((char *)p, "\x1B[[%c", code + 'A' - 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...).     */    switch (wParam) {      case VK_UP:	p += sprintf((char *)p, app_cursor_keys ? "\x1BOA" : "\x1B[A");	return p - output;      case VK_DOWN:	p += sprintf((char *)p, app_cursor_keys ? "\x1BOB" : "\x1B[B");	return p - output;      case VK_RIGHT:	p += sprintf((char *)p, app_cursor_keys ? "\x1BOC" : "\x1B[C");	return p - output;      case VK_LEFT:	p += sprintf((char *)p, app_cursor_keys ? "\x1BOD" : "\x1B[D");	return p - output;      case VK_CLEAR: p += sprintf((char *)p, "\x1B[G"); return p - output;    }    return 0;}