Commit a7dbc6c8 authored by Dimitrie O. Paun's avatar Dimitrie O. Paun Committed by Alexandre Julliard

- updown unicodification

- better/cleaner buddy handling - few bugs fixed - more testing - consistent indentation
parent 6815f3a6
......@@ -17,22 +17,6 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* TODO:
* - I think I do not handle correctly the WS_BORDER style.
* (Should be fixed. <ekohl@abo.rhein-zeitung.de>)
*
* Testing:
* Not much. The following have not been tested at all:
* - horizontal arrows
* - listbox as buddy window
* - acceleration
* - base 16
* - integers with thousand separators.
* (fixed bugs. <noel@macadamian.com>)
*
* Even though the above list seems rather large, the control seems to
* behave very well so I am confident it does work in most (all) of the
* untested cases.
*/
#include <stdlib.h>
......@@ -45,30 +29,29 @@
#include "winuser.h"
#include "commctrl.h"
#include "winnls.h"
#include "ntddk.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(updown);
#define UPDOWN_BUDDYCLASSNAMELEN 40
typedef struct
{
HWND Self; /* Handle to this up-down control */
UINT AccelCount; /* Number of elements in AccelVect */
UDACCEL* AccelVect; /* Vector containing AccelCount elements */
INT AccelIndex; /* Current accel index, -1 if not accelerating */
INT AccelIndex; /* Current accel index, -1 if not accel'ing */
INT Base; /* Base to display nr in the buddy window */
INT CurVal; /* Current up-down value */
INT MinVal; /* Minimum up-down value */
INT MaxVal; /* Maximum up-down value */
HWND Buddy; /* Handle to the buddy window */
CHAR szBuddyClass[UPDOWN_BUDDYCLASSNAMELEN]; /* Buddy window class name */
int BuddyType; /* Remembers the buddy type BUDDY_TYPE_* */
INT Flags; /* Internal Flags FLAG_* */
} UPDOWN_INFO;
/* Control configuration constants */
#define INITIAL_DELAY 500 /* initial timer until auto-increment kicks in */
#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 */
......@@ -85,6 +68,10 @@ typedef struct
#define FLAG_MOUSEIN 0x04
#define FLAG_CLICKED (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 BUDDY_UPDOWN_HWND "buddyUpDownHWND"
......@@ -95,11 +82,30 @@ typedef struct
"(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
#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);
/***********************************************************************
* UPDOWN_IsBuddyEdit
* Tests if our buddy is an edit control.
*/
static inline BOOL UPDOWN_IsBuddyEdit(UPDOWN_INFO *infoPtr)
{
return infoPtr->BuddyType == BUDDY_TYPE_EDIT;
}
/***********************************************************************
* UPDOWN_IsBuddyListbox
* Tests if our buddy is a listbox control.
*/
static inline BOOL UPDOWN_IsBuddyListbox(UPDOWN_INFO *infoPtr)
{
return infoPtr->BuddyType == BUDDY_TYPE_LISTBOX;
}
/***********************************************************************
* UPDOWN_InBounds
* Tests if a given value 'val' is between the Min&Max limits
*/
......@@ -113,22 +119,20 @@ static BOOL UPDOWN_InBounds(UPDOWN_INFO *infoPtr, int val)
/***********************************************************************
* UPDOWN_OffsetVal
* Tests if we can change the current value by delta. If so, it changes
* it and returns TRUE. Else, it leaves it unchanged and returns FALSE.
* Change the current value by delta.
* It returns TRUE is the value was changed successfuly, or FALSE
* if the value was not changed, as it would go out of bounds.
*/
static BOOL UPDOWN_OffsetVal(UPDOWN_INFO *infoPtr, int delta)
{
/* check if we can do the modification first */
if(!UPDOWN_InBounds (infoPtr, infoPtr->CurVal+delta)){
if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & UDS_WRAP)
{
if(!UPDOWN_InBounds (infoPtr, infoPtr->CurVal+delta)) {
if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & UDS_WRAP) {
delta += (delta < 0 ? -1 : 1) *
(infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1) *
(infoPtr->MinVal - infoPtr->MaxVal) +
(delta < 0 ? 1 : -1);
}
else
return FALSE;
} else return FALSE;
}
infoPtr->CurVal += delta;
......@@ -136,7 +140,7 @@ static BOOL UPDOWN_OffsetVal(UPDOWN_INFO *infoPtr, int delta)
}
/***********************************************************************
* UPDOWN_HasBuddyBorder [Internal]
* UPDOWN_HasBuddyBorder
*
* 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.
......@@ -146,8 +150,7 @@ static BOOL UPDOWN_HasBuddyBorder(UPDOWN_INFO* infoPtr)
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
return ( ((dwStyle & (UDS_ALIGNLEFT | UDS_ALIGNRIGHT)) != 0) &&
(SendMessageW(infoPtr->Self, UDM_GETBUDDY, 0, 0) != 0) &&
(lstrcmpiA(infoPtr->szBuddyClass, "EDIT") == 0 ) );
UPDOWN_IsBuddyEdit(infoPtr) );
}
/***********************************************************************
......@@ -217,12 +220,12 @@ static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt
* UPDOWN_GetThousandSep
* Returns the thousand sep. If an error occurs, it returns ','.
*/
static CHAR UPDOWN_GetThousandSep()
static WCHAR UPDOWN_GetThousandSep()
{
CHAR sep[2];
WCHAR sep[2];
if(GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, sep, 2) != 1)
return ',';
if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, sep, 2) != 1)
sep[0] = ',';
return sep[0];
}
......@@ -237,22 +240,19 @@ static CHAR UPDOWN_GetThousandSep()
*/
static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr)
{
char txt[20], sep, *src, *dst;
WCHAR txt[20], sep, *src, *dst;
int newVal;
if (!IsWindow(infoPtr->Buddy))
return FALSE;
/*if the buddy is a list window, we must set curr index */
if (!lstrcmpA (infoPtr->szBuddyClass, "ListBox")){
newVal = SendMessageA(infoPtr->Buddy, LB_GETCARETINDEX, 0, 0);
if(newVal < 0)
return FALSE;
}
else{
if (UPDOWN_IsBuddyListbox(infoPtr)) {
newVal = SendMessageW(infoPtr->Buddy, LB_GETCARETINDEX, 0, 0);
if(newVal < 0) return FALSE;
} else {
/* we have a regular window, so will get the text */
if (!GetWindowTextA(infoPtr->Buddy, txt, sizeof(txt)))
return FALSE;
if (!GetWindowTextW(infoPtr->Buddy, txt, COUNT_OF(txt))) return FALSE;
sep = UPDOWN_GetThousandSep();
......@@ -262,13 +262,11 @@ static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr)
*dst = 0;
/* try to convert the number and validate it */
newVal = strtol(txt, &src, infoPtr->Base);
if(*src || !UPDOWN_InBounds (infoPtr, newVal))
return FALSE;
TRACE("new value(%d) from buddy (old=%d)\n", newVal, infoPtr->CurVal);
newVal = wcstol(txt, &src, infoPtr->Base);
if(*src || !UPDOWN_InBounds (infoPtr, newVal)) return FALSE;
}
TRACE("new value(%d) from buddy (old=%d)\n", newVal, infoPtr->CurVal);
infoPtr->CurVal = newVal;
return TRUE;
}
......@@ -283,53 +281,53 @@ static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr)
*/
static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr)
{
char txt1[20], sep;
WCHAR fmt[3] = { '%', 'd', '\0' };
WCHAR txt[20];
int len;
if (!IsWindow(infoPtr->Buddy))
return FALSE;
if (!IsWindow(infoPtr->Buddy)) return FALSE;
TRACE("set new value(%d) to buddy.\n", infoPtr->CurVal);
/*if the buddy is a list window, we must set curr index */
if(!lstrcmpA (infoPtr->szBuddyClass, "ListBox")){
SendMessageA(infoPtr->Buddy, LB_SETCURSEL, infoPtr->CurVal, 0);
if (UPDOWN_IsBuddyListbox(infoPtr)) {
return SendMessageW(infoPtr->Buddy, LB_SETCURSEL, infoPtr->CurVal, 0) != LB_ERR;
}
else{ /* Regular window, so set caption to the number */
len = sprintf(txt1, (infoPtr->Base==16) ? "%X" : "%d", infoPtr->CurVal);
sep = UPDOWN_GetThousandSep();
/* Regular window, so set caption to the number */
if (infoPtr->Base == 16) fmt[1] = 'X';
len = swprintf(txt, fmt, infoPtr->CurVal);
/* Do thousands seperation if necessary */
if (!(GetWindowLongA (infoPtr->Self, GWL_STYLE) & UDS_NOTHOUSANDS) && (len > 3)) {
char txt2[20], *src = txt1, *dst = txt2;
if(len % 3 > 0) {
lstrcpynA (dst, src, len%3 + 1); /* need to include the null */
dst += len%3;
src += len%3;
}
for(len=0; *src; len++) {
if(len%3==0) *dst++ = sep;
if (!(GetWindowLongW (infoPtr->Self, GWL_STYLE) & UDS_NOTHOUSANDS) && (len > 3)) {
WCHAR tmp[COUNT_OF(txt)], *src = tmp, *dst = txt;
WCHAR sep = UPDOWN_GetThousandSep();
int start = len % 3;
memcpy(tmp, txt, sizeof(txt));
if (start == 0) start = 3;
dst += start;
src += start;
for (len=0; *src; len++) {
if (len % 3 == 0) *dst++ = sep;
*dst++ = *src++;
}
*dst = 0; /* null terminate it */
strcpy(txt1, txt2); /* move it to the proper place */
}
SetWindowTextA(infoPtr->Buddy, txt1);
*dst = 0;
}
return TRUE;
return SetWindowTextW(infoPtr->Buddy, txt);
}
/***********************************************************************
* UPDOWN_DrawBuddyBorder [Internal]
* 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 = GetWindowLongA (infoPtr->Self, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
RECT clientRect;
GetClientRect(infoPtr->Self, &clientRect);
......@@ -341,19 +339,17 @@ static void UPDOWN_DrawBuddyBorder (UPDOWN_INFO *infoPtr, HDC hdc)
}
/***********************************************************************
* UPDOWN_Draw [Internal]
* UPDOWN_Draw
*
* Draw the arrows. The background need not be erased.
*/
static void UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
{
DWORD dwStyle = GetWindowLongA (infoPtr->Self, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
BOOL prssed;
RECT rect;
/*
* Draw the common border between ourselves and our buddy.
*/
/* Draw the common border between ourselves and our buddy */
if (UPDOWN_HasBuddyBorder(infoPtr))
UPDOWN_DrawBuddyBorder(infoPtr, hdc);
......@@ -379,16 +375,16 @@ static void UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc)
}
/***********************************************************************
* UPDOWN_Refresh [Internal]
* UPDOWN_Refresh
*
* Synchronous drawing (must NOT be used in WM_PAINT).
* Calls UPDOWN_Draw.
*/
static void UPDOWN_Refresh (UPDOWN_INFO *infoPtr)
{
HDC hdc = GetDC (infoPtr->Self);
UPDOWN_Draw (infoPtr, hdc);
ReleaseDC (infoPtr->Self, hdc);
HDC hdc = GetDC(infoPtr->Self);
UPDOWN_Draw(infoPtr, hdc);
ReleaseDC(infoPtr->Self, hdc);
}
......@@ -423,17 +419,19 @@ static void UPDOWN_Paint (UPDOWN_INFO *infoPtr, HDC hdc)
*/
static BOOL UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
{
DWORD dwStyle = GetWindowLongA (infoPtr->Self, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
RECT budRect; /* new coord for the buddy */
int x,width; /* new x position and width for the up-down */
int x, width; /* new x position and width for the up-down */
WNDPROC baseWndProc, currWndProc;
CHAR buddyClass[40];
/* Is it a valid bud? */
if(!IsWindow(bud)) return FALSE;
TRACE("(hwnd=%04x, bud=%04x)\n", infoPtr->Self, bud);
/* there is already a body assigned */
if ( infoPtr->Buddy )
RemovePropA(infoPtr->Buddy, BUDDY_UPDOWN_HWND);
if (infoPtr->Buddy) RemovePropA(infoPtr->Buddy, BUDDY_UPDOWN_HWND);
/* Store buddy window handle */
infoPtr->Buddy = bud;
......@@ -441,43 +439,38 @@ static BOOL UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
/* keep upDown ctrl hwnd in a buddy property */
SetPropA( bud, BUDDY_UPDOWN_HWND, infoPtr->Self);
/* Store buddy window clas name */
memset(infoPtr->szBuddyClass, 0, UPDOWN_BUDDYCLASSNAMELEN);
GetClassNameA (bud, infoPtr->szBuddyClass, UPDOWN_BUDDYCLASSNAMELEN-1);
/* Store buddy window class type */
infoPtr->BuddyType = BUDDY_TYPE_UNKNOWN;
if (GetClassNameA(bud, buddyClass, COUNT_OF(buddyClass))) {
if (lstrcmpiA(buddyClass, "Edit") == 0)
infoPtr->BuddyType = BUDDY_TYPE_EDIT;
else if (lstrcmpiA(buddyClass, "Listbox") == 0)
infoPtr->BuddyType = BUDDY_TYPE_LISTBOX;
}
if(dwStyle & UDS_ARROWKEYS){
/* Note that I don't clear the BUDDY_SUPERCLASS_WNDPROC property
when we reset the upDown ctrl buddy to another buddy because it is not
good to break the window proc chain. */
currWndProc = (WNDPROC) GetWindowLongA(bud, GWL_WNDPROC);
if (currWndProc != UPDOWN_Buddy_SubclassProc)
{
// replace the buddy's WndProc with ours
baseWndProc = (WNDPROC)SetWindowLongA(bud, GWL_WNDPROC,
(LPARAM)UPDOWN_Buddy_SubclassProc);
// and save the base class' WndProc
currWndProc = (WNDPROC) GetWindowLongW(bud, GWL_WNDPROC);
if (currWndProc != UPDOWN_Buddy_SubclassProc) {
baseWndProc = (WNDPROC)SetWindowLongW(bud, GWL_WNDPROC, (LPARAM)UPDOWN_Buddy_SubclassProc);
SetPropA(bud, BUDDY_SUPERCLASS_WNDPROC, (HANDLE)baseWndProc);
}
// else
// its already been subclassed, don't overwrite BUDDY_SUPERCLASS_WNDPROC
}
/* Get the rect of the buddy relative to its parent */
GetWindowRect(infoPtr->Buddy, &budRect);
MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy),
(POINT *)(&budRect.left), 2);
MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy), (POINT *)(&budRect.left), 2);
/* now do the positioning */
if (dwStyle & UDS_ALIGNLEFT) {
x = budRect.left;
budRect.left += DEFAULT_WIDTH+DEFAULT_XSEP;
}
else if (dwStyle & UDS_ALIGNRIGHT){
budRect.right -= DEFAULT_WIDTH+DEFAULT_XSEP;
budRect.left += DEFAULT_WIDTH + DEFAULT_XSEP;
} else if (dwStyle & UDS_ALIGNRIGHT) {
budRect.right -= DEFAULT_WIDTH + DEFAULT_XSEP;
x = budRect.right+DEFAULT_XSEP;
}
else {
} else {
x = budRect.right+DEFAULT_XSEP;
}
......@@ -496,17 +489,16 @@ static BOOL UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
* to look as if it is integrated with the buddy control.
* We nudge the control or change it size to overlap.
*/
if (UPDOWN_HasBuddyBorder(infoPtr))
{
if (UPDOWN_HasBuddyBorder(infoPtr)) {
if(dwStyle & UDS_ALIGNLEFT)
width+=DEFAULT_BUDDYBORDER;
width += DEFAULT_BUDDYBORDER;
else
x-=DEFAULT_BUDDYBORDER;
x -= DEFAULT_BUDDYBORDER;
}
SetWindowPos (infoPtr->Self, infoPtr->Buddy,
x, budRect.top-DEFAULT_ADDTOP,
width, (budRect.bottom-budRect.top)+DEFAULT_ADDTOP+DEFAULT_ADDBOT,
SetWindowPos(infoPtr->Self, infoPtr->Buddy, x,
budRect.top - DEFAULT_ADDTOP, width,
budRect.bottom - budRect.top + DEFAULT_ADDTOP + DEFAULT_ADDBOT,
SWP_NOACTIVATE);
return TRUE;
......@@ -523,7 +515,7 @@ static BOOL UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
*/
static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, BOOL incr)
{
DWORD dwStyle = GetWindowLongA (infoPtr->Self, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
NM_UPDOWN ni;
TRACE("%s by %d\n", incr ? "inc" : "dec", delta);
......@@ -535,25 +527,21 @@ static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, BOOL incr)
ni.iPos = infoPtr->CurVal;
ni.iDelta = delta;
ni.hdr.hwndFrom = infoPtr->Self;
ni.hdr.idFrom = GetWindowLongA (infoPtr->Self, GWL_ID);
ni.hdr.idFrom = GetWindowLongW (infoPtr->Self, GWL_ID);
ni.hdr.code = UDN_DELTAPOS;
if (!SendMessageA(GetParent (infoPtr->Self), WM_NOTIFY,
(WPARAM)ni.hdr.idFrom, (LPARAM)&ni))
{
if (!SendMessageW(GetParent (infoPtr->Self), WM_NOTIFY,
(WPARAM)ni.hdr.idFrom, (LPARAM)&ni)) {
/* Parent said: OK to adjust */
/* Now adjust value with (maybe new) delta */
if (UPDOWN_OffsetVal (infoPtr, ni.iDelta))
{
if (UPDOWN_OffsetVal (infoPtr, ni.iDelta)) {
/* Now take care about our buddy */
if(infoPtr->Buddy && IsWindow(infoPtr->Buddy)
&& (dwStyle & UDS_SETBUDDYINT) )
UPDOWN_SetBuddyInt (infoPtr);
if (dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr);
}
}
/* Also, notify it. This message is sent in any case. */
SendMessageA (GetParent (infoPtr->Self),
SendMessageW( GetParent(infoPtr->Self),
dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL,
MAKELONG(SB_THUMBPOSITION, infoPtr->CurVal), infoPtr->Self);
}
......@@ -566,7 +554,7 @@ static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, BOOL incr)
*/
static BOOL UPDOWN_IsEnabled (UPDOWN_INFO *infoPtr)
{
if(GetWindowLongA (infoPtr->Self, GWL_STYLE) & WS_DISABLED)
if(GetWindowLongW (infoPtr->Self, GWL_STYLE) & WS_DISABLED)
return FALSE;
if(infoPtr->Buddy)
return IsWindowEnabled(infoPtr->Buddy);
......@@ -584,14 +572,12 @@ static BOOL UPDOWN_IsEnabled (UPDOWN_INFO *infoPtr)
static BOOL UPDOWN_CancelMode (UPDOWN_INFO *infoPtr)
{
/* if not in 'capture' mode, do nothing */
if(!(infoPtr->Flags & FLAG_CLICKED))
return FALSE;
if(!(infoPtr->Flags & FLAG_CLICKED)) return FALSE;
KillTimer (infoPtr->Self, TIMERID1); /* kill all possible timers */
KillTimer (infoPtr->Self, TIMERID2);
if (GetCapture() == infoPtr->Self) /* let the mouse go */
ReleaseCapture(); /* if we still have it */
if (GetCapture() == infoPtr->Self) ReleaseCapture();
infoPtr->Flags = 0; /* get rid of any flags */
UPDOWN_Refresh (infoPtr); /* redraw the control just in case */
......@@ -608,7 +594,7 @@ static BOOL UPDOWN_CancelMode (UPDOWN_INFO *infoPtr)
*/
static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, POINT pt)
{
DWORD dwStyle = GetWindowLongA (infoPtr->Self, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE);
RECT rect;
int temp;
......@@ -616,24 +602,19 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, POINT pt)
{
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(infoPtr->Flags & FLAG_CLICKED) return;
/* If the buddy is an edit, will set focus to it */
if (!lstrcmpA (infoPtr->szBuddyClass, "Edit"))
SetFocus(infoPtr->Buddy);
if (UPDOWN_IsBuddyEdit(infoPtr)) SetFocus(infoPtr->Buddy);
/* Now see which one is the 'active' arrow */
temp = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt);
/* Update the CurVal if necessary */
if (dwStyle & UDS_SETBUDDYINT)
UPDOWN_GetBuddyInt (infoPtr);
if (dwStyle & UDS_SETBUDDYINT) UPDOWN_GetBuddyInt (infoPtr);
/* Set up the correct flags */
infoPtr->Flags = 0;
infoPtr->Flags |= temp ? FLAG_INCR : FLAG_DECR;
infoPtr->Flags |= FLAG_MOUSEIN;
infoPtr->Flags = FLAG_MOUSEIN | (temp ? FLAG_INCR : FLAG_DECR);
/* repaint the control */
UPDOWN_Refresh (infoPtr);
......@@ -650,8 +631,7 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, POINT pt)
case WM_MOUSEMOVE:
/* If we are not in the 'clicked' mode, then nothing to do */
if(!(infoPtr->Flags & FLAG_CLICKED))
return;
if(!(infoPtr->Flags & FLAG_CLICKED)) return;
/* save the flags to see if any got modified */
temp = infoPtr->Flags;
......@@ -663,20 +643,20 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, POINT pt)
UPDOWN_GetArrowRect (infoPtr, &rect, FALSE);
/* Update the flags if we are in/out */
if(PtInRect(&rect, pt))
if(PtInRect(&rect, pt)) {
infoPtr->Flags |= FLAG_MOUSEIN;
else{
} else {
infoPtr->Flags &= ~FLAG_MOUSEIN;
if(infoPtr->AccelIndex != -1) /* if we have accel info */
infoPtr->AccelIndex = 0; /* reset it */
/* 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) UPDOWN_Refresh (infoPtr);
break;
default:
ERR("Impossible case!\n");
ERR("Impossible case (msg=%x)!\n", msg);
}
}
......@@ -688,20 +668,22 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd);
DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
int temp;
if (!infoPtr && (message != WM_CREATE) && (message != WM_NCCREATE))
return DefWindowProcA (hwnd, message, wParam, lParam);
return DefWindowProcW (hwnd, message, wParam, lParam);
switch(message)
{
case WM_NCCREATE:
/* get rid of border, if any */
SetWindowLongA (hwnd, GWL_STYLE, dwStyle & ~WS_BORDER);
SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~WS_BORDER);
return TRUE;
case WM_CREATE:
infoPtr = (UPDOWN_INFO*)COMCTL32_Alloc (sizeof(UPDOWN_INFO));
SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
SetWindowLongW (hwnd, 0, (DWORD)infoPtr);
/* initialize the info struct */
infoPtr->Self = hwnd;
......@@ -723,34 +705,30 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case WM_DESTROY:
if(infoPtr->AccelVect)
COMCTL32_Free (infoPtr->AccelVect);
if(infoPtr->AccelVect) COMCTL32_Free (infoPtr->AccelVect);
if ( IsWindow(infoPtr->Buddy) ) /* Cleanup */
RemovePropA(infoPtr->Buddy, BUDDY_UPDOWN_HWND);
if(infoPtr->Buddy) RemovePropA(infoPtr->Buddy, BUDDY_UPDOWN_HWND);
COMCTL32_Free (infoPtr);
SetWindowLongA (hwnd, 0, 0);
SetWindowLongW (hwnd, 0, 0);
TRACE("UpDown Ctrl destruction, hwnd=%04x\n", hwnd);
break;
case WM_ENABLE:
if (dwStyle & WS_DISABLED)
UPDOWN_CancelMode (infoPtr);
if (dwStyle & WS_DISABLED) UPDOWN_CancelMode (infoPtr);
UPDOWN_Refresh (infoPtr);
break;
case WM_TIMER:
/* if initial timer, kill it and start the repeat timer */
if(wParam == TIMERID1){
if(wParam == TIMERID1) {
KillTimer(hwnd, TIMERID1);
/* if no accel info given, used default timer */
if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0){
if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) {
infoPtr->AccelIndex = -1;
temp = REPEAT_DELAY;
}
else{
} else {
infoPtr->AccelIndex = 0; /* otherwise, use it */
temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
}
......@@ -758,11 +736,11 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
}
/* now, if the mouse is above us, do the thing...*/
if(infoPtr->Flags & FLAG_MOUSEIN){
if(infoPtr->Flags & FLAG_MOUSEIN) {
temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc;
UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_INCR);
if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1){
if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1) {
KillTimer(hwnd, TIMERID2);
infoPtr->AccelIndex++; /* move to the next accel info */
temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1;
......@@ -773,20 +751,19 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case WM_CANCELMODE:
UPDOWN_CancelMode (infoPtr);
break;
return UPDOWN_CancelMode (infoPtr);
case WM_LBUTTONUP:
if(!UPDOWN_CancelMode(infoPtr))
break;
if(!UPDOWN_CancelMode(infoPtr)) break;
SendMessageA(GetParent(hwnd), dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL,
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 (!lstrcmpA (infoPtr->szBuddyClass, "Edit"))
SendMessageA(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1));
if (UPDOWN_IsBuddyEdit(infoPtr))
SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1));
break;
case WM_LBUTTONDOWN:
......@@ -800,7 +777,7 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case WM_KEYDOWN:
if((dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr)){
if((dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr)) {
switch(wParam){
case VK_UP:
case VK_DOWN:
......@@ -817,91 +794,78 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case UDM_GETACCEL:
if (wParam==0 && lParam==0) /*if both zero, */
return infoPtr->AccelCount; /*just return the accel count*/
if (wParam || lParam){
UNKNOWN_PARAM(UDM_GETACCEL, wParam, lParam);
return 0;
}
if (wParam==0 && lParam==0) return infoPtr->AccelCount;
if (wParam && lParam) {
temp = min(infoPtr->AccelCount, wParam);
memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL));
return temp;
}
UNKNOWN_PARAM(UDM_GETACCEL, wParam, lParam);
return 0;
case UDM_SETACCEL:
TRACE("UpDown Ctrl new accel info, hwnd=%04x\n", hwnd);
if(infoPtr->AccelVect){
if(infoPtr->AccelVect) {
COMCTL32_Free (infoPtr->AccelVect);
infoPtr->AccelCount = 0;
infoPtr->AccelVect = 0;
}
if(wParam==0)
return TRUE;
if(wParam==0) return TRUE;
infoPtr->AccelVect = COMCTL32_Alloc (wParam*sizeof(UDACCEL));
if(infoPtr->AccelVect==0)
return FALSE;
if(infoPtr->AccelVect == 0) return FALSE;
memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL));
return TRUE;
case UDM_GETBASE:
if (wParam || lParam)
UNKNOWN_PARAM(UDM_GETBASE, wParam, lParam);
if (wParam || lParam) UNKNOWN_PARAM(UDM_GETBASE, wParam, lParam);
return infoPtr->Base;
case UDM_SETBASE:
TRACE("UpDown Ctrl new base(%d), hwnd=%04x\n", wParam, hwnd);
if ( !(wParam==10 || wParam==16) || lParam)
UNKNOWN_PARAM(UDM_SETBASE, wParam, lParam);
if (wParam==10 || wParam==16){
if (wParam==10 || wParam==16) {
temp = infoPtr->Base;
infoPtr->Base = wParam;
return temp; /* return the prev base */
return temp;
}
break;
case UDM_GETBUDDY:
if (wParam || lParam)
UNKNOWN_PARAM(UDM_GETBUDDY, wParam, lParam);
if (wParam || lParam) UNKNOWN_PARAM(UDM_GETBUDDY, wParam, lParam);
return infoPtr->Buddy;
case UDM_SETBUDDY:
if (lParam)
UNKNOWN_PARAM(UDM_SETBUDDY, wParam, lParam);
if (lParam) UNKNOWN_PARAM(UDM_SETBUDDY, wParam, lParam);
temp = infoPtr->Buddy;
UPDOWN_SetBuddy (infoPtr, wParam);
TRACE("UpDown Ctrl new buddy(%04x), hwnd=%04x\n", infoPtr->Buddy, hwnd);
return temp;
case UDM_GETPOS:
if (wParam || lParam)
UNKNOWN_PARAM(UDM_GETPOS, wParam, lParam);
if (wParam || lParam) UNKNOWN_PARAM(UDM_GETPOS, wParam, lParam);
temp = UPDOWN_GetBuddyInt (infoPtr);
return MAKELONG(infoPtr->CurVal, temp ? 0 : 1);
case UDM_SETPOS:
if (wParam || HIWORD(lParam))
UNKNOWN_PARAM(UDM_GETPOS, wParam, lParam);
if (wParam || HIWORD(lParam)) UNKNOWN_PARAM(UDM_GETPOS, wParam, lParam);
temp = SLOWORD(lParam);
TRACE("UpDown Ctrl new value(%d), hwnd=%04x\n", temp, hwnd);
if(!UPDOWN_InBounds(infoPtr, temp)){
if(temp < infoPtr->MinVal)
temp = infoPtr->MinVal;
if(temp > infoPtr->MaxVal)
temp = infoPtr->MaxVal;
if(!UPDOWN_InBounds(infoPtr, temp)) {
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 */
if(dwStyle & UDS_SETBUDDYINT)
UPDOWN_SetBuddyInt (infoPtr);
if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr);
return wParam; /* return prev value */
case UDM_GETRANGE:
if (wParam || lParam)
UNKNOWN_PARAM(UDM_GETRANGE, wParam, lParam);
if (wParam || lParam) UNKNOWN_PARAM(UDM_GETRANGE, wParam, lParam);
return MAKELONG(infoPtr->MaxVal, infoPtr->MinVal);
case UDM_SETRANGE:
if (wParam)
UNKNOWN_PARAM(UDM_SETRANGE, wParam, lParam); /* we must have: */
if (wParam) UNKNOWN_PARAM(UDM_SETRANGE, wParam, lParam);
/* we must have: */
infoPtr->MaxVal = SLOWORD(lParam); /* UD_MINVAL <= Max <= UD_MAXVAL */
infoPtr->MinVal = SHIWORD(lParam); /* UD_MINVAL <= Min <= UD_MAXVAL */
/* |Max-Min| <= UD_MAXVAL */
......@@ -910,10 +874,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case UDM_GETRANGE32:
if (wParam)
*(LPINT)wParam = infoPtr->MinVal;
if (lParam)
*(LPINT)lParam = infoPtr->MaxVal;
if (wParam) *(LPINT)wParam = infoPtr->MinVal;
if (lParam) *(LPINT)lParam = infoPtr->MaxVal;
break;
case UDM_SETRANGE32:
......@@ -926,27 +888,23 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
break;
case UDM_GETPOS32:
if ((LPBOOL)lParam != NULL)
*((LPBOOL)lParam) = TRUE;
if ((LPBOOL)lParam != NULL) *((LPBOOL)lParam) = TRUE;
return infoPtr->CurVal;
case UDM_SETPOS32:
if(!UPDOWN_InBounds(infoPtr, (int)lParam)){
if((int)lParam < infoPtr->MinVal)
lParam = infoPtr->MinVal;
if((int)lParam > infoPtr->MaxVal)
lParam = infoPtr->MaxVal;
if(!UPDOWN_InBounds(infoPtr, (int)lParam)) {
if((int)lParam < infoPtr->MinVal) lParam = infoPtr->MinVal;
if((int)lParam > infoPtr->MaxVal) lParam = infoPtr->MaxVal;
}
temp = infoPtr->CurVal; /* save prev value */
infoPtr->CurVal = (int)lParam; /* set the new value */
if(dwStyle & UDS_SETBUDDYINT)
UPDOWN_SetBuddyInt (infoPtr);
if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr);
return temp; /* return prev value */
default:
if (message >= WM_USER)
ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam);
return DefWindowProcA (hwnd, message, wParam, lParam);
return DefWindowProcW (hwnd, message, wParam, lParam);
}
return 0;
......@@ -956,44 +914,31 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam,
* 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)
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)
{
switch (uMsg) {
case WM_KEYDOWN:
{
if ( ((int)wParam == VK_UP ) || ((int)wParam == VK_DOWN ) )
{
if ( ((int)wParam == VK_UP ) || ((int)wParam == VK_DOWN ) ) {
HWND upDownHwnd = GetPropA(hwnd, BUDDY_UPDOWN_HWND);
UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr(upDownHwnd);
if (!lstrcmpA (infoPtr->szBuddyClass, "ListBox"))
{
/* if the buddy is a list window, we must update curr index */
INT oldVal = SendMessageA(hwnd, LB_GETCURSEL, 0, 0);
SendMessageA(hwnd, LB_SETCURSEL, oldVal+1, 0);
}
else
{
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;
}
break;
/* else Fall Through */
}
}
return CallWindowProcA( superClassWndProc, hwnd, uMsg, wParam, lParam);
return CallWindowProcW( superClassWndProc, hwnd, uMsg, wParam, lParam);
}
/***********************************************************************
......@@ -1005,18 +950,18 @@ UPDOWN_Buddy_SubclassProc (
VOID
UPDOWN_Register(void)
{
WNDCLASSA wndClass;
WNDCLASSW wndClass;
ZeroMemory( &wndClass, sizeof( WNDCLASSA ) );
ZeroMemory( &wndClass, sizeof( WNDCLASSW ) );
wndClass.style = CS_GLOBALCLASS | CS_VREDRAW;
wndClass.lpfnWndProc = (WNDPROC)UpDownWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(UPDOWN_INFO*);
wndClass.hCursor = LoadCursorA( 0, IDC_ARROWA );
wndClass.hCursor = LoadCursorW( 0, IDC_ARROWW );
wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wndClass.lpszClassName = UPDOWN_CLASSA;
wndClass.lpszClassName = UPDOWN_CLASSW;
RegisterClassA( &wndClass );
RegisterClassW( &wndClass );
}
......@@ -1029,6 +974,6 @@ UPDOWN_Register(void)
VOID
UPDOWN_Unregister (void)
{
UnregisterClassA (UPDOWN_CLASSA, (HINSTANCE)NULL);
UnregisterClassW (UPDOWN_CLASSW, (HINSTANCE)NULL);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment