if (GetCapture() != hwnd)
if (GetCapture() != hwnd || (send_raw_mouse && !(cfg.mouse_override && is_shift_pressed())))
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,				WPARAM wParam, LPARAM lParam){    HDC hdc;    static int ignore_clip = FALSE;    static int need_backend_resize = FALSE;    static int fullscr_on_max = FALSE;    switch (message) {      case WM_TIMER:	if (pending_netevent)	    enact_pending_netevent();	if (GetCapture() != hwnd)	    term_out();	noise_regular();	HideCaret(hwnd);	term_update();	ShowCaret(hwnd);	if (cfg.ping_interval > 0) {	    time_t now;	    time(&now);	    if (now - last_movement > cfg.ping_interval) {		back->special(TS_PING);		last_movement = now;	    }	}	net_pending_errors();	return 0;      case WM_CREATE:	break;      case WM_CLOSE:	show_mouseptr(1);	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:	show_mouseptr(1);	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) {		    if ((lParam - IDM_SAVED_MIN) / 16 < nsessions) {			char *session =			    sessions[(lParam - IDM_SAVED_MIN) / 16];			cl = smalloc(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			break;		} 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)		    sfree(cl);	    }	    break;	  case IDM_RECONF:	    {		Config prev_cfg;		int init_lvl = 1;		GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle));		prev_cfg = cfg;		if (!do_reconfig(hwnd))		    break;		{		    /* Disable full-screen if resizing forbidden */		    HMENU m = GetSystemMenu (hwnd, FALSE);		    EnableMenuItem(m, IDM_FULLSCREEN, MF_BYCOMMAND | 				   (cfg.resize_action == RESIZE_DISABLED)				   ? MF_GRAYED : MF_ENABLED);		    /* Gracefully unzoom if necessary */		    if (IsZoomed(hwnd) &&			(cfg.resize_action == RESIZE_DISABLED)) {			ShowWindow(hwnd, SW_RESTORE);		    }		}		if (strcmp(prev_cfg.logfilename, cfg.logfilename) ||		    prev_cfg.logtype != cfg.logtype) {		    logfclose();       /* reset logging */		    logfopen();		}		sfree(logpal);		/*		 * Flush the line discipline's edit buffer in the		 * case where local editing has just been disabled.		 */		ldisc_send(NULL, 0, 0);		if (pal)		    DeleteObject(pal);		logpal = NULL;		pal = NULL;		cfgtopalette();		init_palette();		/* Give terminal a heads-up on miscellaneous stuff */		term_reconfig();		/* Screen size changed ? */		if (cfg.height != prev_cfg.height ||		    cfg.width != prev_cfg.width ||		    cfg.savelines != prev_cfg.savelines ||		    cfg.resize_action == RESIZE_FONT ||		    (cfg.resize_action == RESIZE_EITHER && IsZoomed(hwnd)) ||		    cfg.resize_action == RESIZE_DISABLED)		    term_size(cfg.height, cfg.width, cfg.savelines);		/* Enable or disable the scroll bar, etc */		{		    LONG nflg, flag = GetWindowLong(hwnd, GWL_STYLE);		    LONG nexflag, exflag =			GetWindowLong(hwnd, GWL_EXSTYLE);		    nexflag = exflag;		    if (cfg.alwaysontop != prev_cfg.alwaysontop) {			if (cfg.alwaysontop) {			    nexflag |= WS_EX_TOPMOST;			    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,					 SWP_NOMOVE | SWP_NOSIZE);			} else {			    nexflag &= ~(WS_EX_TOPMOST);			    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,					 SWP_NOMOVE | SWP_NOSIZE);			}		    }		    if (cfg.sunken_edge)			nexflag |= WS_EX_CLIENTEDGE;		    else			nexflag &= ~(WS_EX_CLIENTEDGE);		    nflg = flag;		    if (is_full_screen() ?			cfg.scrollbar_in_fullscreen : cfg.scrollbar)			nflg |= WS_VSCROLL;		    else			nflg &= ~WS_VSCROLL;		    if (cfg.resize_action == RESIZE_DISABLED ||                        is_full_screen())			nflg &= ~WS_THICKFRAME;		    else			nflg |= WS_THICKFRAME;		    if (cfg.resize_action == RESIZE_DISABLED)			nflg &= ~WS_MAXIMIZEBOX;		    else			nflg |= WS_MAXIMIZEBOX;		    if (nflg != flag || nexflag != exflag) {			if (nflg != flag)			    SetWindowLong(hwnd, GWL_STYLE, nflg);			if (nexflag != exflag)			    SetWindowLong(hwnd, GWL_EXSTYLE, nexflag);			SetWindowPos(hwnd, NULL, 0, 0, 0, 0,				     SWP_NOACTIVATE | SWP_NOCOPYBITS |				     SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |				     SWP_FRAMECHANGED);			init_lvl = 2;		    }		}		/* Oops */		if (cfg.resize_action == RESIZE_DISABLED && IsZoomed(hwnd)) {		    force_normal(hwnd);		    init_lvl = 2;		}		set_title(cfg.wintitle);		if (IsIconic(hwnd)) {		    SetWindowText(hwnd,				  cfg.win_name_always ? window_name :				  icon_name);		}		if (strcmp(cfg.font, prev_cfg.font) != 0 ||		    strcmp(cfg.line_codepage, prev_cfg.line_codepage) != 0 ||		    cfg.fontisbold != prev_cfg.fontisbold ||		    cfg.fontheight != prev_cfg.fontheight ||		    cfg.fontcharset != prev_cfg.fontcharset ||		    cfg.vtmode != prev_cfg.vtmode ||		    cfg.bold_colour != prev_cfg.bold_colour ||		    cfg.resize_action == RESIZE_DISABLED ||		    cfg.resize_action == RESIZE_EITHER ||		    (cfg.resize_action != prev_cfg.resize_action))		    init_lvl = 2;		InvalidateRect(hwnd, NULL, TRUE);		reset_window(init_lvl);		net_pending_errors();	    }	    break;	  case IDM_COPYALL:	    term_copyall();	    break;	  case IDM_CLRSB:	    term_clrsb();	    break;	  case IDM_RESET:	    term_pwron();	    break;	  case IDM_TEL_AYT:	    back->special(TS_AYT);	    net_pending_errors();	    break;	  case IDM_TEL_BRK:	    back->special(TS_BRK);	    net_pending_errors();	    break;	  case IDM_TEL_SYNCH:	    back->special(TS_SYNCH);	    net_pending_errors();	    break;	  case IDM_TEL_EC:	    back->special(TS_EC);	    net_pending_errors();	    break;	  case IDM_TEL_EL:	    back->special(TS_EL);	    net_pending_errors();	    break;	  case IDM_TEL_GA:	    back->special(TS_GA);	    net_pending_errors();	    break;	  case IDM_TEL_NOP:	    back->special(TS_NOP);	    net_pending_errors();	    break;	  case IDM_TEL_ABORT:	    back->special(TS_ABORT);	    net_pending_errors();	    break;	  case IDM_TEL_AO:	    back->special(TS_AO);	    net_pending_errors();	    break;	  case IDM_TEL_IP:	    back->special(TS_IP);	    net_pending_errors();	    break;	  case IDM_TEL_SUSP:	    back->special(TS_SUSP);	    net_pending_errors();	    break;	  case IDM_TEL_EOR:	    back->special(TS_EOR);	    net_pending_errors();	    break;	  case IDM_TEL_EOF:	    back->special(TS_EOF);	    net_pending_errors();	    break;	  case IDM_ABOUT:	    showabout(hwnd);	    break;	  case IDM_HELP:	    WinHelp(hwnd, help_path,                    help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0);	    break;	  case SC_MOUSEMENU:	    /*	     * We get this if the System menu has been activated	     * using the mouse.	     */	    show_mouseptr(1);	    break;          case SC_KEYMENU:	    /*	     * We get this if the System menu has been activated	     * using the keyboard. This might happen from within	     * TranslateKey, in which case it really wants to be	     * followed by a `space' character to actually _bring	     * the menu up_ rather than just sitting there in	     * `ready to appear' state.	     */	    show_mouseptr(1);	       /* make sure pointer is visible */	    if( lParam == 0 )		PostMessage(hwnd, WM_CHAR, ' ', 0);	    break;	  case IDM_FULLSCREEN:	    flip_full_screen();	    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))-offset_width) / font_width)#define TO_CHR_Y(y) ((((y)<0 ? (y)-font_height+1: (y))-offset_height) / font_height)      case WM_LBUTTONDOWN:      case WM_MBUTTONDOWN:      case WM_RBUTTONDOWN:      case WM_LBUTTONUP:      case WM_MBUTTONUP:      case WM_RBUTTONUP:	{	    int button, press;	    switch (message) {	      case WM_LBUTTONDOWN:		button = MBT_LEFT;		press = 1;		break;	      case WM_MBUTTONDOWN:		button = MBT_MIDDLE;		press = 1;		break;	      case WM_RBUTTONDOWN:		button = MBT_RIGHT;		press = 1;		break;	      case WM_LBUTTONUP:		button = MBT_LEFT;		press = 0;		break;	      case WM_MBUTTONUP:		button = MBT_MIDDLE;		press = 0;		break;	      case WM_RBUTTONUP:		button = MBT_RIGHT;		press = 0;		break;	      default:		button = press = 0;    /* shouldn't happen */	    }	    show_mouseptr(1);	    /*	     * Special case: in full-screen mode, if the left	     * button is clicked in the very top left corner of the	     * window, we put up the System menu instead of doing	     * selection.	     */	    if (is_full_screen() && press && button == MBT_LEFT &&		X_POS(lParam) == 0 && Y_POS(lParam) == 0) {		SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, 0);		return 0;	    }	    if (press) {		click(button,		      TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)),		      wParam & MK_SHIFT, wParam & MK_CONTROL,		      is_alt_pressed());		SetCapture(hwnd);	    } else {		term_mouse(button, MA_RELEASE,			   TO_CHR_X(X_POS(lParam)),			   TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT,			   wParam & MK_CONTROL, is_alt_pressed());		ReleaseCapture();	    }	}	return 0;      case WM_MOUSEMOVE:	show_mouseptr(1);	/*	 * Add the mouse position and message time to the random	 * number noise.	 */	noise_ultralight(lParam);	if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) &&	    GetCapture() == hwnd) {	    Mouse_Button b;	    if (wParam & MK_LBUTTON)		b = MBT_LEFT;	    else if (wParam & MK_MBUTTON)		b = MBT_MIDDLE;	    else		b = MBT_RIGHT;	    term_mouse(b, MA_DRAG, TO_CHR_X(X_POS(lParam)),		       TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT,		       wParam & MK_CONTROL, is_alt_pressed());	}	return 0;      case WM_NCMOUSEMOVE:	show_mouseptr(1);	noise_ultralight(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-offset_width)/font_width,		       (p.rcPaint.top-offset_height)/font_height,		       (p.rcPaint.right-offset_width-1)/font_width,		       (p.rcPaint.bottom-offset_height-1)/font_height);	    if (p.fErase ||	        p.rcPaint.left  < offset_width  ||		p.rcPaint.top   < offset_height ||		p.rcPaint.right >= offset_width + font_width*cols ||		p.rcPaint.bottom>= offset_height + font_height*rows)	    {		HBRUSH fillcolour, oldbrush;		HPEN   edge, oldpen;		fillcolour = CreateSolidBrush (				    colours[(ATTR_DEFBG>>ATTR_BGSHIFT)*2]);		oldbrush = SelectObject(hdc, fillcolour);		edge = CreatePen(PS_SOLID, 0, 				    colours[(ATTR_DEFBG>>ATTR_BGSHIFT)*2]);		oldpen = SelectObject(hdc, edge);		ExcludeClipRect(hdc, 			offset_width, offset_height,			offset_width+font_width*cols,			offset_height+font_height*rows);		Rectangle(hdc, p.rcPaint.left, p.rcPaint.top, 			  p.rcPaint.right, p.rcPaint.bottom);		// SelectClipRgn(hdc, NULL);		SelectObject(hdc, oldbrush);		DeleteObject(fillcolour);		SelectObject(hdc, oldpen);		DeleteObject(edge);	    }	    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;	if (WSAGETSELECTEVENT(lParam) != FD_READ)	    enact_pending_netevent();	time(&last_movement);	return 0;      case WM_SETFOCUS:	has_focus = TRUE;	CreateCaret(hwnd, caretbm, font_width, font_height);	ShowCaret(hwnd);	flash_window(0);	       /* stop */	compose_state = 0;	term_out();	term_update();	break;      case WM_KILLFOCUS:	show_mouseptr(1);	has_focus = FALSE;	DestroyCaret();	caret_x = caret_y = -1;	       /* ensure caret is replaced next time */	term_out();	term_update();	break;      case WM_ENTERSIZEMOVE:#ifdef RDB_DEBUG_PATCH	debug((27, "WM_ENTERSIZEMOVE"));#endif	EnableSizeTip(1);	resizing = TRUE;	need_backend_resize = FALSE;	break;      case WM_EXITSIZEMOVE:	EnableSizeTip(0);	resizing = FALSE;#ifdef RDB_DEBUG_PATCH	debug((27, "WM_EXITSIZEMOVE"));#endif	if (need_backend_resize) {	    term_size(cfg.height, cfg.width, cfg.savelines);	    InvalidateRect(hwnd, NULL, TRUE);	}	break;      case WM_SIZING:	/*	 * This does two jobs:	 * 1) Keep the sizetip uptodate	 * 2) Make sure the window size is _stepped_ in units of the font size.	 */	if (cfg.resize_action != RESIZE_FONT && !alt_pressed) {	    int width, height, w, h, ew, eh;	    LPRECT r = (LPRECT) lParam;	    if ( !need_backend_resize && cfg.resize_action == RESIZE_EITHER &&		    (cfg.height != rows || cfg.width != cols )) {		/* 		 * Great! It seems that both the terminal size and the		 * font size have been changed and the user is now dragging.		 * 		 * It will now be difficult to get back to the configured		 * font size!		 *		 * This would be easier but it seems to be too confusing.		term_size(cfg.height, cfg.width, cfg.savelines);		reset_window(2);		 */	        cfg.height=rows; cfg.width=cols;		InvalidateRect(hwnd, NULL, TRUE);		need_backend_resize = TRUE;	    }	    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;	} else {	    int width, height, w, h, rv = 0;	    int ex_width = extra_width + (cfg.window_border - offset_width) * 2;	    int ex_height = extra_height + (cfg.window_border - offset_height) * 2;	    LPRECT r = (LPRECT) lParam;	    width = r->right - r->left - ex_width;	    height = r->bottom - r->top - ex_height;	    w = (width + cols/2)/cols;	    h = (height + rows/2)/rows;	    if ( r->right != r->left + w*cols + ex_width) 		rv = 1;	    if (wParam == WMSZ_LEFT ||		wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_TOPLEFT)		r->left = r->right - w*cols - ex_width;	    else		r->right = r->left + w*cols + ex_width;	    if (r->bottom != r->top + h*rows + ex_height)		rv = 1;	    if (wParam == WMSZ_TOP ||		wParam == WMSZ_TOPRIGHT || wParam == WMSZ_TOPLEFT)		r->top = r->bottom - h*rows - ex_height;	    else		r->bottom = r->top + h*rows + ex_height;	    return rv;	}	/* break;  (never reached) */      case WM_FULLSCR_ON_MAX:	fullscr_on_max = TRUE;	break;      case WM_MOVE:	sys_cursor_update();	break;      case WM_SIZE:#ifdef RDB_DEBUG_PATCH	debug((27, "WM_SIZE %s (%d,%d)",		(wParam == SIZE_MINIMIZED) ? "SIZE_MINIMIZED":		(wParam == SIZE_MAXIMIZED) ? "SIZE_MAXIMIZED":		(wParam == SIZE_RESTORED && resizing) ? "to":		(wParam == SIZE_RESTORED) ? "SIZE_RESTORED":		"...",	    LOWORD(lParam), HIWORD(lParam)));#endif	if (wParam == SIZE_MINIMIZED)	    SetWindowText(hwnd,			  cfg.win_name_always ? window_name : icon_name);	if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)	    SetWindowText(hwnd, window_name);        if (wParam == SIZE_RESTORED)            clear_full_screen();        if (wParam == SIZE_MAXIMIZED && fullscr_on_max) {            make_full_screen();            fullscr_on_max = FALSE;        }	if (cfg.resize_action == RESIZE_DISABLED) {	    /* A resize, well it better be a minimize. */	    reset_window(-1);	} else {	    int width, height, w, h;	    width = LOWORD(lParam);	    height = HIWORD(lParam);	    if (!resizing) {		if (wParam == SIZE_MAXIMIZED && !was_zoomed) {		    was_zoomed = 1;		    prev_rows = rows;		    prev_cols = cols;		    if (cfg.resize_action == RESIZE_TERM) {			w = width / font_width;			if (w < 1) w = 1;			h = height / font_height;			if (h < 1) h = 1;			term_size(h, w, cfg.savelines);		    }		    reset_window(0);		} else if (wParam == SIZE_RESTORED && was_zoomed) {		    was_zoomed = 0;		    if (cfg.resize_action == RESIZE_TERM)			term_size(prev_rows, prev_cols, cfg.savelines);		    if (cfg.resize_action != RESIZE_FONT)			reset_window(2);		    else			reset_window(0);		}		/* This is an unexpected resize, these will normally happen		 * if the window is too large. Probably either the user		 * selected a huge font or the screen size has changed.		 *		 * This is also called with minimize.		 */		else reset_window(-1);	    }	    /*	     * 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) {		if (cfg.resize_action != RESIZE_FONT && !alt_pressed) {		    need_backend_resize = TRUE;		    w = (width-cfg.window_border*2) / font_width;		    if (w < 1) w = 1;		    h = (height-cfg.window_border*2) / font_height;		    if (h < 1) h = 1;		    cfg.height = h;		    cfg.width = w;	        } else 		    reset_window(0);	    }	}	sys_cursor_update();	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.	 */	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;	    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);		if (len != 0) {		    /*		     * Interrupt an ongoing paste. I'm not sure		     * this is sensible, but for the moment it's		     * preferable to having to faff about buffering		     * things.		     */		    term_nopaste();		    /*		     * We need not bother about stdin backlogs		     * here, because in GUI PuTTY we can't do		     * anything about it anyway; there's no means		     * of asking Windows to hold off on KEYDOWN		     * messages. We _have_ to buffer everything		     * we're sent.		     */		    ldisc_send(buf, len, 1);		    show_mouseptr(0);		}	    }	}	net_pending_errors();	return 0;      case WM_INPUTLANGCHANGE:	/* wParam == Font number */	/* lParam == Locale */	set_input_locale((HKL)lParam);	sys_cursor_update();	break;      case WM_IME_NOTIFY:	if(wParam == IMN_SETOPENSTATUS) {	    HIMC hImc = ImmGetContext(hwnd);	    ImmSetCompositionFont(hImc, &lfont);	    ImmReleaseContext(hwnd, hImc);	    return 0;	}	break;      case WM_IME_COMPOSITION:	{	    HIMC hIMC;	    int n;	    char *buff;	    if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || 	        osVersion.dwPlatformId == VER_PLATFORM_WIN32s) break; /* no Unicode */	    if ((lParam & GCS_RESULTSTR) == 0) /* Composition unfinished. */		break; /* fall back to DefWindowProc */	    hIMC = ImmGetContext(hwnd);	    n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);	    if (n > 0) {		int i;		buff = (char*) smalloc(n);		ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);		/*		 * Jaeyoun Chung reports that Korean character		 * input doesn't work correctly if we do a single		 * luni_send() covering the whole of buff. So		 * instead we luni_send the characters one by one.		 */		for (i = 0; i < n; i += 2)		    luni_send((unsigned short *)(buff+i), 1, 1);		free(buff);	    }	    ImmReleaseContext(hwnd, hIMC);	    return 1;	}      case WM_IME_CHAR:	if (wParam & 0xFF00) {	    unsigned char buf[2];	    buf[1] = wParam;	    buf[0] = wParam >> 8;	    lpage_send(kbd_codepage, buf, 2, 1);	} else {	    char c = (unsigned char) wParam;	    lpage_send(kbd_codepage, &c, 1, 1);	}	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 = (unsigned char)wParam;	    lpage_send(CP_ACP, &c, 1, 1);	}	return 0;      case WM_SETCURSOR:	if (send_raw_mouse && LOWORD(lParam) == HTCLIENT) {	    SetCursor(LoadCursor(NULL, IDC_ARROW));	    return TRUE;	}      default:	if (message == wm_mousewheel || message == WM_MOUSEWHEEL) {	    int shift_pressed=0, control_pressed=0, alt_pressed=0;	    if (message == WM_MOUSEWHEEL) {		wheel_accumulator += (short)HIWORD(wParam);		shift_pressed=LOWORD(wParam) & MK_SHIFT;		control_pressed=LOWORD(wParam) & MK_CONTROL;	    } else {		BYTE keys[256];		wheel_accumulator += (int)wParam;		if (GetKeyboardState(keys)!=0) {		    shift_pressed=keys[VK_SHIFT]&0x80;		    control_pressed=keys[VK_CONTROL]&0x80;		}	    }	    /* process events when the threshold is reached */	    while (abs(wheel_accumulator) >= WHEEL_DELTA) {		int b;		/* reduce amount for next time */		if (wheel_accumulator > 0) {		    b = MBT_WHEEL_UP;		    wheel_accumulator -= WHEEL_DELTA;		} else if (wheel_accumulator < 0) {		    b = MBT_WHEEL_DOWN;		    wheel_accumulator += WHEEL_DELTA;		} else		    break;		if (send_raw_mouse &&		    !(cfg.mouse_override && shift_pressed)) {		    /* send a mouse-down followed by a mouse up */		    term_mouse(b,			       MA_CLICK,			       TO_CHR_X(X_POS(lParam)),			       TO_CHR_Y(Y_POS(lParam)), shift_pressed,			       control_pressed, is_alt_pressed());		    term_mouse(b, MA_RELEASE, TO_CHR_X(X_POS(lParam)),			       TO_CHR_Y(Y_POS(lParam)), shift_pressed,			       control_pressed, is_alt_pressed());		} else {		    /* trigger a scroll */		    term_scroll(0,				b == MBT_WHEEL_UP ? -rows / 2 : rows / 2);		}	    }	    return 0;	}    }    return DefWindowProc(hwnd, message, wParam, lParam);}