X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/c9def1b8e8960113ab4fd91d0b69d5b422cf339f..8d5de7770cde9b808c276bd86a0214189a8f7578:/window.c diff --git a/window.c b/window.c index 5acddc72..b4971232 100644 --- a/window.c +++ b/window.c @@ -36,6 +36,7 @@ #define WM_IGNORE_SIZE (WM_XUSER + 1) #define WM_IGNORE_CLIP (WM_XUSER + 2) +#define WM_IGNORE_KEYMENU (WM_XUSER + 3) static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output); @@ -59,6 +60,7 @@ static void enact_pending_netevent(void); #define FONT_OEMBOLDUND 6 #define FONT_OEMUND 7 static HFONT fonts[8]; +static int font_needs_hand_underlining; static enum { BOLD_COLOURS, BOLD_SHADOW, BOLD_FONT } bold_mode; @@ -89,6 +91,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { int guess_width, guess_height; putty_inst = inst; + flags = FLAG_VERBOSE | FLAG_INTERACTIVE; winsock_ver = MAKEWORD(1, 1); if (WSAStartup(winsock_ver, &wsadata)) { @@ -174,14 +177,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { } else if (*p) { char *q = p; /* - * If the hostname starts with "telnet://", set the + * If the hostname starts with "telnet:", set the * protocol to Telnet and process the string as a * Telnet URL. */ - if (!strncmp(q, "telnet://", 9)) { + if (!strncmp(q, "telnet:", 7)) { char c; - q += 9; + q += 7; + if (q[0] == '/' && q[1] == '/') + q += 2; cfg.protocol = PROT_TELNET; p = q; while (*p && *p != ':' && *p != '/') p++; @@ -516,12 +521,39 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { } /* + * Print a message box and close the connection. + */ +void connection_fatal(char *fmt, ...) { + va_list ap; + char stuff[200]; + + va_start(ap, fmt); + vsprintf(stuff, fmt, ap); + va_end(ap); + MessageBox(hwnd, stuff, "PuTTY Fatal Error", MB_ICONERROR | MB_OK); + if (cfg.close_on_exit) + PostQuitMessage(1); + else { + session_closed = TRUE; + SetWindowText (hwnd, "PuTTY (inactive)"); + } +} + +/* * Actually do the job requested by a WM_NETEVENT */ static void enact_pending_netevent(void) { int i; + static int reentering = 0; + + if (reentering) + return; /* don't unpend the pending */ + pending_netevent = FALSE; + + reentering = 1; i = back->msg (pend_netevent_wParam, pend_netevent_lParam); + reentering = 0; if (i < 0) { char buf[1024]; @@ -533,10 +565,9 @@ static void enact_pending_netevent(void) { sprintf(buf, "Unexpected network error %d", -i); break; } - MessageBox(hwnd, buf, "PuTTY Fatal Error", - MB_ICONERROR | MB_OK); - PostQuitMessage(1); - } else if (i == 0) { + connection_fatal(buf); + } + if (i <= 0) { if (cfg.close_on_exit) PostQuitMessage(0); else { @@ -667,6 +698,50 @@ font_messup: f(FONT_UNDERLINE, cfg.fontcharset, fw_dontcare, TRUE); + /* + * Some fonts, e.g. 9-pt Courier, draw their underlines + * outside their character cell. We successfully prevent + * screen corruption by clipping the text output, but then + * we lose the underline completely. Here we try to work + * out whether this is such a font, and if it is, we set a + * flag that causes underlines to be drawn by hand. + * + * Having tried other more sophisticated approaches (such + * as examining the TEXTMETRIC structure or requesting the + * height of a string), I think we'll do this the brute + * force way: we create a small bitmap, draw an underlined + * space on it, and test to see whether any pixels are + * foreground-coloured. (Since we expect the underline to + * go all the way across the character cell, we only search + * down a single column of the bitmap, half way across.) + */ + { + HDC und_dc; + HBITMAP und_bm, und_oldbm; + int i, gotit; + COLORREF c; + + und_dc = CreateCompatibleDC(hdc); + und_bm = CreateCompatibleBitmap(hdc, font_width, font_height); + und_oldbm = SelectObject(und_dc, und_bm); + SelectObject(und_dc, fonts[FONT_UNDERLINE]); + SetTextAlign(und_dc, TA_TOP | TA_LEFT | TA_NOUPDATECP); + SetTextColor (und_dc, RGB(255,255,255)); + SetBkColor (und_dc, RGB(0,0,0)); + SetBkMode (und_dc, OPAQUE); + ExtTextOut (und_dc, 0, 0, ETO_OPAQUE, NULL, " ", 1, NULL); + gotit = FALSE; + for (i = 0; i < font_height; i++) { + c = GetPixel(und_dc, font_width/2, i); + if (c != RGB(0,0,0)) + gotit = TRUE; + } + SelectObject(und_dc, und_oldbm); + DeleteObject(und_bm); + DeleteDC(und_dc); + font_needs_hand_underlining = !gotit; + } + if (bold_mode == BOLD_FONT) { f(FONT_BOLD, cfg.fontcharset, fw_bold, FALSE); f(FONT_BOLDUND, cfg.fontcharset, fw_bold, TRUE); @@ -852,6 +927,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, HDC hdc; static int ignore_size = FALSE; static int ignore_clip = FALSE; + static int ignore_keymenu = TRUE; static int just_reconfigged = FALSE; switch (message) { @@ -876,6 +952,10 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, return 0; case WM_SYSCOMMAND: switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */ + case SC_KEYMENU: + if (ignore_keymenu) + return 0; /* don't put up system menu on Alt */ + break; case IDM_SHOWLOG: showeventlog(hwnd); break; @@ -1105,6 +1185,9 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, case WM_IGNORE_CLIP: ignore_clip = wParam; /* don't panic on DESTROYCLIPBOARD */ break; + case WM_IGNORE_KEYMENU: + ignore_keymenu = wParam; /* do or don't ignore SC_KEYMENU */ + break; case WM_DESTROYCLIPBOARD: if (!ignore_clip) term_deselect(); @@ -1322,7 +1405,7 @@ void do_text (Context ctx, int x, int y, char *text, int len, RECT line_box; int force_manual_underline = 0; int fnt_width = font_width*(1+(lattr!=LATTR_NORM)); -static int *IpDx = 0, IpDxLEN = 0;; + static int *IpDx = 0, IpDxLEN = 0;; if (len>IpDxLEN || IpDx[0] != fnt_width) { int i; @@ -1465,6 +1548,8 @@ static int *IpDx = 0, IpDxLEN = 0;; nfont &= ~(FONT_BOLD|FONT_UNDERLINE); } + if (font_needs_hand_underlining && (attr & ATTR_UNDER)) + force_manual_underline = 1; if (attr & ATTR_REVERSE) { t = nfg; nfg = nbg; nbg = t; } @@ -1692,19 +1777,22 @@ static WPARAM compose_key = 0; /* 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; + 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; + SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); + return 0; } if (left_alt && wParam == VK_F4 && cfg.alt_f4) { - return -1; + return -1; } if (left_alt && wParam == VK_SPACE && cfg.alt_space) { - SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); - return -1; + + SendMessage (hwnd, WM_IGNORE_KEYMENU, FALSE, 0); + SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); + SendMessage (hwnd, WM_IGNORE_KEYMENU, TRUE, 0); + return -1; } /* Nethack keypad */ @@ -1728,7 +1816,7 @@ static WPARAM compose_key = 0; if ( cfg.funky_type == 0 || ( cfg.funky_type == 1 && app_keypad_keys)) switch(wParam) { - case VK_EXECUTE: xkey = 'P'; break; + case VK_EXECUTE: if (app_keypad_keys) xkey = 'P'; break; case VK_DIVIDE: xkey = 'Q'; break; case VK_MULTIPLY:xkey = 'R'; break; case VK_SUBTRACT:xkey = 'S'; break;