Removed dependencies on the internals of the CLASS structure.
Added support for having both ASCII and Unicode window procedures for
builtin classes.

diff --git a/controls/button.c b/controls/button.c
index 9a8ee6d..1250bdf 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -79,7 +79,7 @@
  * Called with window lock held.
  */
 static inline LRESULT WINAPI ButtonWndProc_locked(WND* wndPtr, UINT uMsg,
-					   WPARAM wParam, LPARAM lParam )
+                                                  WPARAM wParam, LPARAM lParam, BOOL unicode )
 {
     RECT rect;
     HWND	hWnd = wndPtr->hwndSelf;
@@ -215,12 +215,9 @@
         }
         break;
 
-    case WM_NCHITTEST:
-        if(style == BS_GROUPBOX) return HTTRANSPARENT;
-        return DefWindowProcW( hWnd, uMsg, wParam, lParam );
-
     case WM_SETTEXT:
-        DEFWND_SetTextW( wndPtr, (LPCWSTR)lParam );
+        if (unicode) DEFWND_SetTextW( wndPtr, (LPCWSTR)lParam );
+        else DEFWND_SetTextA( wndPtr, (LPCSTR)lParam );
 	if( wndPtr->dwStyle & WS_VISIBLE )
             PAINT_BUTTON( wndPtr, style, ODA_DRAWENTIRE );
         return 1; /* success. FIXME: check text length */
@@ -352,30 +349,49 @@
         PAINT_BUTTON( wndPtr, style, ODA_SELECT );
         break;
 
+    case WM_NCHITTEST:
+        if(style == BS_GROUPBOX) return HTTRANSPARENT;
+        /* fall through */
     default:
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+        return unicode ? DefWindowProcW(hWnd, uMsg, wParam, lParam) :
+                         DefWindowProcA(hWnd, uMsg, wParam, lParam);
     }
     return 0;
 }
 
 /***********************************************************************
- *           ButtonWndProc
+ *           ButtonWndProcW
  * The button window procedure. This is just a wrapper which locks
  * the passed HWND and calls the real window procedure (with a WND*
  * pointer pointing to the locked windowstructure).
  */
-LRESULT WINAPI ButtonWndProc( HWND hWnd, UINT uMsg,
-                              WPARAM wParam, LPARAM lParam )
+LRESULT WINAPI ButtonWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
 {
     LRESULT res;
     WND *wndPtr = WIN_FindWndPtr(hWnd);
 
-    res = ButtonWndProc_locked(wndPtr,uMsg,wParam,lParam);
+    res = ButtonWndProc_locked(wndPtr,uMsg,wParam,lParam,TRUE);
 
     WIN_ReleaseWndPtr(wndPtr);
     return res;
 }
 
+
+/***********************************************************************
+ *           ButtonWndProcA
+ */
+LRESULT WINAPI ButtonWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+    LRESULT res;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+
+    res = ButtonWndProc_locked(wndPtr,uMsg,wParam,lParam,FALSE);
+
+    WIN_ReleaseWndPtr(wndPtr);
+    return res;
+}
+
+
 /**********************************************************************
  *       Push Button Functions
  */
diff --git a/controls/desktop.c b/controls/desktop.c
index 72e41de..a1b70c1 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -96,10 +96,12 @@
 	(!desktopPtr->fTileWallPaper && ((desktopPtr->bitmapSize.cx < rect.right) ||
 	 (desktopPtr->bitmapSize.cy < rect.bottom))))
     {
+        HBRUSH brush = desktopPtr->hbrushPattern;
+        if (!brush) brush = GetClassLongA( hwnd, GCL_HBRBACKGROUND );
 	  /* Set colors in case pattern is a monochrome bitmap */
 	SetBkColor( hdc, RGB(0,0,0) );
 	SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
-	FillRect( hdc, &rect, desktopPtr->hbrushPattern );
+	FillRect( hdc, &rect, brush );
     }
 
       /* Paint wall paper */
@@ -289,7 +291,7 @@
 	desktopPtr->hbrushPattern = CreatePatternBrush( hbitmap );
 	DeleteObject( hbitmap );
     }
-    else desktopPtr->hbrushPattern = CreateSolidBrush( GetSysColor(COLOR_BACKGROUND) );
+    else desktopPtr->hbrushPattern = 0;
     WIN_ReleaseDesktop();
     return TRUE;
 }
diff --git a/controls/widgets.c b/controls/widgets.c
index 5ee17dd..bc7ab1d 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -19,106 +19,49 @@
 #include "static.h"
 #include "wine/unicode.h"
 
-/* Built-in classes */
-
-static const char bi_class_nameA[BIC32_NB_CLASSES][10] =
+struct builtin_class
 {
-    "Button",
-    "Edit",
-    "ListBox",
-    "ComboBox",
-    "ComboLBox",
-    POPUPMENU_CLASS_NAME,
-    "Static",
-    "ScrollBar",
-    "MDIClient",
-    DESKTOP_CLASS_NAME,
-    DIALOG_CLASS_NAME,
-    ICONTITLE_CLASS_NAME
+    LPCSTR  name;
+    UINT    style;
+    WNDPROC procA;
+    WNDPROC procW;
+    INT     extra;
+    LPCSTR  cursor;
+    HBRUSH  brush;
 };
 
-static const WCHAR bi_class_nameW[BIC32_NB_CLASSES][10] =
+/* Under NT all builtin classes have both ASCII and Unicode window
+ * procedures except ScrollBar, PopupMenu, Desktop, WinSwitch and
+ * IconTitle which are Unicode-only.
+ */
+static const struct builtin_class classes[] =
 {
-    {'B','u','t','t','o','n',0},
-    {'E','d','i','t',0},
-    {'L','i','s','t','B','o','x',0},
-    {'C','o','m','b','o','B','o','x',0},
-    {'C','o','m','b','o','L','B','o','x',0},
-    {'#','3','2','7','6','8',0},
-    {'S','t','a','t','i','c',0},
-    {'S','c','r','o','l','l','B','a','r',0},
-    {'M','D','I','C','l','i','e','n','t',0},
-    {'#','3','2','7','6','9',0},
-    {'#','3','2','7','7','0',0},
-    {'#','3','2','7','7','2',0}
+    { "Button", CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
+      ButtonWndProcA, ButtonWndProcW, sizeof(BUTTONINFO), IDC_ARROWA, 0 },
+    { "Edit", CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
+      EditWndProc, NULL, sizeof(void *), IDC_IBEAMA, 0 },
+    { "ListBox", CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
+      ListBoxWndProc, NULL, sizeof(void *), IDC_ARROWA, 0 },
+    { "ComboBox", CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
+      ComboWndProc, NULL, sizeof(void *), IDC_ARROWA, 0 },
+    { "ComboLBox", CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
+      ComboLBWndProc, NULL, sizeof(void *), IDC_ARROWA, 0 },
+    { "Static", CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC,
+      StaticWndProc, NULL, sizeof(STATICINFO), IDC_ARROWA, 0 },
+    { "ScrollBar", CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
+      ScrollBarWndProc, NULL, sizeof(SCROLLBAR_INFO), IDC_ARROWA, 0 },
+    { "MDIClient", CS_GLOBALCLASS,
+      MDIClientWndProc, NULL, sizeof(MDICLIENTINFO), IDC_ARROWA, STOCK_LTGRAY_BRUSH },
+    { POPUPMENU_CLASS_NAME, CS_GLOBALCLASS | CS_SAVEBITS,
+      PopupMenuWndProc, NULL, sizeof(HMENU), IDC_ARROWA, COLOR_MENU+1 },
+    { DESKTOP_CLASS_NAME, CS_GLOBALCLASS,
+      DesktopWndProc, NULL, sizeof(DESKTOP), IDC_ARROWA, COLOR_BACKGROUND+1 },
+    { DIALOG_CLASS_NAME, CS_GLOBALCLASS | CS_SAVEBITS,
+      DefDlgProcA, DefDlgProcW, DLGWINDOWEXTRA, IDC_ARROWA, 0 },
+    { ICONTITLE_CLASS_NAME, CS_GLOBALCLASS,
+      IconTitleWndProc, NULL, 0, IDC_ARROWA, 0 }
 };
 
-typedef struct {
-    BOOL unicode;
-    union {
-	WNDCLASSA A;
-	WNDCLASSW W;
-    } wnd_class;
-} BUILTINCLASS;
-
-static BUILTINCLASS WIDGETS_BuiltinClasses[BIC32_NB_CLASSES] =
-{
-    /* BIC32_BUTTON */
-    { TRUE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0,
-      (HCURSOR)IDC_ARROWW, 0, 0, (LPCSTR)bi_class_nameW[0] }}},
-    /* BIC32_EDIT */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
-      EditWndProc, 0, sizeof(void *), 0, 0,
-      (HCURSOR)IDC_IBEAMA, 0, 0, bi_class_nameA[1] }}},
-    /* BIC32_LISTBOX */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
-      ListBoxWndProc, 0, sizeof(void *), 0, 0,
-      (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[2] }}},
-    /* BIC32_COMBO */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, 
-      ComboWndProc, 0, sizeof(void *), 0, 0,
-      (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[3] }}},
-    /* BIC32_COMBOLB */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS, ComboLBWndProc,
-      0, sizeof(void *), 0, 0, (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[4] }}},
-    /* BIC32_POPUPMENU */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc, 0, sizeof(HMENU),
-      0, 0, (HCURSOR)IDC_ARROWA, NULL_BRUSH, 0, bi_class_nameA[5] }}},
-    /* BIC32_STATIC */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC, StaticWndProc,
-      0, sizeof(STATICINFO), 0, 0, (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[6] }}},
-    /* BIC32_SCROLL */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0,
-      (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[7] }}},
-    /* BIC32_MDICLIENT */
-    { FALSE, {
-    { CS_GLOBALCLASS, MDIClientWndProc,
-      0, sizeof(MDICLIENTINFO), 0, 0, (HCURSOR)IDC_ARROWA, STOCK_LTGRAY_BRUSH, 0, bi_class_nameA[8] }}},
-    /* BIC32_DESKTOP */
-    { FALSE, {
-    { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOP),
-      0, 0, (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[9] }}},
-    /* BIC32_DIALOG */
-    { FALSE, {
-    { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProcA, 0, DLGWINDOWEXTRA,
-      0, 0, (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[10] }}},
-    /* BIC32_ICONTITLE */
-    { FALSE, {
-    { CS_GLOBALCLASS, IconTitleWndProc, 0, 0, 
-      0, 0, (HCURSOR)IDC_ARROWA, 0, 0, bi_class_nameA[11] }}}
-};
-
-static ATOM bicAtomTable[BIC32_NB_CLASSES];
 
 /***********************************************************************
  *           WIDGETS_Init
@@ -127,44 +70,14 @@
  */
 BOOL WIDGETS_Init(void)
 {
+    const struct builtin_class *cls = classes;
     int i;
-    BUILTINCLASS *cls = WIDGETS_BuiltinClasses;
 
-    /* Create builtin classes */
-
-    for (i = 0; i < BIC32_NB_CLASSES; i++, cls++)
+    for (i = 0; i < sizeof(classes)/sizeof(classes[0]); i++, cls++)
     {
-	if(cls->unicode)
-	{
-	    WCHAR nameW[20];
-	    /* Just to make sure the string is > 0x10000 */
-	    strcpyW( nameW, (WCHAR *)cls->wnd_class.W.lpszClassName );
-	    cls->wnd_class.W.lpszClassName = nameW;
-	    cls->wnd_class.W.hCursor = LoadCursorW( 0, (LPCWSTR)cls->wnd_class.W.hCursor );
-	    if (!(bicAtomTable[i] = RegisterClassW( &(cls->wnd_class.W) ))) return FALSE;
-	}
-	else
-	{
-	    char name[20];
-	    /* Just to make sure the string is > 0x10000 */
-	    strcpy( name, (char *)cls->wnd_class.A.lpszClassName );
-	    cls->wnd_class.A.lpszClassName = name;
-	    cls->wnd_class.A.hCursor = LoadCursorA( 0, (LPCSTR)cls->wnd_class.A.hCursor );
-	    if (!(bicAtomTable[i] = RegisterClassA( &(cls->wnd_class.A) ))) return FALSE;
-	}
+        if (!CLASS_RegisterBuiltinClass( cls->name, cls->style, cls->extra, cls->cursor,
+                                         cls->brush, cls->procA, cls->procW ))
+            return FALSE;
     }
-
     return TRUE;
 }
-
-
-/***********************************************************************
- *           WIDGETS_IsControl32
- *
- * Check whether pWnd is a built-in control or not.
- */
-BOOL	WIDGETS_IsControl( WND* pWnd, BUILTIN_CLASS32 cls )
-{
-    assert( cls < BIC32_NB_CLASSES );
-    return (GetClassWord(pWnd->hwndSelf, GCW_ATOM) == bicAtomTable[cls]);
-}