diff options
-rw-r--r-- | lib/XCL/ChKeyCon.c | 42 | ||||
-rw-r--r-- | lib/XCL/ChkTypWEv.c | 81 | ||||
-rw-r--r-- | lib/XCL/CrPixmap.c | 14 | ||||
-rw-r--r-- | lib/XCL/GetGeom.c | 26 | ||||
-rw-r--r-- | lib/XCL/GetKCnt.c | 27 | ||||
-rw-r--r-- | lib/XCL/ListExt.c | 79 | ||||
-rw-r--r-- | lib/XCL/NextEvent.c | 103 | ||||
-rw-r--r-- | lib/XCL/Pending.c | 36 | ||||
-rw-r--r-- | lib/XCL/PmapBgnd.c | 13 | ||||
-rw-r--r-- | lib/XCL/PutImage.c | 897 | ||||
-rw-r--r-- | lib/XCL/QuExt.c | 28 | ||||
-rw-r--r-- | lib/XCL/QuTree.c | 28 | ||||
-rw-r--r-- | lib/XCL/SetCRects.c | 32 | ||||
-rw-r--r-- | lib/XCL/Sync.c | 25 | ||||
-rw-r--r-- | xcl/src/ChKeyCon.c | 42 | ||||
-rw-r--r-- | xcl/src/ChkTypWEv.c | 81 | ||||
-rw-r--r-- | xcl/src/GetGeom.c | 26 | ||||
-rw-r--r-- | xcl/src/GetKCnt.c | 27 | ||||
-rw-r--r-- | xcl/src/ListExt.c | 79 | ||||
-rw-r--r-- | xcl/src/NextEvent.c | 103 | ||||
-rw-r--r-- | xcl/src/Pending.c | 36 | ||||
-rw-r--r-- | xcl/src/PutImage.c | 897 | ||||
-rw-r--r-- | xcl/src/QuExt.c | 28 | ||||
-rw-r--r-- | xcl/src/QuTree.c | 28 | ||||
-rw-r--r-- | xcl/src/SetCRects.c | 32 | ||||
-rw-r--r-- | xcl/src/Sync.c | 25 |
26 files changed, 2489 insertions, 346 deletions
diff --git a/lib/XCL/ChKeyCon.c b/lib/XCL/ChKeyCon.c new file mode 100644 index 0000000..ae44a5b --- /dev/null +++ b/lib/XCL/ChKeyCon.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +int XChangeKeyboardControl(Display *dpy, unsigned long mask, XKeyboardControl *value_list) +{ + unsigned long values[8]; + register unsigned long *value = values; + + if(!mask) + return 1; + + if (mask & KBKeyClickPercent) + *value++ = value_list->key_click_percent; + + if (mask & KBBellPercent) + *value++ = value_list->bell_percent; + + if (mask & KBBellPitch) + *value++ = value_list->bell_pitch; + + if (mask & KBBellDuration) + *value++ = value_list->bell_duration; + + if (mask & KBLed) + *value++ = value_list->led; + + if (mask & KBLedMode) + *value++ = value_list->led_mode; + + if (mask & KBKey) + *value++ = value_list->key; + + if (mask & KBAutoRepeatMode) + *value++ = value_list->auto_repeat_mode; + + XCBChangeKeyboardControl(XCBConnectionOfDisplay(dpy), mask, values); + return 1; +} diff --git a/lib/XCL/ChkTypWEv.c b/lib/XCL/ChkTypWEv.c index 53ca6e6..a2e8b97 100644 --- a/lib/XCL/ChkTypWEv.c +++ b/lib/XCL/ChkTypWEv.c @@ -4,59 +4,50 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> -static Bool _XCheckTypedWindowEvent(Display *dpy, const Window w, const int type, XEvent *event, register _XQEvent **prev) +/* It doesn't matter how this struct is packed by the compiler. */ +typedef struct { - register _XQEvent *qelt = *prev ? (*prev)->next : dpy->head; - register XEvent *e; - while(qelt) { - e = &qelt->event; - if (e->xany.window == w && e->type == type) { - *event = *e; - _XDeq(dpy, *prev, qelt); - UnlockDisplay(dpy); - return True; - } - *prev = qelt; - qelt = qelt->next; - } - return False; + BYTE response_type; + Window w; + Display *dpy; + Bool (*event_proc)(Display *, XEvent *, xEvent *); + XEvent *e; +} TypeWindowEvent; + +static int MatchTypeWindowEvent(const XCBGenericEvent *l, const XCBGenericEvent *r) +{ + TypeWindowEvent *tw; + xEvent *xev; + if(l->response_type != r->response_type) + return 0; + + /* FIXME: breaks encapsulation: relies on r being the queued item */ + tw = (TypeWindowEvent *) l; + xev = (xEvent *) r; + + if(!tw->event_proc(tw->dpy, tw->e, xev)) + return 0; + if(tw->w != tw->e->xany.window) + return 0; + return 1; } -/* Check existing events in queue to find if any match. If so, return. - * If not, flush buffer and see if any more events are readable. If one - * matches, return. If all else fails, tell the user no events found. */ +/* Check events for a match, without blocking. */ /* w: Selected window. */ /* type: Selected event type. */ /* event: XEvent to be filled in. */ Bool XCheckTypedWindowEvent(Display *dpy, Window w, int type, XEvent *event) { - _XQEvent *prev = NULL; - unsigned long qe_serial = 0; - - LockDisplay(dpy); - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; - if (prev) - qe_serial = prev->qserial_num; - _XEventsQueued(dpy, QueuedAfterReading); - if (prev && prev->qserial_num != qe_serial) - /* another thread has snatched this event */ - prev = NULL; - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; - if (prev) - qe_serial = prev->qserial_num; - _XFlush(dpy); - if (prev && prev->qserial_num != qe_serial) - /* another thread has snatched this event */ - prev = NULL; - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; + register XCBConnection *c = XCBConnectionOfDisplay(dpy); + TypeWindowEvent tw = { type, w, dpy, dpy->event_vec[type & 0177], event }; + XCBGenericEvent *ret; - UnlockDisplay(dpy); - return False; + _XEventsQueued(dpy, QueuedAfterFlush); + ret = XCBEventQueueRemove(c, MatchTypeWindowEvent, (XCBGenericEvent *) &tw); + if(!ret) + return False; + free(ret); + return True; } diff --git a/lib/XCL/CrPixmap.c b/lib/XCL/CrPixmap.c new file mode 100644 index 0000000..d822256 --- /dev/null +++ b/lib/XCL/CrPixmap.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +Pixmap XCreatePixmap(Display *dpy, Drawable d, unsigned int width, unsigned int height, unsigned int depth) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + PIXMAP p = XCBPIXMAPNew(c); + XCBCreatePixmap(c, depth, p, XCLDRAWABLE(d), width, height); + return p.xid; +} diff --git a/lib/XCL/GetGeom.c b/lib/XCL/GetGeom.c new file mode 100644 index 0000000..6231751 --- /dev/null +++ b/lib/XCL/GetGeom.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +Status XGetGeometry(Display *dpy, Drawable d, Window *root, int *x, int *y, + unsigned int *width, unsigned int *height, unsigned int *borderWidth, unsigned int *depth) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBGetGeometryRep *r; + + r = XCBGetGeometryReply(c, XCBGetGeometry(c, XCLDRAWABLE(d)), 0); + if(!r) + return 0; + *depth = r->depth; + *root = r->root.xid; + *x = cvtINT16toInt(r->x); + *y = cvtINT16toInt(r->y); + *width = r->width; + *height = r->height; + *borderWidth = r->border_width; + free(r); + return 1; +} diff --git a/lib/XCL/GetKCnt.c b/lib/XCL/GetKCnt.c new file mode 100644 index 0000000..3ccc538 --- /dev/null +++ b/lib/XCL/GetKCnt.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +int XGetKeyboardControl(Display *dpy, register XKeyboardState *state) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBGetKeyboardControlRep *r; + + r = XCBGetKeyboardControlReply(c, XCBGetKeyboardControl(c), 0); + /* error check: Xlib doesn't check this */ + if(!r) + return 0; + + state->global_auto_repeat = r->global_auto_repeat; + state->led_mask = r->led_mask; + state->key_click_percent = r->key_click_percent; + state->bell_percent = r->bell_percent; + state->bell_pitch = r->bell_pitch; + state->bell_duration = r->bell_duration; + memcpy(state->auto_repeats, r->auto_repeats, sizeof state->auto_repeats); + free(r); + return 1; +} diff --git a/lib/XCL/ListExt.c b/lib/XCL/ListExt.c new file mode 100644 index 0000000..f246446 --- /dev/null +++ b/lib/XCL/ListExt.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +char **XListExtensions(Display *dpy, int *nextensions) +{ +#if 0 /* not implemented yet */ + xListExtensionsReply rep; + char **list; + char *ch; + register unsigned i; + register int length; + register xReq *req; + register long rlen; + + LockDisplay(dpy); + GetEmptyReq (ListExtensions, req); + + if (! _XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return (char **) NULL; + } + + if (rep.nExtensions) { + list = (char **) Xmalloc ( + (unsigned)(rep.nExtensions * sizeof (char *))); + rlen = rep.length << 2; + ch = (char *) Xmalloc ((unsigned) rlen + 1); + /* +1 to leave room for last null-terminator */ + + if ((!list) || (!ch)) { + if (list) Xfree((char *) list); + if (ch) Xfree((char *) ch); + _XEatData(dpy, (unsigned long) rlen); + UnlockDisplay(dpy); + SyncHandle(); + return (char **) NULL; + } + + _XReadPad (dpy, ch, rlen); + /* + * unpack into null terminated strings. + */ + length = *ch; + for (i = 0; i < rep.nExtensions; i++) { + list[i] = ch+1; /* skip over length */ + ch += length + 1; /* find next length ... */ + length = *ch; + *ch = '\0'; /* and replace with null-termination */ + } + } + else list = (char **) NULL; + + *nextensions = rep.nExtensions; + UnlockDisplay(dpy); + SyncHandle(); + return (list); +#else + char **list = malloc(sizeof(char *)); + list[0] = malloc(sizeof(char) * 2) + 1; + list[0][0] = '\0'; /* just to be safe */ + *nextensions = 0; + return 0; /* no extensions available */ +#endif +} + +int XFreeExtensionList(char **list) +{ + if(list != NULL) + { + Xfree(list[0]-1); + Xfree((char *)list); + } + return 1; +} diff --git a/lib/XCL/NextEvent.c b/lib/XCL/NextEvent.c index a2c83e4..bc4863e 100644 --- a/lib/XCL/NextEvent.c +++ b/lib/XCL/NextEvent.c @@ -4,109 +4,32 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> #include <assert.h> #include <unistd.h> -/* Return next event in queue, or if none, flush output and wait for events. */ -int XNextEvent(register Display *dpy, register XEvent *event) +static int _XHandleInternalEvent(Display *dpy, XCBGenericEvent *e) { - register _XQEvent *qelt; - - LockDisplay(dpy); - if (dpy->head == NULL) - _XReadEvents(dpy); - qelt = dpy->head; - *event = qelt->event; - _XDeq(dpy, NULL, qelt); - UnlockDisplay(dpy); + if(e->response_type == X_Error) + { + _XError(dpy, (xError *) e); + return 1; + } return 0; } -/* _XReadEvents - Flush the output queue, then read as many events as - * possible (but at least 1) and enqueue them. */ -void _XReadEvents(Display *dpy) +/* Return next event in queue, or if none, flush output and wait for events. */ +int XNextEvent(Display *dpy, register XEvent *event) { register XCBConnection *c = XCBConnectionOfDisplay(dpy); XCBGenericEvent *e; if(XCBEventQueueIsEmpty(c)) - _XFlush(dpy); + XCBFlush(c); - do { + do e = XCBWaitEvent(c); - if(e->response_type == X_Error) - _XError(dpy, (xError *) e); - else - _XEnq(dpy, (xEvent *) e); - free(e); - } while(!XCBEventQueueIsEmpty(c)); -} - -/* _XEnq - Place event packets on the display's queue. note that no - * squishing of move events in V11, since there is pointer motion hints... */ -void _XEnq(register Display *dpy, register xEvent *event) -{ - register _XQEvent *qelt; - - qelt = dpy->qfree; - if(qelt) - /* If dpy->qfree is non-NULL do this, else malloc a new one. */ - dpy->qfree = qelt->next; - else - qelt = (_XQEvent *) Xmalloc(sizeof(_XQEvent)); - -#if 0 /* not implemented yet */ - if(!qelt) - /* Malloc call failed! */ - ESET(ENOMEM); - _XIOError(dpy); - } -#else - assert(qelt); -#endif - - /* invariant: qelt points to usable but uninitialized memory. */ - - /* go call through display to find proper event reformatter */ - if(!(*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) - { - /* reformatter told us not to enqueue this one after all. - * Put it back on the free list. */ - qelt->next = dpy->qfree; - dpy->qfree = qelt; - return; - } - - /* invariant: qelt->event is initialized but nothing else is. */ - qelt->qserial_num = dpy->next_event_serial_num++; - - /* list method: append at end */ - if(dpy->tail) - dpy->tail->next = qelt; - else - dpy->head = qelt; - - dpy->tail = qelt; - qelt->next = NULL; - - dpy->qlen++; -} - -/* _XDeq - Remove event packet from the display's queue. */ -/* prev: element before qelt */ -/* qelt: element to be unlinked */ -void _XDeq(register Display *dpy, register _XQEvent *prev, register _XQEvent *qelt) -{ - if(prev) - prev->next = qelt->next; - else - dpy->head = qelt->next; + while(_XHandleInternalEvent(dpy, e) || !(*dpy->event_vec[e->response_type & 0177])(dpy, event, (xEvent *) e)); - if(!qelt->next) - dpy->tail = prev; - - qelt->qserial_num = 0; - qelt->next = dpy->qfree; - dpy->qfree = qelt; - dpy->qlen--; + return 0; } diff --git a/lib/XCL/Pending.c b/lib/XCL/Pending.c index f8da4f2..4e8380f 100644 --- a/lib/XCL/Pending.c +++ b/lib/XCL/Pending.c @@ -4,18 +4,15 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> /* Read in pending events if needed and return the number of queued events. */ int XEventsQueued(register Display *dpy, int mode) { - int ret_val; - LockDisplay(dpy); - if (dpy->qlen || (mode == QueuedAlready)) - ret_val = dpy->qlen; - else - ret_val = _XEventsQueued (dpy, mode); - UnlockDisplay(dpy); - return ret_val; + int ret = XCBEventQueueLength(XCBConnectionOfDisplay(dpy)); + if(!ret && mode != QueuedAlready) + ret = _XEventsQueued(dpy, mode); + return ret; } int XPending(Display *dpy) @@ -25,21 +22,22 @@ int XPending(Display *dpy) int _XEventsQueued(register Display *dpy, int mode) { - fd_set fds; - struct timeval tv = { 0, 0 }; + XCBConnection *c = XCBConnectionOfDisplay(dpy); if(mode == QueuedAfterFlush) + XCBFlush(c); + + /* wait for handle to be readable, without blocking. */ + /* FIXME: this select/XCBWait hack breaks encapsulation. */ + if(XCBEventQueueIsEmpty(c)) { - _XFlush(dpy); - if(dpy->qlen) - return(dpy->qlen); - } - if(XCBEventQueueIsEmpty(XCBConnectionOfDisplay(dpy))) - { + fd_set fds; + struct timeval tv = { 0, 0 }; FD_ZERO(&fds); FD_SET(dpy->fd, &fds); if(select(dpy->fd + 1, &fds, 0, 0, &tv) < 1) - return(dpy->qlen); + return 0; + XCBWait(c->handle, /* should_write */ 0); } - _XReadEvents(dpy); - return(dpy->qlen); + + return XCBEventQueueLength(c); } diff --git a/lib/XCL/PmapBgnd.c b/lib/XCL/PmapBgnd.c new file mode 100644 index 0000000..452cbe6 --- /dev/null +++ b/lib/XCL/PmapBgnd.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +int XSetWindowBackgroundPixmap(Display *dpy, Window w, Pixmap pixmap) +{ + CARD32 values[] = { pixmap }; + XCBChangeWindowAttributes(XCBConnectionOfDisplay(dpy), XCLWINDOW(w), CWBackPixmap, values); + return 1; +} diff --git a/lib/XCL/PutImage.c b/lib/XCL/PutImage.c new file mode 100644 index 0000000..4d10f50 --- /dev/null +++ b/lib/XCL/PutImage.c @@ -0,0 +1,897 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" +#include <X11/Xutil.h> +#include <stdio.h> + +#if defined(Lynx) && defined(ROUNDUP) +#undef ROUNDUP +#endif + +/* assumes pad is a power of 2 */ +#define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & ~(long)((pad) - 1)) + +static unsigned char const _reverse_byte[0x100] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static unsigned char const _reverse_nibs[0x100] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9, + 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, + 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa, + 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, + 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb, + 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c, + 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc, + 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, + 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, + 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, + 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe, + 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, + 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff +}; + +int +_XReverse_Bytes (bpt, nb) + register unsigned char *bpt; + register int nb; +{ + do { + *bpt = _reverse_byte[*bpt]; + bpt++; + } while (--nb > 0); + return 0; +} + + +/*ARGSUSED*/ +static void +NoSwap (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long h = height; + + if (srcinc == destinc) + memcpy((char *)dest, (char *)src, (int)(srcinc * (h - 1) + srclen)); + else + for (; --h >= 0; src += srcinc, dest += destinc) + memcpy((char *)dest, (char *)src, (int)srclen); +} + +static void +SwapTwoBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 2); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 2; + if (half_order == MSBFirst) + *(dest + length) = *(src + length + 1); + else + *(dest + length + 1) = *(src + length); + } + for (n = length; n > 0; n -= 2, src += 2) { + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapThreeBytes (src, dest, srclen, srcinc, destinc, height, byte_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int byte_order; +{ + long length = ((srclen + 2) / 3) * 3; + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 3; + if ((srclen - length) == 2) + *(dest + length + 1) = *(src + length + 1); + if (byte_order == MSBFirst) + *(dest + length) = *(src + length + 2); + else + *(dest + length + 2) = *(src + length); + } + for (n = length; n > 0; n -= 3, src += 3) { + *dest++ = *(src + 2); + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapFourBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length) = *(src + length + 3); + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length + 1) = *(src + length + 2); + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 2) = *(src + length + 1); + if (half_order == LSBFirst) + *(dest + length + 3) = *(src + length); + } + for (n = length; n > 0; n -= 4, src += 4) { + *dest++ = *(src + 3); + *dest++ = *(src + 2); + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapWords (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length + 1) = *(src + length + 3); + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length) = *(src + length + 2); + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 3) = *(src + length + 1); + if (half_order == LSBFirst) + *(dest + length + 2) = *(src + length); + } + for (n = length; n > 0; n -= 4, src += 2) { + *dest++ = *(src + 2); + *dest++ = *(src + 3); + *dest++ = *src++; + *dest++ = *src++; + } + } +} + +static void +SwapNibbles (src, dest, srclen, srcinc, destinc, height) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; +{ + register long h, n; + register const unsigned char *rev = _reverse_nibs; + + srcinc -= srclen; + destinc -= srclen; + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) + *dest++ = rev[*src++]; +} + +static void +ShiftNibblesLeft (src, dest, srclen, srcinc, destinc, height, nibble_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int nibble_order; +{ + register long h, n; + register unsigned char c1, c2; + + srcinc -= srclen; + destinc -= srclen; + if (nibble_order == MSBFirst) { + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) { + c1 = *src++; + c2 = *src; + *dest++ = ((c1 & 0x0f) << 4) | ((c2 & (unsigned)0xf0) >> 4); + } + } else { + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) { + c1 = *src++; + c2 = *src; + *dest++ = ((c2 & 0x0f) << 4) | ((c1 & (unsigned)0xf0) >> 4); + } + } +} + +/*ARGSUSED*/ +static void +SwapBits (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= srclen; + destinc -= srclen; + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) + *dest++ = rev[*src++]; +} + +static void +SwapBitsAndTwoBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; +{ + long length = ROUNDUP(srclen, 2); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 2; + if (half_order == MSBFirst) + *(dest + length) = rev[*(src + length + 1)]; + else + *(dest + length + 1) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 2, src += 2) { + *dest++ = rev[*(src + 1)]; + *dest++ = rev[*src]; + } + } +} + +static void +SwapBitsAndFourBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length) = rev[*(src + length + 3)]; + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length + 1) = rev[*(src + length + 2)]; + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 2) = rev[*(src + length + 1)]; + if (half_order == LSBFirst) + *(dest + length + 3) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 4, src += 4) { + *dest++ = rev[*(src + 3)]; + *dest++ = rev[*(src + 2)]; + *dest++ = rev[*(src + 1)]; + *dest++ = rev[*src]; + } + } +} + +static void +SwapBitsAndWords (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length + 1) = rev[*(src + length + 3)]; + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length) = rev[*(src + length + 2)]; + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 3) = rev[*(src + length + 1)]; + if (half_order == LSBFirst) + *(dest + length + 2) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 4, src += 2) { + *dest++ = rev[*(src + 2)]; + *dest++ = rev[*(src + 3)]; + *dest++ = rev[*src++]; + *dest++ = rev[*src++]; + } + } +} + +/* + +The following table gives the bit ordering within bytes (when accessed +sequentially) for a scanline containing 32 bits, with bits numbered 0 to +31, where bit 0 should be leftmost on the display. For a given byte +labelled A-B, A is for the most significant bit of the byte, and B is +for the least significant bit. + +legend: + 1 scanline-unit = 8 + 2 scanline-unit = 16 + 4 scanline-unit = 32 + M byte-order = MostSignificant + L byte-order = LeastSignificant + m bit-order = MostSignificant + l bit-order = LeastSignificant + + +format ordering + +1Mm 00-07 08-15 16-23 24-31 +2Mm 00-07 08-15 16-23 24-31 +4Mm 00-07 08-15 16-23 24-31 +1Ml 07-00 15-08 23-16 31-24 +2Ml 15-08 07-00 31-24 23-16 +4Ml 31-24 23-16 15-08 07-00 +1Lm 00-07 08-15 16-23 24-31 +2Lm 08-15 00-07 24-31 16-23 +4Lm 24-31 16-23 08-15 00-07 +1Ll 07-00 15-08 23-16 31-24 +2Ll 07-00 15-08 23-16 31-24 +4Ll 07-00 15-08 23-16 31-24 + + +The following table gives the required conversion between any two +formats. It is based strictly on the table above. If you believe one, +you should believe the other. + +legend: + n no changes + s reverse 8-bit units within 16-bit units + l reverse 8-bit units within 32-bit units + w reverse 16-bit units within 32-bit units + R reverse bits within 8-bit units + S s+R + L l+R + W w+R + +*/ + +static void (* const (SwapFunction[12][12]))() = { +#define n NoSwap, +#define s SwapTwoBytes, +#define l SwapFourBytes, +#define w SwapWords, +#define R SwapBits, +#define S SwapBitsAndTwoBytes, +#define L SwapBitsAndFourBytes, +#define W SwapBitsAndWords, + +/* 1Mm 2Mm 4Mm 1Ml 2Ml 4Ml 1Lm 2Lm 4Lm 1Ll 2Ll 4Ll */ +/* 1Mm */ { n n n R S L n s l R R R }, +/* 2Mm */ { n n n R S L n s l R R R }, +/* 4Mm */ { n n n R S L n s l R R R }, +/* 1Ml */ { R R R n s l R S L n n n }, +/* 2Ml */ { S S S s n w S R W s s s }, +/* 4Ml */ { L L L l w n L W R l l l }, +/* 1Lm */ { n n n R S L n s l R R R }, +/* 2Lm */ { s s s S R W s n w S S S }, +/* 4Lm */ { l l l L W R l w n L L L }, +/* 1Ll */ { R R R n s l R S L n n n }, +/* 2Ll */ { R R R n s l R S L n n n }, +/* 4Ll */ { R R R n s l R S L n n n } + +#undef n +#undef s +#undef l +#undef w +#undef R +#undef S +#undef L +#undef W + +}; + +/* Of course, the table above is a lie. We also need to factor in the + * order of the source data to cope with swapping half of a unit at the + * end of a scanline, since we are trying to avoid de-ref'ing off the + * end of the source. + * + * Defines whether the first half of a unit has the first half of the data + */ +static int const HalfOrder[12] = { + LSBFirst, /* 1Mm */ + LSBFirst, /* 2Mm */ + LSBFirst, /* 4Mm */ + LSBFirst, /* 1Ml */ + MSBFirst, /* 2Ml */ + MSBFirst, /* 4Ml */ + LSBFirst, /* 1Lm */ + MSBFirst, /* 2Lm */ + MSBFirst, /* 4Lm */ + LSBFirst, /* 1Ll */ + LSBFirst, /* 2Ll */ + LSBFirst /* 4Ll */ + }; + +/* Finally, for SwapWords cases, the half order depends not just on the source + * but also on the destination scanline unit. Use of this table changes some + * MSBFirsts to LSBFirsts that are "do not care" (because the function will be + * NoSwap or SwapBits) in addition to changing the desired ones. + */ + +static int const HalfOrderWord[12] = { + MSBFirst, /* 1Mm */ + MSBFirst, /* 2Mm */ + MSBFirst, /* 4Mm */ + MSBFirst, /* 1Ml */ + MSBFirst, /* 2Ml */ + LSBFirst, /* 4Ml */ + MSBFirst, /* 1Lm */ + MSBFirst, /* 2Lm */ + LSBFirst, /* 4Lm */ + MSBFirst, /* 1Ll */ + MSBFirst, /* 2Ll */ + MSBFirst /* 4Ll */ + }; + +/* + * This macro creates a value from 0 to 11 suitable for indexing + * into the table above. + */ +#define ComposeIndex(bitmap_unit, bitmap_bit_order, byte_order) \ + (((bitmap_unit == 32) ? 2 : ((bitmap_unit == 16) ? 1 : 0)) \ + + (((bitmap_bit_order == MSBFirst) ? 0 : 3) \ + + ((byte_order == MSBFirst) ? 0 : 6))) + +#if 0 /* not needed, ever */ +/* Cancel a GetReq operation, before doing _XSend or Data */ + +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define UnGetReq(name)\ + dpy->bufptr -= SIZEOF(x##name##Req);\ + dpy->request-- +#else +#define UnGetReq(name)\ + dpy->bufptr -= SIZEOF(x/**/name/**/Req);\ + dpy->request-- +#endif +#endif + +struct SendImageParams +{ + Display *dpy; + int avail_request_size; + int dest_bits_per_pixel; + int dest_scanline_pad; + int req_xoffset; + int req_yoffset; + DRAWABLE drawable; + GCONTEXT gc; + int x; + int y; + unsigned int width; + unsigned int height; + int format; + int leftPad; + XImage *image; + long total_xoffset; + void (*swapfunc)(); + int half_order; +}; + +static void SendImage(dpy, is_xyimage, p, depth) + register Display *const dpy; + const int is_xyimage; + struct SendImageParams *const p; + const int depth; +{ + long bytes_per_src, bytes_per_dest, length; + long bytes_per_line = p->image->bytes_per_line; + long bytes_per_src_plane = bytes_per_line * p->image->height; + long bytes_per_dest_plane; + unsigned char *src, *dest, *buf; + unsigned char *extra = 0; + register int j; + + p->total_xoffset = (unsigned)(p->total_xoffset - p->leftPad) >> 3; + bytes_per_dest = (unsigned long)ROUNDUP((long)p->width * p->dest_bits_per_pixel + p->leftPad, p->dest_scanline_pad) >> 3; + bytes_per_dest_plane = bytes_per_dest * p->height; + length = bytes_per_dest_plane * depth; + + src = (unsigned char *)p->image->data + (p->req_yoffset * bytes_per_line) + p->total_xoffset; + bytes_per_src = (p->width * p->image->bits_per_pixel + p->leftPad + 7) >> 3; + + if (!is_xyimage && (p->image->bits_per_pixel == 4) && ((unsigned int) p->req_xoffset & 0x01)) { + if (! (extra = (unsigned char *) + Xmalloc((unsigned) (p->height * bytes_per_line)))) { + goto done; + } + + ShiftNibblesLeft(src, extra, bytes_per_src, + bytes_per_line, + bytes_per_line, p->height, + p->image->byte_order); + src = extra; + } + + /* when total_xoffset > 0, we have to worry about stepping off the + * end of p->image->data. + */ + if ((p->swapfunc == NoSwap) && + (bytes_per_line == bytes_per_dest) && + (((p->total_xoffset == 0) && + ((depth == 1) || (p->image->height == p->height))) || + ((depth == 1) && + ((p->req_yoffset + p->height) < (unsigned)p->image->height)))) { + XCBPutImage(XCBConnectionOfDisplay(dpy), p->format, p->drawable, + p->gc, p->width, p->height, p->x, p->y, p->leftPad, depth, + length, src); + goto done; + } + + length = ROUNDUP(length, 4); + if ((buf = _XAllocScratch(dpy, (unsigned long) (length))) == NULL) { + goto done; + } + + p->total_xoffset &= (p->image->bitmap_unit - 1) >> 3; + + if (is_xyimage && (p->total_xoffset > 0) && + (p->image->byte_order != p->image->bitmap_bit_order)) { + char *temp; + long bytes_per_temp_plane, temp_length; + + bytes_per_line = bytes_per_src + p->total_xoffset; + src -= p->total_xoffset; + bytes_per_temp_plane = bytes_per_line * p->height; + temp_length = ROUNDUP(bytes_per_temp_plane * depth, 4); + if ((extra = temp = Xmalloc((unsigned) temp_length)) == NULL) { + goto done; + } + + p->swapfunc = SwapFunction[ComposeIndex(p->image->bitmap_unit, + p->image->bitmap_bit_order, + p->image->byte_order)] + [ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)]; + for (dest = temp, j = depth; + --j >= 0; + src += bytes_per_src_plane, dest += bytes_per_temp_plane) + (*p->swapfunc)((unsigned char *)src, (unsigned char *)dest, + bytes_per_line, (long)p->image->bytes_per_line, + bytes_per_line, p->height, p->half_order); + p->swapfunc = SwapFunction[ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)] + [ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + p->half_order = HalfOrder[ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)]; + src = temp + p->total_xoffset; + bytes_per_src_plane = bytes_per_temp_plane; + } + + for (dest = buf, j = depth; + --j >= 0; + src += bytes_per_src_plane, dest += bytes_per_dest_plane) + (*p->swapfunc)((unsigned char *)src, (unsigned char *)dest, + bytes_per_src, bytes_per_line, + bytes_per_dest, p->height, p->half_order); + + XCBPutImage(XCBConnectionOfDisplay(dpy), p->format, p->drawable, + p->gc, p->width, p->height, p->x, p->y, p->leftPad, depth, + length, buf); + +done: + if (extra) + Xfree(extra); +} + +static void SendXYImage(struct SendImageParams *const p) +{ + /* The protocol requires left-pad of zero on all ZPixmap, even + * though the 1-bit case is identical to bitmap format. This is a + * bug in the protocol, caused because 1-bit ZPixmap was added late + * in the game. Hairy shifting code compensation isn't worth it, + * just use XYPixmap format instead. + */ + if ((p->leftPad != 0) && (p->format == ZPixmap)) + p->format = XYPixmap; + + SendImage(p->dpy, 1, p, p->image->depth); +} + +static void SendZImage(struct SendImageParams *const p) +{ + SendImage(p->dpy, 0, p, 1); +} + +static void +PutSubImage(p, req_xoffset, req_yoffset, x, y, req_width, req_height) + struct SendImageParams *const p; + int req_xoffset, req_yoffset; + int x, y; + unsigned int req_width, req_height; +{ + int BytesPerRow; + + if ((req_width == 0) || (req_height == 0)) + return; + + if ((p->image->bits_per_pixel == 1) || (p->image->format != ZPixmap)) { + p->total_xoffset = p->image->xoffset + req_xoffset; + p->leftPad = p->total_xoffset & (p->dpy->bitmap_unit - 1); + BytesPerRow = (ROUNDUP((long)req_width + p->leftPad, + p->dpy->bitmap_pad) >> 3) * p->image->depth; + } else { + p->total_xoffset = req_xoffset * p->image->bits_per_pixel; + p->leftPad = 0; + BytesPerRow = ROUNDUP((long)req_width * p->dest_bits_per_pixel, + p->dest_scanline_pad) >> 3; + } + + if ((BytesPerRow * req_height) <= p->avail_request_size) { + p->req_xoffset = req_xoffset; + p->req_yoffset = req_yoffset; + p->x = x; + p->y = y; + p->width = req_width; + p->height = req_height; + p->format = p->image->format; + if ((p->image->bits_per_pixel == 1) || (p->image->format != ZPixmap)) + SendXYImage(p); + else + SendZImage(p); + } else if (req_height > 1) { + int SubImageHeight = p->avail_request_size / BytesPerRow; + + if (SubImageHeight == 0) + SubImageHeight = 1; + + PutSubImage(p, req_xoffset, req_yoffset, x, y, + req_width, (unsigned int) SubImageHeight); + + PutSubImage(p, req_xoffset, + req_yoffset + SubImageHeight, x, y + SubImageHeight, + req_width, req_height - SubImageHeight); + } else { + int SubImageWidth = (((p->avail_request_size << 3) / p->dest_scanline_pad) + * p->dest_scanline_pad) - p->leftPad; + + PutSubImage(p, req_xoffset, req_yoffset, x, y, + (unsigned int) SubImageWidth, 1); + + PutSubImage(p, req_xoffset + SubImageWidth, + req_yoffset, x + SubImageWidth, y, + req_width - SubImageWidth, 1); + } +} + +extern void _XInitImageFuncPtrs(); + +int XPutImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, req_width, + req_height) + register Display *dpy; + Drawable d; + GC gc; + register XImage *image; + int x, y; + unsigned int req_width, req_height; + int req_xoffset, req_yoffset; +{ + long width = req_width; + long height = req_height; + char *tmp = 0; + XImage img; + struct SendImageParams p; + + if (req_xoffset < 0) { + width += req_xoffset; + req_xoffset = 0; + } + if (req_yoffset < 0) { + height += req_yoffset; + req_yoffset = 0; + } + if ((req_xoffset + width) > image->width) + width = image->width - req_xoffset; + if ((req_yoffset + height) > image->height) + height = image->height - req_yoffset; + if ((width <= 0) || (height <= 0)) + return 0; + + p.dpy = dpy; + p.drawable = XCLDRAWABLE(d); + p.gc = XCLGCONTEXT(gc->gid); + p.image = image; + p.avail_request_size = ((65536 < dpy->max_request_size) ? + (65536 << 2) : (dpy->max_request_size << 2)) + - SIZEOF(xPutImageReq); + + + if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) { + p.dest_bits_per_pixel = 1; + p.dest_scanline_pad = dpy->bitmap_pad; + + p.swapfunc = SwapFunction[ComposeIndex(image->bitmap_unit, + image->bitmap_bit_order, + image->byte_order)] + [ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + p.half_order = HalfOrder[ComposeIndex(image->bitmap_unit, + image->bitmap_bit_order, + image->byte_order)]; + if (p.half_order == MSBFirst) + p.half_order = HalfOrderWord[ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + } else { + register int n; + register ScreenFormat *format; + + if (image->byte_order == dpy->byte_order || image->bits_per_pixel == 8) + p.swapfunc = NoSwap; + else + switch (p.image->bits_per_pixel) + { + case 32: + p.swapfunc = SwapFourBytes; + break; + case 24: + p.swapfunc = SwapThreeBytes; + break; + case 16: + p.swapfunc = SwapTwoBytes; + break; + default: + p.swapfunc = SwapNibbles; + } + + p.dest_bits_per_pixel = image->bits_per_pixel; + p.dest_scanline_pad = image->bitmap_pad; + for (n = dpy->nformats, format = dpy->pixmap_format; --n >= 0; format++) + if (format->depth == image->depth) { + p.dest_bits_per_pixel = format->bits_per_pixel; + p.dest_scanline_pad = format->scanline_pad; + } + if (p.dest_bits_per_pixel != image->bits_per_pixel) { + register long i, j; + /* XXX slow, but works */ + img.width = width; + img.height = height; + img.xoffset = 0; + img.format = ZPixmap; + img.byte_order = dpy->byte_order; + p.swapfunc = NoSwap; /* inv: img.byte_order == dpy->byte_order */ + img.bitmap_unit = dpy->bitmap_unit; + img.bitmap_bit_order = dpy->bitmap_bit_order; + img.bitmap_pad = p.dest_scanline_pad; + img.depth = image->depth; + img.bits_per_pixel = p.dest_bits_per_pixel; + img.bytes_per_line = ROUNDUP((p.dest_bits_per_pixel * width), + p.dest_scanline_pad) >> 3; + tmp = Xmalloc((unsigned) (img.bytes_per_line * height)); + if (tmp == NULL) + return 0; + img.data = tmp; + _XInitImageFuncPtrs(&img); + for (j = height; --j >= 0; ) + for (i = width; --i >= 0; ) + XPutPixel(&img, i, j, XGetPixel(image, req_xoffset + i, + req_yoffset + j)); + p.image = &img; + req_xoffset = req_yoffset = 0; + } + } + + LockDisplay(dpy); + FlushGC(dpy, gc); + + PutSubImage(&p, req_xoffset, req_yoffset, x, y, + (unsigned int) width, (unsigned int) height); + + UnlockDisplay(dpy); + Xfree(tmp); + return 0; +} diff --git a/lib/XCL/QuExt.c b/lib/XCL/QuExt.c new file mode 100644 index 0000000..f990cca --- /dev/null +++ b/lib/XCL/QuExt.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +/* XXX: for once, XCL caches when Xlib doesn't. Hah! */ + +Bool XQueryExtension(Display *dpy, const char *name, int *major_opcode, + int *first_event, int *first_error) +{ +#if 1 /* FIXME: disabling extensions until XCL progresses further */ + return 0; /* extension not present */ +#else + XCBConnection *c = XCBConnectionOfDisplay(dpy); + const XCBQueryExtensionRep *r = XCBQueryExtensionCached(c, name, 0); + /* error check: Xlib doesn't check this */ + if(!r) + return 0; /* extension not present */ + + *major_opcode = r->major_opcode; + *first_event = r->first_event; + *first_error = r->first_error; + /* must not free r: it's aliased from the cache. */ + return r->present; +#endif +} diff --git a/lib/XCL/QuTree.c b/lib/XCL/QuTree.c new file mode 100644 index 0000000..2af48f6 --- /dev/null +++ b/lib/XCL/QuTree.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +Status XQueryTree(Display *dpy, Window w, Window *root, Window *parent, Window **children, unsigned int *nchildren) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBQueryTreeRep *r; + + r = XCBQueryTreeReply(c, XCBQueryTree(c, XCLWINDOW(w)), 0); + if(!r) + return 0; + + *children = 0; + *root = r->root.xid; + *parent = r->parent.xid; + *nchildren = r->children_len; + if(*nchildren <= 0) + return 1; + + /* reuse the memory chunk the reply came in. */ + memmove(r, XCBQueryTreechildren(r), *nchildren * sizeof(WINDOW)); + *children = (Window *) r; + return 1; +} diff --git a/lib/XCL/SetCRects.c b/lib/XCL/SetCRects.c new file mode 100644 index 0000000..29132a1 --- /dev/null +++ b/lib/XCL/SetCRects.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +/* can only call when display is locked. */ +void _XSetClipRectangles(Display *dpy, GC gc, int clip_x_origin, int clip_y_origin, XRectangle *rectangles, int n, int ordering) +{ + unsigned long dirty; + register _XExtension *ext; + XCBSetClipRectangles(XCBConnectionOfDisplay(dpy), ordering, XCLGCONTEXT(gc->gid), clip_x_origin, clip_y_origin, n, (RECTANGLE *) rectangles); + + gc->values.clip_x_origin = clip_x_origin; + gc->values.clip_y_origin = clip_y_origin; + gc->rects = 1; + dirty = gc->dirty & ~(GCClipMask | GCClipXOrigin | GCClipYOrigin); + gc->dirty = GCClipMask | GCClipXOrigin | GCClipYOrigin; + /* call out to any extensions interested */ + for (ext = dpy->ext_procs; ext; ext = ext->next) + if (ext->flush_GC) (*ext->flush_GC)(dpy, gc, &ext->codes); + gc->dirty = dirty; +} + +int XSetClipRectangles(Display *dpy, GC gc, int clip_x_origin, int clip_y_origin, XRectangle *rectangles, int n, int ordering) +{ + LockDisplay(dpy); + _XSetClipRectangles(dpy, gc, clip_x_origin, clip_y_origin, rectangles, n, ordering); + UnlockDisplay(dpy); + return 1; +} diff --git a/lib/XCL/Sync.c b/lib/XCL/Sync.c index f87a40e..ec07463 100644 --- a/lib/XCL/Sync.c +++ b/lib/XCL/Sync.c @@ -4,27 +4,14 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> /* Synchronize with errors and events, optionally discarding pending events */ - -int XSync(register Display *dpy, Bool discard) +int XSync(Display *dpy, Bool discard) { - LockDisplay(dpy); - XCBSync(XCBConnectionOfDisplay(dpy), 0); - - if (discard && dpy->head) - { - _XQEvent *qelt; - - for (qelt = dpy->head; qelt; qelt = qelt->next) - qelt->qserial_num = 0; - - ((_XQEvent *)dpy->tail)->next = dpy->qfree; - dpy->qfree = (_XQEvent *)dpy->head; - dpy->head = dpy->tail = NULL; - dpy->qlen = 0; - } - UnlockDisplay(dpy); + register XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBSync(c, 0); + if(discard) + XCBEventQueueClear(c); return 1; } - diff --git a/xcl/src/ChKeyCon.c b/xcl/src/ChKeyCon.c new file mode 100644 index 0000000..ae44a5b --- /dev/null +++ b/xcl/src/ChKeyCon.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +int XChangeKeyboardControl(Display *dpy, unsigned long mask, XKeyboardControl *value_list) +{ + unsigned long values[8]; + register unsigned long *value = values; + + if(!mask) + return 1; + + if (mask & KBKeyClickPercent) + *value++ = value_list->key_click_percent; + + if (mask & KBBellPercent) + *value++ = value_list->bell_percent; + + if (mask & KBBellPitch) + *value++ = value_list->bell_pitch; + + if (mask & KBBellDuration) + *value++ = value_list->bell_duration; + + if (mask & KBLed) + *value++ = value_list->led; + + if (mask & KBLedMode) + *value++ = value_list->led_mode; + + if (mask & KBKey) + *value++ = value_list->key; + + if (mask & KBAutoRepeatMode) + *value++ = value_list->auto_repeat_mode; + + XCBChangeKeyboardControl(XCBConnectionOfDisplay(dpy), mask, values); + return 1; +} diff --git a/xcl/src/ChkTypWEv.c b/xcl/src/ChkTypWEv.c index 53ca6e6..a2e8b97 100644 --- a/xcl/src/ChkTypWEv.c +++ b/xcl/src/ChkTypWEv.c @@ -4,59 +4,50 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> -static Bool _XCheckTypedWindowEvent(Display *dpy, const Window w, const int type, XEvent *event, register _XQEvent **prev) +/* It doesn't matter how this struct is packed by the compiler. */ +typedef struct { - register _XQEvent *qelt = *prev ? (*prev)->next : dpy->head; - register XEvent *e; - while(qelt) { - e = &qelt->event; - if (e->xany.window == w && e->type == type) { - *event = *e; - _XDeq(dpy, *prev, qelt); - UnlockDisplay(dpy); - return True; - } - *prev = qelt; - qelt = qelt->next; - } - return False; + BYTE response_type; + Window w; + Display *dpy; + Bool (*event_proc)(Display *, XEvent *, xEvent *); + XEvent *e; +} TypeWindowEvent; + +static int MatchTypeWindowEvent(const XCBGenericEvent *l, const XCBGenericEvent *r) +{ + TypeWindowEvent *tw; + xEvent *xev; + if(l->response_type != r->response_type) + return 0; + + /* FIXME: breaks encapsulation: relies on r being the queued item */ + tw = (TypeWindowEvent *) l; + xev = (xEvent *) r; + + if(!tw->event_proc(tw->dpy, tw->e, xev)) + return 0; + if(tw->w != tw->e->xany.window) + return 0; + return 1; } -/* Check existing events in queue to find if any match. If so, return. - * If not, flush buffer and see if any more events are readable. If one - * matches, return. If all else fails, tell the user no events found. */ +/* Check events for a match, without blocking. */ /* w: Selected window. */ /* type: Selected event type. */ /* event: XEvent to be filled in. */ Bool XCheckTypedWindowEvent(Display *dpy, Window w, int type, XEvent *event) { - _XQEvent *prev = NULL; - unsigned long qe_serial = 0; - - LockDisplay(dpy); - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; - if (prev) - qe_serial = prev->qserial_num; - _XEventsQueued(dpy, QueuedAfterReading); - if (prev && prev->qserial_num != qe_serial) - /* another thread has snatched this event */ - prev = NULL; - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; - if (prev) - qe_serial = prev->qserial_num; - _XFlush(dpy); - if (prev && prev->qserial_num != qe_serial) - /* another thread has snatched this event */ - prev = NULL; - - if(_XCheckTypedWindowEvent(dpy, w, type, event, &prev)) - return True; + register XCBConnection *c = XCBConnectionOfDisplay(dpy); + TypeWindowEvent tw = { type, w, dpy, dpy->event_vec[type & 0177], event }; + XCBGenericEvent *ret; - UnlockDisplay(dpy); - return False; + _XEventsQueued(dpy, QueuedAfterFlush); + ret = XCBEventQueueRemove(c, MatchTypeWindowEvent, (XCBGenericEvent *) &tw); + if(!ret) + return False; + free(ret); + return True; } diff --git a/xcl/src/GetGeom.c b/xcl/src/GetGeom.c new file mode 100644 index 0000000..6231751 --- /dev/null +++ b/xcl/src/GetGeom.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +Status XGetGeometry(Display *dpy, Drawable d, Window *root, int *x, int *y, + unsigned int *width, unsigned int *height, unsigned int *borderWidth, unsigned int *depth) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBGetGeometryRep *r; + + r = XCBGetGeometryReply(c, XCBGetGeometry(c, XCLDRAWABLE(d)), 0); + if(!r) + return 0; + *depth = r->depth; + *root = r->root.xid; + *x = cvtINT16toInt(r->x); + *y = cvtINT16toInt(r->y); + *width = r->width; + *height = r->height; + *borderWidth = r->border_width; + free(r); + return 1; +} diff --git a/xcl/src/GetKCnt.c b/xcl/src/GetKCnt.c new file mode 100644 index 0000000..3ccc538 --- /dev/null +++ b/xcl/src/GetKCnt.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +int XGetKeyboardControl(Display *dpy, register XKeyboardState *state) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBGetKeyboardControlRep *r; + + r = XCBGetKeyboardControlReply(c, XCBGetKeyboardControl(c), 0); + /* error check: Xlib doesn't check this */ + if(!r) + return 0; + + state->global_auto_repeat = r->global_auto_repeat; + state->led_mask = r->led_mask; + state->key_click_percent = r->key_click_percent; + state->bell_percent = r->bell_percent; + state->bell_pitch = r->bell_pitch; + state->bell_duration = r->bell_duration; + memcpy(state->auto_repeats, r->auto_repeats, sizeof state->auto_repeats); + free(r); + return 1; +} diff --git a/xcl/src/ListExt.c b/xcl/src/ListExt.c new file mode 100644 index 0000000..f246446 --- /dev/null +++ b/xcl/src/ListExt.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +char **XListExtensions(Display *dpy, int *nextensions) +{ +#if 0 /* not implemented yet */ + xListExtensionsReply rep; + char **list; + char *ch; + register unsigned i; + register int length; + register xReq *req; + register long rlen; + + LockDisplay(dpy); + GetEmptyReq (ListExtensions, req); + + if (! _XReply (dpy, (xReply *) &rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return (char **) NULL; + } + + if (rep.nExtensions) { + list = (char **) Xmalloc ( + (unsigned)(rep.nExtensions * sizeof (char *))); + rlen = rep.length << 2; + ch = (char *) Xmalloc ((unsigned) rlen + 1); + /* +1 to leave room for last null-terminator */ + + if ((!list) || (!ch)) { + if (list) Xfree((char *) list); + if (ch) Xfree((char *) ch); + _XEatData(dpy, (unsigned long) rlen); + UnlockDisplay(dpy); + SyncHandle(); + return (char **) NULL; + } + + _XReadPad (dpy, ch, rlen); + /* + * unpack into null terminated strings. + */ + length = *ch; + for (i = 0; i < rep.nExtensions; i++) { + list[i] = ch+1; /* skip over length */ + ch += length + 1; /* find next length ... */ + length = *ch; + *ch = '\0'; /* and replace with null-termination */ + } + } + else list = (char **) NULL; + + *nextensions = rep.nExtensions; + UnlockDisplay(dpy); + SyncHandle(); + return (list); +#else + char **list = malloc(sizeof(char *)); + list[0] = malloc(sizeof(char) * 2) + 1; + list[0][0] = '\0'; /* just to be safe */ + *nextensions = 0; + return 0; /* no extensions available */ +#endif +} + +int XFreeExtensionList(char **list) +{ + if(list != NULL) + { + Xfree(list[0]-1); + Xfree((char *)list); + } + return 1; +} diff --git a/xcl/src/NextEvent.c b/xcl/src/NextEvent.c index a2c83e4..bc4863e 100644 --- a/xcl/src/NextEvent.c +++ b/xcl/src/NextEvent.c @@ -4,109 +4,32 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> #include <assert.h> #include <unistd.h> -/* Return next event in queue, or if none, flush output and wait for events. */ -int XNextEvent(register Display *dpy, register XEvent *event) +static int _XHandleInternalEvent(Display *dpy, XCBGenericEvent *e) { - register _XQEvent *qelt; - - LockDisplay(dpy); - if (dpy->head == NULL) - _XReadEvents(dpy); - qelt = dpy->head; - *event = qelt->event; - _XDeq(dpy, NULL, qelt); - UnlockDisplay(dpy); + if(e->response_type == X_Error) + { + _XError(dpy, (xError *) e); + return 1; + } return 0; } -/* _XReadEvents - Flush the output queue, then read as many events as - * possible (but at least 1) and enqueue them. */ -void _XReadEvents(Display *dpy) +/* Return next event in queue, or if none, flush output and wait for events. */ +int XNextEvent(Display *dpy, register XEvent *event) { register XCBConnection *c = XCBConnectionOfDisplay(dpy); XCBGenericEvent *e; if(XCBEventQueueIsEmpty(c)) - _XFlush(dpy); + XCBFlush(c); - do { + do e = XCBWaitEvent(c); - if(e->response_type == X_Error) - _XError(dpy, (xError *) e); - else - _XEnq(dpy, (xEvent *) e); - free(e); - } while(!XCBEventQueueIsEmpty(c)); -} - -/* _XEnq - Place event packets on the display's queue. note that no - * squishing of move events in V11, since there is pointer motion hints... */ -void _XEnq(register Display *dpy, register xEvent *event) -{ - register _XQEvent *qelt; - - qelt = dpy->qfree; - if(qelt) - /* If dpy->qfree is non-NULL do this, else malloc a new one. */ - dpy->qfree = qelt->next; - else - qelt = (_XQEvent *) Xmalloc(sizeof(_XQEvent)); - -#if 0 /* not implemented yet */ - if(!qelt) - /* Malloc call failed! */ - ESET(ENOMEM); - _XIOError(dpy); - } -#else - assert(qelt); -#endif - - /* invariant: qelt points to usable but uninitialized memory. */ - - /* go call through display to find proper event reformatter */ - if(!(*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) - { - /* reformatter told us not to enqueue this one after all. - * Put it back on the free list. */ - qelt->next = dpy->qfree; - dpy->qfree = qelt; - return; - } - - /* invariant: qelt->event is initialized but nothing else is. */ - qelt->qserial_num = dpy->next_event_serial_num++; - - /* list method: append at end */ - if(dpy->tail) - dpy->tail->next = qelt; - else - dpy->head = qelt; - - dpy->tail = qelt; - qelt->next = NULL; - - dpy->qlen++; -} - -/* _XDeq - Remove event packet from the display's queue. */ -/* prev: element before qelt */ -/* qelt: element to be unlinked */ -void _XDeq(register Display *dpy, register _XQEvent *prev, register _XQEvent *qelt) -{ - if(prev) - prev->next = qelt->next; - else - dpy->head = qelt->next; + while(_XHandleInternalEvent(dpy, e) || !(*dpy->event_vec[e->response_type & 0177])(dpy, event, (xEvent *) e)); - if(!qelt->next) - dpy->tail = prev; - - qelt->qserial_num = 0; - qelt->next = dpy->qfree; - dpy->qfree = qelt; - dpy->qlen--; + return 0; } diff --git a/xcl/src/Pending.c b/xcl/src/Pending.c index f8da4f2..4e8380f 100644 --- a/xcl/src/Pending.c +++ b/xcl/src/Pending.c @@ -4,18 +4,15 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> /* Read in pending events if needed and return the number of queued events. */ int XEventsQueued(register Display *dpy, int mode) { - int ret_val; - LockDisplay(dpy); - if (dpy->qlen || (mode == QueuedAlready)) - ret_val = dpy->qlen; - else - ret_val = _XEventsQueued (dpy, mode); - UnlockDisplay(dpy); - return ret_val; + int ret = XCBEventQueueLength(XCBConnectionOfDisplay(dpy)); + if(!ret && mode != QueuedAlready) + ret = _XEventsQueued(dpy, mode); + return ret; } int XPending(Display *dpy) @@ -25,21 +22,22 @@ int XPending(Display *dpy) int _XEventsQueued(register Display *dpy, int mode) { - fd_set fds; - struct timeval tv = { 0, 0 }; + XCBConnection *c = XCBConnectionOfDisplay(dpy); if(mode == QueuedAfterFlush) + XCBFlush(c); + + /* wait for handle to be readable, without blocking. */ + /* FIXME: this select/XCBWait hack breaks encapsulation. */ + if(XCBEventQueueIsEmpty(c)) { - _XFlush(dpy); - if(dpy->qlen) - return(dpy->qlen); - } - if(XCBEventQueueIsEmpty(XCBConnectionOfDisplay(dpy))) - { + fd_set fds; + struct timeval tv = { 0, 0 }; FD_ZERO(&fds); FD_SET(dpy->fd, &fds); if(select(dpy->fd + 1, &fds, 0, 0, &tv) < 1) - return(dpy->qlen); + return 0; + XCBWait(c->handle, /* should_write */ 0); } - _XReadEvents(dpy); - return(dpy->qlen); + + return XCBEventQueueLength(c); } diff --git a/xcl/src/PutImage.c b/xcl/src/PutImage.c new file mode 100644 index 0000000..4d10f50 --- /dev/null +++ b/xcl/src/PutImage.c @@ -0,0 +1,897 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" +#include <X11/Xutil.h> +#include <stdio.h> + +#if defined(Lynx) && defined(ROUNDUP) +#undef ROUNDUP +#endif + +/* assumes pad is a power of 2 */ +#define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & ~(long)((pad) - 1)) + +static unsigned char const _reverse_byte[0x100] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static unsigned char const _reverse_nibs[0x100] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9, + 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, + 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa, + 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, + 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb, + 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c, + 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc, + 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, + 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, + 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, + 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe, + 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, + 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff +}; + +int +_XReverse_Bytes (bpt, nb) + register unsigned char *bpt; + register int nb; +{ + do { + *bpt = _reverse_byte[*bpt]; + bpt++; + } while (--nb > 0); + return 0; +} + + +/*ARGSUSED*/ +static void +NoSwap (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long h = height; + + if (srcinc == destinc) + memcpy((char *)dest, (char *)src, (int)(srcinc * (h - 1) + srclen)); + else + for (; --h >= 0; src += srcinc, dest += destinc) + memcpy((char *)dest, (char *)src, (int)srclen); +} + +static void +SwapTwoBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 2); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 2; + if (half_order == MSBFirst) + *(dest + length) = *(src + length + 1); + else + *(dest + length + 1) = *(src + length); + } + for (n = length; n > 0; n -= 2, src += 2) { + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapThreeBytes (src, dest, srclen, srcinc, destinc, height, byte_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int byte_order; +{ + long length = ((srclen + 2) / 3) * 3; + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 3; + if ((srclen - length) == 2) + *(dest + length + 1) = *(src + length + 1); + if (byte_order == MSBFirst) + *(dest + length) = *(src + length + 2); + else + *(dest + length + 2) = *(src + length); + } + for (n = length; n > 0; n -= 3, src += 3) { + *dest++ = *(src + 2); + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapFourBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length) = *(src + length + 3); + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length + 1) = *(src + length + 2); + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 2) = *(src + length + 1); + if (half_order == LSBFirst) + *(dest + length + 3) = *(src + length); + } + for (n = length; n > 0; n -= 4, src += 4) { + *dest++ = *(src + 3); + *dest++ = *(src + 2); + *dest++ = *(src + 1); + *dest++ = *src; + } + } +} + +static void +SwapWords (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length + 1) = *(src + length + 3); + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length) = *(src + length + 2); + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 3) = *(src + length + 1); + if (half_order == LSBFirst) + *(dest + length + 2) = *(src + length); + } + for (n = length; n > 0; n -= 4, src += 2) { + *dest++ = *(src + 2); + *dest++ = *(src + 3); + *dest++ = *src++; + *dest++ = *src++; + } + } +} + +static void +SwapNibbles (src, dest, srclen, srcinc, destinc, height) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; +{ + register long h, n; + register const unsigned char *rev = _reverse_nibs; + + srcinc -= srclen; + destinc -= srclen; + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) + *dest++ = rev[*src++]; +} + +static void +ShiftNibblesLeft (src, dest, srclen, srcinc, destinc, height, nibble_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int nibble_order; +{ + register long h, n; + register unsigned char c1, c2; + + srcinc -= srclen; + destinc -= srclen; + if (nibble_order == MSBFirst) { + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) { + c1 = *src++; + c2 = *src; + *dest++ = ((c1 & 0x0f) << 4) | ((c2 & (unsigned)0xf0) >> 4); + } + } else { + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) { + c1 = *src++; + c2 = *src; + *dest++ = ((c2 & 0x0f) << 4) | ((c1 & (unsigned)0xf0) >> 4); + } + } +} + +/*ARGSUSED*/ +static void +SwapBits (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= srclen; + destinc -= srclen; + for (h = height; --h >= 0; src += srcinc, dest += destinc) + for (n = srclen; --n >= 0; ) + *dest++ = rev[*src++]; +} + +static void +SwapBitsAndTwoBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; +{ + long length = ROUNDUP(srclen, 2); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 2; + if (half_order == MSBFirst) + *(dest + length) = rev[*(src + length + 1)]; + else + *(dest + length + 1) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 2, src += 2) { + *dest++ = rev[*(src + 1)]; + *dest++ = rev[*src]; + } + } +} + +static void +SwapBitsAndFourBytes (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length) = rev[*(src + length + 3)]; + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length + 1) = rev[*(src + length + 2)]; + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 2) = rev[*(src + length + 1)]; + if (half_order == LSBFirst) + *(dest + length + 3) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 4, src += 4) { + *dest++ = rev[*(src + 3)]; + *dest++ = rev[*(src + 2)]; + *dest++ = rev[*(src + 1)]; + *dest++ = rev[*src]; + } + } +} + +static void +SwapBitsAndWords (src, dest, srclen, srcinc, destinc, height, half_order) + register unsigned char *src, *dest; + long srclen, srcinc, destinc; + unsigned int height; + int half_order; +{ + long length = ROUNDUP(srclen, 4); + register long h, n; + register const unsigned char *rev = _reverse_byte; + + srcinc -= length; + destinc -= length; + for (h = height; --h >= 0; src += srcinc, dest += destinc) { + if ((h == 0) && (srclen != length)) { + length -= 4; + if (half_order == MSBFirst) + *(dest + length + 1) = rev[*(src + length + 3)]; + if (((half_order == LSBFirst) && ((srclen - length) == 3)) || + ((half_order == MSBFirst) && (srclen & 2))) + *(dest + length) = rev[*(src + length + 2)]; + if (((half_order == MSBFirst) && ((srclen - length) == 3)) || + ((half_order == LSBFirst) && (srclen & 2))) + *(dest + length + 3) = rev[*(src + length + 1)]; + if (half_order == LSBFirst) + *(dest + length + 2) = rev[*(src + length)]; + } + for (n = length; n > 0; n -= 4, src += 2) { + *dest++ = rev[*(src + 2)]; + *dest++ = rev[*(src + 3)]; + *dest++ = rev[*src++]; + *dest++ = rev[*src++]; + } + } +} + +/* + +The following table gives the bit ordering within bytes (when accessed +sequentially) for a scanline containing 32 bits, with bits numbered 0 to +31, where bit 0 should be leftmost on the display. For a given byte +labelled A-B, A is for the most significant bit of the byte, and B is +for the least significant bit. + +legend: + 1 scanline-unit = 8 + 2 scanline-unit = 16 + 4 scanline-unit = 32 + M byte-order = MostSignificant + L byte-order = LeastSignificant + m bit-order = MostSignificant + l bit-order = LeastSignificant + + +format ordering + +1Mm 00-07 08-15 16-23 24-31 +2Mm 00-07 08-15 16-23 24-31 +4Mm 00-07 08-15 16-23 24-31 +1Ml 07-00 15-08 23-16 31-24 +2Ml 15-08 07-00 31-24 23-16 +4Ml 31-24 23-16 15-08 07-00 +1Lm 00-07 08-15 16-23 24-31 +2Lm 08-15 00-07 24-31 16-23 +4Lm 24-31 16-23 08-15 00-07 +1Ll 07-00 15-08 23-16 31-24 +2Ll 07-00 15-08 23-16 31-24 +4Ll 07-00 15-08 23-16 31-24 + + +The following table gives the required conversion between any two +formats. It is based strictly on the table above. If you believe one, +you should believe the other. + +legend: + n no changes + s reverse 8-bit units within 16-bit units + l reverse 8-bit units within 32-bit units + w reverse 16-bit units within 32-bit units + R reverse bits within 8-bit units + S s+R + L l+R + W w+R + +*/ + +static void (* const (SwapFunction[12][12]))() = { +#define n NoSwap, +#define s SwapTwoBytes, +#define l SwapFourBytes, +#define w SwapWords, +#define R SwapBits, +#define S SwapBitsAndTwoBytes, +#define L SwapBitsAndFourBytes, +#define W SwapBitsAndWords, + +/* 1Mm 2Mm 4Mm 1Ml 2Ml 4Ml 1Lm 2Lm 4Lm 1Ll 2Ll 4Ll */ +/* 1Mm */ { n n n R S L n s l R R R }, +/* 2Mm */ { n n n R S L n s l R R R }, +/* 4Mm */ { n n n R S L n s l R R R }, +/* 1Ml */ { R R R n s l R S L n n n }, +/* 2Ml */ { S S S s n w S R W s s s }, +/* 4Ml */ { L L L l w n L W R l l l }, +/* 1Lm */ { n n n R S L n s l R R R }, +/* 2Lm */ { s s s S R W s n w S S S }, +/* 4Lm */ { l l l L W R l w n L L L }, +/* 1Ll */ { R R R n s l R S L n n n }, +/* 2Ll */ { R R R n s l R S L n n n }, +/* 4Ll */ { R R R n s l R S L n n n } + +#undef n +#undef s +#undef l +#undef w +#undef R +#undef S +#undef L +#undef W + +}; + +/* Of course, the table above is a lie. We also need to factor in the + * order of the source data to cope with swapping half of a unit at the + * end of a scanline, since we are trying to avoid de-ref'ing off the + * end of the source. + * + * Defines whether the first half of a unit has the first half of the data + */ +static int const HalfOrder[12] = { + LSBFirst, /* 1Mm */ + LSBFirst, /* 2Mm */ + LSBFirst, /* 4Mm */ + LSBFirst, /* 1Ml */ + MSBFirst, /* 2Ml */ + MSBFirst, /* 4Ml */ + LSBFirst, /* 1Lm */ + MSBFirst, /* 2Lm */ + MSBFirst, /* 4Lm */ + LSBFirst, /* 1Ll */ + LSBFirst, /* 2Ll */ + LSBFirst /* 4Ll */ + }; + +/* Finally, for SwapWords cases, the half order depends not just on the source + * but also on the destination scanline unit. Use of this table changes some + * MSBFirsts to LSBFirsts that are "do not care" (because the function will be + * NoSwap or SwapBits) in addition to changing the desired ones. + */ + +static int const HalfOrderWord[12] = { + MSBFirst, /* 1Mm */ + MSBFirst, /* 2Mm */ + MSBFirst, /* 4Mm */ + MSBFirst, /* 1Ml */ + MSBFirst, /* 2Ml */ + LSBFirst, /* 4Ml */ + MSBFirst, /* 1Lm */ + MSBFirst, /* 2Lm */ + LSBFirst, /* 4Lm */ + MSBFirst, /* 1Ll */ + MSBFirst, /* 2Ll */ + MSBFirst /* 4Ll */ + }; + +/* + * This macro creates a value from 0 to 11 suitable for indexing + * into the table above. + */ +#define ComposeIndex(bitmap_unit, bitmap_bit_order, byte_order) \ + (((bitmap_unit == 32) ? 2 : ((bitmap_unit == 16) ? 1 : 0)) \ + + (((bitmap_bit_order == MSBFirst) ? 0 : 3) \ + + ((byte_order == MSBFirst) ? 0 : 6))) + +#if 0 /* not needed, ever */ +/* Cancel a GetReq operation, before doing _XSend or Data */ + +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define UnGetReq(name)\ + dpy->bufptr -= SIZEOF(x##name##Req);\ + dpy->request-- +#else +#define UnGetReq(name)\ + dpy->bufptr -= SIZEOF(x/**/name/**/Req);\ + dpy->request-- +#endif +#endif + +struct SendImageParams +{ + Display *dpy; + int avail_request_size; + int dest_bits_per_pixel; + int dest_scanline_pad; + int req_xoffset; + int req_yoffset; + DRAWABLE drawable; + GCONTEXT gc; + int x; + int y; + unsigned int width; + unsigned int height; + int format; + int leftPad; + XImage *image; + long total_xoffset; + void (*swapfunc)(); + int half_order; +}; + +static void SendImage(dpy, is_xyimage, p, depth) + register Display *const dpy; + const int is_xyimage; + struct SendImageParams *const p; + const int depth; +{ + long bytes_per_src, bytes_per_dest, length; + long bytes_per_line = p->image->bytes_per_line; + long bytes_per_src_plane = bytes_per_line * p->image->height; + long bytes_per_dest_plane; + unsigned char *src, *dest, *buf; + unsigned char *extra = 0; + register int j; + + p->total_xoffset = (unsigned)(p->total_xoffset - p->leftPad) >> 3; + bytes_per_dest = (unsigned long)ROUNDUP((long)p->width * p->dest_bits_per_pixel + p->leftPad, p->dest_scanline_pad) >> 3; + bytes_per_dest_plane = bytes_per_dest * p->height; + length = bytes_per_dest_plane * depth; + + src = (unsigned char *)p->image->data + (p->req_yoffset * bytes_per_line) + p->total_xoffset; + bytes_per_src = (p->width * p->image->bits_per_pixel + p->leftPad + 7) >> 3; + + if (!is_xyimage && (p->image->bits_per_pixel == 4) && ((unsigned int) p->req_xoffset & 0x01)) { + if (! (extra = (unsigned char *) + Xmalloc((unsigned) (p->height * bytes_per_line)))) { + goto done; + } + + ShiftNibblesLeft(src, extra, bytes_per_src, + bytes_per_line, + bytes_per_line, p->height, + p->image->byte_order); + src = extra; + } + + /* when total_xoffset > 0, we have to worry about stepping off the + * end of p->image->data. + */ + if ((p->swapfunc == NoSwap) && + (bytes_per_line == bytes_per_dest) && + (((p->total_xoffset == 0) && + ((depth == 1) || (p->image->height == p->height))) || + ((depth == 1) && + ((p->req_yoffset + p->height) < (unsigned)p->image->height)))) { + XCBPutImage(XCBConnectionOfDisplay(dpy), p->format, p->drawable, + p->gc, p->width, p->height, p->x, p->y, p->leftPad, depth, + length, src); + goto done; + } + + length = ROUNDUP(length, 4); + if ((buf = _XAllocScratch(dpy, (unsigned long) (length))) == NULL) { + goto done; + } + + p->total_xoffset &= (p->image->bitmap_unit - 1) >> 3; + + if (is_xyimage && (p->total_xoffset > 0) && + (p->image->byte_order != p->image->bitmap_bit_order)) { + char *temp; + long bytes_per_temp_plane, temp_length; + + bytes_per_line = bytes_per_src + p->total_xoffset; + src -= p->total_xoffset; + bytes_per_temp_plane = bytes_per_line * p->height; + temp_length = ROUNDUP(bytes_per_temp_plane * depth, 4); + if ((extra = temp = Xmalloc((unsigned) temp_length)) == NULL) { + goto done; + } + + p->swapfunc = SwapFunction[ComposeIndex(p->image->bitmap_unit, + p->image->bitmap_bit_order, + p->image->byte_order)] + [ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)]; + for (dest = temp, j = depth; + --j >= 0; + src += bytes_per_src_plane, dest += bytes_per_temp_plane) + (*p->swapfunc)((unsigned char *)src, (unsigned char *)dest, + bytes_per_line, (long)p->image->bytes_per_line, + bytes_per_line, p->height, p->half_order); + p->swapfunc = SwapFunction[ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)] + [ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + p->half_order = HalfOrder[ComposeIndex(p->image->bitmap_unit, + dpy->byte_order, + dpy->byte_order)]; + src = temp + p->total_xoffset; + bytes_per_src_plane = bytes_per_temp_plane; + } + + for (dest = buf, j = depth; + --j >= 0; + src += bytes_per_src_plane, dest += bytes_per_dest_plane) + (*p->swapfunc)((unsigned char *)src, (unsigned char *)dest, + bytes_per_src, bytes_per_line, + bytes_per_dest, p->height, p->half_order); + + XCBPutImage(XCBConnectionOfDisplay(dpy), p->format, p->drawable, + p->gc, p->width, p->height, p->x, p->y, p->leftPad, depth, + length, buf); + +done: + if (extra) + Xfree(extra); +} + +static void SendXYImage(struct SendImageParams *const p) +{ + /* The protocol requires left-pad of zero on all ZPixmap, even + * though the 1-bit case is identical to bitmap format. This is a + * bug in the protocol, caused because 1-bit ZPixmap was added late + * in the game. Hairy shifting code compensation isn't worth it, + * just use XYPixmap format instead. + */ + if ((p->leftPad != 0) && (p->format == ZPixmap)) + p->format = XYPixmap; + + SendImage(p->dpy, 1, p, p->image->depth); +} + +static void SendZImage(struct SendImageParams *const p) +{ + SendImage(p->dpy, 0, p, 1); +} + +static void +PutSubImage(p, req_xoffset, req_yoffset, x, y, req_width, req_height) + struct SendImageParams *const p; + int req_xoffset, req_yoffset; + int x, y; + unsigned int req_width, req_height; +{ + int BytesPerRow; + + if ((req_width == 0) || (req_height == 0)) + return; + + if ((p->image->bits_per_pixel == 1) || (p->image->format != ZPixmap)) { + p->total_xoffset = p->image->xoffset + req_xoffset; + p->leftPad = p->total_xoffset & (p->dpy->bitmap_unit - 1); + BytesPerRow = (ROUNDUP((long)req_width + p->leftPad, + p->dpy->bitmap_pad) >> 3) * p->image->depth; + } else { + p->total_xoffset = req_xoffset * p->image->bits_per_pixel; + p->leftPad = 0; + BytesPerRow = ROUNDUP((long)req_width * p->dest_bits_per_pixel, + p->dest_scanline_pad) >> 3; + } + + if ((BytesPerRow * req_height) <= p->avail_request_size) { + p->req_xoffset = req_xoffset; + p->req_yoffset = req_yoffset; + p->x = x; + p->y = y; + p->width = req_width; + p->height = req_height; + p->format = p->image->format; + if ((p->image->bits_per_pixel == 1) || (p->image->format != ZPixmap)) + SendXYImage(p); + else + SendZImage(p); + } else if (req_height > 1) { + int SubImageHeight = p->avail_request_size / BytesPerRow; + + if (SubImageHeight == 0) + SubImageHeight = 1; + + PutSubImage(p, req_xoffset, req_yoffset, x, y, + req_width, (unsigned int) SubImageHeight); + + PutSubImage(p, req_xoffset, + req_yoffset + SubImageHeight, x, y + SubImageHeight, + req_width, req_height - SubImageHeight); + } else { + int SubImageWidth = (((p->avail_request_size << 3) / p->dest_scanline_pad) + * p->dest_scanline_pad) - p->leftPad; + + PutSubImage(p, req_xoffset, req_yoffset, x, y, + (unsigned int) SubImageWidth, 1); + + PutSubImage(p, req_xoffset + SubImageWidth, + req_yoffset, x + SubImageWidth, y, + req_width - SubImageWidth, 1); + } +} + +extern void _XInitImageFuncPtrs(); + +int XPutImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, req_width, + req_height) + register Display *dpy; + Drawable d; + GC gc; + register XImage *image; + int x, y; + unsigned int req_width, req_height; + int req_xoffset, req_yoffset; +{ + long width = req_width; + long height = req_height; + char *tmp = 0; + XImage img; + struct SendImageParams p; + + if (req_xoffset < 0) { + width += req_xoffset; + req_xoffset = 0; + } + if (req_yoffset < 0) { + height += req_yoffset; + req_yoffset = 0; + } + if ((req_xoffset + width) > image->width) + width = image->width - req_xoffset; + if ((req_yoffset + height) > image->height) + height = image->height - req_yoffset; + if ((width <= 0) || (height <= 0)) + return 0; + + p.dpy = dpy; + p.drawable = XCLDRAWABLE(d); + p.gc = XCLGCONTEXT(gc->gid); + p.image = image; + p.avail_request_size = ((65536 < dpy->max_request_size) ? + (65536 << 2) : (dpy->max_request_size << 2)) + - SIZEOF(xPutImageReq); + + + if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) { + p.dest_bits_per_pixel = 1; + p.dest_scanline_pad = dpy->bitmap_pad; + + p.swapfunc = SwapFunction[ComposeIndex(image->bitmap_unit, + image->bitmap_bit_order, + image->byte_order)] + [ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + p.half_order = HalfOrder[ComposeIndex(image->bitmap_unit, + image->bitmap_bit_order, + image->byte_order)]; + if (p.half_order == MSBFirst) + p.half_order = HalfOrderWord[ComposeIndex(dpy->bitmap_unit, + dpy->bitmap_bit_order, + dpy->byte_order)]; + } else { + register int n; + register ScreenFormat *format; + + if (image->byte_order == dpy->byte_order || image->bits_per_pixel == 8) + p.swapfunc = NoSwap; + else + switch (p.image->bits_per_pixel) + { + case 32: + p.swapfunc = SwapFourBytes; + break; + case 24: + p.swapfunc = SwapThreeBytes; + break; + case 16: + p.swapfunc = SwapTwoBytes; + break; + default: + p.swapfunc = SwapNibbles; + } + + p.dest_bits_per_pixel = image->bits_per_pixel; + p.dest_scanline_pad = image->bitmap_pad; + for (n = dpy->nformats, format = dpy->pixmap_format; --n >= 0; format++) + if (format->depth == image->depth) { + p.dest_bits_per_pixel = format->bits_per_pixel; + p.dest_scanline_pad = format->scanline_pad; + } + if (p.dest_bits_per_pixel != image->bits_per_pixel) { + register long i, j; + /* XXX slow, but works */ + img.width = width; + img.height = height; + img.xoffset = 0; + img.format = ZPixmap; + img.byte_order = dpy->byte_order; + p.swapfunc = NoSwap; /* inv: img.byte_order == dpy->byte_order */ + img.bitmap_unit = dpy->bitmap_unit; + img.bitmap_bit_order = dpy->bitmap_bit_order; + img.bitmap_pad = p.dest_scanline_pad; + img.depth = image->depth; + img.bits_per_pixel = p.dest_bits_per_pixel; + img.bytes_per_line = ROUNDUP((p.dest_bits_per_pixel * width), + p.dest_scanline_pad) >> 3; + tmp = Xmalloc((unsigned) (img.bytes_per_line * height)); + if (tmp == NULL) + return 0; + img.data = tmp; + _XInitImageFuncPtrs(&img); + for (j = height; --j >= 0; ) + for (i = width; --i >= 0; ) + XPutPixel(&img, i, j, XGetPixel(image, req_xoffset + i, + req_yoffset + j)); + p.image = &img; + req_xoffset = req_yoffset = 0; + } + } + + LockDisplay(dpy); + FlushGC(dpy, gc); + + PutSubImage(&p, req_xoffset, req_yoffset, x, y, + (unsigned int) width, (unsigned int) height); + + UnlockDisplay(dpy); + Xfree(tmp); + return 0; +} diff --git a/xcl/src/QuExt.c b/xcl/src/QuExt.c new file mode 100644 index 0000000..f990cca --- /dev/null +++ b/xcl/src/QuExt.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +/* XXX: for once, XCL caches when Xlib doesn't. Hah! */ + +Bool XQueryExtension(Display *dpy, const char *name, int *major_opcode, + int *first_event, int *first_error) +{ +#if 1 /* FIXME: disabling extensions until XCL progresses further */ + return 0; /* extension not present */ +#else + XCBConnection *c = XCBConnectionOfDisplay(dpy); + const XCBQueryExtensionRep *r = XCBQueryExtensionCached(c, name, 0); + /* error check: Xlib doesn't check this */ + if(!r) + return 0; /* extension not present */ + + *major_opcode = r->major_opcode; + *first_event = r->first_event; + *first_error = r->first_error; + /* must not free r: it's aliased from the cache. */ + return r->present; +#endif +} diff --git a/xcl/src/QuTree.c b/xcl/src/QuTree.c new file mode 100644 index 0000000..2af48f6 --- /dev/null +++ b/xcl/src/QuTree.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +Status XQueryTree(Display *dpy, Window w, Window *root, Window *parent, Window **children, unsigned int *nchildren) +{ + XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBQueryTreeRep *r; + + r = XCBQueryTreeReply(c, XCBQueryTree(c, XCLWINDOW(w)), 0); + if(!r) + return 0; + + *children = 0; + *root = r->root.xid; + *parent = r->parent.xid; + *nchildren = r->children_len; + if(*nchildren <= 0) + return 1; + + /* reuse the memory chunk the reply came in. */ + memmove(r, XCBQueryTreechildren(r), *nchildren * sizeof(WINDOW)); + *children = (Window *) r; + return 1; +} diff --git a/xcl/src/SetCRects.c b/xcl/src/SetCRects.c new file mode 100644 index 0000000..29132a1 --- /dev/null +++ b/xcl/src/SetCRects.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. + * Portions Copyright 1986, 1998 The Open Group + * + * See the file COPYING for licensing information. */ +#include "xclint.h" + +/* can only call when display is locked. */ +void _XSetClipRectangles(Display *dpy, GC gc, int clip_x_origin, int clip_y_origin, XRectangle *rectangles, int n, int ordering) +{ + unsigned long dirty; + register _XExtension *ext; + XCBSetClipRectangles(XCBConnectionOfDisplay(dpy), ordering, XCLGCONTEXT(gc->gid), clip_x_origin, clip_y_origin, n, (RECTANGLE *) rectangles); + + gc->values.clip_x_origin = clip_x_origin; + gc->values.clip_y_origin = clip_y_origin; + gc->rects = 1; + dirty = gc->dirty & ~(GCClipMask | GCClipXOrigin | GCClipYOrigin); + gc->dirty = GCClipMask | GCClipXOrigin | GCClipYOrigin; + /* call out to any extensions interested */ + for (ext = dpy->ext_procs; ext; ext = ext->next) + if (ext->flush_GC) (*ext->flush_GC)(dpy, gc, &ext->codes); + gc->dirty = dirty; +} + +int XSetClipRectangles(Display *dpy, GC gc, int clip_x_origin, int clip_y_origin, XRectangle *rectangles, int n, int ordering) +{ + LockDisplay(dpy); + _XSetClipRectangles(dpy, gc, clip_x_origin, clip_y_origin, rectangles, n, ordering); + UnlockDisplay(dpy); + return 1; +} diff --git a/xcl/src/Sync.c b/xcl/src/Sync.c index f87a40e..ec07463 100644 --- a/xcl/src/Sync.c +++ b/xcl/src/Sync.c @@ -4,27 +4,14 @@ * * See the file COPYING for licensing information. */ #include "xclint.h" +#include <xcb_event.h> /* Synchronize with errors and events, optionally discarding pending events */ - -int XSync(register Display *dpy, Bool discard) +int XSync(Display *dpy, Bool discard) { - LockDisplay(dpy); - XCBSync(XCBConnectionOfDisplay(dpy), 0); - - if (discard && dpy->head) - { - _XQEvent *qelt; - - for (qelt = dpy->head; qelt; qelt = qelt->next) - qelt->qserial_num = 0; - - ((_XQEvent *)dpy->tail)->next = dpy->qfree; - dpy->qfree = (_XQEvent *)dpy->head; - dpy->head = dpy->tail = NULL; - dpy->qlen = 0; - } - UnlockDisplay(dpy); + register XCBConnection *c = XCBConnectionOfDisplay(dpy); + XCBSync(c, 0); + if(discard) + XCBEventQueueClear(c); return 1; } - |