UpDown update

Dimitrie O. Paun dpaun at rogers.com
Sat Mar 30 20:24:54 CST 2002


NOTE: this one depends on the dfcs.diff patch.

ChangeLog:
  -- implement UDS_HOTTRACK
  -- implement NM_RELEASEDCAPTURE
  -- implement UDM_[GS]ETUNICODEFORMAT
  -- get rid of WM_NCCREATE processing
  -- use InvalidateRect instead of a synch refresh
  -- implement auto auto arrow press on key presses
  -- more code cleanups
  -- better drawing, closer to native

Index: dlls/comctl32/updown.c
===================================================================
RCS file: /var/cvs/wine/dlls/comctl32/updown.c,v
retrieving revision 1.37
diff -u -r1.37 updown.c
--- dlls/comctl32/updown.c	28 Mar 2002 22:05:18 -0000	1.37
+++ dlls/comctl32/updown.c	31 Mar 2002 02:14:57 -0000
@@ -1,7 +1,7 @@
 /*		
  * Updown control
  *
- * Copyright 1997 Dimitrie O. Paun
+ * Copyright 1997, 2002 Dimitrie O. Paun
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -45,35 +45,41 @@
     INT       MinVal;          /* Minimum up-down value */
     INT       MaxVal;          /* Maximum up-down value */
     HWND      Buddy;           /* Handle to the buddy window */
-    int       BuddyType;       /* Remembers the buddy type BUDDY_TYPE_* */
+    INT       BuddyType;       /* Remembers the buddy type BUDDY_TYPE_* */
     INT       Flags;           /* Internal Flags FLAG_* */
+    BOOL      UnicodeFormat;   /* Marks the use of Unicode internally */
 } UPDOWN_INFO;
 
 /* Control configuration constants */
 
-#define INITIAL_DELAY    500    /* initial timer until auto-inc kicks in */
-#define REPEAT_DELAY     50     /* delay between auto-increments */
-
-#define DEFAULT_WIDTH       14  /* default width of the ctrl */
-#define DEFAULT_XSEP         0  /* default separation between buddy and crtl */
-#define DEFAULT_ADDTOP       0  /* amount to extend above the buddy window */
-#define DEFAULT_ADDBOT       0  /* amount to extend below the buddy window */
-#define DEFAULT_BUDDYBORDER  2  /* Width/height of the buddy border */
+#define INITIAL_DELAY	500    /* initial timer until auto-inc kicks in */
+#define AUTOPRESS_DELAY	250    /* time to keep arrow pressed on KEY_DOWN */
+#define REPEAT_DELAY	50     /* delay between auto-increments */
+
+#define DEFAULT_WIDTH	    14 /* default width of the ctrl */
+#define DEFAULT_XSEP         0 /* default separation between buddy and ctrl */
+#define DEFAULT_ADDTOP       0 /* amount to extend above the buddy window */
+#define DEFAULT_ADDBOT       0 /* amount to extend below the buddy window */
+#define DEFAULT_BUDDYBORDER  2 /* Width/height of the buddy border */
+#define DEFAULT_BUDDYSPACER  2 /* Spacer between the buddy and the ctrl */
 
 
 /* Work constants */
 
-#define FLAG_INCR        0x01
-#define FLAG_DECR        0x02
-#define FLAG_MOUSEIN     0x04
-#define FLAG_CLICKED     (FLAG_INCR | FLAG_DECR)
+#define FLAG_INCR	0x01
+#define FLAG_DECR	0x02
+#define FLAG_MOUSEIN	0x04
+#define FLAG_PRESSED	0x08
+#define FLAG_ARROW	(FLAG_INCR | FLAG_DECR)
 
 #define BUDDY_TYPE_UNKNOWN 0
 #define BUDDY_TYPE_LISTBOX 1
 #define BUDDY_TYPE_EDIT    2
 
-#define TIMERID1         1
-#define TIMERID2         2
+#define TIMER_AUTOREPEAT   1
+#define TIMER_ACCEL        2
+#define TIMER_AUTOPRESS    3
+
 #define BUDDY_UPDOWN_HWND        "buddyUpDownHWND"
 #define BUDDY_SUPERCLASS_WNDPROC "buddySupperClassWndProc"
 
@@ -84,8 +90,7 @@
 #define UPDOWN_GetInfoPtr(hwnd) ((UPDOWN_INFO *)GetWindowLongA (hwnd,0))
 #define COUNT_OF(a) (sizeof(a)/sizeof(a[0]))
 
-static LRESULT CALLBACK
-UPDOWN_Buddy_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action);
 
 /***********************************************************************
  *           UPDOWN_IsBuddyEdit
@@ -157,13 +162,13 @@
  *           UPDOWN_GetArrowRect
  * wndPtr   - pointer to the up-down wnd
  * rect     - will hold the rectangle
- * incr     - TRUE  get the "increment" rect (up or right)
- *            FALSE get the "decrement" rect (down or left)
+ * arrow    - FLAG_INCR to get the "increment" rect (up or right)
+ *            FLAG_DECR to get the "decrement" rect (down or left)
+ *            If both flags are pressent, the envelope is returned.
  */
-static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, BOOL incr)
+static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
 {
     DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
-    int   len; /* will hold the width or height */
 
     GetClientRect (infoPtr->Self, rect);
 
@@ -180,22 +185,28 @@
         InflateRect(rect, 0, -DEFAULT_BUDDYBORDER);
     }
 
+    /* now figure out if we need a space away from the buddy */
+    if ( IsWindow(infoPtr->Buddy) ) {
+	if (dwStyle & UDS_ALIGNLEFT) rect->right -= DEFAULT_BUDDYSPACER;
+	else rect->left += DEFAULT_BUDDYSPACER;
+    }
+    
     /*
      * We're calculating the midpoint to figure-out where the
      * separation between the buttons will lay. We make sure that we
      * round the uneven numbers by adding 1.
      */
     if (dwStyle & UDS_HORZ) {
-        len = rect->right - rect->left + 1; /* compute the width */
-        if (incr)
+        int len = rect->right - rect->left + 1; /* compute the width */
+        if (arrow & FLAG_INCR)
             rect->left = rect->left + len/2; 
-        else
-            rect->right =  rect->left + len/2;
+        if (arrow & FLAG_DECR)
+            rect->right =  rect->left + len/2 - 1;
     } else {
-        len = rect->bottom - rect->top + 1; /* compute the height */
-        if (incr)
-            rect->bottom =  rect->top + len/2;
-        else
+        int len = rect->bottom - rect->top + 1; /* compute the height */
+        if (arrow & FLAG_INCR)
+            rect->bottom =  rect->top + len/2 - 1;
+        if (arrow & FLAG_DECR)
             rect->top =  rect->top + len/2;
     }
 }
@@ -208,11 +219,13 @@
  */
 static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt)
 {
-    UPDOWN_GetArrowRect (infoPtr, rect, TRUE);
-    if(PtInRect(rect, pt)) return TRUE;
+    UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR);
+    if(PtInRect(rect, pt)) return FLAG_INCR;
 
-    UPDOWN_GetArrowRect (infoPtr, rect, FALSE);
-    return FALSE;
+    UPDOWN_GetArrowRect (infoPtr, rect, FLAG_DECR);
+    if(PtInRect(rect, pt)) return FLAG_DECR;
+
+    return 0;
 }
 
 
@@ -320,91 +333,103 @@
 } 
 
 /***********************************************************************
- * UPDOWN_DrawBuddyBorder
- *
- * When we have a buddy set and that we are aligned on our buddy, we
- * want to draw a sunken edge to make like we are part of that control.
- */
-static void UPDOWN_DrawBuddyBorder (UPDOWN_INFO *infoPtr, HDC hdc)
-{
-    DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
-    RECT  clientRect;
-
-    GetClientRect(infoPtr->Self, &clientRect);
-
-    if (dwStyle & UDS_ALIGNLEFT)
-        DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_BOTTOM | BF_LEFT | BF_TOP);
-    else
-        DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_BOTTOM | BF_RIGHT | BF_TOP);
-}
-
-/***********************************************************************
  * UPDOWN_Draw
  *
  * Draw the arrows. The background need not be erased.
  */
-static void UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
+static LRESULT UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
 {
     DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
-    BOOL prssed;
+    BOOL pressed, hot;
     RECT rect;
 
     /* Draw the common border between ourselves and our buddy */
-    if (UPDOWN_HasBuddyBorder(infoPtr))
-        UPDOWN_DrawBuddyBorder(infoPtr, hdc);
+    if (UPDOWN_HasBuddyBorder(infoPtr)) {
+	GetClientRect(infoPtr->Self, &rect);
+	DrawEdge(hdc, &rect, EDGE_SUNKEN, 
+		 BF_BOTTOM | BF_TOP | 
+		 (dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
+    }
   
     /* Draw the incr button */
-    UPDOWN_GetArrowRect (infoPtr, &rect, TRUE);
-    prssed = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
+    UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR);
+    pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
+    hot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
     DrawFrameControl(hdc, &rect, DFC_SCROLL, 
 	(dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
-	(prssed ? DFCS_PUSHED : 0) |
-	(dwStyle&WS_DISABLED ? DFCS_INACTIVE : 0) );
+        ((dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
+	(pressed ? DFCS_PUSHED : 0) |
+	(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
 
-    /* Draw the space between the buttons */
-    rect.top = rect.bottom; rect.bottom++;
-    DrawEdge(hdc, &rect, 0, BF_MIDDLE);
-		    
     /* Draw the decr button */
-    UPDOWN_GetArrowRect(infoPtr, &rect, FALSE);
-    prssed = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
+    UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR);
+    pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
+    hot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
     DrawFrameControl(hdc, &rect, DFC_SCROLL, 
 	(dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
-	(prssed ? DFCS_PUSHED : 0) |
+        ((dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) |
+	(pressed ? DFCS_PUSHED : 0) |
 	(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
+
+    return 0;
 }
 
 /***********************************************************************
- * UPDOWN_Refresh
+ * UPDOWN_Paint
  *
- * Synchronous drawing (must NOT be used in WM_PAINT).
+ * Asynchronous drawing (must ONLY be used in WM_PAINT).
  * Calls UPDOWN_Draw.
  */
-static void UPDOWN_Refresh (UPDOWN_INFO *infoPtr)
+static LRESULT UPDOWN_Paint (UPDOWN_INFO *infoPtr, HDC hdc)
 {
-    HDC hdc = GetDC(infoPtr->Self);
-    UPDOWN_Draw(infoPtr, hdc);
-    ReleaseDC(infoPtr->Self, hdc);
+    PAINTSTRUCT ps;
+    if (hdc) return UPDOWN_Draw (infoPtr, hdc);
+    hdc = BeginPaint (infoPtr->Self, &ps);
+    UPDOWN_Draw (infoPtr, hdc);
+    EndPaint (infoPtr->Self, &ps);
+    return 0;
 }
 
-
 /***********************************************************************
- * UPDOWN_Paint [Internal]
+ * UPDOWN_KeyPressed
  *
- * Asynchronous drawing (must ONLY be used in WM_PAINT).
- * Calls UPDOWN_Draw.
+ * Handle key presses (up & down) when we have to do so
  */
-static void UPDOWN_Paint (UPDOWN_INFO *infoPtr, HDC hdc)
+static LRESULT UPDOWN_KeyPressed(UPDOWN_INFO *infoPtr, int key)
 {
-    if (hdc) {
-        UPDOWN_Draw (infoPtr, hdc);
-    } else {
-        PAINTSTRUCT ps;
+    int arrow;
+    
+    if (key == VK_UP) arrow = FLAG_INCR;
+    else if (key == VK_DOWN) arrow = FLAG_DECR;
+    else return 1;
+    
+    UPDOWN_GetBuddyInt (infoPtr);
+    infoPtr->Flags &= ~FLAG_ARROW;
+    infoPtr->Flags |= FLAG_PRESSED | arrow;
+    InvalidateRect (infoPtr->Self, NULL, FALSE);
+    SetTimer(infoPtr->Self, TIMER_AUTOPRESS, AUTOPRESS_DELAY, 0);
+    UPDOWN_DoAction (infoPtr, 1, arrow);
+    return 0;
+}
 
-        hdc = BeginPaint (infoPtr->Self, &ps);
-        UPDOWN_Draw (infoPtr, hdc);
-        EndPaint (infoPtr->Self, &ps);
+/***********************************************************************
+ * UPDOWN_Buddy_SubclassProc used to handle messages sent to the buddy 
+ *                           control.
+ */
+static LRESULT CALLBACK 
+UPDOWN_Buddy_SubclassProc(HWND  hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    WNDPROC superClassWndProc = (WNDPROC)GetPropA(hwnd, BUDDY_SUPERCLASS_WNDPROC);
+    TRACE("hwnd=%04x, wndProc=%d, uMsg=%04x, wParam=%d, lParam=%d\n", 
+	  hwnd, (INT)superClassWndProc, uMsg, wParam, (UINT)lParam);
+
+    if (uMsg == WM_KEYDOWN) {
+        HWND upDownHwnd = GetPropA(hwnd, BUDDY_UPDOWN_HWND);
+      
+	UPDOWN_KeyPressed(UPDOWN_GetInfoPtr(upDownHwnd), (int)wParam);
     }
+
+    return CallWindowProcW( superClassWndProc, hwnd, uMsg, wParam, lParam);
 }
 
 /***********************************************************************
@@ -508,20 +533,22 @@
  *           UPDOWN_DoAction
  *
  * This function increments/decrements the CurVal by the 
- * 'delta' amount according to the 'incr' flag
+ * 'delta' amount according to the 'action' flag which can be a
+ * combination of FLAG_INCR and FLAG_DECR
  * It notifies the parent as required.
  * It handles wraping and non-wraping correctly.
  * It is assumed that delta>0
  */
-static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, BOOL incr)
+static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action)
 {
     DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
     NM_UPDOWN ni;
 
-    TRACE("%s by %d\n", incr ? "inc" : "dec", delta);
+    TRACE("%d by %d\n", action, delta);
 
     /* check if we can do the modification first */
-    delta *= (incr ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1);
+    delta *= (action & FLAG_INCR ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1);
+    if ( (action & FLAG_INCR) && (action & FLAG_DECR) ) delta = 0;
 
     /* We must notify parent now to obtain permission */
     ni.iPos = infoPtr->CurVal;
@@ -571,16 +598,23 @@
  */
 static BOOL UPDOWN_CancelMode (UPDOWN_INFO *infoPtr)
 {
-    /* if not in 'capture' mode, do nothing */
-    if(!(infoPtr->Flags & FLAG_CLICKED)) return FALSE;
-
-    KillTimer (infoPtr->Self, TIMERID1); /* kill all possible timers */
-    KillTimer (infoPtr->Self, TIMERID2);
+    if (!(infoPtr->Flags & FLAG_PRESSED)) return FALSE;
+    
+    KillTimer (infoPtr->Self, TIMER_AUTOREPEAT);
+    KillTimer (infoPtr->Self, TIMER_ACCEL);
+    KillTimer (infoPtr->Self, TIMER_AUTOPRESS);
   
-    if (GetCapture() == infoPtr->Self) ReleaseCapture();
+    if (GetCapture() == infoPtr->Self) {
+	NMHDR hdr;
+	hdr.hwndFrom = infoPtr->Self;
+	hdr.idFrom   = GetWindowLongW (infoPtr->Self, GWL_ID);
+	hdr.code = NM_RELEASEDCAPTURE;
+	SendMessageW(GetParent (infoPtr->Self), WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr);
+	ReleaseCapture();
+    }
     
-    infoPtr->Flags = 0;                  /* get rid of any flags     */
-    UPDOWN_Refresh (infoPtr);            /* redraw the control just in case */
+    infoPtr->Flags &= ~FLAG_PRESSED;
+    InvalidateRect (infoPtr->Self, NULL, FALSE);
   
     return TRUE;
 }
@@ -596,63 +630,58 @@
 {
     DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
     RECT rect;
-    int temp;
+    int temp, arrow;
 
     switch(msg)
     {
         case WM_LBUTTONDOWN:  /* Initialise mouse tracking */
-            /* If we are already in the 'clicked' mode, then nothing to do */
-            if(infoPtr->Flags & FLAG_CLICKED) return;
+            /* If we are inside an arrow, then nothing to do */
+            if(!(infoPtr->Flags & FLAG_MOUSEIN)) return;
 
             /* If the buddy is an edit, will set focus to it */
 	    if (UPDOWN_IsBuddyEdit(infoPtr)) SetFocus(infoPtr->Buddy);
 
             /* Now see which one is the 'active' arrow */
-            temp = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt);
+	    if (infoPtr->Flags & FLAG_ARROW) {
 
-            /* Update the CurVal if necessary */
-            if (dwStyle & UDS_SETBUDDYINT) UPDOWN_GetBuddyInt (infoPtr);
+            	/* Update the CurVal if necessary */
+            	if (dwStyle & UDS_SETBUDDYINT) UPDOWN_GetBuddyInt (infoPtr);
 	
-            /* Set up the correct flags */
-            infoPtr->Flags  = FLAG_MOUSEIN | (temp ? FLAG_INCR : FLAG_DECR); 
+            	/* Set up the correct flags */
+            	infoPtr->Flags |= FLAG_PRESSED; 
       
-            /* repaint the control */
-            UPDOWN_Refresh (infoPtr);
+            	/* repaint the control */
+	    	InvalidateRect (infoPtr->Self, NULL, FALSE);
 
-            /* process the click */
-            UPDOWN_DoAction (infoPtr, 1, infoPtr->Flags & FLAG_INCR);
+            	/* process the click */
+            	UPDOWN_DoAction (infoPtr, 1, infoPtr->Flags & FLAG_ARROW);
 
-            /* now capture all mouse messages */
-            SetCapture (infoPtr->Self);
+            	/* now capture all mouse messages */
+            	SetCapture (infoPtr->Self);
 
-            /* and startup the first timer */
-            SetTimer(infoPtr->Self, TIMERID1, INITIAL_DELAY, 0); 
+            	/* and startup the first timer */
+            	SetTimer(infoPtr->Self, TIMER_AUTOREPEAT, INITIAL_DELAY, 0);
+	    }
             break;
 
 	case WM_MOUSEMOVE:
-	    /* If we are not in the 'clicked' mode, then nothing to do */
-	    if(!(infoPtr->Flags & FLAG_CLICKED)) return;
-
             /* save the flags to see if any got modified */
             temp = infoPtr->Flags;
 
-            /* Now get the 'active' arrow rectangle */
-            if (infoPtr->Flags & FLAG_INCR)
-		UPDOWN_GetArrowRect (infoPtr, &rect, TRUE);
-	    else
-		UPDOWN_GetArrowRect (infoPtr, &rect, FALSE);
+            /* Now see which one is the 'active' arrow */
+            arrow = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt);
 
             /* Update the flags if we are in/out */
-            if(PtInRect(&rect, pt)) {
-	        infoPtr->Flags |=  FLAG_MOUSEIN;
+	    infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW);
+            if(arrow) {
+	        infoPtr->Flags |=  FLAG_MOUSEIN | arrow;
             } else {
-	        infoPtr->Flags &= ~FLAG_MOUSEIN;
-		/* reset acceleration */
 	        if(infoPtr->AccelIndex != -1) infoPtr->AccelIndex = 0;
             }
 	    
             /* If state changed, redraw the control */
-            if(temp != infoPtr->Flags) UPDOWN_Refresh (infoPtr);
+            if(temp != infoPtr->Flags)
+		 InvalidateRect (infoPtr->Self, &rect, FALSE);
             break;
 
 	default:
@@ -671,17 +700,13 @@
     DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
     int temp;
     
-    if (!infoPtr && (message != WM_CREATE) && (message != WM_NCCREATE))
+    if (!infoPtr && (message != WM_CREATE))
         return DefWindowProcW (hwnd, message, wParam, lParam); 
 
     switch(message)
     {
-	case WM_NCCREATE:
-	    /* get rid of border, if any */
-            SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~WS_BORDER);
-            return TRUE;
-
         case WM_CREATE:
+            SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~WS_BORDER);
             infoPtr = (UPDOWN_INFO*)COMCTL32_Alloc (sizeof(UPDOWN_INFO));
 	    SetWindowLongW (hwnd, 0, (DWORD)infoPtr);
 
@@ -716,14 +741,20 @@
 	
 	case WM_ENABLE:
 	    if (dwStyle & WS_DISABLED) UPDOWN_CancelMode (infoPtr);
-
-	    UPDOWN_Refresh (infoPtr);
+	    InvalidateRect (infoPtr->Self, NULL, FALSE);
 	    break;
 
 	case WM_TIMER:
+	   /* is this the auto-press timer? */
+	   if(wParam == TIMER_AUTOPRESS) {
+		KillTimer(hwnd, TIMER_AUTOPRESS);
+		infoPtr->Flags &= ~(FLAG_PRESSED | FLAG_ARROW);
+		InvalidateRect(infoPtr->Self, NULL, FALSE);
+	   }
+
 	   /* if initial timer, kill it and start the repeat timer */
-  	   if(wParam == TIMERID1) {
-		KillTimer(hwnd, TIMERID1);
+  	   if(wParam == TIMER_AUTOREPEAT) {
+		KillTimer(hwnd, TIMER_AUTOREPEAT);
 		/* if no accel info given, used default timer */
 		if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) {
 		    infoPtr->AccelIndex = -1;
@@ -732,20 +763,20 @@
 		    infoPtr->AccelIndex = 0; /* otherwise, use it */
 		    temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
 		}
-		SetTimer(hwnd, TIMERID2, temp, 0);
+		SetTimer(hwnd, TIMER_ACCEL, temp, 0);
       	    }
 
 	    /* now, if the mouse is above us, do the thing...*/
 	    if(infoPtr->Flags & FLAG_MOUSEIN) {
 		temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc;
-		UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_INCR);
+		UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_ARROW);
 	
 		if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1) {
-		    KillTimer(hwnd, TIMERID2);
+		    KillTimer(hwnd, TIMER_ACCEL);
 		    infoPtr->AccelIndex++; /* move to the next accel info */
 		    temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
 	  	    /* make sure we have at least 1ms intervals */
-		    SetTimer(hwnd, TIMERID2, temp, 0);	    
+		    SetTimer(hwnd, TIMER_ACCEL, temp, 0);	    
 		}
 	    }
 	    break;
@@ -754,16 +785,18 @@
 	  return UPDOWN_CancelMode (infoPtr);
 
 	case WM_LBUTTONUP:
-	    if(!UPDOWN_CancelMode(infoPtr)) break;
-
-	    SendMessageW( GetParent(hwnd), 
-			  dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL,
-                  	  MAKELONG(SB_ENDSCROLL, infoPtr->CurVal), hwnd);
-
-	    /*If we released the mouse and our buddy is an edit */
-	    /* we must select all text in it.                   */
-	    if (UPDOWN_IsBuddyEdit(infoPtr))
-		SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1));
+	    if (GetCapture() != infoPtr->Self) break;
+	    
+	    if ( (infoPtr->Flags & FLAG_MOUSEIN) &&
+		 (infoPtr->Flags & FLAG_ARROW) ) {
+		    
+	    	SendMessageW( GetParent(hwnd), 
+			      dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL,
+                  	      MAKELONG(SB_ENDSCROLL, infoPtr->CurVal), hwnd);
+		if (UPDOWN_IsBuddyEdit(infoPtr))
+		    SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1));
+	    }
+	    UPDOWN_CancelMode(infoPtr);
 	    break;
       
 	case WM_LBUTTONDOWN:
@@ -778,20 +811,12 @@
 
 	case WM_KEYDOWN:
 	    if((dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr)) {
-		switch(wParam){
-		    case VK_UP:  
-		    case VK_DOWN:
-		  	UPDOWN_GetBuddyInt (infoPtr);
-		        /* FIXME: Paint the according button pressed for some time, like win95 does*/
-			UPDOWN_DoAction (infoPtr, 1, wParam==VK_UP);
-		    break;
-	        }
+		return UPDOWN_KeyPressed(infoPtr, (int)wParam);
 	    }
 	    break;
       
 	case WM_PAINT:
-	    UPDOWN_Paint (infoPtr, (HDC)wParam);
-	    break;
+	    return UPDOWN_Paint (infoPtr, (HDC)wParam);
     
 	case UDM_GETACCEL:
 	    if (wParam==0 && lParam==0) return infoPtr->AccelCount;
@@ -854,8 +879,8 @@
 		if(temp < infoPtr->MinVal) temp = infoPtr->MinVal;
 		if(temp > infoPtr->MaxVal) temp = infoPtr->MaxVal;
 	    }
-	    wParam = infoPtr->CurVal; /* save prev value   */
-	    infoPtr->CurVal = temp;   /* set the new value */
+	    wParam = infoPtr->CurVal;
+	    infoPtr->CurVal = temp;
 	    if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr);
 	    return wParam;            /* return prev value */
       
@@ -901,6 +926,18 @@
 	    if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr);
 	    return temp;                    /* return prev value */
 
+	case UDM_GETUNICODEFORMAT:
+	    if (wParam || lParam) UNKNOWN_PARAM(UDM_GETUNICODEFORMAT, wParam, lParam);
+	    /* we lie a bit here, we're always using Unicode internally */
+	    return infoPtr->UnicodeFormat;
+
+	case UDM_SETUNICODEFORMAT:
+	    if (lParam) UNKNOWN_PARAM(UDM_SETUNICODEFORMAT, wParam, lParam);
+	    /* do we really need to honour this flag? */
+	    temp = infoPtr->UnicodeFormat;
+	    infoPtr->UnicodeFormat = (BOOL)wParam;
+	    return temp;
+	    
 	default: 
 	    if (message >= WM_USER) 
 	     	ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam);
@@ -908,37 +945,6 @@
     } 
 
     return 0;
-}
-
-/***********************************************************************
- * UPDOWN_Buddy_SubclassProc used to handle messages sent to the buddy 
- *                           control.
- */
-LRESULT CALLBACK UPDOWN_Buddy_SubclassProc(HWND  hwnd, UINT uMsg, 
-					   WPARAM wParam, LPARAM lParam)
-{
-    WNDPROC superClassWndProc = (WNDPROC)GetPropA(hwnd, BUDDY_SUPERCLASS_WNDPROC);
-    TRACE("hwnd=%04x, wndProc=%d, uMsg=%04x, wParam=%d, lParam=%d\n", 
-	  hwnd, (INT)superClassWndProc, uMsg, wParam, (UINT)lParam);
-
-    switch (uMsg) {
-        case WM_KEYDOWN:
-            if ( ((int)wParam == VK_UP ) || ((int)wParam == VK_DOWN ) ) {
-                HWND upDownHwnd      = GetPropA(hwnd, BUDDY_UPDOWN_HWND);
-                UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr(upDownHwnd);
-      
-    		if (UPDOWN_IsBuddyListbox(infoPtr)) {
-                    INT oldVal = SendMessageW(hwnd, LB_GETCURSEL, 0, 0);
-                    SendMessageW(hwnd, LB_SETCURSEL, oldVal+1, 0);
-                } else {
-	            UPDOWN_GetBuddyInt(infoPtr);
-                    UPDOWN_DoAction(infoPtr, 1, wParam==VK_UP);
-                }
-	    }
-            break;
-        /* else Fall Through */
-    }
-    return CallWindowProcW( superClassWndProc, hwnd, uMsg, wParam, lParam);
 }
 
 /***********************************************************************




More information about the wine-patches mailing list