Release 941017

Sun Oct 16 13:29:07 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [controls/button.c]
	Implemented WM_GETDLGCODE, WM_SETFONT, BM_SETSTYLE, BM_SETCHECK,
	BM_SETSTATE.
	Implemented default button painting.
	Optimised redrawing.
	Fixed owner-draw buttons.

	* [controls/static.c]
	Implemented WM_SETFONT.
	A few optimisations in painting code.
	Bug fix for SS_SIMPLE controls.

	* [if1632/callback.c]
	Preliminary GetCodeHandle().

	* [if1632/gdi.spec]
	Changed 'pascal' to 'pascal16' everywhere it's needed.

	* [include/windows.h]
	Fixed a few data structures.

	* [memory/heap.c]
	Bug fix in HEAP_ReAlloc().

	* [misc/cursor.c]
	Fixed SetCursor().

	* [objects/bitblt.c]
	Fixed PatBlt() when using BLACKNESS or WHITENESS codes.

	* [objects/font.c]
	Better font mapping code.
	Implemented GetTextFace().

	* [objects/region.c]
	Bug fix in REGION_MakePixmap().
	Faster region copying.

	* [objects/text.c]
	Implemented ExtTextOut().
	Implemented DT_NOCLIP style for DrawText().

	* [windows/dc.c]
	Free the bitmap when deleting a memory DC.

	* [windows/dce.c]
	Added support for windows that have no associated X window.
	Implemented DCX_CLIPSIBLINGS and DCX_PARENTCLIP in GetDCEx().

	* [windows/defdlg.c]
	Implemented default push button handling and DM_SETDEFID.
	Implemented WM_NEXTDLGCTL.

	* [windows/dialog.c]
	Implemented default push button handling.
	Beginning of a keyboard interface in dialogs
	(does not really work yet).
	Fixed dialogs that use a special font.

	* [windows/event.c] [windows/focus.c]
	Added support for non-X windows.

	* [windows/graphics.c]
	Rewritten FloodFill() and implemented ExtFloodFill().

	* [windows/message.c]
	Cleaner hardware messages and X events handling.

	* [windows/defwnd.c] [windows/painting.c]
	Implemented WM_SETREDRAW.

	* [windows/win.c]
	Only create an X window for top-level windows, or for the desktop.
	Child windows now use their parent's drawable.

	* [windows/winpos.c]
	Beginning of support for non-X windows (still somewhat broken).
	Implemented *DeferWindowPos().

	* [*/Imakefile]
	Cleaned up some Imakefiles.
	Moved dc.c from windows/ to objects/.
	Moved cursor.c from misc/ to windows/.

Sun Oct 16 12:21:52 1994  Michael Patra <micky@marie.physik.tu-berlin.d400.de>

	* [include/debug.h]
	  [include/stddebug.h]
	  [*/*.c]
        Rewritten all the calls to printf for displaying debug-information
        (messages like "LoadImage: loading SOL (SOL.EXE)" etc.) 
        Added option "-debugmsg" to Wine. Example: "-debugmsg +all" will turn
        all these messages on, "-debugmsg -dll" will turn all messages 
	concerning DLLs off.

	* [controls/combo.c]
	Added some handling for combo controls with ownerdraw-styles
        (just creating and passing the necessary messages to the 
	corresponding listbox control; the edit-control needs to be
	replaced with something else).

	* [controls/edit.c]
	  [windows/dialog.c]
	Added support for use of global heap memory in dialogs with 
	edit controls.

	* [controls/listbox.c]
	Added support for item data.
	ListBoxInsertString(): Fixed bug for elements which are not inserted
	after the currently last element.
	
	* [misc/dos_fs.c]
	  [miscemu/int21.c]
	DOS_ValidDirectory(): Checks whether a given string is in fact the
	valid name of a directory.

Sat Oct 15 17:35:00 PDT 1994		<martin@cs.csufresno.edu>

	* [Imakefile]
	generate wine.sym after creating wine

	* [debugger/dbg.y]
	load "wine.sym" when entering debugger

	* [debugger/info.c]
	symbolic backtrace for 32-bit stack. Breaks 16-bit bt.

Sun Sep  25 12:00:00 PDT 1994   <martin@osiris.cs.csufresno.edu>

	* [rc/rc.y] [rc/rc.h] [rc/rc.l] [rc/winerc.c]
	Files created

Sun Sep 18 11:04:45 MET DST 1994          Dag Asheim (dash@ifi.uio.no)

	* [misc/spy.c]
	Exclude and Include no longer requires a terminating ';' to
	register the last component.

Thu Sep 15 23:10:09 MET DST 1994          Dag Asheim (dash@ifi.uio.no)

	* [Configure]
	Rewrote much of it.  Added capability to generate a wine.ini
	file.  Commented out the processor emulator options until that
	becomes interesting.  Gives a warning if it sees any *.rej
	files.  I hope I haven't assumed to much about the shell/OS so
	that it breaks under *BSD.

	* [misc/dos_fs.c]
	Removed/changed calls to ToUnix() (which calls tolower()) so
	that the part of the pathname which correspond with the drive
	letter on DOS no longer will be mapped to lowercase.  This
	means that it should be possible to have uppercase letters in
	the [drives] section of wine.ini.

	* [LICENSE]
	Cosmetic changes so that it displays better in the window you
	get from pressing "Credit_License" in the "About WINE" window.

Sun Aug 21 21:12:06 MET DST 1994	<erik@xs4all.nl>

	* [controls/menu.c]
	LoadMenu() moved to loader/resource.c.

	* [misc/main.c]
	Added stub for FileCDR().

	* [include/peexe.h]
	Added, from Eric's pe-test.

	* [include/resource.h]
	Added.

	* [loader/resources.c]
	Removed duplicated code in *Resource() functions.
	Moved NE-program specific functions into ne_image.c.
	Moved NE-fileformat functions to ne_resource.c.

	* [pe_image.c] [pe_resource.c]
	Added. Nothing implemented to run PE-executables, resource
	loading only.

	* [misc/file.c]
	Changed OpenFile() to use macros.

	* [misc/shell.c]
	Added NULL-ptr checks to ShellAbout().

	* [miscemu/int21.c]
	Fixed a few typos.

	* [miscemu/kernel.c]
	Added _DI = _DS, to put the caller's instance in DI. Doesn't
	work properly if caller changed DS :-(
diff --git a/objects/Imakefile b/objects/Imakefile
index b39ccd2..81e345a 100644
--- a/objects/Imakefile
+++ b/objects/Imakefile
@@ -3,44 +3,28 @@
 MODULE = objects
 
 SRCS = \
+	bitblt.c \
 	bitmap.c \
 	brush.c \
+	clipping.c \
+	color.c \
+	dc.c \
+	dcvalues.c \
+	dib.c \
+	dither.c \
 	font.c \
 	gdiobj.c \
+	linedda.c \
+	metafile.c \
 	palette.c \
 	pen.c \
-	dib.c \
 	region.c \
-	text.c \
-	dcvalues.c \
-	clipping.c \
-	bitblt.c \
-	linedda.c \
-	color.c \
-	dither.c \
-	metafile.c
+	text.c
 
-OBJS = \
-	bitmap.o \
-	brush.o \
-	font.o \
-	gdiobj.o \
-	palette.o \
-	pen.o \
-	dib.o \
-	region.o \
-	text.o \
-	dcvalues.o \
-	clipping.o \
-	bitblt.o \
-	linedda.o \
-	color.o \
-	dither.o \
-	metafile.o
+OBJS = $(SRCS:.c=.o)
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
 DependTarget()
-CleanTarget()
 
 includes::
 
diff --git a/objects/bitblt.c b/objects/bitblt.c
index bb83f99..47aa35c 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -13,6 +13,11 @@
 
 #include "gdi.h"
 #include "metafile.h"
+#include "options.h"
+#include "stddebug.h"
+/* #define DEBUG_GDI /* */
+/* #undef  DEBUG_GDI /* */
+#include "debug.h"
 
 extern const int DC_XROPfunction[];
 
@@ -26,8 +31,6 @@
 BOOL PatBlt( HDC hdc, short left, short top,
 	     short width, short height, DWORD rop)
 {
-    int x1, x2, y1, y2;
-    
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) 
     {
@@ -38,22 +41,42 @@
 	return TRUE;
     }
 
-#ifdef DEBUG_GDI
-    printf( "PatBlt: %d %d,%d %dx%d %06x\n",
+    dprintf_gdi(stddeb, "PatBlt: %d %d,%d %dx%d %06x\n",
 	    hdc, left, top, width, height, rop );
-#endif
 
+      /* Convert ROP3 code to ROP2 code */
     rop >>= 16;
     if (!DC_SetupGCForBrush( dc )) rop &= 0x0f;
     else rop = (rop & 0x03) | ((rop >> 4) & 0x0c);
-    XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[rop] );
 
-    x1 = dc->w.DCOrgX + XLPTODP( dc, left );
-    x2 = dc->w.DCOrgX + XLPTODP( dc, left + width );
-    y1 = dc->w.DCOrgY + YLPTODP( dc, top );
-    y2 = dc->w.DCOrgY + YLPTODP( dc, top + height );
-    XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		   MIN(x1,x2), MIN(y1,y2), abs(x2-x1), abs(y2-y1) );
+      /* Special case for BLACKNESS and WHITENESS */
+    if (!Options.usePrivateMap && ((rop == R2_BLACK-1) || (rop == R2_WHITE-1)))
+    {
+        XSetForeground( display, dc->u.x.gc, (rop == R2_BLACK-1) ?
+                      BlackPixelOfScreen(screen) : WhitePixelOfScreen(screen));
+        XSetFillStyle( display, dc->u.x.gc, FillSolid );
+        rop = R2_COPYPEN;
+    }
+
+    XSetFunction( display, dc->u.x.gc, DC_XROPfunction[rop] );
+
+    left = dc->w.DCOrgX + XLPTODP( dc, left );
+    top  = dc->w.DCOrgY + YLPTODP( dc, top );
+
+      /* Convert dimensions to device coords */
+    if ((width = (width * dc->w.VportExtX) / dc->w.WndExtX) < 0)
+    {
+        width = -width;
+        left -= width;
+    }
+    if ((height = (height * dc->w.VportExtY) / dc->w.WndExtY) < 0)
+    {
+        height = -height;
+        top -= height;
+    }
+
+    XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                    left, top, width, height );
     return TRUE;
 }
 
@@ -69,18 +92,17 @@
     DWORD saverop = rop;
     DC *dcDest, *dcSrc;
 
-#ifdef DEBUG_GDI    
-    printf( "BitBlt: %d %d,%d %dx%d %d %d,%d %08x\n",
-	   hdcDest, xDest, yDest, width, height, hdcSrc, xSrc, ySrc, rop );
-#endif
-	if (width == 0 || height == 0) return FALSE;
+    dprintf_gdi(stddeb, "BitBlt: %04x %d,%d %dx%d %04x %d,%d %08x\n",
+                hdcDest, xDest, yDest, width, height, hdcSrc, xSrc, ySrc, rop);
+
+    if (width == 0 || height == 0) return FALSE;
     if ((rop & 0xcc0000) == ((rop & 0x330000) << 2))
 	return PatBlt( hdcDest, xDest, yDest, width, height, rop );
 
     rop >>= 16;
     if ((rop & 0x0f) != (rop >> 4))
     {
-	printf( "BitBlt: Unimplemented ROP %02x\n", rop );
+	dprintf_gdi(stdnimp, "BitBlt: Unimplemented ROP %02x\n", rop );
 	return FALSE;
     }
     
@@ -109,21 +131,21 @@
 	return FALSE;  /* Should call StretchBlt here */
     
     DC_SetupGCForText( dcDest );
-    XSetFunction( XT_display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f] );
+    XSetFunction( display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f] );
     if (dcSrc->w.bitsPerPixel == dcDest->w.bitsPerPixel)
     {
-	XCopyArea( XT_display, dcSrc->u.x.drawable,
+	XCopyArea( display, dcSrc->u.x.drawable,
 		   dcDest->u.x.drawable, dcDest->u.x.gc,
-		   MIN(xs1,xs2), MIN(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
-		   MIN(xd1,xd2), MIN(yd1,yd2) );
+		   min(xs1,xs2), min(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
+		   min(xd1,xd2), min(yd1,yd2) );
     }
     else
     {
 	if (dcSrc->w.bitsPerPixel != 1) return FALSE;
-	XCopyPlane( XT_display, dcSrc->u.x.drawable,
+	XCopyPlane( display, dcSrc->u.x.drawable,
 		    dcDest->u.x.drawable, dcDest->u.x.gc,
-		    MIN(xs1,xs2), MIN(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
-		    MIN(xd1,xd2), MIN(yd1,yd2), 1 );
+		    min(xs1,xs2), min(ys1,ys2), abs(xs2-xs1), abs(ys2-ys1),
+		    min(xd1,xd2), min(yd1,yd2), 1 );
     }
     return TRUE;
 }
@@ -248,7 +270,7 @@
 /* scaling without having to worry about overflows. */
 
 /* ##### muldiv64() borrowed from svgalib 1.03 ##### */
-static inline int muldiv64( int m1, int m2, int d ) 
+static __inline__ int muldiv64( int m1, int m2, int d ) 
 {
 	/* int32 * int32 -> int64 / int32 -> int32 */
 #ifdef i386	
@@ -331,13 +353,11 @@
     WORD stretchmode;
 	BOOL	flg;
 
-#ifdef DEBUG_GDI     
-    fprintf(stderr, "StretchBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
+    dprintf_gdi(stddeb, "StretchBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
            hdcDest, xDest, yDest, widthDest, heightDest, hdcSrc, xSrc, 
            ySrc, widthSrc, heightSrc, rop );
-    printf("StretchMode is %x\n", 
+    dprintf_gdi(stddeb, "StretchMode is %x\n", 
            ((DC *)GDI_GetObjPtr(hdcDest, DC_MAGIC))->w.stretchBltMode);	
-#endif 
 
 	if (widthDest == 0 || heightDest == 0) return FALSE;
 	if (widthSrc == 0 || heightSrc == 0) return FALSE;
@@ -356,7 +376,7 @@
     rop >>= 16;
     if ((rop & 0x0f) != (rop >> 4))
     {
-        printf( "StretchBlt: Unimplemented ROP %02x\n", rop );
+        dprintf_gdi(stdnimp, "StretchBlt: Unimplemented ROP %02x\n", rop );
         return FALSE;
     }
 
@@ -427,7 +447,7 @@
     DC_SetupGCForText(dcDest);
     XSetFunction(display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f]);
     XPutImage(display, dcDest->u.x.drawable, dcDest->u.x.gc,
-	 	dxi, 0, 0, MIN(xd1,xd2), MIN(yd1,yd2), 
+	 	dxi, 0, 0, min(xd1,xd2), min(yd1,yd2), 
 		widthDest, heightDest);
 
     /* now free the images we created */
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 93b0e4a..0785559 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -6,23 +6,28 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include "gdi.h"
 #include "bitmap.h"
+#include "stddebug.h"
+/* #define DEBUG_GDI    /* */
+/* #undef  DEBUG_GDI    /* */
+/* #define DEBUG_BITMAP /* */
+/* #define DEBUG_BITMAP /* */
+#include "debug.h"
 
   /* Include OEM bitmaps */
 #include "bitmaps/check_boxes"
 #include "bitmaps/check_mark"
 #include "bitmaps/menu_arrow"
 
-  /* Handle of the bitmap selected by default in a memory DC */
-HBITMAP BITMAP_hbitmapMemDC = 0;
-
   /* GCs used for B&W and color bitmap operations */
 GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
 
+extern void DC_InitDC( HDC hdc );  /* dc.c */
 
 /***********************************************************************
  *           BITMAP_Init
@@ -49,9 +54,7 @@
 	    XFreePixmap( display, tmpPixmap );
 	}
     }
-
-    BITMAP_hbitmapMemDC = CreateBitmap( 1, 1, 1, 1, NULL );
-    return (BITMAP_hbitmapMemDC != 0);
+    return TRUE;
 }
 
 
@@ -143,10 +146,8 @@
 		      BYTE planes, BYTE bpp, LPSTR bits )
 {
     BITMAP bitmap = { 0, width, height, 0, planes, bpp, bits };
-#ifdef DEBUG_GDI
-    printf( "CreateBitmap: %dx%d, %d colors\n", 
+    dprintf_gdi(stddeb, "CreateBitmap: %dx%d, %d colors\n", 
 	     width, height, 1 << (planes*bpp) );
-#endif
     return CreateBitmapIndirect( &bitmap );
 }
 
@@ -157,9 +158,8 @@
 HBITMAP CreateCompatibleBitmap( HDC hdc, short width, short height )
 {
     DC * dc;
-#ifdef DEBUG_GDI
-    printf( "CreateCompatibleBitmap: %d %dx%d\n", hdc, width, height );
-#endif
+    dprintf_gdi(stddeb, "CreateCompatibleBitmap: %d %dx%d\n", 
+		hdc, width, height );
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
     return CreateBitmap( width, height, 1, dc->w.bitsPerPixel, NULL );
 }
@@ -222,11 +222,9 @@
     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return 0;
 
-#ifdef DEBUG_BITMAP
-    printf( "GetBitmapBits: %dx%d %d colors %p\n",
+    dprintf_bitmap(stddeb, "GetBitmapBits: %dx%d %d colors %p\n",
 	    bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
 	    1 << bmp->bitmap.bmBitsPixel, buffer );
-#endif
       /* Only get entire lines */
     height = count / bmp->bitmap.bmWidthBytes;
     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
@@ -253,11 +251,10 @@
     bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return 0;
 
-#ifdef DEBUG_BITMAP
-    printf( "SetBitmapBits: %dx%d %d colors %p\n",
+    dprintf_bitmap(stddeb, "SetBitmapBits: %dx%d %d colors %p\n",
 	    bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
 	    1 << bmp->bitmap.bmBitsPixel, buffer );
-#endif
+
       /* Only set entire lines */
     height = count / bmp->bitmap.bmWidthBytes;
     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
@@ -314,9 +311,7 @@
 	XFreeGC( display, dc->u.x.gc );
 	dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
 	dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
-	  /* Re-select objects with changed depth */
-	SelectObject( hdc, dc->w.hPen );
-	SelectObject( hdc, dc->w.hBrush );
+        DC_InitDC( hdc );
     }
     return prevHandle;
 }
@@ -326,7 +321,7 @@
  */
 HBITMAP CreateDiscardableBitmap(HDC hdc, short width, short height)
 {
-    printf("CreateDiscardableBitmap(%04X, %d, %d); "
+    dprintf_bitmap(stddeb,"CreateDiscardableBitmap(%04X, %d, %d); "
 	   "// call CreateCompatibleBitmap() for now!\n",
 	   hdc, width, height);
     return CreateCompatibleBitmap(hdc, width, height);
diff --git a/objects/brush.c b/objects/brush.c
index 3979836..1a4ff72 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -10,7 +10,10 @@
 #include "bitmap.h"
 #include "prototypes.h"
 #include "metafile.h"
-
+#include "stddebug.h"
+/* #define DEBUG_GDI /* */
+/* #undef  DEBUG_GDI /* */
+#include "debug.h"
 
 #define NB_HATCH_STYLES  6
 
@@ -47,9 +50,7 @@
 HBRUSH CreateHatchBrush( short style, COLORREF color )
 {
     LOGBRUSH logbrush = { BS_HATCHED, color, style };
-#ifdef DEBUG_GDI
-    printf( "CreateHatchBrush: %d %06x\n", style, color );
-#endif
+    dprintf_gdi(stddeb, "CreateHatchBrush: %d %06x\n", style, color );
     if ((style < 0) || (style >= NB_HATCH_STYLES)) return 0;
     return CreateBrushIndirect( &logbrush );
 }
@@ -63,9 +64,7 @@
     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
     BITMAPOBJ *bmp, *newbmp;
 
-#ifdef DEBUG_GDI
-    printf( "CreatePatternBrush: %d\n", hbitmap );
-#endif
+    dprintf_gdi(stddeb, "CreatePatternBrush: %d\n", hbitmap );
 
       /* Make a copy of the bitmap */
 
@@ -89,9 +88,7 @@
     BITMAPINFO *info, *newInfo;
     int size;
     
-#ifdef DEBUG_GDI
-    printf( "CreateDIBPatternBrush: %d\n", hbitmap );
-#endif
+    dprintf_gdi(stddeb, "CreateDIBPatternBrush: %d\n", hbitmap );
 
       /* Make a copy of the bitmap */
 
@@ -122,9 +119,7 @@
 HBRUSH CreateSolidBrush( COLORREF color )
 {
     LOGBRUSH logbrush = { BS_SOLID, color, 0 };
-#ifdef DEBUG_GDI
-    printf( "CreateSolidBrush: %06x\n", color );
-#endif
+    dprintf_gdi(stddeb, "CreateSolidBrush: %06x\n", color );
     return CreateBrushIndirect( &logbrush );
 }
 
diff --git a/objects/clipping.c b/objects/clipping.c
index 9675b9c..26019dc 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -9,7 +9,10 @@
 #include <stdio.h>
 #include "gdi.h"
 #include "metafile.h"
-
+#include "stddebug.h"
+/* #define DEBUG_CLIPPING /* */
+/* #undef  DEBUG_CLIPPING /* */
+#include "debug.h"
 
 /***********************************************************************
  *           CLIPPING_SetDeviceClipping
@@ -109,9 +112,7 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;
     
-#ifdef DEBUG_CLIPPING
-    printf( "SelectClipRgn: %d %d\n", hdc, hrgn );
-#endif
+    dprintf_clipping(stddeb, "SelectClipRgn: %d %d\n", hdc, hrgn );
     return CLIPPING_SelectRgn( dc, &dc->w.hClipRgn, hrgn );
 }
 
@@ -124,9 +125,7 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;
     
-#ifdef DEBUG_CLIPPING
-    printf( "SelectVisRgn: %d %d\n", hdc, hrgn );
-#endif
+    dprintf_clipping(stddeb, "SelectVisRgn: %d %d\n", hdc, hrgn );
     return CLIPPING_SelectRgn( dc, &dc->w.hVisRgn, hrgn );
 }
 
@@ -145,9 +144,7 @@
 	return NULLREGION;   /* ?? */
     }
 
-#ifdef DEBUG_CLIPPING
-    printf( "OffsetClipRgn: %d %d,%d\n", hdc, x, y );
-#endif
+    dprintf_clipping(stddeb, "OffsetClipRgn: %d %d,%d\n", hdc, x, y );
 
     if (dc->w.hClipRgn)
     {
@@ -166,9 +163,7 @@
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "OffsetVisRgn: %d %d,%d\n", hdc, x, y );
-#endif
+    dprintf_clipping(stddeb, "OffsetVisRgn: %d %d,%d\n", hdc, x, y );
 
     if (dc->w.hVisRgn)
     {
@@ -240,10 +235,8 @@
 	return NULLREGION;   /* ?? */
     }
 
-#ifdef DEBUG_CLIPPING
-    printf( "ExcludeClipRect: %d %dx%d,%dx%d\n",
+    dprintf_clipping(stddeb, "ExcludeClipRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
-#endif
     return CLIPPING_IntersectRect( dc, &dc->w.hClipRgn, left, top,
 				   right, bottom, 1 );
 }
@@ -264,10 +257,8 @@
 	return NULLREGION;   /* ?? */
     }
 
-#ifdef DEBUG_CLIPPING
-    printf( "IntersectClipRect: %d %dx%d,%dx%d\n",
+    dprintf_clipping(stddeb, "IntersectClipRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
-#endif
     return CLIPPING_IntersectRect( dc, &dc->w.hClipRgn, left, top,
 				   right, bottom, 0 );
 }
@@ -281,10 +272,8 @@
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "ExcludeVisRect: %d %dx%d,%dx%d\n",
+    dprintf_clipping(stddeb, "ExcludeVisRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
-#endif
     return CLIPPING_IntersectRect( dc, &dc->w.hVisRgn, left, top,
 				   right, bottom, 1 );
 }
@@ -298,10 +287,8 @@
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "IntersectVisRect: %d %dx%d,%dx%d\n",
+    dprintf_clipping(stddeb, "IntersectVisRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
-#endif
     return CLIPPING_IntersectRect( dc, &dc->w.hVisRgn, left, top,
 				   right, bottom, 0 );
 }
@@ -314,11 +301,10 @@
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "PtVisible: %d %d,%d\n", hdc, x, y );
-#endif
-    if (!dc->w.hClipRgn) return FALSE;
-    return PtInRegion( dc->w.hClipRgn, x, y );
+
+    dprintf_clipping(stddeb, "PtVisible: %d %d,%d\n", hdc, x, y );
+    if (!dc->w.hGCClipRgn) return FALSE;
+    return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x), YLPTODP(dc,y) );
 }
 
 
@@ -327,13 +313,16 @@
  */
 BOOL RectVisible( HDC hdc, LPRECT rect )
 {
+    RECT tmpRect;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "RectVisible: %d %p\n", hdc, rect );
-#endif
-    if (!dc->w.hClipRgn) return FALSE;
-    return RectInRegion( dc->w.hClipRgn, rect );
+    if (!dc) return FALSE;
+    dprintf_clipping(stddeb,"RectVisible: %d %p\n", hdc, rect );
+    if (!dc->w.hGCClipRgn) return FALSE;
+    tmpRect.left   = XLPTODP(dc, rect->left);
+    tmpRect.top    = YLPTODP(dc, rect->top);
+    tmpRect.right  = XLPTODP(dc, rect->right);
+    tmpRect.bottom = YLPTODP(dc, rect->bottom);
+    return RectInRegion( dc->w.hGCClipRgn, &tmpRect );
 }
 
 
@@ -344,9 +333,7 @@
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "GetClipBox: %d %p\n", hdc, rect );
-#endif
+    dprintf_clipping(stddeb, "GetClipBox: %d %p\n", hdc, rect );
 
     if (dc->w.hGCClipRgn) return GetRgnBox( dc->w.hGCClipRgn, rect );
     else
@@ -368,9 +355,7 @@
     RGNOBJ *obj, *copyObj;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
-#ifdef DEBUG_CLIPPING
-    printf( "SaveVisRgn: %d\n", hdc );
-#endif
+    dprintf_clipping(stddeb, "SaveVisRgn: %d\n", hdc );
     if (!dc->w.hVisRgn) return 0;
     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
 	return 0;
@@ -393,9 +378,7 @@
     RGNOBJ *obj, *savedObj;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
-#ifdef DEBUG_CLIPPING
-    printf( "RestoreVisRgn: %d\n", hdc );
-#endif
+    dprintf_clipping(stddeb, "RestoreVisRgn: %d\n", hdc );
     if (!dc->w.hVisRgn) return ERROR;
     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
 	return ERROR;
diff --git a/objects/color.c b/objects/color.c
index c6cbddc..acd145f 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -8,7 +8,7 @@
 
 #include <stdlib.h>
 #include <X11/Xlib.h>
-
+#include <stdio.h>
 #include "windows.h"
 #include "options.h"
 #include "gdi.h"
@@ -128,7 +128,7 @@
 	}
 	else if (!XAllocColor( display, COLOR_WinColormap, &color ))
 	{
-	    printf( "Warning: Not enough free colors. Try using the -privatemap option.\n" );
+	    fprintf(stderr, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
 	    color.pixel = color.red = color.green = color.blue = 0;
 	}
 	colorTranslation[i] = color.pixel;
diff --git a/objects/dc.c b/objects/dc.c
new file mode 100644
index 0000000..5365efb
--- /dev/null
+++ b/objects/dc.c
@@ -0,0 +1,566 @@
+/*
+ * GDI Device Context functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include <stdlib.h>
+#include <string.h>
+#include "gdi.h"
+#include "bitmap.h"
+#include "metafile.h"
+#include "stddebug.h"
+/* #define DEBUG_DC /* */
+/* #undef  DEBUG_DC /* */
+#include "debug.h"
+
+
+static DeviceCaps * displayDevCaps = NULL;
+
+extern const WIN_DC_INFO DCVAL_defaultValues;
+
+extern void CLIPPING_SetDeviceClipping( DC * dc );     /* objects/clipping.c */
+extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );/* objects/color.c */
+extern void COLOR_SetMapping( DC *dc, HANDLE, WORD );  /* objects/color.c */
+
+
+  /* ROP code to GC function conversion */
+const int DC_XROPfunction[16] =
+{
+    GXclear,        /* R2_BLACK */
+    GXnor,          /* R2_NOTMERGEPEN */
+    GXandInverted,  /* R2_MASKNOTPEN */
+    GXcopyInverted, /* R2_NOTCOPYPEN */
+    GXandReverse,   /* R2_MASKPENNOT */
+    GXinvert,       /* R2_NOT */
+    GXxor,          /* R2_XORPEN */
+    GXnand,         /* R2_NOTMASKPEN */
+    GXand,          /* R2_MASKPEN */
+    GXequiv,        /* R2_NOTXORPEN */
+    GXnoop,         /* R2_NOP */
+    GXorInverted,   /* R2_MERGENOTPEN */
+    GXcopy,         /* R2_COPYPEN */
+    GXorReverse,    /* R2_MERGEPENNOT */
+    GXor,           /* R2_MERGEPEN */
+    GXset           /* R2_WHITE */
+};
+
+
+/***********************************************************************
+ *           DC_FillDevCaps
+ *
+ * Fill the device caps structure.
+ */
+void DC_FillDevCaps( DeviceCaps * caps )
+{
+    caps->version       = 0x300; 
+    caps->technology    = DT_RASDISPLAY;
+    caps->horzSize      = WidthMMOfScreen(screen) * screenWidth / WidthOfScreen(screen);
+    caps->vertSize      = HeightMMOfScreen(screen) * screenHeight / HeightOfScreen(screen);
+    caps->horzRes       = screenWidth;
+    caps->vertRes       = screenHeight;
+    caps->bitsPixel     = screenDepth;
+    caps->planes        = 1;
+    caps->numBrushes    = 0;
+    caps->numPens       = 0;
+    caps->numMarkers    = 0;
+    caps->numFonts      = 0;
+    caps->numColors     = 1 << caps->bitsPixel;
+    caps->pdeviceSize   = 0;
+    caps->curveCaps     = CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
+	                  CC_WIDE | CC_STYLED | CC_WIDESTYLED | 
+			  CC_INTERIORS | CC_ROUNDRECT;
+    caps->lineCaps      = LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
+	                  LC_STYLED | LC_WIDESTYLED | LC_INTERIORS;
+    caps->polygonalCaps = PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
+	                  PC_SCANLINE | PC_WIDE | PC_STYLED | 
+			  PC_WIDESTYLED | PC_INTERIORS;
+    caps->textCaps      = TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
+	                  TC_IA_ABLE | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
+    caps->clipCaps      = CP_REGION;
+    caps->rasterCaps    = RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 |
+	                  RC_DI_BITMAP | RC_PALETTE | RC_DIBTODEV | RC_BIGFONT|
+			  RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS;
+    caps->aspectX       = 36;  /* ?? */
+    caps->aspectY       = 36;  /* ?? */
+    caps->aspectXY      = 51;
+    caps->logPixelsX    = (int)(caps->horzRes * 25.4 / caps->horzSize);
+    caps->logPixelsY    = (int)(caps->vertRes * 25.4 / caps->vertSize);
+    caps->sizePalette   = DefaultVisual(display,DefaultScreen(display))->map_entries;
+    caps->numReserved   = 0;
+    caps->colorRes      = 0;
+}
+
+
+/***********************************************************************
+ *           DC_InitDC
+ *
+ * Setup device-specific DC values for a newly created DC.
+ */
+void DC_InitDC( HDC hdc )
+{
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    RealizeDefaultPalette( hdc );
+    SetTextColor( hdc, dc->w.textColor );
+    SetBkColor( hdc, dc->w.backgroundColor );
+    SelectObject( hdc, dc->w.hPen );
+    SelectObject( hdc, dc->w.hBrush );
+    SelectObject( hdc, dc->w.hFont );
+    XSetGraphicsExposures( display, dc->u.x.gc, False );
+    XSetSubwindowMode( display, dc->u.x.gc, IncludeInferiors );
+    CLIPPING_SetDeviceClipping( dc );
+}
+
+
+/***********************************************************************
+ *           DC_SetupDCForBrush
+ *
+ * Setup dc->u.x.gc for drawing operations using current brush.
+ * Return 0 if brush is BS_NULL, 1 otherwise.
+ */
+int DC_SetupGCForBrush( DC * dc )
+{
+    XGCValues val;
+    unsigned long mask = 0;
+
+    if (dc->u.x.brush.style == BS_NULL) return 0;
+    if (dc->u.x.brush.pixel == -1)
+    {
+	/* Special case used for monochrome pattern brushes.
+	 * We need to swap foreground and background because
+	 * Windows does it the wrong way...
+	 */
+	val.foreground = dc->w.backgroundPixel;
+	val.background = dc->w.textPixel;
+    }
+    else
+    {
+	val.foreground = dc->u.x.brush.pixel;
+	val.background = dc->w.backgroundPixel;
+    }
+    val.function = DC_XROPfunction[dc->w.ROPmode-1];
+    val.fill_style = dc->u.x.brush.fillStyle;
+    if (val.fill_style == FillStippled)
+    {
+	if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
+	val.stipple = dc->u.x.brush.pixmap;
+	mask = GCStipple;
+    }
+    else if (val.fill_style == FillTiled)
+    {
+	val.tile = dc->u.x.brush.pixmap;
+	mask = GCTile;
+    }
+    val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
+    val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
+    val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCFillStyle |
+	       GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
+	       &val );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DC_SetupDCForPen
+ *
+ * Setup dc->u.x.gc for drawing operations using current pen.
+ * Return 0 if pen is PS_NULL, 1 otherwise.
+ */
+int DC_SetupGCForPen( DC * dc )
+{
+    XGCValues val;
+
+    if (dc->u.x.pen.style == PS_NULL) return 0;
+    val.function   = DC_XROPfunction[dc->w.ROPmode-1];
+    val.foreground = dc->u.x.pen.pixel;
+    val.background = dc->w.backgroundPixel;
+    val.fill_style = FillSolid;
+    if ((dc->u.x.pen.style!=PS_SOLID) && (dc->u.x.pen.style!=PS_INSIDEFRAME))
+    {
+	XSetDashes( display, dc->u.x.gc, 0,
+		    dc->u.x.pen.dashes, dc->u.x.pen.dash_len );
+	val.line_style = (dc->w.backgroundMode == OPAQUE) ?
+	                      LineDoubleDash : LineOnOffDash;
+    }
+    else val.line_style = LineSolid;
+    val.line_width = dc->u.x.pen.width;
+    val.cap_style  = CapRound;
+    val.join_style = JoinBevel;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCLineWidth |
+	       GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
+    return 1;    
+}
+
+
+/***********************************************************************
+ *           DC_SetupGCForText
+ *
+ * Setup dc->u.x.gc for text drawing operations.
+ * Return 0 if the font is null, 1 otherwise.
+ */
+int DC_SetupGCForText( DC * dc )
+{
+    XGCValues val;
+
+    if (!dc->u.x.font.fstruct)
+    {
+	FONT_SelectObject(dc, STOCK_SYSTEM_FONT, NULL);
+    }
+    val.function   = GXcopy;  /* Text is always GXcopy */
+    val.foreground = dc->w.textPixel;
+    val.background = dc->w.backgroundPixel;
+    val.fill_style = FillSolid;
+    val.font       = dc->u.x.font.fstruct->fid;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCFillStyle |
+	       GCFont, &val );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           GetDCState    (GDI.179)
+ */
+HDC GetDCState( HDC hdc )
+{
+    DC * newdc, * dc;
+    HANDLE handle;
+    
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return 0;
+    newdc = (DC *) GDI_HEAP_ADDR( handle );
+
+    dprintf_dc(stddeb, "GetDCState(%d): returning %d\n", hdc, handle );
+
+    memcpy( &newdc->w, &dc->w, sizeof(dc->w) );
+    memcpy( &newdc->u.x.pen, &dc->u.x.pen, sizeof(dc->u.x.pen) );
+    newdc->saveLevel = 0;
+    newdc->w.flags |= DC_SAVED;
+
+    if (dc->w.hClipRgn)
+    {
+	newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
+	CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
+    }
+    if (dc->w.hVisRgn)
+    {
+	newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
+	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );	
+    }
+    newdc->w.hGCClipRgn = 0;
+    COLOR_SetMapping( newdc, dc->u.x.pal.hMapping, dc->u.x.pal.mappingSize );
+    return handle;
+}
+
+
+/***********************************************************************
+ *           SetDCState    (GDI.180)
+ */
+void SetDCState( HDC hdc, HDC hdcs )
+{
+    DC * dc, * dcs;
+    
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
+    if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
+    if (!dcs->w.flags & DC_SAVED) return;
+    dprintf_dc(stddeb, "SetDCState: %d %d\n", hdc, hdcs );
+    if (dc->w.hClipRgn)	DeleteObject( dc->w.hClipRgn );
+    if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
+    if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
+
+    memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
+    memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
+    dc->w.hClipRgn = dc->w.hVisRgn = dc->w.hGCClipRgn = 0;
+    dc->w.flags &= ~DC_SAVED;
+
+    SelectObject( hdc, dcs->w.hBrush );
+    SelectObject( hdc, dcs->w.hFont );
+    COLOR_SetMapping( dc, dcs->u.x.pal.hMapping, dcs->u.x.pal.mappingSize );
+
+    SelectClipRgn( hdc, dcs->w.hClipRgn );
+    SelectVisRgn( hdc, dcs->w.hVisRgn );
+}
+
+
+/***********************************************************************
+ *           SaveDC    (GDI.30)
+ */
+int SaveDC( HDC hdc )
+{
+    HDC hdcs;
+    DC * dc, * dcs;
+
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+	MF_MetaParam0(dc, META_SAVEDC);
+	return 1;  /* ?? */
+    }
+    if (!(hdcs = GetDCState( hdc ))) return 0;
+    dcs = (DC *) GDI_HEAP_ADDR( hdcs );
+    dcs->header.hNext = dc->header.hNext;
+    dc->header.hNext = hdcs;
+    dprintf_dc(stddeb, "SaveDC(%d): returning %d\n", hdc, dc->saveLevel+1 );
+    return ++dc->saveLevel;
+}
+
+
+/***********************************************************************
+ *           RestoreDC    (GDI.39)
+ */
+BOOL RestoreDC( HDC hdc, short level )
+{
+    DC * dc, * dcs;
+
+    dprintf_dc(stddeb, "RestoreDC: %d %d\n", hdc, level );
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	if (level != -1) return FALSE;
+	MF_MetaParam1(dc, META_RESTOREDC, level);
+	return TRUE;
+    }
+    if (level == -1) level = dc->saveLevel;
+    if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
+    
+    while ((short)dc->saveLevel >= level)
+    {
+	HDC hdcs = dc->header.hNext;
+	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
+	dc->header.hNext = dcs->header.hNext;
+	if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
+	DeleteDC( hdcs );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           CreateDC    (GDI.53)
+ */
+HDC CreateDC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
+{
+    DC * dc;
+    HANDLE handle;
+    
+    handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
+    if (!handle) return 0;
+    dc = (DC *) GDI_HEAP_ADDR( handle );
+
+    dprintf_dc(stddeb, "CreateDC(%s %s %s): returning %d\n", 
+	    driver, device, output, handle );
+
+    if (!displayDevCaps)
+    {
+	displayDevCaps = (DeviceCaps *) malloc( sizeof(DeviceCaps) );
+	DC_FillDevCaps( displayDevCaps );
+    }
+
+    dc->saveLevel = 0;
+    memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
+    memset( &dc->u.x, 0, sizeof(dc->u.x) );
+
+    dc->u.x.drawable   = rootWindow;
+    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
+    dc->w.flags        = 0;
+    dc->w.devCaps      = displayDevCaps;
+    dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
+    dc->w.DCSizeX      = displayDevCaps->horzRes;
+    dc->w.DCSizeY      = displayDevCaps->vertRes;
+
+    DC_InitDC( handle );
+
+    return handle;
+}
+
+
+/***********************************************************************
+ *           CreateIC    (GDI.153)
+ */
+HDC CreateIC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
+{
+      /* Nothing special yet for ICs */
+    return CreateDC( driver, device, output, initData );
+}
+
+
+/***********************************************************************
+ *           CreateCompatibleDC    (GDI.52)
+ */
+HDC CreateCompatibleDC( HDC hdc )
+{
+    DC * dc;
+    HANDLE handle;
+    HBITMAP hbitmap;
+    BITMAPOBJ *bmp;
+
+    handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
+    if (!handle) return 0;
+    dc = (DC *) GDI_HEAP_ADDR( handle );
+
+    dprintf_dc(stddeb, "CreateCompatibleDC(%d): returning %d\n", hdc, handle );
+
+      /* Create default bitmap */
+    if (!(hbitmap = CreateBitmap( 1, 1, 1, 1, NULL )))
+    {
+	GDI_HEAP_FREE( handle );
+	return 0;
+    }
+    bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    
+    dc->saveLevel = 0;
+    memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
+    memset( &dc->u.x, 0, sizeof(dc->u.x) );
+
+    dc->u.x.drawable   = bmp->pixmap;
+    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
+    dc->w.flags        = DC_MEMORY;
+    dc->w.bitsPerPixel = 1;
+    dc->w.devCaps      = displayDevCaps;
+    dc->w.DCSizeX      = 1;
+    dc->w.DCSizeY      = 1;
+    dc->w.hBitmap      = hbitmap;
+
+    DC_InitDC( handle );
+
+    return handle;
+}
+
+
+/***********************************************************************
+ *           DeleteDC    (GDI.68)
+ */
+BOOL DeleteDC( HDC hdc )
+{
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return FALSE;
+
+    dprintf_dc(stddeb, "DeleteDC: %d\n", hdc );
+
+    while (dc->saveLevel)
+    {
+	DC * dcs;
+	HDC hdcs = dc->header.hNext;
+	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
+	dc->header.hNext = dcs->header.hNext;
+	dc->saveLevel--;
+	DeleteDC( hdcs );
+    }
+    
+    if (!(dc->w.flags & DC_SAVED))
+    {
+	SelectObject( hdc, STOCK_BLACK_PEN );
+	SelectObject( hdc, STOCK_WHITE_BRUSH );
+	SelectObject( hdc, STOCK_SYSTEM_FONT );
+	XFreeGC( display, dc->u.x.gc );
+    }
+
+    if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hBitmap );
+
+    if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
+    if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
+    if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
+    
+    return GDI_FreeObject( hdc );
+}
+
+
+/***********************************************************************
+ *           GetDeviceCaps    (GDI.80)
+ */
+int GetDeviceCaps( HDC hdc, WORD cap )
+{
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+
+    if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
+    
+    dprintf_dc(stddeb, "GetDeviceCaps(%d,%d): returning %d\n",
+	    hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
+    return *(WORD *)(((char *)dc->w.devCaps) + cap);
+}
+
+
+/***********************************************************************
+ *           SetBkColor    (GDI.1)
+ */
+COLORREF SetBkColor( HDC hdc, COLORREF color )
+{
+    COLORREF oldColor;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0x80000000;
+	MF_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
+	return 0;  /* ?? */
+    }
+
+    oldColor = dc->w.backgroundColor;
+    dc->w.backgroundColor = color;
+    dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
+    return oldColor;
+}
+
+
+/***********************************************************************
+ *           SetTextColor    (GDI.9)
+ */
+COLORREF SetTextColor( HDC hdc, COLORREF color )
+{
+    COLORREF oldColor;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0x80000000;
+	MF_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color));
+	return 0;  /* ?? */
+    }
+
+    oldColor = dc->w.textColor;
+    dc->w.textColor = color;
+    dc->w.textPixel = COLOR_ToPhysical( dc, color );
+    return oldColor;
+}
+
+
+/***********************************************************************
+ *           GetDCOrg    (GDI.79)
+ */
+DWORD GetDCOrg( HDC hdc )
+{
+    Window root;
+    int x, y, w, h, border, depth;
+
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+    if (dc->w.flags & DC_MEMORY) return 0;
+    XGetGeometry( display, dc->u.x.drawable, &root,
+		  &x, &y, &w, &h, &border, &depth );
+    return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
+}
+
+
+/***********************************************************************
+ *           SetDCOrg    (GDI.117)
+ */
+DWORD SetDCOrg( HDC hdc, short x, short y )
+{
+    DWORD prevOrg;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+    prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
+    dc->w.DCOrgX = x;
+    dc->w.DCOrgY = y;
+    return prevOrg;
+}
diff --git a/objects/dib.c b/objects/dib.c
index 6042cb2..a37509b 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -13,6 +13,12 @@
 #include "gdi.h"
 #include "bitmap.h"
 #include "icon.h"
+#include "stddebug.h"
+/* #define DEBUG_ICON /* */
+/* #undef  DEBUG_ICON /* */
+#include "debug.h"
+
+extern const int DC_XROPfunction[];
 
 extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );  /* color.c */
 
@@ -424,7 +430,8 @@
     if (xSrc+cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth-xSrc;
     if (!cx || !cy) return 0;
 
-    DC_SetupGCForText( dc );  /* To have the correct ROP */
+    DC_SetupGCForText( dc );  /* To have the correct colors */
+    XSetFunction( display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
     return DIB_SetImageBits( dc, lines, dc->w.bitsPerPixel,
 			     bits, info, coloruse,
 			     dc->u.x.drawable, dc->u.x.gc,
@@ -521,33 +528,36 @@
     HBITMAP	hBitTemp;
     HDC		hMemDC;
     HDC		hMemDC2;
-#ifdef DEBUG_ICON
-    printf("DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
-#endif
+    dprintf_icon(stddeb,"DrawIcon(%04X, %d, %d, %04X) \n", hDC, x, y, hIcon);
     if (hIcon == (HICON)NULL) return FALSE;
     lpico = (ICONALLOC *)GlobalLock(hIcon);
     GetObject(lpico->hBitmap, sizeof(BITMAP), (LPSTR)&bm);
-#ifdef DEBUG_ICON
-    printf("DrawIcon / x=%d y=%d\n", x, y);
-    printf("DrawIcon / icon Width=%d\n", (int)lpico->descriptor.Width);
-    printf("DrawIcon / icon Height=%d\n", (int)lpico->descriptor.Height);
-    printf("DrawIcon / icon ColorCount=%d\n", (int)lpico->descriptor.ColorCount);
-    printf("DrawIcon / icon icoDIBSize=%lX\n", (DWORD)lpico->descriptor.icoDIBSize);
-    printf("DrawIcon / icon icoDIBOffset=%lX\n", (DWORD)lpico->descriptor.icoDIBOffset);
-    printf("DrawIcon / bitmap bmWidth=%d bmHeight=%d\n", bm.bmWidth, bm.bmHeight);
-#endif
+    dprintf_icon(stddeb,"DrawIcon / x=%d y=%d\n", x, y);
+    dprintf_icon(stddeb,"DrawIcon / icon Width=%d\n", 
+		 (int)lpico->descriptor.Width);
+    dprintf_icon(stddeb,"DrawIcon / icon Height=%d\n", 
+		 (int)lpico->descriptor.Height);
+    dprintf_icon(stddeb,"DrawIcon / icon ColorCount=%d\n", 
+		 (int)lpico->descriptor.ColorCount);
+    dprintf_icon(stddeb,"DrawIcon / icon icoDIBSize=%lX\n", 
+		 (DWORD)lpico->descriptor.icoDIBSize);
+    dprintf_icon(stddeb,"DrawIcon / icon icoDIBOffset=%lX\n", 
+		 (DWORD)lpico->descriptor.icoDIBOffset);
+    dprintf_icon(stddeb,"DrawIcon / bitmap bmWidth=%d bmHeight=%d\n", 
+		 bm.bmWidth, bm.bmHeight);
     hMemDC = CreateCompatibleDC(hDC);
 #ifdef DEBUG_ICON
-    SelectObject(hMemDC, lpico->hBitmap);
+    hBitTemp = SelectObject(hMemDC, lpico->hBitmap);
     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
     SelectObject(hMemDC, lpico->hBitMask);
     BitBlt(hDC, x, y + bm.bmHeight, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
 #else
-    SelectObject(hMemDC, lpico->hBitMask);
+    hBitTemp = SelectObject(hMemDC, lpico->hBitMask);
     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCAND);
     SelectObject(hMemDC, lpico->hBitmap);
     BitBlt(hDC, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCPAINT);
 #endif
+    SelectObject( hMemDC, hBitTemp );
     DeleteDC(hMemDC);
     return TRUE;
 }
diff --git a/objects/font.c b/objects/font.c
index 3f3b4cb..1a28d6c 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -12,6 +12,10 @@
 #include <X11/Xatom.h>
 #include "user.h"
 #include "gdi.h"
+#include "stddebug.h"
+/* #define DEBUG_FONT /* */
+/* #undef  DEBUG_FONT /* */
+#include "debug.h"
 
 #define MAX_FONTS	256
 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
@@ -44,6 +48,38 @@
 #define CI_GET_DEFAULT_INFO(fs,cs) \
   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
 
+
+/***********************************************************************
+ *           FONT_TranslateName
+ *
+ * Translate a Windows face name to its X11 equivalent.
+ * This will probably have to be customizable.
+ */
+static const char *FONT_TranslateName( char *winFaceName )
+{
+    int i;
+    static const char *mappings[] =
+    {
+        /*Windows name*/  /*X11 name*/
+        "system",         "helvetica",
+        "ms sans serif",  "helvetica",
+        "ms serif",       "times",
+        "fixedsys",       "fixed",
+        "arial",          "helvetica",
+        "helv",           "helvetica",
+        "roman",          "times"
+    };
+
+    for (i = 0; i < sizeof(mappings)/sizeof(mappings[0]); i += 2)
+        if (!strcmp( winFaceName, mappings[i] ))
+        {
+            dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, mappings[i+1] );
+            return mappings[i+1];
+        }
+    return winFaceName;
+}
+
+
 /***********************************************************************
  *           FONT_MatchFont
  *
@@ -52,7 +88,7 @@
 static XFontStruct * FONT_MatchFont( LOGFONT * font )
 {
     char pattern[100];
-    char *family, *weight, *charset;
+    const char *family, *weight, *charset;
     char **names;
     char slant, spacing;
     int width, height, count;
@@ -60,13 +96,13 @@
     
     weight = (font->lfWeight > 550) ? "bold" : "medium";
     slant = font->lfItalic ? 'i' : 'r';
-    height = font->lfHeight * 10;
+    height = abs(font->lfHeight * 10);
     width = font->lfWidth * 10;
     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
 	      (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
-    family = font->lfFaceName;
-    if (!*family) switch(font->lfPitchAndFamily & 0xf0)
+    if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
+    else switch(font->lfPitchAndFamily & 0xf0)
     {
       case FF_ROMAN:      family = "times"; break;
       case FF_SWISS:      family = "helvetica"; break;
@@ -75,36 +111,28 @@
       case FF_DECORATIVE: family = "*"; break;
       default:            family = "*"; break;
     }
-    else 
-	AnsiLower(family);
     
 	while (TRUE) {
 	    /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
 	    if ( width == 0 )
-	      sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
+	      sprintf( pattern, "-*-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
 		      family, weight, slant, height, spacing, charset);
 	    else
-	      sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
+	      sprintf( pattern, "-*-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
 		      family, weight, slant, height, spacing, width, charset);
-#ifdef DEBUG_FONT
-	    printf( "FONT_MatchFont: '%s'\n", pattern );
-#endif
-	    names = XListFonts( XT_display, pattern, 1, &count );
+	    dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
+	    names = XListFonts( display, pattern, 1, &count );
 	    if (count > 0) break;
-		height -= 10;		
-		if (height < 10) {
-#ifdef DEBUG_FONT
-			printf( "        No matching font found\n" );	
-#endif
-			return NULL;
-		    }
-		}
-#ifdef DEBUG_FONT
-	printf( "        Found '%s'\n", *names );
-#endif
-	fontStruct = XLoadQueryFont( XT_display, *names );
-	XFreeFontNames( names );
-	return fontStruct;
+            height -= 10;		
+            if (height < 10) {
+                dprintf_font(stddeb,"*** No match for %s\n", pattern );
+                return NULL;
+            }
+        }
+    dprintf_font(stddeb,"        Found '%s'\n", *names );
+    fontStruct = XLoadQueryFont( display, *names );
+    XFreeFontNames( names );
+    return fontStruct;
 }
 
 
@@ -170,9 +198,8 @@
     if (!hfont) return 0;
     fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
-#ifdef DEBUG_FONT
-	printf("CreateFontIndirect(%08X); return %04X !\n", font, hfont);
-#endif
+    AnsiLower( fontPtr->logfont.lfFaceName );
+    dprintf_font(stddeb,"CreateFontIndirect(%08X); return %04X\n",font,hfont);
     return hfont;
 }
 
@@ -212,9 +239,8 @@
     X_PHYSFONT * stockPtr;
     HFONT prevHandle = dc->w.hFont;
     XFontStruct * fontStruct;
-#ifdef DEBUG_FONT
-	printf("FONT_SelectObject(%04X, %04X, %08X); !\n", dc, hfont, font);
-#endif
+    dprintf_font(stddeb,"FONT_SelectObject(%04X, %04X, %08X); !\n", 
+		     dc, hfont, font);
       /* Load font if necessary */
 
     if (!font)
@@ -242,10 +268,9 @@
     else
     {
 	fontStruct = stockPtr->fstruct;
-#ifdef DEBUG_FONT
-	printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
-	        hfont, fontStruct );
-#endif
+	dprintf_font(stddeb, 
+		     "FONT_SelectObject: Loaded font from cache %x %p\n",
+		     hfont, fontStruct );
     }	
     if (!fontStruct) return 0;
 
@@ -254,7 +279,7 @@
     if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
     {
 	if (dc->u.x.font.fstruct)
-	    XFreeFont( XT_display, dc->u.x.font.fstruct );
+	    XFreeFont( display, dc->u.x.font.fstruct );
     }
 
       /* Store font */
@@ -332,6 +357,23 @@
 
 
 /***********************************************************************
+ *           GetTextFace    (GDI.92)
+ */
+INT GetTextFace( HDC hdc, INT count, LPSTR name )
+{
+    FONTOBJ *font;
+
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+    if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
+        return 0;
+    strncpy( name, font->logfont.lfFaceName, count );
+    name[count-1] = '\0';
+    return strlen(name);
+}
+
+
+/***********************************************************************
  *           GetTextExtent    (GDI.91)
  */
 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
@@ -359,10 +401,8 @@
     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
 		    * dc->w.WndExtY / dc->w.VportExtY);
 
-#ifdef DEBUG_FONT
-    printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
+    dprintf_font(stddeb,"GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
 	    hdc, str, count, size, size->cx, size->cy );
-#endif
     return TRUE;
 }
 
@@ -398,7 +438,8 @@
  */
 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
 {
-    printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC, dwFlag); 
+    dprintf_font(stdnimp,"SetmapperFlags(%04X, %08X) // Empty Stub !\n", 
+		 hDC, dwFlag); 
     return 0L;
 }
 
@@ -445,10 +486,8 @@
 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
 {
 	int 	i, j;
-#ifdef DEBUG_FONT
-	printf("ParseFontParms('%s', %d, %08X, %d);\n", 
+	dprintf_font(stddeb,"ParseFontParms('%s', %d, %08X, %d);\n", 
 			lpFont, wParmsNo, lpRetStr, wMaxSiz);
-#endif
 	if (lpFont == NULL) return 0;
 	if (lpRetStr == NULL) return 0;
 	for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
@@ -461,9 +500,7 @@
 		for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
 			*(lpRetStr + i) = *lpFont++;
 		*(lpRetStr + i) = '\0';
-#ifdef DEBUG_FONT
-		printf("ParseFontParms // '%s'\n", lpRetStr);
-#endif
+		dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
 		return i;
 		}
 	else
@@ -489,22 +526,18 @@
     spacing = '*';
     charset = "*";
     family = "*";
-	printf("InitFontsList !\n");
-    sprintf( pattern, "-*-%s-%s-%c-normal--*-*-*-*-%c-*-%s",
+    dprintf_font(stddeb,"InitFontsList !\n");
+    sprintf( pattern, "-*-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
 	      family, weight, slant, spacing, charset);
-    names = XListFonts( XT_display, pattern, MAX_FONTS, &count );
-#ifdef DEBUG_FONT
-	printf("InitFontsList // count=%d \n", count);
-#endif
+    names = XListFonts( display, pattern, MAX_FONTS, &count );
+    dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
 	for (i = 0; i < count; i++) {
 		lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
 		if (lpNewFont == NULL) {
-			printf("InitFontsList // Error alloc new font structure !\n");
+			dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
 			break;
 			}
-#ifdef DEBUG_FONT
-		printf("InitFontsList // names[%d]='%s' \n", i, names[i]);
-#endif
+		dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
 		ParseFontParms(names[i], 2, str, sizeof(str));
 		if (strcmp(str, "fixed") == 0) strcat(str, "sys");
 		AnsiUpper(str);
@@ -539,11 +572,9 @@
 				lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
 				break;
 			}
-#ifdef DEBUG_FONT
-		printf("InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
-		printf("InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
-		printf("InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
-#endif
+		dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
+		dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
+		dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
 		lpLogFontList[i] = lpNewFont;
 		lpLogFontList[i+1] = NULL;
 		}
@@ -566,20 +597,21 @@
 	char			FaceName[LF_FACESIZE];
 	int				nRet;
 	int				j, i = 0;
-	printf("EnumFonts(%04X, %08X='%s', %08X, %08X)\n", 
+
+	dprintf_font(stddeb,"EnumFonts(%04X, %08X='%s', %08X, %08X)\n", 
 		hDC, lpFaceName, lpFaceName, lpEnumFunc, lpData);
 	if (lpEnumFunc == NULL) return 0;
 	hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
 	lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
 	if (lpLogFont == NULL) {
-		printf("EnumFonts // can't alloc LOGFONT struct !\n");
+		dprintf_font(stddeb,"EnumFonts // can't alloc LOGFONT struct !\n");
 		return 0;
 		}
 	hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
 	lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
 	if (lptm == NULL) {
 		USER_HEAP_FREE(hLog);
-		printf("EnumFonts // can't alloc TEXTMETRIC struct !\n");
+		dprintf_font(stddeb, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
 		return 0;
 		}
 	if (lpFaceName != NULL) {
@@ -600,7 +632,7 @@
 				}
 			if (lpLogFontList[i] == NULL) break;
 			lpFaceList[j] = lpLogFontList[i]->lfFaceName;
-			printf("EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
+			dprintf_font(stddeb,"EnumFonts // enum all 'lpFaceName' '%s' !\n", lpFaceList[j]);
 			}
 		else {
 			while(lpLogFontList[i] != NULL) {
@@ -615,7 +647,8 @@
 		GetTextMetrics(hDC, lptm);
 		SelectObject(hDC, hOldFont);
 		DeleteObject(hFont);
-		printf("EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
+		dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
+
 #ifdef WINELIB
 		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
 #else
@@ -623,7 +656,7 @@
 					2, (int)lptm, 0, (int)0, 2, (int)lpData);
 #endif
 		if (nRet == 0) {
-			printf("EnumFonts // EnumEnd requested by application !\n");
+			dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
 			break;
 			}
 		}
@@ -648,20 +681,21 @@
 	char			FaceName[LF_FACESIZE];
 	int				nRet;
 	int				j, i = 0;
-	printf("EnumFontFamilies(%04X, %08X, %08X, %08X)\n", 
+
+	dprintf_font(stddeb,"EnumFontFamilies(%04X, %08X, %08X, %08X)\n", 
 					hDC, lpszFamily, lpEnumFunc, lpData);
 	if (lpEnumFunc == NULL) return 0;
 	hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
 	lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
 	if (lpLogFont == NULL) {
-		printf("EnumFontFamilies // can't alloc LOGFONT struct !\n");
+		dprintf_font(stddeb,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
 		return 0;
 		}
 	hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
 	lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
 	if (lptm == NULL) {
 		USER_HEAP_FREE(hLog);
-		printf("EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
+		dprintf_font(stddeb,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
 		return 0;
 		}
 	if (lpszFamily != NULL) {
@@ -683,7 +717,7 @@
 				}
 			if (lpLogFontList[i] == NULL) break;
 			lpFaceList[j] = lpLogFontList[i]->lfFaceName;
-			printf("EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
+			dprintf_font(stddeb,"EnumFontFamilies // enum all 'lpszFamily' '%s' !\n", lpFaceList[j]);
 			}
 		else {
 			while(lpLogFontList[i] != NULL) {
@@ -698,7 +732,8 @@
 		GetTextMetrics(hDC, lptm);
 		SelectObject(hDC, hOldFont);
 		DeleteObject(hFont);
-		printf("EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
+		dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%08X lptm=%08X\n", i, lpLogFont, lptm);
+
 #ifdef WINELIB
 		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
 #else
@@ -706,7 +741,7 @@
 					2, (int)lptm, 0, (int)0, 2, (int)lpData);
 #endif
 		if (nRet == 0) {
-			printf("EnumFontFamilies // EnumEnd requested by application !\n");
+			dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
 			break;
 			}
 		}
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 7937282..e521619 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -11,6 +11,10 @@
 #include "user.h"
 #include "gdi.h"
 #include "prototypes.h"
+#include "stddebug.h"
+/* #define DEBUG_GDI /* */
+/* #undef  DEBUG_GDI /* */
+#include "debug.h"
 
 MDESC *GDI_Heap = NULL;
 
@@ -196,17 +200,13 @@
 	if (lpPenBrushList == NULL) {
 		lpPenBrushList = malloc(MAX_OBJ * sizeof(HANDLE));
 		lpPenBrushList[0] = 0;
-#ifdef DEBUG_GDI
-		printf("GDI_AppendToPenBrushList() lpPenBrushList allocated !\n");
-#endif
+		dprintf_gdi(stddeb,"GDI_AppendToPenBrushList() lpPenBrushList allocated !\n");
 		}
 	for (lphObj = lpPenBrushList; i < MAX_OBJ; i++) {
 		if (*lphObj == 0) {
 			*lphObj = hNewObj;
 			*(lphObj + 1) = 0;
-#ifdef DEBUG_GDI
-			printf("GDI_AppendToPenBrushList(%04X) appended (count=%d)\n", hNewObj, i);
-#endif
+			dprintf_gdi(stddeb,"GDI_AppendToPenBrushList(%04X) appended (count=%d)\n", hNewObj, i);
 			return TRUE;
 			}
 		lphObj++;
@@ -244,7 +244,7 @@
     if (!handle) return 0;
     obj = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
     if (obj == NULL) {
-    	printf("GDI_AllocObject // Error trying to get GDI_HEAD_ADDR !\n");
+    	fprintf(stderr,"GDI_AllocObject // Error trying to get GDI_HEAD_ADDR !\n");
     	return 0;
     	}
     obj->hNext   = 0;
@@ -265,10 +265,11 @@
     GDIOBJHDR * object;
 
       /* Can't free stock objects */
-    if (handle >= FIRST_STOCK_HANDLE) return FALSE;
+    if (handle >= FIRST_STOCK_HANDLE) return TRUE;
     
     object = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
     if (!object) return FALSE;
+    object->wMagic = 0;  /* Mark it as invalid */
 
       /* Free object */
     
@@ -308,9 +309,7 @@
     GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_ADDR( obj );
     if (!header) return FALSE;
 
-#ifdef DEBUG_GDI
-    printf( "DeleteObject: %d\n", obj );
-#endif
+    dprintf_gdi(stddeb, "DeleteObject: %d\n", obj );
 
       /* Delete object */
 
@@ -334,9 +333,8 @@
 {
     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
     if (!StockObjects[obj]) return 0;
-#ifdef DEBUG_GDI
-    printf( "GetStockObject: returning %04x\n", FIRST_STOCK_HANDLE + obj );
-#endif
+    dprintf_gdi(stddeb, "GetStockObject: returning %04x\n", 
+		FIRST_STOCK_HANDLE + obj );
     return FIRST_STOCK_HANDLE + obj;
 }
 
@@ -347,9 +345,7 @@
 int GetObject( HANDLE handle, int count, LPSTR buffer )
 {
     GDIOBJHDR * ptr = NULL;
-#ifdef DEBUG_GDI
-    printf( "GetObject: %04x %d %08x\n", handle, count, buffer );
-#endif
+    dprintf_gdi(stddeb, "GetObject: %04x %d %08x\n", handle, count, buffer );
     if (!count) return 0;
 
     if (handle >= FIRST_STOCK_HANDLE)
@@ -385,9 +381,7 @@
     GDIOBJHDR * ptr = NULL;
     DC * dc;
     
-#ifdef DEBUG_GDI
-    printf( "SelectObject: %d %04x\n", hdc, handle );
-#endif
+    dprintf_gdi(stddeb, "SelectObject: %d %04x\n", hdc, handle );
     if (handle >= FIRST_STOCK_HANDLE)
     {
 	if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
@@ -425,9 +419,7 @@
  */
 BOOL UnrealizeObject( HANDLE handle )
 {
-#ifdef DEBUG_GDI
-    printf( "UnrealizeObject: %04x\n", handle );
-#endif
+    dprintf_gdi(stdnimp, "UnrealizeObject: %04x\n", handle );
     return TRUE;
 }
 
@@ -446,53 +438,53 @@
 	HANDLE 		hLog;
 	int			i, nRet;
 	if (lpEnumFunc == NULL) {
-		printf("EnumObjects // Bad EnumProc callback address !\n");
+		fprintf(stderr,"EnumObjects // Bad EnumProc callback address !\n");
 		return 0;
 		}
 	switch (nObjType) {
 		case OBJ_PEN:
 			wMagic = PEN_MAGIC;
-			printf("EnumObjects(%04X, OBJ_PEN, %08X, %08X);\n", 
+			dprintf_gdi(stddeb,"EnumObjects(%04X, OBJ_PEN, %08X, %08X);\n", 
 									hDC, lpEnumFunc, lpData);
 			hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGPEN));
 			lpLog = (LPSTR) USER_HEAP_ADDR(hLog);
 			if (lpLog == NULL) {
-				printf("EnumObjects // Unable to alloc LOGPEN struct !\n");
+				fprintf(stderr,"EnumObjects // Unable to alloc LOGPEN struct !\n");
 				return 0;
 				}
 			break;
 		case OBJ_BRUSH:
 			wMagic = BRUSH_MAGIC;
-			printf("EnumObjects(%04X, OBJ_BRUSH, %08X, %08X);\n", 
+			dprintf_gdi(stddeb,"EnumObjects(%04X, OBJ_BRUSH, %08X, %08X);\n", 
 									hDC, lpEnumFunc, lpData);
 			hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGBRUSH));
 			lpLog = (LPSTR) USER_HEAP_ADDR(hLog);
 			if (lpLog == NULL) {
-				printf("EnumObjects // Unable to alloc LOGBRUSH struct !\n");
+				fprintf(stderr,"EnumObjects // Unable to alloc LOGBRUSH struct !\n");
 				return 0;
 				}
 			break;
 		default:
-			printf("EnumObjects(%04X, %04X, %08X, %08X); // Unknown OBJ type !\n", 
+			fprintf(stderr,"EnumObjects(%04X, %04X, %08X, %08X); // Unknown OBJ type !\n", 
 						hDC, nObjType, lpEnumFunc, lpData);
 			return 0;
 		}
-	printf("EnumObjects // Stock Objects first !\n");
+	dprintf_gdi(stddeb,"EnumObjects // Stock Objects first !\n");
 	for (i = 0; i < NB_STOCK_OBJECTS; i++) {
 		header = StockObjects[i];
 		if (header->wMagic == wMagic) {
 			PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), (LPLOGPEN)lpLog);
 			BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH), (LPLOGBRUSH)lpLog);
-			printf("EnumObjects // StockObj lpLog=%08X lpData=%08X\n", lpLog, lpData);
+			dprintf_gdi(stddeb,"EnumObjects // StockObj lpLog=%08X lpData=%08X\n", lpLog, lpData);
 			if (header->wMagic == BRUSH_MAGIC) {
-				printf("EnumObjects // StockBrush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
-				printf("EnumObjects // StockBrush lbColor=%08X\n", ((LPLOGBRUSH)lpLog)->lbColor);
-				printf("EnumObjects // StockBrush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
+				dprintf_gdi(stddeb,"EnumObjects // StockBrush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
+				dprintf_gdi(stddeb,"EnumObjects // StockBrush lbColor=%08X\n", ((LPLOGBRUSH)lpLog)->lbColor);
+				dprintf_gdi(stddeb,"EnumObjects // StockBrush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
 				}
 			if (header->wMagic == PEN_MAGIC) {
-				printf("EnumObjects // StockPen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
-				printf("EnumObjects // StockPen lopnWidth=%08X\n", ((LPLOGPEN)lpLog)->lopnWidth);
-				printf("EnumObjects // StockPen lopnColor=%08X\n", ((LPLOGPEN)lpLog)->lopnColor);
+				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
+				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnWidth=%08X\n", ((LPLOGPEN)lpLog)->lopnWidth);
+				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnColor=%08X\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
 			nRet = 1;
 /*
@@ -502,36 +494,32 @@
 			nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLog,	2, (int)lpData);
 #endif
 */
-			printf("EnumObjects // after CallBack16 !\n");
+			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
 			if (nRet == 0) {
 				USER_HEAP_FREE(hLog);
-				printf("EnumObjects // EnumEnd requested by application !\n");
+				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
 				return 0;
 				}
 			}
 		}
 	if (lpPenBrushList == NULL) return 0;
-	printf("EnumObjects // Now DC owned objects %08X !\n", header);
+	dprintf_gdi(stddeb,"EnumObjects // Now DC owned objects %08X !\n", header);
 	for (lphObj = lpPenBrushList; *lphObj != 0; ) {
-#ifdef DEBUG_GDI
-		printf("EnumObjects // *lphObj=%04X\n", *lphObj);
-#endif
+		dprintf_gdi(stddeb,"EnumObjects // *lphObj=%04X\n", *lphObj);
 		header = (GDIOBJHDR *) GDI_HEAP_ADDR(*lphObj++);
 		if (header->wMagic == wMagic) {
-#ifdef DEBUG_GDI
-			printf("EnumObjects // DC_Obj lpLog=%08X lpData=%08X\n", lpLog, lpData);
-#endif
+			dprintf_gdi(stddeb,"EnumObjects // DC_Obj lpLog=%08X lpData=%08X\n", lpLog, lpData);
 			if (header->wMagic == BRUSH_MAGIC) {
 				BRUSH_GetObject( (BRUSHOBJ *)header, sizeof(LOGBRUSH), (LPLOGBRUSH)lpLog);
-				printf("EnumObjects // DC_Brush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
-				printf("EnumObjects // DC_Brush lbColor=%08X\n", ((LPLOGBRUSH)lpLog)->lbColor);
-				printf("EnumObjects // DC_Brush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbStyle=%04X\n", ((LPLOGBRUSH)lpLog)->lbStyle);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbColor=%08X\n", ((LPLOGBRUSH)lpLog)->lbColor);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Brush lbHatch=%04X\n", ((LPLOGBRUSH)lpLog)->lbHatch);
 				}
 			if (header->wMagic == PEN_MAGIC) {
 				PEN_GetObject( (PENOBJ *)header, sizeof(LOGPEN), (LPLOGPEN)lpLog);
-				printf("EnumObjects // DC_Pen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
-				printf("EnumObjects // DC_Pen lopnWidth=%08X\n", ((LPLOGPEN)lpLog)->lopnWidth);
-				printf("EnumObjects // DC_Pen lopnColor=%08X\n", ((LPLOGPEN)lpLog)->lopnColor);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnStyle=%04X\n", ((LPLOGPEN)lpLog)->lopnStyle);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnWidth=%08X\n", ((LPLOGPEN)lpLog)->lopnWidth);
+				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnColor=%08X\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
 /*
 #ifdef WINELIB
@@ -541,16 +529,16 @@
 #endif
 */
 			nRet = 1;
-			printf("EnumObjects // after CallBack16 !\n");
+			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
 			if (nRet == 0) {
 				USER_HEAP_FREE(hLog);
-				printf("EnumObjects // EnumEnd requested by application !\n");
+				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
 				return 0;
 				}
 			}
 		}
 	USER_HEAP_FREE(hLog);
-	printf("EnumObjects // End of enumeration !\n");
+	dprintf_gdi(stddeb,"EnumObjects // End of enumeration !\n");
 	return 0;
 }
 
diff --git a/objects/metafile.c b/objects/metafile.c
index fd9c3ae..83cf4c4 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -6,12 +6,15 @@
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
 
+#include <string.h>
 #include "windows.h"
 #include "gdi.h"
 #include "metafile.h"
 #include "prototypes.h"
-
-#define DEBUG_METAFILE
+#include "stddebug.h"
+/* #define DEBUG_METAFILE /* */
+/* #undef  DEBUG_METAFILE /* */
+#include "debug.h"
 
 #define HTINCR  10      /* handle table allocation size increment */
 
@@ -29,9 +32,7 @@
     METAHEADER *mh;
     HANDLETABLE *ht;
 
-#ifdef DEBUG_METAFILE
-    printf("CreateMetaFile: %s\n", lpFilename);
-#endif
+    dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
 
     handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
     if (!handle) return 0;
@@ -94,9 +95,7 @@
     char buffer[15];
     METARECORD *mr = (METARECORD *)&buffer;
 
-#ifdef DEBUG_METAFILE
-    printf("CloseMetaFile\n");
-#endif
+    dprintf_metafile(stddeb,"CloseMetaFile\n");
 
     dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
     if (!dc) return 0;
@@ -442,7 +441,7 @@
 	break;
 
     default:
-	printf("PlayMetaFileRecord: Unknown record type %x\n",
+	fprintf(stderr,"PlayMetaFileRecord: Unknown record type %x\n",
 	                                      mr->rdFunction);
     }
 }
@@ -898,7 +897,7 @@
 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
 	       short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
 {
-    printf("MF_BitBlt: not implemented yet\n");
+    dprintf_metafile(stdnimp,"MF_BitBlt: not implemented yet\n");
 }
 
 
@@ -909,5 +908,5 @@
 		   short heightDest, HDC hdcSrc, short xSrc, short ySrc, 
 		   short widthSrc, short heightSrc, DWORD rop)
 {
-    printf("MF_StretchBlt: not implemented yet\n");
+    dprintf_metafile(stdnimp,"MF_StretchBlt: not implemented yet\n");
 }
diff --git a/objects/palette.c b/objects/palette.c
index dc52635..7761c2e 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -22,6 +22,10 @@
 
 #include <X11/Xlib.h>
 #include "gdi.h"
+#include "stddebug.h"
+/* #define DEBUG_PALETTE /* */
+/* #undef  DEBUG_PALETTE /* */
+#include "debug.h"
 
 extern void COLOR_SetMapping( DC *dc, HANDLE map, WORD size );  /* color.c */
 
@@ -156,10 +160,8 @@
 	}
 	entry++;
     }
-#ifdef DEBUG_GDI
-    printf( "GetNearestPaletteIndex(%x,%06x) : returning %d\n", 
+    dprintf_palette(stddeb,"GetNearestPaletteIndex(%x,%06x) : returning %d\n", 
 	     hpalette, color, index );
-#endif
     return index;
 }
 
@@ -183,9 +185,7 @@
     HPALETTE prev;
     DC *dc;
 
-#ifdef DEBUG_PALETTE
-    printf( "GDISelectPalette: %d %d\n", hdc, hpal );
-#endif
+    dprintf_palette(stddeb, "GDISelectPalette: %d %d\n", hdc, hpal );
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
     prev = dc->w.hPalette;
     dc->w.hPalette = hpal;
@@ -200,9 +200,7 @@
  */
 UINT GDIRealizePalette( HDC hdc )
 {
-#ifdef DEBUG_PALETTE
-    printf( "GDIRealizePalette: %d\n", hdc );
-#endif
+    dprintf_palette(stdnimp, "GDIRealizePalette: %d\n", hdc );
     return 0;
 }
 
diff --git a/objects/pen.c b/objects/pen.c
index 61e1f16..00eba87 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -8,6 +8,10 @@
 
 #include "gdi.h"
 #include "metafile.h"
+#include "stddebug.h"
+/* #define DEBUG_GDI /* */
+/* #undef  DEBUG_GDI /* */
+#include "debug.h"
 
 extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );
 
@@ -17,9 +21,7 @@
 HPEN CreatePen( short style, short width, COLORREF color )
 {
     LOGPEN logpen = { style, { width, 0 }, color };
-#ifdef DEBUG_GDI
-    printf( "CreatePen: %d %d %06x\n", style, width, color );
-#endif
+    dprintf_gdi(stddeb, "CreatePen: %d %d %06x\n", style, width, color );
     return CreatePenIndirect( &logpen );
 }
 
diff --git a/objects/region.c b/objects/region.c
index 74ec57b..ad3379b 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -10,6 +10,10 @@
 #include <stdio.h>
 
 #include "gdi.h"
+#include "stddebug.h"
+/* #define DEBUG_REGION /* */
+/* #undef  DEBUG_REGION /* */
+#include "debug.h"
 
   /* GC used for region operations */
 static GC regionGC = 0;
@@ -50,8 +54,8 @@
     region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
     if (!region->pixmap) return FALSE;
     XSetRegion( display, regionGC, region->xrgn );
-    XSetClipOrigin( display, regionGC, region->box.left, region->box.top );
-    XSetFunction( display, regionGC, GXcopy );
+    XSetClipOrigin( display, regionGC, -region->box.left, -region->box.top );
+    XSetFunction( display, regionGC, GXset );
     XFillRectangle( display, region->pixmap, regionGC, 0, 0, width, height );
     XSetClipMask( display, regionGC, None );  /* Clear clip region */
     return TRUE;
@@ -91,14 +95,9 @@
 
     if (createXrgn)  /* Create and set the X region */
     {
-	Region tmprgn;
 	XRectangle xrect = { region->box.left, region->box.top, width, height};
-
-	if (!(tmprgn = XCreateRegion())) return FALSE;
-	if ((region->xrgn = XCreateRegion()))
-	    XUnionRectWithRegion( &xrect, tmprgn, region->xrgn );
-	XDestroyRegion( tmprgn );
-	if (!region->xrgn) return FALSE;
+	if (!(region->xrgn = XCreateRegion())) return FALSE;
+        XUnionRectWithRegion( &xrect, region->xrgn, region->xrgn );
     }
     else  /* Create the pixmap */
     {
@@ -130,9 +129,7 @@
 {
     RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
     if (!obj) return ERROR;
-#ifdef DEBUG_REGION
-    printf( "OffsetRgn: %d %d,%d\n", hrgn, x, y );
-#endif
+    dprintf_region(stddeb, "OffsetRgn: %d %d,%d\n", hrgn, x, y );
     OffsetRect( &obj->region.box, x, y );
     if (obj->region.xrgn) XOffsetRegion( obj->region.xrgn, x, y );
     return obj->region.type;
@@ -146,9 +143,7 @@
 {
     RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
     if (!obj) return ERROR;
-#ifdef DEBUG_REGION
-    printf( "GetRgnBox: %d\n", hrgn );
-#endif
+    dprintf_region(stddeb, "GetRgnBox: %d\n", hrgn );
     *rect = obj->region.box;
     return obj->region.type;
 }
@@ -171,10 +166,8 @@
 {
     HRGN hrgn;
 
-#ifdef DEBUG_REGION
-    printf( "CreateRectRgnIndirect: %d,%d-%d,%d\n",
+    dprintf_region(stddeb, "CreateRectRgnIndirect: %d,%d-%d,%d\n",
 	    rect->left, rect->top, rect->right, rect->bottom );
-#endif
     
       /* Create region */
 
@@ -198,10 +191,8 @@
     RGNOBJ * rgnObj;
     HRGN hrgn;
 
-#ifdef DEBUG_REGION
-    printf( "CreateRoundRectRgn: %d,%d-%d,%d %dx%d\n",
+    dprintf_region(stddeb, "CreateRoundRectRgn: %d,%d-%d,%d %dx%d\n",
 	    left, top, right, bottom, ellipse_width, ellipse_height );
-#endif
     
       /* Create region */
 
@@ -252,9 +243,8 @@
     RECT rect = { left, top, right, bottom };    
     RGNOBJ * rgnObj;
 
-#ifdef DEBUG_REGION
-    printf( "SetRectRgn: %d %d,%d-%d,%d\n", hrgn, left, top, right, bottom );
-#endif
+    dprintf_region(stddeb, "SetRectRgn: %d %d,%d-%d,%d\n", 
+		   hrgn, left, top, right, bottom );
     
       /* Free previous pixmap */
 
@@ -283,10 +273,8 @@
     RGNOBJ * rgnObj;
     HRGN hrgn;
 
-#ifdef DEBUG_REGION
-    printf( "CreateEllipticRgnIndirect: %d,%d-%d,%d\n",
+    dprintf_region(stddeb, "CreateEllipticRgnIndirect: %d,%d-%d,%d\n",
 	    rect->left, rect->top, rect->right, rect->bottom );
-#endif
     
       /* Create region */
 
@@ -335,9 +323,7 @@
     XRectangle rect;
     Region xrgn;
 
-#ifdef DEBUG_REGION
-    printf( "CreatePolyPolygonRgn: %d polygons\n", nbpolygons );
-#endif
+    dprintf_region(stddeb, "CreatePolyPolygonRgn: %d polygons\n", nbpolygons );
 
       /* Allocate points array */
 
@@ -541,6 +527,47 @@
 
 
 /***********************************************************************
+ *           REGION_CopyRegion
+ *
+ * Copy region src into dest.
+ */
+static int REGION_CopyRegion( RGNOBJ *src, RGNOBJ *dest )
+{
+    if (dest->region.pixmap) XFreePixmap( display, dest->region.pixmap );
+    dest->region.type   = src->region.type;
+    dest->region.box    = src->region.box;
+    dest->region.pixmap = 0;
+    if (src->region.xrgn)  /* Copy only the X region */
+    {
+        Region tmprgn = XCreateRegion();
+        if (!dest->region.xrgn) dest->region.xrgn = XCreateRegion();
+        XUnionRegion( tmprgn, src->region.xrgn, dest->region.xrgn );
+        XDestroyRegion( tmprgn );
+    }
+    else  /* Copy the pixmap (if any) */
+    {
+        if (dest->region.xrgn)
+        {
+            XDestroyRegion( dest->region.xrgn );
+            dest->region.xrgn = 0;
+        }
+        if (src->region.pixmap)
+        {
+            int width = src->region.box.right - src->region.box.left;
+            int height = src->region.box.bottom - src->region.box.top;
+            
+            dest->region.pixmap = XCreatePixmap( display, rootWindow,
+                                                 width, height, 1 );
+            XSetFunction( display, regionGC, GXcopy );
+            XCopyArea( display, src->region.pixmap, dest->region.pixmap,
+                       regionGC, 0, 0, width, height, 0, 0 );
+        }
+    }
+    return dest->region.type;
+}
+
+
+/***********************************************************************
  *           CombineRgn    (GDI.451)
  */
 int CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, short mode )
@@ -550,20 +577,20 @@
     int width, height;
     BOOL res;
     
-#ifdef DEBUG_REGION
-    printf( "CombineRgn: %d %d %d %d\n", hDest, hSrc1, hSrc2, mode );
-#endif
+    dprintf_region(stddeb, "CombineRgn: %d %d %d %d\n", 
+		   hDest, hSrc1, hSrc2, mode );
     
     if (!(destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC )))
 	return ERROR;
     if (!(src1Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc1, REGION_MAGIC )))
 	return ERROR;
-    if (mode != RGN_COPY)
-	if (!(src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC )))
-	    return ERROR;
+    if (mode == RGN_COPY) return REGION_CopyRegion( src1Obj, destObj );
+
+    if (!(src2Obj = (RGNOBJ *) GDI_GetObjPtr( hSrc2, REGION_MAGIC )))
+        return ERROR;
     region = &destObj->region;
 
-    if (src1Obj->region.xrgn && ((mode == RGN_COPY) || src2Obj->region.xrgn))
+    if (src1Obj->region.xrgn && src2Obj->region.xrgn)
     {
 	/* Perform the operation with X regions */
 
@@ -588,18 +615,12 @@
 	    XSubtractRegion( src1Obj->region.xrgn, src2Obj->region.xrgn,
 			     region->xrgn );
 	    break;
-	case RGN_COPY:
-	    {
-		Region tmprgn = XCreateRegion();
-		XUnionRegion( tmprgn, src1Obj->region.xrgn, region->xrgn );
-		XDestroyRegion( tmprgn );
-	    }
-	    break;
 	default:
 	    return ERROR;
 	}
 	if (XEmptyRegion(region->xrgn))
 	{
+            XDestroyRegion( region->xrgn );
 	    region->type = NULLREGION;
 	    region->xrgn = 0;
 	    return NULLREGION;
@@ -620,7 +641,7 @@
     {
 	if (!src1Obj->region.pixmap)
 	    if (!REGION_MakePixmap( &src1Obj->region )) return ERROR;
-	if ((mode != RGN_COPY) && !src2Obj->region.pixmap)
+	if (!src2Obj->region.pixmap)
 	    if (!REGION_MakePixmap( &src2Obj->region )) return ERROR;
     }
     
@@ -646,12 +667,6 @@
 	region->type = COMPLEXREGION;
 	break;
 
-      case RGN_COPY:
-	region->box  = src1Obj->region.box;
-	region->type = src1Obj->region.type;
-	res = (region->type != NULLREGION);
-	break;
-
       default:
 	return ERROR;
     }
@@ -670,8 +685,8 @@
     height = region->box.bottom - region->box.top;
     if (!width || !height)
     {
-	printf( "CombineRgn: width or height is 0. Please report this.\n" );
-	printf( "src1=%d,%d-%d,%d  src2=%d,%d-%d,%d  dst=%d,%d-%d,%d  op=%d\n",
+	fprintf(stderr, "CombineRgn: width or height is 0. Please report this.\n" );
+	fprintf(stderr, "src1=%d,%d-%d,%d  src2=%d,%d-%d,%d  dst=%d,%d-%d,%d  op=%d\n",
 	        src1Obj->region.box.left, src1Obj->region.box.top,
 	        src1Obj->region.box.right, src1Obj->region.box.bottom,
 	        src2Obj->region.box.left, src2Obj->region.box.top,
@@ -711,12 +726,6 @@
 	  XSetFunction( display, regionGC, GXandInverted );
 	  REGION_CopyIntersection( region, &src2Obj->region );
 	  break;
-	  
-      case RGN_COPY:
-	  XSetFunction( display, regionGC, GXcopy );
-	  XCopyArea( display, src1Obj->region.pixmap, region->pixmap,
-		     regionGC, 0, 0, width, height, 0, 0 );
-	  break;
     }
     return region->type;
 }
diff --git a/objects/text.c b/objects/text.c
index 10a6a75..95b2eb7 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -1,15 +1,20 @@
 /*
  * text functions
  *
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1993, 1994 Alexandre Julliard
  */
 
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993, 1994";
 
+#include <stdlib.h>
 #include <X11/Xatom.h>
 #include "windows.h"
 #include "gdi.h"
 #include "metafile.h"
+#include "stddebug.h"
+/* #define DEBUG_TEXT /* */
+/* #undef  DEBUG_TEXT /* */
+#include "debug.h"
 
 #define TAB     9
 #define LF     10
@@ -17,6 +22,8 @@
 #define SPACE  32
 #define PREFIX 38
 
+#define SWAP_INT(a,b)  { int t = a; a = b; b = t; }
+
 static int tabstop = 8;
 static int tabwidth;
 static int spacewidth;
@@ -182,10 +189,8 @@
     int x = rect->left, y = rect->top;
     int width = rect->right - rect->left;
 
-#ifdef DEBUG_TEXT
-    printf( "DrawText: '%s', %d , [(%d,%d),(%d,%d)]\n", str, count,
+    dprintf_text(stddeb,"DrawText: '%s', %d , [(%d,%d),(%d,%d)]\n", str, count,
 	   rect->left, rect->top, rect->right, rect->bottom);
-#endif
 
     if (count == -1) count = strlen(str);
     strPtr = str;
@@ -232,7 +237,9 @@
 	    else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
 	}
 	if (!(flags & DT_CALCRECT))
-	    if (!TextOut(hdc, x, y, line, len)) return 0;
+	    if (!ExtTextOut( hdc, x, y, (flags & DT_NOCLIP) ? 0 : ETO_CLIPPED,
+                             rect, line, len, NULL )) return 0;
+
 	if (prefix_offset != -1)
 	{
 	    HPEN hpen = CreatePen( PS_SOLID, 1, GetTextColor(hdc) );
@@ -260,41 +267,67 @@
 
 
 /***********************************************************************
- *           TextOut    (GDI.33)
+ *           ExtTextOut    (GDI.351)
  */
-BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
+BOOL ExtTextOut( HDC hdc, short x, short y, WORD flags, LPRECT lprect,
+                 LPSTR str, WORD count, LPINT lpDx )
 {
     int dir, ascent, descent, i;
     XCharStruct info;
     XFontStruct *font;
+    RECT rect;
 
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) 
     {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC );
 	if (!dc) return FALSE;
-	MF_TextOut(dc, x, y, str, count);
+	MF_TextOut( dc, x, y, str, count );
 	return TRUE;
     }
 
     if (!DC_SetupGCForText( dc )) return TRUE;
     font = dc->u.x.font.fstruct;
 
+    dprintf_text(stddeb,"ExtTextOut: %d,%d '%s', %d  flags=%d rect=%d,%d,%d,%d\n",
+            x, y, str, count, flags,
+            lprect->left, lprect->top, lprect->right, lprect->bottom );
+
+      /* Setup coordinates */
+
     if (dc->w.textAlign & TA_UPDATECP)
     {
 	x = dc->w.CursPosX;
 	y = dc->w.CursPosY;
     }
-#ifdef DEBUG_TEXT
-    printf( "TextOut: %d,%d '%s', %d\n", x, y, str, count );
-#endif
     x = XLPTODP( dc, x );
     y = YLPTODP( dc, y );
+    if (flags & (ETO_OPAQUE | ETO_CLIPPED))  /* There's a rectangle */
+    {
+        rect.left   = XLPTODP( dc, lprect->left );
+        rect.right  = XLPTODP( dc, lprect->right );
+        rect.top    = YLPTODP( dc, lprect->top );
+        rect.bottom = YLPTODP( dc, lprect->bottom );
+        if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
+        if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
+    }
+
+      /* Draw the rectangle */
+
+    if (flags & ETO_OPAQUE)
+    {
+        XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
+        XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                        dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
+                        rect.right-rect.left, rect.bottom-rect.top );
+    }
+    if (!count) return TRUE;  /* Nothing more to do */
+
+      /* Compute text starting position */
 
     XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
     info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
-
-      /* Compute starting position */
+    if (lpDx) for (i = 0; i < count; i++) info.width += lpDx[i];
 
     switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
     {
@@ -322,52 +355,75 @@
 	  break;
     }
 
-      /* Draw text */
+      /* Set the clip region */
 
-    if (!dc->w.charExtra && !dc->w.breakExtra)
+    if (flags & ETO_CLIPPED)
     {
-	if (dc->w.backgroundMode == TRANSPARENT)
-	    XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc, 
-			 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
-	else
-	    XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			      dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
+        SaveVisRgn( hdc );
+        IntersectVisRect( hdc, rect.left, rect.top, rect.right, rect.bottom );
     }
-    else
+
+      /* Draw the text background if necessary */
+
+    if (dc->w.backgroundMode != TRANSPARENT)
     {
-	char * p = str;
-	int xchar = x;
-	for (i = 0; i < count; i++, p++)
-	{
-	    XCharStruct * charStr;
-	    unsigned char ch = *p;
-	    int extraWidth;
-	    
-	    if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
-		ch = font->default_char;
-	    if (!font->per_char) charStr = &font->min_bounds;
-	    else charStr = font->per_char + ch - font->min_char_or_byte2;
+          /* If rectangle is opaque and clipped, do nothing */
+        if (!(flags & ETO_CLIPPED) || !(flags & ETO_OPAQUE))
+        {
+              /* Only draw if rectangle is not opaque or if some */
+              /* text is outside the rectangle */
+            if (!(flags & ETO_OPAQUE) ||
+                (x < rect.left) ||
+                (x + info.width >= rect.right) ||
+                (y-font->ascent < rect.top) ||
+                (y+font->descent >= rect.bottom))
+            {
+                XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
+                XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                                dc->w.DCOrgX + x,
+                                dc->w.DCOrgY + y - font->ascent,
+                                info.width,
+                                font->ascent + font->descent );
+            }
+        }
+    }
+    
+      /* Draw the text */
 
-	    extraWidth = dc->w.charExtra;
-	    if (ch == dc->u.x.font.metrics.tmBreakChar)
-		extraWidth += dc->w.breakExtra;
+    XSetForeground( display, dc->u.x.gc, dc->w.textPixel );
+    if (!dc->w.charExtra && !dc->w.breakExtra && !lpDx)
+    {
+        XDrawString( display, dc->u.x.drawable, dc->u.x.gc, 
+                     dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
+    }
+    else  /* Now the fun begins... */
+    {
+        XTextItem *items, *pitem;
 
-	    if (dc->w.backgroundMode == TRANSPARENT)
-		XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			     dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
-	    else
-	    {
-		XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-				  dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
-		XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
-		XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			        dc->w.DCOrgX + xchar + charStr->width,
-			        dc->w.DCOrgY + y - font->ascent,
-			        extraWidth, font->ascent + font->descent );
-		XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
-	    }
-	    xchar += charStr->width + extraWidth;
-	}
+        items = malloc( count * sizeof(XTextItem) );
+        for (i = 0, pitem = items; i < count; i++, pitem++)
+        {
+            pitem->chars  = str + i;
+            pitem->nchars = 1;
+            pitem->font   = None;
+            if (i == 0)
+            {
+                pitem->delta = 0;
+                continue;  /* First iteration -> no delta */
+            }
+            pitem->delta = dc->w.charExtra;
+            if (str[i] == dc->u.x.font.metrics.tmBreakChar)
+                pitem->delta += dc->w.breakExtra;
+            if (lpDx)
+            {
+                INT width;
+                GetCharWidth( hdc, str[i], str[i], &width );
+                pitem->delta += lpDx[i-1] - width;
+            }
+        }
+        XDrawText( display, dc->u.x.drawable, dc->u.x.gc,
+                   dc->w.DCOrgX + x, dc->w.DCOrgY + y, items, count );
+        free( items );
     }
 
       /* Draw underline and strike-out if needed */
@@ -380,9 +436,9 @@
 	if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
 	    lineWidth = 0;
 	else if (lineWidth == 1) lineWidth = 0;
-	XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
+	XSetLineAttributes( display, dc->u.x.gc, lineWidth,
 			    LineSolid, CapRound, JoinBevel ); 
-	XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
+        XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
 		   dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
 		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
     }
@@ -393,16 +449,26 @@
 	    lineAscent = font->ascent / 3;
 	if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
 	    lineDescent = -lineAscent;
-	XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
+	XSetLineAttributes( display, dc->u.x.gc, lineAscent + lineDescent,
 			    LineSolid, CapRound, JoinBevel ); 
-	XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
+	XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
 		   dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
 		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
     }
-    
+    if (flags & ETO_CLIPPED) RestoreVisRgn( hdc );
     return TRUE;
 }
 
+
+/***********************************************************************
+ *           TextOut    (GDI.33)
+ */
+BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
+{
+    return ExtTextOut( hdc, x, y, 0, NULL, str, count, NULL );
+}
+
+
 /***********************************************************************
  *		GrayString (USER.185)
  */
@@ -425,6 +491,7 @@
 	}
 }
 
+
 /***********************************************************************
  *			TabbedTextOut		[USER.196]
  */
@@ -432,7 +499,7 @@
 		short nTabCount, LPINT lpTabPos, short nTabOrg)
 {
 	WORD 	width, height;
-	printf("EMPTY STUB !!! TabbedTextOut(); ! call TextOut() for now !\n");
+	dprintf_text(stdnimp,"EMPTY STUB !!! TabbedTextOut(); ! call TextOut() for now !\n");
 	height = HIWORD(GetTextExtent(hDC, lpStr, nCount));
 	width = LOWORD(GetTextExtent(hDC, lpStr, nCount));
 	TextOut(hDC, x, y, lpStr, nCount);
@@ -441,23 +508,12 @@
 
 
 /***********************************************************************
- *			ExtTextOut			[GDI.351]
- */
-BOOL ExtTextOut(HDC hDC, short x, short y, WORD wOptions, LPRECT lprect,
-			LPSTR str, WORD count, LPINT lpDx)
-{
-	printf("EMPTY STUB !!! ExtTextOut(); ! call TextOut() for now !\n");
-	TextOut(hDC, x, y, str, count);
-	return FALSE;
-}
-
-/***********************************************************************
  *			GetTabbedTextExtent		[USER.197]
  */
 DWORD GetTabbedTextExtent(HDC hDC, LPSTR lpString, int nCount, 
 	int nTabPositions, LPINT lpnTabStopPositions)
 {
-	printf("EMPTY STUB !!! GetTabbedTextExtent(); !\n");
+	dprintf_text(stdnimp,"EMPTY STUB !!! GetTabbedTextExtent(); !\n");
 
 	return (18 << 16) | (nCount * 18);
 }