Release 960521

Tue May 21 14:06:07 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/button.c]
	Made ButtonWndProc a 32-bit window procedure.

	* [controls/desktop.c]
	Made DesktopWndProc a 32-bit window procedure.
	Added handling of WM_SETCURSOR.

	* [controls/menu.c]
	Allocate menu items and strings on the 32-bit system heap.
	Implemented Win32 versions for ChangeMenu, InsertMenu, ModifyMenu,
	AppendMenu and LoadMenuIndirect.

	* [controls/widgets.c]
	Added possibility to have 32-bit built-in classes.

	* [files/drive.c]
	Implemented GetLogicalDrive() and GetLogicalDriveStrings().

	* [misc/spy.c] [include/spy.h]
	Added support for spying Win32 messages.

	* [loader/builtin.c]
	Fixed bug in -dll option parsing.

	* [memory/local.c]
	Added back the change by Huw D. M. Davies to free the block in
	LocalRealloc() before allocating the new one.

	* [objects/bitmap.c] [objects/cursoricon.c] [objects/oembitmap.c]
	Fixed bug in bitmap size that caused memory corruption for 24bpp.

	* [windows/defwnd.c]
	Implemented Win32 version of DefWindowProc().

	* [windows/dialog.c]
	Implemented Win32 version of SendDlgItemMessage,
	Get/SetDlgItemText and Get/SetDlgItemInt.

	* [windows/mdi.c]
	Implemented Win32 version of DefFrameProc() and DefMDIChildProc().
	Don't make a copy of the OBM bitmaps for every MDI window.

	* [windows/message.c]
	Implemented Win32 version of SendMessage().
	
	* [windows/winproc.c] [windows/class.c] [windows/win.c]
	New scheme for 32-bit window procedures to replace aliases. All
	32-bit window procedure get a 16-bit address pointing to a
	WINDOWPROC structure.
	Implemented Ansi<->Unicode translation for CallWindowProc().
	Added translation of WM_DRAWITEM between Win16 and Win32.

	* [windows/win.c] [include/callback.h]
	Added ugly hack to build CREATESTRUCT on the stack when sending
	WM_NCCREATE.
	Implemented Win32 version of Get/SetWindowWord/Long and
	Get/SetWindowText.
	
Fri May 17 10:20:16 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [controls/button.c]
	Avoid gray text on gray background in disabled push buttons
	using a b/w raster and some raster operations (PatBlt,BitBlt).

	* [objects/text.c]
	DrawText(): don't draw an underbar anymore if DT_CALCRECT is set.
diff --git a/windows/class.c b/windows/class.c
index 4db7797..4a3f6eb 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -15,6 +15,7 @@
 #include "ldt.h"
 #include "string32.h"
 #include "toolhelp.h"
+#include "winproc.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -155,6 +156,22 @@
 
 
 /***********************************************************************
+ *           CLASS_SetWndProc
+ *
+ * Set the window procedure and return the old one.
+ */
+static WNDPROC16 CLASS_SetWndProc( CLASS *classPtr, WNDPROC16 proc,
+                                   WINDOWPROCTYPE type )
+{
+    WNDPROC16 oldProc = classPtr->lpfnWndProc;
+    if (type == WIN_PROC_16) classPtr->lpfnWndProc = proc;
+    else classPtr->lpfnWndProc = WINPROC_AllocWinProc( (WNDPROC32)proc, type );
+    WINPROC_FreeWinProc( oldProc );
+    return oldProc;
+}
+
+
+/***********************************************************************
  *           CLASS_FreeClass
  *
  * Free a class structure.
@@ -184,6 +201,7 @@
     if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
     GlobalDeleteAtom( classPtr->atomName );
     CLASS_SetMenuNameA( classPtr, NULL );
+    CLASS_SetWndProc( classPtr, (WNDPROC16)0, WIN_PROC_16 );
     HeapFree( SystemHeap, 0, classPtr );
     return TRUE;
 }
@@ -256,7 +274,8 @@
  */
 static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE32 hInstance,
                                    DWORD style, INT32 classExtra,
-                                   INT32 winExtra )
+                                   INT32 winExtra, WNDPROC16 wndProc,
+                                   WINDOWPROCTYPE wndProcType )
 {
     CLASS *classPtr;
 
@@ -286,17 +305,19 @@
     classPtr = (CLASS *)HeapAlloc( SystemHeap, 0, sizeof(CLASS) +
                                        classExtra - sizeof(classPtr->wExtra) );
     if (!classPtr) return NULL;
-    classPtr->next       = firstClass;
-    classPtr->magic      = CLASS_MAGIC;
-    classPtr->cWindows   = 0;  
-    classPtr->style      = style;
-    classPtr->cbWndExtra = winExtra;
-    classPtr->cbClsExtra = classExtra;
-    classPtr->hInstance  = hInstance;
-    classPtr->atomName   = atom;
-    classPtr->menuNameA  = 0;
-    classPtr->menuNameW  = 0;
-    classPtr->hdce       = (style&CS_CLASSDC) ? DCE_AllocDCE(DCE_CLASS_DC) : 0;
+    classPtr->next        = firstClass;
+    classPtr->magic       = CLASS_MAGIC;
+    classPtr->cWindows    = 0;  
+    classPtr->style       = style;
+    classPtr->lpfnWndProc = 0;
+    classPtr->cbWndExtra  = winExtra;
+    classPtr->cbClsExtra  = classExtra;
+    classPtr->hInstance   = hInstance;
+    classPtr->atomName    = atom;
+    classPtr->menuNameA   = 0;
+    classPtr->menuNameW   = 0;
+    classPtr->hdce        = (style&CS_CLASSDC) ? DCE_AllocDCE(DCE_CLASS_DC): 0;
+    CLASS_SetWndProc( classPtr, wndProc, wndProcType );
     /* Other values must be set by caller */
 
     if (classExtra) memset( classPtr->wExtra, 0, classExtra );
@@ -317,7 +338,8 @@
 
     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -328,8 +350,6 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
 
-    classPtr->flags         = 0;
-    classPtr->lpfnWndProc   = wc->lpfnWndProc;
     classPtr->hIcon         = wc->hIcon;
     classPtr->hIconSm       = 0;
     classPtr->hCursor       = wc->hCursor;
@@ -354,7 +374,9 @@
 
     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32A )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -365,13 +387,10 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
     
-    classPtr->flags         = 0;
-    classPtr->lpfnWndProc   = (WNDPROC16)wc->lpfnWndProc;
     classPtr->hIcon         = (HICON16)wc->hIcon;
     classPtr->hIconSm       = 0;
     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
-    ALIAS_RegisterAlias( 0, 0, (DWORD)wc->lpfnWndProc );
     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
     return atom;
 }
@@ -390,7 +409,9 @@
 
     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32W )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -401,14 +422,10 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
     
-    classPtr->flags         = CLASS_FLAG_UNICODE;
-    classPtr->lpfnWndProc   = (WNDPROC16)wc->lpfnWndProc;
     classPtr->hIcon         = (HICON16)wc->hIcon;
     classPtr->hIconSm       = 0;
     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
-
-    ALIAS_RegisterAlias( 0, 0, (DWORD)wc->lpfnWndProc );
     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
     return atom;
 }
@@ -426,7 +443,8 @@
 
     if (!(atom = GlobalAddAtom16( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          wc->lpfnWndProc, WIN_PROC_16 )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -437,7 +455,6 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
     
-    classPtr->lpfnWndProc   = wc->lpfnWndProc;
     classPtr->hIcon         = wc->hIcon;
     classPtr->hIconSm       = wc->hIconSm;
     classPtr->hCursor       = wc->hCursor;
@@ -462,7 +479,9 @@
 
     if (!(atom = GlobalAddAtom32A( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32A )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -473,13 +492,10 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
     
-    classPtr->lpfnWndProc   = (WNDPROC16)wc->lpfnWndProc;
     classPtr->hIcon         = (HICON16)wc->hIcon;
     classPtr->hIconSm       = (HICON16)wc->hIconSm;
     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
-
-    ALIAS_RegisterAlias( 0, 0, (DWORD)wc->lpfnWndProc );
     CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
     return atom;
 }
@@ -498,7 +514,9 @@
 
     if (!(atom = GlobalAddAtom32W( wc->lpszClassName ))) return 0;
     if (!(classPtr = CLASS_RegisterClass( atom, hInstance, wc->style,
-                                          wc->cbClsExtra, wc->cbWndExtra )))
+                                          wc->cbClsExtra, wc->cbWndExtra,
+                                          (WNDPROC16)wc->lpfnWndProc,
+                                          WIN_PROC_32W )))
     {
         GlobalDeleteAtom( atom );
         return 0;
@@ -509,13 +527,10 @@
                    wc->hbrBackground, wc->style, wc->cbClsExtra,
                    wc->cbWndExtra, classPtr );
     
-    classPtr->lpfnWndProc   = (WNDPROC16)wc->lpfnWndProc;
     classPtr->hIcon         = (HICON16)wc->hIcon;
     classPtr->hIconSm       = (HICON16)wc->hIconSm;
     classPtr->hCursor       = (HCURSOR16)wc->hCursor;
     classPtr->hbrBackground = (HBRUSH16)wc->hbrBackground;
-
-    ALIAS_RegisterAlias( 0, 0, (DWORD)wc->lpfnWndProc );
     CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
     return atom;
 }
@@ -572,7 +587,7 @@
 /***********************************************************************
  *           GetClassWord    (USER.129) (USER32.218)
  */
-WORD GetClassWord( HWND hwnd, INT32 offset )
+WORD GetClassWord( HWND32 hwnd, INT32 offset )
 {
     WND * wndPtr;
     
@@ -661,7 +676,7 @@
 /***********************************************************************
  *           SetClassWord    (USER.130) (USER32.468)
  */
-WORD SetClassWord( HWND hwnd, INT32 offset, WORD newval )
+WORD SetClassWord( HWND32 hwnd, INT32 offset, WORD newval )
 {
     WND * wndPtr;
     WORD retval = 0;
@@ -706,9 +721,19 @@
  */
 LONG SetClassLong16( HWND hwnd, INT16 offset, LONG newval )
 {
-    if ((offset == GCL_MENUNAME) && HIWORD(newval))
-        newval = (LONG)PTR_SEG_TO_LIN(newval);
-    return SetClassLong32A( hwnd, offset, newval );
+    WND *wndPtr;
+
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+        return (LONG)CLASS_SetWndProc( wndPtr->class, (WNDPROC16)newval,
+                                       WIN_PROC_16 );
+    case GCL_MENUNAME:
+        return SetClassLong32A( hwnd, offset, (LONG)PTR_SEG_TO_LIN(newval) );
+    default:
+        return SetClassLong32A( hwnd, offset, newval );
+    }
 }
 
 
@@ -738,6 +763,9 @@
         case GCL_MENUNAME:
             CLASS_SetMenuNameA( wndPtr->class, (LPCSTR)newval );
             return 0;  /* Old value is now meaningless anyway */
+        case GCL_WNDPROC:
+            return (LONG)CLASS_SetWndProc( wndPtr->class, (WNDPROC16)newval,
+                                           WIN_PROC_32A );
         case GCL_HBRBACKGROUND:
         case GCL_HCURSOR:
         case GCL_HICON:
@@ -746,7 +774,6 @@
         case GCL_STYLE:      ptr = &wndPtr->class->style; break;
         case GCL_CBWNDEXTRA: ptr = &wndPtr->class->cbWndExtra; break;
         case GCL_CBCLSEXTRA: ptr = &wndPtr->class->cbClsExtra; break;
-        case GCL_WNDPROC:    ptr = &wndPtr->class->lpfnWndProc; break;
         case GCL_HMODULE:    ptr = &wndPtr->class->hInstance; break;
         default:
             fprintf( stderr, "Warning: invalid offset %d for SetClassLong()\n",
@@ -765,10 +792,19 @@
 LONG SetClassLong32W( HWND hwnd, INT32 offset, LONG newval )
 {
     WND *wndPtr;
-    if (offset != GCL_MENUNAME) return SetClassLong32A( hwnd, offset, newval );
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-    CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
-    return 0;  /* Old value is now meaningless anyway */
+
+    switch(offset)
+    {
+    case GCL_WNDPROC:
+        return (LONG)CLASS_SetWndProc( wndPtr->class, (WNDPROC16)newval,
+                                       WIN_PROC_32W );
+    case GCL_MENUNAME:
+        CLASS_SetMenuNameW( wndPtr->class, (LPCWSTR)newval );
+        return 0;  /* Old value is now meaningless anyway */
+    default:
+        return SetClassLong32A( hwnd, offset, newval );
+    }
 }