Complete Listview Unicodification.
Simplify the setting of (sub)item text by using common code.
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index d1eaaee..d5508ae 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -48,6 +48,7 @@
/* Some definitions for inline edit control */
typedef BOOL (*EditlblCallbackW)(HWND, LPWSTR, DWORD);
+typedef BOOL (*EditlblCallbackA)(HWND, LPWSTR, DWORD);
typedef struct tagEDITLABEL_ITEM
{
@@ -167,12 +168,11 @@
*/
/* retrieve the number of items in the listview */
#define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
-#define LVN_GETDISPINFOT(isW) ( (isW) ? LVN_GETDISPINFOW : LVN_GETDISPINFOA )
#define HDM_INSERTITEMT(isW) ( (isW) ? HDM_INSERTITEMW : HDM_INSERTITEMA )
-HWND CreateEditLabelW(LPCWSTR text, DWORD style, INT x, INT y,
+HWND CreateEditLabelT(LPCWSTR text, DWORD style, INT x, INT y,
INT width, INT height, HWND parent, HINSTANCE hinst,
- EditlblCallbackW EditLblCb, DWORD param);
+ EditlblCallbackW EditLblCb, DWORD param, BOOL isW);
/*
* forward declarations
@@ -214,6 +214,7 @@
static VOID LISTVIEW_UnsupportedStyles(LONG lStyle);
static HWND LISTVIEW_EditLabelT(HWND hwnd, INT nItem, BOOL isW);
static BOOL LISTVIEW_EndEditLabelW(HWND hwnd, LPWSTR pszText, DWORD nItem);
+static BOOL LISTVIEW_EndEditLabelA(HWND hwnd, LPSTR pszText, DWORD nItem);
static LRESULT LISTVIEW_Command(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT LISTVIEW_SortItems(HWND hwnd, PFNLVCOMPARE pfnCompare, LPARAM lParamSort);
static LRESULT LISTVIEW_GetStringWidthT(HWND hwnd, LPCWSTR lpszText, BOOL isW);
@@ -286,6 +287,29 @@
if (!isW && wstr) HeapFree(GetProcessHeap(), 0, wstr);
}
+/*
+ * dest is a pointer to a Unicode string
+ * src is a pointer to a string (Unicode if isW, ANSI if !isW)
+ */
+static inline BOOL textsetptrT(LPWSTR *dest, LPWSTR src, BOOL isW)
+{
+ LPWSTR pszText = textdupTtoW(src, isW);
+ BOOL bResult = TRUE;
+ if (*dest == LPSTR_TEXTCALLBACKW) *dest = NULL;
+ bResult = Str_SetPtrW(dest, pszText);
+ textfreeT(pszText, isW);
+ return bResult;
+}
+
+static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam, BOOL isW)
+{
+ if (isW)
+ return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
+ else
+ return CallWindowProcA(proc, hwnd, uMsg, wParam, lParam);
+}
+
static inline BOOL notify(HWND self, INT code, LPNMHDR pnmh)
{
pnmh->hwndFrom = self;
@@ -2374,12 +2398,7 @@
lpItem->pszText = LPSTR_TEXTCALLBACKW;
}
else
- {
- LPWSTR pszText = textdupTtoW(lpLVItem->pszText, isW);
- if (lpItem->pszText == LPSTR_TEXTCALLBACKW) lpItem->pszText = NULL;
- bResult = Str_SetPtrW(&lpItem->pszText, pszText);
- textfreeT(pszText, isW);
- }
+ bResult = textsetptrT(&lpItem->pszText, lpLVItem->pszText, isW);
}
}
@@ -2436,12 +2455,7 @@
lpSubItem->pszText = LPSTR_TEXTCALLBACKW;
}
else
- {
- LPWSTR pszText = textdupTtoW(lpLVItem->pszText, isW);
- if(lpSubItem->pszText == LPSTR_TEXTCALLBACKW) lpSubItem->pszText=NULL;
- bResult = Str_SetPtrW(&lpSubItem->pszText, pszText);
- textfreeT(pszText, isW);
- }
+ bResult = textsetptrT(&lpSubItem->pszText, lpLVItem->pszText, isW);
}
}
}
@@ -4144,12 +4158,13 @@
* [I] HWND : window handle
* [I] LPSTR : modified text
* [I] DWORD : item index
+ * [I] isW : TRUE if psxText is Unicode, FALSE if it's ANSI
*
* RETURN:
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static BOOL LISTVIEW_EndEditLabelW(HWND hwnd, LPWSTR pszText, DWORD nItem)
+static BOOL LISTVIEW_EndEditLabelT(HWND hwnd, LPWSTR pszText, DWORD nItem, BOOL isW)
{
LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(hwnd, 0);
LONG lStyle = GetWindowLongW(hwnd, GWL_STYLE);
@@ -4158,13 +4173,16 @@
HDPA hdpaSubItems;
LISTVIEW_ITEM lvItemRef;
LVITEMW item;
-
+ BOOL bResult = TRUE;
+
+ TRACE("(hwnd=%x, pszText=%s, nItem=%ld, isW=%d)\n", hwnd, debugstr_t(pszText, isW), nItem, isW);
+
if (!(lStyle & LVS_OWNERDATA))
{
- if (NULL == (hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem)))
+ if (!(hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem)))
return FALSE;
- if (NULL == (lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0)))
+ if (!(lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0)))
return FALSE;
}
else
@@ -4187,17 +4205,53 @@
dispInfo.item.state = lpItem->state;
dispInfo.item.stateMask = 0;
dispInfo.item.pszText = pszText;
- dispInfo.item.cchTextMax = pszText ? lstrlenW(pszText) : 0;
+ dispInfo.item.cchTextMax = textlenT(pszText, isW);
dispInfo.item.iImage = lpItem->iImage;
dispInfo.item.lParam = lpItem->lParam;
infoPtr->hwndEdit = 0;
/* Do we need to update the Item Text */
- if(dispinfo_notifyT(hwnd, LVN_ENDLABELEDITW, &dispInfo, TRUE))
- if ((lpItem->pszText != LPSTR_TEXTCALLBACKW)&&(!(lStyle & LVS_OWNERDATA)))
- Str_SetPtrW(&lpItem->pszText, pszText);
+ if(dispinfo_notifyT(hwnd, LVN_ENDLABELEDITW, &dispInfo, isW))
+ if (lpItem->pszText != LPSTR_TEXTCALLBACKW && !(lStyle & LVS_OWNERDATA))
+ bResult = textsetptrT(&lpItem->pszText, pszText, isW);
+
+ return bResult;
+}
- return TRUE;
+/***
+ * DESCRIPTION:
+ * Callback implementation for editlabel control
+ *
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPSTR : modified text
+ * [I] DWORD : item index
+ *
+ * RETURN:
+ * SUCCESS : TRUE
+ * FAILURE : FALSE
+ */
+static BOOL LISTVIEW_EndEditLabelW(HWND hwnd, LPWSTR pszText, DWORD nItem)
+{
+ return LISTVIEW_EndEditLabelT(hwnd, pszText, nItem, TRUE);
+}
+
+/***
+ * DESCRIPTION:
+ * Callback implementation for editlabel control
+ *
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPSTR : modified text
+ * [I] DWORD : item index
+ *
+ * RETURN:
+ * SUCCESS : TRUE
+ * FAILURE : FALSE
+ */
+static BOOL LISTVIEW_EndEditLabelA(HWND hwnd, LPSTR pszText, DWORD nItem)
+{
+ return LISTVIEW_EndEditLabelT(hwnd, (LPWSTR)pszText, nItem, FALSE);
}
/***
@@ -4287,13 +4341,10 @@
if (!LISTVIEW_GetItemRect(hwnd, nItem, &rect))
return 0;
- /* FIXME: if !isW, should we create a ASCII edit label instead
- * with a ASCII callback which should send ASCII notification msgs???
- */
- if (!(hedit = CreateEditLabelW(szDispText , WS_VISIBLE,
- rect.left-2, rect.top-1, 0,
- rect.bottom - rect.top+2,
- hwnd, hinst, LISTVIEW_EndEditLabelW, nItem)))
+ if (!(hedit = CreateEditLabelT(szDispText , WS_VISIBLE,
+ rect.left-2, rect.top-1, 0, rect.bottom - rect.top+2, hwnd, hinst,
+ isW ? LISTVIEW_EndEditLabelW : (EditlblCallbackW)LISTVIEW_EndEditLabelA,
+ nItem, isW)))
return 0;
infoPtr->hwndEdit = hedit;
@@ -5117,10 +5168,7 @@
if (dispInfo.item.mask & LVIF_TEXT)
{
if ((dispInfo.item.mask & LVIF_DI_SETITEM) && *ppszText)
- {
- if (isW) Str_SetPtrW(ppszText, dispInfo.item.pszText);
- else Str_SetPtrA((LPSTR *)ppszText, (LPCSTR)dispInfo.item.pszText);
- }
+ textsetptrT(ppszText, dispInfo.item.pszText, isW);
/* If lpLVItem->pszText==dispInfo.item.pszText a copy is unnecessary, but */
/* some apps give a new pointer in ListView_Notify so we can't be sure. */
@@ -9153,14 +9201,17 @@
*
* RETURN:
*/
-LRESULT CALLBACK EditLblWndProcW(HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
+static LRESULT EditLblWndProcT(HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam, BOOL isW)
{
LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(GetParent(hwnd), 0);
EDITLABEL_ITEM *einfo = infoPtr->pedititem;
static BOOL bIgnoreKillFocus = FALSE;
BOOL cancel = FALSE;
+ TRACE("(hwnd=%x, uMsg=%x, wParam=%x, lParam=%lx, isW=%d)\n",
+ hwnd, uMsg, wParam, lParam, isW);
+
switch (uMsg)
{
case WM_GETDLGCODE:
@@ -9176,7 +9227,7 @@
SetWindowLongW(hwnd, GWL_WNDPROC, (LONG)editProc);
COMCTL32_Free(einfo);
infoPtr->pedititem = NULL;
- return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
+ return CallWindowProcT(editProc, hwnd, uMsg, wParam, lParam, isW);
}
case WM_KEYDOWN:
@@ -9189,8 +9240,7 @@
break;
default:
- return CallWindowProcW(einfo->EditWndProc, hwnd,
- uMsg, wParam, lParam);
+ return CallWindowProcT(einfo->EditWndProc, hwnd, uMsg, wParam, lParam, isW);
}
if (einfo->EditLblCb)
@@ -9199,12 +9249,15 @@
if (!cancel)
{
- int len = 1 + GetWindowTextLengthW(hwnd);
+ int len = 1 + isW ? GetWindowTextLengthW(hwnd) : GetWindowTextLengthA(hwnd);
if (len > 1)
{
- if ( (buffer = COMCTL32_Alloc(len*sizeof(WCHAR))) )
- GetWindowTextW(hwnd, buffer, len);
+ if ( (buffer = COMCTL32_Alloc(len*(isW ? sizeof(WCHAR) : sizeof(CHAR)))) )
+ {
+ if (isW) GetWindowTextW(hwnd, buffer, len);
+ else GetWindowTextA(hwnd, (CHAR*)buffer, len);
+ }
}
}
/* Processing LVN_ENDLABELEDIT message could kill the focus */
@@ -9222,6 +9275,31 @@
return TRUE;
}
+/***
+ * DESCRIPTION:
+ * Subclassed edit control windproc function
+ *
+ * PARAMETER(S):
+ *
+ * RETURN:
+ */
+LRESULT CALLBACK EditLblWndProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return EditLblWndProcT(hwnd, uMsg, wParam, lParam, TRUE);
+}
+
+/***
+ * DESCRIPTION:
+ * Subclassed edit control windproc function
+ *
+ * PARAMETER(S):
+ *
+ * RETURN:
+ */
+LRESULT CALLBACK EditLblWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ return EditLblWndProcT(hwnd, uMsg, wParam, lParam, FALSE);
+}
/***
* DESCRIPTION:
@@ -9231,9 +9309,9 @@
*
* RETURN:
*/
-HWND CreateEditLabelW(LPCWSTR text, DWORD style, INT x, INT y,
+HWND CreateEditLabelT(LPCWSTR text, DWORD style, INT x, INT y,
INT width, INT height, HWND parent, HINSTANCE hinst,
- EditlblCallbackW EditLblCb, DWORD param)
+ EditlblCallbackW EditLblCb, DWORD param, BOOL isW)
{
LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(parent, 0);
WCHAR editName[5] = { 'E', 'd', 'i', 't', '\0' };
@@ -9243,6 +9321,8 @@
HDC hOldFont=0;
TEXTMETRICW textMetric;
+ TRACE("(text=%s, ..., isW=%d)\n", debugstr_t(text, isW), isW);
+
if (NULL == (infoPtr->pedititem = COMCTL32_Alloc(sizeof(EDITLABEL_ITEM))))
return 0;
@@ -9264,8 +9344,12 @@
SelectObject(hdc, hOldFont);
ReleaseDC(parent, hdc);
- if (!(hedit = CreateWindowW(editName, text, style, x, y, sz.cx, height,
- parent, 0, hinst, 0)))
+ if (isW)
+ hedit = CreateWindowW(editName, text, style, x, y, sz.cx, height, parent, 0, hinst, 0);
+ else
+ hedit = CreateWindowA("Edit", (LPCSTR)text, style, x, y, sz.cx, height, parent, 0, hinst, 0);
+
+ if (!hedit)
{
COMCTL32_Free(infoPtr->pedititem);
return 0;
@@ -9273,8 +9357,9 @@
infoPtr->pedititem->param = param;
infoPtr->pedititem->EditLblCb = EditLblCb;
- infoPtr->pedititem->EditWndProc = (WNDPROC)SetWindowLongW(hedit,
- GWL_WNDPROC, (LONG) EditLblWndProcW);
+ infoPtr->pedititem->EditWndProc = (WNDPROC)
+ (isW ? SetWindowLongW(hedit, GWL_WNDPROC, (LONG)EditLblWndProcW) :
+ SetWindowLongA(hedit, GWL_WNDPROC, (LONG)EditLblWndProcA) );
SendMessageW(hedit, WM_SETFONT, infoPtr->hFont, FALSE);