click (MB_SELECT, LOWORD(lParam) / font_width, HIWORD(lParam) / font_height);
SetCapture(hwnd); click (MB_SELECT, X_POS(lParam) / font_width, Y_POS(lParam) / font_height);
static int WINAPI 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;    switch (message) {      case WM_CREATE:	break;      case WM_DESTROY:	PostQuitMessage (0);	return 0;      case WM_SYSCOMMAND:	switch (wParam) {	  case IDM_SHOWLOG:	    shownegot(hwnd);	    break;	  case IDM_NEWSESS:	  case IDM_DUPSESS:	    {		char b[2048];		char c[30], *cl;		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 &%08x", filemap);		    cl = c;		} 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);	    }	    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();	    sfree(logpal);	    if (pal)		DeleteObject(pal);	    logpal = NULL;	    pal = NULL;	    cfgtopalette();	    init_palette();	    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;	}	break;      case WM_LBUTTONDOWN:	click (MB_SELECT, LOWORD(lParam) / font_width,	       HIWORD(lParam) / font_height);	return 0;      case WM_LBUTTONUP:	term_mouse (MB_SELECT, MA_RELEASE, LOWORD(lParam) / font_width,		    HIWORD(lParam) / font_height);	return 0;      case WM_MBUTTONDOWN:	click (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,	       LOWORD(lParam) / font_width,	       HIWORD(lParam) / font_height);	return 0;      case WM_MBUTTONUP:	term_mouse (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,		    MA_RELEASE, LOWORD(lParam) / font_width,		    HIWORD(lParam) / font_height);	return 0;      case WM_RBUTTONDOWN:	click (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,	       LOWORD(lParam) / font_width,	       HIWORD(lParam) / font_height);	return 0;      case WM_RBUTTONUP:	term_mouse (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,		    MA_RELEASE, LOWORD(lParam) / font_width,		    HIWORD(lParam) / font_height);	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, LOWORD(lParam) / font_width,			HIWORD(lParam) / font_height);	}	lastbtn = MB_NOTHING;	lastact = MA_NOTHING;	lasttime = GetMessageTime();	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;	    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);	}	return 0;      case WM_NETEVENT:	{	    int i = back->msg (wParam, lParam);	    if (i < 0) {		char buf[1024];		switch (WSABASEERR + (-i) % 10000) {		  case WSAECONNRESET:		    sprintf(buf, "Connection reset by peer");		    break;		  default:		    sprintf(buf, "Unexpected network error %d", -i);		    break;		}		MessageBox(hwnd, buf, "PuTTY Fatal Error",			   MB_ICONERROR | MB_OK);		PostQuitMessage(1);	    } else if (i == 0) {		if (cfg.close_on_exit)		    PostQuitMessage(0);		else {		    MessageBox(hwnd, "Connection closed by remote host",			       "PuTTY", MB_OK | MB_ICONINFORMATION);		    SetWindowText (hwnd, "PuTTY (inactive)");		}	    }	}	return 0;      case WM_SETFOCUS:	has_focus = TRUE;	term_out();	term_update();	break;      case WM_KILLFOCUS:	has_focus = FALSE;	term_out();	term_update();	break;      case WM_IGNORE_SIZE:	ignore_size = TRUE;	       /* don't panic on next WM_SIZE msg */	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;	    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;      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, ew, eh;	    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);		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:	/*	 * 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 (wParam, lParam, buf);	    back->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 = wParam;	    back->send (&c, 1);	}	return 0;    }    return DefWindowProc (hwnd, message, wParam, lParam);}