Signed-off-by: Zhiyi Zhang zzhang@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);