comctl32: toolbar: test and fix TB_ADDSTRING from resource

Mikołaj Zalewski mikolaj at zalewski.pl
Tue Sep 26 14:30:26 CDT 2006


The way of dividing strings loaded from resources info multiple strings 
is not documented. It seems wine first assumed than only one string is 
added and later a case with '|' as delimiter was added. This doesn't 
always work like with native comctl32. After some testing I've written 
an implementation that passes all the tests I've  made.

This patch also simplifies the TOOLBAR_AddStringA and TOOLBAR_AddStringW 
functions.
-------------- next part --------------
diff --git a/dlls/comctl32/tests/resources.h b/dlls/comctl32/tests/resources.h
index 6c52e8c..826f9c5 100644
--- a/dlls/comctl32/tests/resources.h
+++ b/dlls/comctl32/tests/resources.h
@@ -24,4 +24,14 @@ #define __WINE_COMCTL32_TEST_RESOURCES_H
 #define IDB_BITMAP_128x15       10
 #define IDB_BITMAP_80x15        11
 
+#define IDS_TBADD1      16
+#define IDS_TBADD2      17
+#define IDS_TBADD3      18
+#define IDS_TBADD4      19
+#define IDS_TBADD5      20
+#define IDS_TBADD6      21
+#define IDS_TBADD7      22
+#define IDS_TBADD8      23
+#define IDS_TBADD9      24
+
 #endif  /* __WINE_COMCTL32_TEST_RESOURCES_H */
diff --git a/dlls/comctl32/tests/rsrc.rc b/dlls/comctl32/tests/rsrc.rc
index 23d9ffb..b68ab1b 100644
--- a/dlls/comctl32/tests/rsrc.rc
+++ b/dlls/comctl32/tests/rsrc.rc
@@ -30,6 +30,17 @@ FONT 8, "MS Shell Dlg"
  LTEXT "Test", -1, 10, 6, 100, 8
 }
 
+STRINGTABLE 
+{
+    IDS_TBADD1           "abc"
+    IDS_TBADD2           "|p|q|r"
+    IDS_TBADD3           "*p*q*"
+    IDS_TBADD4           "#p#q##"
+    IDS_TBADD5           "|p||q|r|"
+    IDS_TBADD6           "\000a\000\000"
+    IDS_TBADD7           "abracadabra"
+}
+
 /* BINRES bmp128x15.bmp */
 IDB_BITMAP_128x15 BITMAP bmp128x15.bmp
 /* {
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c
index 7cdc5b9..c9ff6e3 100644
--- a/dlls/comctl32/tests/toolbar.c
+++ b/dlls/comctl32/tests/toolbar.c
@@ -312,6 +312,64 @@ static void test_add_bitmap(void)
     DestroyWindow(hToolbar);
 }
 
+#define CHECK_STRING_TABLE(count, tab) { \
+        INT _i; \
+        CHAR _buf[260]; \
+        for (_i = 0; _i < (count); _i++) {\
+            ret = SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, _i), (LPARAM)_buf); \
+            ok(ret >= 0, "TB_GETSTRING - unexpected return %d while checking string %d\n", ret, _i); \
+            if (ret >= 0) \
+                ok(strcmp(_buf, (tab)[_i]) == 0, "Invalid string #%d - '%s' vs '%s'\n", _i, (tab)[_i], _buf); \
+        } \
+        ok(SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, (count)), (LPARAM)_buf) == -1, \
+            "Too many string in table\n"); \
+    }
+
+void test_add_string()
+{
+    LPCSTR test1 = "a\0b\0";
+    LPCSTR test2 = "|a|b||\0";
+    LPCSTR ret1[] = {"a", "b"};
+    LPCSTR ret2[] = {"a", "b", "|a|b||"};
+    LPCSTR ret3[] = {"a", "b", "|a|b||", "p", "q"};
+    LPCSTR ret4[] = {"a", "b", "|a|b||", "p", "q", "p"};
+    LPCSTR ret5[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q"};
+    LPCSTR ret6[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q"};
+    LPCSTR ret7[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q", "br", "c", "d"};
+    HWND hToolbar = NULL;
+    int ret;
+
+    rebuild_toolbar(&hToolbar);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test1);
+    ok(ret == 0, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(2, ret1);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test2);
+    ok(ret == 2, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(3, ret2);
+
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD1);
+    ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(3, ret2);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD2);
+    ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(5, ret3);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD3);
+    ok(ret == 5, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(6, ret4);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD4);
+    ok(ret == 6, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(8, ret5);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD5);
+    ok(ret == 8, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(11, ret6);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD6);
+    ok(ret == 11, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(11, ret6);
+    ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD7);
+    ok(ret == 11, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+    CHECK_STRING_TABLE(14, ret7);
+}
+
 START_TEST(toolbar)
 {
     WNDCLASSA wc;
@@ -339,6 +397,7 @@ START_TEST(toolbar)
 
     basic_test();
     test_add_bitmap();
+    test_add_string();
 
     PostQuitMessage(0);
     while(GetMessageA(&msg,0,0,0)) {
diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index fe26ac1..9de8e76 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -2931,64 +2931,57 @@ TOOLBAR_AddButtonsW (HWND hwnd, WPARAM w
 
 
 static LRESULT
-TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
+TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
+#define MAX_RESOURCE_STRING_LENGTH 512
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
-    INT nIndex;
+    INT nIndex = infoPtr->nNumStrings;
 
     if ((wParam) && (HIWORD(lParam) == 0)) {
-	char szString[256];
+	WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
+	WCHAR delimiter;
+	WCHAR *next_delim;
+	WCHAR *p;
 	INT len;
 	TRACE("adding string from resource!\n");
 
-	len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam, szString, sizeof(szString));
+        LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
+                             szString, MAX_RESOURCE_STRING_LENGTH);
+        len = lstrlenW(szString);
 
-	TRACE("len=%d \"%s\"\n", len, szString);
-	nIndex = infoPtr->nNumStrings;
-	if (infoPtr->nNumStrings == 0) {
-	    infoPtr->strings =
-		Alloc (sizeof(LPWSTR));
-	}
-	else {
-	    LPWSTR *oldStrings = infoPtr->strings;
-	    infoPtr->strings =
-		Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
-	    memcpy (&infoPtr->strings[0], &oldStrings[0],
-		    sizeof(LPWSTR) * infoPtr->nNumStrings);
-	    Free (oldStrings);
-	}
+        TRACE("len=%d %s\n", len, debugstr_w(szString));
+        if (len == 0 || len == 1)
+            return nIndex;
 
-        /*Alloc zeros out the allocated memory*/
-        Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], szString );
-	infoPtr->nNumStrings++;
+        TRACE("Delimiter: 0x%x\n", *szString);
+        delimiter = *szString;
+        p = szString + 1;
+        if (szString[len-1] == delimiter)
+            szString[len-1] = 0;
+
+        while ((next_delim = strchrW(p, delimiter)) != NULL) {
+            *next_delim = 0;
+
+            infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
+            Str_SetPtrW(&infoPtr->strings[infoPtr->nNumStrings], p);
+            infoPtr->nNumStrings++;
+
+            p = next_delim + 1;
+        }
     }
     else {
-	LPSTR p = (LPSTR)lParam;
+	LPWSTR p = (LPWSTR)lParam;
 	INT len;
 
 	if (p == NULL)
 	    return -1;
 	TRACE("adding string(s) from array!\n");
-
-	nIndex = infoPtr->nNumStrings;
 	while (*p) {
-	    len = strlen (p);
-	    TRACE("len=%d \"%s\"\n", len, p);
+            len = strlenW (p);
 
-	    if (infoPtr->nNumStrings == 0) {
-		infoPtr->strings =
-		    Alloc (sizeof(LPWSTR));
-	    }
-	    else {
-		LPWSTR *oldStrings = infoPtr->strings;
-		infoPtr->strings =
-		    Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
-		memcpy (&infoPtr->strings[0], &oldStrings[0],
-			sizeof(LPWSTR) * infoPtr->nNumStrings);
-		Free (oldStrings);
-	    }
-
-            Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], p );
+            TRACE("len=%d %s\n", len, debugstr_w(p));
+            infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
+            Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p);
 	    infoPtr->nNumStrings++;
 
 	    p += (len+1);
@@ -3000,109 +2993,31 @@ TOOLBAR_AddStringA (HWND hwnd, WPARAM wP
 
 
 static LRESULT
-TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam)
+TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-#define MAX_RESOURCE_STRING_LENGTH 512
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd);
+    LPSTR p;
     INT nIndex;
+    INT len;
 
-    if ((wParam) && (HIWORD(lParam) == 0)) {
-	WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
-	INT len;
-	TRACE("adding string from resource!\n");
-
-	len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam,
-			     szString, MAX_RESOURCE_STRING_LENGTH);
-
-	TRACE("len=%d %s\n", len, debugstr_w(szString));
-	TRACE("First char: 0x%x\n", *szString);
-	if (szString[0] == L'|')
-	{
-	    PWSTR p = szString + 1;
-
-            nIndex = infoPtr->nNumStrings;
-            while (*p != L'|' && *p != L'\0') {
-                PWSTR np;
-
-                if (infoPtr->nNumStrings == 0) {
-                    infoPtr->strings = Alloc (sizeof(LPWSTR));
-                }
-                else
-                {
-                    LPWSTR *oldStrings = infoPtr->strings;
-                    infoPtr->strings = Alloc(sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
-                    memcpy(&infoPtr->strings[0], &oldStrings[0],
-                           sizeof(LPWSTR) * infoPtr->nNumStrings);
-                    Free(oldStrings);
-                }
-
-                np=strchrW (p, '|');
-                if (np!=NULL) {
-                    len = np - p;
-                    np++;
-                } else {
-                    len = strlenW(p);
-                    np = p + len;
-                }
-                TRACE("len=%d %s\n", len, debugstr_w(p));
-                infoPtr->strings[infoPtr->nNumStrings] =
-                    Alloc (sizeof(WCHAR)*(len+1));
-                lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len+1);
-                infoPtr->nNumStrings++;
-
-                p = np;
-            }
-	}
-	else
-	{
-            nIndex = infoPtr->nNumStrings;
-            if (infoPtr->nNumStrings == 0) {
-                infoPtr->strings =
-                    Alloc (sizeof(LPWSTR));
-            }
-            else {
-                LPWSTR *oldStrings = infoPtr->strings;
-                infoPtr->strings =
-                    Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
-                memcpy (&infoPtr->strings[0], &oldStrings[0],
-                        sizeof(LPWSTR) * infoPtr->nNumStrings);
-                Free (oldStrings);
-            }
-
-            Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], szString);
-            infoPtr->nNumStrings++;
-        }
-    }
-    else {
-	LPWSTR p = (LPWSTR)lParam;
-	INT len;
+    if ((wParam) && (HIWORD(lParam) == 0))  /* load from resources */
+        return TOOLBAR_AddStringW(hwnd, wParam, lParam);
 
-	if (p == NULL)
-	    return -1;
-	TRACE("adding string(s) from array!\n");
-	nIndex = infoPtr->nNumStrings;
-	while (*p) {
-	    len = strlenW (p);
+    p = (LPSTR)lParam;
+    if (p == NULL)
+        return -1;
 
-	    TRACE("len=%d %s\n", len, debugstr_w(p));
-	    if (infoPtr->nNumStrings == 0) {
-		infoPtr->strings =
-		    Alloc (sizeof(LPWSTR));
-	    }
-	    else {
-		LPWSTR *oldStrings = infoPtr->strings;
-		infoPtr->strings =
-		    Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1));
-		memcpy (&infoPtr->strings[0], &oldStrings[0],
-			sizeof(LPWSTR) * infoPtr->nNumStrings);
-		Free (oldStrings);
-	    }
+    TRACE("adding string(s) from array!\n");
+    nIndex = infoPtr->nNumStrings;
+    while (*p) {
+        len = strlen (p);
+        TRACE("len=%d \"%s\"\n", len, p);
 
-	    Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p);
-	    infoPtr->nNumStrings++;
+        infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
+        Str_SetPtrAtoW(&infoPtr->strings[infoPtr->nNumStrings], p);
+        infoPtr->nNumStrings++;
 
-	    p += (len+1);
-	}
+        p += (len+1);
     }
 
     return nIndex;
-- 
1.4.1


More information about the wine-patches mailing list