[PATCH] Listview notification

Gerard Patel gerard.patel at nerim.net
Mon Jan 28 20:22:30 CST 2002


- send ID control in wparam parameter (instead of notification code in
current code)
- send correct notification code (Unicode or Ansi) depending on style of
notification.
- convert text before and after notification
- change handling of uninitialized entries.

The last change has nothing to do with the recent unicode 
conversion of Listview. It's trying to fix a regression that appeared 
with this patch (I missed it at the time)

  Changes by:	julliard at wine2.	01/04/18 13:40:05
  Log message:
	James Hatheway <james at macadamian.com>
  Eliminate unitialized garbage being returned from LISTVIEW_GetItemA.

This patch had the unfortunate side-effect of removing the display
of columns where the app has not defined any subitem (these
columns being actually filled by a callback, psztext=-1). I hope
that I did the same thing without the side-effect but I can't be
certain because I don't have (know, even) the app that James 
wanted to fix.


ChangeLog:

	* dlls/comctl32/listview.c
               fix problems with listview notification
-------------- next part --------------
Index: dlls/comctl32/listview.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/listview.c,v
retrieving revision 1.108
diff -u -r1.108 listview.c
--- dlls/comctl32/listview.c	2002/01/18 19:05:35	1.108
+++ dlls/comctl32/listview.c	2002/01/28 23:15:33
@@ -292,7 +292,7 @@
   pnmh->idFrom = GetWindowLongW(self, GWL_ID);
   pnmh->code = code;
   return (BOOL)SendMessageW(GetParent(self), WM_NOTIFY, 
-		            (WPARAM)pnmh->code, (LPARAM)pnmh);
+		            (WPARAM)pnmh->idFrom, (LPARAM)pnmh);
 }
 
 static inline BOOL hdr_notify(HWND self, INT code)
@@ -306,46 +306,102 @@
   return notify(self, code, (LPNMHDR)plvnm);
 }
 
-static BOOL dispinfo_notifyT(HWND self, INT code, LPNMLVDISPINFOW pdi, BOOL isW)
+static int tabNotification[] = {
+  LVN_BEGINLABELEDITW, LVN_BEGINLABELEDITA, 
+  LVN_ENDLABELEDITW, LVN_ENDLABELEDITA,
+  LVN_GETDISPINFOW, LVN_GETDISPINFOA,
+  LVN_SETDISPINFOW, LVN_SETDISPINFOA,
+  LVN_ODFINDITEMW, LVN_ODFINDITEMA,
+  LVN_GETINFOTIPW, LVN_GETINFOTIPA,
+  0
+};
+
+static int get_ansi_notification(INT unicodeNotificationCode)
+{
+  int *pTabNotif = tabNotification;
+  while (*pTabNotif && (unicodeNotificationCode != *pTabNotif++));
+  if (*pTabNotif) return *pTabNotif;
+  ERR("unknown notification %x\n", unicodeNotificationCode);
+  return unicodeNotificationCode;
+}
+
+/*
+  Send notification. depends on dispinfoW having same 
+  structure as dispinfoA.
+  self : listview handle
+  notificationCode : *Unicode* notification code
+  pdi : dispinfo structure (can be unicode or ansi)
+  isW : TRUE if dispinfo is Unicode
+*/
+static BOOL dispinfo_notifyT(HWND self, INT notificationCode, LPNMLVDISPINFOW pdi, BOOL isW)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongW(self, 0);
   BOOL bResult = FALSE;
-  NMLVDISPINFOW diw;
+  BOOL convertToAnsi = FALSE, convertToUnicode = FALSE;
+  INT realNotifCode;
+  INT cchTempBufMax = 0, savCchTextMax = 0;
+  LPWSTR pszTempBuf = NULL, savPszText = NULL;
 
-  TRACE("(self=%x, code=%x, pdi=%p, isW=%d)\n", self, code, pdi, isW);
+  TRACE("(self=%x, code=%x, pdi=%p, isW=%d)\n", self, notificationCode, pdi, isW);
   TRACE("   notifyFormat=%s\n",
 	infoPtr->notifyFormat == NFR_UNICODE ? "NFR_UNICODE" :
 	infoPtr->notifyFormat == NFR_ANSI ? "NFR_ANSI" : "(not set)");
-  if (isW && infoPtr->notifyFormat == NFR_UNICODE) 
-    return notify(self, code, (LPNMHDR)pdi);
-  if (!isW && infoPtr->notifyFormat == NFR_ANSI)
-    return notify(self, code, (LPNMHDR)pdi);
-  if (!is_textT(pdi->item.pszText, isW))
-    return notify(self, code, (LPNMHDR)pdi);
-  if (isW && *pdi->item.pszText == 0)
-    return notify(self, code, (LPNMHDR)pdi);
-  if (!isW && *((LPCSTR)pdi->item.pszText) == 0)
+  if (infoPtr->notifyFormat == NFR_ANSI)
+    realNotifCode = get_ansi_notification(notificationCode);
+  else
+    realNotifCode = notificationCode;
+
+  if (is_textT(pdi->item.pszText, isW))
   {
-    *pdi->item.pszText = 0; /* make sure we have enough zeros... */
-    return notify(self, code, (LPNMHDR)pdi);
+    if (isW && infoPtr->notifyFormat == NFR_ANSI)
+        convertToAnsi = TRUE;
+    if (!isW && infoPtr->notifyFormat == NFR_UNICODE)
+        convertToUnicode = TRUE;
   }
-  if (infoPtr->notifyFormat == 0)
-    return FALSE;
-  TRACE("   we have to convert the text to the correct format\n");
-  ZeroMemory(&diw, sizeof(diw));
-  memcpy(&diw, pdi, sizeof(diw));
-  diw.item.cchTextMax = isW ?
-    WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, NULL, 0, NULL, NULL) :
-    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, NULL, 0);
-  diw.item.pszText = HeapAlloc(GetProcessHeap(), 0, (isW ? sizeof(WCHAR) : sizeof(CHAR)) * diw.item.cchTextMax);
-  if (!diw.item.pszText) return FALSE;
-  if (isW)
-    WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR)diw.item.pszText, diw.item.cchTextMax, NULL, NULL);
-  else
-    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, diw.item.pszText, diw.item.cchTextMax);
-  TRACE("   text=%s\n", debugstr_t(diw.item.pszText, isW));
-  bResult = notify(self, code, (LPNMHDR)&diw);
-  HeapFree(GetProcessHeap(), 0, diw.item.pszText);
+  
+  if (convertToAnsi || convertToUnicode)
+  {
+    TRACE("   we have to convert the text to the correct format\n");
+    if (notificationCode != LVN_GETDISPINFOW)
+    { /* length of existing text */
+      cchTempBufMax = convertToUnicode ?
+      WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, NULL, 0, NULL, NULL) :
+      MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, NULL, 0);
+    }
+    else
+      cchTempBufMax = pdi->item.cchTextMax;
+
+    pszTempBuf = HeapAlloc(GetProcessHeap(), 0, 
+        (convertToUnicode ? sizeof(WCHAR) : sizeof(CHAR)) * cchTempBufMax);
+    if (!pszTempBuf) return FALSE;
+    if (convertToUnicode)
+      WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) pszTempBuf,
+                          cchTempBufMax, NULL, NULL);
+    else
+      MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, 
+                          pszTempBuf, cchTempBufMax);
+    TRACE("   text=%s\n", debugstr_t(pszTempBuf, convertToUnicode));
+    savCchTextMax = pdi->item.cchTextMax;
+    savPszText = pdi->item.pszText;
+    pdi->item.pszText = pszTempBuf;
+    pdi->item.cchTextMax = cchTempBufMax;
+  } 
+  
+  bResult = notify(self, realNotifCode, (LPNMHDR)pdi);
+  
+  if (convertToUnicode || convertToAnsi)
+  { /* convert back result */
+    TRACE("   returned text=%s\n", debugstr_t(pdi->item.pszText, convertToUnicode));
+    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;
+    HeapFree(GetProcessHeap(), 0, pszTempBuf);
+  }
   return bResult;
 }
 
@@ -4229,7 +4285,7 @@
   dispInfo.item.iImage = lpItem->iImage;
   dispInfo.item.lParam = lpItem->lParam;
 
-  if (dispinfo_notifyT(hwnd, isW ? LVN_BEGINLABELEDITW : LVN_BEGINLABELEDITA, &dispInfo, isW))
+  if (dispinfo_notifyT(hwnd, LVN_BEGINLABELEDITW, &dispInfo, isW))
 	  return 0;
 
   rect.left = LVIR_LABEL;
@@ -4971,7 +5027,7 @@
     if (lpLVItem->mask & ~LVIF_STATE)
     {
       memcpy(&dispInfo.item, lpLVItem, sizeof(LVITEMW));
-      dispinfo_notifyT(hwnd, LVN_GETDISPINFOT(isW), &dispInfo, isW);
+      dispinfo_notifyT(hwnd, LVN_GETDISPINFOW, &dispInfo, isW);
       memcpy(lpLVItem, &dispInfo.item, sizeof(LVITEMW));
       TRACE("   getdispinfo(1):lpLVItem=%s\n", debuglvitem_t(lpLVItem, isW));
     }
@@ -5027,7 +5083,9 @@
     dispInfo.item.pszText = lpLVItem->pszText;
     dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
     if (dispInfo.item.pszText && lpLVItem->cchTextMax > 0) 
-      *dispInfo.item.pszText = 0;
+      *dispInfo.item.pszText = '\0';
+    if (dispInfo.item.pszText && (*ppszText == NULL))
+      *dispInfo.item.pszText = '\0';
   }
 
   if (dispInfo.item.mask != 0)
@@ -5036,7 +5094,7 @@
     dispInfo.item.iItem = lpLVItem->iItem;
     dispInfo.item.iSubItem = lpLVItem->iSubItem;
     dispInfo.item.lParam = lpItem->lParam;
-    dispinfo_notifyT(hwnd, LVN_GETDISPINFOT(isW), &dispInfo, isW);
+    dispinfo_notifyT(hwnd, LVN_GETDISPINFOW, &dispInfo, isW);
     TRACE("   getdispinfo(2):lpLVItem=%s\n", debuglvitem_t(&dispInfo.item, isW));
   }
 
@@ -5073,8 +5131,6 @@
     if (lpLVItem->pszText != dispInfo.item.pszText) 
         textcpynT(lpLVItem->pszText, isW, dispInfo.item.pszText, isW, lpLVItem->cchTextMax);
     
-    if (*ppszText == NULL)
-       *lpLVItem->pszText = '\0';
   }
   else if (lpLVItem->mask & LVIF_TEXT)
   {
-------------- next part --------------



More information about the wine-patches mailing list