Release 0.3.0
Fri Sep 3 11:52:18 1993 Bob Amstadt
* [windows/timer.c]
Changed to use CallWindowProc() rather directly calling callback.
* [windows/event.c]
Implemented SetCapture() and ReleaseCapture()
* [windows/keyboard.c]
Created stub for GetKeyState()
* [objects/linedda.c]
Created stub for LineDDA()
* [if1632/callback.c]
Created callback handler for LineDDA callback procedure.
* [if1632/callback.c]
Created FreeProcInstance()
Fri Sep 3 08:36:52 1993 David Metcalfe
* [loader/signal.c]
Patch to and code for INT 1A
Thu Sep 2 00:31:54 1993 Alexandre Julliard
* [objects/font.c] [objects/text.c]
More text support: implemented justification and underlining.
* [windows/clipping.c] [objects/clipping.c]
Moved low-level clipping functions to objects/clipping.c.
* [windows/clipping.c] [windows/event.c] [windows/message.c]
Implemented window update regions.
* [windows/dc.c] [objects/dcvalues.c]
Moved some device-independent DC functions to objects/dcvalues.c.
* [windows/graphics.c]
Implemented InvertRect() and GetPixel().
Sat Aug 28 08:40:23 1993 Eric Youngdale
* [include/neexe.h] [loader/wine.c]
Added code to handle relocation type 4.
* [loader/signal.h] [loader/wine.c] [loader/selector.c]
Added support for dos interrupts.
Thu 26 Aug 19:15:00 1993 Eric Youngdale
* [loader/selector.c]
Fixed bug dealing with loading DLLs.
Thu Aug 26 19:22:40 1993 Alexandre Julliard
* [include/gdi.h] [objects/font.c] [windows/dc.c]
Beginning of real font support.
* [windows/graphics.c]
Implemented PatBlt().
* [memory/global.c]
Corrected a bug with linked list handling in GlobalAlloc().
* [objects/bitmap.c]
Corrected a bug in BITMAP_SelectObject().
Tue Aug 24 19:22:40 1993 David Metcalfe
* [controls/Command*] [controls/Label*] [controls[MenuButto*]
[controls/SmeMenuButt*]
Change code to support & as a special character in menu item text.
Tue Aug 24 19:22:40 1993 Alexandre Julliard
* [include/gdi.h] [windows/dc.c]
Heavily modified the DC structure for better device-independence.
* [objects/bitmap.c]
Implemented bitmap dimensions.
* [windows/dc.c] [windows/dce.c]
Implemented DC state saving and restoring.
* [windows/dc.c]
Implemented ROP mode.
* [windows/graphics.c]
Implemented FillRect().
Mon Aug 23 22:08:34 1993 Bob Amstadt (bob at pooh)
* [misc/xt.c]
Fixed bug in InvalidateRect(). Solitaire attempted to
clear window before it was realized.
* [loader/resource.c]
Began rewrite of LoadBitmap().
* [loader/wine.c]
Fixed code which set Argv and Argc global variables.
* [loader/selector.c]
Added code to set up command line arguments.
* [include/neexe.h]
Fixed error in PSP structure.
Tue Aug 17 20:41:12 1993 Alexandre Julliard
* [include/gdi.h] [windows/dc.c]
Implemented device capabilities.
* [objects/region.c]
Implemented EqualRgn() and CombineRgn().
* [windows/clipping.c]
Implemented Save/RestoreVisRgn().
* [windows/graphics.c]
Implemented PaintRgn() and FillRgn().
* [windows/mapping.c]
Implemented mapping modes.
Tue Aug 10 14:07:38 1993 Alexandre Julliard
* [if1632/user.spec] [misc/rect.c]
Implemented rectangle API functions.
* [if1632/gdi.spec] [include/gdi.h] [objects/region.c]
Implemented regions.
* [windows/class.c]
Corrected a typo in UnregisterClass().
* [windows/clipping.c] [windows/dc.c]
Implemented DC clipping and visible region.
Tue Aug 10 20:57:56 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c]
SetMenu(), GetMenu(), CheckMenuItem() implemented
Thu Aug 5 22:33:22 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c]
Many improvements menus. LoadMenu() should work.
Wed Aug 4 14:55:36 1993 Alexandre Julliard
* [objects/dib.c]
Started the implementation of device-independent bitmaps.
* [objects/bitmap.c]
Added support for multiple bitmap depths.
* [objects/brush.c]
Implemented pattern brushes.
* [windows/dc.c] [windows/graphics.c]
Implemented some GDI graphics primitives.
Tue Aug 3 21:16:47 1993 Bob Amstadt (bob at pooh)
* [controls/menu.c] [windows/win.c] [include/menu.h]
Code to load class menus from executable file.
* [if1632/user.spec]
Fixed specification of SendMessage() and PostMessage.
Mon Jul 26 21:53:24 1993 Alexandre Julliard
* [if1632/call.S]
Corrected a bug in KERNEL_InitTask().
* [include/windows.h]
Added a lot of constants.
* [loader/selector.c]
Corrected a bug in segment allocation in CreateSelectors().
* [objects/bitmap.c]
Implemented SelectObject() for bitmaps.
* [objects/brush.c]
Implemented hatched brushes and SelectObject().
* [objects/gdiobj.c]
Removed linked list (not needed).
* [objects/palette.c]
Implemented system palette creation and misc. palette API functions.
* [windows/timer.c]
Implemented timers.
* [windows/dc.c]
Implemented memory device contexts.
Tue Jul 20 10:38:59 1993 Bob Amstadt (bob at pooh)
* [dos.c]
Split DOS3Call() out of kernel.c. Added support for get date
and time functions.
* [call.S]
Added function ReturnFromRegisterFunc() to allow DOS calls
to return values in registers.
* [regfunc.h]
Macros to access registers saved on stack.
Tue Jul 20 10:38:59 1993 Alexandre Julliard
* [win.c]
Corrected allocation of the WM_CREATE data structure.
* [dce.c] [dce.h]
Implemented DCE handling.
* [bitmap.c] [brush.c] [dc.c] [font.c] [gdi.h] [gdi.spec]
[gdiobj.c] [palette.c] [pen.c]
Implemented the GDI objects data structures and allocation.
* [windows.h]
Added several structures and constants for GDI objects.
Mon Jul 19 12:51:10 1993 Bob Amstadt (bob at pooh)
* [ldtlib.c]
Modified system calls to match Linus' new interface for
the LDT modification.
* [win.c]
Fixed bug with WM_CREATE message.
* [heap.c] [kernel.spec]
Completed local heap allocation functions.
* [global.c]
Created function GlobalQuickAlloc() for easy allocation from DLLs
diff --git a/objects/Makefile b/objects/Makefile
new file mode 100644
index 0000000..ad4d119
--- /dev/null
+++ b/objects/Makefile
@@ -0,0 +1,19 @@
+CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
+
+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
+
+default: objects.o
+
+objects.o: $(OBJS)
+ $(LD) -r -o objects.o $(OBJS)
+
+clean:
+ rm -f *.o *~ *.s dll_* *.a
+
+depend:
+ $(CC) $(CFLAGS) -M *.c > .depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/objects/bitblt.c b/objects/bitblt.c
new file mode 100644
index 0000000..53e9ba1
--- /dev/null
+++ b/objects/bitblt.c
@@ -0,0 +1,111 @@
+/*
+ * GDI bit-blit operations
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+
+#include "gdi.h"
+
+extern const int DC_XROPfunction[];
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+
+/***********************************************************************
+ * PatBlt (GDI.29)
+ */
+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) return FALSE;
+#ifdef DEBUG_GDI
+ printf( "PatBlt: %d %d,%d %dx%d %06x\n",
+ hdc, left, top, width, height, rop );
+#endif
+
+ 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 = XLPTODP( dc, left );
+ x2 = XLPTODP( dc, left + width );
+ y1 = YLPTODP( dc, top );
+ y2 = 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) );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * BitBlt (GDI.34)
+ */
+BOOL BitBlt( HDC hdcDest, short xDest, short yDest, short width, short height,
+ HDC hdcSrc, short xSrc, short ySrc, DWORD rop )
+{
+ int xs1, xs2, ys1, ys2;
+ int xd1, xd2, yd1, yd2;
+ 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 ((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 );
+ return FALSE;
+ }
+
+ dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
+ if (!dcDest) return FALSE;
+ dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
+ if (!dcSrc) return FALSE;
+
+ xs1 = XLPTODP( dcSrc, xSrc );
+ xs2 = XLPTODP( dcSrc, xSrc + width );
+ ys1 = YLPTODP( dcSrc, ySrc );
+ ys2 = YLPTODP( dcSrc, ySrc + height );
+ xd1 = XLPTODP( dcDest, xDest );
+ xd2 = XLPTODP( dcDest, xDest + width );
+ yd1 = YLPTODP( dcDest, yDest );
+ yd2 = YLPTODP( dcDest, yDest + height );
+
+ if ((abs(xs2-xs1) != abs(xd2-xd1)) || (abs(ys2-ys1) != abs(yd2-yd1)))
+ return FALSE; /* Should call StretchBlt here */
+
+ DC_SetupGCForText( dcDest );
+ XSetFunction( XT_display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f] );
+ if (dcSrc->w.bitsPerPixel == dcDest->w.bitsPerPixel)
+ {
+ XCopyArea( XT_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) );
+ }
+ else
+ {
+ if (dcSrc->w.bitsPerPixel != 1) return FALSE;
+ XCopyPlane( XT_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 );
+ }
+ return TRUE;
+}
diff --git a/objects/bitmap.c b/objects/bitmap.c
new file mode 100644
index 0000000..9de4c1c
--- /dev/null
+++ b/objects/bitmap.c
@@ -0,0 +1,423 @@
+/*
+ * GDI bitmap objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "gdi.h"
+
+/* A GDI bitmap object contains a handle to a packed BITMAP,
+ * which is stored on the global heap.
+ * A packed BITMAP is a BITMAP structure followed by the bitmap bits.
+ */
+
+ /* Handle of the bitmap selected by default in a memory DC */
+HBITMAP BITMAP_hbitmapMemDC;
+
+ /* List of supported depths */
+static int depthCount;
+static int * depthList;
+
+ /* List of GC used for bitmap to pixmap operations (one for each depth) */
+static GC * bitmapGC;
+
+
+/***********************************************************************
+ * BITMAP_Init
+ */
+BOOL BITMAP_Init()
+{
+ int i;
+ Pixmap tmpPixmap;
+
+ depthList = XListDepths( XT_display, DefaultScreen(XT_display),
+ &depthCount );
+ if (!depthList || !depthCount) return FALSE;
+ if (!(bitmapGC = (GC *) malloc( depthCount * sizeof(GC) ))) return FALSE;
+
+ /* Create the necessary GCs */
+
+ for (i = 0; i < depthCount; i++)
+ {
+ tmpPixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
+ 1, 1, depthList[i] );
+ if (tmpPixmap)
+ {
+ bitmapGC[i] = XCreateGC( XT_display, tmpPixmap, 0, NULL );
+ XFreePixmap( XT_display, tmpPixmap );
+ }
+ else bitmapGC[i] = 0;
+ }
+
+ BITMAP_hbitmapMemDC = CreateBitmap( 1, 1, 1, 1, NULL );
+ return (BITMAP_hbitmapMemDC != 0);
+}
+
+
+/***********************************************************************
+ * BITMAP_FindGCForDepth
+ *
+ * Return a GC appropriate for operations with the given depth.
+ */
+GC BITMAP_FindGCForDepth( int depth )
+{
+ int i;
+ for (i = 0; i < depthCount; i++)
+ if (depthList[i] == depth) return bitmapGC[i];
+ return 0;
+}
+
+
+/***********************************************************************
+ * BITMAP_BmpToImage
+ *
+ * Create an XImage pointing to the bitmap data.
+ */
+XImage * BITMAP_BmpToImage( BITMAP * bmp, void * bmpData )
+{
+ XImage * image;
+
+ image = XCreateImage( XT_display, DefaultVisualOfScreen(XT_screen),
+ bmp->bmBitsPixel, ZPixmap, 0, bmpData,
+ bmp->bmWidth, bmp->bmHeight, 16, bmp->bmWidthBytes );
+ if (!image) return 0;
+ image->byte_order = MSBFirst;
+ image->bitmap_bit_order = MSBFirst;
+ image->bitmap_unit = 16;
+ _XInitImageFuncPtrs(image);
+ return image;
+}
+
+
+/***********************************************************************
+ * BITMAP_CopyToPixmap
+ *
+ * Copy the content of the bitmap to the pixmap. Both must have the same depth.
+ */
+BOOL BITMAP_CopyToPixmap( BITMAP * bmp, Pixmap pixmap,
+ int x, int y, int width, int height )
+{
+ GC gc;
+ XImage * image;
+
+ gc = BITMAP_FindGCForDepth( bmp->bmBitsPixel );
+ if (!gc) return FALSE;
+
+ image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
+ if (!image) return FALSE;
+
+#ifdef DEBUG_GDI
+ printf( "BITMAP_CopyToPixmap: %dx%d %d colors -> %d,%d %dx%d\n",
+ bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel, x, y, width, height );
+#endif
+ XPutImage(XT_display, pixmap, gc, image, 0, 0, x, y, width, height);
+ image->data = NULL;
+ XDestroyImage( image );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * BITMAP_CopyFromPixmap
+ *
+ * Copy the content of the pixmap to the bitmap. Both must have
+ * the same dimensions and depth.
+ */
+BOOL BITMAP_CopyFromPixmap( BITMAP * bmp, Pixmap pixmap )
+{
+ XImage *image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
+ if (!image) return FALSE;
+
+#ifdef DEBUG_GDI
+ printf( "BITMAP_CopyFromPixmap: %dx%d %d colors\n",
+ bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel );
+#endif
+ XGetSubImage( XT_display, pixmap, 0, 0, bmp->bmWidth, bmp->bmHeight,
+ AllPlanes, ZPixmap, image, 0, 0 );
+ image->data = NULL;
+ XDestroyImage( image );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * CreateBitmap (GDI.48)
+ */
+HBITMAP CreateBitmap( short width, short height,
+ 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",
+ width, height, 1 << (planes*bpp) );
+#endif
+ if (!width || !height) return 0;
+ if ((planes != 1) && (bpp != 1)) return 0;
+ bitmap.bmWidthBytes = (width * bpp + 15) / 16 * 2;
+ return CreateBitmapIndirect( &bitmap );
+}
+
+
+/***********************************************************************
+ * CreateCompatibleBitmap (GDI.51)
+ */
+HBITMAP CreateCompatibleBitmap( HDC hdc, short width, short height )
+{
+ HBITMAP hbitmap;
+ DC * dc;
+#ifdef DEBUG_GDI
+ printf( "CreateCompatibleBitmap: %d %dx%d\n", hdc, width, height );
+#endif
+ dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+ hbitmap = CreateBitmap( width, height, dc->w.planes, dc->w.bitsPerPixel, NULL);
+ return hbitmap;
+}
+
+
+/***********************************************************************
+ * CreateBitmapIndirect (GDI.49)
+ */
+HBITMAP CreateBitmapIndirect( BITMAP * bmp )
+{
+ BITMAPOBJ * bmpObjPtr;
+ char * bmpPtr;
+ HBITMAP hbitmap;
+ int size = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
+
+ /* Create the BITMAPOBJ */
+
+ hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
+ if (!hbitmap) return 0;
+ bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_ADDR( hbitmap );
+
+ /* Create the bitmap in global heap */
+
+ bmpObjPtr->hBitmap = GlobalAlloc( GMEM_MOVEABLE, sizeof(BITMAP) + size );
+ if (!bmpObjPtr->hBitmap)
+ {
+ GDI_FreeObject( hbitmap );
+ return 0;
+ }
+ bmpPtr = (char *) GlobalLock( bmpObjPtr->hBitmap );
+ memcpy( bmpPtr, bmp, sizeof(BITMAP) );
+ ((BITMAP *)bmpPtr)->bmBits = NULL;
+ if (bmp->bmBits) memcpy( bmpPtr + sizeof(BITMAP), bmp->bmBits, size );
+ GlobalUnlock( bmpObjPtr->hBitmap );
+
+ bmpObjPtr->bSelected = FALSE;
+ bmpObjPtr->hdc = 0;
+ bmpObjPtr->size.cx = 0;
+ bmpObjPtr->size.cy = 0;
+ return hbitmap;
+}
+
+
+/***********************************************************************
+ * BITMAP_GetSetBitmapBits
+ */
+LONG BITMAP_GetSetBitmapBits( HBITMAP hbitmap, LONG count,
+ LPSTR buffer, int set )
+{
+ BITMAPOBJ * bmpObjPtr;
+ BITMAP * bmp;
+ DC * dc = NULL;
+ int maxSize;
+
+ if (!count) return 0;
+ bmpObjPtr = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+ if (!bmpObjPtr) return 0;
+ if (!(bmp = (BITMAP *) GlobalLock( bmpObjPtr->hBitmap ))) return 0;
+
+ if (bmpObjPtr->bSelected)
+ dc = (DC *) GDI_GetObjPtr( bmpObjPtr->hdc, DC_MAGIC );
+
+ maxSize = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
+ if (count > maxSize) count = maxSize;
+
+ if (set)
+ {
+ memcpy( bmp+1, buffer, count );
+ if (dc) BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
+ 0, 0, bmp->bmWidth, bmp->bmHeight );
+ }
+ else
+ {
+ if (dc) BITMAP_CopyFromPixmap( bmp, dc->u.x.drawable );
+ memcpy( buffer, bmp+1, count );
+ }
+ GlobalUnlock( bmpObjPtr->hBitmap );
+ return hbitmap;
+}
+
+
+/***********************************************************************
+ * GetBitmapBits (GDI.74)
+ */
+LONG GetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
+{
+ return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 0 );
+}
+
+
+/***********************************************************************
+ * SetBitmapBits (GDI.106)
+ */
+LONG SetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
+{
+ return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 1 );
+}
+
+
+/***********************************************************************
+ * BMP_DeleteObject
+ */
+BOOL BMP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bitmap )
+{
+ /* Free bitmap on global heap */
+ GlobalFree( bitmap->hBitmap );
+ return GDI_FreeObject( hbitmap );
+}
+
+
+/***********************************************************************
+ * BMP_GetObject
+ */
+int BMP_GetObject( BITMAPOBJ * bitmap, int count, LPSTR buffer )
+{
+ char * bmpPtr = (char *) GlobalLock( bitmap->hBitmap );
+ if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
+ memcpy( buffer, bmpPtr, count );
+ GlobalUnlock( bitmap->hBitmap );
+ return count;
+}
+
+
+/***********************************************************************
+ * BITMAP_UnselectBitmap
+ *
+ * Unselect the bitmap from the DC. Used by SelectObject and DeleteDC.
+ */
+BOOL BITMAP_UnselectBitmap( DC * dc )
+{
+ BITMAPOBJ * bmp;
+ BITMAP * bmpPtr;
+
+ if (!dc->w.hBitmap) return TRUE;
+ bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
+ if (!bmp) return FALSE;
+
+ if (!(bmpPtr = (BITMAP *) GlobalLock( bmp->hBitmap ))) return FALSE;
+
+ BITMAP_CopyFromPixmap( bmpPtr, dc->u.x.drawable );
+ XFreePixmap( XT_display, dc->u.x.drawable );
+ bmp->bSelected = FALSE;
+ bmp->hdc = 0;
+ GlobalUnlock( bmp->hBitmap );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * BITMAP_SelectObject
+ */
+HBITMAP BITMAP_SelectObject( HDC hdc, DC * dc, HBITMAP hbitmap,
+ BITMAPOBJ * bitmap )
+{
+ BITMAP * bmp;
+ HBITMAP prevHandle = dc->w.hBitmap;
+
+ if (!(dc->w.flags & DC_MEMORY)) return 0;
+ if (bitmap->bSelected && hbitmap != BITMAP_hbitmapMemDC) return 0;
+ if (!(bmp = (BITMAP *) GlobalLock( bitmap->hBitmap ))) return 0;
+
+ /* Make sure the bitmap has the right format */
+
+ if ((bmp->bmPlanes != 1) || !BITMAP_FindGCForDepth( bmp->bmBitsPixel ))
+ {
+ GlobalUnlock( bitmap->hBitmap );
+ return 0;
+ }
+
+ /* Unselect the previous bitmap */
+
+ if (!BITMAP_UnselectBitmap( dc ))
+ {
+ GlobalUnlock( bitmap->hBitmap );
+ return 0;
+ }
+
+ /* Create the pixmap */
+
+ dc->u.x.drawable = XCreatePixmap( XT_display,
+ DefaultRootWindow( XT_display ),
+ bmp->bmWidth, bmp->bmHeight,
+ bmp->bmBitsPixel );
+ BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
+ 0, 0, bmp->bmWidth, bmp->bmHeight );
+
+ /* Change GC depth if needed */
+
+ if (dc->w.bitsPerPixel != bmp->bmBitsPixel)
+ {
+ XFreeGC( XT_display, dc->u.x.gc );
+ dc->u.x.gc = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
+ dc->w.bitsPerPixel = bmp->bmBitsPixel;
+ DC_SetDeviceInfo( hdc, dc );
+ }
+
+ GlobalUnlock( bitmap->hBitmap );
+ dc->w.hBitmap = hbitmap;
+ bitmap->bSelected = TRUE;
+ bitmap->hdc = hdc;
+ return prevHandle;
+}
+
+
+/***********************************************************************
+ * GetBitmapDimensionEx (GDI.468)
+ */
+BOOL GetBitmapDimensionEx( HBITMAP hbitmap, LPSIZE size )
+{
+ BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+ if (!bmp) return FALSE;
+ *size = bmp->size;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetBitmapDimension (GDI.162)
+ */
+DWORD GetBitmapDimension( HBITMAP hbitmap )
+{
+ SIZE size;
+ if (!GetBitmapDimensionEx( hbitmap, &size )) return 0;
+ return size.cx | (size.cy << 16);
+}
+
+/***********************************************************************
+ * SetBitmapDimensionEx (GDI.478)
+ */
+BOOL SetBitmapDimensionEx( HBITMAP hbitmap, short x, short y, LPSIZE prevSize )
+{
+ BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+ if (!bmp) return FALSE;
+ if (prevSize) *prevSize = bmp->size;
+ bmp->size.cx = x;
+ bmp->size.cy = y;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * SetBitmapDimension (GDI.163)
+ */
+DWORD SetBitmapDimension( HBITMAP hbitmap, short x, short y )
+{
+ SIZE size;
+ if (!SetBitmapDimensionEx( hbitmap, x, y, &size )) return 0;
+ return size.cx | (size.cy << 16);
+}
diff --git a/objects/brush.c b/objects/brush.c
new file mode 100644
index 0000000..11a430b
--- /dev/null
+++ b/objects/brush.c
@@ -0,0 +1,270 @@
+/*
+ * GDI brush objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "gdi.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+#define NB_HATCH_STYLES 6
+
+static 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 */
+};
+
+extern XImage * BITMAP_BmpToImage( BITMAP *, void * );
+
+/***********************************************************************
+ * CreateBrushIndirect (GDI.50)
+ */
+HBRUSH CreateBrushIndirect( LOGBRUSH * brush )
+{
+ BRUSHOBJ * brushPtr;
+ HBRUSH hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC );
+ if (!hbrush) return 0;
+ brushPtr = (BRUSHOBJ *) GDI_HEAP_ADDR( hbrush );
+ memcpy( &brushPtr->logbrush, brush, sizeof(LOGBRUSH) );
+ return hbrush;
+}
+
+
+/***********************************************************************
+ * CreateHatchBrush (GDI.58)
+ */
+HBRUSH CreateHatchBrush( short style, COLORREF color )
+{
+ LOGBRUSH logbrush = { BS_HATCHED, color, style };
+#ifdef DEBUG_GDI
+ printf( "CreateHatchBrush: %d %06x\n", style, color );
+#endif
+ if ((style < 0) || (style >= NB_HATCH_STYLES)) return 0;
+ return CreateBrushIndirect( &logbrush );
+}
+
+
+/***********************************************************************
+ * CreatePatternBrush (GDI.60)
+ */
+HBRUSH CreatePatternBrush( HBITMAP hbitmap )
+{
+ LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
+ BITMAPOBJ * bmpObj;
+ BITMAP * bmp;
+
+#ifdef DEBUG_GDI
+ printf( "CreatePatternBrush: %d\n", hbitmap );
+#endif
+
+ /* Make a copy of the bitmap */
+
+ if (!(bmpObj = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+ return 0;
+ if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
+ logbrush.lbHatch = CreateBitmap( bmp->bmWidth, bmp->bmHeight,
+ bmp->bmPlanes, bmp->bmBitsPixel,
+ ((char *)bmp) + sizeof(BITMAP) );
+ GlobalUnlock( bmpObj->hBitmap );
+ if (!logbrush.lbHatch) return 0;
+ return CreateBrushIndirect( &logbrush );
+}
+
+
+/***********************************************************************
+ * CreateDIBPatternBrush (GDI.445)
+ */
+HBRUSH CreateDIBPatternBrush( HANDLE hbitmap, WORD coloruse )
+{
+ LOGBRUSH logbrush = { BS_DIBPATTERN, coloruse, 0 };
+ BITMAPINFO *info, *newInfo;
+ int size;
+
+#ifdef DEBUG_GDI
+ printf( "CreateDIBPatternBrush: %d\n", hbitmap );
+#endif
+
+ /* Make a copy of the bitmap */
+
+ if (!(info = (BITMAPINFO *) GlobalLock( hbitmap ))) return 0;
+
+ size = info->bmiHeader.biSizeImage;
+ if (!size)
+ size = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) / 32
+ * 8 * info->bmiHeader.biHeight;
+ size += DIB_BitmapInfoSize( info, coloruse );
+
+ if (!(logbrush.lbHatch = GlobalAlloc( GMEM_MOVEABLE, size )))
+ {
+ GlobalUnlock( hbitmap );
+ return 0;
+ }
+ newInfo = (BITMAPINFO *) GlobalLock( logbrush.lbHatch );
+ memcpy( newInfo, info, size );
+ GlobalUnlock( logbrush.lbHatch );
+ GlobalUnlock( hbitmap );
+ return CreateBrushIndirect( &logbrush );
+}
+
+
+/***********************************************************************
+ * CreateSolidBrush (GDI.66)
+ */
+HBRUSH CreateSolidBrush( COLORREF color )
+{
+ LOGBRUSH logbrush = { BS_SOLID, color, 0 };
+#ifdef DEBUG_GDI
+ printf( "CreateSolidBrush: %06x\n", color );
+#endif
+ return CreateBrushIndirect( &logbrush );
+}
+
+
+/***********************************************************************
+ * SetBrushOrg (GDI.148)
+ */
+DWORD SetBrushOrg( HDC hdc, short x, short y )
+{
+ DWORD retval;
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return FALSE;
+ retval = dc->w.brushOrgX | (dc->w.brushOrgY << 16);
+ dc->w.brushOrgX = x;
+ dc->w.brushOrgY = y;
+ return retval;
+}
+
+
+/***********************************************************************
+ * BRUSH_DeleteObject
+ */
+BOOL BRUSH_DeleteObject( HBRUSH hbrush, BRUSHOBJ * brush )
+{
+ switch(brush->logbrush.lbStyle)
+ {
+ case BS_PATTERN:
+ DeleteObject( brush->logbrush.lbHatch );
+ break;
+ case BS_DIBPATTERN:
+ GlobalFree( brush->logbrush.lbHatch );
+ break;
+ }
+ return GDI_FreeObject( hbrush );
+}
+
+
+/***********************************************************************
+ * BRUSH_GetObject
+ */
+int BRUSH_GetObject( BRUSHOBJ * brush, int count, LPSTR buffer )
+{
+ if (count > sizeof(LOGBRUSH)) count = sizeof(LOGBRUSH);
+ memcpy( buffer, &brush->logbrush, count );
+ return count;
+}
+
+
+/***********************************************************************
+ * BRUSH_SelectPatternBrush
+ */
+BOOL BRUSH_SelectPatternBrush( DC * dc, HBITMAP hbitmap )
+{
+ BITMAPOBJ * bmpObjPtr;
+ BITMAP * bmp;
+
+ bmpObjPtr = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+ if (!bmpObjPtr) return FALSE;
+ if (!(bmp = (BITMAP *) GlobalLock( bmpObjPtr->hBitmap ))) return FALSE;
+
+ dc->u.x.brush.pixmap = XCreatePixmap( XT_display,
+ DefaultRootWindow(XT_display),
+ 8, 8, bmp->bmBitsPixel );
+ BITMAP_CopyToPixmap( bmp, dc->u.x.brush.pixmap, 0, 0, 8, 8 );
+
+ if (bmp->bmBitsPixel > 1)
+ {
+ dc->u.x.brush.fillStyle = FillTiled;
+ XSetTile( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
+ dc->u.x.brush.pixel = 0; /* Ignored */
+ }
+ else
+ {
+ dc->u.x.brush.fillStyle = FillOpaqueStippled;
+ XSetStipple( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
+ dc->u.x.brush.pixel = -1; /* Special case (see DC_SetupGCForBrush) */
+ }
+ return TRUE;
+}
+
+
+
+/***********************************************************************
+ * BRUSH_SelectObject
+ */
+HBRUSH BRUSH_SelectObject( HDC hdc, DC * dc, HBRUSH hbrush, BRUSHOBJ * brush )
+{
+ HBITMAP hBitmap;
+ BITMAPINFO * bmpInfo;
+ HBRUSH prevHandle = dc->w.hBrush;
+
+ dc->w.hBrush = hbrush;
+
+ if (dc->u.x.brush.pixmap)
+ {
+ XFreePixmap( XT_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_SOLID:
+ case BS_NULL:
+ dc->u.x.brush.pixel = GetNearestPaletteIndex( dc->w.hPalette,
+ brush->logbrush.lbColor );
+ dc->u.x.brush.fillStyle = FillSolid;
+ break;
+
+ case BS_HATCHED:
+ dc->u.x.brush.pixel = GetNearestPaletteIndex( dc->w.hPalette,
+ brush->logbrush.lbColor );
+ dc->u.x.brush.pixmap = XCreateBitmapFromData(XT_display,
+ DefaultRootWindow(XT_display),
+ HatchBrushes[brush->logbrush.lbHatch],
+ 8, 8 );
+ XSetStipple( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
+ dc->u.x.brush.fillStyle = FillStippled;
+ break;
+
+ case BS_PATTERN:
+ BRUSH_SelectPatternBrush( dc, brush->logbrush.lbHatch );
+ break;
+
+ case BS_DIBPATTERN:
+ if ((bmpInfo = (BITMAPINFO *) GlobalLock( brush->logbrush.lbHatch )))
+ {
+ int size = DIB_BitmapInfoSize( bmpInfo, brush->logbrush.lbColor );
+ hBitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
+ ((char *)bmpInfo) + size, bmpInfo,
+ (WORD) brush->logbrush.lbColor );
+ BRUSH_SelectPatternBrush( dc, hBitmap );
+ DeleteObject( hBitmap );
+ GlobalUnlock( brush->logbrush.lbHatch );
+ }
+
+ break;
+ }
+
+ return prevHandle;
+}
+
+
diff --git a/objects/clipping.c b/objects/clipping.c
new file mode 100644
index 0000000..ec9de9c
--- /dev/null
+++ b/objects/clipping.c
@@ -0,0 +1,354 @@
+/*
+ * DC clipping functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdio.h>
+#include "gdi.h"
+
+
+/***********************************************************************
+ * CLIPPING_UpdateGCRegion
+ *
+ * Update the GC clip region when the ClipRgn of VisRgn have changed.
+ */
+static void CLIPPING_UpdateGCRegion( DC * dc )
+{
+ if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn(0,0,0,0);
+
+ if (!dc->w.hVisRgn)
+ {
+ if (!dc->w.hClipRgn)
+ {
+ DeleteObject( dc->w.hGCClipRgn );
+ dc->w.hGCClipRgn = 0;
+ }
+ else
+ CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
+ }
+ else
+ {
+ if (!dc->w.hClipRgn)
+ CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
+ else
+ CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND );
+ }
+
+ if (dc->w.hGCClipRgn)
+ {
+ RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hGCClipRgn, REGION_MAGIC );
+ XSetClipMask( XT_display, dc->u.x.gc, obj->region.pixmap );
+ XSetClipOrigin( XT_display, dc->u.x.gc,
+ obj->region.box.left, obj->region.box.top );
+ }
+ else
+ {
+ XSetClipMask( XT_display, dc->u.x.gc, None );
+ XSetClipOrigin( XT_display, dc->u.x.gc, 0, 0 );
+ }
+}
+
+
+/***********************************************************************
+ * CLIPPING_SelectRgn
+ *
+ * Helper function for SelectClipRgn() and SelectVisRgn().
+ */
+static int CLIPPING_SelectRgn( DC * dc, HRGN * hrgnPrev, HRGN hrgn )
+{
+ int retval;
+
+ if (hrgn)
+ {
+ if (!*hrgnPrev) *hrgnPrev = CreateRectRgn(0,0,0,0);
+ retval = CombineRgn( *hrgnPrev, hrgn, 0, RGN_COPY );
+ }
+ else
+ {
+ if (*hrgnPrev) DeleteObject( *hrgnPrev );
+ *hrgnPrev = 0;
+ retval = SIMPLEREGION; /* Clip region == client area */
+ }
+ CLIPPING_UpdateGCRegion( dc );
+ return retval;
+}
+
+
+/***********************************************************************
+ * SelectClipRgn (GDI.44)
+ */
+int SelectClipRgn( HDC hdc, HRGN hrgn )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+
+#ifdef DEBUG_CLIPPING
+ printf( "SelectClipRgn: %d %d\n", hdc, hrgn );
+#endif
+ return CLIPPING_SelectRgn( dc, &dc->w.hClipRgn, hrgn );
+}
+
+
+/***********************************************************************
+ * SelectVisRgn (GDI.105)
+ */
+int SelectVisRgn( HDC hdc, HRGN hrgn )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+
+#ifdef DEBUG_CLIPPING
+ printf( "SelectVisRgn: %d %d\n", hdc, hrgn );
+#endif
+ return CLIPPING_SelectRgn( dc, &dc->w.hVisRgn, hrgn );
+}
+
+
+/***********************************************************************
+ * OffsetClipRgn (GDI.32)
+ */
+int OffsetClipRgn( HDC hdc, short x, short y )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "OffsetClipRgn: %d %d,%d\n", hdc, x, y );
+#endif
+
+ if (dc->w.hClipRgn)
+ {
+ int retval = OffsetRgn( dc->w.hClipRgn, x, y );
+ CLIPPING_UpdateGCRegion( dc );
+ return retval;
+ }
+ else return SIMPLEREGION; /* Clip region == client area */
+}
+
+
+/***********************************************************************
+ * OffsetVisRgn (GDI.102)
+ */
+int OffsetVisRgn( HDC hdc, short x, short y )
+{
+ 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
+
+ if (dc->w.hVisRgn)
+ {
+ int retval = OffsetRgn( dc->w.hVisRgn, x, y );
+ CLIPPING_UpdateGCRegion( dc );
+ return retval;
+ }
+ else return SIMPLEREGION; /* Clip region == client area */
+}
+
+
+/***********************************************************************
+ * CLIPPING_IntersectRect
+ *
+ * Helper function for {Intersect,Exclude}{Clip,Vis}Rect
+ */
+int CLIPPING_IntersectRect( DC * dc, HRGN * hrgn, short left, short top,
+ short right, short bottom, int exclude )
+{
+ HRGN tempRgn, newRgn;
+ RGNOBJ *newObj, *prevObj;
+ int retval;
+
+ if (!*hrgn) return NULLREGION;
+ if (!(newRgn = CreateRectRgn( 0, 0, 0, 0))) return ERROR;
+ if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
+ {
+ DeleteObject( newRgn );
+ return ERROR;
+ }
+ retval = CombineRgn( newRgn, *hrgn, tempRgn, exclude ? RGN_DIFF : RGN_AND);
+ newObj = (RGNOBJ *) GDI_GetObjPtr( newRgn, REGION_MAGIC );
+ prevObj = (RGNOBJ *) GDI_GetObjPtr( *hrgn, REGION_MAGIC );
+ if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
+ DeleteObject( tempRgn );
+ DeleteObject( *hrgn );
+ *hrgn = newRgn;
+ CLIPPING_UpdateGCRegion( dc );
+ return retval;
+}
+
+
+/***********************************************************************
+ * ExcludeClipRect (GDI.21)
+ */
+int ExcludeClipRect( HDC hdc, short left, short top,
+ short right, short bottom )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "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 );
+}
+
+
+/***********************************************************************
+ * IntersectClipRect (GDI.22)
+ */
+int IntersectClipRect( HDC hdc, short left, short top,
+ short right, short bottom )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "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 );
+}
+
+
+/***********************************************************************
+ * ExcludeVisRect (GDI.73)
+ */
+int ExcludeVisRect( HDC hdc, short left, short top,
+ short right, short bottom )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "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 );
+}
+
+
+/***********************************************************************
+ * IntersectVisRect (GDI.98)
+ */
+int IntersectVisRect( HDC hdc, short left, short top,
+ short right, short bottom )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "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 );
+}
+
+
+/***********************************************************************
+ * PtVisible (GDI.103)
+ */
+BOOL PtVisible( HDC hdc, short x, short y )
+{
+ 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 );
+}
+
+
+/***********************************************************************
+ * RectVisible (GDI.104)
+ */
+BOOL RectVisible( HDC hdc, LPRECT rect )
+{
+ 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 );
+}
+
+
+/***********************************************************************
+ * GetClipBox (GDI.77)
+ */
+int GetClipBox( HDC hdc, LPRECT rect )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "GetClipBox: %d %p\n", hdc, rect );
+#endif
+
+ if (dc->w.hGCClipRgn) return GetRgnBox( dc->w.hGCClipRgn, rect );
+ else
+ {
+ Window root;
+ int width, height, x, y, border, depth;
+ XGetGeometry( XT_display, dc->u.x.drawable, &root, &x, &y,
+ &width, &height, &border, &depth );
+ rect->top = rect->left = 0;
+ rect->right = width & 0xffff;
+ rect->bottom = height & 0xffff;
+ return SIMPLEREGION;
+ }
+}
+
+
+/***********************************************************************
+ * SaveVisRgn (GDI.129)
+ */
+HRGN SaveVisRgn( HDC hdc )
+{
+ HRGN copy;
+ RGNOBJ *obj, *copyObj;
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+#ifdef DEBUG_CLIPPING
+ printf( "SaveVisRgn: %d\n", hdc );
+#endif
+ if (!dc->w.hVisRgn) return 0;
+ if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
+ return 0;
+ if (!(copy = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
+ CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
+ if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
+ return 0;
+ copyObj->header.hNext = obj->header.hNext;
+ obj->header.hNext = copy;
+ return copy;
+}
+
+
+/***********************************************************************
+ * RestoreVisRgn (GDI.130)
+ */
+int RestoreVisRgn( HDC hdc )
+{
+ HRGN saved;
+ RGNOBJ *obj, *savedObj;
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return ERROR;
+#ifdef DEBUG_CLIPPING
+ printf( "RestoreVisRgn: %d\n", hdc );
+#endif
+ if (!dc->w.hVisRgn) return ERROR;
+ if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
+ return ERROR;
+ if (!(saved = obj->header.hNext)) return ERROR;
+ if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
+ return ERROR;
+ DeleteObject( dc->w.hVisRgn );
+ dc->w.hVisRgn = saved;
+ CLIPPING_UpdateGCRegion( dc );
+ return savedObj->region.type;
+}
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
new file mode 100644
index 0000000..b496e2e
--- /dev/null
+++ b/objects/dcvalues.c
@@ -0,0 +1,142 @@
+/*
+ * DC device-independent Get/SetXXX functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "gdi.h"
+
+ /* Default DC values */
+const WIN_DC_INFO DCVAL_defaultValues =
+{
+ 0, /* flags */
+ NULL, /* devCaps */
+ 0, /* hMetaFile */
+ 0, /* hClipRgn */
+ 0, /* hVisRgn */
+ 0, /* hGCClipRgn */
+ STOCK_BLACK_PEN, /* hPen */
+ STOCK_WHITE_BRUSH, /* hBrush */
+ STOCK_SYSTEM_FONT, /* hFont */
+ 0, /* hBitmap */
+ 0, /* hDevice */
+ STOCK_DEFAULT_PALETTE, /* hPalette */
+ R2_COPYPEN, /* ROPmode */
+ ALTERNATE, /* polyFillMode */
+ BLACKONWHITE, /* stretchBltMode */
+ ABSOLUTE, /* relAbsMode */
+ OPAQUE, /* backgroundMode */
+ RGB( 255, 255, 255 ), /* backgroundColor */
+ RGB( 0, 0, 0 ), /* textColor */
+ 0, /* backgroundPixel */
+ 0, /* textPixel */
+ 0, /* brushOrgX */
+ 0, /* brushOrgY */
+ TA_LEFT | TA_TOP | TA_NOUPDATECP, /* textAlign */
+ 0, /* charExtra */
+ 0, /* breakTotalExtra */
+ 0, /* breakCount */
+ 0, /* breakExtra */
+ 0, /* breakRem */
+ 1, /* planes */
+ 1, /* bitsPerPixel */
+ MM_TEXT, /* MapMode */
+ 0, /* DCOrgX */
+ 0, /* DCOrgY */
+ 0, /* CursPosX */
+ 0, /* CursPosY */
+ 0, /* WndOrgX */
+ 0, /* WndOrgY */
+ 1, /* WndExtX */
+ 1, /* WndExtY */
+ 0, /* VportOrgX */
+ 0, /* VportOrgY */
+ 1, /* VportExtX */
+ 1 /* VportExtY */
+};
+
+
+#define DC_GET_VAL( func_type, func_name, dc_field ) \
+func_type func_name( HDC hdc ) \
+{ \
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
+ if (!dc) return 0; \
+ return dc->w.dc_field; \
+}
+
+#define DC_GET_X_Y( func_type, func_name, ret_x, ret_y ) \
+func_type func_name( HDC hdc ) \
+{ \
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
+ if (!dc) return 0; \
+ return dc->w.ret_x | (dc->w.ret_y << 16); \
+}
+
+#define DC_GET_VAL_EX( func_name, ret_x, ret_y ) \
+BOOL func_name( HDC hdc, LPPOINT pt ) \
+{ \
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
+ if (!dc) return FALSE; \
+ pt->x = dc->w.ret_x; \
+ pt->y = dc->w.ret_y; \
+ return TRUE; \
+}
+
+#define DC_SET_VAL( func_type, func_name, dc_field ) \
+func_type func_name( HDC hdc, func_type val ) \
+{ \
+ func_type prevVal; \
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
+ if (!dc) return 0; \
+ prevVal = dc->w.dc_field; \
+ dc->w.dc_field = val; \
+ return prevVal; \
+}
+
+#define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
+WORD func_name( HDC hdc, WORD mode ) \
+{ \
+ WORD prevMode; \
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
+ if (!dc) return 0; \
+ if ((mode < min_val) || (mode > max_val)) return 0; \
+ prevMode = dc->w.dc_field; \
+ dc->w.dc_field = mode; \
+ return prevMode; \
+}
+
+
+DC_SET_MODE( SetBkMode, backgroundMode, TRANSPARENT, OPAQUE ) /* GDI.2 */
+DC_SET_MODE( SetROP2, ROPmode, R2_BLACK, R2_WHITE ) /* GDI.4 */
+DC_SET_MODE( SetRelAbs, relAbsMode, ABSOLUTE, RELATIVE ) /* GDI.5 */
+DC_SET_MODE( SetPolyFillMode, polyFillMode, ALTERNATE, WINDING ) /* GDI.6 */
+DC_SET_MODE( SetStretchBltMode, stretchBltMode,
+ BLACKONWHITE, COLORONCOLOR ) /* GDI.7 */
+DC_GET_VAL( COLORREF, GetBkColor, backgroundColor ) /* GDI.75 */
+DC_GET_VAL( WORD, GetBkMode, backgroundMode ) /* GDI.76 */
+DC_GET_X_Y( DWORD, GetCurrentPosition, CursPosX, CursPosY ) /* GDI.78 */
+DC_GET_X_Y( DWORD, GetDCOrg, DCOrgX, DCOrgY ) /* GDI.79 */
+DC_GET_VAL( WORD, GetMapMode, MapMode ) /* GDI.81 */
+DC_GET_VAL( WORD, GetPolyFillMode, polyFillMode ) /* GDI.84 */
+DC_GET_VAL( WORD, GetROP2, ROPmode ) /* GDI.85 */
+DC_GET_VAL( WORD, GetRelAbs, relAbsMode ) /* GDI.86 */
+DC_GET_VAL( WORD, GetStretchBltMode, stretchBltMode ) /* GDI.88 */
+DC_GET_VAL( COLORREF, GetTextColor, textColor ) /* GDI.90 */
+DC_GET_X_Y( DWORD, GetViewportExt, VportExtX, VportExtY ) /* GDI.94 */
+DC_GET_X_Y( DWORD, GetViewportOrg, VportOrgX, VportOrgY ) /* GDI.95 */
+DC_GET_X_Y( DWORD, GetWindowExt, WndExtX, WndExtY ) /* GDI.96 */
+DC_GET_X_Y( DWORD, GetWindowOrg, WndOrgX, WndOrgY ) /* GDI.97 */
+DC_GET_VAL( HRGN, InquireVisRgn, hVisRgn ) /* GDI.131 */
+DC_GET_X_Y( DWORD, GetBrushOrg, brushOrgX, brushOrgY ) /* GDI.149 */
+DC_GET_VAL( HRGN, GetClipRgn, hClipRgn ) /* GDI.173 */
+DC_GET_VAL( WORD, GetTextAlign, textAlign ) /* GDI.345 */
+DC_SET_VAL( WORD, SetTextAlign, textAlign ) /* GDI.346 */
+DC_GET_VAL( HFONT, GetCurLogFont, hFont ) /* GDI.411 */
+DC_GET_VAL_EX( GetBrushOrgEx, brushOrgX, brushOrgY ) /* GDI.469 */
+DC_GET_VAL_EX( GetCurrentPositionEx, CursPosX, CursPosY ) /* GDI.470 */
+DC_GET_VAL_EX( GetViewportExtEx, VportExtX, VportExtY ) /* GDI.472 */
+DC_GET_VAL_EX( GetViewportOrgEx, VportOrgX, VportOrgY ) /* GDI.473 */
+DC_GET_VAL_EX( GetWindowExtEx, WndExtX, WndExtY ) /* GDI.474 */
+DC_GET_VAL_EX( GetWindowOrgEx, WndOrgX, WndOrgY ) /* GDI.475 */
diff --git a/objects/dib.c b/objects/dib.c
new file mode 100644
index 0000000..839f0b5
--- /dev/null
+++ b/objects/dib.c
@@ -0,0 +1,203 @@
+/*
+ * GDI device independent bitmaps
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdlib.h>
+
+#include "gdi.h"
+
+
+extern XImage * BITMAP_BmpToImage( BITMAP *, void * );
+
+
+/***********************************************************************
+ * DIB_BitmapInfoSize
+ *
+ * Return the size of the bitmap info structure.
+ */
+int DIB_BitmapInfoSize( BITMAPINFO * info, WORD coloruse )
+{
+ int size = info->bmiHeader.biClrUsed;
+ if (!size && (info->bmiHeader.biBitCount != 24))
+ size = 1 << info->bmiHeader.biBitCount;
+ if (coloruse == DIB_RGB_COLORS)
+ size = info->bmiHeader.biSize + size * sizeof(RGBQUAD);
+ else
+ size = info->bmiHeader.biSize + size * sizeof(WORD);
+ return size;
+}
+
+
+/***********************************************************************
+ * DIB_DIBmpToImage
+ *
+ * Create an XImage pointing to the bitmap data.
+ */
+XImage * DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
+{
+ XImage * image;
+ int bytesPerLine = (bmp->biWidth * bmp->biBitCount + 31) / 32 * 4;
+
+ image = XCreateImage( XT_display, DefaultVisualOfScreen( XT_screen ),
+ bmp->biBitCount, ZPixmap, 0, bmpData,
+ bmp->biWidth, bmp->biHeight, 32, bytesPerLine );
+ if (!image) return 0;
+ image->byte_order = MSBFirst;
+ image->bitmap_bit_order = MSBFirst;
+ image->bitmap_unit = 16;
+ _XInitImageFuncPtrs(image);
+ return image;
+}
+
+
+/***********************************************************************
+ * SetDIBits (GDI.440)
+ */
+int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
+ LPSTR bits, BITMAPINFO * info, WORD coloruse )
+{
+ DC * dc;
+ BITMAPOBJ * bmpObj;
+ BITMAP * bmp;
+ WORD * colorMapping;
+ RGBQUAD * rgbPtr;
+ XImage * bmpImage, * dibImage;
+ int i, x, y, pixel, colors;
+
+ if (!lines) return 0;
+ if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+ if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+ return 0;
+ if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
+
+ /* Build the color mapping table */
+
+ if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
+ else if (coloruse == DIB_RGB_COLORS)
+ {
+ colors = info->bmiHeader.biClrUsed;
+ if (!colors) colors = 1 << info->bmiHeader.biBitCount;
+ if (!(colorMapping = (WORD *)malloc( colors * sizeof(WORD) )))
+ {
+ GlobalUnlock( bmpObj->hBitmap );
+ return 0;
+ }
+ for (i = 0, rgbPtr = info->bmiColors; i < colors; i++, rgbPtr++)
+ colorMapping[i] = GetNearestPaletteIndex( dc->w.hPalette,
+ RGB(rgbPtr->rgbRed,
+ rgbPtr->rgbGreen,
+ rgbPtr->rgbBlue) );
+ }
+ else colorMapping = (WORD *)info->bmiColors;
+
+ /* Transfer the pixels (very slow...) */
+
+ bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
+ dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
+
+ for (y = 0; y < lines; y++)
+ {
+ for (x = 0; x < info->bmiHeader.biWidth; x++)
+ {
+ pixel = XGetPixel( dibImage, x, y );
+ if (colorMapping) pixel = colorMapping[pixel];
+ else pixel = GetNearestPaletteIndex(dc->w.hPalette,(COLORREF)pixel);
+ XPutPixel( bmpImage, x, bmp->bmHeight - startscan - y - 1, pixel );
+ }
+ }
+
+ bmpImage->data = NULL;
+ dibImage->data = NULL;
+ XDestroyImage( bmpImage );
+ XDestroyImage( dibImage );
+
+ if (colorMapping && (coloruse == DIB_RGB_COLORS)) free(colorMapping);
+
+ GlobalUnlock( bmpObj->hBitmap );
+ return lines;
+}
+
+
+/***********************************************************************
+ * GetDIBits (GDI.441)
+ */
+int GetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
+ LPSTR bits, BITMAPINFO * info, WORD coloruse )
+{
+ DC * dc;
+ BITMAPOBJ * bmpObj;
+ BITMAP * bmp;
+ PALETTEENTRY * palEntry;
+ PALETTEOBJ * palette;
+ XImage * bmpImage, * dibImage;
+ int i, x, y;
+
+ if (!lines) return 0;
+ if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+ if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+ return 0;
+ if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
+ return 0;
+ if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
+
+ /* Transfer color info */
+
+ palEntry = palette->logpalette.palPalEntry;
+ for (i = 0; i < info->bmiHeader.biClrUsed; i++, palEntry++)
+ {
+ if (coloruse == DIB_RGB_COLORS)
+ {
+ info->bmiColors[i].rgbRed = palEntry->peRed;
+ info->bmiColors[i].rgbGreen = palEntry->peGreen;
+ info->bmiColors[i].rgbBlue = palEntry->peBlue;
+ info->bmiColors[i].rgbReserved = 0;
+ }
+ else ((WORD *)info->bmiColors)[i] = (WORD)i;
+ }
+
+ /* Transfer the pixels (very slow...) */
+
+ if (bits)
+ {
+ bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
+ dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
+
+ for (y = 0; y < lines; y++)
+ {
+ for (x = 0; x < info->bmiHeader.biWidth; x++)
+ {
+ XPutPixel( dibImage, x, y,
+ XGetPixel(bmpImage, x, bmp->bmHeight-startscan-y-1) );
+
+ }
+ }
+
+ bmpImage->data = NULL;
+ dibImage->data = NULL;
+ XDestroyImage( bmpImage );
+ XDestroyImage( dibImage );
+ }
+
+ GlobalUnlock( bmpObj->hBitmap );
+ return lines;
+}
+
+
+/***********************************************************************
+ * CreateDIBitmap (GDI.442)
+ */
+HBITMAP CreateDIBitmap( HDC hdc, BITMAPINFOHEADER * header, DWORD init,
+ LPSTR bits, BITMAPINFO * data, WORD coloruse )
+{
+ HBITMAP handle;
+
+ handle = CreateCompatibleBitmap( hdc, header->biWidth, header->biHeight );
+ if (!handle) return 0;
+ if (init == CBM_INIT) SetDIBits( hdc, handle, 0, header->biHeight,
+ bits, data, coloruse );
+ return handle;
+}
diff --git a/objects/font.c b/objects/font.c
new file mode 100644
index 0000000..c30fcec
--- /dev/null
+++ b/objects/font.c
@@ -0,0 +1,332 @@
+/*
+ * GDI font objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xatom.h>
+#include "gdi.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+
+/***********************************************************************
+ * FONT_MatchFont
+ *
+ * Find a X font matching the logical font.
+ */
+XFontStruct * FONT_MatchFont( DC * dc, LOGFONT * font )
+{
+ char pattern[100];
+ char *family, *weight, *charset;
+ char **names;
+ char slant, spacing;
+ int width, height, count;
+ XFontStruct * fontStruct;
+
+ weight = (font->lfWeight > 550) ? "bold" : "medium";
+ slant = font->lfItalic ? 'i' : 'r';
+ height = 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)
+ {
+ case FF_ROMAN: family = "times"; break;
+ case FF_SWISS: family = "helvetica"; break;
+ case FF_MODERN: family = "courier"; break;
+ case FF_SCRIPT: family = "*"; break;
+ case FF_DECORATIVE: family = "*"; break;
+ default: family = "*"; break;
+ }
+
+ 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 );
+ if (!count)
+ {
+#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;
+}
+
+
+/***********************************************************************
+ * FONT_GetMetrics
+ */
+void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
+ TEXTMETRIC * metrics )
+{
+ int average, i;
+ unsigned long prop;
+
+ metrics->tmAscent = xfont->ascent;
+ metrics->tmDescent = xfont->descent;
+ metrics->tmHeight = xfont->ascent + xfont->descent;
+
+ metrics->tmInternalLeading = 0;
+ if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
+ metrics->tmInternalLeading = xfont->ascent - (short)prop;
+ metrics->tmExternalLeading = 0;
+ metrics->tmMaxCharWidth = xfont->max_bounds.width;
+ metrics->tmWeight = logfont->lfWeight;
+ metrics->tmItalic = logfont->lfItalic;
+ metrics->tmUnderlined = logfont->lfUnderline;
+ metrics->tmStruckOut = logfont->lfStrikeOut;
+ metrics->tmFirstChar = xfont->min_char_or_byte2;
+ metrics->tmLastChar = xfont->max_char_or_byte2;
+ metrics->tmDefaultChar = xfont->default_char;
+ metrics->tmBreakChar = ' ';
+ metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
+ metrics->tmCharSet = logfont->lfCharSet;
+ metrics->tmOverhang = 0;
+ metrics->tmDigitizedAspectX = 1;
+ metrics->tmDigitizedAspectY = 1;
+
+ if (xfont->per_char) average = metrics->tmMaxCharWidth;
+ else
+ {
+ XCharStruct * charPtr = xfont->per_char;
+ average = 0;
+ for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
+ {
+ average += charPtr->width;
+ charPtr++;
+ }
+ average /= metrics->tmLastChar - metrics->tmFirstChar + 1;
+ }
+ metrics->tmAveCharWidth = average;
+}
+
+
+/***********************************************************************
+ * CreateFontIndirect (GDI.57)
+ */
+HFONT CreateFontIndirect( LOGFONT * font )
+{
+ FONTOBJ * fontPtr;
+ HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
+ if (!hfont) return 0;
+ fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
+ memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
+ return hfont;
+}
+
+
+/***********************************************************************
+ * CreateFont (GDI.56)
+ */
+HFONT CreateFont( int height, int width, int esc, int orient, int weight,
+ BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
+ BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
+ LPSTR name )
+{
+ LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
+ strikeout, charset, outpres, clippres, quality, pitch, };
+ strncpy( logfont.lfFaceName, name, LF_FACESIZE );
+ return CreateFontIndirect( &logfont );
+}
+
+
+/***********************************************************************
+ * FONT_GetObject
+ */
+int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
+{
+ if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
+ memcpy( buffer, &font->logfont, count );
+ return count;
+}
+
+
+/***********************************************************************
+ * FONT_SelectObject
+ */
+HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
+{
+ static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
+ X_PHYSFONT * stockPtr;
+ HFONT prevHandle = dc->w.hFont;
+ XFontStruct * fontStruct;
+
+ /* Load font if necessary */
+
+ if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
+ stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
+ else stockPtr = NULL;
+
+ if (!stockPtr || !stockPtr->fstruct)
+ {
+ fontStruct = FONT_MatchFont( dc, &font->logfont );
+ }
+ else
+ {
+ fontStruct = stockPtr->fstruct;
+#ifdef DEBUG_FONT
+ printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
+ hfont, fontStruct );
+#endif
+ }
+ if (!fontStruct) return 0;
+
+ /* Free previous font */
+
+ if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
+ {
+ if (dc->u.x.font.fstruct)
+ XFreeFont( XT_display, dc->u.x.font.fstruct );
+ }
+
+ /* 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
+ {
+ dc->u.x.font.fstruct = fontStruct;
+ FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
+ }
+ return prevHandle;
+}
+
+
+/***********************************************************************
+ * GetTextCharacterExtra (GDI.89)
+ */
+short GetTextCharacterExtra( HDC hdc )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+ return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
+ / dc->w.VportExtX );
+}
+
+
+/***********************************************************************
+ * SetTextCharacterExtra (GDI.8)
+ */
+short SetTextCharacterExtra( HDC hdc, short extra )
+{
+ short prev;
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+ extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
+ prev = dc->w.charExtra;
+ dc->w.charExtra = abs(extra);
+ return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
+}
+
+
+/***********************************************************************
+ * SetTextJustification (GDI.10)
+ */
+short SetTextJustification( HDC hdc, short extra, short breaks )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+
+ extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
+ if (!extra) breaks = 0;
+ dc->w.breakTotalExtra = extra;
+ dc->w.breakCount = breaks;
+ if (breaks)
+ {
+ dc->w.breakExtra = extra / breaks;
+ dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
+ }
+ else
+ {
+ dc->w.breakExtra = 0;
+ dc->w.breakRem = 0;
+ }
+ return 1;
+}
+
+
+/***********************************************************************
+ * GetTextExtent (GDI.91)
+ */
+DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
+{
+ SIZE size;
+ if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
+ return size.cx | (size.cy << 16);
+}
+
+
+/***********************************************************************
+ * GetTextExtentPoint (GDI.471)
+ */
+BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
+{
+ int dir, ascent, descent;
+ XCharStruct info;
+
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return FALSE;
+ XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
+ &ascent, &descent, &info );
+ size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
+ * dc->w.WndExtX / dc->w.VportExtX);
+ 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",
+ hdc, str, count, size, size->cx, size->cy );
+#endif
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetTextMetrics (GDI.93)
+ */
+BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
+{
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return FALSE;
+ memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
+
+ metrics->tmAscent = abs( metrics->tmAscent
+ * dc->w.WndExtY / dc->w.VportExtY );
+ metrics->tmDescent = abs( metrics->tmDescent
+ * dc->w.WndExtY / dc->w.VportExtY );
+ metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
+ metrics->tmInternalLeading = abs( metrics->tmInternalLeading
+ * dc->w.WndExtY / dc->w.VportExtY );
+ metrics->tmExternalLeading = abs( metrics->tmExternalLeading
+ * dc->w.WndExtY / dc->w.VportExtY );
+ metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
+ * dc->w.WndExtX / dc->w.VportExtX );
+ metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
+ * dc->w.WndExtX / dc->w.VportExtX );
+ return TRUE;
+}
+
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
new file mode 100644
index 0000000..55237c3
--- /dev/null
+++ b/objects/gdiobj.c
@@ -0,0 +1,380 @@
+/*
+ * GDI functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "gdi.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+MDESC *GDI_Heap = NULL;
+
+
+/***********************************************************************
+ * GDI stock objects
+ */
+
+static BRUSHOBJ WhiteBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_SOLID, RGB(255,255,255), 0 } /* logbrush */
+};
+
+static BRUSHOBJ LtGrayBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_SOLID, RGB(192,192,192), 0 } /* logbrush */
+};
+
+static BRUSHOBJ GrayBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_SOLID, RGB(128,128,128), 0 } /* logbrush */
+};
+
+static BRUSHOBJ DkGrayBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_SOLID, RGB(64,64,64), 0 } /* logbrush */
+};
+
+static BRUSHOBJ BlackBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_SOLID, RGB(0,0,0), 0 } /* logbrush */
+};
+
+static BRUSHOBJ NullBrush =
+{
+ { 0, BRUSH_MAGIC, 1, 0 }, /* header */
+ { BS_NULL, 0, 0 } /* logbrush */
+};
+
+static PENOBJ WhitePen =
+{
+ { 0, PEN_MAGIC, 1, 0 }, /* header */
+ { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
+};
+
+static PENOBJ BlackPen =
+{
+ { 0, PEN_MAGIC, 1, 0 }, /* header */
+ { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
+};
+
+static PENOBJ NullPen =
+{
+ { 0, PEN_MAGIC, 1, 0 }, /* header */
+ { PS_NULL, { 1, 0 }, 0 } /* logpen */
+};
+
+static FONTOBJ OEMFixedFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
+};
+
+static FONTOBJ AnsiFixedFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
+};
+
+static FONTOBJ AnsiVarFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
+};
+
+static FONTOBJ SystemFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
+};
+
+static FONTOBJ DeviceDefaultFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
+};
+
+static FONTOBJ SystemFixedFont =
+{
+ { 0, FONT_MAGIC, 1, 0 }, /* header */
+ { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
+};
+
+
+static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
+{
+ (GDIOBJHDR *) &WhiteBrush,
+ (GDIOBJHDR *) &LtGrayBrush,
+ (GDIOBJHDR *) &GrayBrush,
+ (GDIOBJHDR *) &DkGrayBrush,
+ (GDIOBJHDR *) &BlackBrush,
+ (GDIOBJHDR *) &NullBrush,
+ (GDIOBJHDR *) &WhitePen,
+ (GDIOBJHDR *) &BlackPen,
+ (GDIOBJHDR *) &NullPen,
+ NULL,
+ (GDIOBJHDR *) &OEMFixedFont,
+ (GDIOBJHDR *) &AnsiFixedFont,
+ (GDIOBJHDR *) &AnsiVarFont,
+ (GDIOBJHDR *) &SystemFont,
+ (GDIOBJHDR *) &DeviceDefaultFont,
+ NULL, /* DEFAULT_PALETTE created by PALETTE_Init */
+ (GDIOBJHDR *) &SystemFixedFont
+};
+
+extern GDIOBJHDR * PALETTE_systemPalette;
+
+
+/***********************************************************************
+ * GDI_Init
+ *
+ * GDI initialisation.
+ */
+BOOL GDI_Init()
+{
+ struct segment_descriptor_s * s;
+
+ /* Create GDI heap */
+
+ s = GetNextSegment( 0, 0x10000 );
+ if (s == NULL) return FALSE;
+ HEAP_Init( &GDI_Heap, s->base_addr, GDI_HEAP_SIZE );
+ free(s);
+
+ /* Create default palette */
+
+ PALETTE_Init();
+ StockObjects[DEFAULT_PALETTE] = PALETTE_systemPalette;
+
+ /* Create default bitmap */
+
+ if (!BITMAP_Init()) return FALSE;
+
+ /* Initialise regions */
+
+ if (!REGION_Init()) return FALSE;
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GDI_FindPrevObject
+ *
+ * Return the GDI object whose hNext field points to obj.
+ */
+HANDLE GDI_FindPrevObject( HANDLE first, HANDLE obj )
+{
+ HANDLE handle;
+
+ for (handle = first; handle && (handle != obj); )
+ {
+ GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ handle = header->hNext;
+ }
+ return handle;
+}
+
+
+/***********************************************************************
+ * GDI_AllocObject
+ */
+HANDLE GDI_AllocObject( WORD size, WORD magic )
+{
+ static DWORD count = 0;
+ GDIOBJHDR * obj;
+ HANDLE handle = GDI_HEAP_ALLOC( GMEM_MOVEABLE, size );
+ if (!handle) return 0;
+
+ obj = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ obj->hNext = 0;
+ obj->wMagic = magic;
+ obj->dwCount = ++count;
+ return handle;
+}
+
+
+/***********************************************************************
+ * GDI_FreeObject
+ */
+BOOL GDI_FreeObject( HANDLE handle )
+{
+ GDIOBJHDR * object;
+ HANDLE prev;
+
+ /* Can't free stock objects */
+ if (handle >= FIRST_STOCK_HANDLE) return FALSE;
+
+ object = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ if (!object) return FALSE;
+
+ /* Free object */
+
+ GDI_HEAP_FREE( handle );
+ return TRUE;
+}
+
+/***********************************************************************
+ * GDI_GetObjPtr
+ *
+ * Return a pointer to the GDI object associated to the handle.
+ * Return NULL if the object has the wrong magic number.
+ */
+GDIOBJHDR * GDI_GetObjPtr( HANDLE handle, WORD magic )
+{
+ GDIOBJHDR * ptr = NULL;
+
+ if (handle >= FIRST_STOCK_HANDLE)
+ {
+ if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
+ ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
+ }
+ else ptr = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ if (!ptr) return NULL;
+ if (ptr->wMagic != magic) return NULL;
+ return ptr;
+}
+
+
+/***********************************************************************
+ * DeleteObject (GDI.69)
+ */
+BOOL DeleteObject( HANDLE obj )
+{
+ /* Check if object is valid */
+
+ GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_ADDR( obj );
+ if (!header) return FALSE;
+
+#ifdef DEBUG_GDI
+ printf( "DeleteObject: %d\n", obj );
+#endif
+
+ /* Delete object */
+
+ switch(header->wMagic)
+ {
+ case PEN_MAGIC: return GDI_FreeObject( obj );
+ case BRUSH_MAGIC: return BRUSH_DeleteObject( obj, header );
+ case FONT_MAGIC: return GDI_FreeObject( obj );
+ case PALETTE_MAGIC: return GDI_FreeObject( obj );
+ case BITMAP_MAGIC: return BMP_DeleteObject( obj, header );
+ case REGION_MAGIC: return REGION_DeleteObject( obj, header );
+ }
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * GetStockObject (GDI.87)
+ */
+HANDLE GetStockObject( int obj )
+{
+ 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
+ return FIRST_STOCK_HANDLE + obj;
+}
+
+
+/***********************************************************************
+ * GetObject (GDI.82)
+ */
+int GetObject( HANDLE handle, int count, LPSTR buffer )
+{
+ GDIOBJHDR * ptr = NULL;
+#ifdef DEBUG_GDI
+ printf( "GetObject: %04x %d %08x\n", handle, count, buffer );
+#endif
+ if (!count) return 0;
+
+ if (handle >= FIRST_STOCK_HANDLE)
+ {
+ if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
+ ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
+ }
+ else ptr = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ if (!ptr) return 0;
+
+ switch(ptr->wMagic)
+ {
+ case PEN_MAGIC:
+ return PEN_GetObject( (PENOBJ *)ptr, count, buffer );
+ case BRUSH_MAGIC:
+ return BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
+ case BITMAP_MAGIC:
+ return BMP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
+ case FONT_MAGIC:
+ return FONT_GetObject( (FONTOBJ *)ptr, count, buffer );
+ case PALETTE_MAGIC:
+ return PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * SelectObject (GDI.45)
+ */
+HANDLE SelectObject( HDC hdc, HANDLE handle )
+{
+ GDIOBJHDR * ptr = NULL;
+ DC * dc;
+
+#ifdef DEBUG_GDI
+ printf( "SelectObject: %d %04x\n", hdc, handle );
+#endif
+ if (handle >= FIRST_STOCK_HANDLE)
+ {
+ if (handle < FIRST_STOCK_HANDLE + NB_STOCK_OBJECTS)
+ ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
+ }
+ else ptr = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+ if (!ptr) return 0;
+
+ dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return 0;
+
+ switch(ptr->wMagic)
+ {
+ case PEN_MAGIC:
+ return PEN_SelectObject( dc, handle, (PENOBJ *)ptr );
+ case BRUSH_MAGIC:
+ return BRUSH_SelectObject( hdc, dc, handle, (BRUSHOBJ *)ptr );
+ case BITMAP_MAGIC:
+ return BITMAP_SelectObject( hdc, dc, handle, (BITMAPOBJ *)ptr );
+ case FONT_MAGIC:
+ return FONT_SelectObject( dc, handle, (FONTOBJ *)ptr );
+ case REGION_MAGIC:
+ return SelectClipRgn( hdc, handle );
+ }
+ return 0;
+}
+
+
+/***********************************************************************
+ * UnrealizeObject (GDI.150)
+ */
+BOOL UnrealizeObject( HANDLE handle )
+{
+#ifdef DEBUG_GDI
+ printf( "UnrealizeObject: %04x\n", handle );
+#endif
+ return TRUE;
+}
diff --git a/objects/linedda.c b/objects/linedda.c
new file mode 100644
index 0000000..f95ea48
--- /dev/null
+++ b/objects/linedda.c
@@ -0,0 +1,19 @@
+/*
+ * LineDDA
+ *
+ * Copyright 1993 Bob Amstadt
+ */
+
+static char Copyright[] = "Copyright Bob Amstadt, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include "win.h"
+
+/**********************************************************************
+ * LineDDA (GDI.100)
+ */
+void LineDDA(short nXStart, short nYStart, short nXEnd, short nYEnd,
+ FARPROC callback, long lParam)
+{
+}
diff --git a/objects/palette.c b/objects/palette.c
new file mode 100644
index 0000000..bdde29d
--- /dev/null
+++ b/objects/palette.c
@@ -0,0 +1,191 @@
+/*
+ * GDI palette objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdlib.h>
+#include <values.h>
+#include <X11/Xlib.h>
+
+#include "gdi.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+
+#define NB_RESERVED_COLORS 17
+static char * ReservedColors[NB_RESERVED_COLORS] =
+{
+ "black",
+ "gray25",
+ "gray50",
+ "gray75",
+ "white",
+ "red1",
+ "red4",
+ "green1",
+ "green4",
+ "blue1",
+ "blue4",
+ "cyan1",
+ "cyan4",
+ "magenta1",
+ "magenta4",
+ "yellow1",
+ "yellow4"
+};
+
+GDIOBJHDR * PALETTE_systemPalette;
+
+static int SysColorPixels[NB_RESERVED_COLORS];
+
+
+/***********************************************************************
+ * PALETTE_Init
+ */
+BOOL PALETTE_Init()
+{
+ int i, size, pixel;
+ XColor serverColor, exactColor;
+ HPALETTE hpalette;
+ LOGPALETTE * palPtr;
+
+ size = DefaultVisual(XT_display,DefaultScreen(XT_display))->map_entries;
+ palPtr = malloc( sizeof(LOGPALETTE) + (size-1)*sizeof(PALETTEENTRY) );
+ if (!palPtr) return FALSE;
+ palPtr->palVersion = 0x300;
+ palPtr->palNumEntries = size;
+ memset( palPtr->palPalEntry, 0xff, size*sizeof(PALETTEENTRY) );
+
+ for (i = 0; i < NB_RESERVED_COLORS; i++)
+ {
+ if (XAllocNamedColor( XT_display,
+ DefaultColormapOfScreen( XT_screen ),
+ ReservedColors[i],
+ &serverColor, &exactColor ))
+ {
+ pixel = serverColor.pixel;
+ palPtr->palPalEntry[pixel].peRed = serverColor.red >> 8;
+ palPtr->palPalEntry[pixel].peGreen = serverColor.green >> 8;
+ palPtr->palPalEntry[pixel].peBlue = serverColor.blue >> 8;
+ palPtr->palPalEntry[pixel].peFlags = 0;
+ }
+ }
+ hpalette = CreatePalette( palPtr );
+ PALETTE_systemPalette = (GDIOBJHDR *) GDI_HEAP_ADDR( hpalette );
+ free( palPtr );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * CreatePalette (GDI.360)
+ */
+HPALETTE CreatePalette( LOGPALETTE * palette )
+{
+ PALETTEOBJ * palettePtr;
+ HPALETTE hpalette;
+ int size;
+
+ size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);
+ hpalette = GDI_AllocObject( sizeof(GDIOBJHDR) + size, PALETTE_MAGIC );
+ if (!hpalette) return 0;
+ palettePtr = (PALETTEOBJ *) GDI_HEAP_ADDR( hpalette );
+ memcpy( &palettePtr->logpalette, palette, size );
+ return hpalette;
+}
+
+
+/***********************************************************************
+ * GetPaletteEntries (GDI.363)
+ */
+WORD GetPaletteEntries( HPALETTE hpalette, WORD start, WORD count,
+ LPPALETTEENTRY entries )
+{
+ PALETTEOBJ * palPtr;
+ int numEntries;
+
+ palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
+ if (!palPtr) return 0;
+ numEntries = palPtr->logpalette.palNumEntries;
+ if (start >= numEntries) return 0;
+ if (start+count > numEntries) count = numEntries - start;
+ memcpy( entries, &palPtr->logpalette.palPalEntry[start],
+ count * sizeof(PALETTEENTRY) );
+ return count;
+}
+
+
+/***********************************************************************
+ * SetPaletteEntries (GDI.364)
+ */
+WORD SetPaletteEntries( HPALETTE hpalette, WORD start, WORD count,
+ LPPALETTEENTRY entries )
+{
+ PALETTEOBJ * palPtr;
+ int numEntries;
+
+ palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
+ if (!palPtr) return 0;
+ numEntries = palPtr->logpalette.palNumEntries;
+ if (start >= numEntries) return 0;
+ if (start+count > numEntries) count = numEntries - start;
+ memcpy( &palPtr->logpalette.palPalEntry[start], entries,
+ count * sizeof(PALETTEENTRY) );
+ return count;
+}
+
+
+/***********************************************************************
+ * GetNearestPaletteIndex (GDI.370)
+ */
+WORD GetNearestPaletteIndex( HPALETTE hpalette, COLORREF color )
+{
+ int i, minDist, dist;
+ WORD index = 0;
+ BYTE r, g, b;
+ PALETTEENTRY * entry;
+ PALETTEOBJ * palPtr;
+
+ palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
+ if (!palPtr) return 0;
+
+ r = GetRValue(color);
+ g = GetGValue(color);
+ b = GetBValue(color);
+ entry = palPtr->logpalette.palPalEntry;
+ for (i = 0, minDist = MAXINT; i < palPtr->logpalette.palNumEntries; i++)
+ {
+ if (entry->peFlags != 0xff)
+ {
+ dist = (r - entry->peRed) * (r - entry->peRed) +
+ (g - entry->peGreen) * (g - entry->peGreen) +
+ (b - entry->peBlue) * (b - entry->peBlue);
+ if (dist < minDist)
+ {
+ minDist = dist;
+ index = i;
+ }
+ }
+ entry++;
+ }
+#ifdef DEBUG_GDI
+ printf( "GetNearestPaletteIndex(%x,%06x) : returning %d\n",
+ hpalette, color, index );
+#endif
+ return index;
+}
+
+
+/***********************************************************************
+ * PALETTE_GetObject
+ */
+int PALETTE_GetObject( PALETTEOBJ * palette, int count, LPSTR buffer )
+{
+ if (count > sizeof(WORD)) count = sizeof(WORD);
+ memcpy( buffer, &palette->logpalette.palNumEntries, count );
+ return count;
+}
diff --git a/objects/pen.c b/objects/pen.c
new file mode 100644
index 0000000..fa49ef3
--- /dev/null
+++ b/objects/pen.c
@@ -0,0 +1,93 @@
+/*
+ * GDI pen objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include "gdi.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+
+/***********************************************************************
+ * CreatePen (GDI.61)
+ */
+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
+ return CreatePenIndirect( &logpen );
+}
+
+
+/***********************************************************************
+ * CreatePenIndirect (GDI.62)
+ */
+HPEN CreatePenIndirect( LOGPEN * pen )
+{
+ PENOBJ * penPtr;
+ HPEN hpen;
+
+ if (pen->lopnStyle > PS_INSIDEFRAME) return 0;
+ hpen = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC );
+ if (!hpen) return 0;
+ penPtr = (PENOBJ *) GDI_HEAP_ADDR( hpen );
+ memcpy( &penPtr->logpen, pen, sizeof(LOGPEN) );
+ return hpen;
+}
+
+
+/***********************************************************************
+ * PEN_GetObject
+ */
+int PEN_GetObject( PENOBJ * pen, int count, LPSTR buffer )
+{
+ if (count > sizeof(LOGPEN)) count = sizeof(LOGPEN);
+ memcpy( buffer, &pen->logpen, count );
+ return count;
+}
+
+
+/***********************************************************************
+ * PEN_SelectObject
+ */
+HPEN PEN_SelectObject( DC * dc, HPEN hpen, PENOBJ * pen )
+{
+ static char dash_dash[] = { 5, 3 }; /* ----- ----- ----- */
+ static char dash_dot[] = { 2, 2 }; /* -- -- -- -- -- -- */
+ static char dash_dashdot[] = { 4,3,2,3 }; /* ---- -- ---- -- */
+ static char dash_dashdotdot[] = { 4,2,2,2,2,2 }; /* ---- -- -- ---- */
+
+ HPEN 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->w.VportExtX
+ / dc->w.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 = GetNearestPaletteIndex( dc->w.hPalette,
+ pen->logpen.lopnColor );
+ switch(pen->logpen.lopnStyle)
+ {
+ case PS_DASH:
+ XSetDashes( XT_display, dc->u.x.gc, 0, dash_dash, 2 );
+ break;
+ case PS_DOT:
+ XSetDashes( XT_display, dc->u.x.gc, 0, dash_dot, 2 );
+ break;
+ case PS_DASHDOT:
+ XSetDashes( XT_display, dc->u.x.gc, 0, dash_dashdot, 4 );
+ break;
+ case PS_DASHDOTDOT:
+ XSetDashes( XT_display, dc->u.x.gc, 0, dash_dashdotdot, 6 );
+ break;
+ }
+
+ return prevHandle;
+}
diff --git a/objects/region.c b/objects/region.c
new file mode 100644
index 0000000..2c22ee4
--- /dev/null
+++ b/objects/region.c
@@ -0,0 +1,614 @@
+/*
+ * GDI region objects
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "gdi.h"
+
+
+ /* GC used for region operations */
+static GC regionGC = 0;
+
+
+/***********************************************************************
+ * REGION_Init
+ */
+BOOL REGION_Init()
+{
+ Pixmap tmpPixmap;
+
+ /* CreateGC needs a drawable */
+ tmpPixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
+ 1, 1, 1 );
+ if (tmpPixmap)
+ {
+ regionGC = XCreateGC( XT_display, tmpPixmap, 0, NULL );
+ XFreePixmap( XT_display, tmpPixmap );
+ if (!regionGC) return FALSE;
+ XSetForeground( XT_display, regionGC, 1 );
+ return TRUE;
+ }
+ else return FALSE;
+}
+
+
+/***********************************************************************
+ * REGION_SetRect
+ *
+ * Set the bounding box of the region and create the pixmap.
+ * The hrgn must be valid.
+ */
+static BOOL REGION_SetRect( HRGN hrgn, LPRECT rect )
+{
+ int width, height;
+
+ /* Fill region */
+
+ REGION * region = &((RGNOBJ *)GDI_HEAP_ADDR( hrgn ))->region;
+ width = rect->right - rect->left;
+ height = rect->bottom - rect->top;
+ if ((width <= 0) || (height <= 0))
+ {
+ region->type = NULLREGION;
+ region->box.left = 0;
+ region->box.right = 0;
+ region->box.top = 0;
+ region->box.bottom = 0;
+ region->pixmap = 0;
+ return TRUE;
+ }
+ region->type = SIMPLEREGION;
+ region->box = *rect;
+
+ /* Create pixmap */
+
+ region->pixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
+ width, height, 1 );
+ if (!region->pixmap) return FALSE;
+
+ /* Fill pixmap */
+
+ XSetFunction( XT_display, regionGC, GXclear );
+ XFillRectangle( XT_display, region->pixmap, regionGC,
+ 0, 0, width, height );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * REGION_DeleteObject
+ */
+BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj )
+{
+ if (obj->region.pixmap) XFreePixmap( XT_display, obj->region.pixmap );
+ return GDI_FreeObject( hrgn );
+}
+
+
+/***********************************************************************
+ * OffsetRgn (GDI.101)
+ */
+int OffsetRgn( HRGN hrgn, short x, short y )
+{
+ 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
+ OffsetRect( &obj->region.box, x, y );
+ return obj->region.type;
+}
+
+
+/***********************************************************************
+ * GetRgnBox (GDI.134)
+ */
+int GetRgnBox( HRGN hrgn, LPRECT rect )
+{
+ RGNOBJ * obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
+ if (!obj) return ERROR;
+#ifdef DEBUG_REGION
+ printf( "GetRgnBox: %d\n", hrgn );
+#endif
+ *rect = obj->region.box;
+ return obj->region.type;
+}
+
+
+/***********************************************************************
+ * CreateRectRgn (GDI.64)
+ */
+HRGN CreateRectRgn( short left, short top, short right, short bottom )
+{
+ RECT rect = { left, top, right, bottom };
+ return CreateRectRgnIndirect( &rect );
+}
+
+
+/***********************************************************************
+ * CreateRectRgnIndirect (GDI.65)
+ */
+HRGN CreateRectRgnIndirect( LPRECT rect )
+{
+ RGNOBJ * rgnObj;
+ HRGN hrgn;
+
+#ifdef DEBUG_REGION
+ printf( "CreateRectRgnIndirect: %d,%d-%d,%d\n",
+ rect->left, rect->top, rect->right, rect->bottom );
+#endif
+
+ /* Create region */
+
+ if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
+ if (!REGION_SetRect( hrgn, rect ))
+ {
+ GDI_FreeObject( hrgn );
+ return 0;
+ }
+ rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
+
+ /* Fill pixmap */
+
+ if (rgnObj->region.type != NULLREGION)
+ {
+ int width = rgnObj->region.box.right - rgnObj->region.box.left;
+ int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
+ XSetFunction( XT_display, regionGC, GXcopy );
+ XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, 0, width, height );
+ }
+
+ return hrgn;
+}
+
+
+/***********************************************************************
+ * CreateRoundRectRgn (GDI.444)
+ */
+HRGN CreateRoundRectRgn( short left, short top, short right, short bottom,
+ short ellipse_width, short ellipse_height )
+{
+ RECT rect = { left, top, right, bottom };
+ RGNOBJ * rgnObj;
+ HRGN hrgn;
+
+#ifdef DEBUG_REGION
+ printf( "CreateRoundRectRgn: %d,%d-%d,%d %dx%d\n",
+ left, top, right, bottom, ellipse_width, ellipse_height );
+#endif
+
+ /* Create region */
+
+ if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
+ if (!REGION_SetRect( hrgn, &rect ))
+ {
+ GDI_FreeObject( hrgn );
+ return 0;
+ }
+ rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
+
+ /* Fill pixmap */
+
+ if (rgnObj->region.type != NULLREGION)
+ {
+ int width = rgnObj->region.box.right - rgnObj->region.box.left;
+ int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
+ XSetFunction( XT_display, regionGC, GXcopy );
+ XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, ellipse_height / 2,
+ width, height - ellipse_height );
+ XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+ ellipse_width / 2, 0,
+ width - ellipse_width, height );
+ XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, 0,
+ ellipse_width, ellipse_height, 0, 360*64 );
+ XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+ width - ellipse_width, 0,
+ ellipse_width, ellipse_height, 0, 360*64 );
+ XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, height - ellipse_height,
+ ellipse_width, ellipse_height, 0, 360*64 );
+ XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+ width - ellipse_width, height - ellipse_height,
+ ellipse_width, ellipse_height, 0, 360*64 );
+ }
+
+ return hrgn;
+}
+
+
+/***********************************************************************
+ * SetRectRgn (GDI.172)
+ */
+void SetRectRgn( HRGN hrgn, short left, short top, short right, short bottom )
+{
+ 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
+
+ /* Free previous pixmap */
+
+ if (!(rgnObj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return;
+ if (rgnObj->region.pixmap)
+ XFreePixmap( XT_display, rgnObj->region.pixmap );
+
+ if (!REGION_SetRect( hrgn, &rect )) return;
+
+ /* Fill pixmap */
+
+ if (rgnObj->region.type != NULLREGION)
+ {
+ int width = rgnObj->region.box.right - rgnObj->region.box.left;
+ int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
+ XSetFunction( XT_display, regionGC, GXcopy );
+ XFillRectangle( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, 0, width, height );
+ }
+}
+
+
+/***********************************************************************
+ * CreateEllipticRgn (GDI.54)
+ */
+HRGN CreateEllipticRgn( short left, short top, short right, short bottom )
+{
+ RECT rect = { left, top, right, bottom };
+ return CreateEllipticRgnIndirect( &rect );
+}
+
+
+/***********************************************************************
+ * CreateEllipticRgnIndirect (GDI.55)
+ */
+HRGN CreateEllipticRgnIndirect( LPRECT rect )
+{
+ RGNOBJ * rgnObj;
+ HRGN hrgn;
+
+#ifdef DEBUG_REGION
+ printf( "CreateEllipticRgnIndirect: %d,%d-%d,%d\n",
+ rect->left, rect->top, rect->right, rect->bottom );
+#endif
+
+ /* Create region */
+
+ if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC ))) return 0;
+ if (!REGION_SetRect( hrgn, rect ))
+ {
+ GDI_FreeObject( hrgn );
+ return 0;
+ }
+ rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
+
+ /* Fill pixmap */
+
+ if (rgnObj->region.type != NULLREGION)
+ {
+ int width = rgnObj->region.box.right - rgnObj->region.box.left;
+ int height = rgnObj->region.box.bottom - rgnObj->region.box.top;
+ XSetFunction( XT_display, regionGC, GXcopy );
+ XFillArc( XT_display, rgnObj->region.pixmap, regionGC,
+ 0, 0, width, height, 0, 360*64 );
+ }
+
+ return hrgn;
+}
+
+
+/***********************************************************************
+ * CreatePolygonRgn (GDI.63)
+ */
+HRGN CreatePolygonRgn( POINT * points, short count, short mode )
+{
+ return CreatePolyPolygonRgn( points, &count, 1, mode );
+}
+
+
+/***********************************************************************
+ * CreatePolyPolygonRgn (GDI.451)
+ */
+HRGN CreatePolyPolygonRgn( POINT * points, short * count,
+ short nbpolygons, short mode )
+{
+ RGNOBJ * rgnObj;
+ HRGN hrgn;
+ RECT box;
+ int i, j, totalPoints;
+ POINT * pt;
+ XPoint * xpoints;
+
+ if (!nbpolygons) return 0;
+#ifdef DEBUG_REGION
+ printf( "CreatePolyPolygonRgn: %d polygons\n", nbpolygons );
+#endif
+
+ /* Find bounding box */
+
+ box.top = box.left = 32767;
+ box.right = box.bottom = 0;
+ for (i = totalPoints = 0, pt = points; i < nbpolygons; i++)
+ {
+ totalPoints += count[i];
+ for (j = 0; j < count[i]; j++, pt++)
+ {
+ if (pt->x < box.left) box.left = pt->x;
+ if (pt->x > box.right) box.right = pt->x;
+ if (pt->y < box.top) box.top = pt->y;
+ if (pt->y > box.bottom) box.bottom = pt->y;
+ }
+ }
+ if (!totalPoints) return 0;
+
+ /* Build points array */
+
+ xpoints = (XPoint *) malloc( sizeof(XPoint) * totalPoints );
+ if (!xpoints) return 0;
+ for (i = 0, pt = points; i < totalPoints; i++, pt++)
+ {
+ xpoints[i].x = pt->x - box.left;
+ xpoints[i].y = pt->y - box.top;
+ }
+
+ /* Create region */
+
+ if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )) ||
+ !REGION_SetRect( hrgn, &box ))
+ {
+ if (hrgn) GDI_FreeObject( hrgn );
+ free( xpoints );
+ return 0;
+ }
+ rgnObj = (RGNOBJ *) GDI_HEAP_ADDR( hrgn );
+
+ /* Fill pixmap */
+
+ if (rgnObj->region.type != NULLREGION)
+ {
+ XSetFunction( XT_display, regionGC, GXcopy );
+ if (mode == WINDING) XSetFillRule( XT_display, regionGC, WindingRule );
+ else XSetFillRule( XT_display, regionGC, EvenOddRule );
+ for (i = j = 0; i < nbpolygons; i++)
+ {
+ XFillPolygon( XT_display, rgnObj->region.pixmap, regionGC,
+ &xpoints[j], count[i], Complex, CoordModeOrigin );
+ j += count[i];
+ }
+ }
+
+ free( xpoints );
+ return hrgn;
+}
+
+
+/***********************************************************************
+ * PtInRegion (GDI.161)
+ */
+BOOL PtInRegion( HRGN hrgn, short x, short y )
+{
+ XImage * image;
+ BOOL res;
+ RGNOBJ * obj;
+ POINT pt = { x, y };
+
+ if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
+ if (!PtInRect( &obj->region.box, pt )) return FALSE;
+ image = XGetImage( XT_display, obj->region.pixmap,
+ x - obj->region.box.left, y - obj->region.box.top,
+ 1, 1, AllPlanes, ZPixmap );
+ if (!image) return FALSE;
+ res = (XGetPixel( image, 0, 0 ) != 0);
+ XDestroyImage( image );
+ return res;
+}
+
+
+/***********************************************************************
+ * RectInRegion (GDI.181)
+ */
+BOOL RectInRegion( HRGN hrgn, LPRECT rect )
+{
+ XImage * image;
+ RGNOBJ * obj;
+ RECT intersect;
+ int x, y;
+
+ if (!(obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return FALSE;
+ if (!IntersectRect( &intersect, &obj->region.box, rect )) return FALSE;
+
+ image = XGetImage( XT_display, obj->region.pixmap,
+ intersect.left - obj->region.box.left,
+ intersect.top - obj->region.box.top,
+ intersect.right - intersect.left,
+ intersect.bottom - intersect.top,
+ AllPlanes, ZPixmap );
+ if (!image) return FALSE;
+ for (y = 0; y < image->height; y++)
+ for (x = 0; x < image->width; x++)
+ if (XGetPixel( image, x, y ) != 0)
+ {
+ XDestroyImage( image );
+ return TRUE;
+ }
+
+ XDestroyImage( image );
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * EqualRgn (GDI.72)
+ */
+BOOL EqualRgn( HRGN rgn1, HRGN rgn2 )
+{
+ RGNOBJ *obj1, *obj2;
+ XImage *image1, *image2;
+ int width, height, x, y;
+
+ /* Compare bounding boxes */
+
+ if (!(obj1 = (RGNOBJ *) GDI_GetObjPtr( rgn1, REGION_MAGIC ))) return FALSE;
+ if (!(obj2 = (RGNOBJ *) GDI_GetObjPtr( rgn2, REGION_MAGIC ))) return FALSE;
+ if (obj1->region.type == NULLREGION)
+ return (obj2->region.type == NULLREGION);
+ else if (obj2->region.type == NULLREGION) return FALSE;
+ if (!EqualRect( &obj1->region.box, &obj2->region.box )) return FALSE;
+
+ /* Get pixmap contents */
+
+ width = obj1->region.box.right - obj1->region.box.left;
+ height = obj1->region.box.bottom - obj1->region.box.top;
+ image1 = XGetImage( XT_display, obj1->region.pixmap,
+ 0, 0, width, height, AllPlanes, ZPixmap );
+ if (!image1) return FALSE;
+ image2 = XGetImage( XT_display, obj2->region.pixmap,
+ 0, 0, width, height, AllPlanes, ZPixmap );
+ if (!image2)
+ {
+ XDestroyImage( image1 );
+ return FALSE;
+ }
+
+ /* Compare pixmaps */
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ if (XGetPixel( image1, x, y ) != XGetPixel( image2, x, y))
+ {
+ XDestroyImage( image1 );
+ XDestroyImage( image2 );
+ return FALSE;
+ }
+
+ XDestroyImage( image1 );
+ XDestroyImage( image2 );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * REGION_CopyIntersection
+ *
+ * Copy to dest->pixmap the area of src->pixmap delimited by
+ * the intersection of dest and src regions, using the current GC function.
+ */
+void REGION_CopyIntersection( REGION * dest, REGION * src )
+{
+ RECT inter;
+ if (!IntersectRect( &inter, &dest->box, &src->box )) return;
+ XCopyArea( XT_display, src->pixmap, dest->pixmap, regionGC,
+ inter.left - src->box.left, inter.top - src->box.top,
+ inter.right - inter.left, inter.bottom - inter.top,
+ inter.left - dest->box.left, inter.top - dest->box.top );
+}
+
+
+/***********************************************************************
+ * CombineRgn (GDI.451)
+ */
+int CombineRgn( HRGN hDest, HRGN hSrc1, HRGN hSrc2, short mode )
+{
+ RGNOBJ *destObj, *src1Obj, *src2Obj;
+ REGION * region;
+ int width, height;
+ BOOL res;
+
+#ifdef DEBUG_REGION
+ printf( "CombineRgn: %d %d %d %d\n", hDest, hSrc1, hSrc2, mode );
+#endif
+
+ 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;
+ region = &destObj->region;
+
+ switch(mode)
+ {
+ case RGN_AND:
+ res = IntersectRect( ®ion->box, &src1Obj->region.box,
+ &src2Obj->region.box );
+ break;
+
+ case RGN_OR:
+ case RGN_XOR:
+ res = UnionRect( ®ion->box, &src1Obj->region.box,
+ &src2Obj->region.box );
+ break;
+
+ case RGN_DIFF:
+ res = SubtractRect( ®ion->box, &src1Obj->region.box,
+ &src2Obj->region.box );
+ break;
+
+ case RGN_COPY:
+ region->box = src1Obj->region.box;
+ region->type = src1Obj->region.type;
+ res = (region->type != NULLREGION);
+ break;
+
+ default:
+ return ERROR;
+ }
+
+ if (region->pixmap) XFreePixmap( XT_display, region->pixmap );
+ if (!res)
+ {
+ region->type = NULLREGION;
+ region->pixmap = 0;
+ return NULLREGION;
+ }
+
+ width = region->box.right - region->box.left;
+ height = region->box.bottom - region->box.top;
+ region->pixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
+ width, height, 1 );
+
+ switch(mode)
+ {
+ case RGN_AND:
+ XSetFunction( XT_display, regionGC, GXcopy );
+ REGION_CopyIntersection( region, &src1Obj->region );
+ XSetFunction( XT_display, regionGC, GXand );
+ REGION_CopyIntersection( region, &src2Obj->region );
+ return COMPLEXREGION;
+
+ case RGN_OR:
+ case RGN_XOR:
+ XSetFunction( XT_display, regionGC, GXclear );
+ XFillRectangle( XT_display, region->pixmap, regionGC,
+ 0, 0, width, height );
+ XSetFunction( XT_display, regionGC, (mode == RGN_OR) ? GXor : GXxor);
+ REGION_CopyIntersection( region, &src1Obj->region );
+ REGION_CopyIntersection( region, &src2Obj->region );
+ return COMPLEXREGION;
+
+ case RGN_DIFF:
+ XSetFunction( XT_display, regionGC, GXclear );
+ XFillRectangle( XT_display, region->pixmap, regionGC,
+ 0, 0, width, height );
+ XSetFunction( XT_display, regionGC, GXcopy );
+ REGION_CopyIntersection( region, &src1Obj->region );
+ XSetFunction( XT_display, regionGC, GXandInverted );
+ REGION_CopyIntersection( region, &src2Obj->region );
+ return COMPLEXREGION;
+
+ case RGN_COPY:
+ XSetFunction( XT_display, regionGC, GXcopy );
+ XCopyArea( XT_display, src1Obj->region.pixmap, region->pixmap,
+ regionGC, 0, 0, width, height, 0, 0 );
+ return region->type;
+ }
+ return ERROR;
+}
diff --git a/objects/text.c b/objects/text.c
new file mode 100644
index 0000000..43b095a
--- /dev/null
+++ b/objects/text.c
@@ -0,0 +1,168 @@
+/*
+ * text functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright Alexandre Julliard, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Core.h>
+#include <X11/Shell.h>
+#include <X11/Xatom.h>
+
+#include "message.h"
+#include "callback.h"
+#include "win.h"
+#include "gdi.h"
+
+
+/***********************************************************************
+ * DrawText (USER.85)
+ */
+int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
+{
+ int x = rect->left, y = rect->top;
+ if (flags & DT_CENTER) x = (rect->left + rect->right) / 2;
+ if (flags & DT_VCENTER) y = (rect->top + rect->bottom) / 2;
+ if (count == -1) count = strlen(str);
+
+ if (!TextOut( hdc, x, y, str, count )) return 0;
+ return 1;
+}
+
+
+/***********************************************************************
+ * TextOut (GDI.33)
+ */
+BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
+{
+ int dir, ascent, descent, i;
+ XCharStruct info;
+ XFontStruct *font;
+
+ DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+ if (!dc) return FALSE;
+ if (!DC_SetupGCForText( dc )) return TRUE;
+ font = dc->u.x.font.fstruct;
+
+ if (dc->w.textAlign & TA_UPDATECP)
+ {
+ x = dc->w.CursPosX;
+ y = dc->w.CursPosY;
+ }
+#ifdef DEBUG_TEXT
+ printf( "TextOut: %d,%d '%s'\n", x, y, str );
+#endif
+ x = XLPTODP( dc, x );
+ y = YLPTODP( dc, y );
+
+ XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
+ info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
+
+ /* Compute starting position */
+
+ switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
+ {
+ case TA_LEFT:
+ if (dc->w.textAlign & TA_UPDATECP)
+ dc->w.CursPosX = XDPTOLP( dc, x + info.width );
+ break;
+ case TA_RIGHT:
+ x -= info.width;
+ if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
+ break;
+ case TA_CENTER:
+ x -= info.width / 2;
+ break;
+ }
+ switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
+ {
+ case TA_TOP:
+ y += font->ascent;
+ break;
+ case TA_BOTTOM:
+ y -= font->descent;
+ break;
+ case TA_BASELINE:
+ break;
+ }
+
+ /* Draw text */
+
+ if (!dc->w.charExtra && !dc->w.breakExtra)
+ {
+ if (dc->w.backgroundMode == TRANSPARENT)
+ XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ x, y, str, count );
+ else
+ XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ x, y, str, count );
+ }
+ else
+ {
+ 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;
+
+ extraWidth = dc->w.charExtra;
+ if (ch == dc->u.x.font.metrics.tmBreakChar)
+ extraWidth += dc->w.breakExtra;
+
+ if (dc->w.backgroundMode == TRANSPARENT)
+ XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ xchar, y, p, 1 );
+ else
+ {
+ XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ xchar, y, p, 1 );
+ XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
+ XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ xchar + charStr->width, y - font->ascent,
+ extraWidth, font->ascent + font->descent );
+ XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
+ }
+ xchar += charStr->width + extraWidth;
+ }
+ }
+
+ /* Draw underline and strike-out if needed */
+
+ if (dc->u.x.font.metrics.tmUnderlined)
+ {
+ long linePos, lineWidth;
+ if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
+ linePos = font->descent-1;
+ if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
+ lineWidth = 0;
+ else if (lineWidth == 1) lineWidth = 0;
+ XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
+ LineSolid, CapRound, JoinBevel );
+ XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ x, y + linePos, x + info.width, y + linePos );
+ }
+ if (dc->u.x.font.metrics.tmStruckOut)
+ {
+ long lineAscent, lineDescent;
+ if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
+ lineAscent = font->ascent / 3;
+ if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
+ lineDescent = -lineAscent;
+ XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
+ LineSolid, CapRound, JoinBevel );
+ XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
+ x, y - lineAscent, x + info.width, y - lineAscent );
+ }
+
+ return TRUE;
+}