[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[reactos.git] / win32ss / user / user32 / controls / listbox.c
index 18e0fe9..195241d 100644 (file)
@@ -32,8 +32,6 @@
 
 #include <user32.h>
 
-#include <wine/debug.h>
-
 WINE_DEFAULT_DEBUG_CHANNEL(listbox);
 
 /* Items array granularity */
@@ -74,7 +72,7 @@ typedef struct
     INT         item_height;    /* Default item height */
     INT         page_size;      /* Items per listbox page */
     INT         column_width;   /* Column width for multi-column listboxes */
-    INT         horz_extent;    /* Horizontal extent (0 if no hscroll) */
+    INT         horz_extent;    /* Horizontal extent */
     INT         horz_pos;       /* Horizontal position */
     INT         nb_tabs;        /* Number of tabs in array */
     INT        *tabs;           /* Array of tabs */
@@ -259,17 +257,28 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
         if (descr->style & WS_VSCROLL)
             SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
 
-        if (descr->horz_extent)
+        if ((descr->style & WS_HSCROLL) && descr->horz_extent)
         {
-            info.nMin  = 0;
-            info.nMax  = descr->horz_extent - 1;
             info.nPos  = descr->horz_pos;
             info.nPage = descr->width;
-            info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+            info.fMask = SIF_POS | SIF_PAGE;
             if (descr->style & LBS_DISABLENOSCROLL)
                 info.fMask |= SIF_DISABLENOSCROLL;
-            if (descr->style & WS_HSCROLL)
+            SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+        }
+        else
+        {
+            if (descr->style & LBS_DISABLENOSCROLL)
+            {
+                info.nMin  = 0;
+                info.nMax  = 0;
+                info.fMask = SIF_RANGE | SIF_DISABLENOSCROLL;
                 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+            }
+            else
+            {
+                ShowScrollBar( descr->self, SB_HORZ, FALSE );
+            }
         }
     }
 }
@@ -313,10 +322,17 @@ static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll )
         else
             diff = (descr->top_item - index) * descr->item_height;
 
+#ifdef __REACTOS__
+        if (descr->style & LBS_MULTICOLUMN)
+            ScrollWindowEx(descr->self, diff, 0, NULL, NULL, 0, NULL,
+                           SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN);
+        else
+#endif
         ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
                         SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
     }
-    if (!scroll) InvalidateRect( descr->self, NULL, TRUE );
+    else
+        InvalidateRect( descr->self, NULL, TRUE );
     descr->top_item = index;
     LISTBOX_UpdateScroll( descr );
     return LB_OKAY;
@@ -352,8 +368,11 @@ static void LISTBOX_UpdatePage( LB_DESCR *descr )
 static void LISTBOX_UpdateSize( LB_DESCR *descr )
 {
     RECT rect;
+    LONG style = GetWindowLongPtrW( descr->self, GWL_STYLE );
 
     GetClientRect( descr->self, &rect );
+    if (style & WS_HSCROLL)
+        rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
     descr->width  = rect.right - rect.left;
     descr->height = rect.bottom - rect.top;
     if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
@@ -545,7 +564,7 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
         dis.itemData     = item->data;
         dis.rcItem       = *rect;
         TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%s\n",
-              descr->self, index, item ? debugstr_w(item->str) : "", action,
+              descr->self, index, debugstr_w(item->str), action,
               dis.itemState, wine_dbgstr_rect(rect) );
         SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
         SelectClipRgn( hdc, hrgn );
@@ -648,7 +667,12 @@ static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index, UINT action )
     if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
     if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
     if (descr->font) oldFont = SelectObject( hdc, descr->font );
+#ifdef __REACTOS__
     hbrush = GetControlColor( descr->owner, descr->self, hdc, WM_CTLCOLORLISTBOX);
+#else
+    hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
+                                  (WPARAM)hdc, (LPARAM)descr->self );
+#endif
     if (hbrush) oldBrush = SelectObject( hdc, hbrush );
     if (!IsWindowEnabled(descr->self))
         SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
@@ -681,7 +705,7 @@ static void LISTBOX_DrawFocusRect( LB_DESCR *descr, BOOL on )
     if (!IsWindowEnabled(descr->self))
         SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
     SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
-    LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, on ? FALSE : TRUE );
+    LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, !on );
     if (oldFont) SelectObject( hdc, oldFont );
     ReleaseDC( descr->self, hdc );
 }
@@ -738,7 +762,7 @@ static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count, LPINT tabs )
     if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
                                             descr->nb_tabs * sizeof(INT) )))
         return FALSE;
-    memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) ); 
+    memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
 
     /* convert into "dialog units"*/
     for (i = 0; i < descr->nb_tabs; i++)
@@ -788,7 +812,7 @@ static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPWSTR buffer, BOOL
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
-            WARN( "got an invalid buffer (Delphi bug?)\n" );
+            ERR( "got an invalid buffer (Delphi bug?)\n" );
             SetLastError( ERROR_INVALID_PARAMETER );
             len = LB_ERR;
         }
@@ -821,7 +845,7 @@ static inline INT LISTBOX_lstrcmpiW( LCID lcid, LPCWSTR str1, LPCWSTR str2 )
  */
 static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
 {
-    INT index, min, max, res = -1;
+    INT index, min, max, res;
 
     if (!(descr->style & LBS_SORT)) return -1;  /* Add it at the end */
     min = 0;
@@ -864,7 +888,7 @@ static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
  */
 static INT LISTBOX_FindFileStrPos( LB_DESCR *descr, LPCWSTR str )
 {
-    INT min, max, res = -1;
+    INT min, max, res;
 
     if (!HAS_STRINGS(descr))
         return LISTBOX_FindStringPos( descr, str, FALSE );
@@ -1019,7 +1043,12 @@ static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc )
     }
 
     if (descr->font) oldFont = SelectObject( hdc, descr->font );
+#ifdef __REACTOS__
     hbrush = GetControlColor( descr->owner, descr->self, hdc, WM_CTLCOLORLISTBOX);
+#else
+    hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
+                                  (WPARAM)hdc, (LPARAM)descr->self );
+#endif
     if (hbrush) oldBrush = SelectObject( hdc, hbrush );
     if (!IsWindowEnabled(descr->self)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
 
@@ -1044,14 +1073,10 @@ static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc )
         else
             rect.bottom = rect.top + descr->items[i].height;
 
+        /* keep the focus rect, to paint the focus item after */
         if (i == descr->focus_item)
-        {
-           /* keep the focus rect, to paint the focus item after */
-           focusRect.left = rect.left;
-           focusRect.right = rect.right;
-           focusRect.top = rect.top;
-           focusRect.bottom = rect.bottom;
-        }
+            focusRect = rect;
+    
         LISTBOX_PaintItem( descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
         rect.top = rect.bottom;
 
@@ -1236,16 +1261,23 @@ static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos )
  */
 static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr, INT extent )
 {
-    if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
+    if (descr->style & LBS_MULTICOLUMN)
         return LB_OKAY;
-    if (extent <= 0) extent = 1;
     if (extent == descr->horz_extent) return LB_OKAY;
     TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
     descr->horz_extent = extent;
+    if (descr->style & WS_HSCROLL) {
+        SCROLLINFO info;
+        info.cbSize = sizeof(info);
+        info.nMin  = 0;
+        info.nMax = descr->horz_extent ? descr->horz_extent - 1 : 0;
+        info.fMask = SIF_RANGE;
+        if (descr->style & LBS_DISABLENOSCROLL)
+            info.fMask |= SIF_DISABLENOSCROLL;
+        SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
+    }
     if (descr->horz_pos > extent - descr->width)
         LISTBOX_SetHorizontalPos( descr, extent - descr->width );
-    else
-        LISTBOX_UpdateScroll( descr );
     return LB_OKAY;
 }
 
@@ -1933,7 +1965,11 @@ static LRESULT LISTBOX_HandleHScroll( LB_DESCR *descr, WORD scrollReq, WORD pos
         case SB_THUMBTRACK:
             info.cbSize = sizeof(info);
             info.fMask  = SIF_TRACKPOS;
+#ifdef __REACTOS__
+            GetScrollInfo( descr->self, SB_HORZ, &info );
+#else
             GetScrollInfo( descr->self, SB_VERT, &info );
+#endif
             LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
                                 TRUE );
             break;
@@ -2003,6 +2039,10 @@ static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta )
         pulScrollLines = min((UINT) descr->page_size, pulScrollLines);
         cLineScroll = pulScrollLines * (float)descr->wheel_remain / WHEEL_DELTA;
         descr->wheel_remain -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines;
+#ifdef __REACTOS__
+        if (cLineScroll < 0)
+            cLineScroll -= descr->page_size;
+#endif
         LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
     }
     return 0;
@@ -2492,12 +2532,12 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
     descr->item_height   = 1;
     descr->page_size     = 1;
     descr->column_width  = 150;
-    descr->horz_extent   = (descr->style & WS_HSCROLL) ? 1 : 0;
+    descr->horz_extent   = 0;
     descr->horz_pos      = 0;
     descr->nb_tabs       = 0;
     descr->tabs          = NULL;
     descr->wheel_remain  = 0;
-    descr->caret_on      = lphc ? FALSE : TRUE;
+    descr->caret_on      = !lphc;
     if (descr->style & LBS_NOSEL) descr->caret_on = FALSE;
     descr->in_focus     = FALSE;
     descr->captured      = FALSE;
@@ -2628,8 +2668,10 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
         return 0;
 
     case LB_ADDSTRING:
+#ifdef __REACTOS__
     case LB_ADDSTRING_LOWER:
     case LB_ADDSTRING_UPPER:
+#endif
     {
         INT ret;
         LPWSTR textW;
@@ -2644,12 +2686,14 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             else
                 return LB_ERRSPACE;
         }
+#ifdef __REACTOS__
         /* in the unicode the version, the string is really overwritten
            during the converting case */
         if (msg == LB_ADDSTRING_LOWER)
             strlwrW(textW);
         else if (msg == LB_ADDSTRING_UPPER)
             struprW(textW);
+#endif
         wParam = LISTBOX_FindStringPos( descr, textW, FALSE );
         ret = LISTBOX_InsertString( descr, wParam, textW );
         if (!unicode && HAS_STRINGS(descr))
@@ -2658,8 +2702,10 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
     }
 
     case LB_INSERTSTRING:
+#ifdef __REACTOS__
     case LB_INSERTSTRING_UPPER:
     case LB_INSERTSTRING_LOWER:
+#endif
     {
         INT ret;
         LPWSTR textW;
@@ -2674,12 +2720,14 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             else
                 return LB_ERRSPACE;
         }
+#ifdef __REACTOS__
         /* in the unicode the version, the string is really overwritten
            during the converting case */
         if (msg == LB_INSERTSTRING_LOWER)
             strlwrW(textW);
         else if (msg == LB_INSERTSTRING_UPPER)
             struprW(textW);
+#endif
         ret = LISTBOX_InsertString( descr, wParam, textW );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
@@ -2906,7 +2954,7 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
 
     case LB_SETCURSEL:
         if (IS_MULTISELECT(descr)) return LB_ERR;
-        LISTBOX_SetCaretIndex( descr, wParam, FALSE );
+        LISTBOX_SetCaretIndex( descr, wParam, TRUE );
         ret = LISTBOX_SetSelection( descr, wParam, TRUE, FALSE );
        if (ret != LB_ERR) ret = descr->selected_item;
        return ret;
@@ -3007,10 +3055,7 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
         return LB_OKAY;
 
     case LB_GETLISTBOXINFO:
-        if (descr->style & LBS_MULTICOLUMN) //// ReactOS
-           return descr->page_size * descr->column_width;
-        else
-           return descr->page_size;
+        return descr->page_size;
 
     case WM_DESTROY:
         return LISTBOX_Destroy( descr );
@@ -3169,7 +3214,12 @@ LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
         if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
         {
             RECT rect;
+#ifdef __REACTOS__
             HBRUSH hbrush = GetControlColor( descr->owner, descr->self, (HDC)wParam, WM_CTLCOLORLISTBOX);
+#else
+            HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
+                                              wParam, (LPARAM)descr->self );
+#endif
            TRACE("hbrush = %p\n", hbrush);
            if(!hbrush)
                hbrush = GetSysColorBrush(COLOR_WINDOW);