X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/4a0b6d6164ce80aa9c7b160080e2995eec2fa2ce..62ddb51e0424dd4bd1098b024f2427959aefc729:/windows/window.c diff --git a/windows/window.c b/windows/window.c index d58111fd..a2ef1bf0 100644 --- a/windows/window.c +++ b/windows/window.c @@ -100,7 +100,10 @@ static int offset_width, offset_height; static int was_zoomed = 0; static int prev_rows, prev_cols; -static void enact_netevent(WPARAM, LPARAM); +static int pending_netevent = 0; +static WPARAM pend_netevent_wParam = 0; +static LPARAM pend_netevent_lParam = 0; +static void enact_pending_netevent(void); static void flash_window(int mode); static void sys_cursor_update(void); static int is_shift_pressed(void); @@ -272,6 +275,7 @@ static void start_backend(void) DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); } + must_close_session = FALSE; session_closed = FALSE; } @@ -344,31 +348,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)) wm_mousewheel = RegisterWindowMessage("MSWHEEL_ROLLMSG"); - /* - * See if we can find our Help file. - */ - { - char b[2048], *p, *q, *r; - FILE *fp; - GetModuleFileName(NULL, b, sizeof(b) - 1); - r = b; - p = strrchr(b, '\\'); - if (p && p >= r) r = p+1; - q = strrchr(b, ':'); - if (q && q >= r) r = q+1; - strcpy(r, PUTTY_HELP_FILE); - if ( (fp = fopen(b, "r")) != NULL) { - help_path = dupstr(b); - fclose(fp); - } else - help_path = NULL; - strcpy(r, PUTTY_HELP_CONTENTS); - if ( (fp = fopen(b, "r")) != NULL) { - help_has_contents = TRUE; - fclose(fp); - } else - help_has_contents = FALSE; - } + init_help(); /* * Process the command line. @@ -786,7 +766,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) AppendMenu(m, (cfg.resize_action == RESIZE_DISABLED) ? MF_GRAYED : MF_ENABLED, IDM_FULLSCREEN, "&Full Screen"); AppendMenu(m, MF_SEPARATOR, 0, 0); - if (help_path) + if (has_help()) AppendMenu(m, MF_ENABLED, IDM_HELP, "&Help"); str = dupprintf("&About %s", appname); AppendMenu(m, MF_ENABLED, IDM_ABOUT, str); @@ -831,7 +811,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) sfree(handles); if (must_close_session) close_session(); - continue; } sfree(handles); @@ -855,6 +834,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* The messages seem unreliable; especially if we're being tricky */ term_set_focus(term, GetForegroundWindow() == hwnd); + if (pending_netevent) + enact_pending_netevent(); + net_pending_errors(); } @@ -883,6 +865,7 @@ void cleanup_exit(int code) crypto_wrapup(); #endif } + shutdown_help(); exit(code); } @@ -986,7 +969,7 @@ void update_specials_menu(void *frontend) for (j = 0; j < lenof(popup_menus); j++) { if (specials_menu) { /* XXX does this free up all submenus? */ - DeleteMenu(popup_menus[j].menu, specials_menu, MF_BYCOMMAND); + DeleteMenu(popup_menus[j].menu, (UINT)specials_menu, MF_BYCOMMAND); DeleteMenu(popup_menus[j].menu, IDM_SPECIALSEP, MF_BYCOMMAND); } if (new_menu) { @@ -1096,7 +1079,7 @@ void cmdline_error(char *fmt, ...) /* * Actually do the job requested by a WM_NETEVENT */ -static void enact_netevent(WPARAM wParam, LPARAM lParam) +static void enact_pending_netevent(void) { static int reentering = 0; extern int select_result(WPARAM, LPARAM); @@ -1104,8 +1087,10 @@ static void enact_netevent(WPARAM wParam, LPARAM lParam) if (reentering) return; /* don't unpend the pending */ + pending_netevent = FALSE; + reentering = 1; - select_result(wParam, lParam); + select_result(pend_netevent_wParam, pend_netevent_lParam); reentering = 0; } @@ -1260,6 +1245,89 @@ static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc, } /* + * The exact_textout() wrapper, unfortunately, destroys the useful + * Windows `font linking' behaviour: automatic handling of Unicode + * code points not supported in this font by falling back to a font + * which does contain them. Therefore, we adopt a multi-layered + * approach: for any potentially-bidi text, we use exact_textout(), + * and for everything else we use a simple ExtTextOut as we did + * before exact_textout() was introduced. + */ +static void general_textout(HDC hdc, int x, int y, CONST RECT *lprc, + unsigned short *lpString, UINT cbCount, + CONST INT *lpDx, int opaque) +{ + int i, j, xp, xn; + RECT newrc; + +#ifdef FIXME_REMOVE_BEFORE_CHECKIN +int k; +debug(("general_textout: %d,%d", x, y)); +for(k=0;kleft, lprc->top, lprc->right, lprc->bottom)); +debug(("\n")); +#endif + + xp = xn = x; + + for (i = 0; i < (int)cbCount ;) { + int rtl = is_rtl(lpString[i]); + + xn += lpDx[i]; + + for (j = i+1; j < (int)cbCount; j++) { + if (rtl != is_rtl(lpString[j])) + break; + xn += lpDx[j]; + } + + /* + * Now [i,j) indicates a maximal substring of lpString + * which should be displayed using the same textout + * function. + */ + if (rtl) { + newrc.left = lprc->left + xp - x; + newrc.right = lprc->left + xn - x; + newrc.top = lprc->top; + newrc.bottom = lprc->bottom; +#ifdef FIXME_REMOVE_BEFORE_CHECKIN +{ +int k; +debug((" exact_textout: %d,%d", xp, y)); +for(k=0;kleft + xp - x; + newrc.right = lprc->left + xn - x; + newrc.top = lprc->top; + newrc.bottom = lprc->bottom; + ExtTextOutW(hdc, xp, y, ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0), + &newrc, lpString+i, j-i, lpDx+i); + } + + i = j; + xp = xn; + } + +#ifdef FIXME_REMOVE_BEFORE_CHECKIN +debug(("general_textout: done, xn=%d\n", xn)); +#endif + assert(xn - x == lprc->right - lprc->left); +} + +/* * Initialise all the fonts we will need initially. There may be as many as * three or as few as one. The other (poentially) twentyone fonts are done * if/when they are needed. @@ -1983,7 +2051,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } else if (wParam == IDM_SAVEDSESS) { unsigned int sessno = ((lParam - IDM_SAVED_MIN) / MENU_SAVED_STEP) + 1; - if (sessno < sesslist.nsessions) { + if (sessno < (unsigned)sesslist.nsessions) { char *session = sesslist.sessions[sessno]; /* XXX spaces? quotes? "-load"? */ cl = dupprintf("putty @%s", session); @@ -2192,8 +2260,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, showabout(hwnd); break; case IDM_HELP: - WinHelp(hwnd, help_path, - help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0); + launch_help(hwnd, NULL); break; case SC_MOUSEMENU: /* @@ -2505,7 +2572,19 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } return 0; case WM_NETEVENT: - enact_netevent(wParam, lParam); + /* 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(); + net_pending_errors(); return 0; case WM_SETFOCUS: @@ -3294,12 +3373,8 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, wbuf[i] = text[i]; /* print Glyphs as they are, without Windows' Shaping*/ - exact_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, - &line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING)); -/* ExtTextOutW(hdc, x, - y - font_height * (lattr == LATTR_BOT) + text_adjust, - ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx); - */ + general_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust, + &line_box, wbuf, len, IpDx, !(attr & TATTR_COMBINING)); /* And the shadow bold hack. */ if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {