Sync to Wine-0_9:
Vitaliy Margolen <wine-patch@kievinfo.com>
- Correct Page Up/Down handling in report mode.
- Don't start dragging for a single mouse click.
- Don't arrange tabs if there is only one line.
Francois Gouget <fgouget@free.fr>
- Use "static const" rather than "const static" as gcc -W complains
  about the former.
Alexandre Julliard <julliard@winehq.org>
- Don't register classes is no theme is active to avoid trouble (based
  on a patch by Vitaliy Margolen).
Krzysztof Foltman <wdev@foltman.com>
- Separators with group style set don't separate toolbar radio groups
  anymore (which broke tool selection in Front Panel Designer).
Troy Rollo <wine@troy.rollo.name>
- Detect when the notification callback has destroyed the ListView to
  avoid attempts to access data that is no longer valid.
Modified: trunk/reactos/lib/comctl32/listview.c
Modified: trunk/reactos/lib/comctl32/rebar.c
Modified: trunk/reactos/lib/comctl32/status.c
Modified: trunk/reactos/lib/comctl32/tab.c
Modified: trunk/reactos/lib/comctl32/theming.c
Modified: trunk/reactos/lib/comctl32/toolbar.c

Modified: trunk/reactos/lib/comctl32/listview.c
--- trunk/reactos/lib/comctl32/listview.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/listview.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -769,10 +769,12 @@
     return result;
 }
 
-static inline LRESULT notify(LISTVIEW_INFO *infoPtr, INT code)
+static inline BOOL notify(LISTVIEW_INFO *infoPtr, INT code)
 {
     NMHDR nmh;
-    return notify_hdr(infoPtr, code, &nmh);
+    HWND hwnd = infoPtr->hwndSelf;
+    notify_hdr(infoPtr, code, &nmh);
+    return IsWindow(hwnd);
 }
 
 static inline void notify_itemactivate(LISTVIEW_INFO *infoPtr, LVHITTESTINFO *htInfo)
@@ -813,11 +815,12 @@
     return notify_hdr(infoPtr, code, (LPNMHDR)plvnm);
 }
 
-static LRESULT notify_click(LISTVIEW_INFO *infoPtr,  INT code, LVHITTESTINFO *lvht)
+static BOOL notify_click(LISTVIEW_INFO *infoPtr,  INT code, LVHITTESTINFO *lvht)
 {
     NMLISTVIEW nmlv;
     LVITEMW item;
-   
+    HWND hwnd = infoPtr->hwndSelf;
+
     TRACE("code=%d, lvht=%s\n", code, debuglvhittestinfo(lvht)); 
     ZeroMemory(&nmlv, sizeof(nmlv));
     nmlv.iItem = lvht->iItem;
@@ -827,14 +830,16 @@
     item.iItem = lvht->iItem;
     item.iSubItem = 0;
     if (LISTVIEW_GetItemT(infoPtr, &item, TRUE)) nmlv.lParam = item.lParam;
-    return notify_listview(infoPtr, code, &nmlv);
+    notify_listview(infoPtr, code, &nmlv);
+    return IsWindow(hwnd);
 }
 
-static void notify_deleteitem(LISTVIEW_INFO *infoPtr, INT nItem)
+static BOOL notify_deleteitem(LISTVIEW_INFO *infoPtr, INT nItem)
 {
     NMLISTVIEW nmlv;
     LVITEMW item;
-   
+    HWND hwnd = infoPtr->hwndSelf;
+
     ZeroMemory(&nmlv, sizeof (NMLISTVIEW));
     nmlv.iItem = nItem;
     item.mask = LVIF_PARAM;
@@ -842,6 +847,7 @@
     item.iSubItem = 0;
     if (LISTVIEW_GetItemT(infoPtr, &item, TRUE)) nmlv.lParam = item.lParam;
     notify_listview(infoPtr, LVN_DELETEITEM, &nmlv);
+    return IsWindow(hwnd);
 }
 
 static int get_ansi_notification(INT unicodeNotificationCode)
@@ -3014,12 +3020,13 @@
  * [I] nItem : item index
  *
  * RETURN:
- * None
+ * Whether the window is still valid.
  */
-static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem)
+static BOOL LISTVIEW_AddGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem)
 {
     INT nFirst = min(infoPtr->nSelectionMark, nItem);
     INT nLast = max(infoPtr->nSelectionMark, nItem);
+    HWND hwndSelf = infoPtr->hwndSelf;
     NMLVODSTATECHANGE nmlv;
     LVITEMW item;
     BOOL bOldChange;
@@ -3048,7 +3055,10 @@
     nmlv.uOldState = item.state;
 
     notify_hdr(infoPtr, LVN_ODSTATECHANGED, (LPNMHDR)&nmlv);
+    if (!IsWindow(hwndSelf))
+        return FALSE;
     infoPtr->bDoChangeNotify = bOldChange;
+    return TRUE;
 }
 
 
@@ -3279,7 +3289,9 @@
         notify_listview(infoPtr, LVN_BEGINDRAG, &nmlv);
 
         return 0;
-    } 
+    }
+    else
+        infoPtr->bLButtonDown = FALSE;
 
   /* see if we are supposed to be tracking mouse hovering */
   if(infoPtr->dwLvExStyle & LVS_EX_TRACKSELECT) {
@@ -3400,9 +3412,15 @@
     /* send LVN_ITEMCHANGING notification, if the item is not being inserted */
     /* and we are _NOT_ virtual (LVS_OWERNDATA), and change notifications */
     /* are enabled */
-    if(lpItem && !isNew && infoPtr->bDoChangeNotify &&
-       notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv))
+    if(lpItem && !isNew && infoPtr->bDoChangeNotify)
+    {
+      HWND hwndSelf = infoPtr->hwndSelf;
+
+      if (notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv))
 	return FALSE;
+      if (!IsWindow(hwndSelf))
+	return FALSE;
+    }
 
     /* copy information */
     if (lpLVItem->mask & LVIF_TEXT)
@@ -3546,6 +3564,7 @@
 static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isW)
 {
     UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
+    HWND hwndSelf = infoPtr->hwndSelf;
     LPWSTR pszText = NULL;
     BOOL bResult, bChanged = FALSE;
     
@@ -3568,6 +3587,8 @@
 	bResult = set_sub_item(infoPtr, lpLVItem, TRUE, &bChanged);
     else
 	bResult = set_main_item(infoPtr, lpLVItem, FALSE, TRUE, &bChanged);
+    if (!IsWindow(hwndSelf))
+	return FALSE;
 
     /* redraw item, if necessary */
     if (bChanged && !infoPtr->bIsDrawing)
@@ -4516,7 +4537,7 @@
     LISTVIEW_SetItemState(infoPtr, nItem, &item);
 	    
     /* send LVN_DELETEITEM notification. */
-    notify_deleteitem(infoPtr, nItem);
+    if (!notify_deleteitem(infoPtr, nItem)) return FALSE;
 
     /* we need to do this here, because we'll be deleting stuff */  
     if (uView == LVS_SMALLICON || uView == LVS_ICON)
@@ -4568,6 +4589,7 @@
  */
 static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, LPWSTR pszText, BOOL isW)
 {
+    HWND hwndSelf = infoPtr->hwndSelf;
     NMLVDISPINFOW dispInfo;
 
     TRACE("(pszText=%s, isW=%d)\n", debugtext_t(pszText, isW), isW);
@@ -4585,6 +4607,8 @@
 
     /* Do we need to update the Item Text */
     if (!notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW)) return FALSE;
+    if (!IsWindow(hwndSelf))
+	return FALSE;
     if (!pszText) return TRUE;
 
     if (!(infoPtr->dwStyle & LVS_OWNERDATA))
@@ -4625,6 +4649,7 @@
     WCHAR szDispText[DISP_TEXT_SIZE] = { 0 };
     NMLVDISPINFOW dispInfo;
     RECT rect;
+    HWND hwndSelf = infoPtr->hwndSelf;
 
     TRACE("(nItem=%d, isW=%d)\n", nItem, isW);
 
@@ -4662,6 +4687,8 @@
     
     if (notify_dispinfoT(infoPtr, LVN_BEGINLABELEDITW, &dispInfo, isW))
     {
+	if (!IsWindow(hwndSelf))
+	    return 0;
 	SendMessageW(infoPtr->hwndEdit, WM_CLOSE, 0, 0);
 	infoPtr->hwndEdit = 0;
 	return 0;
@@ -6191,6 +6218,7 @@
     ITEM_INFO *lpItem;
     BOOL is_sorted, has_changed;
     LVITEMW item;
+    HWND hwndSelf = infoPtr->hwndSelf;
 
     TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW);
 
@@ -6264,6 +6292,8 @@
     nmlv.iItem = nItem;
     nmlv.lParam = lpItem->lParam;
     notify_listview(infoPtr, LVN_INSERTITEM, &nmlv);
+    if (!IsWindow(hwndSelf))
+	return -1;
 
     /* align items (set position of each item) */
     if ((uView == LVS_SMALLICON || uView == LVS_ICON))
@@ -7969,6 +7999,7 @@
 static LRESULT LISTVIEW_KeyDown(LISTVIEW_INFO *infoPtr, INT nVirtualKey, LONG lKeyData)
 {
   UINT uView =  infoPtr->dwStyle & LVS_TYPEMASK;
+  HWND hwndSelf = infoPtr->hwndSelf;
   INT nItem = -1;
   NMLVKEYDOWN nmKeyDown;
 
@@ -7978,14 +8009,16 @@
   nmKeyDown.wVKey = nVirtualKey;
   nmKeyDown.flags = 0;
   notify_hdr(infoPtr, LVN_KEYDOWN, &nmKeyDown.hdr);
+  if (!IsWindow(hwndSelf))
+    return 0;
 
   switch (nVirtualKey)
   {
   case VK_RETURN:
     if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1))
     {
-      notify(infoPtr, NM_RETURN);
-      notify(infoPtr, LVN_ITEMACTIVATE);
+        if (!notify(infoPtr, NM_RETURN)) return 0;
+        if (!notify(infoPtr, LVN_ITEMACTIVATE)) return 0;
     }
     break;
 
@@ -8017,7 +8050,13 @@
 
   case VK_PRIOR:
     if (uView == LVS_REPORT)
-      nItem = infoPtr->nFocusedItem - LISTVIEW_GetCountPerColumn(infoPtr);
+    {
+      INT topidx = LISTVIEW_GetTopIndex(infoPtr);
+      if (infoPtr->nFocusedItem == topidx)
+        nItem = topidx - LISTVIEW_GetCountPerColumn(infoPtr) + 1;
+      else
+        nItem = topidx;
+    }
     else
       nItem = infoPtr->nFocusedItem - LISTVIEW_GetCountPerColumn(infoPtr)
                                     * LISTVIEW_GetCountPerRow(infoPtr);
@@ -8026,7 +8065,14 @@
 
   case VK_NEXT:
     if (uView == LVS_REPORT)
-      nItem = infoPtr->nFocusedItem + LISTVIEW_GetCountPerColumn(infoPtr);
+    {
+      INT topidx = LISTVIEW_GetTopIndex(infoPtr);
+      INT cnt = LISTVIEW_GetCountPerColumn(infoPtr);
+      if (infoPtr->nFocusedItem == topidx + cnt - 1)
+        nItem = infoPtr->nFocusedItem + cnt - 1;
+      else
+        nItem = topidx + cnt - 1;
+    }
     else
       nItem = infoPtr->nFocusedItem + LISTVIEW_GetCountPerColumn(infoPtr)
                                     * LISTVIEW_GetCountPerRow(infoPtr);
@@ -8058,7 +8104,7 @@
     if (!infoPtr->bFocus) return 0;
    
     /* send NM_KILLFOCUS notification */
-    notify(infoPtr, NM_KILLFOCUS);
+    if (!notify(infoPtr, NM_KILLFOCUS)) return 0;
 
     /* if we have a focus rectagle, get rid of it */
     LISTVIEW_ShowFocusRect(infoPtr, FALSE);
@@ -8091,14 +8137,14 @@
     TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, x, y);
 
     /* send NM_RELEASEDCAPTURE notification */
-    notify(infoPtr, NM_RELEASEDCAPTURE);
+    if (!notify(infoPtr, NM_RELEASEDCAPTURE)) return 0;
 
     htInfo.pt.x = x;
     htInfo.pt.y = y;
 
     /* send NM_DBLCLK notification */
     LISTVIEW_HitTest(infoPtr, &htInfo, TRUE, FALSE);
-    notify_click(infoPtr, NM_DBLCLK, &htInfo);
+    if (!notify_click(infoPtr, NM_DBLCLK, &htInfo)) return 0;
 
     /* To send the LVN_ITEMACTIVATE, it must be on an Item */
     if(htInfo.iItem != -1) notify_itemactivate(infoPtr,&htInfo);
@@ -8128,7 +8174,7 @@
   TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, x, y);
 
   /* send NM_RELEASEDCAPTURE notification */
-  notify(infoPtr, NM_RELEASEDCAPTURE);
+  if (!notify(infoPtr, NM_RELEASEDCAPTURE)) return 0;
 
   if (!infoPtr->bFocus) SetFocus(infoPtr->hwndSelf);
 
@@ -8171,7 +8217,7 @@
       {
         if (bGroupSelect)
 	{
-          LISTVIEW_AddGroupSelection(infoPtr, nItem);
+          if (!LISTVIEW_AddGroupSelection(infoPtr, nItem)) return 0;
     	  LISTVIEW_SetItemFocus(infoPtr, nItem);
           infoPtr->nSelectionMark = nItem;
 	}
@@ -8246,7 +8292,7 @@
 
     /* send NM_CLICK notification */
     LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, FALSE);
-    notify_click(infoPtr, NM_CLICK, &lvHitTestInfo);
+    if (!notify_click(infoPtr, NM_CLICK, &lvHitTestInfo)) return 0;
 
     /* set left button flag */
     infoPtr->bLButtonDown = FALSE;
@@ -8321,6 +8367,7 @@
 static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADERW *lpnmh)
 {
     UINT uView =  infoPtr->dwStyle & LVS_TYPEMASK;
+    HWND hwndSelf = infoPtr->hwndSelf;
     
     TRACE("(lpnmh=%p)\n", lpnmh);
 
@@ -8334,6 +8381,8 @@
 	case HDN_ITEMCHANGEDW:
 	case HDN_ITEMCHANGEDA:
             notify_forward_header(infoPtr, lpnmh);
+	    if (!IsWindow(hwndSelf))
+		break;
             /* Fall through */
 	case HDN_TRACKW:
 	case HDN_TRACKA:
@@ -8564,7 +8613,7 @@
     TRACE("(key=%hu,X=%hu,Y=%hu)\n", wKey, x, y);
 
     /* send NM_RELEASEDCAPTURE notification */
-    notify(infoPtr, NM_RELEASEDCAPTURE);
+    if (!notify(infoPtr, NM_RELEASEDCAPTURE)) return 0;
 
     /* send NM_RDBLCLK notification */
     lvHitTestInfo.pt.x = x;
@@ -8595,7 +8644,7 @@
     TRACE("(key=%hu,X=%hu,Y=%hu)\n", wKey, x, y);
 
     /* send NM_RELEASEDCAPTURE notification */
-    notify(infoPtr, NM_RELEASEDCAPTURE);
+    if (!notify(infoPtr, NM_RELEASEDCAPTURE)) return 0;
 
     /* make sure the listview control window has the focus */
     if (!infoPtr->bFocus) SetFocus(infoPtr->hwndSelf);
@@ -8651,7 +8700,7 @@
     lvHitTestInfo.pt.x = x;
     lvHitTestInfo.pt.y = y;
     LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, FALSE);
-    notify_click(infoPtr, NM_RCLICK, &lvHitTestInfo);
+    if (!notify_click(infoPtr, NM_RCLICK, &lvHitTestInfo)) return 0;
 
     /* Change to screen coordinate for WM_CONTEXTMENU */
     pt = lvHitTestInfo.pt;
@@ -8714,7 +8763,7 @@
     if (infoPtr->bFocus) return 0;
    
     /* send NM_SETFOCUS notification */
-    notify(infoPtr, NM_SETFOCUS);
+    if (!notify(infoPtr, NM_SETFOCUS)) return 0;
 
     /* set window focus flag */
     infoPtr->bFocus = TRUE;

Modified: trunk/reactos/lib/comctl32/rebar.c
--- trunk/reactos/lib/comctl32/rebar.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/rebar.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -1277,7 +1277,7 @@
 static VOID
 REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus)
 {
-    const static WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
+    static const WCHAR strComboBox[] = { 'C','o','m','b','o','B','o','x',0 };
     REBAR_BAND *lpBand;
     WCHAR szClassName[40];
     UINT i;

Modified: trunk/reactos/lib/comctl32/status.c
--- trunk/reactos/lib/comctl32/status.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/status.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -96,7 +96,7 @@
 #define VERT_BORDER 2
 #define HORZ_GAP    2
 
-const static WCHAR themeClass[] = { 'S','t','a','t','u','s',0 };
+static const WCHAR themeClass[] = { 'S','t','a','t','u','s',0 };
 
 /* prototype */
 static void

Modified: trunk/reactos/lib/comctl32/tab.c
--- trunk/reactos/lib/comctl32/tab.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/tab.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -1275,7 +1275,10 @@
   infoPtr->uNumRows = curItemRowCount;
 
   /* Arrange all tabs evenly if style says so */
-   if (!(lStyle & TCS_RAGGEDRIGHT) &&  ((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (infoPtr->uNumItem > 0))
+   if (!(lStyle & TCS_RAGGEDRIGHT) &&
+       ((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) &&
+       (infoPtr->uNumItem > 0) &&
+       (infoPtr->uNumRows > 1))
    {
       INT tabPerRow,remTab,iRow;
       UINT iItm;
@@ -2022,7 +2025,7 @@
       if ((theme = GetWindowTheme (infoPtr->hwnd)) 
           && ((lStyle & (TCS_VERTICAL | TCS_BOTTOM)) == 0))
       {
-          const static int partIds[8] = {
+          static const int partIds[8] = {
               /* Normal item */
               TABP_TABITEM,
               TABP_TABITEMLEFTEDGE,

Modified: trunk/reactos/lib/comctl32/theming.c
--- trunk/reactos/lib/comctl32/theming.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/theming.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -26,6 +26,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "comctl32.h"
+#include "uxtheme.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(theming);
@@ -91,7 +92,7 @@
 MAKE_SUBCLASS_PROC(3)
 MAKE_SUBCLASS_PROC(4)
 
-const static WNDPROC subclassProcs[NUM_SUBCLASSES] = {
+static const WNDPROC subclassProcs[NUM_SUBCLASSES] = {
     subclass_proc0,
     subclass_proc1,
     subclass_proc2,
@@ -113,6 +114,8 @@
     static const WCHAR refDataPropName[] = 
         { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 };
 
+    if (!IsThemeActive()) return;
+
     atSubclassProp = GlobalAddAtomW (subclassPropName);
     atRefDataProp = GlobalAddAtomW (refDataPropName);
 
@@ -154,6 +157,9 @@
 void THEMING_Uninitialize (void)
 {
     int i;
+
+    if (!atSubclassProp) return;  /* not initialized */
+
     for (i = 0; i < NUM_SUBCLASSES; i++)
     {
         UnregisterClassW (subclasses[i].className, NULL);

Modified: trunk/reactos/lib/comctl32/toolbar.c
--- trunk/reactos/lib/comctl32/toolbar.c	2005-10-27 18:56:27 UTC (rev 18792)
+++ trunk/reactos/lib/comctl32/toolbar.c	2005-10-27 19:01:29 UTC (rev 18793)
@@ -1854,7 +1854,7 @@
     nRunIndex = nIndex - 1;
     while (nRunIndex >= 0) {
 	btnPtr = &infoPtr->buttons[nRunIndex];
-	if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) {
+	if ((btnPtr->fsStyle & BTNS_GROUP) == BTNS_GROUP) {
 	    if (btnPtr->fsState & TBSTATE_CHECKED)
 		return nRunIndex;
 	}
@@ -1867,7 +1867,7 @@
     nRunIndex = nIndex + 1;
     while (nRunIndex < infoPtr->nNumButtons) {
 	btnPtr = &infoPtr->buttons[nRunIndex];
-	if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) {
+	if ((btnPtr->fsStyle & BTNS_GROUP) == BTNS_GROUP) {
 	    if (btnPtr->fsState & TBSTATE_CHECKED)
 		return nRunIndex;
 	}