Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57178
This makes [7-zip file manager](https://www.7-zip.org/) pressing enter while editing path work: * before: * [Icon near path becomes dark (7-zip file manager doesn't go to path).](https://old.reddit.com/r/winehq/comments/16ah3ze/7zip_cant_enter_path_from_p...) * after: * 7-zip file manager goes to path. * Path input displays incorrect path (shouldn't happen, bug in wine's comboboxex unrelated to toolbar).
-- v16: comctl32/toolbar: Forward WM_NOTIFY CBEN_ENDEDITW and CBEN_ENDEDITA. comctl32: Move WM_NOTIFY unicode to ansi conversion code from pager.c to commctrl.c. comctl32/tests: Test WM_NOTIFY CBEN_ENDEDITW conversion and forwarding in toolbar.
From: Alanas Tebuev alanas.00@mail.ru
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57178 --- dlls/comctl32/tests/toolbar.c | 112 +++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c index ebeb49fe8d4..df322dcd6da 100644 --- a/dlls/comctl32/tests/toolbar.c +++ b/dlls/comctl32/tests/toolbar.c @@ -179,13 +179,79 @@ static BOOL equal_dc(HDC hdc1, HDC hdc2, int width, int height)
static void *alloced_str;
-static LRESULT parent_wnd_notify(LPARAM lParam) +static const NMCBEENDEDITW test_WM_NOTIFY_NMCBEENDEDITW = +{ + .hdr.hwndFrom = (HWND)0xabcd0001, + .hdr.idFrom = 0xabcd0002, + .hdr.code = CBEN_ENDEDITW, + .fChanged = 0xabcd0003, + .iNewSelection = 0xabcd0004, + .szText = {'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',0}, + .iWhy = 0xabcd0005 +}; + +static const NMCBEENDEDITA test_WM_NOTIFY_NMCBEENDEDITA = +{ + .hdr.hwndFrom = (HWND)0xabcd0001, + .hdr.idFrom = 0xabcd0002, + .hdr.code = CBEN_ENDEDITA, + .fChanged = 0xabcd0003, + .iNewSelection = 0xabcd0004, + .szText = {'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',0}, + .iWhy = 0xabcd0005 +}; + +static enum +{ + TEST_WM_NOTIFY_NO_FORWARD, + TEST_WM_NOTIFY_FORWARD_NO_CONVERT, + TEST_WM_NOTIFY_FORWARD_CONVERT +} test_WM_NOTIFY_expect_CBEN_ENDEDITW, test_WM_NOTIFY_expect_CBEN_ENDEDITA; + +static LRESULT parent_wnd_notify(WPARAM wParam, LPARAM lParam) { NMHDR *hdr = (NMHDR *)lParam; NMTBHOTITEM *nmhi; NMTBDISPINFOA *nmdisp; switch (hdr->code) { + case CBEN_ENDEDITW: + switch (test_WM_NOTIFY_expect_CBEN_ENDEDITW) + { + case TEST_WM_NOTIFY_NO_FORWARD: + ok(FALSE, "Got unexpected WM_NOTIFY.\n"); + break; + case TEST_WM_NOTIFY_FORWARD_NO_CONVERT: + test_WM_NOTIFY_expect_CBEN_ENDEDITW = TEST_WM_NOTIFY_NO_FORWARD; + ok(hdr == &test_WM_NOTIFY_NMCBEENDEDITW.hdr, "Got unexpected header.\n"); + ok(wParam == 0xabcd0002, "Got unexpected wParam 0x%Ix.\n", wParam); + break; + default: + ok(FALSE, "This testing code is broken.\n"); + break; + } + return 0xabcd0006; + case CBEN_ENDEDITA: + switch (test_WM_NOTIFY_expect_CBEN_ENDEDITA) + { + case TEST_WM_NOTIFY_NO_FORWARD: + ok(FALSE, "Got unexpected WM_NOTIFY.\n"); + break; + case TEST_WM_NOTIFY_FORWARD_NO_CONVERT: + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD; + ok(hdr == &test_WM_NOTIFY_NMCBEENDEDITA.hdr, "Got unexpected header.\n"); + ok(wParam == 0xabcd0002, "Got unexpected wParam 0x%Ix.\n", wParam); + break; + case TEST_WM_NOTIFY_FORWARD_CONVERT: + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD; + ok(!memcmp(hdr, &test_WM_NOTIFY_NMCBEENDEDITA, sizeof(NMCBEENDEDITA)), "Incorrectly converted NMCBEENDEDITW to NMCBEENDEDITA.\n"); + ok(wParam == 0xabcd0002, "Got unexpected wParam 0x%Ix.\n", wParam); + break; + default: + ok(FALSE, "This testing code is broken.\n"); + break; + } + return 0xabcd0007; case TBN_HOTITEMCHANGE: nmhi = (NMTBHOTITEM *)lParam; g_fReceivedHotItemChange = TRUE; @@ -375,6 +441,8 @@ static LRESULT parent_wnd_notify(LPARAM lParam) return 0; }
+static LRESULT parent_WM_NOTIFYFORMAT_return = NFR_ANSI; + static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static LONG defwndproc_counter = 0; @@ -428,7 +496,9 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, switch (message) { case WM_NOTIFY: - return parent_wnd_notify(lParam); + return parent_wnd_notify(wParam, lParam); + case WM_NOTIFYFORMAT: + return parent_WM_NOTIFYFORMAT_return; }
defwndproc_counter++; @@ -2833,6 +2903,43 @@ static void test_BTNS_SEP(void) DestroyWindow(hwnd); }
+static void test_WM_NOTIFY(void) +{ + HWND toolbar = NULL; + LRESULT ret; + + parent_WM_NOTIFYFORMAT_return = NFR_UNICODE; + rebuild_toolbar(&toolbar); + + test_WM_NOTIFY_expect_CBEN_ENDEDITW = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; + ret = SendMessageW(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITW); + todo_wine ok(ret == 0xabcd0006, "SendMessageW returned 0x%Ix.\n", ret); + todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITW, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + test_WM_NOTIFY_expect_CBEN_ENDEDITW = TEST_WM_NOTIFY_NO_FORWARD; + + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; + ret = SendMessageA(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITA); + todo_wine ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); + todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD; + + parent_WM_NOTIFYFORMAT_return = NFR_ANSI; + rebuild_toolbar(&toolbar); + + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_CONVERT; + ret = SendMessageW(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITW); + todo_wine ok(ret == 0xabcd0007, "SendMessageW returned 0x%Ix.\n", ret); + todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't convert and forward WM_NOTIFY to parent.\n"); + + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; + ret = SendMessageA(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITA); + todo_wine ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); + todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD; + + DestroyWindow(toolbar); +} + START_TEST(toolbar) { ULONG_PTR ctx_cookie; @@ -2884,6 +2991,7 @@ START_TEST(toolbar) test_drawtext_flags(); test_imagelist(); test_BTNS_SEP(); + test_WM_NOTIFY();
if (!load_v6_module(&ctx_cookie, &ctx)) return;
From: Alanas Tebuev alanas.00@mail.ru
It will be needed for toolbar.c.
Also rewrite COMCTL32_AdjustUnicodeBuffer (was PAGER_AdjustBuffer): • Multiplication by 2 (also known as sizeof(WCHAR)) happens inside COMCTL32_AdjustUnicodeBuffer. • Use DWORD instead of INT for COMCTL32_UnicodeBuffer.sizeInBytes for consistency with Alloc and negative buffer size doesn't make sense. • Don't forget old COMCTL32_UnicodeBuffer.address when ReAlloc returns NULL. --- dlls/comctl32/comctl32.h | 12 ++ dlls/comctl32/commctrl.c | 439 +++++++++++++++++++++++++++++++++++++++ dlls/comctl32/pager.c | 432 +------------------------------------- 3 files changed, 454 insertions(+), 429 deletions(-)
diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h index f44b4ae132f..1bb1f8d0461 100644 --- a/dlls/comctl32/comctl32.h +++ b/dlls/comctl32/comctl32.h @@ -216,6 +216,18 @@ typedef struct int running; } SUBCLASS_INFO, *LPSUBCLASS_INFO;
+/* WM_NOTIFY unicode to ansi conversion and forwarding stuff */ + +/* COMCTL32_UnicodeBuffer is for storing result of ansi to unicode conversion that happens after SendMessageW */ +/* (b.address==NULL)==(b.sizeInBytes==0) && (b.sizeInBytes&1)==0 should always be true (b is COMCTL32_UnicodeBuffer) */ +typedef struct +{ + WCHAR *address; + DWORD sizeInBytes; +} COMCTL32_UnicodeBuffer; + +LRESULT COMCTL32_ForwardNotifyToAnsiWindow(HWND hwndNotify, NMHDR *hdr, COMCTL32_UnicodeBuffer *unicodeBuffer); + /* undocumented functions */
BOOL WINAPI Free (LPVOID); diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index d87e63e813e..d7d2a195a82 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c @@ -2691,3 +2691,442 @@ LRESULT WINAPI SendNotifyEx(HWND hwndTo, HWND hwndFrom, UINT code, NMHDR *hdr, D
return DoNotify(¬ify, code, hdr); } + +/* Text field conversion behavior flags for COMCTL32_SendConvertedNotify() */ +enum conversion_flags +{ + /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */ + CONVERT_SEND = 0x01, + /* Convert ANSI text from parent back to Unicode for children */ + CONVERT_RECEIVE = 0x02, + /* Send empty text to parent if text is NULL. Original text pointer still remains NULL */ + SEND_EMPTY_IF_NULL = 0x04, + /* Set text to null after parent received the notification if the required mask is not set before sending notification */ + SET_NULL_IF_NO_MASK = 0x08, + /* Zero out the text buffer before sending it to parent */ + ZERO_SEND = 0x10 +}; + +static UINT COMCTL32_GetAnsiNtfCode(UINT code) +{ + switch (code) + { + /* ComboxBoxEx */ + case CBEN_DRAGBEGINW: return CBEN_DRAGBEGINA; + case CBEN_ENDEDITW: return CBEN_ENDEDITA; + case CBEN_GETDISPINFOW: return CBEN_GETDISPINFOA; + /* Date and Time Picker */ + case DTN_FORMATW: return DTN_FORMATA; + case DTN_FORMATQUERYW: return DTN_FORMATQUERYA; + case DTN_USERSTRINGW: return DTN_USERSTRINGA; + case DTN_WMKEYDOWNW: return DTN_WMKEYDOWNA; + /* Header */ + case HDN_BEGINTRACKW: return HDN_BEGINTRACKA; + case HDN_DIVIDERDBLCLICKW: return HDN_DIVIDERDBLCLICKA; + case HDN_ENDTRACKW: return HDN_ENDTRACKA; + case HDN_GETDISPINFOW: return HDN_GETDISPINFOA; + case HDN_ITEMCHANGEDW: return HDN_ITEMCHANGEDA; + case HDN_ITEMCHANGINGW: return HDN_ITEMCHANGINGA; + case HDN_ITEMCLICKW: return HDN_ITEMCLICKA; + case HDN_ITEMDBLCLICKW: return HDN_ITEMDBLCLICKA; + case HDN_TRACKW: return HDN_TRACKA; + /* List View */ + case LVN_BEGINLABELEDITW: return LVN_BEGINLABELEDITA; + case LVN_ENDLABELEDITW: return LVN_ENDLABELEDITA; + case LVN_GETDISPINFOW: return LVN_GETDISPINFOA; + case LVN_GETINFOTIPW: return LVN_GETINFOTIPA; + case LVN_INCREMENTALSEARCHW: return LVN_INCREMENTALSEARCHA; + case LVN_ODFINDITEMW: return LVN_ODFINDITEMA; + case LVN_SETDISPINFOW: return LVN_SETDISPINFOA; + /* Toolbar */ + case TBN_GETBUTTONINFOW: return TBN_GETBUTTONINFOA; + case TBN_GETINFOTIPW: return TBN_GETINFOTIPA; + /* Tooltip */ + case TTN_GETDISPINFOW: return TTN_GETDISPINFOA; + /* Tree View */ + case TVN_BEGINDRAGW: return TVN_BEGINDRAGA; + case TVN_BEGINLABELEDITW: return TVN_BEGINLABELEDITA; + case TVN_BEGINRDRAGW: return TVN_BEGINRDRAGA; + case TVN_DELETEITEMW: return TVN_DELETEITEMA; + case TVN_ENDLABELEDITW: return TVN_ENDLABELEDITA; + case TVN_GETDISPINFOW: return TVN_GETDISPINFOA; + case TVN_GETINFOTIPW: return TVN_GETINFOTIPA; + case TVN_ITEMEXPANDEDW: return TVN_ITEMEXPANDEDA; + case TVN_ITEMEXPANDINGW: return TVN_ITEMEXPANDINGA; + case TVN_SELCHANGEDW: return TVN_SELCHANGEDA; + case TVN_SELCHANGINGW: return TVN_SELCHANGINGA; + case TVN_SETDISPINFOW: return TVN_SETDISPINFOA; + } + return code; +} + +/* grow a COMCTL32_UnicodeBuffer if needed so it can hold at least minWChars WCHARs */ +/* return FALSE means failed (unicodeBuffer still valid but too small) */ +/* return TRUE means successful */ +static BOOL COMCTL32_AdjustUnicodeBuffer(COMCTL32_UnicodeBuffer *unicodeBuffer, DWORD minWChars) +{ + WCHAR *address; + DWORD minSizeInBytes; + + if (minWChars > ~(DWORD)0 / sizeof(WCHAR)) + return FALSE; + minSizeInBytes = minWChars * sizeof(WCHAR); + if (unicodeBuffer->sizeInBytes >= minSizeInBytes) + return TRUE; + address = unicodeBuffer->address; + address = address ? ReAlloc(address, minSizeInBytes) : Alloc(minSizeInBytes); + if (!address) + return FALSE; + *unicodeBuffer = (COMCTL32_UnicodeBuffer) { + .address = address, + .sizeInBytes = minSizeInBytes + }; + return TRUE; +} + +/* Convert text to Unicode and return the original text address */ +static WCHAR *COMCTL32_ConvertText(WCHAR **text) +{ + WCHAR *oldText = *text; + *text = NULL; + Str_SetPtrWtoA((CHAR **)text, oldText); + return oldText; +} + +static void COMCTL32_RestoreText(WCHAR **text, WCHAR *oldText) +{ + if (!oldText) return; + + Free(*text); + *text = oldText; +} + +static LRESULT COMCTL32_SendConvertedNotify(HWND hwndNotify, NMHDR *hdr, UINT *mask, UINT requiredMask, WCHAR **text, + INT *textMax, DWORD flags) +{ + CHAR *sendBuffer = NULL; + CHAR *receiveBuffer; + INT bufferSize; + WCHAR *oldText; + INT oldTextMax; + LRESULT ret = NO_ERROR; + + oldText = *text; + oldTextMax = textMax ? *textMax : 0; + + hdr->code = COMCTL32_GetAnsiNtfCode(hdr->code); + + if (mask && !(*mask & requiredMask)) + { + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + if (flags & SET_NULL_IF_NO_MASK) oldText = NULL; + goto done; + } + + if (oldTextMax < 0) goto done; + + if ((*text && flags & (CONVERT_SEND | ZERO_SEND)) || (!*text && flags & SEND_EMPTY_IF_NULL)) + { + bufferSize = textMax ? *textMax : lstrlenW(*text) + 1; + sendBuffer = Alloc(bufferSize); + if (!sendBuffer) goto done; + if (!(flags & ZERO_SEND)) WideCharToMultiByte(CP_ACP, 0, *text, -1, sendBuffer, bufferSize, NULL, FALSE); + *text = (WCHAR *)sendBuffer; + } + + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + + if (*text && oldText && (flags & CONVERT_RECEIVE)) + { + /* MultiByteToWideChar requires that source and destination are not the same buffer */ + if (*text == oldText) + { + bufferSize = lstrlenA((CHAR *)*text) + 1; + receiveBuffer = Alloc(bufferSize); + if (!receiveBuffer) goto done; + memcpy(receiveBuffer, *text, bufferSize); + MultiByteToWideChar(CP_ACP, 0, receiveBuffer, bufferSize, oldText, oldTextMax); + Free(receiveBuffer); + } + else + MultiByteToWideChar(CP_ACP, 0, (CHAR *)*text, -1, oldText, oldTextMax); + } + +done: + Free(sendBuffer); + *text = oldText; + return ret; +} + +LRESULT COMCTL32_ForwardNotifyToAnsiWindow(HWND hwndNotify, NMHDR *hdr, COMCTL32_UnicodeBuffer *unicodeBuffer) +{ + LRESULT ret; + + switch (hdr->code) + { + /* ComboBoxEx */ + case CBEN_GETDISPINFOW: + { + NMCOMBOBOXEXW *nmcbe = (NMCOMBOBOXEXW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmcbe->ceItem.mask, CBEIF_TEXT, &nmcbe->ceItem.pszText, + &nmcbe->ceItem.cchTextMax, ZERO_SEND | SET_NULL_IF_NO_MASK | CONVERT_RECEIVE); + } + case CBEN_DRAGBEGINW: + { + NMCBEDRAGBEGINW *nmdbW = (NMCBEDRAGBEGINW *)hdr; + NMCBEDRAGBEGINA nmdbA = {{0}}; + nmdbA.hdr.code = COMCTL32_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(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmdbA); + } + case CBEN_ENDEDITW: + { + NMCBEENDEDITW *nmedW = (NMCBEENDEDITW *)hdr; + NMCBEENDEDITA nmedA = {{0}}; + nmedA.hdr.code = COMCTL32_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(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmedA); + } + /* Date and Time Picker */ + case DTN_FORMATW: + { + NMDATETIMEFORMATW *nmdtf = (NMDATETIMEFORMATW *)hdr; + WCHAR *oldFormat; + DWORD textLength; + + hdr->code = COMCTL32_GetAnsiNtfCode(hdr->code); + oldFormat = COMCTL32_ConvertText((WCHAR **)&nmdtf->pszFormat); + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)nmdtf); + COMCTL32_RestoreText((WCHAR **)&nmdtf->pszFormat, oldFormat); + + if (nmdtf->pszDisplay) + { + textLength = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, 0, 0); + if (!COMCTL32_AdjustUnicodeBuffer(unicodeBuffer, textLength)) return ret; + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, unicodeBuffer->address, textLength); + if (nmdtf->pszDisplay != nmdtf->szDisplay) + nmdtf->pszDisplay = unicodeBuffer->address; + else + { + textLength = min(textLength, ARRAY_SIZE(nmdtf->szDisplay)); + memcpy(nmdtf->szDisplay, unicodeBuffer->address, textLength * sizeof(WCHAR)); + } + } + + return ret; + } + case DTN_FORMATQUERYW: + { + NMDATETIMEFORMATQUERYW *nmdtfq = (NMDATETIMEFORMATQUERYW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, (WCHAR **)&nmdtfq->pszFormat, NULL, CONVERT_SEND); + } + case DTN_WMKEYDOWNW: + { + NMDATETIMEWMKEYDOWNW *nmdtkd = (NMDATETIMEWMKEYDOWNW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, (WCHAR **)&nmdtkd->pszFormat, NULL, CONVERT_SEND); + } + case DTN_USERSTRINGW: + { + NMDATETIMESTRINGW *nmdts = (NMDATETIMESTRINGW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, (WCHAR **)&nmdts->pszUserString, NULL, CONVERT_SEND); + } + /* Header */ + case HDN_BEGINTRACKW: + case HDN_DIVIDERDBLCLICKW: + case HDN_ENDTRACKW: + case HDN_ITEMCHANGEDW: + case HDN_ITEMCHANGINGW: + case HDN_ITEMCLICKW: + case HDN_ITEMDBLCLICKW: + case HDN_TRACKW: + { + NMHEADERW *nmh = (NMHEADERW *)hdr; + WCHAR *oldText = NULL, *oldFilterText = NULL; + HD_TEXTFILTERW *tf = NULL; + + hdr->code = COMCTL32_GetAnsiNtfCode(hdr->code); + + if (!nmh->pitem) return SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + if (nmh->pitem->mask & HDI_TEXT) oldText = COMCTL32_ConvertText(&nmh->pitem->pszText); + if ((nmh->pitem->mask & HDI_FILTER) && (nmh->pitem->type == HDFT_ISSTRING) && nmh->pitem->pvFilter) + { + tf = (HD_TEXTFILTERW *)nmh->pitem->pvFilter; + oldFilterText = COMCTL32_ConvertText(&tf->pszText); + } + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + COMCTL32_RestoreText(&nmh->pitem->pszText, oldText); + if (tf) COMCTL32_RestoreText(&tf->pszText, oldFilterText); + return ret; + } + case HDN_GETDISPINFOW: + { + NMHDDISPINFOW *nmhddi = (NMHDDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmhddi->mask, HDI_TEXT, &nmhddi->pszText, &nmhddi->cchTextMax, + SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); + } + /* List View */ + case LVN_BEGINLABELEDITW: + case LVN_ENDLABELEDITW: + case LVN_SETDISPINFOW: + { + NMLVDISPINFOW *nmlvdi = (NMLVDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmlvdi->item.mask, LVIF_TEXT, &nmlvdi->item.pszText, + &nmlvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); + } + case LVN_GETDISPINFOW: + { + NMLVDISPINFOW *nmlvdi = (NMLVDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmlvdi->item.mask, LVIF_TEXT, &nmlvdi->item.pszText, + &nmlvdi->item.cchTextMax, CONVERT_RECEIVE); + } + case LVN_GETINFOTIPW: + { + NMLVGETINFOTIPW *nmlvgit = (NMLVGETINFOTIPW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, &nmlvgit->pszText, &nmlvgit->cchTextMax, + CONVERT_SEND | CONVERT_RECEIVE); + } + case LVN_INCREMENTALSEARCHW: + case LVN_ODFINDITEMW: + { + NMLVFINDITEMW *nmlvfi = (NMLVFINDITEMW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmlvfi->lvfi.flags, LVFI_STRING | LVFI_SUBSTRING, + (WCHAR **)&nmlvfi->lvfi.psz, NULL, CONVERT_SEND); + } + /* Toolbar */ + case TBN_GETBUTTONINFOW: + { + NMTOOLBARW *nmtb = (NMTOOLBARW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, &nmtb->pszText, &nmtb->cchText, + SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); + } + case TBN_GETINFOTIPW: + { + NMTBGETINFOTIPW *nmtbgit = (NMTBGETINFOTIPW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, &nmtbgit->pszText, &nmtbgit->cchTextMax, CONVERT_RECEIVE); + } + /* Tooltip */ + case TTN_GETDISPINFOW: + { + NMTTDISPINFOW *nmttdiW = (NMTTDISPINFOW *)hdr; + NMTTDISPINFOA nmttdiA = {{0}}; + DWORD size; + + nmttdiA.hdr.code = COMCTL32_GetAnsiNtfCode(nmttdiW->hdr.code); + nmttdiA.hdr.hwndFrom = nmttdiW->hdr.hwndFrom; + nmttdiA.hdr.idFrom = nmttdiW->hdr.idFrom; + nmttdiA.hinst = nmttdiW->hinst; + nmttdiA.uFlags = nmttdiW->uFlags; + nmttdiA.lParam = nmttdiW->lParam; + nmttdiA.lpszText = nmttdiA.szText; + WideCharToMultiByte(CP_ACP, 0, nmttdiW->szText, ARRAY_SIZE(nmttdiW->szText), nmttdiA.szText, + ARRAY_SIZE(nmttdiA.szText), NULL, FALSE); + + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmttdiA); + + nmttdiW->hinst = nmttdiA.hinst; + nmttdiW->uFlags = nmttdiA.uFlags; + nmttdiW->lParam = nmttdiA.lParam; + + MultiByteToWideChar(CP_ACP, 0, nmttdiA.szText, ARRAY_SIZE(nmttdiA.szText), nmttdiW->szText, + ARRAY_SIZE(nmttdiW->szText)); + if (!nmttdiA.lpszText) + nmttdiW->lpszText = nmttdiW->szText; + else if (!IS_INTRESOURCE(nmttdiA.lpszText)) + { + size = MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, 0, 0); + if (size > ARRAY_SIZE(nmttdiW->szText)) + { + if (!COMCTL32_AdjustUnicodeBuffer(unicodeBuffer, size)) return ret; + MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, unicodeBuffer->address, size); + nmttdiW->lpszText = unicodeBuffer->address; + /* Override content in szText */ + memcpy(nmttdiW->szText, nmttdiW->lpszText, min(sizeof(nmttdiW->szText), size * sizeof(WCHAR))); + } + else + { + MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, nmttdiW->szText, ARRAY_SIZE(nmttdiW->szText)); + nmttdiW->lpszText = nmttdiW->szText; + } + } + else + { + nmttdiW->szText[0] = 0; + nmttdiW->lpszText = (WCHAR *)nmttdiA.lpszText; + } + + return ret; + } + /* Tree View */ + case TVN_BEGINDRAGW: + case TVN_BEGINRDRAGW: + case TVN_ITEMEXPANDEDW: + case TVN_ITEMEXPANDINGW: + { + NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmtv->itemNew.mask, TVIF_TEXT, &nmtv->itemNew.pszText, NULL, + CONVERT_SEND); + } + case TVN_DELETEITEMW: + { + NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmtv->itemOld.mask, TVIF_TEXT, &nmtv->itemOld.pszText, NULL, + CONVERT_SEND); + } + case TVN_BEGINLABELEDITW: + case TVN_ENDLABELEDITW: + { + NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, + &nmtvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); + } + case TVN_SELCHANGINGW: + case TVN_SELCHANGEDW: + { + NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; + WCHAR *oldItemOldText = NULL; + WCHAR *oldItemNewText = NULL; + + hdr->code = COMCTL32_GetAnsiNtfCode(hdr->code); + + if (!((nmtv->itemNew.mask | nmtv->itemOld.mask) & TVIF_TEXT)) + return SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + + if (nmtv->itemOld.mask & TVIF_TEXT) oldItemOldText = COMCTL32_ConvertText(&nmtv->itemOld.pszText); + if (nmtv->itemNew.mask & TVIF_TEXT) oldItemNewText = COMCTL32_ConvertText(&nmtv->itemNew.pszText); + + ret = SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + COMCTL32_RestoreText(&nmtv->itemOld.pszText, oldItemOldText); + COMCTL32_RestoreText(&nmtv->itemNew.pszText, oldItemNewText); + return ret; + } + case TVN_GETDISPINFOW: + { + NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, + &nmtvdi->item.cchTextMax, ZERO_SEND | CONVERT_RECEIVE); + } + case TVN_SETDISPINFOW: + { + NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, + &nmtvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); + } + case TVN_GETINFOTIPW: + { + NMTVGETINFOTIPW *nmtvgit = (NMTVGETINFOTIPW *)hdr; + return COMCTL32_SendConvertedNotify(hwndNotify, hdr, NULL, 0, &nmtvgit->pszText, &nmtvgit->cchTextMax, CONVERT_RECEIVE); + } + } + /* Other notifications, no need to convert */ + return SendMessageW(hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); +} diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c index 07484c6ebf5..cb889177fe4 100644 --- a/dlls/comctl32/pager.c +++ b/dlls/comctl32/pager.c @@ -84,8 +84,7 @@ typedef struct INT TLbtnState; /* state of top or left btn */ INT BRbtnState; /* state of bottom or right btn */ INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */ - WCHAR *pwszBuffer;/* text buffer for converted notifications */ - INT nBufferSize;/* size of the above buffer */ + COMCTL32_UnicodeBuffer unicodeBuffer;/* used in WN_NOTIFY forwarding if bUnicode */ } PAGER_INFO;
#define TIMERID1 1 @@ -93,21 +92,6 @@ typedef struct #define INITIAL_DELAY 500 #define REPEAT_DELAY 50
-/* Text field conversion behavior flags for PAGER_SendConvertedNotify() */ -enum conversion_flags -{ - /* Convert Unicode text to ANSI for parent before sending. If not set, do nothing */ - CONVERT_SEND = 0x01, - /* Convert ANSI text from parent back to Unicode for children */ - CONVERT_RECEIVE = 0x02, - /* Send empty text to parent if text is NULL. Original text pointer still remains NULL */ - SEND_EMPTY_IF_NULL = 0x04, - /* Set text to null after parent received the notification if the required mask is not set before sending notification */ - SET_NULL_IF_NO_MASK = 0x08, - /* Zero out the text buffer before sending it to parent */ - ZERO_SEND = 0x10 -}; - static void PAGER_GetButtonRects(const PAGER_INFO* infoPtr, RECT* prcTopLeft, RECT* prcBottomRight, BOOL bClientCoords) { @@ -611,7 +595,7 @@ static LRESULT PAGER_Destroy (PAGER_INFO *infoPtr) { SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - Free (infoPtr->pwszBuffer); + Free (infoPtr->unicodeBuffer.address); Free (infoPtr); return 0; } @@ -1043,419 +1027,9 @@ static LRESULT PAGER_NotifyFormat(PAGER_INFO *infoPtr, INT command) } }
-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; - /* Date and Time Picker */ - case DTN_FORMATW: return DTN_FORMATA; - case DTN_FORMATQUERYW: return DTN_FORMATQUERYA; - case DTN_USERSTRINGW: return DTN_USERSTRINGA; - case DTN_WMKEYDOWNW: return DTN_WMKEYDOWNA; - /* Header */ - case HDN_BEGINTRACKW: return HDN_BEGINTRACKA; - case HDN_DIVIDERDBLCLICKW: return HDN_DIVIDERDBLCLICKA; - case HDN_ENDTRACKW: return HDN_ENDTRACKA; - case HDN_GETDISPINFOW: return HDN_GETDISPINFOA; - case HDN_ITEMCHANGEDW: return HDN_ITEMCHANGEDA; - case HDN_ITEMCHANGINGW: return HDN_ITEMCHANGINGA; - case HDN_ITEMCLICKW: return HDN_ITEMCLICKA; - case HDN_ITEMDBLCLICKW: return HDN_ITEMDBLCLICKA; - case HDN_TRACKW: return HDN_TRACKA; - /* List View */ - case LVN_BEGINLABELEDITW: return LVN_BEGINLABELEDITA; - case LVN_ENDLABELEDITW: return LVN_ENDLABELEDITA; - case LVN_GETDISPINFOW: return LVN_GETDISPINFOA; - case LVN_GETINFOTIPW: return LVN_GETINFOTIPA; - case LVN_INCREMENTALSEARCHW: return LVN_INCREMENTALSEARCHA; - case LVN_ODFINDITEMW: return LVN_ODFINDITEMA; - case LVN_SETDISPINFOW: return LVN_SETDISPINFOA; - /* Toolbar */ - case TBN_GETBUTTONINFOW: return TBN_GETBUTTONINFOA; - case TBN_GETINFOTIPW: return TBN_GETINFOTIPA; - /* Tooltip */ - case TTN_GETDISPINFOW: return TTN_GETDISPINFOA; - /* Tree View */ - case TVN_BEGINDRAGW: return TVN_BEGINDRAGA; - case TVN_BEGINLABELEDITW: return TVN_BEGINLABELEDITA; - case TVN_BEGINRDRAGW: return TVN_BEGINRDRAGA; - case TVN_DELETEITEMW: return TVN_DELETEITEMA; - case TVN_ENDLABELEDITW: return TVN_ENDLABELEDITA; - case TVN_GETDISPINFOW: return TVN_GETDISPINFOA; - case TVN_GETINFOTIPW: return TVN_GETINFOTIPA; - case TVN_ITEMEXPANDEDW: return TVN_ITEMEXPANDEDA; - case TVN_ITEMEXPANDINGW: return TVN_ITEMEXPANDINGA; - case TVN_SELCHANGEDW: return TVN_SELCHANGEDA; - case TVN_SELCHANGINGW: return TVN_SELCHANGINGA; - case TVN_SETDISPINFOW: return TVN_SETDISPINFOA; - } - return code; -} - -static BOOL PAGER_AdjustBuffer(PAGER_INFO *infoPtr, INT size) -{ - if (!infoPtr->pwszBuffer) - infoPtr->pwszBuffer = Alloc(size); - else if (infoPtr->nBufferSize < size) - infoPtr->pwszBuffer = ReAlloc(infoPtr->pwszBuffer, size); - - if (!infoPtr->pwszBuffer) return FALSE; - if (infoPtr->nBufferSize < size) infoPtr->nBufferSize = size; - - return TRUE; -} - -/* Convert text to Unicode and return the original text address */ -static WCHAR *PAGER_ConvertText(WCHAR **text) -{ - WCHAR *oldText = *text; - *text = NULL; - Str_SetPtrWtoA((CHAR **)text, oldText); - return oldText; -} - -static void PAGER_RestoreText(WCHAR **text, WCHAR *oldText) -{ - if (!oldText) return; - - Free(*text); - *text = oldText; -} - -static LRESULT PAGER_SendConvertedNotify(PAGER_INFO *infoPtr, NMHDR *hdr, UINT *mask, UINT requiredMask, WCHAR **text, - INT *textMax, DWORD flags) -{ - CHAR *sendBuffer = NULL; - CHAR *receiveBuffer; - INT bufferSize; - WCHAR *oldText; - INT oldTextMax; - LRESULT ret = NO_ERROR; - - oldText = *text; - oldTextMax = textMax ? *textMax : 0; - - hdr->code = PAGER_GetAnsiNtfCode(hdr->code); - - if (mask && !(*mask & requiredMask)) - { - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - if (flags & SET_NULL_IF_NO_MASK) oldText = NULL; - goto done; - } - - if (oldTextMax < 0) goto done; - - if ((*text && flags & (CONVERT_SEND | ZERO_SEND)) || (!*text && flags & SEND_EMPTY_IF_NULL)) - { - bufferSize = textMax ? *textMax : lstrlenW(*text) + 1; - sendBuffer = Alloc(bufferSize); - if (!sendBuffer) goto done; - if (!(flags & ZERO_SEND)) WideCharToMultiByte(CP_ACP, 0, *text, -1, sendBuffer, bufferSize, NULL, FALSE); - *text = (WCHAR *)sendBuffer; - } - - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - - if (*text && oldText && (flags & CONVERT_RECEIVE)) - { - /* MultiByteToWideChar requires that source and destination are not the same buffer */ - if (*text == oldText) - { - bufferSize = lstrlenA((CHAR *)*text) + 1; - receiveBuffer = Alloc(bufferSize); - if (!receiveBuffer) goto done; - memcpy(receiveBuffer, *text, bufferSize); - MultiByteToWideChar(CP_ACP, 0, receiveBuffer, bufferSize, oldText, oldTextMax); - Free(receiveBuffer); - } - else - MultiByteToWideChar(CP_ACP, 0, (CHAR *)*text, -1, oldText, oldTextMax); - } - -done: - Free(sendBuffer); - *text = oldText; - return ret; -} - static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) { - LRESULT ret; - - if (infoPtr->bUnicode) return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)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, ZERO_SEND | SET_NULL_IF_NO_MASK | CONVERT_RECEIVE); - } - 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); - } - /* Date and Time Picker */ - case DTN_FORMATW: - { - NMDATETIMEFORMATW *nmdtf = (NMDATETIMEFORMATW *)hdr; - WCHAR *oldFormat; - INT textLength; - - hdr->code = PAGER_GetAnsiNtfCode(hdr->code); - oldFormat = PAGER_ConvertText((WCHAR **)&nmdtf->pszFormat); - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)nmdtf); - PAGER_RestoreText((WCHAR **)&nmdtf->pszFormat, oldFormat); - - if (nmdtf->pszDisplay) - { - textLength = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, 0, 0); - if (!PAGER_AdjustBuffer(infoPtr, textLength * sizeof(WCHAR))) return ret; - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, infoPtr->pwszBuffer, textLength); - if (nmdtf->pszDisplay != nmdtf->szDisplay) - nmdtf->pszDisplay = infoPtr->pwszBuffer; - else - { - textLength = min(textLength, ARRAY_SIZE(nmdtf->szDisplay)); - memcpy(nmdtf->szDisplay, infoPtr->pwszBuffer, textLength * sizeof(WCHAR)); - } - } - - return ret; - } - case DTN_FORMATQUERYW: - { - NMDATETIMEFORMATQUERYW *nmdtfq = (NMDATETIMEFORMATQUERYW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, (WCHAR **)&nmdtfq->pszFormat, NULL, CONVERT_SEND); - } - case DTN_WMKEYDOWNW: - { - NMDATETIMEWMKEYDOWNW *nmdtkd = (NMDATETIMEWMKEYDOWNW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, (WCHAR **)&nmdtkd->pszFormat, NULL, CONVERT_SEND); - } - case DTN_USERSTRINGW: - { - NMDATETIMESTRINGW *nmdts = (NMDATETIMESTRINGW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, (WCHAR **)&nmdts->pszUserString, NULL, CONVERT_SEND); - } - /* Header */ - case HDN_BEGINTRACKW: - case HDN_DIVIDERDBLCLICKW: - case HDN_ENDTRACKW: - case HDN_ITEMCHANGEDW: - case HDN_ITEMCHANGINGW: - case HDN_ITEMCLICKW: - case HDN_ITEMDBLCLICKW: - case HDN_TRACKW: - { - NMHEADERW *nmh = (NMHEADERW *)hdr; - WCHAR *oldText = NULL, *oldFilterText = NULL; - HD_TEXTFILTERW *tf = NULL; - - hdr->code = PAGER_GetAnsiNtfCode(hdr->code); - - if (!nmh->pitem) return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - if (nmh->pitem->mask & HDI_TEXT) oldText = PAGER_ConvertText(&nmh->pitem->pszText); - if ((nmh->pitem->mask & HDI_FILTER) && (nmh->pitem->type == HDFT_ISSTRING) && nmh->pitem->pvFilter) - { - tf = (HD_TEXTFILTERW *)nmh->pitem->pvFilter; - oldFilterText = PAGER_ConvertText(&tf->pszText); - } - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - PAGER_RestoreText(&nmh->pitem->pszText, oldText); - if (tf) PAGER_RestoreText(&tf->pszText, oldFilterText); - return ret; - } - case HDN_GETDISPINFOW: - { - NMHDDISPINFOW *nmhddi = (NMHDDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmhddi->mask, HDI_TEXT, &nmhddi->pszText, &nmhddi->cchTextMax, - SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); - } - /* List View */ - case LVN_BEGINLABELEDITW: - case LVN_ENDLABELEDITW: - case LVN_SETDISPINFOW: - { - NMLVDISPINFOW *nmlvdi = (NMLVDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmlvdi->item.mask, LVIF_TEXT, &nmlvdi->item.pszText, - &nmlvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); - } - case LVN_GETDISPINFOW: - { - NMLVDISPINFOW *nmlvdi = (NMLVDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmlvdi->item.mask, LVIF_TEXT, &nmlvdi->item.pszText, - &nmlvdi->item.cchTextMax, CONVERT_RECEIVE); - } - case LVN_GETINFOTIPW: - { - NMLVGETINFOTIPW *nmlvgit = (NMLVGETINFOTIPW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmlvgit->pszText, &nmlvgit->cchTextMax, - CONVERT_SEND | CONVERT_RECEIVE); - } - case LVN_INCREMENTALSEARCHW: - case LVN_ODFINDITEMW: - { - NMLVFINDITEMW *nmlvfi = (NMLVFINDITEMW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmlvfi->lvfi.flags, LVFI_STRING | LVFI_SUBSTRING, - (WCHAR **)&nmlvfi->lvfi.psz, NULL, CONVERT_SEND); - } - /* Toolbar */ - case TBN_GETBUTTONINFOW: - { - NMTOOLBARW *nmtb = (NMTOOLBARW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtb->pszText, &nmtb->cchText, - SEND_EMPTY_IF_NULL | CONVERT_SEND | CONVERT_RECEIVE); - } - case TBN_GETINFOTIPW: - { - NMTBGETINFOTIPW *nmtbgit = (NMTBGETINFOTIPW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtbgit->pszText, &nmtbgit->cchTextMax, CONVERT_RECEIVE); - } - /* Tooltip */ - case TTN_GETDISPINFOW: - { - NMTTDISPINFOW *nmttdiW = (NMTTDISPINFOW *)hdr; - NMTTDISPINFOA nmttdiA = {{0}}; - INT size; - - nmttdiA.hdr.code = PAGER_GetAnsiNtfCode(nmttdiW->hdr.code); - nmttdiA.hdr.hwndFrom = nmttdiW->hdr.hwndFrom; - nmttdiA.hdr.idFrom = nmttdiW->hdr.idFrom; - nmttdiA.hinst = nmttdiW->hinst; - nmttdiA.uFlags = nmttdiW->uFlags; - nmttdiA.lParam = nmttdiW->lParam; - nmttdiA.lpszText = nmttdiA.szText; - WideCharToMultiByte(CP_ACP, 0, nmttdiW->szText, ARRAY_SIZE(nmttdiW->szText), nmttdiA.szText, - ARRAY_SIZE(nmttdiA.szText), NULL, FALSE); - - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)&nmttdiA); - - nmttdiW->hinst = nmttdiA.hinst; - nmttdiW->uFlags = nmttdiA.uFlags; - nmttdiW->lParam = nmttdiA.lParam; - - MultiByteToWideChar(CP_ACP, 0, nmttdiA.szText, ARRAY_SIZE(nmttdiA.szText), nmttdiW->szText, - ARRAY_SIZE(nmttdiW->szText)); - if (!nmttdiA.lpszText) - nmttdiW->lpszText = nmttdiW->szText; - else if (!IS_INTRESOURCE(nmttdiA.lpszText)) - { - size = MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, 0, 0); - if (size > ARRAY_SIZE(nmttdiW->szText)) - { - if (!PAGER_AdjustBuffer(infoPtr, size * sizeof(WCHAR))) return ret; - MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, infoPtr->pwszBuffer, size); - nmttdiW->lpszText = infoPtr->pwszBuffer; - /* Override content in szText */ - memcpy(nmttdiW->szText, nmttdiW->lpszText, min(sizeof(nmttdiW->szText), size * sizeof(WCHAR))); - } - else - { - MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, nmttdiW->szText, ARRAY_SIZE(nmttdiW->szText)); - nmttdiW->lpszText = nmttdiW->szText; - } - } - else - { - nmttdiW->szText[0] = 0; - nmttdiW->lpszText = (WCHAR *)nmttdiA.lpszText; - } - - return ret; - } - /* Tree View */ - case TVN_BEGINDRAGW: - case TVN_BEGINRDRAGW: - case TVN_ITEMEXPANDEDW: - case TVN_ITEMEXPANDINGW: - { - NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtv->itemNew.mask, TVIF_TEXT, &nmtv->itemNew.pszText, NULL, - CONVERT_SEND); - } - case TVN_DELETEITEMW: - { - NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtv->itemOld.mask, TVIF_TEXT, &nmtv->itemOld.pszText, NULL, - CONVERT_SEND); - } - case TVN_BEGINLABELEDITW: - case TVN_ENDLABELEDITW: - { - NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, - &nmtvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); - } - case TVN_SELCHANGINGW: - case TVN_SELCHANGEDW: - { - NMTREEVIEWW *nmtv = (NMTREEVIEWW *)hdr; - WCHAR *oldItemOldText = NULL; - WCHAR *oldItemNewText = NULL; - - hdr->code = PAGER_GetAnsiNtfCode(hdr->code); - - if (!((nmtv->itemNew.mask | nmtv->itemOld.mask) & TVIF_TEXT)) - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - - if (nmtv->itemOld.mask & TVIF_TEXT) oldItemOldText = PAGER_ConvertText(&nmtv->itemOld.pszText); - if (nmtv->itemNew.mask & TVIF_TEXT) oldItemNewText = PAGER_ConvertText(&nmtv->itemNew.pszText); - - ret = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); - PAGER_RestoreText(&nmtv->itemOld.pszText, oldItemOldText); - PAGER_RestoreText(&nmtv->itemNew.pszText, oldItemNewText); - return ret; - } - case TVN_GETDISPINFOW: - { - NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, - &nmtvdi->item.cchTextMax, ZERO_SEND | CONVERT_RECEIVE); - } - case TVN_SETDISPINFOW: - { - NMTVDISPINFOW *nmtvdi = (NMTVDISPINFOW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, &nmtvdi->item.mask, TVIF_TEXT, &nmtvdi->item.pszText, - &nmtvdi->item.cchTextMax, SET_NULL_IF_NO_MASK | CONVERT_SEND | CONVERT_RECEIVE); - } - case TVN_GETINFOTIPW: - { - NMTVGETINFOTIPW *nmtvgit = (NMTVGETINFOTIPW *)hdr; - return PAGER_SendConvertedNotify(infoPtr, hdr, NULL, 0, &nmtvgit->pszText, &nmtvgit->cchTextMax, CONVERT_RECEIVE); - } - } - /* Other notifications, no need to convert */ - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr); + return infoPtr->bUnicode ? SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, hdr->idFrom, (LPARAM)hdr) : COMCTL32_ForwardNotifyToAnsiWindow(infoPtr->hwndNotify, hdr, &infoPtr->unicodeBuffer); }
static LRESULT WINAPI
From: Alanas Tebuev alanas.00@mail.ru
This makes 7-Zip File Manager press enter in path input work.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57178 --- dlls/comctl32/tests/toolbar.c | 16 ++++++++-------- dlls/comctl32/toolbar.c | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/dlls/comctl32/tests/toolbar.c b/dlls/comctl32/tests/toolbar.c index df322dcd6da..4c11cdbab96 100644 --- a/dlls/comctl32/tests/toolbar.c +++ b/dlls/comctl32/tests/toolbar.c @@ -2913,14 +2913,14 @@ static void test_WM_NOTIFY(void)
test_WM_NOTIFY_expect_CBEN_ENDEDITW = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; ret = SendMessageW(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITW); - todo_wine ok(ret == 0xabcd0006, "SendMessageW returned 0x%Ix.\n", ret); - todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITW, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + ok(ret == 0xabcd0006, "SendMessageW returned 0x%Ix.\n", ret); + ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITW, "Toolbar didn't forward WM_NOTIFY to parent.\n"); test_WM_NOTIFY_expect_CBEN_ENDEDITW = TEST_WM_NOTIFY_NO_FORWARD;
test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; ret = SendMessageA(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITA); - todo_wine ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); - todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); + ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD;
parent_WM_NOTIFYFORMAT_return = NFR_ANSI; @@ -2928,13 +2928,13 @@ static void test_WM_NOTIFY(void)
test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_CONVERT; ret = SendMessageW(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITW); - todo_wine ok(ret == 0xabcd0007, "SendMessageW returned 0x%Ix.\n", ret); - todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't convert and forward WM_NOTIFY to parent.\n"); + ok(ret == 0xabcd0007, "SendMessageW returned 0x%Ix.\n", ret); + ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't convert and forward WM_NOTIFY to parent.\n");
test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_FORWARD_NO_CONVERT; ret = SendMessageA(toolbar, WM_NOTIFY, 0, (LPARAM)&test_WM_NOTIFY_NMCBEENDEDITA); - todo_wine ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); - todo_wine ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); + ok(ret == 0xabcd0007, "SendMessageA returned 0x%Ix.\n", ret); + ok(!test_WM_NOTIFY_expect_CBEN_ENDEDITA, "Toolbar didn't forward WM_NOTIFY to parent.\n"); test_WM_NOTIFY_expect_CBEN_ENDEDITA = TEST_WM_NOTIFY_NO_FORWARD;
DestroyWindow(toolbar); diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c index 690a02db6ee..84aaf648141 100644 --- a/dlls/comctl32/toolbar.c +++ b/dlls/comctl32/toolbar.c @@ -6359,7 +6359,21 @@ TOOLBAR_Notify (TOOLBAR_INFO *infoPtr, LPNMHDR lpnmh) FIXME("TTN_GETDISPINFOA - should not be received; please report\n"); return 0;
+ case CBEN_ENDEDITW: + if (infoPtr->bUnicode) + { + TRACE("Forwarding CBEN_ENDEDITW (no conversion).\n"); + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, lpnmh->idFrom, (LPARAM)lpnmh); + } + TRACE("Converting CBEN_ENDEDITW to CBEN_ENDEDITA and forwarding.\n"); + return COMCTL32_ForwardNotifyToAnsiWindow(infoPtr->hwndNotify, lpnmh, NULL); + + case CBEN_ENDEDITA: + TRACE("Forwarding CBEN_ENDEDITA (no conversion).\n"); + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, lpnmh->idFrom, (LPARAM)lpnmh); + default: + WARN("Should WM_NOTIFY NMHDR code 0x%x be forwarded?\n", lpnmh->code); return 0; } }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150467
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/comctl32/comctl32.h:216 error: patch failed: dlls/comctl32/commctrl.c:2691 error: patch failed: dlls/comctl32/pager.c:84 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/comctl32/comctl32.h:216 error: patch failed: dlls/comctl32/commctrl.c:2691 error: patch failed: dlls/comctl32/pager.c:84 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/comctl32/comctl32.h:216 error: patch failed: dlls/comctl32/commctrl.c:2691 error: patch failed: dlls/comctl32/pager.c:84 Task: Patch failed to apply
On Fri Dec 20 13:39:58 2024 +0000, Alanas Tebuev wrote:
I added `test_WM_NOTIFY_forwarding_to_parent` (tested in wine x86-64 and windows xp professional x64 edition service pack 2). I didn't fix `test_BTNS_SEP`.
<blockquote cite="https://gitlab.winehq.org/wine/wine/-/merge_requests/6737#note_86205">That's a bug that we'll need to patch. First time it's called it's meant to get a null handle, so local variable is missing initializer here.</blockquote><a href="https://gitlab.winehq.org/wine/wine/-/merge_requests/7044/diffs">done</a>