From ab12fd427770141dda8c18a3e3d2a9fa7de7ae05 Mon Sep 17 00:00:00 2001 From: Neil Date: Tue, 18 Mar 2025 13:55:46 +1100 Subject: Set autocompletion list width by measuring each item to find the widest instead of using an approximation which was sometimes wrong, clipping long items. --- win32/PlatWin.cxx | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 8dae4867d..e7ebf01c3 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -3323,13 +3323,12 @@ class ListBoxX : public ListBox { bool unicodeMode = false; int codePage = 0; int desiredVisibleRows = 9; - unsigned int maxItemCharacters = 0; + int maxItemCharacters = 0; unsigned int aveCharWidth = 8; Window *parent = nullptr; int ctrlID = 0; UINT dpi = USER_DEFAULT_SCREEN_DPI; IListBoxDelegate *delegate = nullptr; - const char *widestItem = nullptr; unsigned int maxCharWidth = 1; WPARAM resizeHit = 0; PRectangle rcPreSize; @@ -3472,22 +3471,26 @@ PRectangle ListBoxX::GetDesiredRect() { int width = MinClientWidth(); int textSize = 0; - int len = 0; int averageCharWidth = 8; - if (widestItem) { - len = static_cast(strlen(widestItem)); - // Make a measuring surface - std::unique_ptr surfaceItem(Surface::Allocate(technology)); - surfaceItem->Init(GetID()); - surfaceItem->SetMode(SurfaceMode(codePage, false)); - textSize = static_cast(std::ceil(surfaceItem->WidthText(fontWin.get(), widestItem))); - maxCharWidth = static_cast(std::ceil(surfaceItem->WidthText(fontWin.get(), "W"))); - averageCharWidth = static_cast(surfaceItem->AverageCharWidth(fontWin.get())); + + // Make a measuring surface + std::unique_ptr surfaceItem(Surface::Allocate(technology)); + surfaceItem->Init(GetID()); + surfaceItem->SetMode(SurfaceMode(codePage, false)); + + // Find the widest item in pixels + const int items = lti.Count(); + for (int i = 0; i < items; i++) { + const ListItemData item = lti.Get(i); + const int itemTextSize = static_cast(std::ceil( + surfaceItem->WidthText(fontWin.get(), item.text))); + textSize = std::max(textSize, itemTextSize); } - const int widthDesired = std::max(textSize, (len + 1) * averageCharWidth); - if (width < widthDesired) - width = widthDesired; + maxCharWidth = static_cast(std::ceil(surfaceItem->WidthText(fontWin.get(), "W"))); + averageCharWidth = static_cast(surfaceItem->AverageCharWidth(fontWin.get())); + + width = std::max({ width, textSize, (maxItemCharacters + 1) * averageCharWidth }); rcDesired.right = rcDesired.left + TextOffset() + width + (TextInset.x * 2); if (Length() > rows) @@ -3511,7 +3514,6 @@ int ListBoxX::CaretFromEdge() { void ListBoxX::Clear() noexcept { ListBox_ResetContent(lb); maxItemCharacters = 0; - widestItem = nullptr; lti.Clear(); } @@ -3645,11 +3647,7 @@ void ListBoxX::AppendListItem(const char *text, const char *numword) { } lti.AllocItem(text, pixId); - const unsigned int len = static_cast(strlen(text)); - if (maxItemCharacters < len) { - maxItemCharacters = len; - widestItem = text; - } + maxItemCharacters = std::max(maxItemCharacters, static_cast(strlen(text))); } void ListBoxX::SetDelegate(IListBoxDelegate *lbDelegate) { -- cgit v1.2.3