X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/5321c0c69fbb8966982687d208ffc5f0c17ba191..43e95114cbfc44a5d3a6f1adeff986cb5cd12f78:/windows/window.c diff --git a/windows/window.c b/windows/window.c index 98b35105..8448ca34 100644 --- a/windows/window.c +++ b/windows/window.c @@ -108,6 +108,7 @@ static void *backhandle; static struct unicode_data ucsdata; static int session_closed; +static int reconfiguring = FALSE; static const struct telnet_special *specials; static int n_specials; @@ -299,6 +300,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) int guess_width, guess_height; hinst = inst; + hwnd = NULL; flags = FLAG_VERBOSE | FLAG_INTERACTIVE; sk_init(); @@ -340,13 +342,13 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if (p && p >= r) r = p+1; q = strrchr(b, ':'); if (q && q >= r) r = q+1; - strcpy(r, "putty.hlp"); + strcpy(r, PUTTY_HELP_FILE); if ( (fp = fopen(b, "r")) != NULL) { help_path = dupstr(b); fclose(fp); } else help_path = NULL; - strcpy(r, "putty.cnt"); + strcpy(r, PUTTY_HELP_CONTENTS); if ( (fp = fopen(b, "r")) != NULL) { help_has_contents = TRUE; fclose(fp); @@ -436,28 +438,50 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) i++; /* skip next argument */ } else if (ret == 1) { continue; /* nothing further needs doing */ - } else if (!strcmp(p, "-cleanup")) { + } else if (!strcmp(p, "-cleanup") || + !strcmp(p, "-cleanup-during-uninstall")) { /* * `putty -cleanup'. Remove all registry * entries associated with PuTTY, and also find * and delete the random seed file. */ char *s1, *s2; - s1 = dupprintf("This procedure will remove ALL Registry\n" - "entries associated with %s, and will\n" - "also remove the random seed file.\n" - "\n" - "THIS PROCESS WILL DESTROY YOUR SAVED\n" - "SESSIONS. Are you really sure you want\n" - "to continue?", appname); - s2 = dupprintf("%s Warning", appname); - if (MessageBox(NULL, s1, s2, - MB_YESNO | MB_ICONWARNING) == IDYES) { + /* Are we being invoked from an uninstaller? */ + if (!strcmp(p, "-cleanup-during-uninstall")) { + s1 = dupprintf("Remove saved sessions and random seed file?\n" + "\n" + "If you hit Yes, ALL Registry entries associated\n" + "with %s will be removed, as well as the\n" + "random seed file. THIS PROCESS WILL\n" + "DESTROY YOUR SAVED SESSIONS.\n" + "(This only affects the currently logged-in user.)\n" + "\n" + "If you hit No, uninstallation will proceed, but\n" + "saved sessions etc will be left on the machine.", + appname); + s2 = dupprintf("%s Uninstallation", appname); + } else { + s1 = dupprintf("This procedure will remove ALL Registry entries\n" + "associated with %s, and will also remove\n" + "the random seed file. (This only affects the\n" + "currently logged-in user.)\n" + "\n" + "THIS PROCESS WILL DESTROY YOUR SAVED SESSIONS.\n" + "Are you really sure you want to continue?", + appname); + s2 = dupprintf("%s Warning", appname); + } + if (message_box(s1, s2, + MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, + HELPCTXID(option_cleanup)) == IDYES) { cleanup_all(); } sfree(s1); sfree(s2); exit(0); + } else if (!strcmp(p, "-pgpfp")) { + pgp_fingerprints(); + exit(1); } else if (*p != '-') { char *q = p; if (got_host) { @@ -597,8 +621,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) RegisterClass(&wndclass); } - hwnd = NULL; - memset(&ucsdata, 0, sizeof(ucsdata)); cfgtopalette(); @@ -1274,24 +1296,11 @@ static void init_fonts(int pick_width, int pick_height) f(FONT_NORMAL, cfg.font.charset, fw_dontcare, FALSE); - lfont.lfHeight = font_height; - lfont.lfWidth = font_width; - lfont.lfEscapement = 0; - lfont.lfOrientation = 0; - lfont.lfWeight = fw_dontcare; - lfont.lfItalic = FALSE; - lfont.lfUnderline = FALSE; - lfont.lfStrikeOut = FALSE; - lfont.lfCharSet = cfg.font.charset; - lfont.lfOutPrecision = OUT_DEFAULT_PRECIS; - lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lfont.lfQuality = DEFAULT_QUALITY; - lfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; - strncpy(lfont.lfFaceName, cfg.font.name, LF_FACESIZE); - SelectObject(hdc, fonts[FONT_NORMAL]); GetTextMetrics(hdc, &tm); + GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont); + if (pick_width == 0 || pick_height == 0) { font_height = tm.tmHeight; font_width = tm.tmAveCharWidth; @@ -1860,7 +1869,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (!cfg.warn_on_close || session_closed || MessageBox(hwnd, "Are you sure you want to close this session?", - str, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2) + str, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1) == IDOK) DestroyWindow(hwnd); sfree(str); @@ -1883,6 +1892,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, char b[2048]; char c[30], *cl; int freecl = FALSE; + BOOL inherit_handles; STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE filemap = NULL; @@ -1911,6 +1921,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, UnmapViewOfFile(p); } } + inherit_handles = TRUE; sprintf(c, "putty &%p", filemap); cl = c; } else if (wParam == IDM_SAVEDSESS) { @@ -1920,11 +1931,14 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, char *session = sesslist.sessions[sessno]; /* XXX spaces? quotes? "-load"? */ cl = dupprintf("putty @%s", session); + inherit_handles = FALSE; freecl = TRUE; } else break; - } else + } else /* IDM_NEWSESS */ { cl = NULL; + inherit_handles = FALSE; + } GetModuleFileName(NULL, b, sizeof(b) - 1); si.cb = sizeof(si); @@ -1934,7 +1948,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, si.dwFlags = 0; si.cbReserved2 = 0; si.lpReserved2 = NULL; - CreateProcess(b, cl, NULL, NULL, TRUE, + CreateProcess(b, cl, NULL, NULL, inherit_handles, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); if (filemap) @@ -1954,11 +1968,20 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, { Config prev_cfg; int init_lvl = 1; + int reconfig_result; + + if (reconfiguring) + break; + else + reconfiguring = TRUE; GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle)); prev_cfg = cfg; - if (!do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0)) + reconfig_result = + do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0); + reconfiguring = FALSE; + if (!reconfig_result) break; { @@ -2337,12 +2360,44 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, RealizePalette(hdc); } + /* + * We have to be careful about term_paint(). It will + * set a bunch of character cells to INVALID and then + * call do_paint(), which will redraw those cells and + * _then mark them as done_. This may not be accurate: + * when painting in WM_PAINT context we are restricted + * to the rectangle which has just been exposed - so if + * that only covers _part_ of a character cell and the + * rest of it was already visible, that remainder will + * not be redrawn at all. Accordingly, we must not + * paint any character cell in a WM_PAINT context which + * already has a pending update due to terminal output. + * The simplest solution to this - and many, many + * thanks to Hung-Te Lin for working all this out - is + * not to do any actual painting at _all_ if there's a + * pending terminal update: just mark the relevant + * character cells as INVALID and wait for the + * scheduled full update to sort it out. + * + * I have a suspicion this isn't the _right_ solution. + * An alternative approach would be to have terminal.c + * separately track what _should_ be on the terminal + * screen and what _is_ on the terminal screen, and + * have two completely different types of redraw (one + * for full updates, which syncs the former with the + * terminal itself, and one for WM_PAINT which syncs + * the latter with the former); yet another possibility + * would be to have the Windows front end do what the + * GTK one already does, and maintain a bitmap of the + * current terminal appearance so that WM_PAINT becomes + * completely trivial. However, this should do for now. + */ term_paint(term, 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, - TRUE); + !term->window_update_pending); if (p.fErase || p.rcPaint.left < offset_width || @@ -2679,13 +2734,15 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, 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); + if (wParam == VK_PROCESSKEY) { /* IME PROCESS key */ + if (message == WM_KEYDOWN) { + MSG m; + m.hwnd = hwnd; + m.message = WM_KEYDOWN; + m.wParam = wParam; + m.lParam = lParam & 0xdfff; + TranslateMessage(&m); + } else break; /* pass to Windows for default processing */ } else { len = TranslateKey(message, wParam, lParam, buf); if (len == -1) @@ -2723,12 +2780,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, set_input_locale((HKL)lParam); sys_cursor_update(); break; - case WM_IME_NOTIFY: - if(wParam == IMN_SETOPENSTATUS) { + case WM_IME_STARTCOMPOSITION: + { HIMC hImc = ImmGetContext(hwnd); ImmSetCompositionFont(hImc, &lfont); ImmReleaseContext(hwnd, hImc); - return 0; } break; case WM_IME_COMPOSITION: @@ -2869,6 +2925,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } } + /* + * Any messages we don't process completely above are passed through to + * DefWindowProc() for default processing. + */ return DefWindowProc(hwnd, message, wParam, lParam); }