Nikolay Sivov : comctl32/listview: Use a code set by dispinfo holder to convert data encoding after LVN_GETDISPINFO .
Alexandre Julliard
julliard at winehq.org
Wed Nov 17 10:38:01 CST 2010
Module: wine
Branch: master
Commit: 119860b05f8c22d1525b573e461afe95e430a63b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=119860b05f8c22d1525b573e461afe95e430a63b
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue Nov 16 23:55:23 2010 +0300
comctl32/listview: Use a code set by dispinfo holder to convert data encoding after LVN_GETDISPINFO.
---
dlls/comctl32/listview.c | 130 ++++++++++++++++++++++++---------------
dlls/comctl32/tests/listview.c | 41 +++++++++++++
2 files changed, 121 insertions(+), 50 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 6c4165d..fd9a499 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -928,74 +928,104 @@ static BOOL notify_deleteitem(const LISTVIEW_INFO *infoPtr, INT nItem)
Send notification. depends on dispinfoW having same
structure as dispinfoA.
infoPtr : listview struct
- notificationCode : *Unicode* notification code
+ code : *Unicode* notification code
pdi : dispinfo structure (can be unicode or ansi)
isW : TRUE if dispinfo is Unicode
*/
-static BOOL notify_dispinfoT(const LISTVIEW_INFO *infoPtr, UINT notificationCode, LPNMLVDISPINFOW pdi, BOOL isW)
+static BOOL notify_dispinfoT(const LISTVIEW_INFO *infoPtr, UINT code, LPNMLVDISPINFOW pdi, BOOL isW)
{
- BOOL bResult = FALSE;
- BOOL convertToAnsi = FALSE, convertToUnicode = FALSE;
- INT cchTempBufMax = 0, savCchTextMax = 0;
- UINT realNotifCode;
- LPWSTR pszTempBuf = NULL, savPszText = NULL;
+ INT length = 0, ret_length;
+ LPWSTR buffer = NULL, ret_text;
+ BOOL return_ansi = FALSE;
+ BOOL return_unicode = FALSE;
+ BOOL ret;
if ((pdi->item.mask & LVIF_TEXT) && is_text(pdi->item.pszText))
{
- convertToAnsi = (isW && infoPtr->notifyFormat == NFR_ANSI);
- convertToUnicode = (!isW && infoPtr->notifyFormat == NFR_UNICODE);
+ return_unicode = ( isW && infoPtr->notifyFormat == NFR_ANSI);
+ return_ansi = (!isW && infoPtr->notifyFormat == NFR_UNICODE);
}
- if (convertToAnsi || convertToUnicode)
+ ret_length = pdi->item.cchTextMax;
+ ret_text = pdi->item.pszText;
+
+ if (return_unicode || return_ansi)
{
- if (notificationCode != LVN_GETDISPINFOW)
- {
- cchTempBufMax = convertToUnicode ?
+ if (code != LVN_GETDISPINFOW)
+ {
+ length = return_ansi ?
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, NULL, 0):
WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, NULL, 0, NULL, NULL);
- }
- else
- {
- cchTempBufMax = pdi->item.cchTextMax;
- *pdi->item.pszText = 0; /* make sure we don't process garbage */
- }
-
- pszTempBuf = Alloc( (convertToUnicode ? sizeof(WCHAR) : sizeof(CHAR)) * cchTempBufMax);
- if (!pszTempBuf) return FALSE;
-
- if (convertToUnicode)
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1,
- pszTempBuf, cchTempBufMax);
- else
- WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) pszTempBuf,
- cchTempBufMax, NULL, NULL);
+ }
+ else
+ {
+ length = pdi->item.cchTextMax;
+ *pdi->item.pszText = 0; /* make sure we don't process garbage */
+ }
- savCchTextMax = pdi->item.cchTextMax;
- savPszText = pdi->item.pszText;
- pdi->item.pszText = pszTempBuf;
- pdi->item.cchTextMax = cchTempBufMax;
+ buffer = Alloc( (return_ansi ? sizeof(WCHAR) : sizeof(CHAR)) * length);
+ if (!buffer) return FALSE;
+
+ if (return_ansi)
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1,
+ buffer, length);
+ else
+ WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) buffer,
+ length, NULL, NULL);
+
+ pdi->item.pszText = buffer;
+ pdi->item.cchTextMax = length;
}
if (infoPtr->notifyFormat == NFR_ANSI)
- realNotifCode = get_ansi_notification(notificationCode);
- else
- realNotifCode = notificationCode;
+ code = get_ansi_notification(code);
+
TRACE(" pdi->item=%s\n", debuglvitem_t(&pdi->item, infoPtr->notifyFormat != NFR_ANSI));
- bResult = notify_hdr(infoPtr, realNotifCode, &pdi->hdr);
+ ret = notify_hdr(infoPtr, code, &pdi->hdr);
+ TRACE(" resulting code=0x%08x\n", pdi->hdr.code);
- if (convertToUnicode || convertToAnsi)
+ if (return_ansi || return_unicode)
{
- if (convertToUnicode) /* note : pointer can be changed by app ! */
- WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) savPszText,
- savCchTextMax, NULL, NULL);
- else
- MultiByteToWideChar(CP_ACP, 0, (LPSTR) pdi->item.pszText, -1,
- savPszText, savCchTextMax);
- pdi->item.pszText = savPszText; /* restores our buffer */
- pdi->item.cchTextMax = savCchTextMax;
- Free (pszTempBuf);
+ if (return_ansi && (pdi->hdr.code == LVN_GETDISPINFOA))
+ {
+ strcpy((char*)ret_text, (char*)pdi->item.pszText);
+ }
+ else if (return_unicode && (pdi->hdr.code == LVN_GETDISPINFOW))
+ {
+ strcpyW(ret_text, pdi->item.pszText);
+ }
+ else if (return_ansi) /* note : pointer can be changed by app ! */
+ {
+ WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) ret_text,
+ ret_length, NULL, NULL);
+ }
+ else
+ MultiByteToWideChar(CP_ACP, 0, (LPSTR) pdi->item.pszText, -1,
+ ret_text, ret_length);
+
+ pdi->item.pszText = ret_text; /* restores our buffer */
+ pdi->item.cchTextMax = ret_length;
+
+ Free(buffer);
+ return ret;
}
- return bResult;
+
+ /* if dipsinfo holder changed notification code then convert */
+ if (!isW && (pdi->hdr.code == LVN_GETDISPINFOW))
+ {
+ length = WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, NULL, 0, NULL, NULL);
+
+ buffer = Alloc(length * sizeof(CHAR));
+ if (!buffer) return FALSE;
+
+ WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) buffer,
+ ret_length, NULL, NULL);
+
+ strcpy((LPSTR)pdi->item.pszText, (LPSTR)buffer);
+ Free(buffer);
+ }
+
+ return ret;
}
static void customdraw_fill(NMLVCUSTOMDRAW *lpnmlvcd, const LISTVIEW_INFO *infoPtr, HDC hdc,
@@ -6490,7 +6520,7 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
if (lpLVItem->mask & LVIF_STATE)
dispInfo.item.stateMask = lpLVItem->stateMask & infoPtr->uCallbackMask;
/* could be zeroed on LVIF_NORECOMPUTE case */
- if (dispInfo.item.mask != 0)
+ if (dispInfo.item.mask)
{
notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
dispInfo.item.stateMask = lpLVItem->stateMask;
@@ -6596,7 +6626,7 @@ static BOOL LISTVIEW_GetItemT(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem,
}
/* If we don't have all the requested info, query the application */
- if (dispInfo.item.mask != 0)
+ if (dispInfo.item.mask)
{
dispInfo.item.iItem = lpLVItem->iItem;
dispInfo.item.iSubItem = lpLVItem->iSubItem; /* yes: the original subitem */
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index 0223167..89619f7 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -59,6 +59,8 @@ static INT notifyFormat;
static BOOL g_is_below_5;
/* item data passed to LVN_GETDISPINFOA */
static LVITEMA g_itema;
+/* alter notification code A->W */
+static BOOL g_disp_A_to_W;
static HWND subclass_editbox(HWND hwndListview);
@@ -372,6 +374,13 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
{
NMLVDISPINFOA *dispinfo = (NMLVDISPINFOA*)lParam;
g_itema = dispinfo->item;
+
+ if (g_disp_A_to_W && (dispinfo->item.mask & LVIF_TEXT))
+ {
+ static const WCHAR testW[] = {'T','E','S','T',0};
+ dispinfo->hdr.code = LVN_GETDISPINFOW;
+ memcpy(dispinfo->item.pszText, testW, sizeof(testW));
+ }
}
break;
case NM_HOVER:
@@ -4538,6 +4547,37 @@ static void test_createdragimage(void)
DestroyWindow(list);
}
+static void test_dispinfo(void)
+{
+ static const char testA[] = "TEST";
+ WCHAR buff[10];
+ LVITEMA item;
+ HWND hwnd;
+ INT ret;
+
+ hwnd = create_listview_control(LVS_ICON);
+ ok(hwnd != 0, "failed to create listview window\n");
+
+ insert_item(hwnd, 0);
+
+ memset(&item, 0, sizeof(item));
+ item.pszText = LPSTR_TEXTCALLBACKA;
+ ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
+ ok(ret, "got %d\n", ret);
+
+ g_disp_A_to_W = TRUE;
+ item.pszText = (char*)buff;
+ item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
+ ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
+ ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
+ g_disp_A_to_W = FALSE;
+
+ ok(memcmp(item.pszText, testA, sizeof(testA)) == 0,
+ "got %s, expected %s\n", item.pszText, testA);
+
+ DestroyWindow(hwnd);
+}
+
START_TEST(listview)
{
HMODULE hComctl32;
@@ -4601,6 +4641,7 @@ START_TEST(listview)
test_hover();
test_destroynotify();
test_createdragimage();
+ test_dispinfo();
if (!load_v6_module(&ctx_cookie, &hCtx))
{
More information about the wine-cvs
mailing list