[PATCH 3/3] comctl32/pager: Support comboboxex notification conversion.

Zhiyi Zhang zzhang at codeweavers.com
Mon Aug 27 22:28:37 CDT 2018


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/comctl32/pager.c       |  59 +++++++++++++-
 dlls/comctl32/tests/pager.c | 148 +++++++++++++++++++++++++++++++++---
 2 files changed, 192 insertions(+), 15 deletions(-)

diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c
index 9ab492e333..37b2e52325 100644
--- a/dlls/comctl32/pager.c
+++ b/dlls/comctl32/pager.c
@@ -101,7 +101,11 @@ typedef enum
     /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */
     TO_ANSI = 0x02,
     /* Send empty text to parent if text is NULL, original text pointer still remain NULL */
-    SET_NULL_EMPTY = 0x04
+    SET_NULL_EMPTY = 0x04,
+    /* Set text to null after parent received the notification if the required mask is not set before sending notification */
+    NO_MASK_SET_NULL = 0x08,
+    /* Zero the text buffer before sending */
+    ZERO_BUFFER = 0x10
 } ConversionFlag;
 
 static void
@@ -1038,6 +1042,10 @@ static UINT PAGER_GetAnsiNtfCode(UINT code)
 {
     switch (code)
     {
+    /* ComboxBoxEx */
+    case CBEN_DRAGBEGINW: return CBEN_DRAGBEGINA;
+    case CBEN_ENDEDITW: return CBEN_ENDEDITA;
+    case CBEN_GETDISPINFOW: return CBEN_GETDISPINFOA;
     /* Toolbar */
     case TBN_GETBUTTONINFOW: return TBN_GETBUTTONINFOA;
     case TBN_GETINFOTIPW: return TBN_GETINFOTIPA;
@@ -1060,7 +1068,8 @@ static BOOL PAGER_AdjustBuffer(PAGER_INFO *infoPtr, INT size)
     return TRUE;
 }
 
-static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, WCHAR **text, INT *textMax, ConversionFlag flags)
+static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, UINT *mask, UINT requiredMask, WCHAR **text,
+                                         INT *textMax, ConversionFlag flags)
 {
     WCHAR emptyW[] = {0};
     WCHAR *oldText;
@@ -1075,8 +1084,17 @@ static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, WCHAR
 
     hdr->code = PAGER_GetAnsiNtfCode(hdr->code);
 
+    if (mask && !(*mask & requiredMask))
+    {
+        ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr);
+        if (flags & NO_MASK_SET_NULL) oldText = NULL;
+        goto done;
+    }
+
     if (oldTextMax < 0) goto done;
 
+    if (*text && flags & ZERO_BUFFER) memset(*text, 0, oldTextMax * sizeof(WCHAR));
+
     if (!*text && flags & SET_NULL_EMPTY)
         *text = emptyW;
 
@@ -1117,17 +1135,50 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr)
 
     switch (hdr->code)
     {
+    /* ComboBoxEx */
+    case CBEN_GETDISPINFOW:
+    {
+        NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr;
+        return PAGER_SendConvertedNotify(infoPtr, hdr, &nmcbe->ceItem.mask, CBEIF_TEXT, &nmcbe->ceItem.pszText,
+                                         &nmcbe->ceItem.cchTextMax, NO_MASK_SET_NULL | ZERO_BUFFER | FROM_ANSI);
+    }
+    case CBEN_DRAGBEGINW:
+    {
+        NMCBEDRAGBEGINW *nmdbW = (NMCBEDRAGBEGINW *)hdr;
+        NMCBEDRAGBEGINA nmdbA = {0};
+        nmdbA.hdr.code = PAGER_GetAnsiNtfCode(nmdbW->hdr.code);
+        nmdbA.hdr.hwndFrom = nmdbW->hdr.hwndFrom;
+        nmdbA.hdr.idFrom = nmdbW->hdr.idFrom;
+        nmdbA.iItemid = nmdbW->iItemid;
+        WideCharToMultiByte(CP_ACP, 0, nmdbW->szText, ARRAY_SIZE(nmdbW->szText), nmdbA.szText, ARRAY_SIZE(nmdbA.szText),
+                            NULL, FALSE);
+        return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmdbA);
+    }
+    case CBEN_ENDEDITW:
+    {
+        NMCBEENDEDITW *nmedW = (NMCBEENDEDITW *)hdr;
+        NMCBEENDEDITA nmedA = {0};
+        nmedA.hdr.code = PAGER_GetAnsiNtfCode(nmedW->hdr.code);
+        nmedA.hdr.hwndFrom = nmedW->hdr.hwndFrom;
+        nmedA.hdr.idFrom = nmedW->hdr.idFrom;
+        nmedA.fChanged = nmedW->fChanged;
+        nmedA.iNewSelection = nmedW->iNewSelection;
+        nmedA.iWhy = nmedW->iWhy;
+        WideCharToMultiByte(CP_ACP, 0, nmedW->szText, ARRAY_SIZE(nmedW->szText), nmedA.szText, ARRAY_SIZE(nmedA.szText),
+                            NULL, FALSE);
+        return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmedA);
+    }
     /* Toolbar */
     case TBN_GETBUTTONINFOW:
     {
         NMTOOLBARW *nmtb = (NMTOOLBARW *)hdr;
-        return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtb->pszText, &nmtb->cchText,
+        return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtb->pszText, &nmtb->cchText,
                                          SET_NULL_EMPTY | TO_ANSI | FROM_ANSI);
     }
     case TBN_GETINFOTIPW:
     {
         NMTBGETINFOTIPW *nmtbgit = (NMTBGETINFOTIPW *)hdr;
-        return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtbgit->pszText, &nmtbgit->cchTextMax, FROM_ANSI);
+        return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtbgit->pszText, &nmtbgit->cchTextMax, FROM_ANSI);
     }
     /* Tooltip */
     case TTN_GETDISPINFOW:
diff --git a/dlls/comctl32/tests/pager.c b/dlls/comctl32/tests/pager.c
index bf79f34c5b..ee8d36d040 100644
--- a/dlls/comctl32/tests/pager.c
+++ b/dlls/comctl32/tests/pager.c
@@ -45,7 +45,11 @@ typedef enum
     /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */
     TO_ANSI = 0x02,
     /* Send empty text to parent if text is NULL, original text pointer still remain NULL */
-    SET_NULL_EMPTY = 0x04
+    SET_NULL_EMPTY = 0x04,
+    /* Set text to null after parent received the notification if the required mask is not set before sending notification */
+    NO_MASK_SET_NULL = 0x08,
+    /* Zero the text buffer before sending */
+    ZERO_BUFFER = 0x10
 } ConversionFlag;
 
 static struct notify_test_data
@@ -505,12 +509,15 @@ static void wm_notify_text_handler(CHAR **text, INT *textMax)
     expect_eq_int(*textMax, notify_test_data.text_size);
     switch (notify_test_data.sub_test_id)
     {
-    case 1:
+    case 0:
         if (notify_test_data.flags & SET_NULL_EMPTY)
             expect_text_empty(*text);
         else
             expect_null(*text);
         break;
+    case 1:
+        expect_text_empty(*text);
+        break;
     case 2:
     {
         INT length = lstrlenA(*text);
@@ -521,7 +528,9 @@ static void wm_notify_text_handler(CHAR **text, INT *textMax)
         break;
     }
     case 3:
-        if (notify_test_data.flags & TO_ANSI)
+        if (notify_test_data.flags & ZERO_BUFFER)
+            expect_text_empty(*text);
+        else if (notify_test_data.flags & TO_ANSI)
         {
             expect_eq_text_a(*text, test_a);
             ok(*text != (CHAR *)buffer, "Expect using a new buffer\n");
@@ -579,6 +588,49 @@ static LRESULT WINAPI test_notify_proc(HWND hwnd, UINT message, WPARAM wParam, L
         }
         switch (hdr->code)
         {
+        /* ComboBoxEx */
+        /* No conversion for CBEN_INSERTITEM and CBEN_DELETEITEM */
+        case CBEN_INSERTITEM:
+        case CBEN_DELETEITEM:
+        {
+            NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr;
+            expect_eq_text_w(nmcbe->ceItem.pszText, test_w);
+            break;
+        }
+        case CBEN_DRAGBEGINA:
+        {
+            NMCBEDRAGBEGINA *nmcbedb = (NMCBEDRAGBEGINA *)hdr;
+            switch (notify_test_data.sub_test_id)
+            {
+            case 0:
+                expect_text_empty(nmcbedb->szText);
+                break;
+            case 1:
+                expect_eq_text_a(nmcbedb->szText, test_a);
+                break;
+            }
+            break;
+        }
+        case CBEN_ENDEDITA:
+        {
+            NMCBEENDEDITA *nmcbeed = (NMCBEENDEDITA *)hdr;
+            switch (notify_test_data.sub_test_id)
+            {
+            case 0:
+                expect_text_empty(nmcbeed->szText);
+                break;
+            case 1:
+                expect_eq_text_a(nmcbeed->szText, test_a);
+                break;
+            }
+            break;
+        }
+        case CBEN_GETDISPINFOA:
+        {
+            NMCOMBOBOXEXA *nmcbe = (NMCOMBOBOXEXA *)hdr;
+            wm_notify_text_handler(&nmcbe->ceItem.pszText, &nmcbe->ceItem.cchTextMax);
+            break;
+        }
         /* Toolbar */
         /* No conversion for TBN_SAVE and TBN_RESTORE */
         case TBN_SAVE:
@@ -724,24 +776,46 @@ static void send_notify_(HWND pager, UINT unicode, UINT ansi, LPARAM lParam, BOO
 #define send_notify(a, b, c, d, e) send_notify_(pager, a, b, c, d, e)
 
 /* Send notify to test text field conversion. In parent proc wm_notify_text_handler() handles these messages */
-static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHAR **text, INT *textMax,
-                                        UINT code_unicode, UINT code_ansi, ConversionFlag flags)
+static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, UINT *mask, UINT requiredMask, WCHAR **text,
+                                        INT *textMax, UINT code_unicode, UINT code_ansi, ConversionFlag flags)
 {
     notify_test_data.flags = flags;
 
     /* NULL text */
-    notify_test_data.sub_test_id = 1;
+    notify_test_data.sub_test_id = 0;
     memset(ptr, 0, size);
+    if (mask) *mask = requiredMask;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
     send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
     expect_null(*text);
     expect_eq_int(*textMax, notify_test_data.text_size);
 
+    if (mask)
+    {
+        /* No required mask */
+        notify_test_data.sub_test_id = 1;
+        memset(ptr, 0, size);
+        memset(buffer, 0, sizeof(buffer));
+        *text = buffer;
+        *textMax = ARRAY_SIZE(buffer);
+        notify_test_data.text_size = *textMax;
+        send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
+        if (flags & NO_MASK_SET_NULL)
+            expect_null(*text);
+        else
+        {
+            expect_text_empty(*text);
+            expect_eq_pointer(*text, buffer);
+        }
+        expect_eq_int(*textMax, notify_test_data.text_size);
+    }
+
     /* Zero text max size */
     notify_test_data.sub_test_id = 2;
     memset(ptr, 0, size);
     memset(buffer, 0, sizeof(buffer));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     notify_test_data.text_size = *textMax;
     send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
@@ -753,11 +827,14 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     notify_test_data.sub_test_id = 3;
     memset(ptr, 0, size);
     memcpy(buffer, test_w, sizeof(test_w));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
     send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
-    if (!(flags & TO_ANSI) && flags & FROM_ANSI)
+    if (flags & ZERO_BUFFER)
+        expect_text_empty(*text);
+    else if (!(flags & TO_ANSI) && flags & FROM_ANSI)
         expect_eq_text_w(*text, t_w);
     else
         expect_eq_text_w(*text, test_w);
@@ -768,6 +845,7 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     notify_test_data.sub_test_id = 4;
     memset(ptr, 0, size);
     memset(buffer, 0, sizeof(buffer));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
@@ -780,6 +858,7 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     notify_test_data.sub_test_id = 5;
     memset(ptr, 0, size);
     memset(buffer, 0, sizeof(buffer));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
@@ -791,6 +870,7 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     notify_test_data.sub_test_id = 6;
     memset(ptr, 0, size);
     memset(buffer, 0, sizeof(buffer));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
@@ -802,6 +882,7 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     /* NULL text. Parent replace buffer */
     notify_test_data.sub_test_id = 7;
     memset(ptr, 0, size);
+    if (mask) *mask = requiredMask;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
     send_notify(code_unicode, code_ansi, (LPARAM)ptr, TRUE, TRUE);
@@ -813,6 +894,7 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     memset(ptr, 0, size);
     memset(buffer, 0, sizeof(buffer));
     memset(buffer2, 0, sizeof(buffer2));
+    if (mask) *mask = requiredMask;
     *text = buffer;
     *textMax = ARRAY_SIZE(buffer);
     notify_test_data.text_size = *textMax;
@@ -823,7 +905,50 @@ static void test_wm_notify_text_helper_(HWND pager, void *ptr, size_t size, WCHA
     expect_eq_int(*textMax, notify_test_data.text_size);
 }
 
-#define test_wm_notify_text_helper(a, b, c, d, e, f, g) test_wm_notify_text_helper_(pager, a, b, c, d, e, f, g)
+#define test_wm_notify_text_helper(a, b, c, d, e, f, g, h, i) \
+    test_wm_notify_text_helper_(pager, a, b, c, d, e, f, g, h, i)
+
+static void test_wm_notify_comboboxex(HWND pager)
+{
+    NMCOMBOBOXEXW nmcbe;
+    NMCBEDRAGBEGINW nmcbedb;
+    NMCBEENDEDITW nmcbeed;
+
+    /* CBEN_INSERTITEM and CBEN_DELETEITEM will be forwarded unchanged */
+    memset(&nmcbe, 0, sizeof(nmcbe));
+    nmcbe.ceItem.mask = CBEIF_TEXT;
+    nmcbe.ceItem.pszText = test_w;
+    nmcbe.ceItem.cchTextMax = ARRAY_SIZE(test_w);
+    send_notify(CBEN_INSERTITEM, CBEN_INSERTITEM, (LPARAM)&nmcbe, TRUE, TRUE);
+    send_notify(CBEN_DELETEITEM, CBEN_DELETEITEM, (LPARAM)&nmcbe, TRUE, TRUE);
+
+    /* CBEN_DRAGBEGIN */
+    notify_test_data.sub_test_id = 0;
+    memset(&nmcbedb, 0, sizeof(nmcbedb));
+    send_notify(CBEN_DRAGBEGINW, CBEN_DRAGBEGINA, (LPARAM)&nmcbedb, FALSE, TRUE);
+
+    notify_test_data.sub_test_id = 1;
+    memset(&nmcbedb, 0, sizeof(nmcbedb));
+    memcpy(nmcbedb.szText, test_w, sizeof(test_w));
+    send_notify(CBEN_DRAGBEGINW, CBEN_DRAGBEGINA, (LPARAM)&nmcbedb, FALSE, TRUE);
+    expect_eq_text_w(nmcbedb.szText, test_w);
+
+    /* CBEN_ENDEDIT */
+    notify_test_data.sub_test_id = 0;
+    memset(&nmcbeed, 0, sizeof(nmcbeed));
+    send_notify(CBEN_ENDEDITW, CBEN_ENDEDITA, (LPARAM)&nmcbeed, FALSE, TRUE);
+
+    notify_test_data.sub_test_id = 1;
+    memset(&nmcbeed, 0, sizeof(nmcbeed));
+    memcpy(nmcbeed.szText, test_w, sizeof(test_w));
+    send_notify(CBEN_ENDEDITW, CBEN_ENDEDITA, (LPARAM)&nmcbeed, FALSE, TRUE);
+    expect_eq_text_w(nmcbeed.szText, test_w);
+
+    /* CBEN_GETDISPINFO */
+    test_wm_notify_text_helper(&nmcbe, sizeof(nmcbe), &nmcbe.ceItem.mask, CBEIF_TEXT, &nmcbe.ceItem.pszText,
+                               &nmcbe.ceItem.cchTextMax, CBEN_GETDISPINFOW, CBEN_GETDISPINFOA,
+                               NO_MASK_SET_NULL | ZERO_BUFFER | FROM_ANSI);
+}
 
 static void test_wm_notify_toolbar(HWND pager)
 {
@@ -869,10 +994,10 @@ static void test_wm_notify_toolbar(HWND pager)
     send_notify(TBN_GETDISPINFOW, TBN_GETDISPINFOW, (LPARAM)&nmtbdi, TRUE, TRUE);
     expect_eq_text_a((CHAR *)nmtbdi.pszText, test_a);
 
-    test_wm_notify_text_helper(&nmtb, sizeof(nmtb), &nmtb.pszText, &nmtb.cchText, TBN_GETBUTTONINFOW,
+    test_wm_notify_text_helper(&nmtb, sizeof(nmtb), NULL, 0, &nmtb.pszText, &nmtb.cchText, TBN_GETBUTTONINFOW,
                                TBN_GETBUTTONINFOA, SET_NULL_EMPTY | TO_ANSI);
-    test_wm_notify_text_helper(&nmtbgit, sizeof(nmtbgit), &nmtbgit.pszText, &nmtbgit.cchTextMax, TBN_GETINFOTIPW,
-                               TBN_GETINFOTIPA, FROM_ANSI);
+    test_wm_notify_text_helper(&nmtbgit, sizeof(nmtbgit), NULL, 0, &nmtbgit.pszText, &nmtbgit.cchTextMax,
+                               TBN_GETINFOTIPW, TBN_GETINFOTIPA, FROM_ANSI);
 }
 
 static void test_wm_notify_tooltip(HWND pager)
@@ -979,6 +1104,7 @@ static void test_wm_notify(void)
     ok(child1_wnd != NULL, "CreateWindow failed\n");
     SendMessageW(pager, PGM_SETCHILD, 0, (LPARAM)child1_wnd);
 
+    test_wm_notify_comboboxex(pager);
     test_wm_notify_toolbar(pager);
     test_wm_notify_tooltip(pager);
 
-- 
2.18.0




More information about the wine-devel mailing list