Nikolay Sivov : wordpad: Fill font selection combobox with fully processed font list.

Alexandre Julliard julliard at winehq.org
Fri Nov 13 15:57:52 CST 2020


Module: wine
Branch: master
Commit: a600d7ece16845d2b16020a510669abc7d66f21f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a600d7ece16845d2b16020a510669abc7d66f21f

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Nov 13 11:16:16 2020 +0300

wordpad: Fill font selection combobox with fully processed font list.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46478
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/wordpad/wordpad.c | 142 +++++++++++++++++++++++++++++++++------------
 1 file changed, 104 insertions(+), 38 deletions(-)

diff --git a/programs/wordpad/wordpad.c b/programs/wordpad/wordpad.c
index c8e3132b343..5ba5cc857f6 100644
--- a/programs/wordpad/wordpad.c
+++ b/programs/wordpad/wordpad.c
@@ -536,36 +536,6 @@ static void on_fontlist_modified(LPWSTR wszNewFaceName)
         set_font(wszNewFaceName);
 }
 
-static void add_font(LPCWSTR fontName, DWORD fontType, HWND hListWnd, const NEWTEXTMETRICEXW *ntmc)
-{
-    COMBOBOXEXITEMW cbItem;
-    WCHAR buffer[MAX_PATH];
-    int fontHeight = 0;
-
-    cbItem.mask = CBEIF_TEXT;
-    cbItem.pszText = buffer;
-    cbItem.cchTextMax = MAX_STRING_LEN;
-    cbItem.iItem = 0;
-
-    while(SendMessageW(hListWnd, CBEM_GETITEMW, 0, (LPARAM)&cbItem))
-    {
-        if(lstrcmpiW(cbItem.pszText, fontName) <= 0)
-            cbItem.iItem++;
-        else
-            break;
-    }
-    cbItem.pszText = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(fontName) + 1)*sizeof(WCHAR) );
-    lstrcpyW( cbItem.pszText, fontName );
-
-    cbItem.mask |= CBEIF_LPARAM;
-    if(fontType & RASTER_FONTTYPE)
-        fontHeight = ntmc->ntmTm.tmHeight - ntmc->ntmTm.tmInternalLeading;
-
-    cbItem.lParam = MAKELONG(fontType,fontHeight);
-    SendMessageW(hListWnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbItem);
-    HeapFree( GetProcessHeap(), 0, cbItem.pszText );
-}
-
 static void dialog_choose_font(void)
 {
     CHOOSEFONTW cf;
@@ -614,36 +584,132 @@ static void dialog_choose_font(void)
     }
 }
 
+struct font_desc
+{
+    WCHAR *name;
+    LPARAM lParam;
+};
+
+struct font_array
+{
+    struct font_desc *fonts;
+    size_t count;
+    size_t capacity;
+};
+
+static BOOL array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+    size_t new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    new_elements = *elements ? HeapReAlloc(GetProcessHeap(), 0, *elements, new_capacity * size) :
+            HeapAlloc(GetProcessHeap(), 0, new_capacity * size);
+    if (!new_elements)
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+
+    return TRUE;
+}
+
+static void add_font(struct font_array *fonts, LPCWSTR fontName, DWORD fontType, const NEWTEXTMETRICEXW *ntmc)
+{
+    int fontHeight = 0;
+    size_t idx;
+
+    if (!array_reserve((void **)&fonts->fonts, &fonts->capacity, fonts->count + 1, sizeof(*fonts->fonts)))
+        return;
+
+    if (fontType & RASTER_FONTTYPE)
+        fontHeight = ntmc->ntmTm.tmHeight - ntmc->ntmTm.tmInternalLeading;
+
+    idx = fonts->count;
+    fonts->fonts[idx].name = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(fontName) + 1)*sizeof(WCHAR) );
+    lstrcpyW( fonts->fonts[idx].name, fontName );
+    fonts->fonts[idx].lParam = MAKELONG(fontType, fontHeight);
+
+    fonts->count++;
+}
 
 static int CALLBACK enum_font_proc(const LOGFONTW *lpelfe, const TEXTMETRICW *lpntme,
                             DWORD FontType, LPARAM lParam)
 {
-    HWND hListWnd = (HWND) lParam;
+    struct font_array *fonts = (void *)lParam;
 
     if (lpelfe->lfFaceName[0] == '@') return 1;  /* ignore vertical fonts */
 
-    if(SendMessageW(hListWnd, CB_FINDSTRINGEXACT, -1, (LPARAM)lpelfe->lfFaceName) == CB_ERR)
-    {
-
-        add_font(lpelfe->lfFaceName, FontType, hListWnd, (const NEWTEXTMETRICEXW*)lpntme);
-    }
+    add_font(fonts, lpelfe->lfFaceName, FontType, (const NEWTEXTMETRICEXW *)lpntme);
 
     return 1;
 }
 
+static int fonts_desc_compare(const void *a, const void *b)
+{
+    const struct font_desc *left = a, *right = b;
+    return lstrcmpiW(left->name, right->name);
+}
+
 static void populate_font_list(HWND hListWnd)
 {
+    struct font_array font_array = { 0 };
     HDC hdc = GetDC(hMainWnd);
     LOGFONTW fontinfo;
     HWND hListEditWnd = (HWND)SendMessageW(hListWnd, CBEM_GETEDITCONTROL, 0, 0);
     CHARFORMAT2W fmt;
+    size_t i, j;
 
     fontinfo.lfCharSet = DEFAULT_CHARSET;
     *fontinfo.lfFaceName = '\0';
     fontinfo.lfPitchAndFamily = 0;
 
-    EnumFontFamiliesExW(hdc, &fontinfo, enum_font_proc,
-                        (LPARAM)hListWnd, 0);
+    /* Collect font names, sort, remove duplicates. */
+    EnumFontFamiliesExW(hdc, &fontinfo, enum_font_proc, (LPARAM)&font_array, 0);
+
+    qsort(font_array.fonts, font_array.count, sizeof(*font_array.fonts), fonts_desc_compare);
+
+    for (i = 1, j = 0; i < font_array.count; ++i)
+    {
+        if (!lstrcmpiW(font_array.fonts[i].name, font_array.fonts[j].name))
+        {
+            HeapFree(GetProcessHeap(), 0, font_array.fonts[i].name);
+            font_array.fonts[i].name = NULL;
+        }
+        else if (++j != i)
+        {
+            font_array.fonts[j] = font_array.fonts[i];
+            font_array.fonts[i].name = NULL;
+        }
+    }
+    font_array.count = j + 1;
+
+    for (i = 0; i < font_array.count; ++i)
+    {
+        COMBOBOXEXITEMW cbitem = { 0 };
+
+        cbitem.mask = CBEIF_TEXT | CBEIF_LPARAM;
+        cbitem.pszText = font_array.fonts[i].name;
+        cbitem.iItem = -1;
+        cbitem.lParam = font_array.fonts[i].lParam;
+
+        SendMessageW(hListWnd, CBEM_INSERTITEMW, 0, (LPARAM)&cbitem);
+
+        HeapFree(GetProcessHeap(), 0, font_array.fonts[i].name);
+    }
+    HeapFree(GetProcessHeap(), 0, font_array.fonts);
 
     ZeroMemory(&fmt, sizeof(fmt));
     fmt.cbSize = sizeof(fmt);




More information about the wine-cvs mailing list