XlibInt.c revision c17aa6b1
11ab64890Smrg/*
21ab64890Smrg
31ab64890SmrgCopyright 1985, 1986, 1987, 1998  The Open Group
41ab64890Smrg
51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
71ab64890Smrgthe above copyright notice appear in all copies and that both that
81ab64890Smrgcopyright notice and this permission notice appear in supporting
91ab64890Smrgdocumentation.
101ab64890Smrg
111ab64890SmrgThe above copyright notice and this permission notice shall be included
121ab64890Smrgin all copies or substantial portions of the Software.
131ab64890Smrg
141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE.
211ab64890Smrg
221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall
231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or
241ab64890Smrgother dealings in this Software without prior written authorization
251ab64890Smrgfrom The Open Group.
261ab64890Smrg
271ab64890Smrg*/
281ab64890Smrg
291ab64890Smrg/*
301ab64890Smrg *	XlibInt.c - Internal support routines for the C subroutine
311ab64890Smrg *	interface library (Xlib) to the X Window System Protocol V11.0.
321ab64890Smrg */
331ab64890Smrg
341ab64890Smrg#ifdef WIN32
351ab64890Smrg#define _XLIBINT_
361ab64890Smrg#endif
371ab64890Smrg#ifdef HAVE_CONFIG_H
381ab64890Smrg#include <config.h>
391ab64890Smrg#endif
401ab64890Smrg#include "Xlibint.h"
4161b2299dSmrg#include "Xprivate.h"
421ab64890Smrg#include <X11/Xpoll.h>
4361b2299dSmrg#include <assert.h>
441ab64890Smrg#include <stdio.h>
451ab64890Smrg#ifdef WIN32
461ab64890Smrg#include <direct.h>
471ab64890Smrg#endif
481ab64890Smrg
491ab64890Smrg#ifdef XTHREADS
501ab64890Smrg#include "locking.h"
511ab64890Smrg
521ab64890Smrg/* these pointers get initialized by XInitThreads */
531ab64890SmrgLockInfoPtr _Xglobal_lock = NULL;
541ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
551ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
561ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
571ab64890Smrgvoid (*_XLockMutex_fn)(
581ab64890Smrg    LockInfoPtr /* lock */
591ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
601ab64890Smrg    , char * /* file */
611ab64890Smrg    , int /* line */
621ab64890Smrg#endif
631ab64890Smrg    ) = NULL;
641ab64890Smrgvoid (*_XUnlockMutex_fn)(
651ab64890Smrg    LockInfoPtr /* lock */
661ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
671ab64890Smrg    , char * /* file */
681ab64890Smrg    , int /* line */
691ab64890Smrg#endif
701ab64890Smrg    ) = NULL;
711ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL;
721ab64890Smrg
731ab64890Smrg#define XThread_Self()	((*_Xthread_self_fn)())
741ab64890Smrg
75295fb823Smrg#endif /* XTHREADS */
761ab64890Smrg
771ab64890Smrg/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
781ab64890Smrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN
791ab64890Smrg */
801ab64890Smrg#ifdef WIN32
811ab64890Smrg#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
821ab64890Smrg#else
831ab64890Smrg#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
841ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
851ab64890Smrg#else
861ab64890Smrg#if defined(EAGAIN) && defined(EWOULDBLOCK)
871ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
881ab64890Smrg#else
891ab64890Smrg#ifdef EAGAIN
901ab64890Smrg#define ETEST() (errno == EAGAIN)
911ab64890Smrg#else
921ab64890Smrg#define ETEST() (errno == EWOULDBLOCK)
931ab64890Smrg#endif /* EAGAIN */
941ab64890Smrg#endif /* EAGAIN && EWOULDBLOCK */
951ab64890Smrg#endif /* __CYGWIN__ */
961ab64890Smrg#endif /* WIN32 */
971ab64890Smrg
981ab64890Smrg#ifdef WIN32
991ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err)
1001ab64890Smrg#define ESET(val) WSASetLastError(val)
1011ab64890Smrg#else
1021ab64890Smrg#ifdef __UNIXOS2__
1031ab64890Smrg#define ECHECK(err) (errno == err)
1041ab64890Smrg#define ESET(val)
1051ab64890Smrg#else
1061ab64890Smrg#define ECHECK(err) (errno == err)
1071ab64890Smrg#define ESET(val) errno = val
1081ab64890Smrg#endif
1091ab64890Smrg#endif
1101ab64890Smrg
1111ab64890Smrg#if defined(LOCALCONN) || defined(LACHMAN)
1121ab64890Smrg#ifdef EMSGSIZE
1131ab64890Smrg#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
1141ab64890Smrg#else
1151ab64890Smrg#define ESZTEST() ECHECK(ERANGE)
1161ab64890Smrg#endif
1171ab64890Smrg#else
1181ab64890Smrg#ifdef EMSGSIZE
1191ab64890Smrg#define ESZTEST() ECHECK(EMSGSIZE)
1201ab64890Smrg#endif
1211ab64890Smrg#endif
1221ab64890Smrg
1231ab64890Smrg#ifdef __UNIXOS2__
1241ab64890Smrg#include <limits.h>
1251ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX
1261ab64890Smrg#endif
1271ab64890Smrg
1281ab64890Smrg/*
1291ab64890Smrg * The following routines are internal routines used by Xlib for protocol
1301ab64890Smrg * packet transmission and reception.
1311ab64890Smrg *
1321ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
1331ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
1341ab64890Smrg *
1351ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
1361ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
1371ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
1381ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
1391ab64890Smrg *
1401ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
14161b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
1421ab64890Smrg * return anything.  Whenever possible routines that create objects return
1431ab64890Smrg * the object they have created.
1441ab64890Smrg */
1451ab64890Smrg
1461ab64890Smrg#define POLLFD_CACHE_SIZE 5
1471ab64890Smrg
1481ab64890Smrg/* initialize the struct array passed to poll() below */
1491ab64890SmrgBool _XPollfdCacheInit(
1501ab64890Smrg    Display *dpy)
1511ab64890Smrg{
1521ab64890Smrg#ifdef USE_POLL
1531ab64890Smrg    struct pollfd *pfp;
1541ab64890Smrg
1551ab64890Smrg    pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1561ab64890Smrg    if (!pfp)
1571ab64890Smrg	return False;
1581ab64890Smrg    pfp[0].fd = dpy->fd;
1591ab64890Smrg    pfp[0].events = POLLIN;
1601ab64890Smrg
1611ab64890Smrg    dpy->filedes = (XPointer)pfp;
1621ab64890Smrg#endif
1631ab64890Smrg    return True;
1641ab64890Smrg}
1651ab64890Smrg
1661ab64890Smrgvoid _XPollfdCacheAdd(
1671ab64890Smrg    Display *dpy,
1681ab64890Smrg    int fd)
1691ab64890Smrg{
1701ab64890Smrg#ifdef USE_POLL
1711ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1721ab64890Smrg
1731ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1741ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
1751ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
1761ab64890Smrg    }
1771ab64890Smrg#endif
1781ab64890Smrg}
1791ab64890Smrg
1801ab64890Smrg/* ARGSUSED */
1811ab64890Smrgvoid _XPollfdCacheDel(
1821ab64890Smrg    Display *dpy,
1831ab64890Smrg    int fd)			/* not used */
1841ab64890Smrg{
1851ab64890Smrg#ifdef USE_POLL
1861ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1871ab64890Smrg    struct _XConnectionInfo *conni;
1881ab64890Smrg
1891ab64890Smrg    /* just recalculate whole list */
1901ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1911ab64890Smrg	int loc = 1;
1921ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1931ab64890Smrg	    pfp[loc].fd = conni->fd;
1941ab64890Smrg	    pfp[loc].events = POLLIN;
1951ab64890Smrg	    loc++;
1961ab64890Smrg	}
1971ab64890Smrg    }
1981ab64890Smrg#endif
1991ab64890Smrg}
2001ab64890Smrg
20161b2299dSmrgstatic int sync_hazard(Display *dpy)
20261b2299dSmrg{
20361b2299dSmrg    unsigned long span = dpy->request - dpy->last_request_read;
20461b2299dSmrg    unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
20561b2299dSmrg    return span >= 65535 - hazard - 10;
20661b2299dSmrg}
20761b2299dSmrg
2081ab64890Smrgstatic
20988de56ccSmrgvoid sync_while_locked(Display *dpy)
21088de56ccSmrg{
21188de56ccSmrg#ifdef XTHREADS
21288de56ccSmrg    if (dpy->lock)
21388de56ccSmrg        (*dpy->lock->user_lock_display)(dpy);
21488de56ccSmrg#endif
21588de56ccSmrg    UnlockDisplay(dpy);
21688de56ccSmrg    SyncHandle();
21788de56ccSmrg    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
21888de56ccSmrg#ifdef XTHREADS
21988de56ccSmrg    if (dpy->lock)
22088de56ccSmrg        (*dpy->lock->user_unlock_display)(dpy);
22188de56ccSmrg#endif
22288de56ccSmrg}
22388de56ccSmrg
22488de56ccSmrgvoid _XSeqSyncFunction(
2251ab64890Smrg    register Display *dpy)
2261ab64890Smrg{
2271ab64890Smrg    xGetInputFocusReply rep;
2281ab64890Smrg    register xReq *req;
2291ab64890Smrg
23061b2299dSmrg    if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
2311ab64890Smrg	GetEmptyReq(GetInputFocus, req);
2321ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
23388de56ccSmrg	sync_while_locked(dpy);
23461b2299dSmrg    } else if (sync_hazard(dpy))
23561b2299dSmrg	_XSetPrivSyncFunction(dpy);
2361ab64890Smrg}
2371ab64890Smrg
23888de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
23961b2299dSmrgstatic int
24061b2299dSmrg_XPrivSyncFunction (Display *dpy)
24161b2299dSmrg{
242e0787e08Smrg#ifdef XTHREADS
24388de56ccSmrg    assert(!dpy->lock_fns);
24488de56ccSmrg#endif
24561b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
24661b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
24761b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
24861b2299dSmrg    dpy->savedsynchandler = NULL;
24961b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
25088de56ccSmrg    if(dpy->synchandler)
25188de56ccSmrg        dpy->synchandler(dpy);
25261b2299dSmrg    _XIDHandler(dpy);
25361b2299dSmrg    _XSeqSyncFunction(dpy);
25461b2299dSmrg    return 0;
25561b2299dSmrg}
25661b2299dSmrg
25761b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
2581ab64890Smrg{
25988de56ccSmrg#ifdef XTHREADS
26088de56ccSmrg    if (dpy->lock_fns)
26188de56ccSmrg        return;
26288de56ccSmrg#endif
26361b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
2641ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
26561b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
2661ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
2671ab64890Smrg    }
2681ab64890Smrg}
2691ab64890Smrg
27061b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
27161b2299dSmrg{
27261b2299dSmrg    if (sync_hazard(dpy))
27361b2299dSmrg	_XSetPrivSyncFunction (dpy);
27461b2299dSmrg}
27561b2299dSmrg
2761ab64890Smrg#ifdef LONG64
2771ab64890Smrgvoid _XRead32(
2781ab64890Smrg    Display *dpy,
2791ab64890Smrg    register long *data,
2801ab64890Smrg    long len)
2811ab64890Smrg{
2821ab64890Smrg    register int *buf;
2831ab64890Smrg    register long i;
2841ab64890Smrg
2851ab64890Smrg    if (len) {
2861ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
2871ab64890Smrg	i = len >> 2;
2881ab64890Smrg	buf = (int *)data + i;
2891ab64890Smrg	data += i;
2901ab64890Smrg	while (--i >= 0)
2911ab64890Smrg	    *--data = *--buf;
2921ab64890Smrg    }
2931ab64890Smrg}
2941ab64890Smrg#endif /* LONG64 */
2951ab64890Smrg
2961ab64890Smrg#ifdef WORD64
2971ab64890Smrg
2981ab64890Smrg/*
2991ab64890Smrg * XXX This is a *really* stupid way of doing this....
3001ab64890Smrg * PACKBUFFERSIZE must be a multiple of 4.
3011ab64890Smrg */
3021ab64890Smrg
3031ab64890Smrg#define PACKBUFFERSIZE 4096
3041ab64890Smrg
3051ab64890Smrg
3061ab64890Smrg/*
3071ab64890Smrg * _XRead32 - Read bytes from the socket unpacking each 32 bits
3081ab64890Smrg *            into a long (64 bits on a CRAY computer).
30961b2299dSmrg *
3101ab64890Smrg */
3111ab64890Smrgstatic void _doXRead32(
3121ab64890Smrg        register Display *dpy,
3131ab64890Smrg        register long *data
3141ab64890Smrg        register long size,
3151ab64890Smrg	register char *packbuffer)
3161ab64890Smrg{
3171ab64890Smrg long *lpack,*lp;
3181ab64890Smrg long mask32 = 0x00000000ffffffff;
3191ab64890Smrg long maskw, nwords, i, bits;
3201ab64890Smrg
3211ab64890Smrg        _XReadPad (dpy, packbuffer, size);
3221ab64890Smrg
3231ab64890Smrg        lp = data;
3241ab64890Smrg        lpack = (long *) packbuffer;
3251ab64890Smrg        nwords = size >> 2;
3261ab64890Smrg        bits = 32;
3271ab64890Smrg
3281ab64890Smrg        for(i=0;i<nwords;i++){
3291ab64890Smrg            maskw = mask32 << bits;
3301ab64890Smrg           *lp++ = ( *lpack & maskw ) >> bits;
3311ab64890Smrg            bits = bits ^32;
3321ab64890Smrg            if(bits){
3331ab64890Smrg               lpack++;
3341ab64890Smrg            }
3351ab64890Smrg        }
3361ab64890Smrg}
3371ab64890Smrg
3381ab64890Smrgvoid _XRead32(
3391ab64890Smrg    Display *dpy,
3401ab64890Smrg    long *data,
3411ab64890Smrg    long len)
3421ab64890Smrg{
3431ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
3441ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 2;
3451ab64890Smrg
3461ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3471ab64890Smrg	_doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
3481ab64890Smrg    }
3491ab64890Smrg    if (len) _doXRead32 (dpy, data, len, packbuffer);
3501ab64890Smrg}
3511ab64890Smrg
3521ab64890Smrg
3531ab64890Smrg
3541ab64890Smrg/*
3551ab64890Smrg * _XRead16 - Read bytes from the socket unpacking each 16 bits
3561ab64890Smrg *            into a long (64 bits on a CRAY computer).
3571ab64890Smrg *
3581ab64890Smrg */
3591ab64890Smrgstatic _doXRead16(
3601ab64890Smrg        register Display *dpy,
3611ab64890Smrg        register short *data,
3621ab64890Smrg        register long size,
3631ab64890Smrg	char *packbuffer)
3641ab64890Smrg{
3651ab64890Smrg	long *lpack,*lp;
3661ab64890Smrg	long mask16 = 0x000000000000ffff;
3671ab64890Smrg	long maskw, nwords, i, bits;
3681ab64890Smrg
3691ab64890Smrg        (void) _XRead(dpy,packbuffer,size);	/* don't do a padded read... */
3701ab64890Smrg
3711ab64890Smrg        lp = (long *) data;
3721ab64890Smrg        lpack = (long *) packbuffer;
3731ab64890Smrg        nwords = size >> 1;  /* number of 16 bit words to be unpacked */
3741ab64890Smrg        bits = 48;
3751ab64890Smrg        for(i=0;i<nwords;i++){
3761ab64890Smrg            maskw = mask16 << bits;
3771ab64890Smrg           *lp++ = ( *lpack & maskw ) >> bits;
3781ab64890Smrg            bits -= 16;
3791ab64890Smrg            if(bits < 0){
3801ab64890Smrg               lpack++;
3811ab64890Smrg               bits = 48;
3821ab64890Smrg            }
3831ab64890Smrg        }
3841ab64890Smrg}
3851ab64890Smrg
3861ab64890Smrgvoid _XRead16(
3871ab64890Smrg    Display *dpy,
3881ab64890Smrg    short *data,
3891ab64890Smrg    long len)
3901ab64890Smrg{
3911ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
3921ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 1;
3931ab64890Smrg
3941ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
3951ab64890Smrg	_doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
3961ab64890Smrg    }
3971ab64890Smrg    if (len) _doXRead16 (dpy, data, len, packbuffer);
3981ab64890Smrg}
3991ab64890Smrg
4001ab64890Smrgvoid _XRead16Pad(
4011ab64890Smrg    Display *dpy,
4021ab64890Smrg    short *data,
4031ab64890Smrg    long size)
4041ab64890Smrg{
4051ab64890Smrg    int slop = (size & 3);
4061ab64890Smrg    short slopbuf[3];
4071ab64890Smrg
4081ab64890Smrg    _XRead16 (dpy, data, size);
4091ab64890Smrg    if (slop > 0) {
4101ab64890Smrg	_XRead16 (dpy, slopbuf, 4 - slop);
4111ab64890Smrg    }
4121ab64890Smrg}
4131ab64890Smrg#endif /* WORD64 */
4141ab64890Smrg
4151ab64890Smrg/*
4161ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
4171ab64890Smrg * We have three values that will march along, with the following invariant:
4181ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
4191ab64890Smrg * We have to keep
4201ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
4211ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
4221ab64890Smrg * by forcing syncs when we get close.
4231ab64890Smrg */
4241ab64890Smrg
4251ab64890Smrgunsigned long
4261ab64890Smrg_XSetLastRequestRead(
4271ab64890Smrg    register Display *dpy,
4281ab64890Smrg    register xGenericReply *rep)
4291ab64890Smrg{
4301ab64890Smrg    register unsigned long	newseq, lastseq;
4311ab64890Smrg
4321ab64890Smrg    lastseq = dpy->last_request_read;
4331ab64890Smrg    /*
4341ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
4351ab64890Smrg     * to immediately follow another event, except when generated via
4361ab64890Smrg     * SendEvent (hmmm).
4371ab64890Smrg     */
4381ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
4391ab64890Smrg	return(lastseq);
4401ab64890Smrg
4411ab64890Smrg    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
4421ab64890Smrg
4431ab64890Smrg    if (newseq < lastseq) {
4441ab64890Smrg	newseq += 0x10000;
4451ab64890Smrg	if (newseq > dpy->request) {
44661b2299dSmrg	    (void) fprintf (stderr,
4471ab64890Smrg	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
44861b2299dSmrg			    newseq, dpy->request,
4491ab64890Smrg			    (unsigned int) rep->type);
4501ab64890Smrg	    newseq -= 0x10000;
4511ab64890Smrg	}
4521ab64890Smrg    }
4531ab64890Smrg
4541ab64890Smrg    dpy->last_request_read = newseq;
4551ab64890Smrg    return(newseq);
4561ab64890Smrg}
4571ab64890Smrg
4581ab64890Smrg/*
4591ab64890Smrg * Support for internal connections, such as an IM might use.
4601ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
4611ab64890Smrg */
4621ab64890Smrg
4631ab64890Smrg/* _XRegisterInternalConnection
4641ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
4651ab64890Smrg * include in its select/poll mask must call this function to register the
4661ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
4671ab64890Smrg * will also be called.
4681ab64890Smrg *
4691ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
4701ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
4711ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
4721ab64890Smrg * which will call the associated callback.
4731ab64890Smrg *
4741ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
4751ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
4761ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
4771ab64890Smrg * to be called when fds are registered or unregistered.
4781ab64890Smrg *
4791ab64890Smrg * Returns True if registration succeeded, False if not, typically
4801ab64890Smrg * because could not allocate memory.
4811ab64890Smrg * Assumes Display locked when called.
4821ab64890Smrg */
4831ab64890SmrgStatus
4841ab64890Smrg_XRegisterInternalConnection(
4851ab64890Smrg    Display* dpy,
4861ab64890Smrg    int fd,
4871ab64890Smrg    _XInternalConnectionProc callback,
4881ab64890Smrg    XPointer call_data
4891ab64890Smrg)
4901ab64890Smrg{
4911ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
4921ab64890Smrg    struct _XConnWatchInfo *watchers;
4931ab64890Smrg    XPointer *wd;
4941ab64890Smrg
4951ab64890Smrg    new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
4961ab64890Smrg    if (!new_conni)
4971ab64890Smrg	return 0;
4981ab64890Smrg    new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
4991ab64890Smrg    if (!new_conni->watch_data) {
5001ab64890Smrg	Xfree(new_conni);
5011ab64890Smrg	return 0;
5021ab64890Smrg    }
5031ab64890Smrg    new_conni->fd = fd;
5041ab64890Smrg    new_conni->read_callback = callback;
5051ab64890Smrg    new_conni->call_data = call_data;
5061ab64890Smrg    new_conni->next = NULL;
5071ab64890Smrg    /* link new structure onto end of list */
5081ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
5091ab64890Smrg	;
5101ab64890Smrg    *iptr = new_conni;
5111ab64890Smrg    dpy->im_fd_length++;
5121ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
5131ab64890Smrg
5141ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
5151ab64890Smrg	 watchers;
5161ab64890Smrg	 watchers=watchers->next, wd++) {
5171ab64890Smrg	*wd = NULL;		/* for cleanliness */
5181ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
5191ab64890Smrg    }
5201ab64890Smrg
5211ab64890Smrg    return 1;
5221ab64890Smrg}
5231ab64890Smrg
5241ab64890Smrg/* _XUnregisterInternalConnection
5251ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
5261ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
5271ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
5281ab64890Smrg * will also be called.
5291ab64890Smrg *
5301ab64890Smrg * Assumes Display locked when called.
5311ab64890Smrg */
5321ab64890Smrgvoid
5331ab64890Smrg_XUnregisterInternalConnection(
5341ab64890Smrg    Display* dpy,
5351ab64890Smrg    int fd
5361ab64890Smrg)
5371ab64890Smrg{
5381ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
5391ab64890Smrg    struct _XConnWatchInfo *watch;
5401ab64890Smrg    XPointer *wd;
5411ab64890Smrg
5421ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
5431ab64890Smrg	 prev = &info_list->next) {
5441ab64890Smrg	if (info_list->fd == fd) {
5451ab64890Smrg	    *prev = info_list->next;
5461ab64890Smrg	    dpy->im_fd_length--;
5471ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
5481ab64890Smrg		 watch;
5491ab64890Smrg		 watch=watch->next, wd++) {
5501ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
5511ab64890Smrg	    }
5521ab64890Smrg	    if (info_list->watch_data)
5531ab64890Smrg		Xfree (info_list->watch_data);
5541ab64890Smrg	    Xfree (info_list);
5551ab64890Smrg	    break;
5561ab64890Smrg	}
5571ab64890Smrg    }
5581ab64890Smrg    _XPollfdCacheDel(dpy, fd);
5591ab64890Smrg}
5601ab64890Smrg
5611ab64890Smrg/* XInternalConnectionNumbers
5621ab64890Smrg * Returns an array of fds and an array of corresponding call data.
5631ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
5641ab64890Smrg * will be used instead of this function to discover
5651ab64890Smrg * additional fds to include in the select/poll mask.
5661ab64890Smrg *
5671ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
5681ab64890Smrg * with Xfree;
5691ab64890Smrg */
5701ab64890SmrgStatus
5711ab64890SmrgXInternalConnectionNumbers(
5721ab64890Smrg    Display *dpy,
5731ab64890Smrg    int **fd_return,
5741ab64890Smrg    int *count_return
5751ab64890Smrg)
5761ab64890Smrg{
5771ab64890Smrg    int count;
5781ab64890Smrg    struct _XConnectionInfo *info_list;
5791ab64890Smrg    int *fd_list;
5801ab64890Smrg
5811ab64890Smrg    LockDisplay(dpy);
5821ab64890Smrg    count = 0;
5831ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
5841ab64890Smrg	count++;
5851ab64890Smrg    fd_list = (int*) Xmalloc (count * sizeof(int));
5861ab64890Smrg    if (!fd_list) {
5871ab64890Smrg	UnlockDisplay(dpy);
5881ab64890Smrg	return 0;
5891ab64890Smrg    }
5901ab64890Smrg    count = 0;
5911ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5921ab64890Smrg	fd_list[count] = info_list->fd;
5931ab64890Smrg	count++;
5941ab64890Smrg    }
5951ab64890Smrg    UnlockDisplay(dpy);
5961ab64890Smrg
5971ab64890Smrg    *fd_return = fd_list;
5981ab64890Smrg    *count_return = count;
5991ab64890Smrg    return 1;
6001ab64890Smrg}
6011ab64890Smrg
6021ab64890Smrgvoid _XProcessInternalConnection(
6031ab64890Smrg    Display *dpy,
6041ab64890Smrg    struct _XConnectionInfo *conn_info)
6051ab64890Smrg{
6061ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
6071ab64890Smrg    UnlockDisplay(dpy);
6081ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
6091ab64890Smrg    LockDisplay(dpy);
6101ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
6111ab64890Smrg}
6121ab64890Smrg
6131ab64890Smrg/* XProcessInternalConnection
6141ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
6151ab64890Smrg * for this fd.
6161ab64890Smrg * The Display is NOT locked during the call.
6171ab64890Smrg */
6181ab64890Smrgvoid
6191ab64890SmrgXProcessInternalConnection(
6201ab64890Smrg    Display* dpy,
6211ab64890Smrg    int fd
6221ab64890Smrg)
6231ab64890Smrg{
6241ab64890Smrg    struct _XConnectionInfo *info_list;
6251ab64890Smrg
6261ab64890Smrg    LockDisplay(dpy);
6271ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
6281ab64890Smrg	if (info_list->fd == fd) {
6291ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
6301ab64890Smrg	    break;
6311ab64890Smrg	}
6321ab64890Smrg    }
6331ab64890Smrg    UnlockDisplay(dpy);
6341ab64890Smrg}
6351ab64890Smrg
6361ab64890Smrg/* XAddConnectionWatch
6371ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
6381ab64890Smrg * or _XUnregisterInternalConnection is called.
6391ab64890Smrg * Callbacks are called with the Display locked.
6401ab64890Smrg * If any connections are already registered, the callback is immediately
6411ab64890Smrg * called for each of them.
6421ab64890Smrg */
6431ab64890SmrgStatus
6441ab64890SmrgXAddConnectionWatch(
6451ab64890Smrg    Display* dpy,
6461ab64890Smrg    XConnectionWatchProc callback,
6471ab64890Smrg    XPointer client_data
6481ab64890Smrg)
6491ab64890Smrg{
6501ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
6511ab64890Smrg    struct _XConnectionInfo *info_list;
6521ab64890Smrg    XPointer *wd_array;
6531ab64890Smrg
6541ab64890Smrg    LockDisplay(dpy);
6551ab64890Smrg
6561ab64890Smrg    /* allocate new watch data */
6571ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
6581ab64890Smrg	wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
6591ab64890Smrg					(dpy->watcher_count + 1) *
6601ab64890Smrg					sizeof(XPointer));
6611ab64890Smrg	if (!wd_array) {
6621ab64890Smrg	    UnlockDisplay(dpy);
6631ab64890Smrg	    return 0;
6641ab64890Smrg	}
665c17aa6b1Smrg	info_list->watch_data = wd_array;
6661ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
6671ab64890Smrg    }
6681ab64890Smrg
6691ab64890Smrg    new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
6701ab64890Smrg    if (!new_watcher) {
6711ab64890Smrg	UnlockDisplay(dpy);
6721ab64890Smrg	return 0;
6731ab64890Smrg    }
6741ab64890Smrg    new_watcher->fn = callback;
6751ab64890Smrg    new_watcher->client_data = client_data;
6761ab64890Smrg    new_watcher->next = NULL;
6771ab64890Smrg
6781ab64890Smrg    /* link new structure onto end of list */
6791ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
6801ab64890Smrg	;
6811ab64890Smrg    *wptr = new_watcher;
6821ab64890Smrg    dpy->watcher_count++;
6831ab64890Smrg
6841ab64890Smrg    /* call new watcher on all currently registered fds */
6851ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
6861ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
6871ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
6881ab64890Smrg    }
6891ab64890Smrg
6901ab64890Smrg    UnlockDisplay(dpy);
6911ab64890Smrg    return 1;
6921ab64890Smrg}
6931ab64890Smrg
6941ab64890Smrg/* XRemoveConnectionWatch
6951ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
6961ab64890Smrg * Both callback and client_data must match what was passed to
6971ab64890Smrg * XAddConnectionWatch.
69861b2299dSmrg */
6991ab64890Smrgvoid
7001ab64890SmrgXRemoveConnectionWatch(
7011ab64890Smrg    Display* dpy,
7021ab64890Smrg    XConnectionWatchProc callback,
7031ab64890Smrg    XPointer client_data
7041ab64890Smrg)
7051ab64890Smrg{
7061ab64890Smrg    struct _XConnWatchInfo *watch;
7071ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
7081ab64890Smrg    struct _XConnectionInfo *conni;
7091ab64890Smrg    int counter = 0;
7101ab64890Smrg
7111ab64890Smrg    LockDisplay(dpy);
7121ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
7131ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
7141ab64890Smrg	    if (previous)
7151ab64890Smrg		previous->next = watch->next;
7161ab64890Smrg	    else
7171ab64890Smrg		dpy->conn_watchers = watch->next;
7181ab64890Smrg	    Xfree (watch);
7191ab64890Smrg	    dpy->watcher_count--;
7201ab64890Smrg	    /* remove our watch_data for each connection */
7211ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
7221ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
7231ab64890Smrg		/* overlapping */
7241ab64890Smrg		memmove(conni->watch_data+counter,
7251ab64890Smrg			conni->watch_data+counter+1,
7261ab64890Smrg			dpy->watcher_count - counter);
7271ab64890Smrg	    }
7281ab64890Smrg	    break;
7291ab64890Smrg	}
7301ab64890Smrg	previous = watch;
7311ab64890Smrg	counter++;
7321ab64890Smrg    }
7331ab64890Smrg    UnlockDisplay(dpy);
7341ab64890Smrg}
7351ab64890Smrg
7361ab64890Smrg/* end of internal connections support */
7371ab64890Smrg
738b4ee4795Smrg/* Cookie jar implementation
739b4ee4795Smrg   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
740b4ee4795Smrg   them in the normal EQ. _XStoreEvent returns the cookie event (minus
741b4ee4795Smrg   data pointer) and adds it to the cookiejar. _XDeq just removes
742b4ee4795Smrg   the entry like any other event but resets the data pointer for
743b4ee4795Smrg   cookie events (to avoid double-free, the memory is re-used by Xlib).
744b4ee4795Smrg
745b4ee4795Smrg   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
746b4ee4795Smrg   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
747b4ee4795Smrg   (called by XNextEvent).
748b4ee4795Smrg
749b4ee4795Smrg   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
750b4ee4795Smrg   normal EQ.
751b4ee4795Smrg */
752b4ee4795Smrg
753b4ee4795Smrg#include "utlist.h"
754b4ee4795Smrgstruct stored_event {
755b4ee4795Smrg    XGenericEventCookie ev;
756b4ee4795Smrg    struct stored_event *prev;
757b4ee4795Smrg    struct stored_event *next;
758b4ee4795Smrg};
759b4ee4795Smrg
760b4ee4795SmrgBool
761b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev)
762b4ee4795Smrg{
763b4ee4795Smrg    return (ev->xcookie.type == GenericEvent &&
764b4ee4795Smrg	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
765b4ee4795Smrg}
766b4ee4795Smrg
767b4ee4795Smrg/**
768b4ee4795Smrg * Free all events in the event list.
769b4ee4795Smrg */
770b4ee4795Smrgvoid
771b4ee4795Smrg_XFreeEventCookies(Display *dpy)
772b4ee4795Smrg{
773b4ee4795Smrg    struct stored_event **head, *e, *tmp;
774b4ee4795Smrg
775b4ee4795Smrg    if (!dpy->cookiejar)
776b4ee4795Smrg        return;
777b4ee4795Smrg
778b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
779b4ee4795Smrg
780b4ee4795Smrg    DL_FOREACH_SAFE(*head, e, tmp) {
781b4ee4795Smrg        if (dpy->cookiejar == e)
782b4ee4795Smrg            dpy->cookiejar = NULL;
783c17aa6b1Smrg        XFree(e->ev.data);
784c17aa6b1Smrg        XFree(e);
785b4ee4795Smrg    }
786b4ee4795Smrg}
787b4ee4795Smrg
788b4ee4795Smrg/**
789b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the
790b4ee4795Smrg * next call to XNextEvent().
791b4ee4795Smrg */
792b4ee4795Smrgvoid
793b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event)
794b4ee4795Smrg{
795b4ee4795Smrg    XGenericEventCookie* cookie = &event->xcookie;
796b4ee4795Smrg    struct stored_event **head, *add;
797b4ee4795Smrg
798b4ee4795Smrg    if (!_XIsEventCookie(dpy, event))
799b4ee4795Smrg        return;
800b4ee4795Smrg
801b4ee4795Smrg    head = (struct stored_event**)(&dpy->cookiejar);
802b4ee4795Smrg
803b4ee4795Smrg    add = Xmalloc(sizeof(struct stored_event));
804b4ee4795Smrg    if (!add) {
805b4ee4795Smrg        ESET(ENOMEM);
806b4ee4795Smrg        _XIOError(dpy);
807b4ee4795Smrg    }
808b4ee4795Smrg    add->ev = *cookie;
809b4ee4795Smrg    DL_APPEND(*head, add);
810b4ee4795Smrg    cookie->data = NULL; /* don't return data yet, must be claimed */
811b4ee4795Smrg}
812b4ee4795Smrg
813b4ee4795Smrg/**
814b4ee4795Smrg * Return the event with the given cookie and remove it from the list.
815b4ee4795Smrg */
816b4ee4795SmrgBool
817b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
818b4ee4795Smrg{
819b4ee4795Smrg    Bool ret = False;
820b4ee4795Smrg    struct stored_event **head, *event;
821b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
822b4ee4795Smrg
823b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)ev))
824b4ee4795Smrg        return ret;
825b4ee4795Smrg
826b4ee4795Smrg    DL_FOREACH(*head, event) {
827b4ee4795Smrg        if (event->ev.cookie == ev->cookie &&
828b4ee4795Smrg            event->ev.extension == ev->extension &&
829b4ee4795Smrg            event->ev.evtype == ev->evtype) {
830b4ee4795Smrg            *ev = event->ev;
831b4ee4795Smrg            DL_DELETE(*head, event);
832b4ee4795Smrg            Xfree(event);
833b4ee4795Smrg            ret = True;
834b4ee4795Smrg            break;
835b4ee4795Smrg        }
836b4ee4795Smrg    }
837b4ee4795Smrg
838b4ee4795Smrg    return ret;
839b4ee4795Smrg}
840b4ee4795Smrg
841b4ee4795SmrgBool
842b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
843b4ee4795Smrg{
844b4ee4795Smrg    Bool ret = False;
845b4ee4795Smrg    int extension;
846b4ee4795Smrg
847b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
848b4ee4795Smrg        return ret;
849b4ee4795Smrg
850b4ee4795Smrg    extension = in->extension & 0x7F;
851b4ee4795Smrg
852b4ee4795Smrg    if (!dpy->generic_event_copy_vec[extension])
853b4ee4795Smrg        return ret;
854b4ee4795Smrg
855b4ee4795Smrg    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
856b4ee4795Smrg    out->cookie = ret ? ++dpy->next_cookie  : 0;
857b4ee4795Smrg    return ret;
858b4ee4795Smrg}
859b4ee4795Smrg
8601ab64890Smrg
8611ab64890Smrg/*
8621ab64890Smrg * _XEnq - Place event packets on the display's queue.
8631ab64890Smrg * note that no squishing of move events in V11, since there
8641ab64890Smrg * is pointer motion hints....
8651ab64890Smrg */
8661ab64890Smrgvoid _XEnq(
8671ab64890Smrg	register Display *dpy,
8681ab64890Smrg	register xEvent *event)
8691ab64890Smrg{
8701ab64890Smrg	register _XQEvent *qelt;
871b4ee4795Smrg	int type, extension;
8721ab64890Smrg
8731ab64890Smrg	if ((qelt = dpy->qfree)) {
8741ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
8751ab64890Smrg		dpy->qfree = qelt->next;
8761ab64890Smrg	}
87761b2299dSmrg	else if ((qelt =
8781ab64890Smrg	    (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
8791ab64890Smrg		/* Malloc call failed! */
8801ab64890Smrg		ESET(ENOMEM);
8811ab64890Smrg		_XIOError(dpy);
8821ab64890Smrg	}
8831ab64890Smrg	qelt->next = NULL;
884b4ee4795Smrg
885b4ee4795Smrg	type = event->u.u.type & 0177;
886b4ee4795Smrg	extension = ((xGenericEvent*)event)->extension;
887295fb823Smrg
888295fb823Smrg	qelt->event.type = type;
889b4ee4795Smrg	/* If an extension has registerd a generic_event_vec handler, then
890b4ee4795Smrg	 * it can handle event cookies. Otherwise, proceed with the normal
891b4ee4795Smrg	 * event handlers.
892b4ee4795Smrg	 *
893b4ee4795Smrg	 * If the generic_event_vec is called, qelt->event is a event cookie
894b4ee4795Smrg	 * with the data pointer and the "free" pointer set. Data pointer is
895b4ee4795Smrg	 * some memory allocated by the extension.
896b4ee4795Smrg	 */
897b4ee4795Smrg        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
898b4ee4795Smrg	    XGenericEventCookie *cookie = &qelt->event.xcookie;
899b4ee4795Smrg	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
900b4ee4795Smrg	    cookie->cookie = ++dpy->next_cookie;
901b4ee4795Smrg
902b4ee4795Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
903b4ee4795Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
904b4ee4795Smrg	    else		dpy->head = qelt;
905b4ee4795Smrg
906b4ee4795Smrg	    dpy->tail = qelt;
907b4ee4795Smrg	    dpy->qlen++;
908b4ee4795Smrg	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
9091ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
9101ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
9111ab64890Smrg	    else 		dpy->head = qelt;
91261b2299dSmrg
9131ab64890Smrg	    dpy->tail = qelt;
9141ab64890Smrg	    dpy->qlen++;
9151ab64890Smrg	} else {
9161ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
9171ab64890Smrg	    qelt->next = dpy->qfree;
9181ab64890Smrg	    dpy->qfree = qelt;
9191ab64890Smrg	}
9201ab64890Smrg}
9211ab64890Smrg
9221ab64890Smrg/*
9231ab64890Smrg * _XDeq - Remove event packet from the display's queue.
9241ab64890Smrg */
9251ab64890Smrgvoid _XDeq(
9261ab64890Smrg    register Display *dpy,
9271ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
9281ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
9291ab64890Smrg{
9301ab64890Smrg    if (prev) {
9311ab64890Smrg	if ((prev->next = qelt->next) == NULL)
9321ab64890Smrg	    dpy->tail = prev;
9331ab64890Smrg    } else {
9341ab64890Smrg	/* no prev, so removing first elt */
9351ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
9361ab64890Smrg	    dpy->tail = NULL;
9371ab64890Smrg    }
9381ab64890Smrg    qelt->qserial_num = 0;
9391ab64890Smrg    qelt->next = dpy->qfree;
9401ab64890Smrg    dpy->qfree = qelt;
9411ab64890Smrg    dpy->qlen--;
942b4ee4795Smrg
943b4ee4795Smrg    if (_XIsEventCookie(dpy, &qelt->event)) {
944b4ee4795Smrg	XGenericEventCookie* cookie = &qelt->event.xcookie;
945b4ee4795Smrg	/* dpy->qfree is re-used, reset memory to avoid double free on
946b4ee4795Smrg	 * _XFreeDisplayStructure */
947b4ee4795Smrg	cookie->data = NULL;
948b4ee4795Smrg    }
9491ab64890Smrg}
9501ab64890Smrg
9511ab64890Smrg/*
9521ab64890Smrg * EventToWire in separate file in that often not needed.
9531ab64890Smrg */
9541ab64890Smrg
9551ab64890Smrg/*ARGSUSED*/
9561ab64890SmrgBool
9571ab64890Smrg_XUnknownWireEvent(
9581ab64890Smrg    register Display *dpy,	/* pointer to display structure */
9591ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
9601ab64890Smrg    register xEvent *event)	/* wire protocol event */
9611ab64890Smrg{
9621ab64890Smrg#ifdef notdef
96361b2299dSmrg	(void) fprintf(stderr,
9641ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
9651ab64890Smrg			event->u.u.type, dpy);
9661ab64890Smrg#endif
9671ab64890Smrg	return(False);
9681ab64890Smrg}
9691ab64890Smrg
970b4ee4795SmrgBool
971b4ee4795Smrg_XUnknownWireEventCookie(
972b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
973b4ee4795Smrg    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
974b4ee4795Smrg    xEvent *event)	/* wire protocol event */
975b4ee4795Smrg{
976b4ee4795Smrg#ifdef notdef
977b4ee4795Smrg	fprintf(stderr,
978b4ee4795Smrg	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
979b4ee4795Smrg			((xGenericEvent*)event)->extension, dpy);
980b4ee4795Smrg#endif
981b4ee4795Smrg	return(False);
982b4ee4795Smrg}
983b4ee4795Smrg
984b4ee4795SmrgBool
985b4ee4795Smrg_XUnknownCopyEventCookie(
986b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
987b4ee4795Smrg    XGenericEventCookie *in,	/* source */
988b4ee4795Smrg    XGenericEventCookie *out)	/* destination */
989b4ee4795Smrg{
990b4ee4795Smrg#ifdef notdef
991b4ee4795Smrg	fprintf(stderr,
992b4ee4795Smrg	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
993b4ee4795Smrg			in->extension, dpy);
994b4ee4795Smrg#endif
995b4ee4795Smrg	return(False);
996b4ee4795Smrg}
997b4ee4795Smrg
9981ab64890Smrg/*ARGSUSED*/
9991ab64890SmrgStatus
10001ab64890Smrg_XUnknownNativeEvent(
10011ab64890Smrg    register Display *dpy,	/* pointer to display structure */
10021ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
10031ab64890Smrg    register xEvent *event)	/* wire protocol event */
10041ab64890Smrg{
10051ab64890Smrg#ifdef notdef
100661b2299dSmrg	(void) fprintf(stderr,
10071ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
10081ab64890Smrg			re->type, dpy);
10091ab64890Smrg#endif
10101ab64890Smrg	return(0);
10111ab64890Smrg}
10121ab64890Smrg/*
10131ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
10141ab64890Smrg */
10151ab64890SmrgBool
10161ab64890Smrg_XWireToEvent(
10171ab64890Smrg    register Display *dpy,	/* pointer to display structure */
10181ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
10191ab64890Smrg    register xEvent *event)	/* wire protocol event */
10201ab64890Smrg{
10211ab64890Smrg
10221ab64890Smrg	re->type = event->u.u.type & 0x7f;
10231ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
10241ab64890Smrg					(xGenericReply *)event);
10251ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
10261ab64890Smrg	((XAnyEvent *)re)->display = dpy;
102761b2299dSmrg
10281ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
10291ab64890Smrg		client sends an event rather than the server. */
10301ab64890Smrg
10311ab64890Smrg	switch (event-> u.u.type & 0177) {
10321ab64890Smrg	      case KeyPress:
10331ab64890Smrg	      case KeyRelease:
10341ab64890Smrg	        {
10351ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
10361ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
10371ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
10381ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
10391ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
10401ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
10411ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
10421ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
10431ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
10441ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
10451ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
10461ab64890Smrg			ev->keycode 	= event->u.u.detail;
10471ab64890Smrg		}
10481ab64890Smrg	      	break;
10491ab64890Smrg	      case ButtonPress:
10501ab64890Smrg	      case ButtonRelease:
10511ab64890Smrg	        {
10521ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) re;
10531ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
10541ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
10551ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
10561ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
10571ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
10581ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
10591ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
10601ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
10611ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
10621ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
10631ab64890Smrg			ev->button 	= event->u.u.detail;
10641ab64890Smrg		}
10651ab64890Smrg	        break;
10661ab64890Smrg	      case MotionNotify:
10671ab64890Smrg	        {
10681ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
10691ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
10701ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
10711ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
10721ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
10731ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
10741ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
10751ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
10761ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
10771ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
10781ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
10791ab64890Smrg			ev->is_hint 	= event->u.u.detail;
10801ab64890Smrg		}
10811ab64890Smrg	        break;
10821ab64890Smrg	      case EnterNotify:
10831ab64890Smrg	      case LeaveNotify:
10841ab64890Smrg		{
10851ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
10861ab64890Smrg			ev->root	= event->u.enterLeave.root;
10871ab64890Smrg			ev->window	= event->u.enterLeave.event;
10881ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
10891ab64890Smrg			ev->time	= event->u.enterLeave.time;
10901ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
10911ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
10921ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
10931ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
10941ab64890Smrg			ev->state	= event->u.enterLeave.state;
10951ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
109661b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
10971ab64890Smrg				ELFlagSameScreen) && True;
10981ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
10991ab64890Smrg			  	ELFlagFocus) && True;
11001ab64890Smrg			ev->detail	= event->u.u.detail;
11011ab64890Smrg		}
11021ab64890Smrg		  break;
11031ab64890Smrg	      case FocusIn:
11041ab64890Smrg	      case FocusOut:
11051ab64890Smrg		{
11061ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
11071ab64890Smrg			ev->window 	= event->u.focus.window;
11081ab64890Smrg			ev->mode	= event->u.focus.mode;
11091ab64890Smrg			ev->detail	= event->u.u.detail;
11101ab64890Smrg		}
11111ab64890Smrg		  break;
11121ab64890Smrg	      case KeymapNotify:
11131ab64890Smrg		{
11141ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
11151ab64890Smrg			ev->window	= None;
11161ab64890Smrg			memcpy(&ev->key_vector[1],
11171ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
11181ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
11191ab64890Smrg		}
11201ab64890Smrg		break;
11211ab64890Smrg	      case Expose:
11221ab64890Smrg		{
11231ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
11241ab64890Smrg			ev->window	= event->u.expose.window;
11251ab64890Smrg			ev->x		= event->u.expose.x;
11261ab64890Smrg			ev->y		= event->u.expose.y;
11271ab64890Smrg			ev->width	= event->u.expose.width;
11281ab64890Smrg			ev->height	= event->u.expose.height;
11291ab64890Smrg			ev->count	= event->u.expose.count;
11301ab64890Smrg		}
11311ab64890Smrg		break;
11321ab64890Smrg	      case GraphicsExpose:
11331ab64890Smrg		{
11341ab64890Smrg		    register XGraphicsExposeEvent *ev =
11351ab64890Smrg			(XGraphicsExposeEvent *) re;
11361ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
11371ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
11381ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
11391ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
11401ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
11411ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
11421ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
11431ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
11441ab64890Smrg		}
11451ab64890Smrg		break;
11461ab64890Smrg	      case NoExpose:
11471ab64890Smrg		{
11481ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
11491ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
11501ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
11511ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
11521ab64890Smrg		}
11531ab64890Smrg		break;
11541ab64890Smrg	      case VisibilityNotify:
11551ab64890Smrg		{
11561ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
11571ab64890Smrg		    ev->window		= event->u.visibility.window;
11581ab64890Smrg		    ev->state		= event->u.visibility.state;
11591ab64890Smrg		}
11601ab64890Smrg		break;
11611ab64890Smrg	      case CreateNotify:
11621ab64890Smrg		{
11631ab64890Smrg		    register XCreateWindowEvent *ev =
11641ab64890Smrg			 (XCreateWindowEvent *) re;
11651ab64890Smrg		    ev->window		= event->u.createNotify.window;
11661ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
11671ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
11681ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
11691ab64890Smrg		    ev->width		= event->u.createNotify.width;
11701ab64890Smrg		    ev->height		= event->u.createNotify.height;
11711ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
11721ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
11731ab64890Smrg		}
11741ab64890Smrg		break;
11751ab64890Smrg	      case DestroyNotify:
11761ab64890Smrg		{
11771ab64890Smrg		    register XDestroyWindowEvent *ev =
11781ab64890Smrg				(XDestroyWindowEvent *) re;
11791ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
11801ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
11811ab64890Smrg		}
11821ab64890Smrg		break;
11831ab64890Smrg	      case UnmapNotify:
11841ab64890Smrg		{
11851ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
11861ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
11871ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
11881ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
11891ab64890Smrg		}
11901ab64890Smrg		break;
11911ab64890Smrg	      case MapNotify:
11921ab64890Smrg		{
11931ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
11941ab64890Smrg		    ev->window		= event->u.mapNotify.window;
11951ab64890Smrg		    ev->event		= event->u.mapNotify.event;
11961ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
11971ab64890Smrg		}
11981ab64890Smrg		break;
11991ab64890Smrg	      case MapRequest:
12001ab64890Smrg		{
12011ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
12021ab64890Smrg		    ev->window		= event->u.mapRequest.window;
12031ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
12041ab64890Smrg		}
12051ab64890Smrg		break;
12061ab64890Smrg	      case ReparentNotify:
12071ab64890Smrg		{
12081ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
12091ab64890Smrg		    ev->event		= event->u.reparent.event;
12101ab64890Smrg		    ev->window		= event->u.reparent.window;
12111ab64890Smrg		    ev->parent		= event->u.reparent.parent;
12121ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
12131ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
12141ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
12151ab64890Smrg		}
12161ab64890Smrg		break;
12171ab64890Smrg	      case ConfigureNotify:
12181ab64890Smrg		{
12191ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
12201ab64890Smrg		    ev->event	= event->u.configureNotify.event;
12211ab64890Smrg		    ev->window	= event->u.configureNotify.window;
12221ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
12231ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
12241ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
12251ab64890Smrg		    ev->width	= event->u.configureNotify.width;
12261ab64890Smrg		    ev->height	= event->u.configureNotify.height;
12271ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
12281ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
12291ab64890Smrg		}
12301ab64890Smrg		break;
12311ab64890Smrg	      case ConfigureRequest:
12321ab64890Smrg		{
12331ab64890Smrg		    register XConfigureRequestEvent *ev =
12341ab64890Smrg		        (XConfigureRequestEvent *) re;
12351ab64890Smrg		    ev->window		= event->u.configureRequest.window;
12361ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
12371ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
12381ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
12391ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
12401ab64890Smrg		    ev->width		= event->u.configureRequest.width;
12411ab64890Smrg		    ev->height		= event->u.configureRequest.height;
12421ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
12431ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
12441ab64890Smrg		    ev->detail  	= event->u.u.detail;
12451ab64890Smrg		}
12461ab64890Smrg		break;
12471ab64890Smrg	      case GravityNotify:
12481ab64890Smrg		{
12491ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
12501ab64890Smrg		    ev->window		= event->u.gravity.window;
12511ab64890Smrg		    ev->event		= event->u.gravity.event;
12521ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
12531ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
12541ab64890Smrg		}
12551ab64890Smrg		break;
12561ab64890Smrg	      case ResizeRequest:
12571ab64890Smrg		{
12581ab64890Smrg		    register XResizeRequestEvent *ev =
12591ab64890Smrg			(XResizeRequestEvent *) re;
12601ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
12611ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
12621ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
12631ab64890Smrg		}
12641ab64890Smrg		break;
12651ab64890Smrg	      case CirculateNotify:
12661ab64890Smrg		{
12671ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
12681ab64890Smrg		    ev->window		= event->u.circulate.window;
12691ab64890Smrg		    ev->event		= event->u.circulate.event;
12701ab64890Smrg		    ev->place		= event->u.circulate.place;
12711ab64890Smrg		}
12721ab64890Smrg		break;
12731ab64890Smrg	      case CirculateRequest:
12741ab64890Smrg		{
12751ab64890Smrg		    register XCirculateRequestEvent *ev =
12761ab64890Smrg		        (XCirculateRequestEvent *) re;
12771ab64890Smrg		    ev->window		= event->u.circulate.window;
12781ab64890Smrg		    ev->parent		= event->u.circulate.event;
12791ab64890Smrg		    ev->place		= event->u.circulate.place;
12801ab64890Smrg		}
12811ab64890Smrg		break;
12821ab64890Smrg	      case PropertyNotify:
12831ab64890Smrg		{
12841ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
12851ab64890Smrg		    ev->window		= event->u.property.window;
12861ab64890Smrg		    ev->atom		= event->u.property.atom;
12871ab64890Smrg		    ev->time		= event->u.property.time;
12881ab64890Smrg		    ev->state		= event->u.property.state;
12891ab64890Smrg		}
12901ab64890Smrg		break;
12911ab64890Smrg	      case SelectionClear:
12921ab64890Smrg		{
12931ab64890Smrg		    register XSelectionClearEvent *ev =
12941ab64890Smrg			 (XSelectionClearEvent *) re;
12951ab64890Smrg		    ev->window		= event->u.selectionClear.window;
12961ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
12971ab64890Smrg		    ev->time		= event->u.selectionClear.time;
12981ab64890Smrg		}
12991ab64890Smrg		break;
13001ab64890Smrg	      case SelectionRequest:
13011ab64890Smrg		{
13021ab64890Smrg		    register XSelectionRequestEvent *ev =
13031ab64890Smrg		        (XSelectionRequestEvent *) re;
13041ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
13051ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
13061ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
13071ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
13081ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
13091ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
13101ab64890Smrg		}
13111ab64890Smrg		break;
13121ab64890Smrg	      case SelectionNotify:
13131ab64890Smrg		{
13141ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
13151ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
13161ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
13171ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
13181ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
13191ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
13201ab64890Smrg		}
13211ab64890Smrg		break;
13221ab64890Smrg	      case ColormapNotify:
13231ab64890Smrg		{
13241ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
13251ab64890Smrg		    ev->window		= event->u.colormap.window;
13261ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
13271ab64890Smrg		    ev->new		= event->u.colormap.new;
13281ab64890Smrg		    ev->state		= event->u.colormap.state;
13291ab64890Smrg	        }
13301ab64890Smrg		break;
13311ab64890Smrg	      case ClientMessage:
13321ab64890Smrg		{
13331ab64890Smrg		   register int i;
133461b2299dSmrg		   register XClientMessageEvent *ev
13351ab64890Smrg		   			= (XClientMessageEvent *) re;
13361ab64890Smrg		   ev->window		= event->u.clientMessage.window;
13371ab64890Smrg		   ev->format		= event->u.u.detail;
13381ab64890Smrg		   switch (ev->format) {
133961b2299dSmrg			case 8:
13401ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
134161b2299dSmrg			   for (i = 0; i < 20; i++)
13421ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
13431ab64890Smrg			   break;
13441ab64890Smrg			case 16:
13451ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
13461ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
13471ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
13481ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
13491ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
13501ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
13511ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
13521ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
13531ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
13541ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
13551ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
13561ab64890Smrg			   break;
13571ab64890Smrg			case 32:
13581ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
13591ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
13601ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
13611ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
13621ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
13631ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
13641ab64890Smrg			   break;
13651ab64890Smrg			default: /* XXX should never occur */
13661ab64890Smrg				break;
13671ab64890Smrg		    }
13681ab64890Smrg	        }
13691ab64890Smrg		break;
13701ab64890Smrg	      case MappingNotify:
13711ab64890Smrg		{
13721ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
13731ab64890Smrg		   ev->window		= 0;
13741ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
13751ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
13761ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
13771ab64890Smrg		}
13781ab64890Smrg		break;
13791ab64890Smrg	      default:
13801ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
13811ab64890Smrg	}
13821ab64890Smrg	return(True);
13831ab64890Smrg}
13841ab64890Smrg
13851ab64890Smrg
13861ab64890Smrg/*
138761b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
13881ab64890Smrg * when an X internal system error is encountered.
13891ab64890Smrg */
13901ab64890Smrgint _XDefaultIOError(
13911ab64890Smrg	Display *dpy)
13921ab64890Smrg{
13931ab64890Smrg	if (ECHECK(EPIPE)) {
13941ab64890Smrg	    (void) fprintf (stderr,
13951ab64890Smrg	"X connection to %s broken (explicit kill or server shutdown).\r\n",
13961ab64890Smrg			    DisplayString (dpy));
13971ab64890Smrg	} else {
139861b2299dSmrg	    (void) fprintf (stderr,
13991ab64890Smrg			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
14001ab64890Smrg#ifdef WIN32
14011ab64890Smrg			WSAGetLastError(), strerror(WSAGetLastError()),
14021ab64890Smrg#else
14031ab64890Smrg			errno, strerror (errno),
14041ab64890Smrg#endif
14051ab64890Smrg			DisplayString (dpy));
140661b2299dSmrg	    (void) fprintf (stderr,
14071ab64890Smrg	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
14081ab64890Smrg			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
14091ab64890Smrg			QLength(dpy));
14101ab64890Smrg
14111ab64890Smrg	}
14121ab64890Smrg	exit(1);
14131ab64890Smrg        return(0); /* dummy - function should never return */
14141ab64890Smrg}
14151ab64890Smrg
14161ab64890Smrg
14171ab64890Smrgstatic int _XPrintDefaultError(
14181ab64890Smrg    Display *dpy,
14191ab64890Smrg    XErrorEvent *event,
14201ab64890Smrg    FILE *fp)
14211ab64890Smrg{
14221ab64890Smrg    char buffer[BUFSIZ];
14231ab64890Smrg    char mesg[BUFSIZ];
14241ab64890Smrg    char number[32];
14251ab64890Smrg    const char *mtype = "XlibMessage";
14261ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
14271ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
14281ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
14291ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
14301ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
143161b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
14321ab64890Smrg	mesg, BUFSIZ);
14331ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
14341ab64890Smrg    if (event->request_code < 128) {
14351ab64890Smrg	sprintf(number, "%d", event->request_code);
14361ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
14371ab64890Smrg    } else {
14381ab64890Smrg	for (ext = dpy->ext_procs;
14391ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
14401ab64890Smrg	     ext = ext->next)
14411ab64890Smrg	  ;
1442c17aa6b1Smrg	if (ext) {
1443c17aa6b1Smrg	    strncpy(buffer, ext->name, BUFSIZ);
1444c17aa6b1Smrg	    buffer[BUFSIZ - 1] = '\0';
1445c17aa6b1Smrg        } else
14461ab64890Smrg	    buffer[0] = '\0';
14471ab64890Smrg    }
14481ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
14491ab64890Smrg    if (event->request_code >= 128) {
14501ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
14511ab64890Smrg			      mesg, BUFSIZ);
14521ab64890Smrg	fputs("  ", fp);
14531ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
14541ab64890Smrg	if (ext) {
14551ab64890Smrg	    sprintf(mesg, "%s.%d", ext->name, event->minor_code);
14561ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
14571ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
14581ab64890Smrg	}
14591ab64890Smrg	fputs("\n", fp);
14601ab64890Smrg    }
14611ab64890Smrg    if (event->error_code >= 128) {
14621ab64890Smrg	/* kludge, try to find the extension that caused it */
14631ab64890Smrg	buffer[0] = '\0';
14641ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
146561b2299dSmrg	    if (ext->error_string)
14661ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
14671ab64890Smrg				     buffer, BUFSIZ);
14681ab64890Smrg	    if (buffer[0]) {
14691ab64890Smrg		bext = ext;
14701ab64890Smrg		break;
14711ab64890Smrg	    }
14721ab64890Smrg	    if (ext->codes.first_error &&
14731ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
14741ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
14751ab64890Smrg		bext = ext;
147661b2299dSmrg	}
14771ab64890Smrg	if (bext)
14781ab64890Smrg	    sprintf(buffer, "%s.%d", bext->name,
14791ab64890Smrg		    event->error_code - bext->codes.first_error);
14801ab64890Smrg	else
14811ab64890Smrg	    strcpy(buffer, "Value");
14821ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
14831ab64890Smrg	if (mesg[0]) {
14841ab64890Smrg	    fputs("  ", fp);
14851ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
14861ab64890Smrg	    fputs("\n", fp);
14871ab64890Smrg	}
14881ab64890Smrg	/* let extensions try to print the values */
14891ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
14901ab64890Smrg	    if (ext->error_values)
14911ab64890Smrg		(*ext->error_values)(dpy, event, fp);
14921ab64890Smrg	}
14931ab64890Smrg    } else if ((event->error_code == BadWindow) ||
14941ab64890Smrg	       (event->error_code == BadPixmap) ||
14951ab64890Smrg	       (event->error_code == BadCursor) ||
14961ab64890Smrg	       (event->error_code == BadFont) ||
14971ab64890Smrg	       (event->error_code == BadDrawable) ||
14981ab64890Smrg	       (event->error_code == BadColor) ||
14991ab64890Smrg	       (event->error_code == BadGC) ||
15001ab64890Smrg	       (event->error_code == BadIDChoice) ||
15011ab64890Smrg	       (event->error_code == BadValue) ||
15021ab64890Smrg	       (event->error_code == BadAtom)) {
15031ab64890Smrg	if (event->error_code == BadValue)
15041ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
15051ab64890Smrg				  mesg, BUFSIZ);
15061ab64890Smrg	else if (event->error_code == BadAtom)
15071ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
15081ab64890Smrg				  mesg, BUFSIZ);
15091ab64890Smrg	else
15101ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
15111ab64890Smrg				  mesg, BUFSIZ);
15121ab64890Smrg	fputs("  ", fp);
15131ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
15141ab64890Smrg	fputs("\n", fp);
15151ab64890Smrg    }
151661b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
15171ab64890Smrg			  mesg, BUFSIZ);
15181ab64890Smrg    fputs("  ", fp);
15191ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
15201ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
15211ab64890Smrg			  mesg, BUFSIZ);
15221ab64890Smrg    fputs("\n  ", fp);
15231ab64890Smrg    (void) fprintf(fp, mesg, dpy->request);
15241ab64890Smrg    fputs("\n", fp);
15251ab64890Smrg    if (event->error_code == BadImplementation) return 0;
15261ab64890Smrg    return 1;
15271ab64890Smrg}
15281ab64890Smrg
15291ab64890Smrgint _XDefaultError(
15301ab64890Smrg	Display *dpy,
15311ab64890Smrg	XErrorEvent *event)
15321ab64890Smrg{
15331ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
15341ab64890Smrg    exit(1);
15351ab64890Smrg    /*NOTREACHED*/
15361ab64890Smrg}
15371ab64890Smrg
15381ab64890Smrg/*ARGSUSED*/
153961b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
15401ab64890Smrg{
15411ab64890Smrg    return True;
15421ab64890Smrg}
15431ab64890Smrg
15441ab64890Smrg/*
15451ab64890Smrg * _XError - upcall internal or user protocol error handler
15461ab64890Smrg */
15471ab64890Smrgint _XError (
15481ab64890Smrg    Display *dpy,
15491ab64890Smrg    register xError *rep)
15501ab64890Smrg{
155161b2299dSmrg    /*
15521ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
15531ab64890Smrg     * giving it to the user.
15541ab64890Smrg     */
15551ab64890Smrg    XEvent event; /* make it a large event */
15561ab64890Smrg    register _XAsyncHandler *async, *next;
15571ab64890Smrg
15581ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
15591ab64890Smrg
15601ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
15611ab64890Smrg	next = async->next;
15621ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
15631ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
15641ab64890Smrg	    return 0;
15651ab64890Smrg    }
15661ab64890Smrg
15671ab64890Smrg    event.xerror.display = dpy;
15681ab64890Smrg    event.xerror.type = X_Error;
15691ab64890Smrg    event.xerror.resourceid = rep->resourceID;
15701ab64890Smrg    event.xerror.error_code = rep->errorCode;
15711ab64890Smrg    event.xerror.request_code = rep->majorCode;
15721ab64890Smrg    event.xerror.minor_code = rep->minorCode;
15731ab64890Smrg    if (dpy->error_vec &&
15741ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
15751ab64890Smrg	return 0;
15761ab64890Smrg    if (_XErrorFunction != NULL) {
1577c17aa6b1Smrg	int rtn_val;
1578c17aa6b1Smrg#ifdef XTHREADS
1579c17aa6b1Smrg	if (dpy->lock)
1580c17aa6b1Smrg	    (*dpy->lock->user_lock_display)(dpy);
1581c17aa6b1Smrg	UnlockDisplay(dpy);
1582c17aa6b1Smrg#endif
1583c17aa6b1Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1584c17aa6b1Smrg#ifdef XTHREADS
1585c17aa6b1Smrg	LockDisplay(dpy);
1586c17aa6b1Smrg	if (dpy->lock)
1587c17aa6b1Smrg	    (*dpy->lock->user_unlock_display)(dpy);
1588c17aa6b1Smrg#endif
1589c17aa6b1Smrg	return rtn_val;
15901ab64890Smrg    } else {
15911ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
15921ab64890Smrg    }
15931ab64890Smrg}
159461b2299dSmrg
15951ab64890Smrg/*
15961ab64890Smrg * _XIOError - call user connection error handler and exit
15971ab64890Smrg */
15981ab64890Smrgint
15991ab64890Smrg_XIOError (
16001ab64890Smrg    Display *dpy)
16011ab64890Smrg{
16021ab64890Smrg    dpy->flags |= XlibDisplayIOError;
16031ab64890Smrg#ifdef WIN32
16041ab64890Smrg    errno = WSAGetLastError();
16051ab64890Smrg#endif
16061ab64890Smrg
16071ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
16081ab64890Smrg     * If this does not hold, then an alternate solution would involve
16091ab64890Smrg     * registering an atexit handler to take over the lock, which would only
16101ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
16111ab64890Smrg#ifdef XTHREADS
16121ab64890Smrg    if (dpy->lock)
16131ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
16141ab64890Smrg#endif
16151ab64890Smrg    UnlockDisplay(dpy);
16161ab64890Smrg
16171ab64890Smrg    if (_XIOErrorFunction != NULL)
16181ab64890Smrg	(*_XIOErrorFunction)(dpy);
16191ab64890Smrg    else
16201ab64890Smrg	_XDefaultIOError(dpy);
16211ab64890Smrg    exit (1);
16221ab64890Smrg    return 0;
16231ab64890Smrg}
16241ab64890Smrg
16251ab64890Smrg
16261ab64890Smrg/*
16271ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
16281ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
16291ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
16301ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
16311ab64890Smrg * is guaranteed to not unlock the display.
16321ab64890Smrg */
16331ab64890Smrgchar *_XAllocScratch(
16341ab64890Smrg	register Display *dpy,
16351ab64890Smrg	unsigned long nbytes)
16361ab64890Smrg{
16371ab64890Smrg	if (nbytes > dpy->scratch_length) {
16381ab64890Smrg	    if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
16391ab64890Smrg	    if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
16401ab64890Smrg		dpy->scratch_length = nbytes;
16411ab64890Smrg	    else dpy->scratch_length = 0;
16421ab64890Smrg	}
16431ab64890Smrg	return (dpy->scratch_buffer);
16441ab64890Smrg}
16451ab64890Smrg
16461ab64890Smrg/*
16471ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
16481ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
16491ab64890Smrg */
16501ab64890Smrgchar *_XAllocTemp(
16511ab64890Smrg    register Display *dpy,
16521ab64890Smrg    unsigned long nbytes)
16531ab64890Smrg{
16541ab64890Smrg    char *buf;
16551ab64890Smrg
16561ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
16571ab64890Smrg    dpy->scratch_buffer = NULL;
16581ab64890Smrg    dpy->scratch_length = 0;
16591ab64890Smrg    return buf;
16601ab64890Smrg}
16611ab64890Smrg
16621ab64890Smrgvoid _XFreeTemp(
16631ab64890Smrg    register Display *dpy,
16641ab64890Smrg    char *buf,
16651ab64890Smrg    unsigned long nbytes)
16661ab64890Smrg{
16671ab64890Smrg    if (dpy->scratch_buffer)
16681ab64890Smrg	Xfree(dpy->scratch_buffer);
16691ab64890Smrg    dpy->scratch_buffer = buf;
16701ab64890Smrg    dpy->scratch_length = nbytes;
16711ab64890Smrg}
16721ab64890Smrg
16731ab64890Smrg/*
16741ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
16751ab64890Smrg */
16761ab64890SmrgVisual *_XVIDtoVisual(
16771ab64890Smrg	Display *dpy,
16781ab64890Smrg	VisualID id)
16791ab64890Smrg{
16801ab64890Smrg	register int i, j, k;
16811ab64890Smrg	register Screen *sp;
16821ab64890Smrg	register Depth *dp;
16831ab64890Smrg	register Visual *vp;
16841ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
16851ab64890Smrg		sp = &dpy->screens[i];
16861ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
16871ab64890Smrg			dp = &sp->depths[j];
16881ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
16891ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
16901ab64890Smrg				vp = &dp->visuals[k];
16911ab64890Smrg				if (vp->visualid == id) return (vp);
16921ab64890Smrg			}
16931ab64890Smrg		}
16941ab64890Smrg	}
16951ab64890Smrg	return (NULL);
16961ab64890Smrg}
16971ab64890Smrg
16981ab64890Smrgint
16991ab64890SmrgXFree (void *data)
17001ab64890Smrg{
17011ab64890Smrg	Xfree (data);
17021ab64890Smrg	return 1;
17031ab64890Smrg}
17041ab64890Smrg
17051ab64890Smrg#ifdef _XNEEDBCOPYFUNC
17061ab64890Smrgvoid _Xbcopy(b1, b2, length)
17071ab64890Smrg    register char *b1, *b2;
17081ab64890Smrg    register length;
17091ab64890Smrg{
17101ab64890Smrg    if (b1 < b2) {
17111ab64890Smrg	b2 += length;
17121ab64890Smrg	b1 += length;
17131ab64890Smrg	while (length--)
17141ab64890Smrg	    *--b2 = *--b1;
17151ab64890Smrg    } else {
17161ab64890Smrg	while (length--)
17171ab64890Smrg	    *b2++ = *b1++;
17181ab64890Smrg    }
17191ab64890Smrg}
17201ab64890Smrg#endif
17211ab64890Smrg
17221ab64890Smrg#ifdef DataRoutineIsProcedure
17231ab64890Smrgvoid Data(
17241ab64890Smrg	Display *dpy,
17251ab64890Smrg	char *data,
17261ab64890Smrg	long len)
17271ab64890Smrg{
17281ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
17291ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
17301ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
17311ab64890Smrg	} else {
17321ab64890Smrg		_XSend(dpy, data, len);
17331ab64890Smrg	}
17341ab64890Smrg}
17351ab64890Smrg#endif /* DataRoutineIsProcedure */
17361ab64890Smrg
17371ab64890Smrg
17381ab64890Smrg#ifdef LONG64
17391ab64890Smrgint
17401ab64890Smrg_XData32(
17411ab64890Smrg    Display *dpy,
17421ab64890Smrg    register long *data,
17431ab64890Smrg    unsigned len)
17441ab64890Smrg{
17451ab64890Smrg    register int *buf;
17461ab64890Smrg    register long i;
17471ab64890Smrg
17481ab64890Smrg    while (len) {
17491ab64890Smrg	buf = (int *)dpy->bufptr;
17501ab64890Smrg	i = dpy->bufmax - (char *)buf;
17511ab64890Smrg	if (!i) {
17521ab64890Smrg	    _XFlush(dpy);
17531ab64890Smrg	    continue;
17541ab64890Smrg	}
17551ab64890Smrg	if (len < i)
17561ab64890Smrg	    i = len;
17571ab64890Smrg	dpy->bufptr = (char *)buf + i;
17581ab64890Smrg	len -= i;
17591ab64890Smrg	i >>= 2;
17601ab64890Smrg	while (--i >= 0)
17611ab64890Smrg	    *buf++ = *data++;
17621ab64890Smrg    }
17631ab64890Smrg    return 0;
17641ab64890Smrg}
17651ab64890Smrg#endif /* LONG64 */
17661ab64890Smrg
17671ab64890Smrg#ifdef WORD64
17681ab64890Smrg
17691ab64890Smrg/*
177061b2299dSmrg * XXX This is a *really* stupid way of doing this.  It should just use
17711ab64890Smrg * dpy->bufptr directly, taking into account where in the word it is.
17721ab64890Smrg */
17731ab64890Smrg
17741ab64890Smrg/*
17751ab64890Smrg * Data16 - Place 16 bit data in the buffer.
17761ab64890Smrg *
17771ab64890Smrg * "dpy" is a pointer to a Display.
17781ab64890Smrg * "data" is a pointer to the data.
17791ab64890Smrg * "len" is the length in bytes of the data.
17801ab64890Smrg */
17811ab64890Smrg
17821ab64890Smrgstatic doData16(
17831ab64890Smrg    register Display *dpy,
17841ab64890Smrg    short *data,
17851ab64890Smrg    unsigned len,
17861ab64890Smrg    char *packbuffer)
17871ab64890Smrg{
17881ab64890Smrg    long *lp,*lpack;
17891ab64890Smrg    long i, nwords,bits;
17901ab64890Smrg    long mask16 = 0x000000000000ffff;
17911ab64890Smrg
17921ab64890Smrg        lp = (long *)data;
17931ab64890Smrg        lpack = (long *)packbuffer;
17941ab64890Smrg
17951ab64890Smrg/*  nwords is the number of 16 bit values to be packed,
17961ab64890Smrg *  the low order 16 bits of each word will be packed
17971ab64890Smrg *  into 64 bit words
17981ab64890Smrg */
17991ab64890Smrg        nwords = len >> 1;
18001ab64890Smrg        bits = 48;
18011ab64890Smrg
18021ab64890Smrg        for(i=0;i<nwords;i++){
18031ab64890Smrg	   if (bits == 48) *lpack = 0;
18041ab64890Smrg           *lpack ^= (*lp & mask16) << bits;
18051ab64890Smrg           bits -= 16 ;
18061ab64890Smrg           lp++;
18071ab64890Smrg           if(bits < 0){
18081ab64890Smrg               lpack++;
18091ab64890Smrg               bits = 48;
18101ab64890Smrg           }
18111ab64890Smrg        }
18121ab64890Smrg        Data(dpy, packbuffer, len);
18131ab64890Smrg}
18141ab64890Smrg
18151ab64890Smrg_XData16 (
18161ab64890Smrg    Display *dpy,
18171ab64890Smrg    short *data,
18181ab64890Smrg    unsigned len)
18191ab64890Smrg{
18201ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
18211ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 1;
18221ab64890Smrg
18231ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
18241ab64890Smrg	doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
18251ab64890Smrg    }
18261ab64890Smrg    if (len) doData16 (dpy, data, len, packbuffer);
18271ab64890Smrg}
18281ab64890Smrg
18291ab64890Smrg/*
18301ab64890Smrg * Data32 - Place 32 bit data in the buffer.
18311ab64890Smrg *
18321ab64890Smrg * "dpy" is a pointer to a Display.
18331ab64890Smrg * "data" is a pointer to the data.
18341ab64890Smrg * "len" is the length in bytes of the data.
18351ab64890Smrg */
18361ab64890Smrg
18371ab64890Smrgstatic doData32(
18381ab64890Smrg    register Display *dpy
18391ab64890Smrg    long *data,
18401ab64890Smrg    unsigned len,
18411ab64890Smrg    char *packbuffer)
18421ab64890Smrg{
18431ab64890Smrg    long *lp,*lpack;
18441ab64890Smrg    long i,bits,nwords;
18451ab64890Smrg    long mask32 = 0x00000000ffffffff;
18461ab64890Smrg
18471ab64890Smrg        lpack = (long *) packbuffer;
18481ab64890Smrg        lp = data;
18491ab64890Smrg
18501ab64890Smrg/*  nwords is the number of 32 bit values to be packed
18511ab64890Smrg *  the low order 32 bits of each word will be packed
18521ab64890Smrg *  into 64 bit words
18531ab64890Smrg */
18541ab64890Smrg        nwords = len >> 2;
18551ab64890Smrg        bits = 32;
18561ab64890Smrg
18571ab64890Smrg        for(i=0;i<nwords;i++){
18581ab64890Smrg	   if (bits == 32) *lpack = 0;
18591ab64890Smrg           *lpack ^= (*lp & mask32) << bits;
18601ab64890Smrg           bits = bits ^32;
18611ab64890Smrg           lp++;
18621ab64890Smrg           if(bits)
18631ab64890Smrg              lpack++;
18641ab64890Smrg        }
18651ab64890Smrg        Data(dpy, packbuffer, len);
18661ab64890Smrg}
18671ab64890Smrg
18681ab64890Smrgvoid _XData32(
18691ab64890Smrg    Display *dpy,
18701ab64890Smrg    long *data,
187161b2299dSmrg    unsigned len)
18721ab64890Smrg{
18731ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
18741ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 2;
18751ab64890Smrg
18761ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
18771ab64890Smrg	doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
18781ab64890Smrg    }
18791ab64890Smrg    if (len) doData32 (dpy, data, len, packbuffer);
18801ab64890Smrg}
18811ab64890Smrg
18821ab64890Smrg#endif /* WORD64 */
18831ab64890Smrg
18841ab64890Smrg
18851ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
18861ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
18871ab64890Smrg *
18881ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
18891ab64890Smrg *       to have sufficient information for interfacing to the network,
18901ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
18911ab64890Smrg */
18921ab64890Smrg
18932e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
18941ab64890Smrg#define NEED_UTSNAME
18951ab64890Smrg#include <sys/utsname.h>
189688de56ccSmrg#else
189788de56ccSmrg#ifdef HAVE_UNISTD_H
189888de56ccSmrg#include <unistd.h>
189988de56ccSmrg#endif
19001ab64890Smrg#endif
19011ab64890Smrg
19021ab64890Smrg/*
19031ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
19041ab64890Smrg */
19051ab64890Smrgint _XGetHostname (
19061ab64890Smrg    char *buf,
19071ab64890Smrg    int maxlen)
19081ab64890Smrg{
19091ab64890Smrg    int len;
19101ab64890Smrg
19111ab64890Smrg#ifdef NEED_UTSNAME
19121ab64890Smrg    struct utsname name;
19131ab64890Smrg
19141ab64890Smrg    if (maxlen <= 0 || buf == NULL)
19151ab64890Smrg	return 0;
19161ab64890Smrg
19171ab64890Smrg    uname (&name);
19181ab64890Smrg    len = strlen (name.nodename);
19191ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
19201ab64890Smrg    strncpy (buf, name.nodename, len);
19211ab64890Smrg    buf[len] = '\0';
19221ab64890Smrg#else
19231ab64890Smrg    if (maxlen <= 0 || buf == NULL)
19241ab64890Smrg	return 0;
19251ab64890Smrg
19261ab64890Smrg    buf[0] = '\0';
19271ab64890Smrg    (void) gethostname (buf, maxlen);
19281ab64890Smrg    buf [maxlen - 1] = '\0';
19291ab64890Smrg    len = strlen(buf);
19301ab64890Smrg#endif /* NEED_UTSNAME */
19311ab64890Smrg    return len;
19321ab64890Smrg}
19331ab64890Smrg
19341ab64890Smrg
19351ab64890Smrg/*
19361ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
19371ab64890Smrg */
19381ab64890Smrg
193961b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
19401ab64890Smrg{
19411ab64890Smrg    register int i;
19421ab64890Smrg    Window root;
19431ab64890Smrg    int x, y;				/* dummy variables */
19441ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
19451ab64890Smrg
19461ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
19471ab64890Smrg		      &bw, &depth) == False) {
19482e9c7c8cSmrg	return NULL;
19491ab64890Smrg    }
19501ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
19511ab64890Smrg	if (root == RootWindow (dpy, i)) {
19521ab64890Smrg	    return ScreenOfDisplay (dpy, i);
19531ab64890Smrg	}
19541ab64890Smrg    }
19551ab64890Smrg    return NULL;
19561ab64890Smrg}
19571ab64890Smrg
19581ab64890Smrg
19591ab64890Smrg#if defined(WIN32)
19601ab64890Smrg
19611ab64890Smrg/*
19621ab64890Smrg * These functions are intended to be used internally to Xlib only.
19631ab64890Smrg * These functions will always prefix the path with a DOS drive in the
19641ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
19651ab64890Smrg * for use by Xlib function that supply a root-based path to some
19661ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
19671ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
19681ab64890Smrg */
19691ab64890Smrg
19701ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
19711ab64890Smrg    char* path;
19721ab64890Smrg    char* pathbuf;
19731ab64890Smrg    int len_pathbuf;
19741ab64890Smrg    char** pathret;
19751ab64890Smrg{
19761ab64890Smrg    if (access (path, F_OK) == 0) {
19771ab64890Smrg	if (strlen (path) < len_pathbuf)
19781ab64890Smrg	    *pathret = pathbuf;
19791ab64890Smrg	else
19801ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
19811ab64890Smrg	if (*pathret) {
19821ab64890Smrg	    strcpy (*pathret, path);
19831ab64890Smrg	    return 1;
19841ab64890Smrg	}
19851ab64890Smrg    }
19861ab64890Smrg    return 0;
19871ab64890Smrg}
19881ab64890Smrg
19891ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
19901ab64890Smrg    char* path;
19911ab64890Smrg    char* pathbuf;
19921ab64890Smrg    int len_pathbuf;
19931ab64890Smrg    char** pathret;
19941ab64890Smrg{
19951ab64890Smrg    unsigned long drives;
19961ab64890Smrg    int i, len;
19971ab64890Smrg    char* drive;
19981ab64890Smrg    char buf[MAX_PATH];
19991ab64890Smrg    char* bufp;
20001ab64890Smrg
20011ab64890Smrg    /* just try the "raw" name first and see if it works */
20021ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
20031ab64890Smrg	return 1;
20041ab64890Smrg
20051ab64890Smrg    /* try the places set in the environment */
20061ab64890Smrg    drive = getenv ("_XBASEDRIVE");
20071ab64890Smrg#ifdef __UNIXOS2__
20081ab64890Smrg    if (!drive)
20091ab64890Smrg	drive = getenv ("X11ROOT");
20101ab64890Smrg#endif
20111ab64890Smrg    if (!drive)
20121ab64890Smrg	drive = "C:";
20131ab64890Smrg    len = strlen (drive) + strlen (path);
20141ab64890Smrg    if (len < MAX_PATH) bufp = buf;
20151ab64890Smrg    else bufp = Xmalloc (len + 1);
20161ab64890Smrg    strcpy (bufp, drive);
20171ab64890Smrg    strcat (bufp, path);
20181ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
20191ab64890Smrg	if (bufp != buf) Xfree (bufp);
20201ab64890Smrg	return 1;
20211ab64890Smrg    }
20221ab64890Smrg
202361b2299dSmrg#ifndef __UNIXOS2__
20241ab64890Smrg    /* one last place to look */
20251ab64890Smrg    drive = getenv ("HOMEDRIVE");
20261ab64890Smrg    if (drive) {
20271ab64890Smrg	len = strlen (drive) + strlen (path);
20281ab64890Smrg	if (len < MAX_PATH) bufp = buf;
20291ab64890Smrg	else bufp = Xmalloc (len + 1);
20301ab64890Smrg	strcpy (bufp, drive);
20311ab64890Smrg	strcat (bufp, path);
20321ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
20331ab64890Smrg	    if (bufp != buf) Xfree (bufp);
20341ab64890Smrg	    return 1;
20351ab64890Smrg	}
20361ab64890Smrg    }
20371ab64890Smrg
20381ab64890Smrg    /* tried everywhere else, go fishing */
20391ab64890Smrg#define C_DRIVE ('C' - 'A')
20401ab64890Smrg#define Z_DRIVE ('Z' - 'A')
20411ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
20421ab64890Smrg    drives = _getdrives ();
20431ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
20441ab64890Smrg	if ((1 << i) & drives) {
20451ab64890Smrg	    len = 2 + strlen (path);
20461ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
20471ab64890Smrg	    else bufp = Xmalloc (len + 1);
20481ab64890Smrg	    *bufp = 'A' + i;
20491ab64890Smrg	    *(bufp + 1) = ':';
20501ab64890Smrg	    *(bufp + 2) = '\0';
20511ab64890Smrg	    strcat (bufp, path);
20521ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
20531ab64890Smrg		if (bufp != buf) Xfree (bufp);
20541ab64890Smrg		return 1;
20551ab64890Smrg	    }
20561ab64890Smrg	}
20571ab64890Smrg    }
20581ab64890Smrg#endif
20591ab64890Smrg    return 0;
20601ab64890Smrg}
20611ab64890Smrg
20621ab64890Smrgint _XOpenFile(path, flags)
20631ab64890Smrg    _Xconst char* path;
20641ab64890Smrg    int flags;
20651ab64890Smrg{
20661ab64890Smrg    char buf[MAX_PATH];
20671ab64890Smrg    char* bufp = NULL;
20681ab64890Smrg    int ret = -1;
20691ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
20701ab64890Smrg
20711ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
20721ab64890Smrg	ret = open (bufp, flags);
20731ab64890Smrg
20741ab64890Smrg    (void) SetErrorMode (olderror);
20751ab64890Smrg
20761ab64890Smrg    if (bufp != buf) Xfree (bufp);
20771ab64890Smrg
20781ab64890Smrg    return ret;
20791ab64890Smrg}
20801ab64890Smrg
20811ab64890Smrgint _XOpenFileMode(path, flags, mode)
20821ab64890Smrg    _Xconst char* path;
20831ab64890Smrg    int flags;
20841ab64890Smrg    mode_t mode;
20851ab64890Smrg{
20861ab64890Smrg    char buf[MAX_PATH];
20871ab64890Smrg    char* bufp = NULL;
20881ab64890Smrg    int ret = -1;
20891ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
20901ab64890Smrg
20911ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
20921ab64890Smrg	ret = open (bufp, flags, mode);
20931ab64890Smrg
20941ab64890Smrg    (void) SetErrorMode (olderror);
20951ab64890Smrg
20961ab64890Smrg    if (bufp != buf) Xfree (bufp);
20971ab64890Smrg
20981ab64890Smrg    return ret;
20991ab64890Smrg}
21001ab64890Smrg
21011ab64890Smrgvoid* _XFopenFile(path, mode)
21021ab64890Smrg    _Xconst char* path;
21031ab64890Smrg    _Xconst char* mode;
21041ab64890Smrg{
21051ab64890Smrg    char buf[MAX_PATH];
21061ab64890Smrg    char* bufp = NULL;
21071ab64890Smrg    void* ret = NULL;
21081ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
21091ab64890Smrg
21101ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
21111ab64890Smrg	ret = fopen (bufp, mode);
21121ab64890Smrg
21131ab64890Smrg    (void) SetErrorMode (olderror);
21141ab64890Smrg
21151ab64890Smrg    if (bufp != buf) Xfree (bufp);
21161ab64890Smrg
21171ab64890Smrg    return ret;
21181ab64890Smrg}
21191ab64890Smrg
21201ab64890Smrgint _XAccessFile(path)
21211ab64890Smrg    _Xconst char* path;
21221ab64890Smrg{
21231ab64890Smrg    char buf[MAX_PATH];
21241ab64890Smrg    char* bufp;
21251ab64890Smrg    int ret = -1;
21261ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
21271ab64890Smrg
21281ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
21291ab64890Smrg
21301ab64890Smrg    (void) SetErrorMode (olderror);
21311ab64890Smrg
21321ab64890Smrg    if (bufp != buf) Xfree (bufp);
21331ab64890Smrg
21341ab64890Smrg    return ret;
21351ab64890Smrg}
21361ab64890Smrg
21371ab64890Smrg#endif
21381ab64890Smrg
21391ab64890Smrg#ifdef WIN32
21401ab64890Smrg#undef _Xdebug
21411ab64890Smrgint _Xdebug = 0;
21421ab64890Smrgint *_Xdebug_p = &_Xdebug;
21431ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
21441ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
21451ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
21461ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
21471ab64890Smrg    , char * /* file */
21481ab64890Smrg    , int /* line */
21491ab64890Smrg#endif
21501ab64890Smrg        ) = &_XLockMutex_fn;
21511ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
21521ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
21531ab64890Smrg    , char * /* file */
21541ab64890Smrg    , int /* line */
21551ab64890Smrg#endif
21561ab64890Smrg        ) = &_XUnlockMutex_fn;
21571ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
21581ab64890Smrg#endif
2159