Release 970914

Thu Sep 11 18:24:56 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [objects/dc.c]
	In DC_SetupGCForPatBlt, replace R2_NOT by GXxor with (black xor white).

Tue Sep  9 23:04:02 1997  U. Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>

	* [memory/virtual.c] 
	Do not write debugging info unconditionally to stderr.

	* [files/profile.c]
	Call PROFILE_GetSection in PROFILE_GetString for key_name "" too.

	* [misc/crtdll.c]
	Many new functions.

	* [include/windows.h] [windows/winpos.c]
	ClientToScreen16 doesn't have a return value.

Sun Sep  7 10:06:39 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [misc/main.c] [AUTHORS]
	Update the list of contributors. Please let me know if I forgot
	someone.

	* [if1632/*.spec] [if1632/builtin.c] [tools/build.c]
	Ordinal base for Win32 DLLs is now computed automatically from the
	lowest ordinal found.

	* [include/wintypes.h]
	WINAPI is now defined as attribute((stdcall)). This will require
	gcc to compile.

	* [if1632/thunk.c]
	Removed Win32 thunks (no longer needed with stdcall).

	* [if1632/crtdll.spec] [misc/crtdll.c]
	Make sure we only reference cdecl functions in the spec file.

	* [objects/dc.c]
	Use CapNotLast drawing style for 1-pixel wide lines.

	* [tools/build.c]
	Added 'double' argument type.
	Added 'varargs' function type for Win32.
	Made CallTo16_xxx functions stdcall.

Fri Sep  5 14:50:49 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [tools/build.c] [windows/win.c] [windows/event.c] [windows/message.c]
	More fixes to get message exchange closer to the original.

	* [misc/spy.c]
	Message logs now contain window names.

	* [loader/resource.c] [loader/ne_resource.c] [loader/task.c]
	  [objects/cursoricon.c] [windows/user.c]
	Added some obscure features to fix memory leaks.

Fri Sep  5 00:46:28 1997  Jan Willamowius <jan@janhh.shnet.org>

	* [if1632/kernel32.spec] [win32/newfns.c]
	Added stub for UTRegister() and UTUnRegister().

Thu Sep  4 12:03:12 1997  Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
	* [controls/edit.c]
	Allow ASCII codes > 127 in WM_CHAR.

Mon Sep  1 17:23:24 1997  Dimitrie O. Paun  <dimi@mail.cs.toronto.edu>

	* [controls/widgets.c]
	In InitCommonControls, remember the name of the class
	because lpszClassName was made to point to a local array
	Added the ProgressBar to the list of implemented controls.
	Call InitCommonControls from WIDGETS_Init to register all
	implemented Common Controls.
	
	* [include/commctrl.h]
	Added misc decl for the Progress Bar.

	* [controls/progress.c] [include/progress.h]
	First attempt at implementiong the Progress Bar class.

	* [objects/brush.h]
	Implementation for GetSysColorBrush[16|32]

	* [controls/status.c]
	Use DrawEdge to draw the borders and fill the background

	* [controls/uitools.c]
	Added DrawDiagEdge32 and DrawRectEdge32

	* [graphics/painting.c]
	Implement DrawEdge[16|32]
	Started DrawFrameControl32

Mon Sep  1 10:07:09 1997  Lawson Whitney <lawson_whitney@juno.com>

	* [misc/comm.c] [include/windows.h]
	SetCommEventMask returns a SEGPTR.

Sun Aug 31 23:28:32 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/pe_image.c][loader/module.c][include/pe_image.h]
	  [include/module.h]
	Cleaned up the whole Win32 library mess (a bit).

	* [debugger/stabs.c]
	If 'wine' has no absolute path and isn't found, check $PATH too.

	* [misc/ole2nls.c]
	Some fixes.

	* [misc/ver.c]
	Added support for PE style version resources.

	* [memory/string.c]
	Check for NULL pointers to _lstr* functions, just as Windows95 does.

	* [multimedia/time.c]
	Made list of timers a simple linked list.

	* [loader/resource.c]
	Netscape 3 seems to pass NEGATIVE resource Ids (in an
	unsigned int, yes). Don't know why, fixed it anyway.

	* [objects/bitmap.c]
	LoadImageW added.

	* [include/win.h][windows/win.c]
	Change wIDmenu from UINT16 to UINT32 and changed the
	SetWindow(Long|Word) accordingly.

Thu Aug 28 19:30:08 1997  Morten Welinder  <terra@diku.dk>

	* [include/windows.h]
	Add a few more colors defined for Win95.
	Add a few more brush styles.

	* [windows/syscolor.c]
 	Add error checks for SYSCOLOR_SetColor, SYSCOLOR_Init,
	GetSysColor16, GetSysColor32.  Add support for above colors.

Sun Aug 24 16:22:57 1997  Andrew Taylor <andrew@riscan.com>

	* [multimedia/mmsystem.c]
	Changed mmioDescend to use mmio functions for file I/O, neccessary
	for memory files.
diff --git a/controls/Makefile.in b/controls/Makefile.in
index 9d24345..9be0848 100644
--- a/controls/Makefile.in
+++ b/controls/Makefile.in
@@ -13,9 +13,11 @@
 	icontitle.c \
 	listbox.c \
 	menu.c \
+	progress.c \
 	scroll.c \
 	static.c \
 	status.c \
+	uitools.c \
 	updown.c \
 	widgets.c
 
diff --git a/controls/edit.c b/controls/edit.c
index 28373cd..7e32b57 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -982,11 +982,17 @@
 						segptr + start, index, count, action);
 		LocalUnlock16(hloc16);
 		return ret;
-	} else if (es->word_break_proc32A)
-		return (INT32)CallWordBreakProc32A((FARPROC32)es->word_break_proc32A,
-						es->text + start, index, count, action);
+	}
+        else if (es->word_break_proc32A)
+        {
+            dprintf_relay( stddeb, "CallTo32(wordbrk=%p,str='%s',idx=%d,cnt=%d,act=%d)\n",
+                           es->word_break_proc32A, es->text + start, index,
+                           count, action );
+            return (INT32)es->word_break_proc32A( es->text + start, index,
+                                                  count, action );
+        }
 	else
-		return EDIT_WordBreakProc(es->text + start, index, count, action);
+            return EDIT_WordBreakProc(es->text + start, index, count, action);
 }
 
 
@@ -2819,7 +2825,7 @@
 			EDIT_EM_ReplaceSel(wnd, es, TRUE, "\t");
 		break;
 	default:
-		if (!(es->style & ES_READONLY) && (c >= ' ') && (c != 127)) {
+		if (!(es->style & ES_READONLY) && ((BYTE)c >= ' ') && (c != 127)) {
 			char str[2];
  			str[0] = c;
  			str[1] = '\0';
diff --git a/controls/listbox.c b/controls/listbox.c
index 5466abe..1308e81 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -2462,7 +2462,7 @@
 
     default:
         if ((msg >= WM_USER) && (msg < 0xc000))
-            fprintf(stderr,"Listbox %04x: unknown msg %04x wp %08x lp %08lx\n",
+            dprintf_listbox(stddeb,"Listbox %04x: unknown msg %04x wp %08x lp %08lx\n",
                     hwnd, msg, wParam, lParam );
         return DefWindowProc32A( hwnd, msg, wParam, lParam );
     }
diff --git a/controls/menu.c b/controls/menu.c
index 5a1e28c..9e08d31 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1141,48 +1141,44 @@
 /***********************************************************************
  *	     MENU_PatchResidentPopup
  */
-BOOL32 MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* wndOwner )
+BOOL32 MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* checkWnd )
 {
-   /* checkQueue tells us whether we have to disconnect top
-    * popup from the wndOwner or (if the latter is NULL) from 
-    * the checkQueue. If checkQueue is 0 then we need to set 
-    * popup owner to the wndOwner.
-    *
-    * This is supposed to be called when top popup is hidden. */
-
     if( pTopPopupWnd )
     {
 	HTASK16 hTask = 0;
 
-	dprintf_menu(stddeb,"patching resident popup: %04x, %08x\n", 
-				   checkQueue, (unsigned) wndOwner);
-	if( wndOwner )
-	{
-	    if( pTopPopupWnd->owner == wndOwner )
-	    {
-		if( checkQueue ) pTopPopupWnd->owner = NULL;
-		return TRUE;
-	    }
-	
-	    /* switch to the new owner */
+	dprintf_menu(stddeb,"patching resident popup: %04x %04x [%04x %04x]\n", 
+		checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTopPopupWnd->hmemTaskQ, 
+		pTopPopupWnd->owner ? pTopPopupWnd->owner->hwndSelf : 0);
 
-	    if( wndOwner->hmemTaskQ == pTopPopupWnd->hmemTaskQ ) 
-		return TRUE;
-	    hTask = QUEUE_GetQueueTask( wndOwner->hmemTaskQ );
-	} 
-	else if( pTopPopupWnd->hmemTaskQ == checkQueue )
+	switch( checkQueue )
 	{
-	    /* switch to the different task */
+	    case 0: /* checkWnd is the new popup owner */
+		 if( checkWnd )
+		 {
+		     pTopPopupWnd->owner = checkWnd;
+		     if( pTopPopupWnd->hmemTaskQ != checkWnd->hmemTaskQ )
+			 hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
+		 }
+		 break;
 
-	    hTask = QUEUE_GetQueueTask( pTopPopupWnd->hmemTaskQ );
-	    hTask = TASK_GetNextTask( hTask );  
+	    case 0xFFFF: /* checkWnd is destroyed */
+		 if( pTopPopupWnd->owner == checkWnd )
+		     pTopPopupWnd->owner = NULL;
+		 return TRUE; 
+
+	    default: /* checkQueue is exiting */
+		 if( pTopPopupWnd->hmemTaskQ == checkQueue )
+		 {
+		     hTask = QUEUE_GetQueueTask( pTopPopupWnd->hmemTaskQ );
+		     hTask = TASK_GetNextTask( hTask );
+		 }
+		 break;
 	}
 
 	if( hTask )
 	{
 	    TDB* task = (TDB*)GlobalLock16( hTask );
-
-	    pTopPopupWnd->owner = wndOwner;
 	    if( task )
 	    {
 		pTopPopupWnd->hInstance = task->hInstance;
@@ -3537,7 +3533,7 @@
     if (!name) return 0;
     
     /* check for Win32 module */
-    instance = GetExePtr( instance );
+    instance = MODULE_HANDLEtoHMODULE16( instance );
     if (MODULE_GetPtr(instance)->flags & NE_FFLAGS_WIN32)
         return LoadMenu32A(instance,PTR_SEG_TO_LIN(name));
 
@@ -3837,7 +3833,7 @@
 
     miia.cbSize        = sizeof(miia);
     miia.fMask         = mii->fMask;
-    miia.dwTypeData    = miia.dwTypeData;
+    miia.dwTypeData    = mii->dwTypeData;
     miia.fType         = mii->fType;
     miia.fState        = mii->fState;
     miia.wID           = mii->wID;
diff --git a/controls/progress.c b/controls/progress.c
new file mode 100644
index 0000000..c0311e2
--- /dev/null
+++ b/controls/progress.c
@@ -0,0 +1,208 @@
+/*		
+ * Progress control
+ *
+ * Copyright 1997 Dimitrie O. Paun
+ *
+ * TODO:
+ *   - I do not know what to to on WM_[SG]ET_FONT
+ * Problems:
+ *   - I think I do not compute correctly the numer of leds to be drawn
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "windows.h"
+#include "syscolor.h"
+#include "sysmetrics.h"
+#include "progress.h"
+#include "graphics.h"
+#include "heap.h"
+#include "win.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/* Control configuration constants */
+
+#define LED_WIDTH  8
+#define LED_GAP    2
+
+/* Work constants */
+
+#define UNKNOWN_PARAM(msg, wParam, lParam) dprintf_progress(stddeb, \
+        "Progress Ctrl: Unknown parameter(s) for message " #msg     \
+	"(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam); 
+
+#define PROGRESS_GetInfoPtr(wndPtr) ((PROGRESS_INFO *)wndPtr->wExtra)
+
+
+/***********************************************************************
+ *           PROGRESS_Paint
+ * Draw the arrows. The background need not be erased.
+ * If dc!=0, it draws on it
+ */
+static void PROGRESS_Paint(WND *wndPtr, HDC32 dc)
+{
+  PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr);
+  HBRUSH32 ledBrush;
+  int rightBar, rightMost;
+  PAINTSTRUCT32 ps;
+  RECT32 rect;
+  HDC32 hdc;
+
+  dprintf_progress(stddeb, "Progress Bar: paint pos=%d min=%d, max=%d\n",
+		   infoPtr->CurVal, infoPtr->MinVal, infoPtr->MaxVal);
+
+  /* get a dc */
+  hdc = dc==0 ? BeginPaint32(wndPtr->hwndSelf, &ps) : dc;
+
+  /* get the required brush */
+  ledBrush = GetSysColorBrush32(COLOR_HIGHLIGHT);
+
+  /* get rect for the bar, adjusted for the border */
+  GetClientRect32(wndPtr->hwndSelf, &rect);
+
+  /* draw the border */
+  DrawEdge32(hdc, &rect, BDR_SUNKENOUTER, BF_RECT|BF_ADJUST|BF_MIDDLE);
+  rect.left++; rect.right--; rect.top++; rect.bottom--;
+  rightMost = rect.right;
+
+  /* compute extent of progress bar */
+  rightBar = rect.left + 
+    MulDiv32(infoPtr->CurVal-infoPtr->MinVal,
+	     rect.right - rect.left,
+	     infoPtr->MaxVal-infoPtr->MinVal);
+
+  /* now draw the bar */
+  while(rect.left < rightBar) { 
+    rect.right = rect.left+LED_WIDTH;
+    FillRect32(hdc, &rect, ledBrush);
+    rect.left  = rect.right+LED_GAP;
+  }
+
+  /* clean-up */  
+  if(!dc)
+    EndPaint32(wndPtr->hwndSelf, &ps);
+}
+
+/***********************************************************************
+ *           PROGRESS_CoercePos
+ * Makes sure the current position (CUrVal) is within bounds.
+ */
+static void PROGRESS_CoercePos(WND *wndPtr)
+{
+  PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
+
+  if(infoPtr->CurVal < infoPtr->MinVal)
+    infoPtr->CurVal = infoPtr->MinVal;
+  if(infoPtr->CurVal > infoPtr->MaxVal)
+    infoPtr->CurVal = infoPtr->MaxVal;
+}
+
+/***********************************************************************
+ *           ProgressWindowProc
+ */
+LRESULT WINAPI ProgressWindowProc(HWND32 hwnd, UINT32 message, 
+                                  WPARAM32 wParam, LPARAM lParam)
+{
+  WND *wndPtr = WIN_FindWndPtr(hwnd);
+  PROGRESS_INFO *infoPtr = PROGRESS_GetInfoPtr(wndPtr); 
+  UINT32 temp;
+
+  switch(message)
+    {
+    case WM_CREATE:
+      /* initialize the info struct */
+      infoPtr->MinVal=0; 
+      infoPtr->MaxVal=100;
+      infoPtr->CurVal=0; 
+      infoPtr->Step=10;
+      dprintf_updown(stddeb, "Progress Ctrl creation, hwnd=%04x\n", hwnd);
+      break;
+    
+    case WM_DESTROY:
+      dprintf_updown(stddeb, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
+      break;
+
+    case WM_ERASEBKGND:
+      /* pretend to erase it here, but we will do it in the paint
+	 function to avoid flicker */
+      return 1;
+	
+    case WM_GETFONT:
+      /* FIXME: What do we need to do? */
+      break;
+
+    case WM_SETFONT:
+      /* FIXME: What do we need to do? */
+      break;
+
+    case WM_PAINT:
+      PROGRESS_Paint(wndPtr, wParam);
+      break;
+    
+    case PBM_DELTAPOS:
+      if(lParam)
+	UNKNOWN_PARAM(PBM_DELTAPOS, wParam, lParam);
+      temp = infoPtr->CurVal;
+      if(wParam != 0){
+	infoPtr->CurVal += (UINT16)wParam;
+	PROGRESS_CoercePos(wndPtr);
+	PROGRESS_Paint(wndPtr, 0);
+      }
+      return temp;
+
+    case PBM_SETPOS:
+      if (lParam)
+	UNKNOWN_PARAM(PBM_SETPOS, wParam, lParam);
+      temp = infoPtr->CurVal;
+      if(temp != wParam){
+	infoPtr->CurVal = (UINT16)wParam;
+	PROGRESS_CoercePos(wndPtr);
+	PROGRESS_Paint(wndPtr, 0);
+      }
+      return temp;          
+      
+    case PBM_SETRANGE:
+      if (wParam)
+	UNKNOWN_PARAM(PBM_SETRANGE, wParam, lParam);
+      temp = MAKELONG(infoPtr->MinVal, infoPtr->MaxVal);
+      if(temp != lParam){
+	infoPtr->MinVal = LOWORD(lParam); 
+	infoPtr->MaxVal = HIWORD(lParam);
+	if(infoPtr->MaxVal <= infoPtr->MinVal)
+	  infoPtr->MaxVal = infoPtr->MinVal+1;
+	PROGRESS_CoercePos(wndPtr);
+	PROGRESS_Paint(wndPtr, 0);
+      }
+      return temp;
+
+    case PBM_SETSTEP:
+      if (lParam)
+	UNKNOWN_PARAM(PBM_SETSTEP, wParam, lParam);
+      temp = infoPtr->Step;   
+      infoPtr->Step = (UINT16)wParam;   
+      return temp;
+
+    case PBM_STEPIT:
+      if (wParam || lParam)
+	UNKNOWN_PARAM(PBM_STEPIT, wParam, lParam);
+      temp = infoPtr->CurVal;   
+      infoPtr->CurVal += infoPtr->Step;
+      if(infoPtr->CurVal > infoPtr->MaxVal)
+	infoPtr->CurVal = infoPtr->MinVal;
+      if(temp != infoPtr->CurVal)
+	PROGRESS_Paint(wndPtr, 0);
+      return temp;
+    
+    default: 
+      if (message >= WM_USER) 
+	fprintf( stderr, "Progress Ctrl: unknown msg %04x wp=%04x lp=%08lx\n", 
+		 message, wParam, lParam );
+      return DefWindowProc32A( hwnd, message, wParam, lParam ); 
+    } 
+
+    return 0;
+}
+
+
+
diff --git a/controls/status.c b/controls/status.c
index 0732664..df14c53 100644
--- a/controls/status.c
+++ b/controls/status.c
@@ -41,34 +41,29 @@
 void WINAPI DrawStatusText32A( HDC32 hdc, LPRECT32 lprc, LPCSTR text,
                                UINT32 style )
 {
-    RECT32		r, rt;
+    RECT32 r, rt;
     int	oldbkmode;
+    UINT32 border;
 
     r = *lprc;
 
-    if (style == 0 ||
-	style == SBT_POPOUT) {
-	InflateRect32(&r, -1, -1);
-	SelectObject32(hdc, sysColorObjects.hbrushScrollbar);
-	Rectangle32(hdc, r.left, r.top, r.right, r.bottom);
+    if(style == SBT_OWNERDRAW){
+      /* FIXME for SBT_OWNERDRAW, SBT_RTLREADING */
+    }
+    else{
+      DrawEdge32(hdc, &r, BDR_RAISEDINNER, BF_RECT|BF_ADJUST|BF_FLAT);
 
-	/* draw border */
-	SelectObject32(hdc, sysColorObjects.hpenWindowFrame);
-	if (style == 0)
-	    DrawEdge32(hdc, &r, EDGE_SUNKEN, BF_RECT);
-	else
-	    DrawEdge32(hdc, &r, EDGE_RAISED, BF_RECT);
-    }
-    else if (style == SBT_NOBORDERS) {
-	SelectObject32(hdc, sysColorObjects.hbrushScrollbar);
-	Rectangle32(hdc, r.left, r.top, r.right, r.bottom);
-    }
-    else {	/* fixme for SBT_OWNERDRAW, SBT_RTLREADING */
-	
-    }
+      if(style==SBT_POPOUT)
+	border = BDR_RAISEDOUTER;
+      else if(style==SBT_NOBORDERS)
+	border = 0;
+      else
+	border = BDR_SUNKENOUTER;
 
-    /* now draw text */
-    if ((style != SBT_OWNERDRAW) && text) {
+      DrawEdge32(hdc, &r, border, BF_RECT | BF_ADJUST | BF_MIDDLE);
+
+      /* now draw text */
+      if (text) {
 	SelectObject32(hdc, sysColorObjects.hpenWindowText);
 	oldbkmode = SetBkMode32(hdc, TRANSPARENT);
 	rt = r;
@@ -77,8 +72,10 @@
 		    &rt, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 
 	if (oldbkmode != TRANSPARENT)
-	    SetBkMode32(hdc, oldbkmode);
+	  SetBkMode32(hdc, oldbkmode);
+      }
     }
+
 }
 
 static BOOL32 SW_Refresh( HWND32 hwnd, HDC32 hdc, STATUSWINDOWINFO *self )
diff --git a/controls/uitools.c b/controls/uitools.c
new file mode 100644
index 0000000..b245ebc
--- /dev/null
+++ b/controls/uitools.c
@@ -0,0 +1,390 @@
+/*
+ * User Interface Functions
+ *
+ * Copyright 1997 Dimitrie O. Paun
+ */
+
+#include <stdio.h>
+#include "windows.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           UITOOLS_DrawDiagEdge
+ *
+ * Same as DrawEdge, but with BF_DIAGONAL
+ * I tested it extensively and as far as I can tell it is identical to the
+ * implementaion in Win95.
+ * I do not like that I create and
+ * use the 3 Pens to draw the diagonals. It would be better to draw them
+ * using the brushes returned by GetSysColorBrush func, but I did not have
+ * the patience to implement that yet.
+ */
+static BOOL32 UITOOLS_DrawDiagEdge(HDC32 hdc, RECT32 *rect, UINT32 edge,
+                                   UINT32 flags)
+{
+  HPEN32 facePen, shadowPen, lightPen, blackPen, grayPen, nullPen;
+  HPEN32 iPen, oPen, oldPen;
+  HBRUSH32 oldBrush, faceBrush;
+  int cl, cr, ct, cb;
+  BOOL32 mainDiag;
+  POINT32 tp;
+  RECT32 r;
+
+  /* If both rasied and sunken is specified, they anihilate one another */
+  if( !((flags & BF_MONO) || (flags & BF_FLAT)) ){
+    if( (edge & BDR_RAISEDOUTER) && (edge & BDR_SUNKENOUTER) )
+      return FALSE;
+    if( (edge & BDR_RAISEDINNER) && (edge & BDR_SUNKENINNER) )
+      return FALSE;
+  }
+
+  /* Create/get the tools of the trade... */
+  facePen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNFACE));
+  shadowPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNSHADOW));
+  lightPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_BTNHILIGHT));
+  grayPen = CreatePen32(PS_SOLID, 0, RGB(168, 152, 144));
+  blackPen = GetStockObject32(BLACK_PEN);
+  nullPen = GetStockObject32(NULL_PEN);
+  faceBrush = GetSysColorBrush32(COLOR_BTNFACE);
+  oldPen = SelectObject32(hdc, nullPen);
+  oldBrush = SelectObject32(hdc, faceBrush);
+
+  /* this is my working rectangle */
+  r = *rect;
+
+  if(flags & BF_MONO){
+    oPen = blackPen;
+    iPen = nullPen;
+  }else if(flags & BF_FLAT){
+    oPen = shadowPen;
+    iPen = facePen;
+  }else {
+    if(flags & BF_SOFT){
+      if(flags & BF_BOTTOM){
+	oPen = (edge & BDR_RAISEDOUTER) ? blackPen : lightPen;
+	iPen = (edge & BDR_RAISEDINNER) ? shadowPen : grayPen;
+      }
+      else{
+	oPen = (edge & BDR_RAISEDOUTER) ? lightPen : blackPen;
+	iPen = (edge & BDR_RAISEDINNER) ? grayPen : shadowPen;
+      }
+    }
+    else{
+      if(flags & BF_BOTTOM){
+	oPen = (edge & BDR_RAISEDOUTER) ? blackPen : lightPen;
+	iPen = (edge & BDR_RAISEDINNER) ? shadowPen : grayPen;
+      }
+      else{
+	oPen = (edge & BDR_RAISEDOUTER) ? grayPen : shadowPen;
+	iPen = (edge & BDR_RAISEDINNER) ? lightPen : blackPen;
+      }
+    }
+  }
+
+  if(flags & BF_BOTTOM){
+    if(flags & BF_LEFT){
+      cr = -1; cl =  0;
+      ct =  0; cb = -1;
+      mainDiag = TRUE;
+      tp.x = r.left; tp.y = r.top;
+    }
+    else{ /* RIGHT */
+      cr = -1; cl =  0;
+      ct =  1; cb =  0;
+      tp.x = r.left; tp.y = r.bottom-1;
+      mainDiag = FALSE;
+    }
+  }
+  else{  /* TOP */
+    if(flags & BF_LEFT){
+      cr =  0; cl =  1;
+      ct =  0; cb = -1;
+      mainDiag = FALSE;
+      tp.x = r.right; tp.y = r.top;
+    }
+    else{ /* RIGHT */
+      cr =  0; cl =  1;
+      ct =  1; cb =  0;
+      tp.x = r.right; tp.y = r.bottom-1;
+      mainDiag = TRUE;
+    }
+  }
+
+  /* if it has external edge, draw it */
+  if(edge & BDR_OUTER){
+    SelectObject32(hdc, oPen);
+    MoveToEx32(hdc, r.left, mainDiag ? r.bottom-1 : r.top, 0);
+    LineTo32(hdc, r.right, mainDiag ? r.top-1 : r.bottom);
+    r.left += cl; r.right += cr; r.top += ct; r.bottom += cb;
+  }
+
+  /* if it has internal edge, draw it */
+  if(edge & BDR_INNER){
+    SelectObject32(hdc, iPen);
+    MoveToEx32(hdc, r.left, mainDiag ? r.bottom-1 : r.top, 0);
+    LineTo32(hdc, r.right, mainDiag ? r.top-1 : r.bottom);
+    r.left += cl; r.right += cr; r.top += ct; r.bottom += cb;
+  }
+
+  if((flags & BF_MIDDLE) && !(flags & BF_MONO)){
+    POINT32 p[3];
+    p[0].x = mainDiag ? r.right: r.left;
+    p[0].y = r.top;
+    p[1].x = mainDiag ? r.left : r.right;
+    p[1].y = r.bottom;
+    p[2].x = tp.x;
+    p[2].y = tp.y;
+    SelectObject32(hdc, nullPen);
+    SelectObject32(hdc, faceBrush);
+    Polygon32(hdc, p, 3);
+  }
+
+  if(flags & BF_ADJUST)
+    *rect = r;
+
+  /* Restore the DC */
+  SelectObject32(hdc, oldPen);
+  SelectObject32(hdc, oldBrush);
+
+  /* Clean-up */
+  DeleteObject32(facePen);
+  DeleteObject32(shadowPen);
+  DeleteObject32(lightPen);
+  DeleteObject32(grayPen);
+
+  return TRUE;
+}
+
+
+/***********************************************************************
+ *           UITOOLS_DrawRectEdge
+ *
+ * Same as DrawEdge, but without BF_DIAGONAL
+ * I tested this function and it works very well. You should not change it
+ * unless you find a bug. If you don't like the colors, it it not its 
+ * fault - the system colors are not OK.
+ * Again, I tested this function on Win95 and I compared the output with the
+ * one generated by the native DrawEdge and it is identical on all cases that
+ * I tried, and I tried quite a few.
+ */
+static BOOL32 UITOOLS_DrawRectEdge(HDC32 hdc, RECT32 *rect,
+                                   UINT32 edge, UINT32 flags)
+{
+  HBRUSH32 faceBrush, shadowBrush, lightBrush, blackBrush, grayBrush, nullBrush;
+  HBRUSH32 iNBrush, iSBrush, iEBrush, iWBrush;
+  HBRUSH32 oNBrush, oSBrush, oEBrush, oWBrush;
+  HBRUSH32 oldBrush;
+  RECT32 r;
+
+  /* If both rasied and sunken is specified, they anihilate one another */
+  if( !((flags & BF_MONO) || (flags & BF_FLAT)) ){
+    if( (edge & BDR_RAISEDOUTER) && (edge & BDR_SUNKENOUTER) )
+      return FALSE;
+    if( (edge & BDR_RAISEDINNER) && (edge & BDR_SUNKENINNER) )
+      return FALSE;
+  }
+
+  faceBrush = GetSysColorBrush32(COLOR_BTNFACE);
+  shadowBrush = GetSysColorBrush32(COLOR_BTNSHADOW);
+  lightBrush = GetSysColorBrush32(COLOR_BTNHILIGHT);
+  blackBrush = GetStockObject32(BLACK_BRUSH);
+  grayBrush = GetStockObject32(LTGRAY_BRUSH);
+  nullBrush = GetStockObject32(NULL_BRUSH);
+  oldBrush = SelectObject32(hdc, nullBrush);
+
+  /* this is my working rectangle */
+  r = *rect;
+
+  if(flags & BF_MONO){
+    oNBrush = oSBrush = oEBrush = oWBrush = blackBrush;
+    iNBrush = iSBrush = iEBrush = iWBrush = nullBrush;
+  }else if(flags & BF_FLAT){
+    oNBrush = oSBrush = oEBrush = oWBrush = shadowBrush;
+    iNBrush = iSBrush = iEBrush = iWBrush = faceBrush;
+  }else {
+    if(flags & BF_SOFT){
+      oNBrush = oWBrush = (edge & BDR_RAISEDOUTER) ? lightBrush  : blackBrush;
+      oSBrush = oEBrush = (edge & BDR_RAISEDOUTER) ? blackBrush  : lightBrush;
+      iNBrush = iWBrush = (edge & BDR_RAISEDINNER) ? grayBrush   : shadowBrush;
+      iSBrush = iEBrush = (edge & BDR_RAISEDINNER) ? shadowBrush : grayBrush;
+    }
+    else{
+      oNBrush = oWBrush = (edge & BDR_RAISEDOUTER) ? grayBrush   : shadowBrush;
+      oSBrush = oEBrush = (edge & BDR_RAISEDOUTER) ? blackBrush  : lightBrush;
+      iNBrush = iWBrush = (edge & BDR_RAISEDINNER) ? lightBrush  : blackBrush;
+      iSBrush = iEBrush = (edge & BDR_RAISEDINNER) ? shadowBrush : grayBrush;
+    }
+  }
+
+  /* if it has external edge, draw it */
+  if(edge & BDR_OUTER){
+    if(flags & BF_RIGHT){
+      SelectObject32(hdc, oEBrush);
+      PatBlt32(hdc, r.right-1, r.top, 1, r.bottom - r.top, PATCOPY);
+      r.right--;
+    }
+    if(flags & BF_BOTTOM){
+      SelectObject32(hdc, oSBrush);
+      PatBlt32(hdc, r.left, r.bottom-1, r.right-r.left, 1, PATCOPY);
+      r.bottom--;
+    }
+    if(flags & BF_LEFT){
+      SelectObject32(hdc, oWBrush);
+      PatBlt32(hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
+      r.left++;
+    }
+    if(flags & BF_TOP){
+      SelectObject32(hdc, oNBrush);
+      PatBlt32(hdc, r.left, r.top, r.right-r.left, 1, PATCOPY);
+      r.top++;
+    }
+  }
+
+  /* if it has internal edge, draw it */
+  if(edge & BDR_INNER){
+    if(flags & BF_RIGHT){
+      SelectObject32(hdc, iEBrush);
+      PatBlt32(hdc, r.right-1, r.top, 1, r.bottom - r.top, PATCOPY);
+      r.right--;
+    }
+    if(flags & BF_BOTTOM){
+      SelectObject32(hdc, iSBrush);
+      PatBlt32(hdc, r.left, r.bottom-1, r.right-r.left, 1, PATCOPY);
+      r.bottom--;
+    }
+    if(flags & BF_LEFT){
+      SelectObject32(hdc, iWBrush);
+      PatBlt32(hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
+      r.left++;
+    }
+    if(flags & BF_TOP){
+      SelectObject32(hdc, iNBrush);
+      PatBlt32(hdc, r.left, r.top, r.right-r.left, 1, PATCOPY);
+      r.top++;
+    }
+  }
+
+  /* if we got to fill the middle, to it now */
+  if((flags & BF_MIDDLE) && !(flags & BF_MONO))
+    FillRect32(hdc, &r, faceBrush);
+
+  /* adjust the rectangle if required */
+  if(flags & BF_ADJUST)
+    *rect = r;
+
+  /* Restore the DC */
+  SelectObject32(hdc, oldBrush);
+
+  return TRUE;
+}
+
+
+/**********************************************************************
+ *          DrawEdge16   (USER.659)
+ */
+BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
+{
+    RECT32 rect32;
+    BOOL32 ret;
+
+    CONV_RECT16TO32( rc, &rect32 );
+    ret = DrawEdge32( hdc, &rect32, edge, flags );
+    CONV_RECT32TO16( &rect32, rc );
+    return ret;
+}
+
+/**********************************************************************
+ *          DrawEdge32   (USER32.154)
+ */
+BOOL32 WINAPI DrawEdge32( HDC32 hdc, LPRECT32 rc, UINT32 edge, UINT32 flags )
+{
+    dprintf_graphics( stddeb, "DrawEdge: %04x %d,%d-%d,%d %04x %04x\n",
+                      hdc, rc->left, rc->top, rc->right, rc->bottom,
+                      edge, flags );
+
+    if(flags & BF_DIAGONAL)
+      return UITOOLS_DrawDiagEdge(hdc, rc, edge, flags);
+    else
+      return UITOOLS_DrawRectEdge(hdc, rc, edge, flags);
+}
+
+
+/***********************************************************************
+ *           UITOOLS_DrawFrameButton
+ */
+static BOOL32 UITOOLS_DrawFrameButton(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+{
+    fprintf( stdnimp,"DrawFrameButton(%x,%p,%x), empty stub!\n",
+             hdc,rc,uState );
+    return FALSE;
+}
+
+/***********************************************************************
+ *           UITOOLS_DrawFrameCaption
+ */
+static BOOL32 UITOOLS_DrawFrameCaption(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+{
+    fprintf( stdnimp,"DrawFrameCaption(%x,%p,%x), empty stub!\n",
+             hdc,rc,uState );
+    return FALSE;
+}
+
+/***********************************************************************
+ *           UITOOLS_DrawFrameMenu
+ */
+static BOOL32 UITOOLS_DrawFrameMenu(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+{
+    fprintf( stdnimp,"DrawFrameMenu32(%x,%p,%x), empty stub!\n",
+             hdc,rc,uState );
+    return FALSE;
+}
+
+/***********************************************************************
+ *           UITOOLS_DrawFrameScroll
+ */
+static BOOL32 UITOOLS_DrawFrameScroll(HDC32 hdc, LPRECT32 rc, UINT32 uState)
+{
+    fprintf( stdnimp,"DrawFrameScroll32(%x,%p,%x), empty stub!\n",
+             hdc,rc,uState );
+    return FALSE;
+}
+
+
+/**********************************************************************
+ *          DrawFrameControl16  (USER.656)
+ */
+BOOL16 WINAPI DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 uType,
+                                  UINT16 uState )
+{
+    RECT32 rect32;
+    BOOL32 ret;
+
+    CONV_RECT16TO32( rc, &rect32 );
+    ret = DrawFrameControl32( hdc, &rect32, uType, uState );
+    CONV_RECT32TO16( &rect32, rc );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          DrawFrameControl32  (USER32.157)
+ */
+BOOL32 WINAPI DrawFrameControl32( HDC32 hdc, LPRECT32 rc, UINT32 uType,
+                                  UINT32 uState )
+{
+    switch(uType)
+    {
+    case DFC_BUTTON:
+      return UITOOLS_DrawFrameButton(hdc, rc, uState);
+    case DFC_CAPTION:
+      return UITOOLS_DrawFrameCaption(hdc, rc, uState);
+    case DFC_MENU:
+      return UITOOLS_DrawFrameMenu(hdc, rc, uState);
+    case DFC_SCROLL:
+      return UITOOLS_DrawFrameScroll(hdc, rc, uState);
+    default:
+      fprintf( stdnimp,"DrawFrameControl32(%x,%p,%d,%x), bad type!\n",
+	       hdc,rc,uType,uState );
+    }
+    return FALSE;
+}
diff --git a/controls/updown.c b/controls/updown.c
index a3a75ef..4282300 100644
--- a/controls/updown.c
+++ b/controls/updown.c
@@ -8,6 +8,7 @@
  *     arrow keys
  *   - I am not sure about the default values for the Min, Max, Pos
  *     (in the UPDOWN_INFO the fields: MinVal, MaxVal, CurVal)
+ *   - I think I do not handle correctly the WS_BORDER style.
  * Testing:
  *   Not much. The following  have not been tested at all:
  *     - horizontal arrows
@@ -20,10 +21,7 @@
  *   behave very well so I am confident it does work in most (all) of the
  *   untested cases.
  * Problems:
- *   At the moment, the control will no draw itself very well because it
- *   uses some features in DrawEdge that are not yet implemented. 
- *   In other words, there is no known problem, exempt for the things in
- *   the TODO list above.
+ *   I do not like the arrows yet, I'll work more on them later on.
  */
 
 #include <stdlib.h>
@@ -47,10 +45,10 @@
 #define INITIAL_DELAY    500 /* initial timer until auto-increment kicks in */
 #define REPEAT_DELAY     50  /* delay between auto-increments */
 
-#define DEFAULT_WIDTH    10  /* default width of the ctrl */
-#define DEFAULT_XSEP     0   /* default separation between buddy and crtl */
-#define DEFAULT_ADDTOP   1   /* amount to extend above the buddy window */
-#define DEFAULT_ADDBOT   1   /* amount to extend below the buddy window */
+#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 */
 
 
 /* Work constants */
@@ -65,9 +63,6 @@
 
 static int accelIndex = -1;
 
-#define max(a,b) ((a)>(b)?(a):(b))
-#define min(a,b) ((a)<(b)?(a):(b))
-
 #define UNKNOWN_PARAM(msg, wParam, lParam) dprintf_updown(stddeb, \
         "UpDown Ctrl: Unknown parameter(s) for message " #msg     \
 	"(%04x): wp=%04x lp=%08lx\n", msg, wParam, lParam);
@@ -129,7 +124,7 @@
   if (wndPtr->dwStyle & UDS_HORZ) {
     len = rect->right - rect->left; /* compute the width */
     if (incr)
-      rect->left = len/2;
+      rect->left = len/2+1; 
     else
       rect->right = len/2;
   }
@@ -138,7 +133,7 @@
     if (incr)
       rect->bottom = len/2;
     else
-      rect->top = len/2;
+      rect->top = len/2+1;
   }
 }
 
@@ -290,48 +285,57 @@
 static void UPDOWN_DrawArrow(HDC32 hdc, RECT32 *rect, BOOL32 incr, 
 			     BOOL32 pressed, BOOL32 horz)
 {
-  const int w = rect->right - rect->left;
-  const int h = rect->bottom - rect->top;
-  int offset = pressed ? 1 : 0, tmp;
-  POINT32 pts[3];
+  const int rw = rect->right - rect->left;
+  const int rh = rect->bottom - rect->top;
+  int offset = pressed ? 1 : 0;
+  int th, x, y, len;
 
+  /* compute max extents of the triangle */
   if(horz){ /* horizontal arrows */
-    pts[0].x = rect->right  - max(2, w/3) + offset;
-    pts[0].y = rect->top    + max(2, h/4) + offset;
-    pts[1].x = pts[0].x;
-    pts[1].y = rect->bottom - max(2, h/4) + offset;
-    pts[2].x = rect->left + w/3 + offset;
-    pts[2].y = (pts[0].y + pts[1].y)/2;
-    if(pts[2].x-2<rect->left)
-      pts[2].x = rect->left + 2;
-    if(pts[2].x <= pts[0].x)
-      pts[2].x = pts[0].x - 1;
+    th = (3*rh)/5-2*4;
+    if(th > rw/2)
+      th = rw/2;
+    if(th < 2)
+      th = 2;
 
-    if(incr){
-      tmp = pts[2].x;
-      pts[2].x = pts[0].x;
-      pts[0].x = pts[1].x = tmp;
-    }
+    /* compute the position of the tip */
+    y = (rect->top+rect->bottom+1)/2 + offset; 
+    if(incr)
+      x = (rect->left+rect->right+1)/2 + (2*th)/3 + offset;
+    else
+      x = (rect->left+rect->right)/2 + th/3 + offset;
+
+    for(len=1; th>0; th--, len+=2){
+      MoveToEx32(hdc, x, y, 0);
+      LineTo32(hdc, x, y+len);
+      if(incr) x--;
+      else     x++;
+      y++;
+    }  
   }
   else{                   /* vertical arrows */
-    pts[0].x = rect->left + max(2, w/4) + offset;
-    pts[0].y = rect->top  + max(2, h/3) + offset;
-    pts[1].x = rect->right- max(2, w/4) + offset;
-    pts[1].y = pts[0].y;
-    pts[2].x = (pts[0].x + pts[1].x)/2;
-    pts[2].y = pts[0].y + h/3 + offset;
-    if(pts[2].y+2>rect->bottom)
-      pts[2].y = rect->bottom - 2;
-    if(pts[2].y <= pts[0].y)
-      pts[2].y = pts[0].y + 1;
+    th = (3*rw)/5-2*4;
+    if(th > rh/2)
+      th = rh/2;
+    if(th < 2)
+      th = 2;
 
-    if(incr){
-      tmp = pts[2].y;
-      pts[2].y = pts[0].y;
-      pts[0].y = pts[1].y = tmp;
+    /* compute the position of the tip */
+    x = (rect->left+rect->right+1)/2 + offset;
+    if(incr)
+      y = (rect->top+rect->bottom+1)/2 - th/3 + offset;
+    else
+      y = (rect->top+rect->bottom)/2 + (2*th)/3 + offset;
+
+    for(len=1; th>0; th--, len+=2){
+      MoveToEx32(hdc, x, y, 0);
+      LineTo32(hdc, x+len, y);
+      if(incr) y++;
+      else     y--;
+      x--;
     }
+    
   }
-  Polygon32(hdc, pts, 3);
 
 }
 
@@ -350,14 +354,6 @@
 
   hdc = BeginPaint32( wndPtr->hwndSelf, &ps );
 
-  /*FIXME - this is just for test */
-  /*      - when DrawEdge works properly, this should dissapear 
-	  as DrawEdge will erase the background */
-/*oldBrush = SelectObject32(hdc, GetStockObject32(GRAY_BRUSH));
-  GetClientRect32(wndPtr->hwndSelf, &rect);
-  Rectangle32(hdc, rect.left, rect.top, rect.right, rect.bottom);
-  SelectObject32(hdc, oldBrush);*/
-
   /* First select the proper brush */
   oldBrush = wndPtr->dwStyle & WS_DISABLED ? GRAY_BRUSH : BLACK_BRUSH;
   oldBrush = SelectObject32(hdc, GetStockObject32(oldBrush));
@@ -365,9 +361,12 @@
   /* Draw the incr button */
   UPDOWN_GetArrowRect(wndPtr, &rect, TRUE);
   prssed = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
-  DrawEdge32(hdc, &rect, prssed ? EDGE_SUNKEN : EDGE_RAISED, 
-	   BF_RECT | BF_SOFT | BF_MIDDLE);
+  DrawEdge32(hdc, &rect, prssed?EDGE_SUNKEN:EDGE_RAISED, BF_RECT|BF_MIDDLE);
   UPDOWN_DrawArrow(hdc, &rect, TRUE, prssed, wndPtr->dwStyle & UDS_HORZ);
+
+  /* Draw the space between the buttons */
+  rect.top = rect.bottom; rect.bottom++;
+  DrawEdge32(hdc, &rect, 0, BF_MIDDLE);
 		    
   /* Draw the decr button */
   UPDOWN_GetArrowRect(wndPtr, &rect, FALSE);
@@ -634,7 +633,7 @@
  *           UpDownWndProc
  */
 LRESULT WINAPI UpDownWindowProc(HWND32 hwnd, UINT32 message, WPARAM32 wParam,
-                                LPARAM lParam)
+				LPARAM lParam)
 {
   WND *wndPtr = WIN_FindWndPtr(hwnd);
   UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr(wndPtr); 
@@ -643,6 +642,9 @@
   switch(message)
     {
     case WM_CREATE:
+      /* get rid of border, if any */
+      wndPtr->dwStyle &= ~WS_BORDER;
+
       /* initialize the info struct */
       infoPtr->AccelCount=0; infoPtr->AccelVect=0; 
       infoPtr->CurVal=0; infoPtr->MinVal=0; infoPtr->MaxVal=100; /*FIXME*/
@@ -745,7 +747,7 @@
 	UNKNOWN_PARAM(UDM_GETACCEL, wParam, lParam);
 	return 0;
       }
-      temp = min(infoPtr->AccelCount, wParam);
+      temp = MIN(infoPtr->AccelCount, wParam);
       memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL));
       return temp;
 
diff --git a/controls/widgets.c b/controls/widgets.c
index c8b9990..9c1d4a3 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -9,8 +9,10 @@
 #include "win.h"
 #include "commctrl.h"
 #include "button.h"
+#include "progress.h"
 #include "static.h"
 #include "status.h"
+#include "updown.h"
 #include "scroll.h"
 #include "updown.h"
 #include "desktop.h"
@@ -104,7 +106,9 @@
     { CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW, StatusWindowProc, 0,
       sizeof(STATUSWINDOWINFO), 0, 0, 0, 0, 0, STATUSCLASSNAME32A },
     { CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW, UpDownWindowProc, 0,
-      sizeof(UPDOWN_INFO), 0, 0, 0, 0, 0, UPDOWN_CLASS32A }
+      sizeof(UPDOWN_INFO), 0, 0, 0, 0, 0, UPDOWN_CLASS32A },
+    { CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW, ProgressWindowProc, 0,
+      sizeof(PROGRESS_INFO), 0, 0, 0, 0, 0, PROGRESS_CLASS32A }
 };
 
 #define NB_COMMON_CONTROLS32 \
@@ -155,6 +159,8 @@
         if (!(bicAtomTable[i] = RegisterClass32A( class32 ))) return FALSE;
     }
 
+    /* FIXME: hack to enable using built-in controls with Windows COMCTL32 */
+    InitCommonControls();
     SEGPTR_FREE(name);
     return TRUE;
 }
@@ -167,15 +173,18 @@
 {
     int i;
     char name[30];
+    const char *old_name;
     WNDCLASS32A *class32 = WIDGETS_CommonControls32;
 
     for (i = 0; i < NB_COMMON_CONTROLS32; i++, class32++)
     {
         /* Just to make sure the string is > 0x10000 */
+        old_name = class32->lpszClassName;
         strcpy( name, (char *)class32->lpszClassName );
         class32->lpszClassName = name;
         class32->hCursor = LoadCursor16( 0, IDC_ARROW );
         RegisterClass32A( class32 );
+        class32->lpszClassName = old_name;	
     }
 }