X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/a655127470fd533cf892f3b554ee93618bb4b74d..d7e526bfcbb8d0dd2781e13b0494908bcc5909ab:/windows/window.c?ds=sidebyside diff --git a/windows/window.c b/windows/window.c index 40c69e54..3d865e7f 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; static const struct telnet_special *specials; static int n_specials; @@ -1901,6 +1902,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; @@ -1929,6 +1931,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) { @@ -1938,11 +1941,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); @@ -1952,7 +1958,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) @@ -1973,6 +1979,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, Config prev_cfg; int init_lvl = 1; + if (reconfiguring) + break; + else + reconfiguring = TRUE; + GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle)); prev_cfg = cfg; @@ -2109,6 +2120,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, InvalidateRect(hwnd, NULL, TRUE); reset_window(init_lvl); net_pending_errors(); + reconfiguring = FALSE; } break; case IDM_COPYALL: @@ -2355,12 +2367,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 ||