From b6d7c81d43a7d54cbdd4dcee75099248227627f9 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 2 Aug 2022 18:34:18 +0100 Subject: [PATCH] Windows Pageant: dynamically size list box columns. The fixed tab stops that we used to use in the old LBS_HASSTRINGS list box, and that I carefully replicated in the new owner-drawn version, are no more! Now, every time we refresh the key list, we actually _measure_ the maximum size of string that needs to fit into each column, and size the columns based on that. Now I don't have to worry any more about whether the set of algorithm names might one day overflow the fixed column width, or whether a particularly unlucky choice of key with lots of wide letters like M and W in its base64-encoded SHA256 hash might do the same. Also, the previous column sizes were pessimistic (for reason of exactly that worry), so this change generally moves things over towards the left of the list box - which means there's now room for longer key comments, and more chance of the suffixes '(encrypted)' or '(re-encryptable)' being visible on the right. --- windows/pageant.c | 58 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/windows/pageant.c b/windows/pageant.c index 05447f5f..accf0ccb 100644 --- a/windows/pageant.c +++ b/windows/pageant.c @@ -313,6 +313,8 @@ void old_keyfile_warning(void) } struct keylist_update_ctx { + HDC hdc; + int algbitswidth, algwidth, bitswidth, hashwidth; bool enable_remove_controls; bool enable_reencrypt_controls; }; @@ -382,6 +384,19 @@ static void keylist_update_callback( put_dataz(disp->comment, comment); + SIZE sz; + if (disp->bits->len) { + GetTextExtentPoint32(ctx->hdc, disp->alg->s, disp->alg->len, &sz); + if (ctx->algwidth < sz.cx) ctx->algwidth = sz.cx; + GetTextExtentPoint32(ctx->hdc, disp->bits->s, disp->bits->len, &sz); + if (ctx->bitswidth < sz.cx) ctx->bitswidth = sz.cx; + } else { + GetTextExtentPoint32(ctx->hdc, disp->alg->s, disp->alg->len, &sz); + if (ctx->algbitswidth < sz.cx) ctx->algbitswidth = sz.cx; + } + GetTextExtentPoint32(ctx->hdc, disp->hash->s, disp->hash->len, &sz); + if (ctx->hashwidth < sz.cx) ctx->hashwidth = sz.cx; + if (ext_flags & LIST_EXTENDED_FLAG_HAS_NO_CLEARTEXT_KEY) { put_fmt(disp->info, "(encrypted)"); } else if (ext_flags & LIST_EXTENDED_FLAG_HAS_ENCRYPTED_KEY_FILE) { @@ -398,6 +413,9 @@ static void keylist_update_callback( LB_ADDSTRING, 0, (LPARAM)disp); } +/* Column start positions for the list box, in pixels (not dialog units). */ +static int colpos_bits, colpos_hash, colpos_comment; + /* * Update the visible key list. */ @@ -430,7 +448,22 @@ void keylist_update(void) struct keylist_update_ctx ctx[1]; ctx->enable_remove_controls = false; ctx->enable_reencrypt_controls = false; + ctx->algbitswidth = ctx->algwidth = 0; + ctx->bitswidth = ctx->hashwidth = 0; + ctx->hdc = GetDC(keylist); + SelectObject(ctx->hdc, (HFONT)SendMessage(keylist, WM_GETFONT, 0, 0)); int status = pageant_enum_keys(keylist_update_callback, ctx, &errmsg); + + SIZE sz; + GetTextExtentPoint32(ctx->hdc, "MM", 2, &sz); + int gutter = sz.cx; + + DeleteDC(ctx->hdc); + colpos_hash = ctx->algwidth + ctx->bitswidth + 2*gutter; + if (colpos_hash < ctx->algbitswidth + gutter) + colpos_hash = ctx->algbitswidth + gutter; + colpos_bits = colpos_hash - ctx->bitswidth - gutter; + colpos_comment = colpos_hash + ctx->hashwidth + gutter; assert(status == PAGEANT_ACTION_OK); assert(!errmsg); @@ -669,20 +702,14 @@ static INT_PTR CALLBACK KeyListProc(HWND hwnd, UINT msg, disp->alg->len, NULL); if (disp->bits->len) { - r.left = r.top = r.bottom = 0; - r.right = 35; - MapDialogRect(hwnd, &r); - ExtTextOut(di->hDC, di->rcItem.left + r.right, di->rcItem.top, - ETO_CLIPPED, &di->rcItem, disp->bits->s, - disp->bits->len, NULL); + ExtTextOut(di->hDC, di->rcItem.left + r.right + colpos_bits, + di->rcItem.top, ETO_CLIPPED, &di->rcItem, + disp->bits->s, disp->bits->len, NULL); } - r.left = r.top = r.bottom = 0; - r.right = 75; - MapDialogRect(hwnd, &r); - ExtTextOut(di->hDC, di->rcItem.left + r.right, di->rcItem.top, - ETO_CLIPPED, &di->rcItem, disp->hash->s, - disp->hash->len, NULL); + ExtTextOut(di->hDC, di->rcItem.left + r.right + colpos_hash, + di->rcItem.top, ETO_CLIPPED, &di->rcItem, + disp->hash->s, disp->hash->len, NULL); strbuf *sb = strbuf_new(); put_datapl(sb, ptrlen_from_strbuf(disp->comment)); @@ -691,11 +718,8 @@ static INT_PTR CALLBACK KeyListProc(HWND hwnd, UINT msg, put_datapl(sb, ptrlen_from_strbuf(disp->info)); } - r.left = r.top = r.bottom = 0; - r.right = 300; - MapDialogRect(hwnd, &r); - TabbedTextOut(di->hDC, di->rcItem.left + r.right, di->rcItem.top, - sb->s, sb->len, 0, NULL, 0); + TabbedTextOut(di->hDC, di->rcItem.left + r.right + colpos_comment, + di->rcItem.top, sb->s, sb->len, 0, NULL, 0); strbuf_free(sb);