Release 970202

Sun Feb  2 12:31:03 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Fixed SetCurrentDirectory() to also change the current drive.

	* [win32/except.c] [tools/build.c]
	Use Win32 register functions to implement exception handling.
	Fixed UnhandledExceptionFilter.

Fri Jan 31 15:42:41  1997  David Faure  <david.faure@ihamy.insa-lyon.fr>

	* [windows/keyboard.c]
	Added KEYBOARD_GenerateMsg to generate Caps Lock and NumLock events
	Added calls to KEYBOARD_GenerateMsg when the key is pressed/released
	or when the state has changed, out of wine.
	Changed type 3-state 'ToggleKeyState' to boolean. The On/Off is given
	by InputKeyStateTable.

Wed Jan 29 21:53:04 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/*resource.c][if1632/thunk.c]
	EnumResource* added.

	* [loader/pe_resource.] [loader/resource.c]
	SizeofResource32(), LoadAccelerators32() added.

	* [misc/lstr.c]
	FormatMessage %n added.

	* [misc/crtdll.c][include/ctrdll.h][if1632/crtdll.spec]
	_chdrive,_errno,_isctype added.

	* [misc/cpu.c]
	Replaced runtime_cpu by GetSystemInfo().

	* [windows/hook.c][include/hook.h]
	Fixed mapping of hooks to win32/unicode.

	* [windows/keyboard.c] [windows/defwnd.c]
	Updated to win32 standard.
	ALT-<Menukey> fixed.

	* [windows/queue.c]
	GetWindowThreadProcessId() implemented.

Mon Jan 27 16:42:49 1997  John Harvey <john@division.co.uk>

	* [graphics/metafiledrv/*] [graphics/x11drv/*]
	  [objects/bitmap.c] [objects/brush.c] [objects/font.c]
	  [objects/gdiobj.c] [objects/pen.c]
	Moved SelectObject to graphics drivers. Printer support now works
	in a few cases but is definitely not complete. Generic/text driver
	works. The postscript driver works if true type fonts are disabled
	from the control panel. To enable printer support add Printer=on
	to the wine section of your wine.conf file. This causes write not
	to work properly. I know that several other printer drivers do not
	work.

	* [tools/build.c]
	Make .stabs not used for svr4 since it doesn't use GNU assembler.

	* [misc/fontengine.c]
	Make sure a printf doesn't crash the system.

Sat Jan 25 15:53:35 1997  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c]
	Fixed some problems with PlayMetaFileRecord().

	* [objects/dc.c]
	hClipRgn gets initialized in GetDCState().

Fri Jan 24 21:22:26 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [debugger/stabs.c]
	Handle file names beginning with '/'.

Fri Jan 24 18:33:04 1997  Robert Pouliot <krynos@clic.net>

	* [*/*]
	Some more patches for OS/2 support.

Fri Jan 24 11:30:41 1997  Bang Jun-Young  <bangjy@nownuri.nowcom.co.kr>

	* [resources/sysres_Ko.rc]
	Updated support for Korean (Ko) language.
diff --git a/graphics/metafiledrv/Makefile.in b/graphics/metafiledrv/Makefile.in
index 5246a6c..ff538f2 100644
--- a/graphics/metafiledrv/Makefile.in
+++ b/graphics/metafiledrv/Makefile.in
@@ -10,6 +10,7 @@
 	graphics.c \
 	init.c \
 	mapping.c \
+	objects.c \
 	text.c
 
 all: $(MODULE).o
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index 6545c9e..08dac5d 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -52,7 +52,7 @@
     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
     NULL,                            /* pSelectClipRgn */
-    NULL,                            /* pSelectObject */
+    MFDRV_SelectObject,              /* pSelectObject */
     NULL,                            /* pSelectPalette */
     NULL,                            /* pSetBkColor */
     NULL,                            /* pSetBkMode */
diff --git a/graphics/metafiledrv/objects.c b/graphics/metafiledrv/objects.c
new file mode 100644
index 0000000..2c1aa22
--- /dev/null
+++ b/graphics/metafiledrv/objects.c
@@ -0,0 +1,104 @@
+/*
+ * GDI objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "bitmap.h"
+#include "brush.h"
+#include "font.h"
+#include "metafile.h"
+#include "metafiledrv.h"
+#include "pen.h"
+#include "stddebug.h"
+#include "debug.h"
+
+
+/***********************************************************************
+ *           MFDRV_BITMAP_SelectObject
+ */
+static HBITMAP16 MFDRV_BITMAP_SelectObject( DC * dc, HBITMAP16 hbitmap,
+                                            BITMAPOBJ * bmp )
+{
+    return 0;
+}
+
+
+/***********************************************************************
+ *           MFDRV_BRUSH_SelectObject
+ */
+static HBRUSH32 MFDRV_BRUSH_SelectObject( DC * dc, HBRUSH32 hbrush,
+                                          BRUSHOBJ * brush )
+{
+    LOGBRUSH16 logbrush = { brush->logbrush.lbStyle,
+                            brush->logbrush.lbColor,
+                            brush->logbrush.lbHatch };
+    switch (brush->logbrush.lbStyle)
+    {
+    case BS_SOLID:
+    case BS_HATCHED:
+    case BS_HOLLOW:
+        if (!MF_CreateBrushIndirect( dc, hbrush, &logbrush )) return 0;
+        break;
+    case BS_PATTERN:
+    case BS_DIBPATTERN:
+        if (!MF_CreatePatternBrush( dc, hbrush, &logbrush )) return 0;
+        break;
+    }
+    return 1;  /* FIXME? */
+}
+
+
+/***********************************************************************
+ *           MFDRV_FONT_SelectObject
+ */
+static HFONT16 MFDRV_FONT_SelectObject( DC * dc, HFONT16 hfont,
+                                        FONTOBJ * font )
+{
+    HFONT16 prevHandle = dc->w.hFont;
+    if (MF_CreateFontIndirect(dc, hfont, &(font->logfont))) return prevHandle;
+    return 0;
+}
+
+
+/***********************************************************************
+ *           MFDRV_PEN_SelectObject
+ */
+static HPEN32 MFDRV_PEN_SelectObject( DC * dc, HPEN32 hpen, PENOBJ * pen )
+{
+    HPEN32 prevHandle = dc->w.hPen;
+    LOGPEN16 logpen = { pen->logpen.lopnStyle,
+                        { pen->logpen.lopnWidth.x, pen->logpen.lopnWidth.y },
+                        pen->logpen.lopnColor };
+    if (MF_CreatePenIndirect( dc, hpen, &logpen )) return prevHandle;
+    return 0;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectObject
+ */
+HGDIOBJ32 MFDRV_SelectObject( DC *dc, HGDIOBJ32 handle )
+{
+    GDIOBJHDR * ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+
+    if (!ptr) return 0;
+    dprintf_gdi(stddeb, "SelectObject: hdc=%04x %04x\n", dc->hSelf, handle );
+    
+    switch(ptr->wMagic)
+    {
+      case PEN_MAGIC:
+	  return MFDRV_PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
+      case BRUSH_MAGIC:
+	  return MFDRV_BRUSH_SelectObject( dc, handle, (BRUSHOBJ *)ptr );
+      case BITMAP_MAGIC:
+	  return MFDRV_BITMAP_SelectObject( dc, handle, (BITMAPOBJ *)ptr );
+      case FONT_MAGIC:
+	  return MFDRV_FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );	  
+      case REGION_MAGIC:
+	  return (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
+    }
+    return 0;
+}
diff --git a/graphics/x11drv/Makefile.in b/graphics/x11drv/Makefile.in
index 1fd36db..9001dad 100644
--- a/graphics/x11drv/Makefile.in
+++ b/graphics/x11drv/Makefile.in
@@ -7,10 +7,14 @@
 
 C_SRCS = \
 	bitblt.c \
+	bitmap.c \
+	brush.c \
 	clipping.c \
 	font.c \
 	graphics.c \
 	init.c \
+	objects.c \
+	pen.c \
 	text.c
 
 all: $(MODULE).o
diff --git a/graphics/x11drv/bitmap.c b/graphics/x11drv/bitmap.c
new file mode 100644
index 0000000..d0cc825
--- /dev/null
+++ b/graphics/x11drv/bitmap.c
@@ -0,0 +1,81 @@
+/*
+ * GDI bitmap objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "gdi.h"
+#include "callback.h"
+#include "dc.h"
+#include "bitmap.h"
+#include "heap.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           X11DRV_BITMAP_Init
+ */
+BOOL32 X11DRV_BITMAP_Init(void)
+{
+    Pixmap tmpPixmap;
+    
+      /* Create the necessary GCs */
+    
+    if ((tmpPixmap = XCreatePixmap( display, rootWindow, 1, 1, 1 )))
+    {
+	BITMAP_monoGC = XCreateGC( display, tmpPixmap, 0, NULL );
+	XSetGraphicsExposures( display, BITMAP_monoGC, False );
+	XFreePixmap( display, tmpPixmap );
+    }
+
+    if (screenDepth != 1)
+    {
+	if ((tmpPixmap = XCreatePixmap(display, rootWindow, 1,1,screenDepth)))
+	{
+	    BITMAP_colorGC = XCreateGC( display, tmpPixmap, 0, NULL );
+	    XSetGraphicsExposures( display, BITMAP_colorGC, False );
+	    XFreePixmap( display, tmpPixmap );
+	}
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           X11DRV_BITMAP_SelectObject
+ */
+HBITMAP32 X11DRV_BITMAP_SelectObject( DC * dc, HBITMAP32 hbitmap,
+                                      BITMAPOBJ * bmp )
+{
+    HRGN32 hrgn;
+    HBITMAP32 prevHandle = dc->w.hBitmap;
+    
+    if (!(dc->w.flags & DC_MEMORY)) return 0;
+
+    if (dc->w.hVisRgn)
+       SetRectRgn(dc->w.hVisRgn, 0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight );
+    else
+    { 
+       hrgn = CreateRectRgn32(0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
+       if (!hrgn) return 0;
+       dc->w.hVisRgn    = hrgn;
+    }
+
+    dc->u.x.drawable = bmp->pixmap;
+    dc->w.hBitmap    = hbitmap;
+
+      /* Change GC depth if needed */
+
+    if (dc->w.bitsPerPixel != bmp->bitmap.bmBitsPixel)
+    {
+	XFreeGC( display, dc->u.x.gc );
+	dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
+	dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
+        DC_InitDC( dc );
+    }
+    else CLIPPING_UpdateGCRegion( dc );  /* Just update GC clip region */
+    return prevHandle;
+}
diff --git a/graphics/x11drv/brush.c b/graphics/x11drv/brush.c
new file mode 100644
index 0000000..62bc41f
--- /dev/null
+++ b/graphics/x11drv/brush.c
@@ -0,0 +1,270 @@
+/*
+ * GDI brush objects
+ *
+ * Copyright 1993, 1994  Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include "brush.h"
+#include "bitmap.h"
+#include "color.h"
+#include "x11drv.h"
+#include "stddebug.h"
+#include "debug.h"
+
+static const char HatchBrushes[NB_HATCH_STYLES][8] =
+{
+    { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HS_HORIZONTAL */
+    { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HS_VERTICAL   */
+    { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HS_FDIAGONAL  */
+    { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HS_BDIAGONAL  */
+    { 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HS_CROSS      */
+    { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }  /* HS_DIAGCROSS  */
+};
+
+  /* Levels of each primary for dithering */
+#define PRIMARY_LEVELS  3  
+#define TOTAL_LEVELS    (PRIMARY_LEVELS*PRIMARY_LEVELS*PRIMARY_LEVELS)
+
+ /* Dithering matrix size  */
+#define MATRIX_SIZE     8
+#define MATRIX_SIZE_2   (MATRIX_SIZE*MATRIX_SIZE)
+
+  /* Total number of possible levels for a dithered primary color */
+#define DITHER_LEVELS   (MATRIX_SIZE_2 * (PRIMARY_LEVELS-1) + 1)
+
+  /* Dithering matrix */
+static const int dither_matrix[MATRIX_SIZE_2] =
+{
+     0, 32,  8, 40,  2, 34, 10, 42,
+    48, 16, 56, 24, 50, 18, 58, 26,
+    12, 44,  4, 36, 14, 46,  6, 38,
+    60, 28, 52, 20, 62, 30, 54, 22,
+     3, 35, 11, 43,  1, 33,  9, 41,
+    51, 19, 59, 27, 49, 17, 57, 25,
+    15, 47,  7, 39, 13, 45,  5, 37,
+    63, 31, 55, 23, 61, 29, 53, 21
+};
+
+  /* Mapping between (R,G,B) triples and EGA colors */
+static const int EGAmapping[TOTAL_LEVELS] =
+{
+    0,  /* 000000 -> 000000 */
+    4,  /* 00007f -> 000080 */
+    12, /* 0000ff -> 0000ff */
+    2,  /* 007f00 -> 008000 */
+    6,  /* 007f7f -> 008080 */
+    6,  /* 007fff -> 008080 */
+    10, /* 00ff00 -> 00ff00 */
+    6,  /* 00ff7f -> 008080 */
+    14, /* 00ffff -> 00ffff */
+    1,  /* 7f0000 -> 800000 */
+    5,  /* 7f007f -> 800080 */
+    5,  /* 7f00ff -> 800080 */
+    3,  /* 7f7f00 -> 808000 */
+    8,  /* 7f7f7f -> 808080 */
+    7,  /* 7f7fff -> c0c0c0 */
+    3,  /* 7fff00 -> 808000 */
+    7,  /* 7fff7f -> c0c0c0 */
+    7,  /* 7fffff -> c0c0c0 */
+    9,  /* ff0000 -> ff0000 */
+    5,  /* ff007f -> 800080 */
+    13, /* ff00ff -> ff00ff */
+    3,  /* ff7f00 -> 808000 */
+    7,  /* ff7f7f -> c0c0c0 */
+    7,  /* ff7fff -> c0c0c0 */
+    11, /* ffff00 -> ffff00 */
+    7,  /* ffff7f -> c0c0c0 */
+    15  /* ffffff -> ffffff */
+};
+
+#define PIXEL_VALUE(r,g,b) \
+    COLOR_mapEGAPixel[EGAmapping[((r)*PRIMARY_LEVELS+(g))*PRIMARY_LEVELS+(b)]]
+
+  /* X image for building dithered pixmap */
+static XImage *ditherImage = NULL;
+
+
+/***********************************************************************
+ *           BRUSH_Init
+ *
+ * Create the X image used for dithering.
+ */
+BOOL32 X11DRV_BRUSH_Init(void)
+{
+    XCREATEIMAGE( ditherImage, MATRIX_SIZE, MATRIX_SIZE, screenDepth );
+    return (ditherImage != NULL);
+}
+
+
+/***********************************************************************
+ *           BRUSH_DitherColor
+ */
+static Pixmap BRUSH_DitherColor( DC *dc, COLORREF color )
+{
+    static COLORREF prevColor = 0xffffffff;
+    unsigned int x, y;
+    Pixmap pixmap;
+
+    if (color != prevColor)
+    {
+	int r = GetRValue( color ) * DITHER_LEVELS;
+	int g = GetGValue( color ) * DITHER_LEVELS;
+	int b = GetBValue( color ) * DITHER_LEVELS;
+	const int *pmatrix = dither_matrix;
+
+	for (y = 0; y < MATRIX_SIZE; y++)
+	{
+	    for (x = 0; x < MATRIX_SIZE; x++)
+	    {
+		int d  = *pmatrix++ * 256;
+		int dr = ((r + d) / MATRIX_SIZE_2) / 256;
+		int dg = ((g + d) / MATRIX_SIZE_2) / 256;
+		int db = ((b + d) / MATRIX_SIZE_2) / 256;
+		XPutPixel( ditherImage, x, y, PIXEL_VALUE(dr,dg,db) );
+	    }
+	}
+	prevColor = color;
+    }
+    
+    pixmap = XCreatePixmap( display, rootWindow,
+			    MATRIX_SIZE, MATRIX_SIZE, screenDepth );
+    XPutImage( display, pixmap, BITMAP_colorGC, ditherImage, 0, 0,
+	       0, 0, MATRIX_SIZE, MATRIX_SIZE );
+    return pixmap;
+}
+
+
+/***********************************************************************
+ *           BRUSH_SelectSolidBrush
+ */
+static void BRUSH_SelectSolidBrush( DC *dc, COLORREF color )
+{
+    if ((dc->w.bitsPerPixel > 1) && (screenDepth <= 8) && !COLOR_IsSolid( color ))
+    {
+	  /* Dithered brush */
+	dc->u.x.brush.pixmap = BRUSH_DitherColor( dc, color );
+	dc->u.x.brush.fillStyle = FillTiled;
+	dc->u.x.brush.pixel = 0;
+    }
+    else
+    {
+	  /* Solid brush */
+	dc->u.x.brush.pixel = COLOR_ToPhysical( dc, color );
+	dc->u.x.brush.fillStyle = FillSolid;
+    }
+}
+
+
+/***********************************************************************
+ *           BRUSH_SelectPatternBrush
+ */
+static BOOL32 BRUSH_SelectPatternBrush( DC * dc, HBITMAP32 hbitmap )
+{
+    BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    if (!bmp) return FALSE;
+    dc->u.x.brush.pixmap = XCreatePixmap( display, rootWindow,
+					  8, 8, bmp->bitmap.bmBitsPixel );
+    XCopyArea( display, bmp->pixmap, dc->u.x.brush.pixmap,
+	       BITMAP_GC(bmp), 0, 0, 8, 8, 0, 0 );
+    
+    if (bmp->bitmap.bmBitsPixel > 1)
+    {
+	dc->u.x.brush.fillStyle = FillTiled;
+	dc->u.x.brush.pixel = 0;  /* Ignored */
+    }
+    else
+    {
+	dc->u.x.brush.fillStyle = FillOpaqueStippled;
+	dc->u.x.brush.pixel = -1;  /* Special case (see DC_SetupGCForBrush) */
+    }
+    return TRUE;
+}
+
+
+
+
+/***********************************************************************
+ *           BRUSH_SelectObject
+ */
+HBRUSH32 X11DRV_BRUSH_SelectObject( DC * dc, HBRUSH32 hbrush, BRUSHOBJ * brush )
+{
+    HBITMAP16 hBitmap;
+    BITMAPINFO * bmpInfo;
+    HBRUSH16 prevHandle = dc->w.hBrush;
+
+    dprintf_gdi(stddeb, "Brush_SelectObject: hdc=%04x hbrush=%04x\n",
+                dc->hSelf,hbrush);
+#ifdef NOTDEF
+    if (dc->header.wMagic == METAFILE_DC_MAGIC)
+    {
+        LOGBRUSH16 logbrush = { brush->logbrush.lbStyle,
+                                brush->logbrush.lbColor,
+                                brush->logbrush.lbHatch };
+	switch (brush->logbrush.lbStyle)
+	{
+	case BS_SOLID:
+	case BS_HATCHED:
+	case BS_HOLLOW:
+	    if (!MF_CreateBrushIndirect( dc, hbrush, &logbrush )) return 0;
+	    break;
+	case BS_PATTERN:
+	case BS_DIBPATTERN:
+	    if (!MF_CreatePatternBrush( dc, hbrush, &logbrush )) return 0;
+	    break;
+	}
+	return 1;  /* FIXME? */
+    }
+#endif    
+    dc->w.hBrush = hbrush;
+
+    if (dc->u.x.brush.pixmap)
+    {
+	XFreePixmap( display, dc->u.x.brush.pixmap );
+	dc->u.x.brush.pixmap = 0;
+    }
+    dc->u.x.brush.style = brush->logbrush.lbStyle;
+    
+    switch(brush->logbrush.lbStyle)
+    {
+      case BS_NULL:
+	dprintf_gdi( stddeb,"BS_NULL\n" );
+	break;
+
+      case BS_SOLID:
+        dprintf_gdi( stddeb,"BS_SOLID\n" );
+	BRUSH_SelectSolidBrush( dc, brush->logbrush.lbColor );
+	break;
+	
+      case BS_HATCHED:
+	dprintf_gdi( stddeb, "BS_HATCHED\n" );
+	dc->u.x.brush.pixel = COLOR_ToPhysical( dc, brush->logbrush.lbColor );
+	dc->u.x.brush.pixmap = XCreateBitmapFromData( display, rootWindow,
+				 HatchBrushes[brush->logbrush.lbHatch], 8, 8 );
+	dc->u.x.brush.fillStyle = FillStippled;
+	break;
+	
+      case BS_PATTERN:
+	dprintf_gdi( stddeb, "BS_PATTERN\n");
+	BRUSH_SelectPatternBrush( dc, (HBRUSH16)brush->logbrush.lbHatch );
+	break;
+
+      case BS_DIBPATTERN:
+	dprintf_gdi( stddeb, "BS_DIBPATTERN\n");
+	if ((bmpInfo = (BITMAPINFO *) GlobalLock16( (HGLOBAL16)brush->logbrush.lbHatch )))
+	{
+	    int size = DIB_BitmapInfoSize( bmpInfo, brush->logbrush.lbColor );
+	    hBitmap = CreateDIBitmap32( dc->hSelf, &bmpInfo->bmiHeader,
+                                        CBM_INIT, ((char *)bmpInfo) + size,
+                                        bmpInfo,
+                                        (WORD)brush->logbrush.lbColor );
+	    BRUSH_SelectPatternBrush( dc, hBitmap );
+	    DeleteObject16( hBitmap );
+	    GlobalUnlock16( (HGLOBAL16)brush->logbrush.lbHatch );	    
+	}
+	
+	break;
+    }
+    
+    return prevHandle;
+}
diff --git a/graphics/x11drv/font.c b/graphics/x11drv/font.c
index 4b816e2..a2f5151 100644
--- a/graphics/x11drv/font.c
+++ b/graphics/x11drv/font.c
@@ -4,9 +4,250 @@
  * Copyright 1996 Alexandre Julliard
  */
 
-#include "windows.h"
-#include "x11drv.h"
-#include "gdi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xatom.h>
+#include "font.h"
+#include "heap.h"
+#include "metafile.h"
+#include "options.h"
+#include "xmalloc.h"
+#include "stddebug.h"
+#include "debug.h"
+
+
+struct FontStructure {
+	char *window;
+	char *x11;
+} FontNames[32];
+int FontSize;
+
+
+/***********************************************************************
+ *           X11DRV_FONT_Init
+ */
+BOOL32 X11DRV_FONT_Init( void )
+{
+  char  temp[1024];
+  LPSTR ptr;
+  int i;
+
+  if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
+  {
+    for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
+      if( strcmp( ptr, "default" ) )
+	FontNames[i++].window = xstrdup( ptr );
+    FontSize = i;
+
+    for( i = 1; i < FontSize; i++ )
+    {
+        PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
+                                  temp, sizeof(temp) );
+        FontNames[i].x11 = xstrdup( temp );
+    }
+    PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
+    FontNames[0].x11 = xstrdup( temp );
+
+  } else {
+    FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
+    FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
+    FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
+    FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
+    FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
+    FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
+    FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
+    FontNames[7].window = "system"; FontNames[7].x11 = "*-helvetica";
+    FontSize = 8;
+  }
+  return TRUE;
+}
+/***********************************************************************
+ *           FONT_ChkX11Family
+ *
+ * returns a valid X11 equivalent if a Windows face name 
+ * is like a X11 family  - or NULL if translation is needed
+ */
+static char *FONT_ChkX11Family(char *winFaceName )
+{
+  static char x11fam[32+2];   /* will be returned */
+  int i;
+
+  for(i = 0; lpLogFontList[i] != NULL; i++)
+    if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
+    {
+	strcpy(x11fam,"*-");
+	return strcat(x11fam,winFaceName);
+    }    
+  return NULL;               /* a FONT_TranslateName() call is needed */
+}
+
+
+
+/***********************************************************************
+ *           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;
+
+  for (i = 1; i < FontSize; i ++)
+    if( !lstrcmpi32A( winFaceName, FontNames[i].window ) ) {
+      dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
+      return FontNames[i].x11;
+    }
+  return FontNames[0].x11;
+}
+
+
+/***********************************************************************
+ *           FONT_MatchFont
+ *
+ * Find a X font matching the logical font.
+ */
+static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
+{
+    char pattern[100];
+    const char *family, *weight, *charset;
+    char **names;
+    char slant, oldspacing, spacing;
+    int width, height, oldheight, count;
+    XFontStruct * fontStruct;
+    
+    dprintf_font(stddeb,
+	"FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
+	font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
+    weight = (font->lfWeight > 550) ? "bold" : "medium";
+    slant = font->lfItalic ? 'i' : 'r';
+    if (font->lfHeight == -1)
+	height = 0;
+    else
+	height = font->lfHeight * dc->vportExtX / dc->wndExtX;
+    if (height == 0) height = 120;  /* Default height = 12 */
+    else if (height < 0)
+    {
+        /* If height is negative, it means the height of the characters */
+        /* *without* the internal leading. So we adjust it a bit to     */
+        /* compensate. 5/4 seems to give good results for small fonts.  */
+	/* 
+         * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write 
+        height = 10 * (-height * 9 / 8);
+	 * may be we have to use an non linear function
+	*/
+	/* assume internal leading is 2 pixels. Else small fonts will become
+         * very small. */
+        height = (height-2) * -10; 
+    }
+    else height *= 10;
+    width  = 10 * (font->lfWidth * dc->vportExtY / dc->wndExtY);
+    if (width < 0) {
+	dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
+		      width, font->lfWidth );
+	width = -width;
+    }
+
+    spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
+	      (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
+    
+  
+    charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
+    if (*font->lfFaceName) {
+	family = FONT_ChkX11Family(font->lfFaceName);
+	/*--do _not_ translate if lfFaceName is family from X11  A.K.*/
+	if (!family) 
+	  family = FONT_TranslateName( font->lfFaceName );
+	/* FIX ME: I don't if that's correct but it works J.M. */
+	spacing = '*';
+	}
+    else switch(font->lfPitchAndFamily & 0xf0)
+    {
+    case FF_ROMAN:
+      family = FONT_TranslateName( "roman" );
+      break;
+    case FF_SWISS:
+      family = FONT_TranslateName( "swiss" );
+      break;
+    case FF_MODERN:
+      family = FONT_TranslateName( "modern" );
+      break;
+    case FF_SCRIPT:
+      family = FONT_TranslateName( "script" );
+      break;
+    case FF_DECORATIVE:
+      family = FONT_TranslateName( "decorative" );
+      break;
+    default:
+      family = "*-*";
+      break;
+    }
+    sprintf( pattern, "-%s-%s-*-normal-*-*-*-*-*-*-*-%s",
+	    family, weight, charset);
+    dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
+    names = XListFonts( display, pattern, 1, &count );
+    if (names) XFreeFontNames( names );
+    else
+    {
+        if (strcmp(family, "*-*") == 0)
+        {
+            fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
+            return NULL;
+        }
+        else family = "*-*";
+    }
+    oldheight = height;
+    oldspacing = spacing;
+    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",
+		      family, weight, slant, height, spacing, charset);
+	    else
+	      sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
+		      family, weight, slant, height, spacing, width, charset);
+	    dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
+	    names = XListFonts( display, pattern, 1, &count );
+	    if (count > 0) break;
+            if (spacing == 'm') /* try 'c' if no 'm' found */ {
+
+                spacing = 'c';
+                continue;
+            } else if (spacing == 'p') /* try '*' if no 'p' found */ {
+                spacing = '*';
+                continue;
+            }
+            spacing = oldspacing;
+            height -= 10;		
+            if (height < 10) {
+                if (slant == 'i') {
+		    /* try oblique if no italic font */
+		    slant = 'o';
+		    height = oldheight;
+		    continue;
+		}
+		if (spacing == 'm' && strcmp(family, "*-*") != 0) {
+		    /* If a fixed spacing font could not be found, ignore
+		     * the family */
+		    family = "*-*";
+		    height = oldheight;
+		    continue;
+		}
+                fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
+		return NULL;
+            }
+    }
+    dprintf_font(stddeb,"        Found '%s'\n", *names );
+    if (!*font->lfFaceName)
+        FONT_ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
+    /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
+
+    fontStruct = XLoadQueryFont( display, *names );
+    XFreeFontNames( names );
+    return fontStruct;
+}
+
 
 /***********************************************************************
  *           X11DRV_GetTextExtentPoint
@@ -62,4 +303,156 @@
 }
 
 
+/***********************************************************************
+ *           X11DRV_FONT_SelectObject
+ */
+HFONT32 X11DRV_FONT_SelectObject( DC * dc, HFONT32 hfont, FONTOBJ * font )
+{
+    static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
 
+    static struct {
+		HFONT32		id;
+		LOGFONT16	logfont;
+		int		access;
+		int		used;
+		X_PHYSFONT	cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
+    int 	i;
+
+    X_PHYSFONT * stockPtr;
+    HFONT32 prevHandle = dc->w.hFont;
+    XFontStruct * fontStruct;
+    dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
+
+#if 0 /* From the code in SelectObject, this can not happen */
+      /* Load font if necessary */
+    if (!font)
+    {
+	HFONT16 hnewfont;
+
+	hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
+			      FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
+			      DEFAULT_QUALITY, FF_DONTCARE, "*" );
+	font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
+    }
+#endif
+
+    if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
+	stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
+    else {
+	stockPtr = NULL;
+	/*
+	 * Ok, It's not a stock font but 
+	 * may be it's cached in dynamic cache
+	 */
+	for(i=0; i<FONTCACHE; i++) /* search for same handle */
+	     if (cacheFonts[i].id==hfont) { /* Got the handle */
+		/*
+		 * Check if Handle matches the font 
+		 */
+		if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
+			/* No: remove handle id from dynamic font cache */
+			cacheFonts[i].access=0;
+			cacheFonts[i].used=0;
+			cacheFonts[i].id=0;
+			/* may be there is an unused handle which contains the font */
+			for(i=0; i<FONTCACHE; i++) {
+				if((cacheFonts[i].used == 0) &&
+				  (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
+					/* got it load from cache and set new handle id */
+					stockPtr = &cacheFonts[i].cacheFont;
+					cacheFonts[i].access=1;
+					cacheFonts[i].used=1;
+					cacheFonts[i].id=hfont;
+					dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
+					break;
+					}
+				}
+	
+			}
+		else {
+			/* Yes: load from dynamic font cache */
+			stockPtr = &cacheFonts[i].cacheFont;
+			cacheFonts[i].access++;
+			cacheFonts[i].used++;
+			}
+		break;
+		}
+	}
+    if (!stockPtr || !stockPtr->fstruct)
+    {
+	if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
+        {
+              /* If it is not a stock font, we can simply return 0 */
+            if (!stockPtr) return 0;
+              /* Otherwise we must try to find a substitute */
+            dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
+            font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
+            font->logfont.lfPitchAndFamily |= FIXED_PITCH;
+            fontStruct = XLoadQueryFont( display, "fixed" );
+            if (!fontStruct)
+            {
+                fprintf( stderr, "No system font could be found. Please check your font path.\n" );
+                exit( 1 );
+            }
+        }
+    }
+    else
+    {
+	fontStruct = stockPtr->fstruct;
+	dprintf_font(stddeb,
+                     "FONT_SelectObject: Loaded font from cache %04x %p\n",
+		     hfont, fontStruct );
+    }	
+
+      /* Unuse previous font */
+	for (i=0; i < FONTCACHE; i++) {
+		if (cacheFonts[i].id == prevHandle) {
+			if(cacheFonts[i].used == 0)
+				fprintf(stderr, "Trying to decrement a use count of 0.\n");
+			else 
+				cacheFonts[i].used--;
+		}
+	}
+
+      /* Store font */
+    dc->w.hFont = hfont;
+    if (stockPtr)
+    {
+	if (!stockPtr->fstruct)
+	{
+	    stockPtr->fstruct = fontStruct;
+	    FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
+	}
+	memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
+    }
+    else
+    {
+	/* 
+	 * Check in cacheFont
+	 */
+	cacheFontsMin=NULL;
+	for (i=0; i < FONTCACHE; i++) {
+		if (cacheFonts[i].used==0) 
+			if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
+				cacheFontsMin=&cacheFonts[i];
+		}
+	if (!cacheFontsMin) {
+		fprintf(stderr,"No unused font cache entry !!!!\n" );
+		return prevHandle;
+	}
+	if (cacheFontsMin->id!=0) {
+		dprintf_font(stddeb,
+			"FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
+		XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
+		}
+	cacheFontsMin->cacheFont.fstruct = fontStruct;
+	FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
+	cacheFontsMin->access=1;
+	cacheFontsMin->used=1;
+	cacheFontsMin->id=hfont;
+	memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
+	memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
+
+    }
+    return prevHandle;
+}
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index a7fd361..6f34f63 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -52,7 +52,7 @@
     NULL,                            /* pScaleViewportExt (optional) */
     NULL,                            /* pScaleWindowExt (optional) */
     NULL,                            /* pSelectClipRgn */
-    NULL,                            /* pSelectObject */
+    X11DRV_SelectObject,             /* pSelectObject */
     NULL,                            /* pSelectPalette */
     NULL,                            /* pSetBkColor */
     NULL,                            /* pSetBkMode */
@@ -84,6 +84,18 @@
  */
 BOOL32 X11DRV_Init(void)
 {
+    /* Create default bitmap */
+
+    if (!X11DRV_BITMAP_Init()) return FALSE;
+
+    /* Initialize brush dithering */
+
+    if (!X11DRV_BRUSH_Init()) return FALSE;
+
+    /* Initialize fonts */
+
+    if (!X11DRV_FONT_Init()) return FALSE;
+
     return DRIVER_RegisterDriver( "DISPLAY", &X11DRV_Funcs );
 }
 
diff --git a/graphics/x11drv/objects.c b/graphics/x11drv/objects.c
new file mode 100644
index 0000000..fb2f0b8
--- /dev/null
+++ b/graphics/x11drv/objects.c
@@ -0,0 +1,50 @@
+/*
+ * GDI objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "bitmap.h"
+#include "brush.h"
+#include "font.h"
+#include "pen.h"
+#include "stddebug.h"
+#include "debug.h"
+
+
+extern HBITMAP32 X11DRV_BITMAP_SelectObject( DC * dc, HBITMAP32 hbitmap,
+                                             BITMAPOBJ * bmp );
+extern HBRUSH32 X11DRV_BRUSH_SelectObject( DC * dc, HBRUSH32 hbrush,
+                                           BRUSHOBJ * brush );
+extern HFONT32 X11DRV_FONT_SelectObject( DC * dc, HFONT32 hfont,
+                                         FONTOBJ * font );
+extern HPEN32 X11DRV_PEN_SelectObject( DC * dc, HPEN32 hpen, PENOBJ * pen );
+
+
+/***********************************************************************
+ *           X11DRV_SelectObject
+ */
+HGDIOBJ32 X11DRV_SelectObject( DC *dc, HGDIOBJ32 handle )
+{
+    GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+
+    if (!ptr) return 0;
+    dprintf_gdi(stddeb, "SelectObject: hdc=%04x %04x\n", dc->hSelf, handle );
+    
+    switch(ptr->wMagic)
+    {
+      case PEN_MAGIC:
+	  return X11DRV_PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
+      case BRUSH_MAGIC:
+	  return X11DRV_BRUSH_SelectObject( dc, handle, (BRUSHOBJ *)ptr );
+      case BITMAP_MAGIC:
+	  return X11DRV_BITMAP_SelectObject( dc, handle, (BITMAPOBJ *)ptr );
+      case FONT_MAGIC:
+	  return X11DRV_FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );	  
+      case REGION_MAGIC:
+	  return (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
+    }
+    return 0;
+}
diff --git a/graphics/x11drv/pen.c b/graphics/x11drv/pen.c
new file mode 100644
index 0000000..8516569
--- /dev/null
+++ b/graphics/x11drv/pen.c
@@ -0,0 +1,51 @@
+/*
+ * GDI pen objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#include "pen.h"
+#include "color.h"
+#include "stddebug.h"
+#include "debug.h"
+
+static const char PEN_dash[]       = { 5,3 };      /* -----   -----   -----  */
+static const char PEN_dot[]        = { 1,1 };      /* --  --  --  --  --  -- */
+static const char PEN_dashdot[]    = { 4,3,2,3 };  /* ----   --   ----   --  */
+static const char PEN_dashdotdot[] = { 4,2,2,2,2,2 }; /* ----  --  --  ----  */
+
+/***********************************************************************
+ *           PEN_SelectObject
+ */
+HPEN32 X11DRV_PEN_SelectObject( DC * dc, HPEN32 hpen, PENOBJ * pen )
+{
+    HPEN32 prevHandle = dc->w.hPen;
+
+    dc->w.hPen = hpen;
+    dc->u.x.pen.style = pen->logpen.lopnStyle;
+    dc->u.x.pen.width = pen->logpen.lopnWidth.x * dc->vportExtX / dc->wndExtX;
+    if (dc->u.x.pen.width < 0) dc->u.x.pen.width = -dc->u.x.pen.width;
+    if (dc->u.x.pen.width == 1) dc->u.x.pen.width = 0;  /* Faster */
+    dc->u.x.pen.pixel = COLOR_ToPhysical( dc, pen->logpen.lopnColor );    
+    switch(pen->logpen.lopnStyle)
+    {
+      case PS_DASH:
+	dc->u.x.pen.dashes = (char *)PEN_dash;
+	dc->u.x.pen.dash_len = 2;
+	break;
+      case PS_DOT:
+	dc->u.x.pen.dashes = (char *)PEN_dot;
+	dc->u.x.pen.dash_len = 2;
+	break;
+      case PS_DASHDOT:
+	dc->u.x.pen.dashes = (char *)PEN_dashdot;
+	dc->u.x.pen.dash_len = 4;
+	break;
+      case PS_DASHDOTDOT:
+	dc->u.x.pen.dashes = (char *)PEN_dashdotdot;
+	dc->u.x.pen.dash_len = 6;
+	break;
+    }
+    
+    return prevHandle;
+}