From b4994d18e94c8703a54fa31e19859d798d48d52e Mon Sep 17 00:00:00 2001
From: "Guy L. Albertelli" <galberte@neo.lrun.com>
Date: Wed, 20 Mar 2002 01:29:04 +0000
Subject: [PATCH] - Preliminary implementation of TVS_NOSCROLL and
 TVS_NOHSCROLL - Implement A and W versions of WM_NOTIFY based on response to 
  WM_NOTIFYFORMAT. Note that the EDITLABEL notifies are not done. - Implement
 WM_NOTIFYFORMAT.

---
 dlls/comctl32/treeview.c | 257 ++++++++++++++++++++++++++++++++-------
 1 file changed, 211 insertions(+), 46 deletions(-)

diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c
index 649ba1faaba..3374eb04640 100644
--- a/dlls/comctl32/treeview.c
+++ b/dlls/comctl32/treeview.c
@@ -127,6 +127,8 @@ typedef struct tagTREEVIEW_INFO
   BOOL          bIgnoreEditKillFocus;
   BOOL          bLabelChanged;
 
+  BOOL          bNtfUnicode;    /* TRUE if should send NOTIFY with W */
+  BOOL          bUnicode;       /* set by CCM_SETUNICODEFORMAT       */
   HIMAGELIST    himlNormal;
   int           normalImageHeight;
   int           normalImageWidth;
@@ -192,6 +194,7 @@ static LRESULT TREEVIEW_RButtonUp(TREEVIEW_INFO *, LPPOINT);
 static LRESULT TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel);
 static VOID TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr);
 static LRESULT TREEVIEW_HScroll(TREEVIEW_INFO *, WPARAM);
+static LRESULT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
 
 
 /* Random Utilities *****************************************************/
@@ -409,6 +412,17 @@ TREEVIEW_GetListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 
 /* Notifications ************************************************************/
 
+static LRESULT
+TREEVIEW_SendRealNotify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    if (infoPtr->bNtfUnicode)
+	return (BOOL)SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
+				  wParam, lParam);
+    else
+	return (BOOL)SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+				  wParam, lParam);
+}
+
 static BOOL
 TREEVIEW_SendSimpleNotify(TREEVIEW_INFO *infoPtr, UINT code)
 {
@@ -420,24 +434,38 @@ TREEVIEW_SendSimpleNotify(TREEVIEW_INFO *infoPtr, UINT code)
     nmhdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
     nmhdr.code = code;
 
-    return (BOOL)SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
-			      (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+				  (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
 }
 
 static VOID
-TREEVIEW_TVItemFromItem(UINT mask, TVITEMA *tvItem, TREEVIEW_ITEM *item)
+TREEVIEW_TVItemFromItem(TREEVIEW_INFO *infoPtr, UINT mask, TVITEMA *tvItem, TREEVIEW_ITEM *item)
 {
     tvItem->mask = mask;
     tvItem->hItem = item;
     tvItem->state = item->state;
     tvItem->stateMask = 0;
     tvItem->iImage = item->iImage;
-    tvItem->pszText = item->pszText;
     tvItem->cchTextMax = item->cchTextMax;
     tvItem->iImage = item->iImage;
     tvItem->iSelectedImage = item->iSelectedImage;
     tvItem->cChildren = item->cChildren;
     tvItem->lParam = item->lParam;
+
+    /* **** **** **** **** WARNING **** **** **** **** */
+    /* This control stores all the data in A format    */
+    /* we will convert it to W if the notify format    */
+    /* is Unicode.                                     */
+    /* **** **** **** **** WARNING **** **** **** **** */
+    if (infoPtr->bNtfUnicode) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, NULL, 0 );
+        if (len > 1) {
+            tvItem->pszText = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, item->pszText, -1, (LPWSTR)tvItem->pszText, len*sizeof(WCHAR) );
+	}
+    }
+    else
+	tvItem->pszText = item->pszText;
 }
 
 static BOOL
@@ -446,6 +474,7 @@ TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr, UINT code, UINT action,
 {
     HWND hwnd = infoPtr->hwnd;
     NMTREEVIEWA nmhdr;
+    BOOL ret;
 
     TRACE("code:%x action:%x olditem:%p newitem:%p\n",
 	  code, action, oldItem, newItem);
@@ -458,17 +487,22 @@ TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr, UINT code, UINT action,
     nmhdr.action = action;
 
     if (oldItem)
-	TREEVIEW_TVItemFromItem(mask, &nmhdr.itemOld, oldItem);
+	TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemOld, oldItem);
 
     if (newItem)
-	TREEVIEW_TVItemFromItem(mask, &nmhdr.itemNew, newItem);
+	TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemNew, newItem);
 
     nmhdr.ptDrag.x = 0;
     nmhdr.ptDrag.y = 0;
 
-    return (BOOL)SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
 			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
 			      (LPARAM)&nmhdr);
+    if (infoPtr->bNtfUnicode) {
+	COMCTL32_Free(nmhdr.itemOld.pszText);
+	COMCTL32_Free(nmhdr.itemNew.pszText);
+    }
+    return ret;
 }
 
 static BOOL
@@ -492,7 +526,7 @@ TREEVIEW_SendTreeviewDnDNotify(TREEVIEW_INFO *infoPtr, UINT code,
     nmhdr.ptDrag.x = pt.x;
     nmhdr.ptDrag.y = pt.y;
 
-    return (BOOL)SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
 			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
 			      (LPARAM)&nmhdr);
 }
@@ -522,7 +556,7 @@ TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage,
     nmcdhdr.clrTextBk = infoPtr->clrBk;
     nmcdhdr.iLevel = 0;
 
-    return (BOOL)SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+    return (BOOL)TREEVIEW_SendRealNotify(infoPtr,
 			      (WPARAM)GetWindowLongA(hwnd, GWL_ID),
 			      (LPARAM)&nmcdhdr);
 }
@@ -570,7 +604,7 @@ TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc,
 	  nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
 	  nmcd->uItemState, nmcd->lItemlParam);
 
-    retval = SendMessageA(infoPtr->hwndNotify, WM_NOTIFY,
+    retval = TREEVIEW_SendRealNotify(infoPtr,
 			  (WPARAM)GetWindowLongA(hwnd, GWL_ID),
 			  (LPARAM)&nmcdhdr);
 
@@ -583,7 +617,9 @@ static BOOL
 TREEVIEW_BeginLabelEditNotify(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *editItem)
 {
     HWND hwnd = infoPtr->hwnd;
+    LPSTR allocated = NULL;
     NMTVDISPINFOA tvdi;
+    BOOL ret;
 
     tvdi.hdr.hwndFrom = hwnd;
     tvdi.hdr.idFrom = GetWindowLongA(hwnd, GWL_ID);
@@ -593,11 +629,29 @@ TREEVIEW_BeginLabelEditNotify(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *editItem)
     tvdi.item.hItem = editItem;
     tvdi.item.state = editItem->state;
     tvdi.item.lParam = editItem->lParam;
-    tvdi.item.pszText = editItem->pszText;
-    tvdi.item.cchTextMax = editItem->cchTextMax;
+    if (infoPtr->bNtfUnicode) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, NULL, 0 );
+        if (len > 1) {
+            tvdi.item.pszText = allocated = (LPSTR)COMCTL32_Alloc (len*sizeof(WCHAR));
+            MultiByteToWideChar( CP_ACP, 0, editItem->pszText, -1, (LPWSTR)tvdi.item.pszText, len*sizeof(WCHAR) );
+	    tvdi.item.cchTextMax = len*sizeof(WCHAR);
+	}
+	else {
+	    tvdi.item.pszText = editItem->pszText;  /* ??? */
+	    tvdi.item.cchTextMax = editItem->cchTextMax;  /* ??? */
+	}
+    }
+    else {
+	tvdi.item.pszText = editItem->pszText;
+	tvdi.item.cchTextMax = editItem->cchTextMax;
+    }
 
-    return SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, tvdi.hdr.idFrom,
-			(LPARAM)&tvdi);
+    ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
+					 tvdi.hdr.idFrom,
+					(LPARAM)&tvdi);
+    if (allocated)
+	COMCTL32_Free(allocated);
+    return ret;
 }
 
 static void
@@ -613,7 +667,8 @@ TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 
     callback.hdr.hwndFrom         = hwnd;
     callback.hdr.idFrom           = GetWindowLongA(hwnd, GWL_ID);
-    callback.hdr.code             = TVN_GETDISPINFOA;
+    callback.hdr.code             = (infoPtr->bNtfUnicode) ? TVN_GETDISPINFOW :
+	                                           TVN_GETDISPINFOA;
 
     /* 'state' always contains valid value, as well as 'lParam'.
      * All other parameters are uninitialized.
@@ -629,7 +684,8 @@ TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     if (mask & TVIF_TEXT)
        wineItem->textWidth = 0;
 
-    SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, callback.hdr.idFrom, (LPARAM)&callback);
+    TREEVIEW_SendRealNotify(infoPtr,
+                            (WPARAM)callback.hdr.idFrom, (LPARAM)&callback);
 
     /* It may have changed due to a call to SetItem. */ 
     mask &= wineItem->callbackMask;
@@ -637,18 +693,75 @@ TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
     if ((mask & TVIF_TEXT) && callback.item.pszText != wineItem->pszText)
     {
 	/* Instead of copying text into our buffer user specified its own */
-	int len = max(lstrlenA(callback.item.pszText) + 1, TEXT_CALLBACK_SIZE);
-	LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len);
+	if (infoPtr->bNtfUnicode) {
+	    LPWSTR newText;
+	    int buflen;
+            int len = WideCharToMultiByte( CP_ACP, 0, 
+					   (LPWSTR)callback.item.pszText, -1,
+                                           NULL, 0, NULL, NULL );
+	    buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
+	    newText = (LPWSTR)COMCTL32_ReAlloc(wineItem->pszText, buflen);
 
-	if (newText)
-	{
-	   wineItem->pszText = newText;
-	   strcpy(wineItem->pszText, callback.item.pszText);
-	   wineItem->cchTextMax = len;
+	    TRACE("returned wstr %s, len=%d, buflen=%d\n",
+		  debugstr_w((LPWSTR)callback.item.pszText), len, buflen);
+
+	    if (newText)
+	    {
+		wineItem->pszText = (LPSTR)newText;
+		WideCharToMultiByte( CP_ACP, 0, 
+				     (LPWSTR)callback.item.pszText, -1,
+				     wineItem->pszText, buflen, 
+				     NULL, NULL );
+		wineItem->cchTextMax = buflen;
+	    }
+	    /* If ReAlloc fails we have nothing to do, but keep original text */
+	}
+	else {
+	    int len = max(lstrlenA(callback.item.pszText) + 1, 
+			  TEXT_CALLBACK_SIZE);
+	    LPSTR newText = COMCTL32_ReAlloc(wineItem->pszText, len);
+
+	    TRACE("returned str %s, len=%d\n",
+		  debugstr_a(callback.item.pszText), len);
+
+	    if (newText)
+	    {
+		wineItem->pszText = newText;
+		strcpy(wineItem->pszText, callback.item.pszText);
+		wineItem->cchTextMax = len;
+	    }
+	    /* If ReAlloc fails we have nothing to do, but keep original text */
 	}
-        /* If ReAlloc fails we have nothing to do, but keep original text */
     }
+    else if (mask & TVIF_TEXT) {
+	/* User put text into our buffer, that is ok unless W string */
+	if (infoPtr->bNtfUnicode) {
+	    LPWSTR newText;
+	    LPSTR oldText = NULL;
+	    int buflen;
+            int len = WideCharToMultiByte( CP_ACP, 0, 
+					   (LPWSTR)callback.item.pszText, -1,
+                                           NULL, 0, NULL, NULL );
+	    buflen = max((len+1)*sizeof(WCHAR), TEXT_CALLBACK_SIZE);
+	    newText = (LPWSTR)COMCTL32_Alloc(buflen);
+
+	    TRACE("same buffer wstr %s, len=%d, buflen=%d\n",
+		  debugstr_w((LPWSTR)callback.item.pszText), len, buflen);
 
+	    if (newText)
+	    {
+		oldText = wineItem->pszText;
+		wineItem->pszText = (LPSTR)newText;
+		WideCharToMultiByte( CP_ACP, 0, 
+				     (LPWSTR)callback.item.pszText, -1,
+				     wineItem->pszText, buflen, NULL, NULL );
+		wineItem->cchTextMax = buflen;
+		if (oldText)
+		    COMCTL32_Free(oldText);
+	    }
+	}
+    }
+ 
     if (mask & TVIF_IMAGE)
 	wineItem->iImage = callback.item.iImage;
 
@@ -948,6 +1061,8 @@ TREEVIEW_DoSetItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 	    wineItem->pszText = newText;
 	    wineItem->cchTextMax = len;
 	    lstrcpynA(wineItem->pszText, tvItem->pszText, len);
+	    TRACE("setting text %s, item %p\n",
+		  debugstr_a(wineItem->pszText), wineItem);
 	}
 	else
 	{
@@ -956,6 +1071,8 @@ TREEVIEW_DoSetItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 	    wineItem->pszText = COMCTL32_ReAlloc(wineItem->pszText,
 						 TEXT_CALLBACK_SIZE);
 	    wineItem->cchTextMax = TEXT_CALLBACK_SIZE;
+	    TRACE("setting callback, item %p\n",
+		  wineItem);
 	}
     }
 
@@ -1318,7 +1435,9 @@ TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
 {
     TRACE("%p, (%s)\n", wineItem, TREEVIEW_ItemName(wineItem));
 
-    TREEVIEW_SendTreeviewNotify(infoPtr, TVN_DELETEITEMA,
+    TREEVIEW_SendTreeviewNotify(infoPtr, 
+				(infoPtr->bNtfUnicode) ? TVN_DELETEITEMW : 
+				                         TVN_DELETEITEMA,
 				TVIF_HANDLE | TVIF_PARAM, 0, wineItem, 0);
 
     if (wineItem->firstChild)
@@ -1948,7 +2067,7 @@ TREEVIEW_SetItemA(TREEVIEW_INFO *infoPtr, LPTVITEMEXA tvItem)
 }
 
 static LRESULT
-TREEVIEW_GetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXA tvItem)
+TREEVIEW_GetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem)
 {
     TREEVIEW_ITEM *wineItem;
     INT         iItem;
@@ -1987,17 +2106,20 @@ TREEVIEW_GetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXA tvItem)
 
     if (tvItem->mask & TVIF_TEXT) {
         if (wineItem->pszText == LPSTR_TEXTCALLBACKA) {
-            tvItem->pszText = LPSTR_TEXTCALLBACKA;
+            tvItem->pszText = LPSTR_TEXTCALLBACKW;
             FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n");
         }
         else if (wineItem->pszText) {
+	    TRACE("orig str %s at %p\n",
+		  debugstr_a(wineItem->pszText), wineItem->pszText);
             MultiByteToWideChar(CP_ACP, 0, wineItem->pszText,
-                                -1 , (LPWSTR)tvItem->pszText, tvItem->cchTextMax);
+                                -1 , tvItem->pszText, tvItem->cchTextMax);
         }
     }
 
-    TRACE("item %d<%p>, txt %p, img %p, action %x\n",
-        iItem, tvItem, tvItem->pszText, &tvItem->iImage, tvItem->mask);
+    TRACE("item %d<%p>, txt %p<%s>, img %p, action %x\n",
+	  iItem, tvItem, tvItem->pszText, debugstr_w(tvItem->pszText),
+	  &tvItem->iImage, tvItem->mask);
     return TRUE;
 }
 
@@ -2012,17 +2134,19 @@ TREEVIEW_SetItemW(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem)
     tvItemA.hItem = tvItem->hItem;
     tvItemA.state = tvItem->state;
     tvItemA.stateMask = tvItem->stateMask;
-    len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
-          NULL ,0 , NULL,NULL);
-    if (len)
-    {
-        len ++;
-        tvItemA.pszText = HeapAlloc(GetProcessHeap(),0,len);
-        len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
-            tvItemA.pszText ,len , NULL,NULL);
+    if (tvItem->mask & TVIF_TEXT) {
+	len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
+				  NULL ,0 , NULL,NULL);
+	if (len) {
+	    len ++;
+	    tvItemA.pszText = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
+	    len = WideCharToMultiByte(CP_ACP, 0, tvItem->pszText, -1,
+				      tvItemA.pszText ,len*sizeof(WCHAR), 
+				      NULL,NULL);
+	}
+	else
+	    tvItemA.pszText = NULL;
     }
-    else
-        tvItemA.pszText = NULL;
     tvItemA.cchTextMax = tvItem->cchTextMax;
     tvItemA.iImage = tvItem->iImage;
     tvItemA.iSelectedImage = tvItem->iSelectedImage;
@@ -2413,6 +2537,10 @@ TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem)
 
 	    InflateRect(&rcText, -2, -1); /* allow for the focus rect */
 
+	    TRACE("drawing text %s at (%d,%d)-(%d,%d)\n",
+		  debugstr_a(wineItem->pszText),
+		  rcText.left, rcText.top, rcText.right, rcText.bottom);
+
 	    /* Draw it */
 	    DrawTextA(hdc,
 		      wineItem->pszText,
@@ -2515,6 +2643,8 @@ TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr)
 
     infoPtr->treeWidth += infoPtr->scrollX;
 
+    if (infoPtr->dwStyle & TVS_NOSCROLL) return;
+
     /* Adding one scroll bar may take up enough space that it forces us
      * to add the other as well. */
     if (infoPtr->treeHeight > infoPtr->clientHeight)
@@ -2532,6 +2662,8 @@ TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr)
 	> infoPtr->clientHeight - GetSystemMetrics(SM_CYVSCROLL))
 	vert = TRUE;
 
+    if (horz && (infoPtr->dwStyle & TVS_NOHSCROLL)) horz = FALSE;
+
     si.cbSize = sizeof(SCROLLINFO);
     si.fMask  = SIF_POS|SIF_RANGE|SIF_PAGE;
     si.nMin   = 0;
@@ -2917,7 +3049,10 @@ static BOOL
 TREEVIEW_SendExpanding(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 		       UINT action)
 {
-    return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGA, action,
+    return !TREEVIEW_SendTreeviewNotify(infoPtr,
+				(infoPtr->bNtfUnicode) ? TVN_ITEMEXPANDINGW : 
+				                         TVN_ITEMEXPANDINGA,
+				action,
 					TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
 					| TVIF_IMAGE | TVIF_SELECTEDIMAGE,
 					0, wineItem);
@@ -2927,7 +3062,10 @@ static VOID
 TREEVIEW_SendExpanded(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem,
 		      UINT action)
 {
-    TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDEDA, action,
+    TREEVIEW_SendTreeviewNotify(infoPtr, 
+				(infoPtr->bNtfUnicode) ? TVN_ITEMEXPANDEDW : 
+				                         TVN_ITEMEXPANDEDA,
+				action,
 				TVIF_HANDLE | TVIF_STATE | TVIF_PARAM
 				| TVIF_IMAGE | TVIF_SELECTEDIMAGE,
 				0, wineItem);
@@ -3514,8 +3652,7 @@ TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel)
 	tvdi.item.cchTextMax = 0;
     }
 
-    bCommit = (BOOL)SendMessageA(infoPtr->hwndNotify,
-				 WM_NOTIFY,
+    bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr,
 				 (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi);
 
     if (!bCancel && bCommit)	/* Apply the changes */
@@ -4626,6 +4763,13 @@ TREEVIEW_Create(HWND hwnd)
 #endif
 
     infoPtr->hwndToolTip = 0;
+
+    infoPtr->bUnicode = IsWindowUnicode (hwnd);
+
+    /* Determine what type of notify should be issued */
+    /* sets infoPtr->bNtfUnicode */
+    TREEVIEW_NotifyFormat(infoPtr, 0, NF_REQUERY); 
+
     if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS))
 	infoPtr->hwndToolTip = COMCTL32_CreateToolTip(hwnd);
 
@@ -4878,6 +5022,26 @@ TREEVIEW_Notify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
     return DefWindowProcA(infoPtr->hwnd, WM_NOTIFY, wParam, lParam);
 }
 
+static LRESULT
+TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
+{
+    INT i;
+
+    if (lParam == NF_REQUERY) {
+	i = SendMessageA(GetParent (infoPtr->hwnd),
+			 WM_NOTIFYFORMAT, infoPtr->hwnd, NF_QUERY);
+	if ((i < NFR_ANSI) || (i > NFR_UNICODE)) {
+	    ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n",
+		i);
+	    i = NFR_ANSI;
+	}
+	infoPtr->bNtfUnicode = (i == NFR_UNICODE) ? 1 : 0;
+	return (LRESULT)i;
+    }
+    return (LRESULT)((infoPtr->bNtfUnicode) ? NFR_UNICODE : NFR_ANSI);
+}
+
+
 static LRESULT
 TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
 {
@@ -5027,7 +5191,7 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 	return TREEVIEW_GetItemA(infoPtr, (LPTVITEMEXA)lParam);
 
     case TVM_GETITEMW:
-	return TREEVIEW_GetItemW(infoPtr, (LPTVITEMEXA)lParam);
+	return TREEVIEW_GetItemW(infoPtr, (LPTVITEMEXW)lParam);
 
     case TVM_GETITEMHEIGHT:
 	return TREEVIEW_GetItemHeight(infoPtr);
@@ -5161,7 +5325,8 @@ TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     case WM_NOTIFY:
 	return TREEVIEW_Notify(infoPtr, wParam, lParam);
 
-	/* WM_NOTIFYFORMAT */
+    case WM_NOTIFYFORMAT:
+	return TREEVIEW_NotifyFormat(infoPtr, wParam, lParam);
 
     case WM_PAINT:
 	return TREEVIEW_Paint(infoPtr, wParam);
-- 
GitLab