X11GraphicsContext.st
changeset 8357 f1060ceb2b3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X11GraphicsContext.st	Tue May 08 12:47:31 2018 +0200
@@ -0,0 +1,840 @@
+"{ Encoding: utf8 }"
+
+"
+COPYRIGHT (c) 1989 by Claus Gittinger
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libview' }"
+
+"{ NameSpace: Smalltalk }"
+
+DeviceGraphicsContext subclass:#X11GraphicsContext
+	instanceVariableNames:'depth xftDrawId'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-Graphics'
+!
+
+!X11GraphicsContext primitiveDefinitions!
+%{
+
+#define SUPPORT_MOTIF_WM_HINTS
+
+#ifdef LINUX
+# ifndef __arm__
+#  define SHM
+# endif
+#endif
+
+/*
+ * x does a typedef Time - I need Object Time ...
+ */
+#undef Time
+#define Time XTime
+
+/*
+ * x does a #define True / False
+ * we are lucky - the ST/X True/False are not needed
+ */
+#undef True
+#undef False
+
+#include <stdio.h>
+
+#if defined(__osx__)
+# include <malloc/malloc.h>
+extern void *malloc();
+#else
+# ifndef FREEBSD
+#  include <malloc.h>
+# endif
+#endif
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#define XK_MISCELLANY
+#include <X11/keysymdef.h>
+
+#include <X11/cursorfont.h>
+
+#ifdef LINUX
+# include <sys/socket.h>
+#endif
+
+extern OBJ __GLOBAL_GET_BY_NAME(char *);
+
+# define __HANDLE_VAL(type, externalAddress) \
+	((type)__externalAddressVal(externalAddress))
+
+# define __HANDLE_NEW(ptr, __cls)                    \
+	({                                           \
+	    OBJ handle = __MKEXTERNALADDRESS(ptr);   \
+	    OBJ clsObj = __GLOBAL_GET_BY_NAME(__cls);\
+	    __InstPtr(handle)->o_class = clsObj;     \
+	    __STORE(handle, clsObj);                 \
+	    handle;                                  \
+	})
+
+/*
+ * this define suppresses XAllocColor/XFreeColor on
+ * TrueColor systems - I am not certain, if this is
+ * always legal to do (it works with XFree servers).
+ */
+#define QUICK_TRUE_COLORS
+
+/*
+ * shape support works; enabled by -DSHAPE in makefile
+ * see RoundClock and RoundGlobe examples
+ */
+#ifdef SHAPE
+# include <X11/extensions/shape.h>
+#endif
+
+/*
+ * shared memory extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef SHM
+# include <X11/extensions/XShm.h>
+#endif
+
+/*
+ * multiBuffer extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef MBUF
+# include <X11/extensions/multibuf.h>
+#endif
+
+/*
+ * XVideo extension access is currently not supported
+ * (only query is implemented)
+ */
+#ifdef XVIDEO
+# include <X11/extensions/Xv.h>
+#endif
+
+/*
+ * PEX extension - if available
+ */
+#ifdef PEX5
+# include <PEX5/PEX.h>
+#endif
+
+/*
+ * XImage extension - if available
+ */
+#ifdef XIE
+# include <X11/extensions/XIE.h>
+#endif
+
+/*
+ * multiscreen extension - if available
+ */
+#ifdef XINERAMA
+# include <X11/extensions/Xinerama.h>
+#endif
+
+/*
+ * XCURSOR extension - if available
+ */
+#ifdef XCURSOR
+# include <X11/Xcursor/Xcursor.h>
+#endif
+
+/*
+ * xft library (based on RENDER extension) - if available
+ */
+#ifdef XFT
+# include <X11/Xft/Xft.h>
+# include <X11/extensions/Xrender.h>
+# include <X11/extensions/render.h>
+
+# define XFT_FONT(x)            __HANDLE_VAL(XftFont*, x)
+# define XFT_FONT_HANDLE_NEW(x) __HANDLE_NEW(x, "XftFontDescription::XftFontHandle")
+
+# define XFT_DRAW(x)            __HANDLE_VAL(XftDraw*, x)
+# define XFT_DRAW_HANDLE_NEW(x) __HANDLE_NEW(x, "XftFontDescription::XftDrawHandle")
+#endif // XFT
+
+/*
+ * when I have more time to check it out, I will support display-PS
+ */
+#ifdef DPS
+# ifdef sgi
+#  include <X11/extensions/XDPS.h>
+#  include <X11/extensions/XDPSlib.h>
+#  include <X11/extensions/dpsXclient.h>
+# else
+#  include <DPS/XDPS.h>
+#  include <DPS/XDPSlib.h>
+#  include <DPS/dpsXclient.h>
+# endif
+#endif
+
+#if defined(someMachine)
+/*
+ * if nformats cannot be found in the Display structure ...
+ */
+# define NO_PRIVATE_DISPLAY_ACCESS
+#endif
+
+#if defined(IRIX5) || defined(__VMS) || (XlibSpecificationRelease == 6)
+  /*
+   * accessing private data in Display ... sorry
+   */
+# define DISPLAYACCESS(d) ((_XPrivDisplay)d)
+#else
+# define DISPLAYACCESS(d) d
+#endif
+
+# define DISPLAY(x)    __HANDLE_VAL(Display*, x)
+# define SCREEN(x)     ((int)(__intVal(x)))
+# define DRAWABLE(x)   __HANDLE_VAL(Drawable, x)
+# define GC(x)         __HANDLE_VAL(GC, x)
+# define VISUAL(x)     __HANDLE_VAL(Visual*, x)
+# define COLORMAP(x)   __HANDLE_VAL(Colormap, x)
+
+
+/*
+ * some defines - tired of typing ...
+ */
+#define __DisplayVal(o)      (Display *)(__externalAddressVal(o))
+#define __DrawableVal(o)     (Drawable)(__externalAddressVal(o))
+#define __WindowVal(o)       (Window)(__externalAddressVal(o))
+#define __PixmapVal(o)       (Pixmap)(__externalAddressVal(o))
+#define __GCVal(o)           (GC)(__externalAddressVal(o))
+#define __CursorVal(o)       (Cursor)(__externalAddressVal(o))
+#define __FontVal(o)         (XFontStruct *)(__externalAddressVal(o))
+#define __DPSContextVal(o)   (DPSContext)(__externalAddressVal(o))
+
+#define __MKATOMOBJ(a)       __MKSMALLINT(a)   /* add STORE macro if ever changed */
+#define __AtomVal(o)         __intVal(o)
+#define __isAtomID(o)        __isSmallInteger(o)
+
+#define myDpy                __DisplayVal(__INST(displayId))
+#define ISCONNECTED          ((__INST(displayId) != nil) && (__INST(hasConnectionBroken) != nil))
+
+#ifdef __VMS__
+# include "vms_Xnames.h"
+#endif
+
+void __XTimeoutErrorHandler();
+int __XErrorHandler__();
+int __XIOErrorHandler__();
+
+/*
+ * these two macros should be placed around X-lib calls,
+ * which may block due to a broken connection.
+ * They setup/remove a VM-timeout which raises an exception
+ * after xlibTimeout seconds.
+ * This exception will shutDown the connection.
+ * Q: is this a good idea for the local display ?
+ */
+#define __ENTER_XLIB(whichTimeout)   \
+    { \
+	__blockingPrimitiveTimoutHandler__ = (voidFUNC)__XTimeoutErrorHandler; \
+	__blockingPrimitiveTimeoutArg__ = self; \
+	__blockingPrimitiveTimeout__ = whichTimeout; \
+    } {
+
+#define LEAVE_XLIB()   \
+    { \
+	__blockingPrimitiveTimoutHandler__ = (voidFUNC)0; \
+	__blockingPrimitiveTimeoutArg__ = nil; \
+	__blockingPrimitiveTimeout__ = 0; \
+    } }
+
+#define ENTER_XLIB()   __ENTER_XLIB(__intVal(__INST(xlibTimeout)) * 1000)
+#define ENTER_XLIB2()  __ENTER_XLIB(__intVal(__INST(xlibTimeoutForWindowCreation)) * 1000)
+
+#ifdef SUPPORT_MOTIF_WM_HINTS
+# ifdef SOME_MACHINE
+#  include <anIncludeFileWhichDefinesTheStuffBelow>
+# endif
+
+# ifndef MWM_HINTS_FUNCTIONS
+#  define MWM_HINTS_FUNCTIONS       (1L << 0)
+#  define MWM_HINTS_DECORATIONS     (1L << 1)
+#  define MWM_HINTS_INPUT_MODE      (1L << 2)
+#  define MWM_HINTS_STATUS          (1L << 3)
+
+#  define MWM_FUNC_ALL              (1L << 0)
+#  define MWM_FUNC_RESIZE           (1L << 1)
+#  define MWM_FUNC_MOVE             (1L << 2)
+#  define MWM_FUNC_MINIMIZE         (1L << 3)
+#  define MWM_FUNC_MAXIMIZE         (1L << 4)
+#  define MWM_FUNC_CLOSE            (1L << 5)
+
+#  define MWM_INPUT_MODELESS                      0
+#  define MWM_INPUT_PRIMARY_APPLICATION_MODAL     1
+#  define MWM_INPUT_SYSTEM_MODAL                  2
+#  define MWM_INPUT_FULL_APPLICATION_MODAL        3
+
+#  define MWM_DECOR_NONE            0
+#  define MWM_DECOR_ALL             (1L << 0)
+#  define MWM_DECOR_BORDER          (1L << 1)
+#  define MWM_DECOR_RESIZEH         (1L << 2)
+#  define MWM_DECOR_TITLE           (1L << 3)
+#  define MWM_DECOR_MENU            (1L << 4)
+#  define MWM_DECOR_MINIMIZE        (1L << 5)
+#  define MWM_DECOR_MAXIMIZE        (1L << 6)
+# endif
+#endif /* SUPPORT_MOTIF_WM_HINTS */
+
+/*
+ * openlook hints are not supported yet
+ * - noone needs them anymore ;-(
+ */
+#ifdef SUPPORT_OPENLOOCK_WM_HINTS
+# ifdef SOME_MACHINE
+#  include <anIncludeFileWhichDefinesTheStuffBelow>
+# endif
+
+# ifndef OL_DECOR_CLOSE
+#  define OL_DECOR_CLOSE            (1L << 0)
+#  define OL_DECOR_RESIZEH          (1L << 1)
+#  define OL_DECOR_HEADER           (1L << 2)
+#  define OL_DECOR_ICON_NAME        (1L << 3)
+#  define OL_DECOR_ALL              (OL_DECOR_CLOSE | OL_DECOR_RESIZEH | OL_DECOR_HEADER | OL_DECOR_ICON_NAME)
+#  define OL_ANY_HINTS              (1L << 7)
+# endif
+#endif /* SUPPORT_OPENLOOCK_WM_HINTS */
+
+
+%}
+! !
+
+!X11GraphicsContext methodsFor:'accessing'!
+
+depth
+    ^ depth
+!
+
+xftDrawId
+    ^ xftDrawId
+! !
+
+!X11GraphicsContext methodsFor:'destroying'!
+
+destroy
+    xftDrawId notNil ifTrue:[
+	self destroyXftDrawId.
+    ].
+    super destroy.
+!
+
+destroyXftDrawId
+    |id|
+
+    id := xftDrawId.
+    xftDrawId := nil.
+%{
+#ifdef XFT
+    if (__isExternalAddress(id)) {
+	XftDraw *address = (XftDraw *)__externalAddressVal(id);
+	if (address) {
+	    XftDrawDestroy(address);
+	    __externalAddressVal(id) = 0;
+	}
+    }
+#endif
+%}.
+! !
+
+!X11GraphicsContext methodsFor:'displaying'!
+
+displayDeviceString:aString from:index1 to:index2 x:x y:y opaque:opaque
+    "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+     foreground and background characters.
+     If the coordinates are not integers, an error is triggered."
+
+    <context: #return>
+
+    |displayId|
+
+    font isXftFont ifTrue:[
+	self displayDeviceXftString:aString from:index1 to:index2 x:x y:y opaque:opaque.
+	^ self.
+    ].
+
+    device flushIfAppropriate.
+    displayId := device displayIdOrErrorIfBroken.
+
+%{
+    GC gc;
+    Window win;
+    char *cp;
+    int  i1, i2, l, n;
+#   define NLOCALBUFFER 200
+    XChar2b xlatebuffer[NLOCALBUFFER];
+    int nInstBytes;
+
+    if (__isExternalAddress(displayId)
+     && __isExternalAddress(__INST(gcId))
+     && __isExternalAddress(__INST(drawableId))
+     && __isNonNilObject(aString)
+     && __bothSmallInteger(index1, index2)
+     && __bothSmallInteger(x, y)) {
+	int lMax = __intVal(@global(XWorkstation:MaxStringLength));
+	Display *dpy = __DisplayVal(displayId);
+	gc = __GCVal(__INST(gcId));
+	win = __WindowVal(__INST(drawableId));
+
+	i1 = __intVal(index1) - 1;
+	if (i1 >= 0) {
+	    OBJ cls;
+
+	    i2 = __intVal(index2) - 1;
+	    if (i2 < i1) {
+		RETURN (self);
+	    }
+	    cp = (char *) __stringVal(aString);
+	    l = i2 - i1 + 1;
+
+	    if (__isStringLike(aString)) {
+		n = __stringSize(aString);
+		if (i2 < n) {
+		    cp += i1;
+		    if (l > lMax) l = lMax;
+		    __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+		    if (opaque == true)
+			XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+		    else
+			XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+		    LEAVE_XLIB();
+		    RETURN ( self );
+		}
+	    }
+
+	    cls = __qClass(aString);
+	    nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+	    cp += nInstBytes;
+
+	    if (__isBytes(aString)) {
+		n = __byteArraySize(aString) - nInstBytes - 1;
+
+		if (i2 < n) {
+		    cp += i1;
+		    if (l > lMax) l = lMax;
+		    __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+		    if (opaque == true)
+			XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+		    else
+			XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+		    LEAVE_XLIB();
+		    RETURN ( self );
+		}
+	    }
+
+	    /* TWOBYTESTRINGS */
+	    if (__isWords(aString)) {
+		n = (__byteArraySize(aString) - nInstBytes) / 2;
+		if (i2 < n) {
+		    union {
+			char b[2];
+			unsigned short s;
+		    } u;
+		    int i;
+		    XChar2b *cp2 = (XChar2b *)0;
+		    int mustFree = 0;
+
+		    cp += (i1 * 2);
+		    if (l > lMax) l = lMax;
+
+#if defined(MSBFIRST) || defined(__MSBFIRST)
+		    /*
+		     * chars already in correct order
+		     */
+#else
+# if ! (defined(LSBFIRST) || defined(__LSBFIRST))
+		    /*
+		     * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+		     * X expects them MSB first
+		     * convert as required
+		     */
+		    u.s = 0x1234;
+		    if (u.b[0] != 0x12)
+# endif  // ! (defined(LSBFIRST) || defined(__LSBFIRST))
+		    {
+			if (l <= NLOCALBUFFER) {
+			    cp2 = xlatebuffer;
+			} else {
+			    cp2 = (XChar2b *)(malloc(l * 2));
+			    mustFree = 1;
+			}
+			for (i=0; i<l; i++) {
+			    cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+			    cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+			}
+			cp = (char *) cp2;
+		    }
+#endif  // ! (defined(MSBFIRST) || defined(__MSBFIRST))
+		    __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+		    if (opaque == true)
+			XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+		    else
+			XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+		    LEAVE_XLIB();
+
+		    if (mustFree) {
+			free(cp2);
+		    }
+
+		    RETURN ( self );
+		}
+	    }
+
+	    /* FOURBYTESTRINGS */
+	    if (__isLongs(aString)) {
+		n = (__byteArraySize(aString) - nInstBytes) / 4;
+		if (i2 < n) {
+		    union {
+			char b[2];
+			unsigned short s;
+		    } u;
+		    int i;
+		    XChar2b *cp2 = (XChar2b *)0;
+		    int32 *ip;
+		    int mustFree = 0;
+
+		    cp += (i1 * 4);
+		    if (l > lMax) l = lMax;
+
+		    /*
+		     * all codePoints <= 16rFFFF are draw; above 16bit range are drawn as 16rFFFF.
+		     */
+		    if (l <= NLOCALBUFFER) {
+			cp2 = xlatebuffer;
+		    } else {
+			cp2 = (XChar2b *)(malloc(l * 2));
+			mustFree = 1;
+		    }
+		    for (i=0; i<l; i++) {
+			int32 codePoint = ((int32 *)cp)[i];
+
+			if (codePoint > 0xFFFF) {
+			    codePoint = 0xFFFF;
+			}
+			cp2[i].byte1 = (codePoint >> 8) & 0xFF;
+			cp2[i].byte2 = codePoint & 0xFF;
+		    }
+
+		    __ENTER_XLIB(1000 * __intVal(@global(XWorkstation:DefaultXLibTimeout)));
+		    if (opaque == true)
+			XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp2, l);
+		    else
+			XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp2, l);
+		    LEAVE_XLIB();
+
+		    if (mustFree) {
+			free(cp2);
+		    }
+
+		    RETURN ( self );
+		}
+	    }
+	}
+    }
+#undef NLOCALBUFFER
+%}.
+
+    "x/y not integer, badGC or drawable, or not a string"
+    device primitiveFailedOrClosedConnection
+!
+
+displayDeviceXftString:aString from:index1 to:index2Arg x:drawX y:drawY opaque:opaque
+    "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+     foreground and background characters.
+     If the coordinates are not integers, an error is triggered."
+
+    <context: #return>
+
+    |index2 bytesPerCharacter
+     clipX clipY clipW clipH
+     fgR fgG fgB fgA fgPixel bgR bgG bgB bgA bgPixel
+     displayId screen error stringLen
+     newXftDrawId pixmapDepth fontId|
+
+"/    device flushIfAppropriate.
+    displayId := device displayIdOrErrorIfBroken.
+
+    "limit the string len, otherwise bad output is generated"
+    stringLen := index2Arg - index1 + 1.
+    stringLen > 1000 "8000" ifTrue:[
+	index2 := index1 + 1000 "8000" - 1.
+    ]  ifFalse:[
+	stringLen <= 0 ifTrue:[^ self].
+	index2 := index2Arg.
+    ].
+    bytesPerCharacter := aString bytesPerCharacter.
+
+    clipRect notNil ifTrue:[
+	clipX := clipRect left.
+	clipY := clipRect top.
+	clipW := clipRect width.
+	clipH := clipRect height.
+"/clipW > 32767 ifTrue:['clipW > 32767: ' errorPrint. clipW errorPrintCR. clipW := 32767].
+"/(clipX > 16384 or:[clipX < -16384]) ifTrue:['clipX > 16384: ' errorPrint. clipX errorPrintCR.].
+	"/ YES YES YES: this MUST be transformed!!
+	"/ (see htmlView) fix the notebook, please.
+    ].
+
+    fgR := paint scaledRed.
+    fgR notNil ifTrue:[
+	fgG := paint scaledGreen.
+	fgB := paint scaledBlue.
+	fgA := paint scaledAlpha.
+    ] ifFalse:[
+	"/ when drawing into a pixmap...
+	fgPixel := paint colorId.
+	fgPixel == 0 ifTrue:[
+	    fgR := fgG := fgB := 0.
+	] ifFalse:[
+	    fgR := fgG := fgB := 16rFFFF.
+	].
+	fgA := 16rFFFF.
+    ].
+
+    opaque ifTrue:[
+	bgPaint isColor ifTrue:[
+	    bgR := bgPaint scaledRed.
+	    bgR notNil ifTrue:[
+		bgG := bgPaint scaledGreen.
+		bgB := bgPaint scaledBlue.
+		bgA := bgPaint scaledAlpha.
+	    ] ifFalse:[
+		"/ when drawing into a pixmap...
+		bgPixel := bgPaint colorId.
+		bgPixel == 0 ifTrue:[
+		    bgR := bgG := bgB := 0.
+		] ifFalse:[
+		    bgR := bgG := bgB := 16rFFFF.
+		].
+		bgA := 16rFFFF.
+	    ].
+	] ifFalse:[
+	    "images as background are not yet implemented"
+	    "/ #todo: fill background rectangle
+	    bgR := bgG := bgB := bgA := 16rFFFF.
+	].
+    ].
+
+    screen := device screen.
+    self isPixmap ifTrue:[
+	pixmapDepth := depth.
+    ].
+    fontId := font getXftFontId.
+
+%{ /* STACK: 64000 */
+#ifdef XFT
+    XftColor color;
+    XGlyphInfo extents;
+    XRectangle clipRX;
+    char *string;
+    int len;
+    int __bytesPerCharacter;
+    XftDraw *__xftDrawId;
+    XftFont *__xftFont;
+
+    if (!(__bothSmallInteger(drawX, drawY)
+	  && __bothSmallInteger(index1, index2)
+	  && __isSmallInteger(bytesPerCharacter)
+	  && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
+	  && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
+	  && __isNonNilObject(aString)
+	  && __isExternalAddress(displayId)
+	  && __isExternalAddressLike(fontId)
+    )) {
+	error = @symbol(badArgument);
+	goto out;
+    }
+
+    __xftFont = XFT_FONT(fontId);
+    __bytesPerCharacter = __intVal(bytesPerCharacter);
+
+    if (__INST(xftDrawId) != nil) {
+	__xftDrawId = __externalAddressVal(__INST(xftDrawId));
+    } else {
+	if (pixmapDepth != nil) {
+	    int __pixmapDepth = __intVal(pixmapDepth);
+
+	    if (__pixmapDepth == 1) {
+		__xftDrawId = XftDrawCreateBitmap(DISPLAY(displayId), DRAWABLE(__INST(drawableId)));
+	    } else {
+		__xftDrawId = XftDrawCreateAlpha(DISPLAY(displayId), DRAWABLE(__INST(drawableId)), __pixmapDepth);
+	    }
+	} else {
+	    __xftDrawId = XftDrawCreate(DISPLAY(displayId),
+					   DRAWABLE(__INST(drawableId)),
+					   DefaultVisual(DISPLAY(displayId), SCREEN(screen)),
+					   DefaultColormap(DISPLAY(displayId), SCREEN(screen)));
+	}
+	__INST(xftDrawId) = newXftDrawId = XFT_DRAW_HANDLE_NEW(__xftDrawId);
+	__STORE(self, newXftDrawId);
+    }
+
+    string = __stringVal(aString) + ((__intVal(index1) - 1 ) * __bytesPerCharacter);
+    len = __intVal(index2) - __intVal(index1) + 1;
+
+    if (clipX != nil) {
+	clipRX.x = __intVal(clipX);
+	clipRX.y = __intVal(clipY);
+	clipRX.width = __intVal(clipW);
+	clipRX.height = __intVal(clipH);
+	XftDrawSetClipRectangles(__xftDrawId, 0, 0, &clipRX, 1);
+    } else {
+	XftDrawSetClip(__xftDrawId, 0);
+    }
+
+    if (opaque == true) {
+	if (bgPixel != nil) {
+	    color.pixel = (unsigned long)__intVal(bgPixel);
+	}
+	color.color.red = __intVal(bgR);
+	color.color.green = __intVal(bgG);
+	color.color.blue = __intVal(bgB);
+	color.color.alpha = __intVal(bgA);
+
+	switch (__bytesPerCharacter) {
+	case 1:
+	    XftTextExtents8(DISPLAY(displayId), __xftFont, (FcChar8*)string, len, &extents);
+	    break;
+	case 2:
+	    XftTextExtents16(DISPLAY(displayId), __xftFont, (FcChar16*)string, len, &extents);
+	    break;
+	case 4:
+	    XftTextExtents32(DISPLAY(displayId), __xftFont, (FcChar32*)string, len, &extents);
+	    break;
+	}
+if (extents.width < 0) printf("width: %d  < 0\n", extents.width);
+
+	XftDrawRect(__xftDrawId, &color, __intVal(drawX) - extents.x, __intVal(drawY) - __xftFont->ascent, extents.width, __xftFont->height);
+    }
+    if (__isSmallInteger(fgPixel)) {
+	color.pixel = (unsigned long)__intVal(fgPixel);
+    }
+    color.color.red = __intVal(fgR);
+    color.color.green = __intVal(fgG);
+    color.color.blue = __intVal(fgB);
+    color.color.alpha = __intVal(fgA);
+
+    switch (__bytesPerCharacter) {
+    case 1:
+	XftDrawString8(__xftDrawId, &color,__xftFont,
+			__intVal(drawX),
+			__intVal(drawY),
+			(FcChar8*)string,
+			len);
+	break;
+
+    case 2:
+	XftDrawString16(__xftDrawId, &color, __xftFont,
+			__intVal(drawX),
+			__intVal(drawY),
+			(FcChar16*)string,
+			len);
+	break;
+
+    case 4:
+	XftDrawString32(__xftDrawId, &color, __xftFont,
+			__intVal(drawX),
+			__intVal(drawY),
+			(FcChar32*)string,
+			len);
+	break;
+
+    default:
+	error = @symbol(invalidStringSize);
+	goto out;
+    }
+
+out:;
+#endif
+%}.
+    error notNil ifTrue:[
+	self primitiveFailed: error.
+    ].
+! !
+
+!X11GraphicsContext methodsFor:'drawing'!
+
+XXclearDeviceRectangleX:x y:y width:width height:height
+    device clearRectangleX:x y:y width:width height:height in:drawableId with:gcId
+!
+
+XXclearRectangleX:x y:y width:w height:h
+    "draw a filled rectangle; apply transformation if nonNil"
+
+    |pX pY nW nH pO pC|
+
+    gcId isNil ifTrue:[
+	self initGC
+    ].
+    transformation notNil ifTrue:[
+	pO := transformation transformPoint:x@y.
+	pC := transformation transformPoint:(x+w-1)@(y+h-1).
+	pX := pO x.
+	pY := pO y.
+	nW := pC x - pX + 1.
+	nH := pC y - pY + 1.
+
+	nW < 0 ifTrue:[
+	      nW := nW abs.
+	      pX := pX - nW.
+	].
+	nH < 0 ifTrue:[
+	      nH := nH abs.
+	      pY := pY - nH.
+	].
+    ] ifFalse:[
+	pX := x.
+	pY := y.
+	nW := w.
+	nH := h.
+    ].
+    pX := pX rounded.
+    pY := pY rounded.
+    nW := nW rounded.
+    nH := nH rounded.
+
+    device
+	clearRectangleX:pX
+		     y:pY
+		 width:nW
+		height:nH
+		    in:drawableId with:gcId
+! !
+
+!X11GraphicsContext methodsFor:'view creation'!
+
+createBitmapFromArray:data width:width height:height
+    depth := 1.
+    super createBitmapFromArray:data width:width height:height
+!
+
+createPixmapWidth:w height:h depth:d
+    depth := d.
+    super createPixmapWidth:w height:h depth:d
+! !
+
+!X11GraphicsContext class methodsFor:'documentation'!
+
+version
+    ^ '$Header$'
+!
+
+version_CVS
+    ^ '$Header$'
+! !
+
+
+X11GraphicsContext initialize!