--- a/XWorkstation.st Sat Jul 16 18:24:24 2016 +0200
+++ b/XWorkstation.st Tue Jul 19 21:44:36 2016 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -9,6 +11,8 @@
other person. No title to or ownership of the software is
hereby transferred.
"
+'From Smalltalk/X, Version:7.1.0.0 on 19-07-2016 at 15:46:14' !
+
"{ Package: 'stx:libview' }"
"{ NameSpace: Smalltalk }"
@@ -53,7 +57,7 @@
!
DeviceGraphicsContext subclass:#X11GraphicsContext
- instanceVariableNames:'useXftFont xftDrawId'
+ instanceVariableNames:'depth xftDrawId'
classVariableNames:''
poolDictionaries:''
privateIn:XWorkstation
@@ -123,6 +127,19 @@
# 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
@@ -198,7 +215,13 @@
# include <X11/Xft/Xft.h>
# include <X11/extensions/Xrender.h>
# include <X11/extensions/render.h>
-#endif
+
+# 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
@@ -231,6 +254,14 @@
# 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 ...
*/
@@ -268,20 +299,20 @@
*/
#define __ENTER_XLIB(whichTimeout) \
{ \
- __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)__XTimeoutErrorHandler; \
- __blockingPrimitiveTimeoutArg__ = self; \
- __blockingPrimitiveTimeout__ = __intVal(__INST(whichTimeout)) * 1000; \
+ __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)__XTimeoutErrorHandler; \
+ __blockingPrimitiveTimeoutArg__ = self; \
+ __blockingPrimitiveTimeout__ = whichTimeout; \
} {
#define LEAVE_XLIB() \
{ \
- __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)0; \
- __blockingPrimitiveTimeoutArg__ = nil; \
- __blockingPrimitiveTimeout__ = 0; \
+ __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)0; \
+ __blockingPrimitiveTimeoutArg__ = nil; \
+ __blockingPrimitiveTimeout__ = 0; \
} }
-#define ENTER_XLIB() __ENTER_XLIB(xlibTimeout)
-#define ENTER_XLIB2() __ENTER_XLIB(xlibTimeoutForWindowCreation)
+#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
@@ -365,30 +396,26 @@
* to include that stuff. Should be #ifdef'd ...
*/
#ifndef ELF
-
# ifdef __GNUC__
VOLATILE
# endif
static void
dummyToForceLoading() {
- XCreateSimpleWindow(0, 0, 0, 0, 0, 0, 0, 0, 0);
- XCloseDisplay(0);
- XCreateImage(0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0);
- XSetWindowColormap(0, 0, 0);
- XQueryColors(0,0,0,0);
+ XCreateSimpleWindow(0, 0, 0, 0, 0, 0, 0, 0, 0);
+ XCloseDisplay(0);
+ XCreateImage(0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0);
+ XSetWindowColormap(0, 0, 0);
+ XQueryColors(0,0,0,0);
# ifdef SHM
- XShmAttach(0, 0);
- XShmCreateImage(0, 0, 0, 0, 0, 0, 0 ,0);
- XShmDetach(0, 0);
- XShmPutImage(0, 0, 0, 0 , 0,0,0,0,0,0,0);
- shmctl(0,0,0);
- fgetc(0);
-# endif
+ XShmAttach(0, 0);
+ XShmCreateImage(0, 0, 0, 0, 0, 0, 0 ,0);
+ XShmDetach(0, 0);
+ XShmPutImage(0, 0, 0, 0 , 0,0,0,0,0,0,0);
+ shmctl(0,0,0);
+ fgetc(0);
+# endif // SHM
}
-#endif
-
-#undef __myInstPtr
-#define __myInstPtr(obj) ((struct __XWorkstation_struct *)(obj))
+#endif // !ELF
static char* requestNames[] = {
"X_CreateWindow", // 0
@@ -512,6 +539,11 @@
"X_GetModifierMapping",
};
+#if !defined(__INCREMENTAL_COMPILE__)
+// __myInstPtr has been redefined/overwritten by private classes - restore
+#undef __myInstPtr
+#define __myInstPtr(obj) ((struct __XWorkstation_struct *)(obj))
+
/*
* catch X-errors and forward as errorInterrupt:#DisplayError,
* (which itself invokes my handler and optionally raises an exceptionSignal)
@@ -521,50 +553,48 @@
* allows passing an additional argument, which is the displayID ...)
*/
int
-__XErrorHandler__(dpy, event)
- Display *dpy;
- XErrorEvent *event;
+__XErrorHandler__(Display *dpy, XErrorEvent *event)
{
XGetErrorText(dpy, event->error_code, lastErrorMsg, 127);
lastErrorMsg[127] = '\0';
if (lastErrorMsg[0] == '\0') {
- sprintf(lastErrorMsg, "code: %d", event->error_code);
+ sprintf(lastErrorMsg, "code: %d", event->error_code);
}
lastRequestCode = event->request_code;
lastMinorCode = event->minor_code;
lastResource = event->resourceid;
if ((event->error_code == BadWindow) && (lastRequestCode == 4) && (lastMinorCode == 0)) {
- /*
- * this is a BadWindow error for X_DestroyWindow.
- * ignore it here, since it results from the GC freeing windows
- * in non bottom-up window order.
- */
- return 0;
+ /*
+ * this is a BadWindow error for X_DestroyWindow.
+ * ignore it here, since it results from the GC freeing windows
+ * in non bottom-up window order.
+ */
+ return 0;
}
if (@global(DeviceWorkstation:ErrorPrinting) == true) {
- char *requestName = "?";
-
- if (event->request_code < (sizeof(requestNames)/sizeof(char *))) {
- requestName = requestNames[event->request_code];
- }
- console_fprintf(stderr, "XWorkstation [error]: x-error caught maj=%d (0x%x) \"%s\", min=%d (0x%x), resource=%"_lx_"\n",
- event->request_code, event->request_code, requestName,
- event->minor_code, event->minor_code, (INT)(event->resourceid));
- console_fprintf(stderr, "XWorkstation [error]: x-error message is [%d] '%s'\n",
- event->error_code, lastErrorMsg);
+ char *requestName = "?";
+
+ if (event->request_code < (sizeof(requestNames)/sizeof(char *))) {
+ requestName = requestNames[event->request_code];
+ }
+ console_fprintf(stderr, "XWorkstation [error]: x-error caught maj=%d (0x%x) \"%s\", min=%d (0x%x), resource=%"_lx_"\n",
+ event->request_code, event->request_code, requestName,
+ event->minor_code, event->minor_code, (INT)(event->resourceid));
+ console_fprintf(stderr, "XWorkstation [error]: x-error message is [%d] '%s'\n",
+ event->error_code, lastErrorMsg);
}
#if 0
// cg: should no longer be needed - librun no longer sends an errorInterrupt while running on C-stack
#ifdef XFT
if ((strncmp(lastErrorMsg, "RenderBadPicture", 16) == 0)) {
- /*
- * this is a RenderBadPicture error from XFT drawing.
- * ignore it for now, as this is due to an incomplete implementation
- */
- console_fprintf(stderr, "XWorkstation [info]: x-error ignored\n");
- return 0;
+ /*
+ * this is a RenderBadPicture error from XFT drawing.
+ * ignore it for now, as this is due to an incomplete implementation
+ */
+ console_fprintf(stderr, "XWorkstation [info]: x-error ignored\n");
+ return 0;
}
#endif
#endif
@@ -581,14 +611,13 @@
* connection should not affect the other users.
*/
int
-__XIOErrorHandler__(dpy)
- Display *dpy;
+__XIOErrorHandler__(Display *dpy)
{
if (@global(DeviceWorkstation:ErrorPrinting) == true) {
- console_fprintf(stderr, "XWorkstation [error]: I/O error\n");
+ console_fprintf(stderr, "XWorkstation [error]: I/O error\n");
}
__immediateErrorInterruptWithIDAndParameter__(@symbol(DisplayIOError),
- __MKEXTERNALADDRESS(dpy));
+ __MKEXTERNALADDRESS(dpy));
#if 0
/*
@@ -616,16 +645,15 @@
* timeoutHandler has been set.
*/
void
-__XTimeoutErrorHandler(displayDeviceInst)
- OBJ displayDeviceInst;
+__XTimeoutErrorHandler(OBJ displayDeviceInst)
{
if ((displayDeviceInst == @global(MainDisplay))
- || (displayDeviceInst == @global(DeviceWorkstation:DefaultScreen))) {
- console_fprintf(stderr, "XWorkstation [error]: keep display connection for master display after X11 timeout (no shutdown)\n");
- return;
+ || (displayDeviceInst == @global(DeviceWorkstation:DefaultScreen))) {
+ console_fprintf(stderr, "XWorkstation [error]: keep display connection for master display after X11 timeout (no shutdown)\n");
+ return;
}
if (@global(DeviceWorkstation:ErrorPrinting) == true) {
- console_fprintf(stderr, "XWorkstation [error]: X11 request timeout dpy=%"_lx_"\n", (INT)displayDeviceInst);
+ console_fprintf(stderr, "XWorkstation [error]: X11 request timeout dpy=%"_lx_"\n", (INT)displayDeviceInst);
}
__OINST(displayDeviceInst, hasConnectionBroken) = true;
@@ -637,16 +665,17 @@
* if we return from the error interrupt ...
*/
if (__OINST(displayDeviceInst, displayId) != nil) {
- __internalError("unhandled X11 display timeout error");
-
- /*
- * the current process failed to do an X11 request.
- * Terminate it!
- */
- __terminateProcess(0); /* soft terminate */
- __terminateProcess(1); /* hard terminate */
+ __internalError("unhandled X11 display timeout error");
+
+ /*
+ * the current process failed to do an X11 request.
+ * Terminate it!
+ */
+ __terminateProcess(0); /* soft terminate */
+ __terminateProcess(1); /* hard terminate */
}
}
+#endif // __INCREMENTAL_COMPILE__
%}
! !
@@ -1795,10 +1824,7 @@
except for XQuartz, which has."
"XQuartz seems to have a bug here..."
- OperatingSystem isOSXlike ifTrue:[^ false].
- ^ true
-
- "Created: / 4.5.1999 / 12:16:43 / cg"
+ ^ OperatingSystem isOSXlike not.
!
supportsScreenReading
@@ -1992,19 +2018,19 @@
Pixmap newBitmap;
if (__bothSmallInteger(w, h) && ISCONNECTED) {
- Display *dpy = myDpy;
-
-
- ENTER_XLIB();
- newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
- __intVal(w), __intVal(h), 1);
- LEAVE_XLIB();
+ Display *dpy = myDpy;
+
+
+ ENTER_XLIB();
+ newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
+ __intVal(w), __intVal(h), 1);
+ LEAVE_XLIB();
#ifdef COUNT_RESOURCES
- if (newBitmap)
- __cnt_bitmap++;
-#endif
-
- RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
+ if (newBitmap)
+ __cnt_bitmap++;
+#endif
+
+ RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
}
%}.
self primitiveFailedOrClosedConnection.
@@ -2586,7 +2612,6 @@
!
primCreateBitmapFromArray:anArray width:w height:h
-
<context: #return>
%{ /* UNLIMITEDSTACK */
@@ -2602,93 +2627,93 @@
REGISTER int col;
unsigned bits;
static char reverseBitTable[256];
- static firstCall = 1;
+ static int firstCall = 1;
int nBytes;
unsigned char fastBits[10000];
OBJ num, *op;
int bytesPerRow;
if (! ISCONNECTED) {
- RETURN (nil);
+ RETURN (nil);
}
dpy = myDpy;
if (firstCall) {
- for (index=0; index < 256; index++) {
- int t = 0;
-
- if (index & 128) t |= 1;
- if (index & 64) t |= 2;
- if (index & 32) t |= 4;
- if (index & 16) t |= 8;
- if (index & 8) t |= 16;
- if (index & 4) t |= 32;
- if (index & 2) t |= 64;
- if (index & 1) t |= 128;
-
- reverseBitTable[index] = t;
- }
- firstCall = 0;
+ for (index=0; index < 256; index++) {
+ int t = 0;
+
+ if (index & 128) t |= 1;
+ if (index & 64) t |= 2;
+ if (index & 32) t |= 4;
+ if (index & 16) t |= 8;
+ if (index & 8) t |= 16;
+ if (index & 4) t |= 32;
+ if (index & 2) t |= 64;
+ if (index & 1) t |= 128;
+
+ reverseBitTable[index] = t;
+ }
+ firstCall = 0;
}
if (__bothSmallInteger(w, h) && _isNonNilObject(anArray)) {
- newBitmap = (Pixmap)0;
- b_width = __intVal(w);
- b_height = __intVal(h);
- bytesPerRow = (b_width + 7) / 8;
- nBytes = b_height * bytesPerRow;
- if (nBytes < sizeof(fastBits)) {
- cp = b_bits = fastBits;
- allocatedBits = 0;
- } else {
- cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
- if (! cp) goto fail;
- }
-
- if (__isArrayLike(anArray)) {
- index = 1;
- op = &(__ArrayInstPtr(anArray)->a_element[index - 1]);
- for (row = b_height; row; row--) {
- for (col = bytesPerRow; col; col--) {
- num = *op++;
- if (__isSmallInteger(num)) {
- bits = __intVal(num);
- } else {
- bits = __longIntVal(num);
- if (bits == 0) {
- goto fail;
- }
- }
- *cp++ = reverseBitTable[bits & 0xFF];
- }
- }
- } else {
- if (__isByteArrayLike(anArray)) {
- pBits = __ByteArrayInstPtr(anArray)->ba_element;
- for (col = b_height*bytesPerRow; col; col--) {
- *cp++ = reverseBitTable[*pBits++];
- }
- } else {
- goto fail;
- }
- }
-
-
- ENTER_XLIB();
- newBitmap = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
- (char *)b_bits,
- b_width, b_height);
- LEAVE_XLIB();
+ newBitmap = (Pixmap)0;
+ b_width = __intVal(w);
+ b_height = __intVal(h);
+ bytesPerRow = (b_width + 7) / 8;
+ nBytes = b_height * bytesPerRow;
+ if (nBytes < sizeof(fastBits)) {
+ cp = b_bits = fastBits;
+ allocatedBits = 0;
+ } else {
+ cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+ if (! cp) goto fail;
+ }
+
+ if (__isArrayLike(anArray)) {
+ index = 1;
+ op = &(__ArrayInstPtr(anArray)->a_element[index - 1]);
+ for (row = b_height; row; row--) {
+ for (col = bytesPerRow; col; col--) {
+ num = *op++;
+ if (__isSmallInteger(num)) {
+ bits = __intVal(num);
+ } else {
+ bits = __longIntVal(num);
+ if (bits == 0) {
+ goto fail;
+ }
+ }
+ *cp++ = reverseBitTable[bits & 0xFF];
+ }
+ }
+ } else {
+ if (__isByteArrayLike(anArray)) {
+ pBits = __ByteArrayInstPtr(anArray)->ba_element;
+ for (col = b_height*bytesPerRow; col; col--) {
+ *cp++ = reverseBitTable[*pBits++];
+ }
+ } else {
+ goto fail;
+ }
+ }
+
+
+ ENTER_XLIB();
+ newBitmap = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
+ (char *)b_bits,
+ b_width, b_height);
+ LEAVE_XLIB();
#ifdef COUNT_RESOURCES
- if (newBitmap)
- __cnt_bitmap++;
+ if (newBitmap)
+ __cnt_bitmap++;
#endif
fail: ;
- if (allocatedBits)
- free(allocatedBits);
- RETURN ( newBitmap ? __MKEXTERNALADDRESS(newBitmap) : nil );
+ if (allocatedBits)
+ free(allocatedBits);
+ RETURN ( newBitmap ? __MKEXTERNALADDRESS(newBitmap) : nil );
}
%}.
^ nil
@@ -3564,6 +3589,45 @@
!XWorkstation methodsFor:'drawing'!
+clearRectangleX:x y:y width:width height:height in:aDrawableId with:aGCId
+ "clear (fill with background) a rectangle. If any coordinate is not integer, an error is triggered."
+
+ <context: #return>
+
+ operationsUntilFlush notNil ifTrue:[
+ operationsUntilFlush <= 0 ifTrue:[
+ self flush.
+ ] ifFalse:[
+ operationsUntilFlush := operationsUntilFlush - 1.
+ ].
+ ].
+%{
+
+ int w, h;
+
+ if (ISCONNECTED
+ && __isExternalAddress(aDrawableId)
+ && __bothSmallInteger(x, y)
+ && __bothSmallInteger(width, height)) {
+ w = __intVal(width);
+ h = __intVal(height);
+ /*
+ * need this check here: some servers simply dump core with bad args
+ */
+ if ((w >= 0) && (h >= 0)) {
+ ENTER_XLIB();
+ XClearArea(myDpy,
+ __DrawableVal(aDrawableId),
+ __intVal(x), __intVal(y), w, h, 0);
+ LEAVE_XLIB();
+ }
+ RETURN ( self );
+ }
+%}.
+ "badGC, badDrawable or coordinates not integer"
+ self primitiveFailedOrClosedConnection
+!
+
copyFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
"do a bit-blt; copy bits from the rectangle defined by
srcX/srcY and w/h from the sourceId drawable to the rectangle
@@ -7805,7 +7869,7 @@
).
Screen current
- heightOf:'hello World gggÖÜ' from:1 to:15
+ heightOf:'hello World gggÖÜ' from:1 to:15
inFont:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
"
!
@@ -13731,10 +13795,47 @@
^ true
! !
+!XWorkstation::X11GraphicsContext methodsFor:'accessing'!
+
+depth
+ ^ depth
+!
+
+xftDrawId
+ ^ xftDrawId
+! !
+
+!XWorkstation::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
+%}.
+! !
+
!XWorkstation::X11GraphicsContext methodsFor:'displaying'!
-displayString:aString x:x y:y opaque:opaque
- "draw a string - if opaque is false, draw foreground only; otherwise, draw both
+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."
@@ -13742,121 +13843,469 @@
|displayId|
+ font isXftFont ifTrue:[
+ self displayDeviceXftString:aString from:index1 to:index2 x:x y:y opaque:opaque.
+ ^ self.
+ ].
+
device flushIfAppropriate.
displayId := device displayIdOrErrorIfBroken.
%{
-#if 0
GC gc;
Window win;
char *cp;
- int n;
- OBJ cls;
+ int i1, i2, l, n;
# define NLOCALBUFFER 200
XChar2b xlatebuffer[NLOCALBUFFER];
int nInstBytes;
- if (displayId != nil
+ 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));
-
- cp = (char *) __stringVal(aString);
-
- if (__isStringLike(aString)) {
- n = __stringSize(aString);
- if (n > lMax) n = lMax;
- ENTER_XLIB();
- if (opaque == true)
- XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
- else
- XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
- 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 (n > lMax) n = lMax;
- ENTER_XLIB();
- if (opaque == true)
- XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
- else
- XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
- LEAVE_XLIB();
- RETURN ( self );
- }
-
- /* TWOBYTESTRINGS */
- if (__isWords(aString)) {
- union {
- char b[2];
- unsigned short s;
- } u;
- int i;
- XChar2b *cp2;
- int mustFree = 0;
-
- n = (__byteArraySize(aString) - nInstBytes) / 2;
- if (n > lMax) n = lMax;
+ 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
- */
+ /*
+ * 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
- {
- if (n <= NLOCALBUFFER) {
- cp2 = xlatebuffer;
- } else {
- cp2 = (XChar2b *)(malloc(n * 2));
- mustFree = 1;
- }
-
- for (i=0; i<n; i++) {
- cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
- cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
- }
- cp = (char *) cp2;
- }
-#endif
- ENTER_XLIB();
- if (opaque == true)
- XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, n);
- else
- XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, n);
- LEAVE_XLIB();
-
- if (mustFree) {
- free(cp2);
- }
-
- RETURN ( self );
- }
+ /*
+ * 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
-#endif
-%}.
- ^ super displayString:aString x:x y:y opaque:opaque
+%}.
+
+ "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 getFontId.
+
+%{ /* 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.
+ ].
+! !
+
+!XWorkstation::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
+! !
+
+!XWorkstation::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
! !
!XWorkstation class methodsFor:'documentation'!