XlibInt.c revision 295fb823
11.1.1.2Sjmcneill/*
21.1Sjmcneill
31.1SjmcneillCopyright 1985, 1986, 1987, 1998  The Open Group
41.1Sjmcneill
51.1.1.2SjmcneillPermission to use, copy, modify, distribute, and sell this software and its
61.1Sjmcneilldocumentation for any purpose is hereby granted without fee, provided that
71.1Sjmcneillthe above copyright notice appear in all copies and that both that
81.1Sjmcneillcopyright notice and this permission notice appear in supporting
91.1Sjmcneilldocumentation.
101.1Sjmcneill
111.1SjmcneillThe above copyright notice and this permission notice shall be included
121.1Sjmcneillin all copies or substantial portions of the Software.
131.1Sjmcneill
141.1SjmcneillTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151.1SjmcneillOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161.1SjmcneillMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
171.1SjmcneillIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
181.1SjmcneillOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191.1SjmcneillARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201.1SjmcneillOTHER DEALINGS IN THE SOFTWARE.
211.1Sjmcneill
221.1SjmcneillExcept as contained in this notice, the name of The Open Group shall
231.1Sjmcneillnot be used in advertising or otherwise to promote the sale, use or
241.1Sjmcneillother dealings in this Software without prior written authorization
251.1Sjmcneillfrom The Open Group.
261.1Sjmcneill
271.1Sjmcneill*/
281.1Sjmcneill
291.1Sjmcneill/*
301.1Sjmcneill *	XlibInt.c - Internal support routines for the C subroutine
311.1Sjmcneill *	interface library (Xlib) to the X Window System Protocol V11.0.
321.1Sjmcneill */
331.1Sjmcneill
341.1Sjmcneill#ifdef WIN32
351.1Sjmcneill#define _XLIBINT_
361.1Sjmcneill#endif
371.1Sjmcneill#ifdef HAVE_CONFIG_H
381.1Sjmcneill#include <config.h>
391.1Sjmcneill#endif
401.1Sjmcneill#include "Xlibint.h"
411.1Sjmcneill#include "Xprivate.h"
421.1Sjmcneill#include <X11/Xpoll.h>
431.1Sjmcneill#include <assert.h>
441.1Sjmcneill#include <stdio.h>
451.1Sjmcneill#ifdef WIN32
461.1Sjmcneill#include <direct.h>
471.1Sjmcneill#endif
481.1Sjmcneill
491.1Sjmcneill#ifdef XTHREADS
501.1Sjmcneill#include "locking.h"
511.1.1.2Sjmcneill
521.1Sjmcneill/* these pointers get initialized by XInitThreads */
531.1SjmcneillLockInfoPtr _Xglobal_lock = NULL;
541.1Sjmcneillvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
551.1Sjmcneill/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
561.1Sjmcneillvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
571.1Sjmcneillvoid (*_XLockMutex_fn)(
581.1Sjmcneill    LockInfoPtr /* lock */
591.1Sjmcneill#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
601.1Sjmcneill    , char * /* file */
611.1Sjmcneill    , int /* line */
621.1Sjmcneill#endif
631.1Sjmcneill    ) = NULL;
641.1Sjmcneillvoid (*_XUnlockMutex_fn)(
651.1Sjmcneill    LockInfoPtr /* lock */
661.1Sjmcneill#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
671.1Sjmcneill    , char * /* file */
681.1Sjmcneill    , int /* line */
691.1Sjmcneill#endif
701.1Sjmcneill    ) = NULL;
711.1Sjmcneillxthread_t (*_Xthread_self_fn)(void) = NULL;
721.1Sjmcneill
731.1Sjmcneill#define XThread_Self()	((*_Xthread_self_fn)())
741.1Sjmcneill
751.1Sjmcneill#endif /* XTHREADS */
761.1Sjmcneill
771.1Sjmcneill/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
781.1Sjmcneill * systems are broken and return EWOULDBLOCK when they should return EAGAIN
791.1Sjmcneill */
801.1Sjmcneill#ifdef WIN32
811.1Sjmcneill#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
821.1Sjmcneill#else
831.1Sjmcneill#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
841.1Sjmcneill#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
851.1Sjmcneill#else
861.1Sjmcneill#if defined(EAGAIN) && defined(EWOULDBLOCK)
871.1Sjmcneill#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
881.1Sjmcneill#else
891.1Sjmcneill#ifdef EAGAIN
901.1Sjmcneill#define ETEST() (errno == EAGAIN)
911.1Sjmcneill#else
921.1Sjmcneill#define ETEST() (errno == EWOULDBLOCK)
931.1Sjmcneill#endif /* EAGAIN */
941.1Sjmcneill#endif /* EAGAIN && EWOULDBLOCK */
951.1Sjmcneill#endif /* __CYGWIN__ */
961.1Sjmcneill#endif /* WIN32 */
971.1Sjmcneill
981.1Sjmcneill#ifdef WIN32
991.1Sjmcneill#define ECHECK(err) (WSAGetLastError() == err)
1001.1Sjmcneill#define ESET(val) WSASetLastError(val)
1011.1Sjmcneill#else
1021.1Sjmcneill#ifdef __UNIXOS2__
1031.1Sjmcneill#define ECHECK(err) (errno == err)
1041.1Sjmcneill#define ESET(val)
1051.1Sjmcneill#else
1061.1Sjmcneill#define ECHECK(err) (errno == err)
1071.1Sjmcneill#define ESET(val) errno = val
1081.1Sjmcneill#endif
1091.1Sjmcneill#endif
1101.1Sjmcneill
1111.1Sjmcneill#if defined(LOCALCONN) || defined(LACHMAN)
1121.1Sjmcneill#ifdef EMSGSIZE
1131.1Sjmcneill#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
1141.1Sjmcneill#else
1151.1Sjmcneill#define ESZTEST() ECHECK(ERANGE)
1161.1Sjmcneill#endif
1171.1Sjmcneill#else
1181.1Sjmcneill#ifdef EMSGSIZE
1191.1Sjmcneill#define ESZTEST() ECHECK(EMSGSIZE)
1201.1Sjmcneill#endif
1211.1Sjmcneill#endif
1221.1Sjmcneill
1231.1Sjmcneill#ifdef __UNIXOS2__
1241.1Sjmcneill#include <limits.h>
1251.1Sjmcneill#define MAX_PATH _POSIX_PATH_MAX
1261.1Sjmcneill#endif
1271.1Sjmcneill
1281.1Sjmcneill/*
1291.1Sjmcneill * The following routines are internal routines used by Xlib for protocol
1301.1Sjmcneill * packet transmission and reception.
1311.1Sjmcneill *
1321.1Sjmcneill * _XIOError(Display *) will be called if any sort of system call error occurs.
1331.1Sjmcneill * This is assumed to be a fatal condition, i.e., XIOError should not return.
1341.1Sjmcneill *
1351.1Sjmcneill * _XError(Display *, xError *) will be called whenever an X_Error event is
1361.1Sjmcneill * received.  This is not assumed to be a fatal condition, i.e., it is
1371.1Sjmcneill * acceptable for this procedure to return.  However, XError should NOT
1381.1Sjmcneill * perform any operations (directly or indirectly) on the DISPLAY.
1391.1Sjmcneill *
1401.1Sjmcneill * Routines declared with a return type of 'Status' return 0 on failure,
1411.1Sjmcneill * and non 0 on success.  Routines with no declared return type don't
1421.1Sjmcneill * return anything.  Whenever possible routines that create objects return
1431.1Sjmcneill * the object they have created.
1441.1Sjmcneill */
1451.1Sjmcneill
1461.1Sjmcneill#define POLLFD_CACHE_SIZE 5
1471.1Sjmcneill
1481.1Sjmcneill/* initialize the struct array passed to poll() below */
1491.1SjmcneillBool _XPollfdCacheInit(
1501.1Sjmcneill    Display *dpy)
1511.1Sjmcneill{
1521.1Sjmcneill#ifdef USE_POLL
1531.1Sjmcneill    struct pollfd *pfp;
1541.1Sjmcneill
1551.1Sjmcneill    pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1561.1Sjmcneill    if (!pfp)
1571.1Sjmcneill	return False;
1581.1Sjmcneill    pfp[0].fd = dpy->fd;
1591.1Sjmcneill    pfp[0].events = POLLIN;
1601.1.1.2Sjmcneill
1611.1Sjmcneill    dpy->filedes = (XPointer)pfp;
1621.1Sjmcneill#endif
1631.1Sjmcneill    return True;
1641.1Sjmcneill}
1651.1Sjmcneill
1661.1Sjmcneillvoid _XPollfdCacheAdd(
1671.1Sjmcneill    Display *dpy,
1681.1Sjmcneill    int fd)
1691.1Sjmcneill{
1701.1Sjmcneill#ifdef USE_POLL
1711.1.1.2Sjmcneill    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1721.1Sjmcneill
1731.1Sjmcneill    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1741.1Sjmcneill	pfp[dpy->im_fd_length].fd = fd;
1751.1Sjmcneill	pfp[dpy->im_fd_length].events = POLLIN;
1761.1Sjmcneill    }
1771.1Sjmcneill#endif
1781.1Sjmcneill}
1791.1Sjmcneill
1801.1Sjmcneill/* ARGSUSED */
1811.1.1.2Sjmcneillvoid _XPollfdCacheDel(
1821.1Sjmcneill    Display *dpy,
1831.1Sjmcneill    int fd)			/* not used */
1841.1Sjmcneill{
1851.1Sjmcneill#ifdef USE_POLL
1861.1Sjmcneill    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1871.1Sjmcneill    struct _XConnectionInfo *conni;
1881.1Sjmcneill
1891.1Sjmcneill    /* just recalculate whole list */
1901.1Sjmcneill    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1911.1Sjmcneill	int loc = 1;
1921.1.1.2Sjmcneill	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1931.1Sjmcneill	    pfp[loc].fd = conni->fd;
1941.1Sjmcneill	    pfp[loc].events = POLLIN;
1951.1Sjmcneill	    loc++;
1961.1Sjmcneill	}
1971.1Sjmcneill    }
1981.1Sjmcneill#endif
1991.1Sjmcneill}
2001.1Sjmcneill
2011.1Sjmcneillstatic int sync_hazard(Display *dpy)
2021.1.1.2Sjmcneill{
2031.1Sjmcneill    unsigned long span = dpy->request - dpy->last_request_read;
2041.1Sjmcneill    unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
2051.1Sjmcneill    return span >= 65535 - hazard - 10;
2061.1Sjmcneill}
2071.1Sjmcneill
2081.1Sjmcneillstatic
2091.1Sjmcneillvoid sync_while_locked(Display *dpy)
2101.1Sjmcneill{
2111.1Sjmcneill#ifdef XTHREADS
2121.1.1.2Sjmcneill    if (dpy->lock)
2131.1Sjmcneill        (*dpy->lock->user_lock_display)(dpy);
2141.1Sjmcneill#endif
2151.1Sjmcneill    UnlockDisplay(dpy);
2161.1Sjmcneill    SyncHandle();
2171.1Sjmcneill    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
2181.1Sjmcneill#ifdef XTHREADS
2191.1Sjmcneill    if (dpy->lock)
2201.1Sjmcneill        (*dpy->lock->user_unlock_display)(dpy);
2211.1Sjmcneill#endif
2221.1.1.2Sjmcneill}
2231.1Sjmcneill
2241.1Sjmcneillvoid _XSeqSyncFunction(
2251.1Sjmcneill    register Display *dpy)
2261.1Sjmcneill{
2271.1Sjmcneill    xGetInputFocusReply rep;
2281.1Sjmcneill    register xReq *req;
2291.1Sjmcneill
2301.1Sjmcneill    if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
2311.1Sjmcneill	GetEmptyReq(GetInputFocus, req);
2321.1.1.2Sjmcneill	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
2331.1Sjmcneill	sync_while_locked(dpy);
2341.1Sjmcneill    } else if (sync_hazard(dpy))
2351.1Sjmcneill	_XSetPrivSyncFunction(dpy);
2361.1Sjmcneill}
2371.1Sjmcneill
2381.1Sjmcneill/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
2391.1Sjmcneillstatic int
2401.1Sjmcneill_XPrivSyncFunction (Display *dpy)
2411.1Sjmcneill{
2421.1.1.2Sjmcneill#ifdef XTHREADS
2431.1Sjmcneill    assert(!dpy->lock_fns);
2441.1Sjmcneill#endif
2451.1Sjmcneill    assert(dpy->synchandler == _XPrivSyncFunction);
2461.1Sjmcneill    assert((dpy->flags & XlibDisplayPrivSync) != 0);
2471.1Sjmcneill    dpy->synchandler = dpy->savedsynchandler;
2481.1Sjmcneill    dpy->savedsynchandler = NULL;
2491.1Sjmcneill    dpy->flags &= ~XlibDisplayPrivSync;
2501.1Sjmcneill    if(dpy->synchandler)
2511.1Sjmcneill        dpy->synchandler(dpy);
2521.1.1.2Sjmcneill    _XIDHandler(dpy);
2531.1Sjmcneill    _XSeqSyncFunction(dpy);
2541.1Sjmcneill    return 0;
2551.1Sjmcneill}
2561.1Sjmcneill
2571.1Sjmcneillvoid _XSetPrivSyncFunction(Display *dpy)
2581.1Sjmcneill{
2591.1Sjmcneill#ifdef XTHREADS
2601.1Sjmcneill    if (dpy->lock_fns)
2611.1Sjmcneill        return;
2621.1.1.2Sjmcneill#endif
2631.1Sjmcneill    if (!(dpy->flags & XlibDisplayPrivSync)) {
2641.1Sjmcneill	dpy->savedsynchandler = dpy->synchandler;
2651.1Sjmcneill	dpy->synchandler = _XPrivSyncFunction;
2661.1Sjmcneill	dpy->flags |= XlibDisplayPrivSync;
2671.1Sjmcneill    }
2681.1Sjmcneill}
2691.1Sjmcneill
2701.1Sjmcneillvoid _XSetSeqSyncFunction(Display *dpy)
2711.1Sjmcneill{
2721.1.1.2Sjmcneill    if (sync_hazard(dpy))
2731.1Sjmcneill	_XSetPrivSyncFunction (dpy);
2741.1Sjmcneill}
2751.1Sjmcneill
2761.1Sjmcneill#ifdef LONG64
2771.1Sjmcneillvoid _XRead32(
2781.1Sjmcneill    Display *dpy,
2791.1Sjmcneill    register long *data,
2801.1Sjmcneill    long len)
2811.1Sjmcneill{
2821.1.1.2Sjmcneill    register int *buf;
2831.1Sjmcneill    register long i;
2841.1Sjmcneill
2851.1Sjmcneill    if (len) {
2861.1Sjmcneill	(void) _XRead(dpy, (char *)data, len);
2871.1Sjmcneill	i = len >> 2;
2881.1Sjmcneill	buf = (int *)data + i;
2891.1Sjmcneill	data += i;
2901.1Sjmcneill	while (--i >= 0)
2911.1Sjmcneill	    *--data = *--buf;
2921.1.1.2Sjmcneill    }
2931.1Sjmcneill}
2941.1Sjmcneill#endif /* LONG64 */
2951.1Sjmcneill
2961.1Sjmcneill#ifdef WORD64
2971.1Sjmcneill
2981.1Sjmcneill/*
2991.1Sjmcneill * XXX This is a *really* stupid way of doing this....
3001.1Sjmcneill * PACKBUFFERSIZE must be a multiple of 4.
3011.1Sjmcneill */
3021.1.1.2Sjmcneill
3031.1Sjmcneill#define PACKBUFFERSIZE 4096
3041.1Sjmcneill
3051.1Sjmcneill
3061.1Sjmcneill/*
3071.1Sjmcneill * _XRead32 - Read bytes from the socket unpacking each 32 bits
3081.1Sjmcneill *            into a long (64 bits on a CRAY computer).
3091.1Sjmcneill *
3101.1Sjmcneill */
3111.1Sjmcneillstatic void _doXRead32(
3121.1.1.2Sjmcneill        register Display *dpy,
3131.1Sjmcneill        register long *data
3141.1Sjmcneill        register long size,
3151.1Sjmcneill	register char *packbuffer)
3161.1Sjmcneill{
3171.1Sjmcneill long *lpack,*lp;
3181.1Sjmcneill long mask32 = 0x00000000ffffffff;
3191.1Sjmcneill long maskw, nwords, i, bits;
3201.1Sjmcneill
3211.1Sjmcneill        _XReadPad (dpy, packbuffer, size);
3221.1.1.2Sjmcneill
3231.1Sjmcneill        lp = data;
3241.1Sjmcneill        lpack = (long *) packbuffer;
3251.1Sjmcneill        nwords = size >> 2;
3261.1Sjmcneill        bits = 32;
3271.1Sjmcneill
3281.1Sjmcneill        for(i=0;i<nwords;i++){
3291.1Sjmcneill            maskw = mask32 << bits;
3301.1Sjmcneill           *lp++ = ( *lpack & maskw ) >> bits;
3311.1Sjmcneill            bits = bits ^32;
3321.1.1.2Sjmcneill            if(bits){
3331.1Sjmcneill               lpack++;
3341.1Sjmcneill            }
3351.1Sjmcneill        }
3361.1Sjmcneill}
3371.1Sjmcneill
3381.1Sjmcneillvoid _XRead32(
3391.1Sjmcneill    Display *dpy,
3401.1Sjmcneill    long *data,
3411.1Sjmcneill    long len)
3421.1.1.2Sjmcneill{
3431.1Sjmcneill    char packbuffer[PACKBUFFERSIZE];
3441.1Sjmcneill    unsigned nunits = PACKBUFFERSIZE >> 2;
3451.1Sjmcneill
3461.1Sjmcneill    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3471.1Sjmcneill	_doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
3481.1Sjmcneill    }
3491.1Sjmcneill    if (len) _doXRead32 (dpy, data, len, packbuffer);
3501.1Sjmcneill}
3511.1Sjmcneill
3521.1.1.2Sjmcneill
3531.1Sjmcneill
3541.1Sjmcneill/*
3551.1Sjmcneill * _XRead16 - Read bytes from the socket unpacking each 16 bits
3561.1Sjmcneill *            into a long (64 bits on a CRAY computer).
3571.1Sjmcneill *
3581.1Sjmcneill */
3591.1Sjmcneillstatic _doXRead16(
3601.1Sjmcneill        register Display *dpy,
3611.1Sjmcneill        register short *data,
3621.1.1.2Sjmcneill        register long size,
3631.1Sjmcneill	char *packbuffer)
3641.1Sjmcneill{
3651.1Sjmcneill	long *lpack,*lp;
3661.1Sjmcneill	long mask16 = 0x000000000000ffff;
3671.1Sjmcneill	long maskw, nwords, i, bits;
3681.1Sjmcneill
3691.1Sjmcneill        (void) _XRead(dpy,packbuffer,size);	/* don't do a padded read... */
3701.1Sjmcneill
3711.1Sjmcneill        lp = (long *) data;
3721.1.1.2Sjmcneill        lpack = (long *) packbuffer;
3731.1Sjmcneill        nwords = size >> 1;  /* number of 16 bit words to be unpacked */
3741.1Sjmcneill        bits = 48;
3751.1Sjmcneill        for(i=0;i<nwords;i++){
3761.1Sjmcneill            maskw = mask16 << bits;
3771.1Sjmcneill           *lp++ = ( *lpack & maskw ) >> bits;
3781.1Sjmcneill            bits -= 16;
3791.1Sjmcneill            if(bits < 0){
3801.1Sjmcneill               lpack++;
3811.1Sjmcneill               bits = 48;
3821.1.1.2Sjmcneill            }
3831.1Sjmcneill        }
3841.1Sjmcneill}
3851.1Sjmcneill
3861.1Sjmcneillvoid _XRead16(
3871.1Sjmcneill    Display *dpy,
3881.1Sjmcneill    short *data,
3891.1Sjmcneill    long len)
3901.1Sjmcneill{
3911.1Sjmcneill    char packbuffer[PACKBUFFERSIZE];
3921.1.1.2Sjmcneill    unsigned nunits = PACKBUFFERSIZE >> 1;
3931.1Sjmcneill
3941.1Sjmcneill    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3951.1Sjmcneill	_doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
3961.1Sjmcneill    }
3971.1Sjmcneill    if (len) _doXRead16 (dpy, data, len, packbuffer);
3981.1Sjmcneill}
3991.1Sjmcneill
4001.1Sjmcneillvoid _XRead16Pad(
4011.1Sjmcneill    Display *dpy,
4021.1.1.2Sjmcneill    short *data,
4031.1Sjmcneill    long size)
4041.1Sjmcneill{
4051.1Sjmcneill    int slop = (size & 3);
4061.1Sjmcneill    short slopbuf[3];
4071.1Sjmcneill
4081.1Sjmcneill    _XRead16 (dpy, data, size);
4091.1Sjmcneill    if (slop > 0) {
4101.1Sjmcneill	_XRead16 (dpy, slopbuf, 4 - slop);
4111.1.1.3Sskrll    }
4121.1.1.3Sskrll}
4131.1.1.3Sskrll#endif /* WORD64 */
4141.1.1.3Sskrll
4151.1.1.3Sskrll/*
4161.1.1.3Sskrll * The hard part about this is that we only get 16 bits from a reply.
4171.1.1.3Sskrll * We have three values that will march along, with the following invariant:
4181.1.1.3Sskrll *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
4191.1.1.3Sskrll * We have to keep
4201.1.1.3Sskrll *	dpy->request - dpy->last_request_read < 2^16
4211.1.1.3Sskrll * or else we won't know for sure what value to use in events.  We do this
4221.1.1.3Sskrll * by forcing syncs when we get close.
4231.1.1.3Sskrll */
4241.1.1.3Sskrll
4251.1.1.3Sskrllunsigned long
4261.1.1.3Sskrll_XSetLastRequestRead(
4271.1.1.3Sskrll    register Display *dpy,
4281.1.1.3Sskrll    register xGenericReply *rep)
4291.1.1.3Sskrll{
4301.1.1.3Sskrll    register unsigned long	newseq, lastseq;
4311.1.1.3Sskrll
4321.1.1.3Sskrll    lastseq = dpy->last_request_read;
4331.1.1.3Sskrll    /*
4341.1.1.3Sskrll     * KeymapNotify has no sequence number, but is always guaranteed
4351.1.1.3Sskrll     * to immediately follow another event, except when generated via
4361.1.1.3Sskrll     * SendEvent (hmmm).
4371.1.1.3Sskrll     */
4381.1Sjmcneill    if ((rep->type & 0x7f) == KeymapNotify)
439	return(lastseq);
440
441    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
442
443    if (newseq < lastseq) {
444	newseq += 0x10000;
445	if (newseq > dpy->request) {
446	    (void) fprintf (stderr,
447	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
448			    newseq, dpy->request,
449			    (unsigned int) rep->type);
450	    newseq -= 0x10000;
451	}
452    }
453
454    dpy->last_request_read = newseq;
455    return(newseq);
456}
457
458/*
459 * Support for internal connections, such as an IM might use.
460 * By Stephen Gildea, X Consortium, September 1993
461 */
462
463/* _XRegisterInternalConnection
464 * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
465 * include in its select/poll mask must call this function to register the
466 * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
467 * will also be called.
468 *
469 * Whenever Xlib detects input available on fd, it will call callback
470 * with call_data to process it.  If non-Xlib code calls select/poll
471 * and detects input available, it must call XProcessInternalConnection,
472 * which will call the associated callback.
473 *
474 * Non-Xlib code can learn about these additional fds by calling
475 * XInternalConnectionNumbers or, more typically, by registering
476 * a XConnectionWatchProc with XAddConnectionWatch
477 * to be called when fds are registered or unregistered.
478 *
479 * Returns True if registration succeeded, False if not, typically
480 * because could not allocate memory.
481 * Assumes Display locked when called.
482 */
483Status
484_XRegisterInternalConnection(
485    Display* dpy,
486    int fd,
487    _XInternalConnectionProc callback,
488    XPointer call_data
489)
490{
491    struct _XConnectionInfo *new_conni, **iptr;
492    struct _XConnWatchInfo *watchers;
493    XPointer *wd;
494
495    new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
496    if (!new_conni)
497	return 0;
498    new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
499    if (!new_conni->watch_data) {
500	Xfree(new_conni);
501	return 0;
502    }
503    new_conni->fd = fd;
504    new_conni->read_callback = callback;
505    new_conni->call_data = call_data;
506    new_conni->next = NULL;
507    /* link new structure onto end of list */
508    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
509	;
510    *iptr = new_conni;
511    dpy->im_fd_length++;
512    _XPollfdCacheAdd(dpy, fd);
513
514    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
515	 watchers;
516	 watchers=watchers->next, wd++) {
517	*wd = NULL;		/* for cleanliness */
518	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
519    }
520
521    return 1;
522}
523
524/* _XUnregisterInternalConnection
525 * Each IM (or Xlib extension) that closes a file descriptor previously
526 * registered with _XRegisterInternalConnection must call this function.
527 * Any XConnectionWatchProc registered by XAddConnectionWatch
528 * will also be called.
529 *
530 * Assumes Display locked when called.
531 */
532void
533_XUnregisterInternalConnection(
534    Display* dpy,
535    int fd
536)
537{
538    struct _XConnectionInfo *info_list, **prev;
539    struct _XConnWatchInfo *watch;
540    XPointer *wd;
541
542    for (prev = &dpy->im_fd_info; (info_list = *prev);
543	 prev = &info_list->next) {
544	if (info_list->fd == fd) {
545	    *prev = info_list->next;
546	    dpy->im_fd_length--;
547	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
548		 watch;
549		 watch=watch->next, wd++) {
550		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
551	    }
552	    if (info_list->watch_data)
553		Xfree (info_list->watch_data);
554	    Xfree (info_list);
555	    break;
556	}
557    }
558    _XPollfdCacheDel(dpy, fd);
559}
560
561/* XInternalConnectionNumbers
562 * Returns an array of fds and an array of corresponding call data.
563 * Typically a XConnectionWatchProc registered with XAddConnectionWatch
564 * will be used instead of this function to discover
565 * additional fds to include in the select/poll mask.
566 *
567 * The list is allocated with Xmalloc and should be freed by the caller
568 * with Xfree;
569 */
570Status
571XInternalConnectionNumbers(
572    Display *dpy,
573    int **fd_return,
574    int *count_return
575)
576{
577    int count;
578    struct _XConnectionInfo *info_list;
579    int *fd_list;
580
581    LockDisplay(dpy);
582    count = 0;
583    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
584	count++;
585    fd_list = (int*) Xmalloc (count * sizeof(int));
586    if (!fd_list) {
587	UnlockDisplay(dpy);
588	return 0;
589    }
590    count = 0;
591    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
592	fd_list[count] = info_list->fd;
593	count++;
594    }
595    UnlockDisplay(dpy);
596
597    *fd_return = fd_list;
598    *count_return = count;
599    return 1;
600}
601
602void _XProcessInternalConnection(
603    Display *dpy,
604    struct _XConnectionInfo *conn_info)
605{
606    dpy->flags |= XlibDisplayProcConni;
607    UnlockDisplay(dpy);
608    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
609    LockDisplay(dpy);
610    dpy->flags &= ~XlibDisplayProcConni;
611}
612
613/* XProcessInternalConnection
614 * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
615 * for this fd.
616 * The Display is NOT locked during the call.
617 */
618void
619XProcessInternalConnection(
620    Display* dpy,
621    int fd
622)
623{
624    struct _XConnectionInfo *info_list;
625
626    LockDisplay(dpy);
627    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
628	if (info_list->fd == fd) {
629	    _XProcessInternalConnection(dpy, info_list);
630	    break;
631	}
632    }
633    UnlockDisplay(dpy);
634}
635
636/* XAddConnectionWatch
637 * Register a callback to be called whenever _XRegisterInternalConnection
638 * or _XUnregisterInternalConnection is called.
639 * Callbacks are called with the Display locked.
640 * If any connections are already registered, the callback is immediately
641 * called for each of them.
642 */
643Status
644XAddConnectionWatch(
645    Display* dpy,
646    XConnectionWatchProc callback,
647    XPointer client_data
648)
649{
650    struct _XConnWatchInfo *new_watcher, **wptr;
651    struct _XConnectionInfo *info_list;
652    XPointer *wd_array;
653
654    LockDisplay(dpy);
655
656    /* allocate new watch data */
657    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
658	wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
659					(dpy->watcher_count + 1) *
660					sizeof(XPointer));
661	if (!wd_array) {
662	    UnlockDisplay(dpy);
663	    return 0;
664	}
665	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
666    }
667
668    new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
669    if (!new_watcher) {
670	UnlockDisplay(dpy);
671	return 0;
672    }
673    new_watcher->fn = callback;
674    new_watcher->client_data = client_data;
675    new_watcher->next = NULL;
676
677    /* link new structure onto end of list */
678    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
679	;
680    *wptr = new_watcher;
681    dpy->watcher_count++;
682
683    /* call new watcher on all currently registered fds */
684    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
685	(*callback) (dpy, client_data, info_list->fd, True,
686		     info_list->watch_data + dpy->watcher_count - 1);
687    }
688
689    UnlockDisplay(dpy);
690    return 1;
691}
692
693/* XRemoveConnectionWatch
694 * Unregister a callback registered by XAddConnectionWatch.
695 * Both callback and client_data must match what was passed to
696 * XAddConnectionWatch.
697 */
698void
699XRemoveConnectionWatch(
700    Display* dpy,
701    XConnectionWatchProc callback,
702    XPointer client_data
703)
704{
705    struct _XConnWatchInfo *watch;
706    struct _XConnWatchInfo *previous = NULL;
707    struct _XConnectionInfo *conni;
708    int counter = 0;
709
710    LockDisplay(dpy);
711    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
712	if (watch->fn == callback  &&  watch->client_data == client_data) {
713	    if (previous)
714		previous->next = watch->next;
715	    else
716		dpy->conn_watchers = watch->next;
717	    Xfree (watch);
718	    dpy->watcher_count--;
719	    /* remove our watch_data for each connection */
720	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
721		/* don't bother realloc'ing; these arrays are small anyway */
722		/* overlapping */
723		memmove(conni->watch_data+counter,
724			conni->watch_data+counter+1,
725			dpy->watcher_count - counter);
726	    }
727	    break;
728	}
729	previous = watch;
730	counter++;
731    }
732    UnlockDisplay(dpy);
733}
734
735/* end of internal connections support */
736
737/* Cookie jar implementation
738   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
739   them in the normal EQ. _XStoreEvent returns the cookie event (minus
740   data pointer) and adds it to the cookiejar. _XDeq just removes
741   the entry like any other event but resets the data pointer for
742   cookie events (to avoid double-free, the memory is re-used by Xlib).
743
744   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
745   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
746   (called by XNextEvent).
747
748   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
749   normal EQ.
750 */
751
752#include "utlist.h"
753struct stored_event {
754    XGenericEventCookie ev;
755    struct stored_event *prev;
756    struct stored_event *next;
757};
758
759Bool
760_XIsEventCookie(Display *dpy, XEvent *ev)
761{
762    return (ev->xcookie.type == GenericEvent &&
763	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
764}
765
766/**
767 * Free all events in the event list.
768 */
769void
770_XFreeEventCookies(Display *dpy)
771{
772    struct stored_event **head, *e, *tmp;
773
774    if (!dpy->cookiejar)
775        return;
776
777    head = (struct stored_event**)&dpy->cookiejar;
778
779    DL_FOREACH_SAFE(*head, e, tmp) {
780        XFree(e->ev.data);
781        XFree(e);
782        if (dpy->cookiejar == e)
783            dpy->cookiejar = NULL;
784    }
785}
786
787/**
788 * Add an event to the display's event list. This event must be freed on the
789 * next call to XNextEvent().
790 */
791void
792_XStoreEventCookie(Display *dpy, XEvent *event)
793{
794    XGenericEventCookie* cookie = &event->xcookie;
795    struct stored_event **head, *add;
796
797    if (!_XIsEventCookie(dpy, event))
798        return;
799
800    head = (struct stored_event**)(&dpy->cookiejar);
801
802    add = Xmalloc(sizeof(struct stored_event));
803    if (!add) {
804        ESET(ENOMEM);
805        _XIOError(dpy);
806    }
807    add->ev = *cookie;
808    DL_APPEND(*head, add);
809    cookie->data = NULL; /* don't return data yet, must be claimed */
810}
811
812/**
813 * Return the event with the given cookie and remove it from the list.
814 */
815Bool
816_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
817{
818    Bool ret = False;
819    struct stored_event **head, *event;
820    head = (struct stored_event**)&dpy->cookiejar;
821
822    if (!_XIsEventCookie(dpy, (XEvent*)ev))
823        return ret;
824
825    DL_FOREACH(*head, event) {
826        if (event->ev.cookie == ev->cookie &&
827            event->ev.extension == ev->extension &&
828            event->ev.evtype == ev->evtype) {
829            *ev = event->ev;
830            DL_DELETE(*head, event);
831            Xfree(event);
832            ret = True;
833            break;
834        }
835    }
836
837    return ret;
838}
839
840Bool
841_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
842{
843    Bool ret = False;
844    int extension;
845
846    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
847        return ret;
848
849    extension = in->extension & 0x7F;
850
851    if (!dpy->generic_event_copy_vec[extension])
852        return ret;
853
854    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
855    out->cookie = ret ? ++dpy->next_cookie  : 0;
856    return ret;
857}
858
859
860/*
861 * _XEnq - Place event packets on the display's queue.
862 * note that no squishing of move events in V11, since there
863 * is pointer motion hints....
864 */
865void _XEnq(
866	register Display *dpy,
867	register xEvent *event)
868{
869	register _XQEvent *qelt;
870	int type, extension;
871
872	if ((qelt = dpy->qfree)) {
873		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
874		dpy->qfree = qelt->next;
875	}
876	else if ((qelt =
877	    (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
878		/* Malloc call failed! */
879		ESET(ENOMEM);
880		_XIOError(dpy);
881	}
882	qelt->next = NULL;
883
884	type = event->u.u.type & 0177;
885	extension = ((xGenericEvent*)event)->extension;
886
887	qelt->event.type = type;
888	/* If an extension has registerd a generic_event_vec handler, then
889	 * it can handle event cookies. Otherwise, proceed with the normal
890	 * event handlers.
891	 *
892	 * If the generic_event_vec is called, qelt->event is a event cookie
893	 * with the data pointer and the "free" pointer set. Data pointer is
894	 * some memory allocated by the extension.
895	 */
896        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
897	    XGenericEventCookie *cookie = &qelt->event.xcookie;
898	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
899	    cookie->cookie = ++dpy->next_cookie;
900
901	    qelt->qserial_num = dpy->next_event_serial_num++;
902	    if (dpy->tail)	dpy->tail->next = qelt;
903	    else		dpy->head = qelt;
904
905	    dpy->tail = qelt;
906	    dpy->qlen++;
907	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
908	    qelt->qserial_num = dpy->next_event_serial_num++;
909	    if (dpy->tail)	dpy->tail->next = qelt;
910	    else 		dpy->head = qelt;
911
912	    dpy->tail = qelt;
913	    dpy->qlen++;
914	} else {
915	    /* ignored, or stashed away for many-to-one compression */
916	    qelt->next = dpy->qfree;
917	    dpy->qfree = qelt;
918	}
919}
920
921/*
922 * _XDeq - Remove event packet from the display's queue.
923 */
924void _XDeq(
925    register Display *dpy,
926    register _XQEvent *prev,	/* element before qelt */
927    register _XQEvent *qelt)	/* element to be unlinked */
928{
929    if (prev) {
930	if ((prev->next = qelt->next) == NULL)
931	    dpy->tail = prev;
932    } else {
933	/* no prev, so removing first elt */
934	if ((dpy->head = qelt->next) == NULL)
935	    dpy->tail = NULL;
936    }
937    qelt->qserial_num = 0;
938    qelt->next = dpy->qfree;
939    dpy->qfree = qelt;
940    dpy->qlen--;
941
942    if (_XIsEventCookie(dpy, &qelt->event)) {
943	XGenericEventCookie* cookie = &qelt->event.xcookie;
944	/* dpy->qfree is re-used, reset memory to avoid double free on
945	 * _XFreeDisplayStructure */
946	cookie->data = NULL;
947    }
948}
949
950/*
951 * EventToWire in separate file in that often not needed.
952 */
953
954/*ARGSUSED*/
955Bool
956_XUnknownWireEvent(
957    register Display *dpy,	/* pointer to display structure */
958    register XEvent *re,	/* pointer to where event should be reformatted */
959    register xEvent *event)	/* wire protocol event */
960{
961#ifdef notdef
962	(void) fprintf(stderr,
963	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
964			event->u.u.type, dpy);
965#endif
966	return(False);
967}
968
969Bool
970_XUnknownWireEventCookie(
971    Display *dpy,	/* pointer to display structure */
972    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
973    xEvent *event)	/* wire protocol event */
974{
975#ifdef notdef
976	fprintf(stderr,
977	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
978			((xGenericEvent*)event)->extension, dpy);
979#endif
980	return(False);
981}
982
983Bool
984_XUnknownCopyEventCookie(
985    Display *dpy,	/* pointer to display structure */
986    XGenericEventCookie *in,	/* source */
987    XGenericEventCookie *out)	/* destination */
988{
989#ifdef notdef
990	fprintf(stderr,
991	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
992			in->extension, dpy);
993#endif
994	return(False);
995}
996
997/*ARGSUSED*/
998Status
999_XUnknownNativeEvent(
1000    register Display *dpy,	/* pointer to display structure */
1001    register XEvent *re,	/* pointer to where event should be reformatted */
1002    register xEvent *event)	/* wire protocol event */
1003{
1004#ifdef notdef
1005	(void) fprintf(stderr,
1006 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
1007			re->type, dpy);
1008#endif
1009	return(0);
1010}
1011/*
1012 * reformat a wire event into an XEvent structure of the right type.
1013 */
1014Bool
1015_XWireToEvent(
1016    register Display *dpy,	/* pointer to display structure */
1017    register XEvent *re,	/* pointer to where event should be reformatted */
1018    register xEvent *event)	/* wire protocol event */
1019{
1020
1021	re->type = event->u.u.type & 0x7f;
1022	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
1023					(xGenericReply *)event);
1024	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
1025	((XAnyEvent *)re)->display = dpy;
1026
1027	/* Ignore the leading bit of the event type since it is set when a
1028		client sends an event rather than the server. */
1029
1030	switch (event-> u.u.type & 0177) {
1031	      case KeyPress:
1032	      case KeyRelease:
1033	        {
1034			register XKeyEvent *ev = (XKeyEvent*) re;
1035			ev->root 	= event->u.keyButtonPointer.root;
1036			ev->window 	= event->u.keyButtonPointer.event;
1037			ev->subwindow 	= event->u.keyButtonPointer.child;
1038			ev->time 	= event->u.keyButtonPointer.time;
1039			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
1040			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
1041			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
1042			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
1043			ev->state	= event->u.keyButtonPointer.state;
1044			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
1045			ev->keycode 	= event->u.u.detail;
1046		}
1047	      	break;
1048	      case ButtonPress:
1049	      case ButtonRelease:
1050	        {
1051			register XButtonEvent *ev =  (XButtonEvent *) re;
1052			ev->root 	= event->u.keyButtonPointer.root;
1053			ev->window 	= event->u.keyButtonPointer.event;
1054			ev->subwindow 	= event->u.keyButtonPointer.child;
1055			ev->time 	= event->u.keyButtonPointer.time;
1056			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
1057			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
1058			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
1059			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
1060			ev->state	= event->u.keyButtonPointer.state;
1061			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
1062			ev->button 	= event->u.u.detail;
1063		}
1064	        break;
1065	      case MotionNotify:
1066	        {
1067			register XMotionEvent *ev =   (XMotionEvent *)re;
1068			ev->root 	= event->u.keyButtonPointer.root;
1069			ev->window 	= event->u.keyButtonPointer.event;
1070			ev->subwindow 	= event->u.keyButtonPointer.child;
1071			ev->time 	= event->u.keyButtonPointer.time;
1072			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
1073			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
1074			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
1075			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
1076			ev->state	= event->u.keyButtonPointer.state;
1077			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
1078			ev->is_hint 	= event->u.u.detail;
1079		}
1080	        break;
1081	      case EnterNotify:
1082	      case LeaveNotify:
1083		{
1084			register XCrossingEvent *ev   = (XCrossingEvent *) re;
1085			ev->root	= event->u.enterLeave.root;
1086			ev->window	= event->u.enterLeave.event;
1087			ev->subwindow	= event->u.enterLeave.child;
1088			ev->time	= event->u.enterLeave.time;
1089			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
1090			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
1091			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
1092			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
1093			ev->state	= event->u.enterLeave.state;
1094			ev->mode	= event->u.enterLeave.mode;
1095			ev->same_screen = (event->u.enterLeave.flags &
1096				ELFlagSameScreen) && True;
1097			ev->focus	= (event->u.enterLeave.flags &
1098			  	ELFlagFocus) && True;
1099			ev->detail	= event->u.u.detail;
1100		}
1101		  break;
1102	      case FocusIn:
1103	      case FocusOut:
1104		{
1105			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
1106			ev->window 	= event->u.focus.window;
1107			ev->mode	= event->u.focus.mode;
1108			ev->detail	= event->u.u.detail;
1109		}
1110		  break;
1111	      case KeymapNotify:
1112		{
1113			register XKeymapEvent *ev = (XKeymapEvent *) re;
1114			ev->window	= None;
1115			memcpy(&ev->key_vector[1],
1116			       (char *)((xKeymapEvent *) event)->map,
1117			       sizeof (((xKeymapEvent *) event)->map));
1118		}
1119		break;
1120	      case Expose:
1121		{
1122			register XExposeEvent *ev = (XExposeEvent *) re;
1123			ev->window	= event->u.expose.window;
1124			ev->x		= event->u.expose.x;
1125			ev->y		= event->u.expose.y;
1126			ev->width	= event->u.expose.width;
1127			ev->height	= event->u.expose.height;
1128			ev->count	= event->u.expose.count;
1129		}
1130		break;
1131	      case GraphicsExpose:
1132		{
1133		    register XGraphicsExposeEvent *ev =
1134			(XGraphicsExposeEvent *) re;
1135		    ev->drawable	= event->u.graphicsExposure.drawable;
1136		    ev->x		= event->u.graphicsExposure.x;
1137		    ev->y		= event->u.graphicsExposure.y;
1138		    ev->width		= event->u.graphicsExposure.width;
1139		    ev->height		= event->u.graphicsExposure.height;
1140		    ev->count		= event->u.graphicsExposure.count;
1141		    ev->major_code	= event->u.graphicsExposure.majorEvent;
1142		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
1143		}
1144		break;
1145	      case NoExpose:
1146		{
1147		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
1148		    ev->drawable	= event->u.noExposure.drawable;
1149		    ev->major_code	= event->u.noExposure.majorEvent;
1150		    ev->minor_code	= event->u.noExposure.minorEvent;
1151		}
1152		break;
1153	      case VisibilityNotify:
1154		{
1155		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
1156		    ev->window		= event->u.visibility.window;
1157		    ev->state		= event->u.visibility.state;
1158		}
1159		break;
1160	      case CreateNotify:
1161		{
1162		    register XCreateWindowEvent *ev =
1163			 (XCreateWindowEvent *) re;
1164		    ev->window		= event->u.createNotify.window;
1165		    ev->parent		= event->u.createNotify.parent;
1166		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
1167		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
1168		    ev->width		= event->u.createNotify.width;
1169		    ev->height		= event->u.createNotify.height;
1170		    ev->border_width	= event->u.createNotify.borderWidth;
1171		    ev->override_redirect	= event->u.createNotify.override;
1172		}
1173		break;
1174	      case DestroyNotify:
1175		{
1176		    register XDestroyWindowEvent *ev =
1177				(XDestroyWindowEvent *) re;
1178		    ev->window		= event->u.destroyNotify.window;
1179		    ev->event		= event->u.destroyNotify.event;
1180		}
1181		break;
1182	      case UnmapNotify:
1183		{
1184		    register XUnmapEvent *ev = (XUnmapEvent *) re;
1185		    ev->window		= event->u.unmapNotify.window;
1186		    ev->event		= event->u.unmapNotify.event;
1187		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
1188		}
1189		break;
1190	      case MapNotify:
1191		{
1192		    register XMapEvent *ev = (XMapEvent *) re;
1193		    ev->window		= event->u.mapNotify.window;
1194		    ev->event		= event->u.mapNotify.event;
1195		    ev->override_redirect	= event->u.mapNotify.override;
1196		}
1197		break;
1198	      case MapRequest:
1199		{
1200		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
1201		    ev->window		= event->u.mapRequest.window;
1202		    ev->parent		= event->u.mapRequest.parent;
1203		}
1204		break;
1205	      case ReparentNotify:
1206		{
1207		    register XReparentEvent *ev = (XReparentEvent *) re;
1208		    ev->event		= event->u.reparent.event;
1209		    ev->window		= event->u.reparent.window;
1210		    ev->parent		= event->u.reparent.parent;
1211		    ev->x		= cvtINT16toInt(event->u.reparent.x);
1212		    ev->y		= cvtINT16toInt(event->u.reparent.y);
1213		    ev->override_redirect	= event->u.reparent.override;
1214		}
1215		break;
1216	      case ConfigureNotify:
1217		{
1218		    register XConfigureEvent *ev = (XConfigureEvent *) re;
1219		    ev->event	= event->u.configureNotify.event;
1220		    ev->window	= event->u.configureNotify.window;
1221		    ev->above	= event->u.configureNotify.aboveSibling;
1222		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
1223		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
1224		    ev->width	= event->u.configureNotify.width;
1225		    ev->height	= event->u.configureNotify.height;
1226		    ev->border_width  = event->u.configureNotify.borderWidth;
1227		    ev->override_redirect = event->u.configureNotify.override;
1228		}
1229		break;
1230	      case ConfigureRequest:
1231		{
1232		    register XConfigureRequestEvent *ev =
1233		        (XConfigureRequestEvent *) re;
1234		    ev->window		= event->u.configureRequest.window;
1235		    ev->parent		= event->u.configureRequest.parent;
1236		    ev->above		= event->u.configureRequest.sibling;
1237		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
1238		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
1239		    ev->width		= event->u.configureRequest.width;
1240		    ev->height		= event->u.configureRequest.height;
1241		    ev->border_width	= event->u.configureRequest.borderWidth;
1242		    ev->value_mask	= event->u.configureRequest.valueMask;
1243		    ev->detail  	= event->u.u.detail;
1244		}
1245		break;
1246	      case GravityNotify:
1247		{
1248		    register XGravityEvent *ev = (XGravityEvent *) re;
1249		    ev->window		= event->u.gravity.window;
1250		    ev->event		= event->u.gravity.event;
1251		    ev->x		= cvtINT16toInt(event->u.gravity.x);
1252		    ev->y		= cvtINT16toInt(event->u.gravity.y);
1253		}
1254		break;
1255	      case ResizeRequest:
1256		{
1257		    register XResizeRequestEvent *ev =
1258			(XResizeRequestEvent *) re;
1259		    ev->window		= event->u.resizeRequest.window;
1260		    ev->width		= event->u.resizeRequest.width;
1261		    ev->height		= event->u.resizeRequest.height;
1262		}
1263		break;
1264	      case CirculateNotify:
1265		{
1266		    register XCirculateEvent *ev = (XCirculateEvent *) re;
1267		    ev->window		= event->u.circulate.window;
1268		    ev->event		= event->u.circulate.event;
1269		    ev->place		= event->u.circulate.place;
1270		}
1271		break;
1272	      case CirculateRequest:
1273		{
1274		    register XCirculateRequestEvent *ev =
1275		        (XCirculateRequestEvent *) re;
1276		    ev->window		= event->u.circulate.window;
1277		    ev->parent		= event->u.circulate.event;
1278		    ev->place		= event->u.circulate.place;
1279		}
1280		break;
1281	      case PropertyNotify:
1282		{
1283		    register XPropertyEvent *ev = (XPropertyEvent *) re;
1284		    ev->window		= event->u.property.window;
1285		    ev->atom		= event->u.property.atom;
1286		    ev->time		= event->u.property.time;
1287		    ev->state		= event->u.property.state;
1288		}
1289		break;
1290	      case SelectionClear:
1291		{
1292		    register XSelectionClearEvent *ev =
1293			 (XSelectionClearEvent *) re;
1294		    ev->window		= event->u.selectionClear.window;
1295		    ev->selection	= event->u.selectionClear.atom;
1296		    ev->time		= event->u.selectionClear.time;
1297		}
1298		break;
1299	      case SelectionRequest:
1300		{
1301		    register XSelectionRequestEvent *ev =
1302		        (XSelectionRequestEvent *) re;
1303		    ev->owner		= event->u.selectionRequest.owner;
1304		    ev->requestor	= event->u.selectionRequest.requestor;
1305		    ev->selection	= event->u.selectionRequest.selection;
1306		    ev->target		= event->u.selectionRequest.target;
1307		    ev->property	= event->u.selectionRequest.property;
1308		    ev->time		= event->u.selectionRequest.time;
1309		}
1310		break;
1311	      case SelectionNotify:
1312		{
1313		    register XSelectionEvent *ev = (XSelectionEvent *) re;
1314		    ev->requestor	= event->u.selectionNotify.requestor;
1315		    ev->selection	= event->u.selectionNotify.selection;
1316		    ev->target		= event->u.selectionNotify.target;
1317		    ev->property	= event->u.selectionNotify.property;
1318		    ev->time		= event->u.selectionNotify.time;
1319		}
1320		break;
1321	      case ColormapNotify:
1322		{
1323		    register XColormapEvent *ev = (XColormapEvent *) re;
1324		    ev->window		= event->u.colormap.window;
1325		    ev->colormap	= event->u.colormap.colormap;
1326		    ev->new		= event->u.colormap.new;
1327		    ev->state		= event->u.colormap.state;
1328	        }
1329		break;
1330	      case ClientMessage:
1331		{
1332		   register int i;
1333		   register XClientMessageEvent *ev
1334		   			= (XClientMessageEvent *) re;
1335		   ev->window		= event->u.clientMessage.window;
1336		   ev->format		= event->u.u.detail;
1337		   switch (ev->format) {
1338			case 8:
1339			   ev->message_type = event->u.clientMessage.u.b.type;
1340			   for (i = 0; i < 20; i++)
1341			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
1342			   break;
1343			case 16:
1344			   ev->message_type = event->u.clientMessage.u.s.type;
1345			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
1346			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
1347			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
1348			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
1349			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
1350			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
1351			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
1352			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
1353			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
1354			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
1355			   break;
1356			case 32:
1357			   ev->message_type = event->u.clientMessage.u.l.type;
1358			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
1359			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
1360			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
1361			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
1362			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
1363			   break;
1364			default: /* XXX should never occur */
1365				break;
1366		    }
1367	        }
1368		break;
1369	      case MappingNotify:
1370		{
1371		   register XMappingEvent *ev = (XMappingEvent *)re;
1372		   ev->window		= 0;
1373		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
1374		   ev->request 		= event->u.mappingNotify.request;
1375		   ev->count 		= event->u.mappingNotify.count;
1376		}
1377		break;
1378	      default:
1379		return(_XUnknownWireEvent(dpy, re, event));
1380	}
1381	return(True);
1382}
1383
1384
1385/*
1386 * _XDefaultIOError - Default fatal system error reporting routine.  Called
1387 * when an X internal system error is encountered.
1388 */
1389int _XDefaultIOError(
1390	Display *dpy)
1391{
1392	if (ECHECK(EPIPE)) {
1393	    (void) fprintf (stderr,
1394	"X connection to %s broken (explicit kill or server shutdown).\r\n",
1395			    DisplayString (dpy));
1396	} else {
1397	    (void) fprintf (stderr,
1398			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
1399#ifdef WIN32
1400			WSAGetLastError(), strerror(WSAGetLastError()),
1401#else
1402			errno, strerror (errno),
1403#endif
1404			DisplayString (dpy));
1405	    (void) fprintf (stderr,
1406	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
1407			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
1408			QLength(dpy));
1409
1410	}
1411	exit(1);
1412        return(0); /* dummy - function should never return */
1413}
1414
1415
1416static int _XPrintDefaultError(
1417    Display *dpy,
1418    XErrorEvent *event,
1419    FILE *fp)
1420{
1421    char buffer[BUFSIZ];
1422    char mesg[BUFSIZ];
1423    char number[32];
1424    const char *mtype = "XlibMessage";
1425    register _XExtension *ext = (_XExtension *)NULL;
1426    _XExtension *bext = (_XExtension *)NULL;
1427    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
1428    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
1429    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
1430    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
1431	mesg, BUFSIZ);
1432    (void) fprintf(fp, mesg, event->request_code);
1433    if (event->request_code < 128) {
1434	sprintf(number, "%d", event->request_code);
1435	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
1436    } else {
1437	for (ext = dpy->ext_procs;
1438	     ext && (ext->codes.major_opcode != event->request_code);
1439	     ext = ext->next)
1440	  ;
1441	if (ext)
1442	    strcpy(buffer, ext->name);
1443	else
1444	    buffer[0] = '\0';
1445    }
1446    (void) fprintf(fp, " (%s)\n", buffer);
1447    if (event->request_code >= 128) {
1448	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
1449			      mesg, BUFSIZ);
1450	fputs("  ", fp);
1451	(void) fprintf(fp, mesg, event->minor_code);
1452	if (ext) {
1453	    sprintf(mesg, "%s.%d", ext->name, event->minor_code);
1454	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
1455	    (void) fprintf(fp, " (%s)", buffer);
1456	}
1457	fputs("\n", fp);
1458    }
1459    if (event->error_code >= 128) {
1460	/* kludge, try to find the extension that caused it */
1461	buffer[0] = '\0';
1462	for (ext = dpy->ext_procs; ext; ext = ext->next) {
1463	    if (ext->error_string)
1464		(*ext->error_string)(dpy, event->error_code, &ext->codes,
1465				     buffer, BUFSIZ);
1466	    if (buffer[0]) {
1467		bext = ext;
1468		break;
1469	    }
1470	    if (ext->codes.first_error &&
1471		ext->codes.first_error < (int)event->error_code &&
1472		(!bext || ext->codes.first_error > bext->codes.first_error))
1473		bext = ext;
1474	}
1475	if (bext)
1476	    sprintf(buffer, "%s.%d", bext->name,
1477		    event->error_code - bext->codes.first_error);
1478	else
1479	    strcpy(buffer, "Value");
1480	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
1481	if (mesg[0]) {
1482	    fputs("  ", fp);
1483	    (void) fprintf(fp, mesg, event->resourceid);
1484	    fputs("\n", fp);
1485	}
1486	/* let extensions try to print the values */
1487	for (ext = dpy->ext_procs; ext; ext = ext->next) {
1488	    if (ext->error_values)
1489		(*ext->error_values)(dpy, event, fp);
1490	}
1491    } else if ((event->error_code == BadWindow) ||
1492	       (event->error_code == BadPixmap) ||
1493	       (event->error_code == BadCursor) ||
1494	       (event->error_code == BadFont) ||
1495	       (event->error_code == BadDrawable) ||
1496	       (event->error_code == BadColor) ||
1497	       (event->error_code == BadGC) ||
1498	       (event->error_code == BadIDChoice) ||
1499	       (event->error_code == BadValue) ||
1500	       (event->error_code == BadAtom)) {
1501	if (event->error_code == BadValue)
1502	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
1503				  mesg, BUFSIZ);
1504	else if (event->error_code == BadAtom)
1505	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
1506				  mesg, BUFSIZ);
1507	else
1508	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
1509				  mesg, BUFSIZ);
1510	fputs("  ", fp);
1511	(void) fprintf(fp, mesg, event->resourceid);
1512	fputs("\n", fp);
1513    }
1514    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
1515			  mesg, BUFSIZ);
1516    fputs("  ", fp);
1517    (void) fprintf(fp, mesg, event->serial);
1518    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
1519			  mesg, BUFSIZ);
1520    fputs("\n  ", fp);
1521    (void) fprintf(fp, mesg, dpy->request);
1522    fputs("\n", fp);
1523    if (event->error_code == BadImplementation) return 0;
1524    return 1;
1525}
1526
1527int _XDefaultError(
1528	Display *dpy,
1529	XErrorEvent *event)
1530{
1531    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
1532    exit(1);
1533    /*NOTREACHED*/
1534}
1535
1536/*ARGSUSED*/
1537Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
1538{
1539    return True;
1540}
1541
1542/*
1543 * _XError - upcall internal or user protocol error handler
1544 */
1545int _XError (
1546    Display *dpy,
1547    register xError *rep)
1548{
1549    /*
1550     * X_Error packet encountered!  We need to unpack the error before
1551     * giving it to the user.
1552     */
1553    XEvent event; /* make it a large event */
1554    register _XAsyncHandler *async, *next;
1555
1556    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
1557
1558    for (async = dpy->async_handlers; async; async = next) {
1559	next = async->next;
1560	if ((*async->handler)(dpy, (xReply *)rep,
1561			      (char *)rep, SIZEOF(xError), async->data))
1562	    return 0;
1563    }
1564
1565    event.xerror.display = dpy;
1566    event.xerror.type = X_Error;
1567    event.xerror.resourceid = rep->resourceID;
1568    event.xerror.error_code = rep->errorCode;
1569    event.xerror.request_code = rep->majorCode;
1570    event.xerror.minor_code = rep->minorCode;
1571    if (dpy->error_vec &&
1572	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
1573	return 0;
1574    if (_XErrorFunction != NULL) {
1575	return (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1576    } else {
1577	return _XDefaultError(dpy, (XErrorEvent *)&event);
1578    }
1579}
1580
1581/*
1582 * _XIOError - call user connection error handler and exit
1583 */
1584int
1585_XIOError (
1586    Display *dpy)
1587{
1588    dpy->flags |= XlibDisplayIOError;
1589#ifdef WIN32
1590    errno = WSAGetLastError();
1591#endif
1592
1593    /* This assumes that the thread calling exit will call any atexit handlers.
1594     * If this does not hold, then an alternate solution would involve
1595     * registering an atexit handler to take over the lock, which would only
1596     * assume that the same thread calls all the atexit handlers. */
1597#ifdef XTHREADS
1598    if (dpy->lock)
1599	(*dpy->lock->user_lock_display)(dpy);
1600#endif
1601    UnlockDisplay(dpy);
1602
1603    if (_XIOErrorFunction != NULL)
1604	(*_XIOErrorFunction)(dpy);
1605    else
1606	_XDefaultIOError(dpy);
1607    exit (1);
1608    return 0;
1609}
1610
1611
1612/*
1613 * This routine can be used to (cheaply) get some memory within a single
1614 * Xlib routine for scratch space.  A single buffer is reused each time
1615 * if possible.  To be MT safe, you can only call this between a call to
1616 * GetReq* and a call to Data* or _XSend*, or in a context when the thread
1617 * is guaranteed to not unlock the display.
1618 */
1619char *_XAllocScratch(
1620	register Display *dpy,
1621	unsigned long nbytes)
1622{
1623	if (nbytes > dpy->scratch_length) {
1624	    if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
1625	    if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
1626		dpy->scratch_length = nbytes;
1627	    else dpy->scratch_length = 0;
1628	}
1629	return (dpy->scratch_buffer);
1630}
1631
1632/*
1633 * Scratch space allocator you can call any time, multiple times, and be
1634 * MT safe, but you must hand the buffer back with _XFreeTemp.
1635 */
1636char *_XAllocTemp(
1637    register Display *dpy,
1638    unsigned long nbytes)
1639{
1640    char *buf;
1641
1642    buf = _XAllocScratch(dpy, nbytes);
1643    dpy->scratch_buffer = NULL;
1644    dpy->scratch_length = 0;
1645    return buf;
1646}
1647
1648void _XFreeTemp(
1649    register Display *dpy,
1650    char *buf,
1651    unsigned long nbytes)
1652{
1653    if (dpy->scratch_buffer)
1654	Xfree(dpy->scratch_buffer);
1655    dpy->scratch_buffer = buf;
1656    dpy->scratch_length = nbytes;
1657}
1658
1659/*
1660 * Given a visual id, find the visual structure for this id on this display.
1661 */
1662Visual *_XVIDtoVisual(
1663	Display *dpy,
1664	VisualID id)
1665{
1666	register int i, j, k;
1667	register Screen *sp;
1668	register Depth *dp;
1669	register Visual *vp;
1670	for (i = 0; i < dpy->nscreens; i++) {
1671		sp = &dpy->screens[i];
1672		for (j = 0; j < sp->ndepths; j++) {
1673			dp = &sp->depths[j];
1674			/* if nvisuals == 0 then visuals will be NULL */
1675			for (k = 0; k < dp->nvisuals; k++) {
1676				vp = &dp->visuals[k];
1677				if (vp->visualid == id) return (vp);
1678			}
1679		}
1680	}
1681	return (NULL);
1682}
1683
1684int
1685XFree (void *data)
1686{
1687	Xfree (data);
1688	return 1;
1689}
1690
1691#ifdef _XNEEDBCOPYFUNC
1692void _Xbcopy(b1, b2, length)
1693    register char *b1, *b2;
1694    register length;
1695{
1696    if (b1 < b2) {
1697	b2 += length;
1698	b1 += length;
1699	while (length--)
1700	    *--b2 = *--b1;
1701    } else {
1702	while (length--)
1703	    *b2++ = *b1++;
1704    }
1705}
1706#endif
1707
1708#ifdef DataRoutineIsProcedure
1709void Data(
1710	Display *dpy,
1711	char *data,
1712	long len)
1713{
1714	if (dpy->bufptr + (len) <= dpy->bufmax) {
1715		memcpy(dpy->bufptr, data, (int)len);
1716		dpy->bufptr += ((len) + 3) & ~3;
1717	} else {
1718		_XSend(dpy, data, len);
1719	}
1720}
1721#endif /* DataRoutineIsProcedure */
1722
1723
1724#ifdef LONG64
1725int
1726_XData32(
1727    Display *dpy,
1728    register long *data,
1729    unsigned len)
1730{
1731    register int *buf;
1732    register long i;
1733
1734    while (len) {
1735	buf = (int *)dpy->bufptr;
1736	i = dpy->bufmax - (char *)buf;
1737	if (!i) {
1738	    _XFlush(dpy);
1739	    continue;
1740	}
1741	if (len < i)
1742	    i = len;
1743	dpy->bufptr = (char *)buf + i;
1744	len -= i;
1745	i >>= 2;
1746	while (--i >= 0)
1747	    *buf++ = *data++;
1748    }
1749    return 0;
1750}
1751#endif /* LONG64 */
1752
1753#ifdef WORD64
1754
1755/*
1756 * XXX This is a *really* stupid way of doing this.  It should just use
1757 * dpy->bufptr directly, taking into account where in the word it is.
1758 */
1759
1760/*
1761 * Data16 - Place 16 bit data in the buffer.
1762 *
1763 * "dpy" is a pointer to a Display.
1764 * "data" is a pointer to the data.
1765 * "len" is the length in bytes of the data.
1766 */
1767
1768static doData16(
1769    register Display *dpy,
1770    short *data,
1771    unsigned len,
1772    char *packbuffer)
1773{
1774    long *lp,*lpack;
1775    long i, nwords,bits;
1776    long mask16 = 0x000000000000ffff;
1777
1778        lp = (long *)data;
1779        lpack = (long *)packbuffer;
1780
1781/*  nwords is the number of 16 bit values to be packed,
1782 *  the low order 16 bits of each word will be packed
1783 *  into 64 bit words
1784 */
1785        nwords = len >> 1;
1786        bits = 48;
1787
1788        for(i=0;i<nwords;i++){
1789	   if (bits == 48) *lpack = 0;
1790           *lpack ^= (*lp & mask16) << bits;
1791           bits -= 16 ;
1792           lp++;
1793           if(bits < 0){
1794               lpack++;
1795               bits = 48;
1796           }
1797        }
1798        Data(dpy, packbuffer, len);
1799}
1800
1801_XData16 (
1802    Display *dpy,
1803    short *data,
1804    unsigned len)
1805{
1806    char packbuffer[PACKBUFFERSIZE];
1807    unsigned nunits = PACKBUFFERSIZE >> 1;
1808
1809    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
1810	doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
1811    }
1812    if (len) doData16 (dpy, data, len, packbuffer);
1813}
1814
1815/*
1816 * Data32 - Place 32 bit data in the buffer.
1817 *
1818 * "dpy" is a pointer to a Display.
1819 * "data" is a pointer to the data.
1820 * "len" is the length in bytes of the data.
1821 */
1822
1823static doData32(
1824    register Display *dpy
1825    long *data,
1826    unsigned len,
1827    char *packbuffer)
1828{
1829    long *lp,*lpack;
1830    long i,bits,nwords;
1831    long mask32 = 0x00000000ffffffff;
1832
1833        lpack = (long *) packbuffer;
1834        lp = data;
1835
1836/*  nwords is the number of 32 bit values to be packed
1837 *  the low order 32 bits of each word will be packed
1838 *  into 64 bit words
1839 */
1840        nwords = len >> 2;
1841        bits = 32;
1842
1843        for(i=0;i<nwords;i++){
1844	   if (bits == 32) *lpack = 0;
1845           *lpack ^= (*lp & mask32) << bits;
1846           bits = bits ^32;
1847           lp++;
1848           if(bits)
1849              lpack++;
1850        }
1851        Data(dpy, packbuffer, len);
1852}
1853
1854void _XData32(
1855    Display *dpy,
1856    long *data,
1857    unsigned len)
1858{
1859    char packbuffer[PACKBUFFERSIZE];
1860    unsigned nunits = PACKBUFFERSIZE >> 2;
1861
1862    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
1863	doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
1864    }
1865    if (len) doData32 (dpy, data, len, packbuffer);
1866}
1867
1868#endif /* WORD64 */
1869
1870
1871/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
1872 * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
1873 *
1874 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
1875 *       to have sufficient information for interfacing to the network,
1876 *       and so, you may be better off using gethostname (if it exists).
1877 */
1878
1879#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
1880#define NEED_UTSNAME
1881#include <sys/utsname.h>
1882#else
1883#ifdef HAVE_UNISTD_H
1884#include <unistd.h>
1885#endif
1886#endif
1887
1888/*
1889 * _XGetHostname - similar to gethostname but allows special processing.
1890 */
1891int _XGetHostname (
1892    char *buf,
1893    int maxlen)
1894{
1895    int len;
1896
1897#ifdef NEED_UTSNAME
1898    struct utsname name;
1899
1900    if (maxlen <= 0 || buf == NULL)
1901	return 0;
1902
1903    uname (&name);
1904    len = strlen (name.nodename);
1905    if (len >= maxlen) len = maxlen - 1;
1906    strncpy (buf, name.nodename, len);
1907    buf[len] = '\0';
1908#else
1909    if (maxlen <= 0 || buf == NULL)
1910	return 0;
1911
1912    buf[0] = '\0';
1913    (void) gethostname (buf, maxlen);
1914    buf [maxlen - 1] = '\0';
1915    len = strlen(buf);
1916#endif /* NEED_UTSNAME */
1917    return len;
1918}
1919
1920
1921/*
1922 * _XScreenOfWindow - get the Screen of a given window
1923 */
1924
1925Screen *_XScreenOfWindow(Display *dpy, Window w)
1926{
1927    register int i;
1928    Window root;
1929    int x, y;				/* dummy variables */
1930    unsigned int width, height, bw, depth;  /* dummy variables */
1931
1932    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
1933		      &bw, &depth) == False) {
1934	return NULL;
1935    }
1936    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
1937	if (root == RootWindow (dpy, i)) {
1938	    return ScreenOfDisplay (dpy, i);
1939	}
1940    }
1941    return NULL;
1942}
1943
1944
1945#if defined(WIN32)
1946
1947/*
1948 * These functions are intended to be used internally to Xlib only.
1949 * These functions will always prefix the path with a DOS drive in the
1950 * form "<drive-letter>:". As such, these functions are only suitable
1951 * for use by Xlib function that supply a root-based path to some
1952 * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
1953 * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
1954 */
1955
1956static int access_file (path, pathbuf, len_pathbuf, pathret)
1957    char* path;
1958    char* pathbuf;
1959    int len_pathbuf;
1960    char** pathret;
1961{
1962    if (access (path, F_OK) == 0) {
1963	if (strlen (path) < len_pathbuf)
1964	    *pathret = pathbuf;
1965	else
1966	    *pathret = Xmalloc (strlen (path) + 1);
1967	if (*pathret) {
1968	    strcpy (*pathret, path);
1969	    return 1;
1970	}
1971    }
1972    return 0;
1973}
1974
1975static int AccessFile (path, pathbuf, len_pathbuf, pathret)
1976    char* path;
1977    char* pathbuf;
1978    int len_pathbuf;
1979    char** pathret;
1980{
1981    unsigned long drives;
1982    int i, len;
1983    char* drive;
1984    char buf[MAX_PATH];
1985    char* bufp;
1986
1987    /* just try the "raw" name first and see if it works */
1988    if (access_file (path, pathbuf, len_pathbuf, pathret))
1989	return 1;
1990
1991    /* try the places set in the environment */
1992    drive = getenv ("_XBASEDRIVE");
1993#ifdef __UNIXOS2__
1994    if (!drive)
1995	drive = getenv ("X11ROOT");
1996#endif
1997    if (!drive)
1998	drive = "C:";
1999    len = strlen (drive) + strlen (path);
2000    if (len < MAX_PATH) bufp = buf;
2001    else bufp = Xmalloc (len + 1);
2002    strcpy (bufp, drive);
2003    strcat (bufp, path);
2004    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
2005	if (bufp != buf) Xfree (bufp);
2006	return 1;
2007    }
2008
2009#ifndef __UNIXOS2__
2010    /* one last place to look */
2011    drive = getenv ("HOMEDRIVE");
2012    if (drive) {
2013	len = strlen (drive) + strlen (path);
2014	if (len < MAX_PATH) bufp = buf;
2015	else bufp = Xmalloc (len + 1);
2016	strcpy (bufp, drive);
2017	strcat (bufp, path);
2018	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
2019	    if (bufp != buf) Xfree (bufp);
2020	    return 1;
2021	}
2022    }
2023
2024    /* tried everywhere else, go fishing */
2025#define C_DRIVE ('C' - 'A')
2026#define Z_DRIVE ('Z' - 'A')
2027    /* does OS/2 (with or with gcc-emx) have getdrives? */
2028    drives = _getdrives ();
2029    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
2030	if ((1 << i) & drives) {
2031	    len = 2 + strlen (path);
2032	    if (len < MAX_PATH) bufp = buf;
2033	    else bufp = Xmalloc (len + 1);
2034	    *bufp = 'A' + i;
2035	    *(bufp + 1) = ':';
2036	    *(bufp + 2) = '\0';
2037	    strcat (bufp, path);
2038	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
2039		if (bufp != buf) Xfree (bufp);
2040		return 1;
2041	    }
2042	}
2043    }
2044#endif
2045    return 0;
2046}
2047
2048int _XOpenFile(path, flags)
2049    _Xconst char* path;
2050    int flags;
2051{
2052    char buf[MAX_PATH];
2053    char* bufp = NULL;
2054    int ret = -1;
2055    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
2056
2057    if (AccessFile (path, buf, MAX_PATH, &bufp))
2058	ret = open (bufp, flags);
2059
2060    (void) SetErrorMode (olderror);
2061
2062    if (bufp != buf) Xfree (bufp);
2063
2064    return ret;
2065}
2066
2067int _XOpenFileMode(path, flags, mode)
2068    _Xconst char* path;
2069    int flags;
2070    mode_t mode;
2071{
2072    char buf[MAX_PATH];
2073    char* bufp = NULL;
2074    int ret = -1;
2075    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
2076
2077    if (AccessFile (path, buf, MAX_PATH, &bufp))
2078	ret = open (bufp, flags, mode);
2079
2080    (void) SetErrorMode (olderror);
2081
2082    if (bufp != buf) Xfree (bufp);
2083
2084    return ret;
2085}
2086
2087void* _XFopenFile(path, mode)
2088    _Xconst char* path;
2089    _Xconst char* mode;
2090{
2091    char buf[MAX_PATH];
2092    char* bufp = NULL;
2093    void* ret = NULL;
2094    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
2095
2096    if (AccessFile (path, buf, MAX_PATH, &bufp))
2097	ret = fopen (bufp, mode);
2098
2099    (void) SetErrorMode (olderror);
2100
2101    if (bufp != buf) Xfree (bufp);
2102
2103    return ret;
2104}
2105
2106int _XAccessFile(path)
2107    _Xconst char* path;
2108{
2109    char buf[MAX_PATH];
2110    char* bufp;
2111    int ret = -1;
2112    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
2113
2114    ret = AccessFile (path, buf, MAX_PATH, &bufp);
2115
2116    (void) SetErrorMode (olderror);
2117
2118    if (bufp != buf) Xfree (bufp);
2119
2120    return ret;
2121}
2122
2123#endif
2124
2125#ifdef WIN32
2126#undef _Xdebug
2127int _Xdebug = 0;
2128int *_Xdebug_p = &_Xdebug;
2129void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
2130void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
2131void (**_XLockMutex_fn_p)(LockInfoPtr
2132#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
2133    , char * /* file */
2134    , int /* line */
2135#endif
2136        ) = &_XLockMutex_fn;
2137void (**_XUnlockMutex_fn_p)(LockInfoPtr
2138#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
2139    , char * /* file */
2140    , int /* line */
2141#endif
2142        ) = &_XUnlockMutex_fn;
2143LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
2144#endif
2145