comctl32 updown base 16 bug fix

Leslie Choong septikus at gmail.com
Sat Mar 24 14:52:40 CDT 2007


Hi There, this bug fix addresses the issue brought up here:
http://bugs.winehq.org/show_bug.cgi?id=7034

I have added tests to confirm the existence of the bug and that it has
been fixed.

Let me know of any changes you think are necessary.
-Leslie Choong
-------------- next part --------------
From 538f7ffdac284ff15daafa72c4209a24221768e8 Mon Sep 17 00:00:00 2001
From: U-SEPTIKUS\Leslie <septikus at gmail.com>
Date: Thu, 22 Mar 2007 20:22:03 -0800
Subject: [PATCH] comctl32: updown: Fixed Base 16 range handling bug

---
 tests/updown.c |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 updown.c       |   43 ++++++++++++++++++++++++++++++++++------
 2 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/dlls/comctl32/tests/updown.c b/dlls/comctl32/tests/updown.c
index a5781ee..2dfa61c 100644
--- a/dlls/comctl32/tests/updown.c
+++ b/dlls/comctl32/tests/updown.c
@@ -546,6 +546,65 @@ static void test_updown_unicode(void)
     ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_unicode_seq, "test updown unicode", FALSE);
 }
 
+static void test_set_base16_range_bug(void)
+{
+    int r;
+
+    /* Some messages are not checked as previous value set before function */
+    SendMessage(updown, UDM_SETBASE, 10 , 0);
+    r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+    expect(10,r);
+
+    SendMessage(updown, UDM_SETRANGE, 0 , MAKELONG(10,-10) );
+    r = SendMessage(updown, UDM_GETRANGE, 0,0);
+    expect(MAKELONG(10,-10),r);
+
+    r = SendMessage(updown, UDM_SETBASE, 16 , 0);
+    expect(10,r);
+    r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+    expect(16,r);
+
+    r = SendMessage(updown, UDM_GETRANGE, 0,0);
+    expect(MAKELONG(10,-10),r);
+
+    /* Test that the lower range is 0xA */
+    SendMessage(updown, UDM_SETPOS, 0,MAKELONG(10,0));
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(10,LOWORD(r));
+    expect(1,HIWORD(r));
+
+    r = SendMessage(updown, UDM_SETPOS, 0,MAKELONG(9,0));
+    expect(10,r);
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(10,LOWORD(r));
+    expect(1,HIWORD(r));
+
+    r = SendMessage(updown, UDM_SETPOS, 0,MAKELONG(11,0));
+    expect(10,r);
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(11,LOWORD(r));
+    expect(1,HIWORD(r));
+
+    /* Test that upper range is 0xFFF6 (-10 unsigned) */
+    r = SendMessage(updown, UDM_SETPOS, 0, MAKELONG(0xFFF6,0));
+    expect(11,r);
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(0xFFF6,LOWORD(r));
+    expect(1,HIWORD(r));
+   
+    r = SendMessage(updown, UDM_SETPOS, 0, MAKELONG(0xFFF7,0));
+    expect(-10,r);
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(0xFFF6,LOWORD(r));
+    expect(1,HIWORD(r));
+
+    r = SendMessage(updown, UDM_SETPOS, 0, MAKELONG(0xFFF5,0));
+    expect(-10,r);
+    r = SendMessage(updown, UDM_GETPOS, 0,0);
+    expect(0xFFF5,LOWORD(r));
+    expect(1,HIWORD(r));
+}
+
 static void test_create_updown_control(void)
 {
     CHAR text[MAX_PATH];
@@ -580,6 +639,7 @@ static void test_create_updown_control(void)
     test_updown_buddy();
     test_updown_base();
     test_updown_unicode();
+    test_set_base16_range_bug();
 }
 
 START_TEST(updown)
diff --git a/dlls/comctl32/updown.c b/dlls/comctl32/updown.c
old mode 100644
new mode 100755
index 7fbe3c9..aec1e4a
--- a/dlls/comctl32/updown.c
+++ b/dlls/comctl32/updown.c
@@ -128,10 +128,20 @@ static inline BOOL UPDOWN_IsBuddyListbox(UPDOWN_INFO *infoPtr)
  */
 static BOOL UPDOWN_InBounds(UPDOWN_INFO *infoPtr, int val)
 {
-    if(infoPtr->MaxVal > infoPtr->MinVal)
-        return (infoPtr->MinVal <= val) && (val <= infoPtr->MaxVal);
-    else
-        return (infoPtr->MaxVal <= val) && (val <= infoPtr->MinVal);
+    if(infoPtr->Base == 10) {
+        if(infoPtr->MaxVal > infoPtr->MinVal)
+            return (infoPtr->MinVal <= val) && (val <= infoPtr->MaxVal);
+        else
+            return (infoPtr->MaxVal <= val) && (val <= infoPtr->MinVal);
+    } else { /* Base is 16 and must do unsigned integer comparison */
+        unsigned int uMinVal = (unsigned int) infoPtr->MinVal;
+        unsigned int uMaxVal = (unsigned int) infoPtr->MaxVal;
+        unsigned int uval = (unsigned int) val;
+        if(uMaxVal > uMinVal)
+            return (uMinVal <= uval) && (uval <= uMaxVal);
+        else
+            return (uMaxVal <= uval) && (uval <= uMinVal);
+    }
 }
 
 /***********************************************************************
@@ -616,7 +626,13 @@ static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action)
     TRACE("%d by %d\n", action, delta);
 
     /* check if we can do the modification first */
-    delta *= (action & FLAG_INCR ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1);
+    if(infoPtr->Base == 10)
+        delta *= (action & FLAG_INCR ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1);
+    else {
+        unsigned int uMinVal = (unsigned int) infoPtr->MinVal;
+        unsigned int uMaxVal = (unsigned int) infoPtr->MaxVal;
+        delta *= (action & FLAG_INCR ? 1 : -1) * (uMaxVal < uMinVal ? -1 : 1);
+    }
     if ( (action & FLAG_INCR) && (action & FLAG_DECR) ) delta = 0;
 
     TRACE("current %d, delta: %d\n", infoPtr->CurVal, delta);
@@ -992,8 +1008,21 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L
 	    temp = (short)LOWORD(lParam);
 	    TRACE("UpDown Ctrl new value(%d), hwnd=%p\n", temp, hwnd);
 	    if(!UPDOWN_InBounds(infoPtr, temp)) {
-		if(temp < infoPtr->MinVal) temp = infoPtr->MinVal;
-		if(temp > infoPtr->MaxVal) temp = infoPtr->MaxVal;
+                if(infoPtr->Base == 10) {
+                    if(temp < infoPtr->MinVal) temp = infoPtr->MinVal;
+                    if(temp > infoPtr->MaxVal) temp = infoPtr->MaxVal;
+                } else { /* In Base 16 mode and must treat as unsigned */
+                    unsigned int uMinVal = (unsigned int) infoPtr->MinVal;
+                    unsigned int uMaxVal = (unsigned int) infoPtr->MaxVal;
+                    unsigned int utemp = (unsigned int) temp;
+                    if(uMaxVal > uMinVal) {
+                        if(utemp < uMinVal) temp = infoPtr->MinVal;
+                        if(utemp > uMaxVal) temp = infoPtr->MaxVal;
+                    } else { /* Ranges are flopped so must flop comparison */
+                        if(utemp > uMinVal) temp = infoPtr->MinVal;
+                        if(utemp < uMaxVal) temp = infoPtr->MaxVal;
+                    }
+                }
 	    }
 	    wParam = infoPtr->CurVal;
 	    infoPtr->CurVal = temp;


More information about the wine-patches mailing list