len = TranslateKey (message, wParam, lParam, buf); if (len == -1) return DefWindowProc (hwnd, message, wParam, lParam); ldisc->send (buf, len); } return 0;
if (wParam==VK_PROCESSKEY) { MSG m; m.hwnd = hwnd; m.message = WM_KEYDOWN; m.wParam = wParam; m.lParam = lParam & 0xdfff; TranslateMessage(&m); } else { len = TranslateKey (message, wParam, lParam, buf); if (len == -1) return DefWindowProc (hwnd, message, wParam, lParam); ldisc->send (buf, len); } } return 0; case WM_IME_CHAR: { unsigned char buf[2];  buf[1] = wParam; buf[0] = wParam >> 8; ldisc->send (buf, 2); }
static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,                                 WPARAM wParam, LPARAM lParam) {    HDC hdc;    static int ignore_size = FALSE;    static int ignore_clip = FALSE;    static int just_reconfigged = FALSE;    static int resizing = FALSE;    switch (message) {      case WM_TIMER:	if (pending_netevent)	    enact_pending_netevent();	if (inbuf_head)	    term_out();        HideCaret(hwnd);	term_update();        ShowCaret(hwnd);	if (cfg.ping_interval > 0)        {           time_t now;           time(&now);           if (now-last_movement > cfg.ping_interval * 60 - 10)           {              back->special(TS_PING);              last_movement = now;           }        }	return 0;      case WM_CREATE:	break;      case WM_CLOSE:	if (!cfg.warn_on_close || session_closed ||	    MessageBox(hwnd, "Are you sure you want to close this session?",		       "PuTTY Exit Confirmation",		       MB_ICONWARNING | MB_OKCANCEL) == IDOK)	    DestroyWindow(hwnd);	return 0;      case WM_DESTROY:	PostQuitMessage (0);	return 0;      case WM_SYSCOMMAND:	switch (wParam & ~0xF) {       /* low 4 bits reserved to Windows */	  case IDM_SHOWLOG:	    showeventlog(hwnd);	    break;	  case IDM_NEWSESS:	  case IDM_DUPSESS:	  case IDM_SAVEDSESS:	    {		char b[2048];		char c[30], *cl;		int freecl = FALSE;		STARTUPINFO si;		PROCESS_INFORMATION pi;		HANDLE filemap = NULL;		if (wParam == IDM_DUPSESS) {		    /*		     * Allocate a file-mapping memory chunk for the		     * config structure.		     */		    SECURITY_ATTRIBUTES sa;		    Config *p;		    sa.nLength = sizeof(sa);		    sa.lpSecurityDescriptor = NULL;		    sa.bInheritHandle = TRUE;		    filemap = CreateFileMapping((HANDLE)0xFFFFFFFF,						&sa,						PAGE_READWRITE,						0,						sizeof(Config),						NULL);		    if (filemap) {			p = (Config *)MapViewOfFile(filemap,						    FILE_MAP_WRITE,						    0, 0, sizeof(Config));			if (p) {			    *p = cfg;  /* structure copy */			    UnmapViewOfFile(p);			}		    }		    sprintf(c, "putty &%p", filemap);		    cl = c;		} else if (wParam == IDM_SAVEDSESS) {		    char *session = sessions[(lParam - IDM_SAVED_MIN) / 16];		    cl = malloc(16 + strlen(session)); /* 8, but play safe */		    if (!cl)			cl = NULL;     /* not a very important failure mode */		    else {			sprintf(cl, "putty @%s", session);			freecl = TRUE;		    }		} else		    cl = NULL;		GetModuleFileName (NULL, b, sizeof(b)-1);		si.cb = sizeof(si);		si.lpReserved = NULL;		si.lpDesktop = NULL;		si.lpTitle = NULL;		si.dwFlags = 0;		si.cbReserved2 = 0;		si.lpReserved2 = NULL;		CreateProcess (b, cl, NULL, NULL, TRUE,			       NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);		if (filemap)		    CloseHandle(filemap);		if (freecl)		    free(cl);	    }	    break;	  case IDM_RECONF:	    if (!do_reconfig(hwnd))		break;	    just_reconfigged = TRUE;	    {		int i;		for (i=0; i<8; i++)		    if (fonts[i])			DeleteObject(fonts[i]);	    }	    bold_mode = cfg.bold_colour ? BOLD_COLOURS : BOLD_FONT;	    und_mode = UND_FONT;	    init_fonts(0);	    sfree(logpal);	    /* Telnet will change local echo -> remote if the remote asks */	    if (cfg.protocol != PROT_TELNET)	        ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);	    if (pal)		DeleteObject(pal);	    logpal = NULL;	    pal = NULL;	    cfgtopalette();	    init_palette();	    /* Enable or disable the scroll bar, etc */	    {		LONG nflg, flag = GetWindowLong(hwnd, GWL_STYLE);		nflg = flag;		if (cfg.scrollbar) nflg |=  WS_VSCROLL;		else               nflg &= ~WS_VSCROLL;		if (cfg.locksize) 		   nflg &= ~(WS_THICKFRAME|WS_MAXIMIZEBOX);		else              		   nflg |= (WS_THICKFRAME|WS_MAXIMIZEBOX);		if (nflg != flag)		{		    RECT cr, wr;		    SetWindowLong(hwnd, GWL_STYLE, nflg);		    SendMessage (hwnd, WM_IGNORE_SIZE, 0, 0);	            SetWindowPos(hwnd, NULL, 0,0,0,0,		         SWP_NOACTIVATE|SWP_NOCOPYBITS|			 SWP_NOMOVE|SWP_NOSIZE| SWP_NOZORDER|			 SWP_FRAMECHANGED);		    GetWindowRect (hwnd, &wr);		    GetClientRect (hwnd, &cr);		    extra_width = wr.right - wr.left - cr.right + cr.left;		    extra_height = wr.bottom - wr.top - cr.bottom + cr.top;		}	    }	    term_size(cfg.height, cfg.width, cfg.savelines);	    InvalidateRect(hwnd, NULL, TRUE);	    SetWindowPos (hwnd, NULL, 0, 0,			  extra_width + font_width * cfg.width,			  extra_height + font_height * cfg.height,			  SWP_NOACTIVATE | SWP_NOCOPYBITS |			  SWP_NOMOVE | SWP_NOZORDER);	    if (IsIconic(hwnd)) {		SetWindowText (hwnd,			       cfg.win_name_always ? window_name : icon_name);	    }	    break;	  case IDM_CLRSB:	    term_clrsb();	    break;	  case IDM_RESET:	    term_pwron();	    break;	  case IDM_TEL_AYT: back->special (TS_AYT); break;	  case IDM_TEL_BRK: back->special (TS_BRK); break;	  case IDM_TEL_SYNCH: back->special (TS_SYNCH); break;	  case IDM_TEL_EC: back->special (TS_EC); break;	  case IDM_TEL_EL: back->special (TS_EL); break;	  case IDM_TEL_GA: back->special (TS_GA); break;	  case IDM_TEL_NOP: back->special (TS_NOP); break;	  case IDM_TEL_ABORT: back->special (TS_ABORT); break;	  case IDM_TEL_AO: back->special (TS_AO); break;	  case IDM_TEL_IP: back->special (TS_IP); break;	  case IDM_TEL_SUSP: back->special (TS_SUSP); break;	  case IDM_TEL_EOR: back->special (TS_EOR); break;	  case IDM_TEL_EOF: back->special (TS_EOF); break;	  case IDM_ABOUT:	    showabout (hwnd);	    break;	default:	  if (wParam >= IDM_SAVED_MIN && wParam <= IDM_SAVED_MAX) {	    SendMessage(hwnd, WM_SYSCOMMAND, IDM_SAVEDSESS, wParam);	  }	}	break;#define X_POS(l) ((int)(short)LOWORD(l))#define Y_POS(l) ((int)(short)HIWORD(l))#define TO_CHR_X(x) (((x)<0 ? (x)-font_width+1 : (x)) / font_width)#define TO_CHR_Y(y) (((y)<0 ? (y)-font_height+1: (y)) / font_height)      case WM_LBUTTONDOWN:	click (MB_SELECT, TO_CHR_X(X_POS(lParam)),	       TO_CHR_Y(Y_POS(lParam)));        SetCapture(hwnd);	return 0;      case WM_LBUTTONUP:	term_mouse (MB_SELECT, MA_RELEASE, TO_CHR_X(X_POS(lParam)),		    TO_CHR_Y(Y_POS(lParam)));        ReleaseCapture();	return 0;      case WM_MBUTTONDOWN:        SetCapture(hwnd);	click (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,	       TO_CHR_X(X_POS(lParam)),	       TO_CHR_Y(Y_POS(lParam)));	return 0;      case WM_MBUTTONUP:	term_mouse (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,		    MA_RELEASE, TO_CHR_X(X_POS(lParam)),		    TO_CHR_Y(Y_POS(lParam)));        ReleaseCapture();	return 0;      case WM_RBUTTONDOWN:        SetCapture(hwnd);	click (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,	       TO_CHR_X(X_POS(lParam)),	       TO_CHR_Y(Y_POS(lParam)));	return 0;      case WM_RBUTTONUP:	term_mouse (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,		    MA_RELEASE, TO_CHR_X(X_POS(lParam)),		    TO_CHR_Y(Y_POS(lParam)));        ReleaseCapture();	return 0;      case WM_MOUSEMOVE:	/*	 * Add the mouse position and message time to the random	 * number noise, if we're using ssh.	 */	if (cfg.protocol == PROT_SSH)	    noise_ultralight(lParam);	if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {	    Mouse_Button b;	    if (wParam & MK_LBUTTON)		b = MB_SELECT;	    else if (wParam & MK_MBUTTON)		b = cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND;	    else		b = cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE;	    term_mouse (b, MA_DRAG, TO_CHR_X(X_POS(lParam)),			TO_CHR_Y(Y_POS(lParam)));	}	return 0;      case WM_IGNORE_CLIP:	ignore_clip = wParam;	       /* don't panic on DESTROYCLIPBOARD */	break;      case WM_DESTROYCLIPBOARD:	if (!ignore_clip)	    term_deselect();	ignore_clip = FALSE;	return 0;      case WM_PAINT:	{	    PAINTSTRUCT p;            HideCaret(hwnd);	    hdc = BeginPaint (hwnd, &p);	    if (pal) {		SelectPalette (hdc, pal, TRUE);		RealizePalette (hdc);	    }	    term_paint (hdc, p.rcPaint.left, p.rcPaint.top,			p.rcPaint.right, p.rcPaint.bottom);	    SelectObject (hdc, GetStockObject(SYSTEM_FONT));	    SelectObject (hdc, GetStockObject(WHITE_PEN));	    EndPaint (hwnd, &p);            ShowCaret(hwnd);	}	return 0;      case WM_NETEVENT:	/* Notice we can get multiple netevents, FD_READ, FD_WRITE etc	 * but the only one that's likely to try to overload us is FD_READ.	 * This means buffering just one is fine.	 */	if (pending_netevent)	    enact_pending_netevent();	pending_netevent = TRUE;	pend_netevent_wParam=wParam;	pend_netevent_lParam=lParam;	time(&last_movement);	return 0;      case WM_SETFOCUS:	has_focus = TRUE;        CreateCaret(hwnd, caretbm, 0, 0);        ShowCaret(hwnd);	term_out();	term_update();	break;      case WM_KILLFOCUS:	has_focus = FALSE;        DestroyCaret();	term_out();	term_update();	break;      case WM_IGNORE_SIZE:	ignore_size = TRUE;	       /* don't panic on next WM_SIZE msg */	break;      case WM_ENTERSIZEMOVE:        EnableSizeTip(1);        resizing = TRUE;        break;      case WM_EXITSIZEMOVE:        EnableSizeTip(0);        resizing = FALSE;        back->size();        break;      case WM_SIZING:	{	    int width, height, w, h, ew, eh;	    LPRECT r = (LPRECT)lParam;	    width = r->right - r->left - extra_width;	    height = r->bottom - r->top - extra_height;	    w = (width + font_width/2) / font_width; if (w < 1) w = 1;	    h = (height + font_height/2) / font_height; if (h < 1) h = 1;            UpdateSizeTip(hwnd, w, h);	    ew = width - w * font_width;	    eh = height - h * font_height;	    if (ew != 0) {		if (wParam == WMSZ_LEFT ||		    wParam == WMSZ_BOTTOMLEFT ||		    wParam == WMSZ_TOPLEFT)		    r->left += ew;		else		    r->right -= ew;	    }	    if (eh != 0) {		if (wParam == WMSZ_TOP ||		    wParam == WMSZ_TOPRIGHT ||		    wParam == WMSZ_TOPLEFT)		    r->top += eh;		else		    r->bottom -= eh;	    }	    if (ew || eh)		return 1;	    else		return 0;	}        /* break;  (never reached) */      case WM_SIZE:	if (wParam == SIZE_MINIMIZED) {	    SetWindowText (hwnd,			   cfg.win_name_always ? window_name : icon_name);	    break;	}	if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)	    SetWindowText (hwnd, window_name);	if (!ignore_size) {	    int width, height, w, h;#if 0 /* we have fixed this using WM_SIZING now */            int ew, eh;#endif	    width = LOWORD(lParam);	    height = HIWORD(lParam);	    w = width / font_width; if (w < 1) w = 1;	    h = height / font_height; if (h < 1) h = 1;#if 0 /* we have fixed this using WM_SIZING now */	    ew = width - w * font_width;	    eh = height - h * font_height;	    if (ew != 0 || eh != 0) {		RECT r;		GetWindowRect (hwnd, &r);		SendMessage (hwnd, WM_IGNORE_SIZE, 0, 0);		SetWindowPos (hwnd, NULL, 0, 0,			      r.right - r.left - ew, r.bottom - r.top - eh,			      SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);	    }#endif	    if (w != cols || h != rows || just_reconfigged) {		term_invalidate();		term_size (h, w, cfg.savelines);                /*                 * Don't call back->size in mid-resize. (To prevent                 * massive numbers of resize events getting sent                 * down the connection during an NT opaque drag.)                 */                if (!resizing)                    back->size();		just_reconfigged = FALSE;	    }	}	ignore_size = FALSE;	return 0;      case WM_VSCROLL:	switch (LOWORD(wParam)) {	  case SB_BOTTOM: term_scroll(-1, 0); break;	  case SB_TOP: term_scroll(+1, 0); break;	  case SB_LINEDOWN: term_scroll (0, +1); break;	  case SB_LINEUP: term_scroll (0, -1); break;	  case SB_PAGEDOWN: term_scroll (0, +rows/2); break;	  case SB_PAGEUP: term_scroll (0, -rows/2); break;	  case SB_THUMBPOSITION: case SB_THUMBTRACK:	    term_scroll (1, HIWORD(wParam)); break;	}	break;      case WM_PALETTECHANGED:	if ((HWND) wParam != hwnd && pal != NULL) {	    HDC hdc = get_ctx();	    if (hdc) {		if (RealizePalette (hdc) > 0)		    UpdateColors (hdc);		free_ctx (hdc);	    }	}	break;      case WM_QUERYNEWPALETTE:	if (pal != NULL) {	    HDC hdc = get_ctx();	    if (hdc) {		if (RealizePalette (hdc) > 0)		    UpdateColors (hdc);		free_ctx (hdc);		return TRUE;	    }	}	return FALSE;      case WM_KEYDOWN:      case WM_SYSKEYDOWN:      case WM_KEYUP:      case WM_SYSKEYUP:	/*	 * Add the scan code and keypress timing to the random	 * number noise, if we're using ssh.	 */	if (cfg.protocol == PROT_SSH)	    noise_ultralight(lParam);	/*	 * We don't do TranslateMessage since it disassociates the	 * resulting CHAR message from the KEYDOWN that sparked it,	 * which we occasionally don't want. Instead, we process	 * KEYDOWN, and call the Win32 translator functions so that	 * we get the translations under _our_ control.	 */	{	    unsigned char buf[20];	    int len;	    len = TranslateKey (message, wParam, lParam, buf);	    if (len == -1)		return DefWindowProc (hwnd, message, wParam, lParam);	    ldisc->send (buf, len);	}	return 0;      case WM_CHAR:      case WM_SYSCHAR:	/*	 * Nevertheless, we are prepared to deal with WM_CHAR	 * messages, should they crop up. So if someone wants to	 * post the things to us as part of a macro manoeuvre,	 * we're ready to cope.	 */	{	    char c = xlat_kbd2tty((unsigned char)wParam);	    ldisc->send (&c, 1);	}	return 0;    }    return DefWindowProc (hwnd, message, wParam, lParam);}