XlibInt.c revision 2e9c7c8c
11ab64890Smrg/* $Xorg: XlibInt.c,v 1.8 2001/02/09 02:03:38 xorgcvs Exp $ */
21ab64890Smrg/*
31ab64890Smrg
41ab64890SmrgCopyright 1985, 1986, 1987, 1998  The Open Group
51ab64890Smrg
61ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
71ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
81ab64890Smrgthe above copyright notice appear in all copies and that both that
91ab64890Smrgcopyright notice and this permission notice appear in supporting
101ab64890Smrgdocumentation.
111ab64890Smrg
121ab64890SmrgThe above copyright notice and this permission notice shall be included
131ab64890Smrgin all copies or substantial portions of the Software.
141ab64890Smrg
151ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
161ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
171ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
181ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
191ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
211ab64890SmrgOTHER DEALINGS IN THE SOFTWARE.
221ab64890Smrg
231ab64890SmrgExcept as contained in this notice, the name of The Open Group shall
241ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or
251ab64890Smrgother dealings in this Software without prior written authorization
261ab64890Smrgfrom The Open Group.
271ab64890Smrg
281ab64890Smrg*/
291ab64890Smrg/* $XFree86: xc/lib/X11/XlibInt.c,v 3.38 2003/10/30 21:55:05 alanh Exp $ */
301ab64890Smrg
311ab64890Smrg/*
321ab64890Smrg *	XlibInt.c - Internal support routines for the C subroutine
331ab64890Smrg *	interface library (Xlib) to the X Window System Protocol V11.0.
341ab64890Smrg */
351ab64890Smrg#define NEED_EVENTS
361ab64890Smrg#define NEED_REPLIES
371ab64890Smrg
381ab64890Smrg#ifdef WIN32
391ab64890Smrg#define _XLIBINT_
401ab64890Smrg#endif
411ab64890Smrg#ifdef HAVE_CONFIG_H
421ab64890Smrg#include <config.h>
431ab64890Smrg#endif
441ab64890Smrg#include "Xlibint.h"
4561b2299dSmrg#include "Xprivate.h"
461ab64890Smrg#include <X11/Xpoll.h>
471ab64890Smrg#if !USE_XCB
481ab64890Smrg#include <X11/Xtrans/Xtrans.h>
491ab64890Smrg#include <X11/extensions/xcmiscstr.h>
501ab64890Smrg#endif /* !USE_XCB */
5161b2299dSmrg#include <assert.h>
521ab64890Smrg#include <stdio.h>
531ab64890Smrg#ifdef WIN32
541ab64890Smrg#include <direct.h>
551ab64890Smrg#endif
561ab64890Smrg
571ab64890Smrg#ifdef XTHREADS
581ab64890Smrg#include "locking.h"
591ab64890Smrg
601ab64890Smrg/* these pointers get initialized by XInitThreads */
611ab64890SmrgLockInfoPtr _Xglobal_lock = NULL;
621ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
631ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
641ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
651ab64890Smrgvoid (*_XLockMutex_fn)(
661ab64890Smrg    LockInfoPtr /* lock */
671ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
681ab64890Smrg    , char * /* file */
691ab64890Smrg    , int /* line */
701ab64890Smrg#endif
711ab64890Smrg    ) = NULL;
721ab64890Smrgvoid (*_XUnlockMutex_fn)(
731ab64890Smrg    LockInfoPtr /* lock */
741ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
751ab64890Smrg    , char * /* file */
761ab64890Smrg    , int /* line */
771ab64890Smrg#endif
781ab64890Smrg    ) = NULL;
791ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL;
801ab64890Smrg
811ab64890Smrg#define XThread_Self()	((*_Xthread_self_fn)())
821ab64890Smrg
831ab64890Smrg#if !USE_XCB
841ab64890Smrg#define UnlockNextReplyReader(d) if ((d)->lock) \
851ab64890Smrg    (*(d)->lock->pop_reader)((d),&(d)->lock->reply_awaiters,&(d)->lock->reply_awaiters_tail)
861ab64890Smrg
871ab64890Smrg#define QueueReplyReaderLock(d) ((d)->lock ? \
881ab64890Smrg    (*(d)->lock->push_reader)(d,&(d)->lock->reply_awaiters_tail) : NULL)
891ab64890Smrg#define QueueEventReaderLock(d) ((d)->lock ? \
901ab64890Smrg    (*(d)->lock->push_reader)(d,&(d)->lock->event_awaiters_tail) : NULL)
911ab64890Smrg
921ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
931ab64890Smrg#define InternalLockDisplay(d,wskip) if ((d)->lock) \
941ab64890Smrg    (*(d)->lock->internal_lock_display)(d,wskip,__FILE__,__LINE__)
951ab64890Smrg#else
961ab64890Smrg#define InternalLockDisplay(d,wskip) if ((d)->lock) \
971ab64890Smrg    (*(d)->lock->internal_lock_display)(d,wskip)
981ab64890Smrg#endif
991ab64890Smrg#endif /* !USE_XCB */
1001ab64890Smrg
1011ab64890Smrg#else /* XTHREADS else */
1021ab64890Smrg
1031ab64890Smrg#if !USE_XCB
10461b2299dSmrg#define UnlockNextReplyReader(d)
1051ab64890Smrg#define UnlockNextEventReader(d)
1061ab64890Smrg#define InternalLockDisplay(d,wskip)
1071ab64890Smrg#endif /* !USE_XCB */
1081ab64890Smrg
10961b2299dSmrg#endif /* XTHREADS else */
1101ab64890Smrg
1111ab64890Smrg/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
1121ab64890Smrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN
1131ab64890Smrg */
1141ab64890Smrg#ifdef WIN32
1151ab64890Smrg#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
1161ab64890Smrg#else
1171ab64890Smrg#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
1181ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
1191ab64890Smrg#else
1201ab64890Smrg#if defined(EAGAIN) && defined(EWOULDBLOCK)
1211ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
1221ab64890Smrg#else
1231ab64890Smrg#ifdef EAGAIN
1241ab64890Smrg#define ETEST() (errno == EAGAIN)
1251ab64890Smrg#else
1261ab64890Smrg#define ETEST() (errno == EWOULDBLOCK)
1271ab64890Smrg#endif /* EAGAIN */
1281ab64890Smrg#endif /* EAGAIN && EWOULDBLOCK */
1291ab64890Smrg#endif /* __CYGWIN__ */
1301ab64890Smrg#endif /* WIN32 */
1311ab64890Smrg
1321ab64890Smrg#ifdef WIN32
1331ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err)
1341ab64890Smrg#define ESET(val) WSASetLastError(val)
1351ab64890Smrg#else
1361ab64890Smrg#ifdef __UNIXOS2__
1371ab64890Smrg#define ECHECK(err) (errno == err)
1381ab64890Smrg#define ESET(val)
1391ab64890Smrg#else
1401ab64890Smrg#define ECHECK(err) (errno == err)
1411ab64890Smrg#define ESET(val) errno = val
1421ab64890Smrg#endif
1431ab64890Smrg#endif
1441ab64890Smrg
1451ab64890Smrg#if defined(LOCALCONN) || defined(LACHMAN)
1461ab64890Smrg#ifdef EMSGSIZE
1471ab64890Smrg#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
1481ab64890Smrg#else
1491ab64890Smrg#define ESZTEST() ECHECK(ERANGE)
1501ab64890Smrg#endif
1511ab64890Smrg#else
1521ab64890Smrg#ifdef EMSGSIZE
1531ab64890Smrg#define ESZTEST() ECHECK(EMSGSIZE)
1541ab64890Smrg#endif
1551ab64890Smrg#endif
1561ab64890Smrg
1571ab64890Smrg#ifdef __UNIXOS2__
1581ab64890Smrg#if !USE_XCB
1591ab64890Smrg#define select(n,r,w,x,t) os2ClientSelect(n,r,w,x,t)
1601ab64890Smrg#endif /* !USE_XCB */
1611ab64890Smrg#include <limits.h>
1621ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX
1631ab64890Smrg#endif
1641ab64890Smrg
1651ab64890Smrg#if !USE_XCB
1661ab64890Smrg#ifdef MUSTCOPY
1671ab64890Smrg
1681ab64890Smrg#define STARTITERATE(tpvar,type,start,endcond) \
1691ab64890Smrg  { register char *cpvar; \
1701ab64890Smrg  for (cpvar = (char *) (start); endcond; ) { \
1711ab64890Smrg    type dummy; memcpy ((char *) &dummy, cpvar, SIZEOF(type)); \
1721ab64890Smrg    tpvar = &dummy;
1731ab64890Smrg#define ITERPTR(tpvar) cpvar
1741ab64890Smrg#define RESETITERPTR(tpvar,type,start) cpvar = start
1751ab64890Smrg#define INCITERPTR(tpvar,type) cpvar += SIZEOF(type)
1761ab64890Smrg#define ENDITERATE }}
1771ab64890Smrg
1781ab64890Smrg#else
1791ab64890Smrg
1801ab64890Smrg#define STARTITERATE(tpvar,type,start,endcond) \
1811ab64890Smrg  for (tpvar = (type *) (start); endcond; )
1821ab64890Smrg#define ITERPTR(tpvar) (char *)tpvar
1831ab64890Smrg#define RESETITERPTR(tpvar,type,start) tpvar = (type *) (start)
1841ab64890Smrg#define INCITERPTR(tpvar,type) tpvar++
1851ab64890Smrg#define ENDITERATE
1861ab64890Smrg
1871ab64890Smrg#endif /* MUSTCOPY */
1881ab64890Smrg
1891ab64890Smrgtypedef union {
1901ab64890Smrg    xReply rep;
1911ab64890Smrg    char buf[BUFSIZE];
1921ab64890Smrg} _XAlignedBuffer;
1931ab64890Smrg
1941ab64890Smrgstatic char *_XAsyncReply(
1951ab64890Smrg    Display *dpy,
1961ab64890Smrg    register xReply *rep,
1971ab64890Smrg    char *buf,
1981ab64890Smrg    register int *lenp,
1991ab64890Smrg    Bool discard);
2001ab64890Smrg#endif /* !USE_XCB */
2011ab64890Smrg
2021ab64890Smrg/*
2031ab64890Smrg * The following routines are internal routines used by Xlib for protocol
2041ab64890Smrg * packet transmission and reception.
2051ab64890Smrg *
2061ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
2071ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
2081ab64890Smrg *
2091ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
2101ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
2111ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
2121ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
2131ab64890Smrg *
2141ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
21561b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
2161ab64890Smrg * return anything.  Whenever possible routines that create objects return
2171ab64890Smrg * the object they have created.
2181ab64890Smrg */
2191ab64890Smrg
2201ab64890Smrg#if !USE_XCB
2211ab64890Smrgstatic xReq _dummy_request = {
2221ab64890Smrg	0, 0, 0
2231ab64890Smrg};
2241ab64890Smrg
2251ab64890Smrg/*
2261ab64890Smrg * This is an OS dependent routine which:
2271ab64890Smrg * 1) returns as soon as the connection can be written on....
2281ab64890Smrg * 2) if the connection can be read, must enqueue events and handle errors,
2291ab64890Smrg * until the connection is writable.
2301ab64890Smrg */
2311ab64890Smrgstatic void
2321ab64890Smrg_XWaitForWritable(
2331ab64890Smrg    Display *dpy
2341ab64890Smrg#ifdef XTHREADS
2351ab64890Smrg    ,
2361ab64890Smrg    xcondition_t cv		/* our reading condition variable */
2371ab64890Smrg#endif
2381ab64890Smrg    )
2391ab64890Smrg{
2401ab64890Smrg#ifdef USE_POLL
2411ab64890Smrg    struct pollfd filedes;
2421ab64890Smrg#else
2431ab64890Smrg    fd_set r_mask;
2441ab64890Smrg    fd_set w_mask;
2451ab64890Smrg#endif
2461ab64890Smrg    int nfound;
2471ab64890Smrg
2481ab64890Smrg#ifdef USE_POLL
2491ab64890Smrg    filedes.fd = dpy->fd;
2501ab64890Smrg    filedes.events = 0;
2511ab64890Smrg#else
2521ab64890Smrg    FD_ZERO(&r_mask);
2531ab64890Smrg    FD_ZERO(&w_mask);
2541ab64890Smrg#endif
2551ab64890Smrg
2561ab64890Smrg    for (;;) {
2571ab64890Smrg#ifdef XTHREADS
2581ab64890Smrg	/* We allow only one thread at a time to read, to minimize
2591ab64890Smrg	   passing of read data between threads.
2601ab64890Smrg	   Now, who is it?  If there is a non-NULL reply_awaiters and
2611ab64890Smrg	   we (i.e., our cv) are not at the head of it, then whoever
2621ab64890Smrg	   is at the head is the reader, and we don't read.
2631ab64890Smrg	   Otherwise there is no reply_awaiters or we are at the
2641ab64890Smrg	   head, having just appended ourselves.
2651ab64890Smrg	   In this case, if there is a event_awaiters, then whoever
2661ab64890Smrg	   is at the head of it got there before we did, and they are the
2671ab64890Smrg	   reader.
2681ab64890Smrg
2691ab64890Smrg	   Last cases: no event_awaiters and we are at the head of
2701ab64890Smrg	   reply_awaiters or reply_awaiters is NULL: we are the reader,
2711ab64890Smrg	   since there is obviously no one else involved.
2721ab64890Smrg
2731ab64890Smrg	   XXX - what if cv is NULL and someone else comes along after
2741ab64890Smrg	   us while we are waiting?
2751ab64890Smrg	   */
27661b2299dSmrg
2771ab64890Smrg	if (!dpy->lock ||
2781ab64890Smrg	    (!dpy->lock->event_awaiters &&
2791ab64890Smrg	     (!dpy->lock->reply_awaiters ||
2801ab64890Smrg	      dpy->lock->reply_awaiters->cv == cv)))
2811ab64890Smrg#endif
2821ab64890Smrg#ifdef USE_POLL
2831ab64890Smrg	    filedes.events = POLLIN;
2841ab64890Smrg	filedes.events |= POLLOUT;
2851ab64890Smrg#else
2861ab64890Smrg	FD_SET(dpy->fd, &r_mask);
2871ab64890Smrg        FD_SET(dpy->fd, &w_mask);
2881ab64890Smrg#endif
2891ab64890Smrg
2901ab64890Smrg	do {
2911ab64890Smrg	    UnlockDisplay(dpy);
2921ab64890Smrg#ifdef USE_POLL
2931ab64890Smrg	    nfound = poll (&filedes, 1, -1);
2941ab64890Smrg#else
2951ab64890Smrg	    nfound = Select (dpy->fd + 1, &r_mask, &w_mask, NULL, NULL);
2961ab64890Smrg#endif
2971ab64890Smrg	    InternalLockDisplay(dpy, cv != NULL);
2982e9c7c8cSmrg	    if (nfound < 0 && !(ECHECK(EINTR) || ETEST()))
2991ab64890Smrg		_XIOError(dpy);
3001ab64890Smrg	} while (nfound <= 0);
3011ab64890Smrg
3021ab64890Smrg	if (
3031ab64890Smrg#ifdef USE_POLL
3041ab64890Smrg	    filedes.revents & POLLIN
3051ab64890Smrg#else
3061ab64890Smrg	    FD_ISSET(dpy->fd, &r_mask)
3071ab64890Smrg#endif
3081ab64890Smrg	    )
3091ab64890Smrg	{
3101ab64890Smrg	    _XAlignedBuffer buf;
3111ab64890Smrg	    BytesReadable_t pend;
3121ab64890Smrg	    register int len;
3131ab64890Smrg	    register xReply *rep;
3141ab64890Smrg
3151ab64890Smrg	    /* find out how much data can be read */
3161ab64890Smrg	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
3171ab64890Smrg		_XIOError(dpy);
3181ab64890Smrg	    len = pend;
3191ab64890Smrg
3201ab64890Smrg	    /* must read at least one xEvent; if none is pending, then
3211ab64890Smrg	       we'll just block waiting for it */
3221ab64890Smrg	    if (len < SIZEOF(xReply)
3231ab64890Smrg#ifdef XTHREADS
3241ab64890Smrg		|| dpy->async_handlers
3251ab64890Smrg#endif
3261ab64890Smrg		)
3271ab64890Smrg		len = SIZEOF(xReply);
32861b2299dSmrg
3291ab64890Smrg	    /* but we won't read more than the max buffer size */
3301ab64890Smrg	    if (len > BUFSIZE) len = BUFSIZE;
3311ab64890Smrg
3321ab64890Smrg	    /* round down to an integral number of XReps */
3331ab64890Smrg	    len = (len / SIZEOF(xReply)) * SIZEOF(xReply);
3341ab64890Smrg
3351ab64890Smrg	    (void) _XRead (dpy, buf.buf, (long) len);
3361ab64890Smrg
3371ab64890Smrg	    STARTITERATE(rep,xReply,buf.buf,len > 0) {
3381ab64890Smrg		if (rep->generic.type == X_Reply) {
3391ab64890Smrg                    int tmp = len;
3401ab64890Smrg		    RESETITERPTR(rep,xReply,
3411ab64890Smrg				 _XAsyncReply (dpy, rep,
3421ab64890Smrg					       ITERPTR(rep), &tmp, True));
3431ab64890Smrg                    len = tmp;
3441ab64890Smrg		    pend = len;
3451ab64890Smrg		} else {
3461ab64890Smrg		    if (rep->generic.type == X_Error)
3471ab64890Smrg			_XError (dpy, (xError *)rep);
3481ab64890Smrg		    else	/* must be an event packet */
3491ab64890Smrg			_XEnq (dpy, (xEvent *)rep);
3501ab64890Smrg		    INCITERPTR(rep,xReply);
3511ab64890Smrg		    len -= SIZEOF(xReply);
3521ab64890Smrg		}
3531ab64890Smrg	    } ENDITERATE
3541ab64890Smrg#ifdef XTHREADS
3551ab64890Smrg	    if (dpy->lock && dpy->lock->event_awaiters)
3561ab64890Smrg		ConditionSignal(dpy, dpy->lock->event_awaiters->cv);
3571ab64890Smrg#endif
3581ab64890Smrg	}
3591ab64890Smrg#ifdef USE_POLL
3601ab64890Smrg	if (filedes.revents & (POLLOUT|POLLHUP|POLLERR))
3611ab64890Smrg#else
3621ab64890Smrg	if (FD_ISSET(dpy->fd, &w_mask))
3631ab64890Smrg#endif
3641ab64890Smrg	{
3651ab64890Smrg#ifdef XTHREADS
3661ab64890Smrg	    if (dpy->lock) {
3671ab64890Smrg		ConditionBroadcast(dpy, dpy->lock->writers);
3681ab64890Smrg	    }
3691ab64890Smrg#endif
3701ab64890Smrg	    return;
3711ab64890Smrg	}
3721ab64890Smrg    }
3731ab64890Smrg}
3741ab64890Smrg#endif /* !USE_XCB */
3751ab64890Smrg
3761ab64890Smrg
3771ab64890Smrg#define POLLFD_CACHE_SIZE 5
3781ab64890Smrg
3791ab64890Smrg/* initialize the struct array passed to poll() below */
3801ab64890SmrgBool _XPollfdCacheInit(
3811ab64890Smrg    Display *dpy)
3821ab64890Smrg{
3831ab64890Smrg#ifdef USE_POLL
3841ab64890Smrg    struct pollfd *pfp;
3851ab64890Smrg
3861ab64890Smrg    pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
3871ab64890Smrg    if (!pfp)
3881ab64890Smrg	return False;
3891ab64890Smrg    pfp[0].fd = dpy->fd;
3901ab64890Smrg    pfp[0].events = POLLIN;
3911ab64890Smrg
3921ab64890Smrg    dpy->filedes = (XPointer)pfp;
3931ab64890Smrg#endif
3941ab64890Smrg    return True;
3951ab64890Smrg}
3961ab64890Smrg
3971ab64890Smrgvoid _XPollfdCacheAdd(
3981ab64890Smrg    Display *dpy,
3991ab64890Smrg    int fd)
4001ab64890Smrg{
4011ab64890Smrg#ifdef USE_POLL
4021ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
4031ab64890Smrg
4041ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
4051ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
4061ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
4071ab64890Smrg    }
4081ab64890Smrg#endif
4091ab64890Smrg}
4101ab64890Smrg
4111ab64890Smrg/* ARGSUSED */
4121ab64890Smrgvoid _XPollfdCacheDel(
4131ab64890Smrg    Display *dpy,
4141ab64890Smrg    int fd)			/* not used */
4151ab64890Smrg{
4161ab64890Smrg#ifdef USE_POLL
4171ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
4181ab64890Smrg    struct _XConnectionInfo *conni;
4191ab64890Smrg
4201ab64890Smrg    /* just recalculate whole list */
4211ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
4221ab64890Smrg	int loc = 1;
4231ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
4241ab64890Smrg	    pfp[loc].fd = conni->fd;
4251ab64890Smrg	    pfp[loc].events = POLLIN;
4261ab64890Smrg	    loc++;
4271ab64890Smrg	}
4281ab64890Smrg    }
4291ab64890Smrg#endif
4301ab64890Smrg}
4311ab64890Smrg
4321ab64890Smrg#if !USE_XCB
4331ab64890Smrg/* returns True iff there is an event in the queue newer than serial_num */
4341ab64890Smrg
4351ab64890Smrgstatic Bool
4361ab64890Smrg_XNewerQueuedEvent(
4371ab64890Smrg    Display *dpy,
4381ab64890Smrg    int serial_num)
4391ab64890Smrg{
4401ab64890Smrg    _XQEvent *qev;
4411ab64890Smrg
4421ab64890Smrg    if (dpy->next_event_serial_num == serial_num)
4431ab64890Smrg	return False;
4441ab64890Smrg
4451ab64890Smrg    qev = dpy->head;
4461ab64890Smrg    while (qev) {
4471ab64890Smrg	if (qev->qserial_num >= serial_num) {
4481ab64890Smrg	    return True;
4491ab64890Smrg	}
4501ab64890Smrg	qev = qev->next;
4511ab64890Smrg    }
4521ab64890Smrg    return False;
4531ab64890Smrg}
4541ab64890Smrg
4551ab64890Smrgstatic int
4561ab64890Smrg_XWaitForReadable(
4571ab64890Smrg  Display *dpy)
4581ab64890Smrg{
4591ab64890Smrg    int result;
4601ab64890Smrg    int fd = dpy->fd;
46161b2299dSmrg    struct _XConnectionInfo *ilist;
4621ab64890Smrg    register int saved_event_serial = 0;
4631ab64890Smrg    int in_read_events = 0;
4641ab64890Smrg    register Bool did_proc_conni = False;
4651ab64890Smrg#ifdef USE_POLL
4661ab64890Smrg    struct pollfd *filedes;
4671ab64890Smrg#else
4681ab64890Smrg    fd_set r_mask;
4691ab64890Smrg    int highest_fd = fd;
4701ab64890Smrg#endif
4711ab64890Smrg
4721ab64890Smrg#ifdef USE_POLL
4731ab64890Smrg    if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE
4741ab64890Smrg	&& !(dpy->flags & XlibDisplayProcConni)) {
4751ab64890Smrg	/* XXX - this fallback is gross */
4761ab64890Smrg	int i;
4771ab64890Smrg
4781ab64890Smrg	filedes = (struct pollfd *)Xmalloc(dpy->im_fd_length * sizeof(struct pollfd));
4791ab64890Smrg	filedes[0].fd = fd;
4801ab64890Smrg	filedes[0].events = POLLIN;
4811ab64890Smrg	for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) {
4821ab64890Smrg	    filedes[i].fd = ilist->fd;
4831ab64890Smrg	    filedes[i].events = POLLIN;
4841ab64890Smrg	}
4851ab64890Smrg    } else {
4861ab64890Smrg	filedes = (struct pollfd *)dpy->filedes;
4871ab64890Smrg    }
4881ab64890Smrg#else
4891ab64890Smrg    FD_ZERO(&r_mask);
4901ab64890Smrg#endif
4911ab64890Smrg    for (;;) {
4921ab64890Smrg#ifndef USE_POLL
4931ab64890Smrg	FD_SET(fd, &r_mask);
4941ab64890Smrg	if (!(dpy->flags & XlibDisplayProcConni))
4951ab64890Smrg	    for (ilist=dpy->im_fd_info; ilist; ilist=ilist->next) {
4961ab64890Smrg		FD_SET(ilist->fd, &r_mask);
4971ab64890Smrg		if (ilist->fd > highest_fd)
4981ab64890Smrg		    highest_fd = ilist->fd;
4991ab64890Smrg	    }
5001ab64890Smrg#endif
5011ab64890Smrg	UnlockDisplay(dpy);
5021ab64890Smrg#ifdef USE_POLL
5031ab64890Smrg	result = poll(filedes,
5041ab64890Smrg		      (dpy->flags & XlibDisplayProcConni) ? 1 : 1+dpy->im_fd_length,
5051ab64890Smrg		      -1);
5061ab64890Smrg#else
5071ab64890Smrg	result = Select(highest_fd + 1, &r_mask, NULL, NULL, NULL);
5081ab64890Smrg#endif
5091ab64890Smrg	InternalLockDisplay(dpy, dpy->flags & XlibDisplayReply);
5102e9c7c8cSmrg	if (result == -1 && !(ECHECK(EINTR) || ETEST())) _XIOError(dpy);
5111ab64890Smrg	if (result <= 0)
5121ab64890Smrg	    continue;
5131ab64890Smrg#ifdef USE_POLL
5141ab64890Smrg	if (filedes[0].revents & (POLLIN|POLLHUP|POLLERR))
5151ab64890Smrg#else
5161ab64890Smrg	if (FD_ISSET(fd, &r_mask))
5171ab64890Smrg#endif
5181ab64890Smrg	    break;
5191ab64890Smrg	if (!(dpy->flags & XlibDisplayProcConni)) {
5201ab64890Smrg	    int i;
5211ab64890Smrg
5221ab64890Smrg	    saved_event_serial = dpy->next_event_serial_num;
5231ab64890Smrg	    /* dpy flags can be clobbered by internal connection callback */
5241ab64890Smrg	    in_read_events = dpy->flags & XlibDisplayReadEvents;
5251ab64890Smrg	    for (ilist=dpy->im_fd_info, i=1; ilist; ilist=ilist->next, i++) {
5261ab64890Smrg#ifdef USE_POLL
5271ab64890Smrg		if (filedes[i].revents & POLLIN)
5281ab64890Smrg#else
5291ab64890Smrg		if (FD_ISSET(ilist->fd, &r_mask))
5301ab64890Smrg#endif
5311ab64890Smrg		{
5321ab64890Smrg		    _XProcessInternalConnection(dpy, ilist);
5331ab64890Smrg		    did_proc_conni = True;
5341ab64890Smrg		}
5351ab64890Smrg	    }
5361ab64890Smrg#ifdef USE_POLL
5371ab64890Smrg	    if (dpy->im_fd_length + 1 > POLLFD_CACHE_SIZE)
5381ab64890Smrg		Xfree(filedes);
5391ab64890Smrg#endif
5401ab64890Smrg	}
5411ab64890Smrg	if (did_proc_conni) {
5421ab64890Smrg	    /* some internal connection callback might have done an
5431ab64890Smrg	       XPutBackEvent.  We notice it here and if we needed an event,
5441ab64890Smrg	       we can return all the way. */
5451ab64890Smrg	    if (_XNewerQueuedEvent(dpy, saved_event_serial)
5461ab64890Smrg		&& (in_read_events
5471ab64890Smrg#ifdef XTHREADS
5481ab64890Smrg		    || (dpy->lock && dpy->lock->event_awaiters)
5491ab64890Smrg#endif
5501ab64890Smrg		    ))
5511ab64890Smrg		return -2;
5521ab64890Smrg	    did_proc_conni = False;
5531ab64890Smrg	}
5541ab64890Smrg    }
5551ab64890Smrg#ifdef XTHREADS
5561ab64890Smrg#ifdef XTHREADS_DEBUG
5571ab64890Smrg    printf("thread %x _XWaitForReadable returning\n", XThread_Self());
5581ab64890Smrg#endif
5591ab64890Smrg#endif
5601ab64890Smrg    return 0;
5611ab64890Smrg}
5621ab64890Smrg#endif /* !USE_XCB */
5631ab64890Smrg
56461b2299dSmrgstatic int sync_hazard(Display *dpy)
56561b2299dSmrg{
56661b2299dSmrg    unsigned long span = dpy->request - dpy->last_request_read;
56761b2299dSmrg    unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
56861b2299dSmrg    return span >= 65535 - hazard - 10;
56961b2299dSmrg}
57061b2299dSmrg
5711ab64890Smrgstatic
5721ab64890Smrgint _XSeqSyncFunction(
5731ab64890Smrg    register Display *dpy)
5741ab64890Smrg{
5751ab64890Smrg    xGetInputFocusReply rep;
5761ab64890Smrg    register xReq *req;
57761b2299dSmrg    int sent_sync = 0;
5781ab64890Smrg
5791ab64890Smrg    LockDisplay(dpy);
58061b2299dSmrg    if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
5811ab64890Smrg	GetEmptyReq(GetInputFocus, req);
5821ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
58361b2299dSmrg	sent_sync = 1;
58461b2299dSmrg    } else if (sync_hazard(dpy))
58561b2299dSmrg	_XSetPrivSyncFunction(dpy);
5861ab64890Smrg    UnlockDisplay(dpy);
58761b2299dSmrg    if (sent_sync)
58861b2299dSmrg        SyncHandle();
5891ab64890Smrg    return 0;
5901ab64890Smrg}
5911ab64890Smrg
59261b2299dSmrgstatic int
59361b2299dSmrg_XPrivSyncFunction (Display *dpy)
59461b2299dSmrg{
59561b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
59661b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
59761b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
59861b2299dSmrg    dpy->savedsynchandler = NULL;
59961b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
60061b2299dSmrg    _XIDHandler(dpy);
60161b2299dSmrg    _XSeqSyncFunction(dpy);
60261b2299dSmrg    return 0;
60361b2299dSmrg}
60461b2299dSmrg
60561b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
6061ab64890Smrg{
60761b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
6081ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
60961b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
6101ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
6111ab64890Smrg    }
6121ab64890Smrg}
6131ab64890Smrg
61461b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
61561b2299dSmrg{
61661b2299dSmrg    if (sync_hazard(dpy))
61761b2299dSmrg	_XSetPrivSyncFunction (dpy);
61861b2299dSmrg}
61961b2299dSmrg
6201ab64890Smrg#if !USE_XCB
6211ab64890Smrg#ifdef XTHREADS
6221ab64890Smrgstatic void _XFlushInt(
6231ab64890Smrg        register Display *dpy,
6241ab64890Smrg        register xcondition_t cv);
6251ab64890Smrg#endif
6261ab64890Smrg
6271ab64890Smrg/*
6281ab64890Smrg * _XFlush - Flush the X request buffer.  If the buffer is empty, no
6291ab64890Smrg * action is taken.  This routine correctly handles incremental writes.
6301ab64890Smrg * This routine may have to be reworked if int < long.
6311ab64890Smrg */
6321ab64890Smrgvoid _XFlush(
6331ab64890Smrg	register Display *dpy)
6341ab64890Smrg{
6351ab64890Smrg#ifdef XTHREADS
6361ab64890Smrg    /* With multi-threading we introduce an internal routine to which
6371ab64890Smrg       we can pass a condition variable to do locking correctly. */
6381ab64890Smrg
6391ab64890Smrg    _XFlushInt(dpy, NULL);
6401ab64890Smrg}
6411ab64890Smrg
6421ab64890Smrg/* _XFlushInt - Internal version of _XFlush used to do multi-threaded
6431ab64890Smrg * locking correctly.
6441ab64890Smrg */
6451ab64890Smrg
6461ab64890Smrgstatic void _XFlushInt(
6471ab64890Smrg	register Display *dpy,
6481ab64890Smrg        register xcondition_t cv)
6491ab64890Smrg{
6501ab64890Smrg#endif /* XTHREADS*/
6511ab64890Smrg	register long size, todo;
6521ab64890Smrg	register int write_stat;
6531ab64890Smrg	register char *bufindex;
6541ab64890Smrg	_XExtension *ext;
6551ab64890Smrg
6561ab64890Smrg	/* This fix resets the bufptr to the front of the buffer so
6571ab64890Smrg	 * additional appends to the bufptr will not corrupt memory. Since
65861b2299dSmrg	 * the server is down, these appends are no-op's anyway but
6591ab64890Smrg	 * callers of _XFlush() are not verifying this before they call it.
6601ab64890Smrg	 */
6611ab64890Smrg	if (dpy->flags & XlibDisplayIOError)
6621ab64890Smrg	{
6631ab64890Smrg	    dpy->bufptr = dpy->buffer;
6641ab64890Smrg	    dpy->last_req = (char *)&_dummy_request;
6651ab64890Smrg	    return;
6661ab64890Smrg	}
6671ab64890Smrg
6681ab64890Smrg#ifdef XTHREADS
6691ab64890Smrg	while (dpy->flags & XlibDisplayWriting) {
6701ab64890Smrg	    if (dpy->lock) {
6711ab64890Smrg		ConditionWait(dpy, dpy->lock->writers);
6721ab64890Smrg	    } else {
6731ab64890Smrg		_XWaitForWritable (dpy, cv);
6741ab64890Smrg	    }
6751ab64890Smrg	}
6761ab64890Smrg#endif
6771ab64890Smrg	size = todo = dpy->bufptr - dpy->buffer;
6781ab64890Smrg	if (!size) return;
6791ab64890Smrg#ifdef XTHREADS
6801ab64890Smrg	dpy->flags |= XlibDisplayWriting;
6811ab64890Smrg	/* make sure no one else can put in data */
6821ab64890Smrg	dpy->bufptr = dpy->bufmax;
6831ab64890Smrg#endif
6841ab64890Smrg	for (ext = dpy->flushes; ext; ext = ext->next_flush)
6851ab64890Smrg	    (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, size);
6861ab64890Smrg	bufindex = dpy->buffer;
6871ab64890Smrg	/*
6881ab64890Smrg	 * While write has not written the entire buffer, keep looping
6891ab64890Smrg	 * until the entire buffer is written.  bufindex will be
6901ab64890Smrg	 * incremented and size decremented as buffer is written out.
6911ab64890Smrg	 */
6921ab64890Smrg	while (size) {
6931ab64890Smrg	    ESET(0);
6941ab64890Smrg	    write_stat = _X11TransWrite(dpy->trans_conn,
6951ab64890Smrg					bufindex, (int) todo);
6961ab64890Smrg	    if (write_stat >= 0) {
6971ab64890Smrg		size -= write_stat;
6981ab64890Smrg		todo = size;
6991ab64890Smrg		bufindex += write_stat;
7001ab64890Smrg	    } else if (ETEST()) {
7011ab64890Smrg		_XWaitForWritable(dpy
7021ab64890Smrg#ifdef XTHREADS
7031ab64890Smrg				  , cv
7041ab64890Smrg#endif
7051ab64890Smrg				  );
7061ab64890Smrg#ifdef SUNSYSV
7071ab64890Smrg	    } else if (ECHECK(0)) {
7081ab64890Smrg		_XWaitForWritable(dpy
7091ab64890Smrg#ifdef XTHREADS
7101ab64890Smrg				  , cv
7111ab64890Smrg#endif
7121ab64890Smrg				  );
7131ab64890Smrg#endif
7141ab64890Smrg#ifdef ESZTEST
7151ab64890Smrg	    } else if (ESZTEST()) {
71661b2299dSmrg		if (todo > 1)
7171ab64890Smrg		    todo >>= 1;
7181ab64890Smrg		else {
7191ab64890Smrg		    _XWaitForWritable(dpy
7201ab64890Smrg#ifdef XTHREADS
7211ab64890Smrg				      , cv
7221ab64890Smrg#endif
7231ab64890Smrg				      );
7241ab64890Smrg		}
7251ab64890Smrg#endif
7261ab64890Smrg	    } else if (!ECHECK(EINTR)) {
7271ab64890Smrg		/* Write failed! */
7281ab64890Smrg		/* errno set by write system call. */
7291ab64890Smrg		_XIOError(dpy);
7301ab64890Smrg	    }
7311ab64890Smrg	}
7321ab64890Smrg	dpy->last_req = (char *)&_dummy_request;
7331ab64890Smrg	_XSetSeqSyncFunction(dpy);
7341ab64890Smrg	dpy->bufptr = dpy->buffer;
7351ab64890Smrg#ifdef XTHREADS
7361ab64890Smrg	dpy->flags &= ~XlibDisplayWriting;
7371ab64890Smrg#endif
7381ab64890Smrg}
7391ab64890Smrg
7401ab64890Smrgint
7411ab64890Smrg_XEventsQueued(
7421ab64890Smrg    register Display *dpy,
7431ab64890Smrg    int mode)
7441ab64890Smrg{
7451ab64890Smrg	register int len;
7461ab64890Smrg	BytesReadable_t pend;
7471ab64890Smrg	_XAlignedBuffer buf;
7481ab64890Smrg	register xReply *rep;
7491ab64890Smrg	char *read_buf;
7501ab64890Smrg#ifdef XTHREADS
7511ab64890Smrg	int entry_event_serial_num;
7521ab64890Smrg	struct _XCVList *cvl = NULL;
7531ab64890Smrg	xthread_t self;
7541ab64890Smrg
7551ab64890Smrg#ifdef XTHREADS_DEBUG
7561ab64890Smrg	printf("_XEventsQueued called in thread %x\n", XThread_Self());
7571ab64890Smrg#endif
7581ab64890Smrg#endif /* XTHREADS*/
7591ab64890Smrg
7601ab64890Smrg	if (mode == QueuedAfterFlush)
7611ab64890Smrg	{
7621ab64890Smrg	    _XFlush(dpy);
7631ab64890Smrg	    if (dpy->qlen)
7641ab64890Smrg		return(dpy->qlen);
7651ab64890Smrg	}
7661ab64890Smrg	if (dpy->flags & XlibDisplayIOError) return(dpy->qlen);
7671ab64890Smrg
7681ab64890Smrg#ifdef XTHREADS
7691ab64890Smrg	/* create our condition variable and append to list,
7701ab64890Smrg	 * unless we were called from within XProcessInternalConnection
7711ab64890Smrg	 * or XLockDisplay
7721ab64890Smrg	 */
7731ab64890Smrg	xthread_clear_id(self);
7741ab64890Smrg	if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread)
7751ab64890Smrg			  || xthread_have_id (dpy->lock->locking_thread)))
7761ab64890Smrg	    /* some thread is in XProcessInternalConnection or XLockDisplay
7771ab64890Smrg	       so we have to see if we are it */
7781ab64890Smrg	    self = XThread_Self();
7791ab64890Smrg	if (!xthread_have_id(self)
7801ab64890Smrg	    || (!xthread_equal(self, dpy->lock->conni_thread)
7811ab64890Smrg		&& !xthread_equal(self, dpy->lock->locking_thread))) {
7821ab64890Smrg	    /* In the multi-threaded case, if there is someone else
7831ab64890Smrg	       reading events, then there aren't any available, so
7841ab64890Smrg	       we just return.  If we waited we would block.
7851ab64890Smrg	       */
7861ab64890Smrg	    if (dpy->lock && dpy->lock->event_awaiters)
7871ab64890Smrg		return dpy->qlen;
7881ab64890Smrg	    /* nobody here but us, so lock out any newcomers */
7891ab64890Smrg	    cvl = QueueEventReaderLock(dpy);
7901ab64890Smrg	}
7911ab64890Smrg
7921ab64890Smrg	while (dpy->lock && cvl && dpy->lock->reply_first) {
7931ab64890Smrg	    /* note which events we have already seen so we'll know
7941ab64890Smrg	       if _XReply (in another thread) reads one */
7951ab64890Smrg	    entry_event_serial_num = dpy->next_event_serial_num;
7961ab64890Smrg	    ConditionWait(dpy, cvl->cv);
7971ab64890Smrg	    /* did _XReply read an event we can return? */
7981ab64890Smrg	    if (_XNewerQueuedEvent(dpy, entry_event_serial_num))
7991ab64890Smrg	    {
8001ab64890Smrg		UnlockNextEventReader(dpy);
8011ab64890Smrg		return 0;
8021ab64890Smrg	    }
8031ab64890Smrg	}
8041ab64890Smrg#endif /* XTHREADS*/
8051ab64890Smrg
8061ab64890Smrg	if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
8071ab64890Smrg	    _XIOError(dpy);
8081ab64890Smrg#ifdef XCONN_CHECK_FREQ
8091ab64890Smrg	/* This is a crock, required because FIONREAD or equivalent is
8101ab64890Smrg	 * not guaranteed to detect a broken connection.
8111ab64890Smrg	 */
8121ab64890Smrg	if (!pend && !dpy->qlen && ++dpy->conn_checker >= XCONN_CHECK_FREQ)
8131ab64890Smrg	{
8141ab64890Smrg	    int	result;
8151ab64890Smrg#ifdef USE_POLL
8161ab64890Smrg	    struct pollfd filedes;
8171ab64890Smrg#else
8181ab64890Smrg	    fd_set r_mask;
8191ab64890Smrg	    static struct timeval zero_time;
8201ab64890Smrg#endif
8211ab64890Smrg
8221ab64890Smrg	    dpy->conn_checker = 0;
8231ab64890Smrg#ifdef USE_POLL
8241ab64890Smrg	    filedes.fd = dpy->fd;
8251ab64890Smrg	    filedes.events = POLLIN;
8261ab64890Smrg	    if ((result = poll(&filedes, 1, 0)))
8271ab64890Smrg#else
8281ab64890Smrg	    FD_ZERO(&r_mask);
8291ab64890Smrg	    FD_SET(dpy->fd, &r_mask);
8301ab64890Smrg	    if ((result = Select(dpy->fd + 1, &r_mask, NULL, NULL, &zero_time)))
8311ab64890Smrg#endif
8321ab64890Smrg	    {
8331ab64890Smrg		if (result > 0)
8341ab64890Smrg		{
8351ab64890Smrg		    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
8361ab64890Smrg			_XIOError(dpy);
8371ab64890Smrg		    /* we should not get zero, if we do, force a read */
8381ab64890Smrg		    if (!pend)
8391ab64890Smrg			pend = SIZEOF(xReply);
8401ab64890Smrg		}
8412e9c7c8cSmrg		else if (result < 0 && !(ECHECK(EINTR) || ETEST()))
8421ab64890Smrg		    _XIOError(dpy);
8431ab64890Smrg	    }
8441ab64890Smrg	}
8451ab64890Smrg#endif /* XCONN_CHECK_FREQ */
8461ab64890Smrg	if (!(len = pend)) {
8471ab64890Smrg	    /* _XFlush can enqueue events */
8481ab64890Smrg#ifdef XTHREADS
8491ab64890Smrg	    if (cvl)
8501ab64890Smrg#endif
8511ab64890Smrg	    {
8521ab64890Smrg		UnlockNextEventReader(dpy);
8531ab64890Smrg	    }
8541ab64890Smrg	    return(dpy->qlen);
8551ab64890Smrg	}
8561ab64890Smrg      /* Force a read if there is not enough data.  Otherwise,
8571ab64890Smrg       * a select() loop at a higher-level will spin undesirably,
8581ab64890Smrg       * and we've seen at least one OS that appears to not update
8591ab64890Smrg       * the result from FIONREAD once it has returned nonzero.
8601ab64890Smrg       */
8611ab64890Smrg#ifdef XTHREADS
8621ab64890Smrg	if (dpy->lock && dpy->lock->reply_awaiters) {
8631ab64890Smrg	    read_buf = (char *)dpy->lock->reply_awaiters->buf;
8641ab64890Smrg	    len = SIZEOF(xReply);
8651ab64890Smrg	} else
8661ab64890Smrg#endif /* XTHREADS*/
8671ab64890Smrg	{
8681ab64890Smrg	    read_buf = buf.buf;
86961b2299dSmrg
8701ab64890Smrg	    if (len < SIZEOF(xReply)
8711ab64890Smrg#ifdef XTHREADS
8721ab64890Smrg		|| dpy->async_handlers
8731ab64890Smrg#endif
8741ab64890Smrg		)
8751ab64890Smrg		len = SIZEOF(xReply);
8761ab64890Smrg	    else if (len > BUFSIZE)
8771ab64890Smrg		len = BUFSIZE;
8781ab64890Smrg	    len = (len / SIZEOF(xReply)) * SIZEOF(xReply);
8791ab64890Smrg	}
8801ab64890Smrg#ifdef XCONN_CHECK_FREQ
8811ab64890Smrg	dpy->conn_checker = 0;
8821ab64890Smrg#endif
8831ab64890Smrg
8841ab64890Smrg	(void) _XRead (dpy, read_buf, (long) len);
88561b2299dSmrg
8861ab64890Smrg#ifdef XTHREADS
8871ab64890Smrg	/* what did we actually read: reply or event? */
8881ab64890Smrg	if (dpy->lock && dpy->lock->reply_awaiters) {
8891ab64890Smrg	    if (((xReply *)read_buf)->generic.type == X_Reply ||
8901ab64890Smrg		((xReply *)read_buf)->generic.type == X_Error)
8911ab64890Smrg	    {
8921ab64890Smrg		dpy->lock->reply_was_read = True;
8931ab64890Smrg		dpy->lock->reply_first = True;
8941ab64890Smrg		if (read_buf != (char *)dpy->lock->reply_awaiters->buf)
8951ab64890Smrg		    memcpy(dpy->lock->reply_awaiters->buf, read_buf,
8961ab64890Smrg			   len);
8971ab64890Smrg		if (cvl) {
8981ab64890Smrg		    UnlockNextEventReader(dpy);
8991ab64890Smrg		}
9001ab64890Smrg		return(dpy->qlen); /* we read, so we can return */
9011ab64890Smrg	    } else if (read_buf != buf.buf)
9021ab64890Smrg		memcpy(buf.buf, read_buf, len);
9031ab64890Smrg	}
9041ab64890Smrg#endif /* XTHREADS*/
9051ab64890Smrg
9061ab64890Smrg	STARTITERATE(rep,xReply,buf.buf,len > 0) {
9071ab64890Smrg	    if (rep->generic.type == X_Reply) {
9081ab64890Smrg                int tmp = len;
9091ab64890Smrg		RESETITERPTR(rep,xReply,
9101ab64890Smrg			     _XAsyncReply (dpy, rep,
9111ab64890Smrg					   ITERPTR(rep), &tmp, True));
9121ab64890Smrg                len = tmp;
9131ab64890Smrg		pend = len;
9141ab64890Smrg	    } else {
9151ab64890Smrg		if (rep->generic.type == X_Error)
9161ab64890Smrg		    _XError (dpy, (xError *)rep);
9171ab64890Smrg		else   /* must be an event packet */
9181ab64890Smrg		    _XEnq (dpy, (xEvent *)rep);
9191ab64890Smrg		INCITERPTR(rep,xReply);
9201ab64890Smrg		len -= SIZEOF(xReply);
9211ab64890Smrg	    }
9221ab64890Smrg	} ENDITERATE
9231ab64890Smrg
9241ab64890Smrg#ifdef XTHREADS
9251ab64890Smrg	if (cvl)
9261ab64890Smrg#endif
9271ab64890Smrg	{
9281ab64890Smrg	    UnlockNextEventReader(dpy);
9291ab64890Smrg	}
9301ab64890Smrg	return(dpy->qlen);
9311ab64890Smrg}
9321ab64890Smrg
9331ab64890Smrg/* _XReadEvents - Flush the output queue,
9341ab64890Smrg * then read as many events as possible (but at least 1) and enqueue them
9351ab64890Smrg */
9361ab64890Smrgvoid _XReadEvents(
9371ab64890Smrg	register Display *dpy)
9381ab64890Smrg{
9391ab64890Smrg	_XAlignedBuffer buf;
9401ab64890Smrg	BytesReadable_t pend;
9411ab64890Smrg	int len;
9421ab64890Smrg	register xReply *rep;
9431ab64890Smrg	Bool not_yet_flushed = True;
9441ab64890Smrg	char *read_buf;
9451ab64890Smrg	int i;
9461ab64890Smrg	int entry_event_serial_num = dpy->next_event_serial_num;
9471ab64890Smrg#ifdef XTHREADS
9481ab64890Smrg	struct _XCVList *cvl = NULL;
9491ab64890Smrg	xthread_t self;
9501ab64890Smrg
9511ab64890Smrg#ifdef XTHREADS_DEBUG
9521ab64890Smrg	printf("_XReadEvents called in thread %x\n",
9531ab64890Smrg	       XThread_Self());
9541ab64890Smrg#endif
9551ab64890Smrg	/* create our condition variable and append to list,
9561ab64890Smrg	 * unless we were called from within XProcessInternalConnection
9571ab64890Smrg	 * or XLockDisplay
9581ab64890Smrg	 */
9591ab64890Smrg	xthread_clear_id(self);
9601ab64890Smrg	if (dpy->lock && (xthread_have_id (dpy->lock->conni_thread)
9611ab64890Smrg			  || xthread_have_id (dpy->lock->locking_thread)))
9621ab64890Smrg	    /* some thread is in XProcessInternalConnection or XLockDisplay
9631ab64890Smrg	       so we have to see if we are it */
9641ab64890Smrg	    self = XThread_Self();
9651ab64890Smrg	if (!xthread_have_id(self)
9661ab64890Smrg	    || (!xthread_equal(self, dpy->lock->conni_thread)
9671ab64890Smrg		&& !xthread_equal(self, dpy->lock->locking_thread)))
9681ab64890Smrg	    cvl = QueueEventReaderLock(dpy);
9691ab64890Smrg#endif /* XTHREADS */
9701ab64890Smrg
9711ab64890Smrg	do {
9721ab64890Smrg#ifdef XTHREADS
9731ab64890Smrg	    /* if it is not our turn to read an event off the wire,
9741ab64890Smrg	       wait til we're at head of list */
9751ab64890Smrg	    if (dpy->lock && cvl &&
9761ab64890Smrg		(dpy->lock->event_awaiters != cvl ||
9771ab64890Smrg		 dpy->lock->reply_first)) {
9781ab64890Smrg		ConditionWait(dpy, cvl->cv);
9791ab64890Smrg		continue;
9801ab64890Smrg	    }
9811ab64890Smrg#endif /* XTHREADS */
9821ab64890Smrg	    /* find out how much data can be read */
9831ab64890Smrg	    if (_X11TransBytesReadable(dpy->trans_conn, &pend) < 0)
9841ab64890Smrg	    	_XIOError(dpy);
9851ab64890Smrg	    len = pend;
9861ab64890Smrg
9871ab64890Smrg	    /* must read at least one xEvent; if none is pending, then
9881ab64890Smrg	       we'll just flush and block waiting for it */
9891ab64890Smrg	    if (len < SIZEOF(xEvent)
9901ab64890Smrg#ifdef XTHREADS
9911ab64890Smrg		|| dpy->async_handlers
9921ab64890Smrg#endif
9931ab64890Smrg		) {
9941ab64890Smrg	    	len = SIZEOF(xEvent);
9951ab64890Smrg		/* don't flush until the first time we would block */
9961ab64890Smrg		if (not_yet_flushed) {
9971ab64890Smrg		    _XFlush (dpy);
9981ab64890Smrg		    if (_XNewerQueuedEvent(dpy, entry_event_serial_num)) {
9991ab64890Smrg			/* _XReply has read an event for us */
10001ab64890Smrg			goto got_event;
10011ab64890Smrg		    }
10021ab64890Smrg		    not_yet_flushed = False;
10031ab64890Smrg		}
10041ab64890Smrg	    }
10051ab64890Smrg
10061ab64890Smrg#ifdef XTHREADS
10071ab64890Smrg	    /* If someone is waiting for a reply, gamble that
10081ab64890Smrg	       the reply will be the next thing on the wire
10091ab64890Smrg	       and read it into their buffer. */
10101ab64890Smrg	    if (dpy->lock && dpy->lock->reply_awaiters) {
10111ab64890Smrg		read_buf = (char *)dpy->lock->reply_awaiters->buf;
10121ab64890Smrg		len = SIZEOF(xReply);
10131ab64890Smrg	    } else
10141ab64890Smrg#endif /* XTHREADS*/
10151ab64890Smrg	    {
10161ab64890Smrg		read_buf = buf.buf;
10171ab64890Smrg
10181ab64890Smrg		/* but we won't read more than the max buffer size */
10191ab64890Smrg		if (len > BUFSIZE)
10201ab64890Smrg		    len = BUFSIZE;
10211ab64890Smrg
10221ab64890Smrg		/* round down to an integral number of XReps */
10231ab64890Smrg		len = (len / SIZEOF(xEvent)) * SIZEOF(xEvent);
10241ab64890Smrg	    }
10251ab64890Smrg
10261ab64890Smrg#ifdef XTHREADS
10271ab64890Smrg	    if (xthread_have_id(self))
10281ab64890Smrg		/* save value we may have to stick in conni_thread */
10291ab64890Smrg		dpy->lock->reading_thread = self;
10301ab64890Smrg#endif /* XTHREADS */
10311ab64890Smrg	    dpy->flags |= XlibDisplayReadEvents;
10321ab64890Smrg	    i = _XRead (dpy, read_buf, (long) len);
10331ab64890Smrg	    dpy->flags &= ~XlibDisplayReadEvents;
10341ab64890Smrg	    if (i == -2) {
10351ab64890Smrg		/* special flag from _XRead to say that internal connection has
10361ab64890Smrg		   done XPutBackEvent.  Which we can use so we're done. */
10371ab64890Smrg	      got_event:
10381ab64890Smrg#ifdef XTHREADS
10391ab64890Smrg		if (dpy->lock && dpy->lock->lock_wait) {
10401ab64890Smrg		    if (dpy->lock->event_awaiters != cvl)
10411ab64890Smrg			/* since it is not us, must be user lock thread */
10421ab64890Smrg			ConditionSignal(dpy,
10431ab64890Smrg					dpy->lock->event_awaiters->cv);
10441ab64890Smrg		    (*dpy->lock->lock_wait)(dpy);
10451ab64890Smrg		    continue;
10461ab64890Smrg		}
10471ab64890Smrg#endif
10481ab64890Smrg		break;
10491ab64890Smrg	    }
10501ab64890Smrg#ifdef XTHREADS
10511ab64890Smrg	    if (xthread_have_id(self))
10521ab64890Smrg		xthread_clear_id(dpy->lock->reading_thread);
10531ab64890Smrg
10541ab64890Smrg	    /* what did we actually read: reply or event? */
10551ab64890Smrg	    if (dpy->lock && dpy->lock->reply_awaiters) {
10561ab64890Smrg		if (((xReply *)read_buf)->generic.type == X_Reply ||
10571ab64890Smrg		    ((xReply *)read_buf)->generic.type == X_Error)
10581ab64890Smrg		{
10591ab64890Smrg		    dpy->lock->reply_was_read = True;
10601ab64890Smrg		    dpy->lock->reply_first = True;
10611ab64890Smrg		    if (read_buf != (char *)dpy->lock->reply_awaiters->buf)
10621ab64890Smrg			memcpy(dpy->lock->reply_awaiters->buf,
10631ab64890Smrg			       read_buf, len);
10641ab64890Smrg		    ConditionSignal(dpy, dpy->lock->reply_awaiters->cv);
10651ab64890Smrg		    continue;
10661ab64890Smrg		} else if (read_buf != buf.buf)
10671ab64890Smrg		    memcpy(buf.buf, read_buf, len);
10681ab64890Smrg	    }
10691ab64890Smrg#endif /* XTHREADS */
10701ab64890Smrg
10711ab64890Smrg	    STARTITERATE(rep,xReply,buf.buf,len > 0) {
10721ab64890Smrg		if (rep->generic.type == X_Reply) {
10731ab64890Smrg		    RESETITERPTR(rep,xReply,
10741ab64890Smrg				 _XAsyncReply (dpy, rep,
10751ab64890Smrg					       ITERPTR(rep), &len, True));
107661b2299dSmrg		    pend = len;
10771ab64890Smrg		} else {
10781ab64890Smrg		    if (rep->generic.type == X_Error)
10791ab64890Smrg			_XError (dpy, (xError *) rep);
10801ab64890Smrg		    else   /* must be an event packet */
108161b2299dSmrg                    {
108261b2299dSmrg                        if (rep->generic.type == GenericEvent)
108361b2299dSmrg                        {
108461b2299dSmrg                            int evlen;
108561b2299dSmrg                            evlen = (rep->generic.length << 2);
108661b2299dSmrg                            if (_XRead(dpy, &read_buf[len], evlen) == -2)
108761b2299dSmrg                                goto got_event; /* XXX: aargh! */
108861b2299dSmrg                        }
108961b2299dSmrg
109061b2299dSmrg                        _XEnq (dpy, (xEvent *)rep);
109161b2299dSmrg                    }
10921ab64890Smrg		    INCITERPTR(rep,xReply);
10931ab64890Smrg		    len -= SIZEOF(xReply);
10941ab64890Smrg		}
10951ab64890Smrg	    } ENDITERATE;
10961ab64890Smrg	} while (!_XNewerQueuedEvent(dpy, entry_event_serial_num));
10971ab64890Smrg
10981ab64890Smrg	UnlockNextEventReader(dpy);
10991ab64890Smrg}
11001ab64890Smrg
110161b2299dSmrg/*
11021ab64890Smrg * _XRead - Read bytes from the socket taking into account incomplete
11031ab64890Smrg * reads.  This routine may have to be reworked if int < long.
11041ab64890Smrg */
11051ab64890Smrgint _XRead(
11061ab64890Smrg	register Display *dpy,
11071ab64890Smrg	register char *data,
11081ab64890Smrg	register long size)
11091ab64890Smrg{
11101ab64890Smrg	register long bytes_read;
11111ab64890Smrg#ifdef XTHREADS
11121ab64890Smrg	int original_size = size;
11131ab64890Smrg#endif
11141ab64890Smrg
11151ab64890Smrg	if ((dpy->flags & XlibDisplayIOError) || size == 0)
11161ab64890Smrg	    return 0;
11171ab64890Smrg	ESET(0);
11181ab64890Smrg	while ((bytes_read = _X11TransRead(dpy->trans_conn, data, (int)size))
11191ab64890Smrg		!= size) {
11201ab64890Smrg
11211ab64890Smrg	    	if (bytes_read > 0) {
11221ab64890Smrg		    size -= bytes_read;
11231ab64890Smrg		    data += bytes_read;
11241ab64890Smrg		    }
11251ab64890Smrg		else if (ETEST()) {
11261ab64890Smrg		    if (_XWaitForReadable(dpy) == -2)
11271ab64890Smrg			return -2; /* internal connection did XPutBackEvent */
11281ab64890Smrg		    ESET(0);
11291ab64890Smrg		}
11301ab64890Smrg#ifdef SUNSYSV
11311ab64890Smrg		else if (ECHECK(0)) {
11321ab64890Smrg		    if (_XWaitForReadable(dpy) == -2)
11331ab64890Smrg			return -2; /* internal connection did XPutBackEvent */
11341ab64890Smrg		}
11351ab64890Smrg#endif
11361ab64890Smrg		else if (bytes_read == 0) {
11371ab64890Smrg		    /* Read failed because of end of file! */
11381ab64890Smrg		    ESET(EPIPE);
11391ab64890Smrg		    _XIOError(dpy);
11401ab64890Smrg		    }
11411ab64890Smrg
11421ab64890Smrg		else  /* bytes_read is less than 0; presumably -1 */ {
11431ab64890Smrg		    /* If it's a system call interrupt, it's not an error. */
11441ab64890Smrg		    if (!ECHECK(EINTR))
11451ab64890Smrg		    	_XIOError(dpy);
11461ab64890Smrg		    }
11471ab64890Smrg	    	 }
11481ab64890Smrg#ifdef XTHREADS
11491ab64890Smrg       if (dpy->lock && dpy->lock->reply_bytes_left > 0)
11501ab64890Smrg       {
11511ab64890Smrg           dpy->lock->reply_bytes_left -= original_size;
11521ab64890Smrg           if (dpy->lock->reply_bytes_left == 0) {
11531ab64890Smrg	       dpy->flags &= ~XlibDisplayReply;
11541ab64890Smrg               UnlockNextReplyReader(dpy);
11551ab64890Smrg	   }
11561ab64890Smrg       }
11571ab64890Smrg#endif /* XTHREADS*/
11581ab64890Smrg	return 0;
11591ab64890Smrg}
11601ab64890Smrg#endif /* !USE_XCB */
11611ab64890Smrg
11621ab64890Smrg#ifdef LONG64
11631ab64890Smrgvoid _XRead32(
11641ab64890Smrg    Display *dpy,
11651ab64890Smrg    register long *data,
11661ab64890Smrg    long len)
11671ab64890Smrg{
11681ab64890Smrg    register int *buf;
11691ab64890Smrg    register long i;
11701ab64890Smrg
11711ab64890Smrg    if (len) {
11721ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
11731ab64890Smrg	i = len >> 2;
11741ab64890Smrg	buf = (int *)data + i;
11751ab64890Smrg	data += i;
11761ab64890Smrg	while (--i >= 0)
11771ab64890Smrg	    *--data = *--buf;
11781ab64890Smrg    }
11791ab64890Smrg}
11801ab64890Smrg#endif /* LONG64 */
11811ab64890Smrg
11821ab64890Smrg#ifdef WORD64
11831ab64890Smrg
11841ab64890Smrg/*
11851ab64890Smrg * XXX This is a *really* stupid way of doing this....
11861ab64890Smrg * PACKBUFFERSIZE must be a multiple of 4.
11871ab64890Smrg */
11881ab64890Smrg
11891ab64890Smrg#define PACKBUFFERSIZE 4096
11901ab64890Smrg
11911ab64890Smrg
11921ab64890Smrg/*
11931ab64890Smrg * _XRead32 - Read bytes from the socket unpacking each 32 bits
11941ab64890Smrg *            into a long (64 bits on a CRAY computer).
119561b2299dSmrg *
11961ab64890Smrg */
11971ab64890Smrgstatic void _doXRead32(
11981ab64890Smrg        register Display *dpy,
11991ab64890Smrg        register long *data
12001ab64890Smrg        register long size,
12011ab64890Smrg	register char *packbuffer)
12021ab64890Smrg{
12031ab64890Smrg long *lpack,*lp;
12041ab64890Smrg long mask32 = 0x00000000ffffffff;
12051ab64890Smrg long maskw, nwords, i, bits;
12061ab64890Smrg
12071ab64890Smrg        _XReadPad (dpy, packbuffer, size);
12081ab64890Smrg
12091ab64890Smrg        lp = data;
12101ab64890Smrg        lpack = (long *) packbuffer;
12111ab64890Smrg        nwords = size >> 2;
12121ab64890Smrg        bits = 32;
12131ab64890Smrg
12141ab64890Smrg        for(i=0;i<nwords;i++){
12151ab64890Smrg            maskw = mask32 << bits;
12161ab64890Smrg           *lp++ = ( *lpack & maskw ) >> bits;
12171ab64890Smrg            bits = bits ^32;
12181ab64890Smrg            if(bits){
12191ab64890Smrg               lpack++;
12201ab64890Smrg            }
12211ab64890Smrg        }
12221ab64890Smrg}
12231ab64890Smrg
12241ab64890Smrgvoid _XRead32(
12251ab64890Smrg    Display *dpy,
12261ab64890Smrg    long *data,
12271ab64890Smrg    long len)
12281ab64890Smrg{
12291ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
12301ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 2;
12311ab64890Smrg
12321ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
12331ab64890Smrg	_doXRead32 (dpy, data, PACKBUFFERSIZE, packbuffer);
12341ab64890Smrg    }
12351ab64890Smrg    if (len) _doXRead32 (dpy, data, len, packbuffer);
12361ab64890Smrg}
12371ab64890Smrg
12381ab64890Smrg
12391ab64890Smrg
12401ab64890Smrg/*
12411ab64890Smrg * _XRead16 - Read bytes from the socket unpacking each 16 bits
12421ab64890Smrg *            into a long (64 bits on a CRAY computer).
12431ab64890Smrg *
12441ab64890Smrg */
12451ab64890Smrgstatic _doXRead16(
12461ab64890Smrg        register Display *dpy,
12471ab64890Smrg        register short *data,
12481ab64890Smrg        register long size,
12491ab64890Smrg	char *packbuffer)
12501ab64890Smrg{
12511ab64890Smrg	long *lpack,*lp;
12521ab64890Smrg	long mask16 = 0x000000000000ffff;
12531ab64890Smrg	long maskw, nwords, i, bits;
12541ab64890Smrg
12551ab64890Smrg        (void) _XRead(dpy,packbuffer,size);	/* don't do a padded read... */
12561ab64890Smrg
12571ab64890Smrg        lp = (long *) data;
12581ab64890Smrg        lpack = (long *) packbuffer;
12591ab64890Smrg        nwords = size >> 1;  /* number of 16 bit words to be unpacked */
12601ab64890Smrg        bits = 48;
12611ab64890Smrg        for(i=0;i<nwords;i++){
12621ab64890Smrg            maskw = mask16 << bits;
12631ab64890Smrg           *lp++ = ( *lpack & maskw ) >> bits;
12641ab64890Smrg            bits -= 16;
12651ab64890Smrg            if(bits < 0){
12661ab64890Smrg               lpack++;
12671ab64890Smrg               bits = 48;
12681ab64890Smrg            }
12691ab64890Smrg        }
12701ab64890Smrg}
12711ab64890Smrg
12721ab64890Smrgvoid _XRead16(
12731ab64890Smrg    Display *dpy,
12741ab64890Smrg    short *data,
12751ab64890Smrg    long len)
12761ab64890Smrg{
12771ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
12781ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 1;
12791ab64890Smrg
12801ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
12811ab64890Smrg	_doXRead16 (dpy, data, PACKBUFFERSIZE, packbuffer);
12821ab64890Smrg    }
12831ab64890Smrg    if (len) _doXRead16 (dpy, data, len, packbuffer);
12841ab64890Smrg}
12851ab64890Smrg
12861ab64890Smrgvoid _XRead16Pad(
12871ab64890Smrg    Display *dpy,
12881ab64890Smrg    short *data,
12891ab64890Smrg    long size)
12901ab64890Smrg{
12911ab64890Smrg    int slop = (size & 3);
12921ab64890Smrg    short slopbuf[3];
12931ab64890Smrg
12941ab64890Smrg    _XRead16 (dpy, data, size);
12951ab64890Smrg    if (slop > 0) {
12961ab64890Smrg	_XRead16 (dpy, slopbuf, 4 - slop);
12971ab64890Smrg    }
12981ab64890Smrg}
12991ab64890Smrg#endif /* WORD64 */
13001ab64890Smrg
13011ab64890Smrg
13021ab64890Smrg#if !USE_XCB
13031ab64890Smrg/*
13041ab64890Smrg * _XReadPad - Read bytes from the socket taking into account incomplete
13051ab64890Smrg * reads.  If the number of bytes is not 0 mod 4, read additional pad
13061ab64890Smrg * bytes. This routine may have to be reworked if int < long.
13071ab64890Smrg */
13081ab64890Smrgvoid _XReadPad(
13091ab64890Smrg    	register Display *dpy,
13101ab64890Smrg	register char *data,
13111ab64890Smrg	register long size)
13121ab64890Smrg{
13131ab64890Smrg    	register long bytes_read;
13141ab64890Smrg	struct iovec iov[2];
13151ab64890Smrg	char pad[3];
13161ab64890Smrg#ifdef XTHREADS
13171ab64890Smrg        int original_size;
13181ab64890Smrg#endif
13191ab64890Smrg
13201ab64890Smrg	if ((dpy->flags & XlibDisplayIOError) || size == 0) return;
13211ab64890Smrg	iov[0].iov_len = (int)size;
13221ab64890Smrg	iov[0].iov_base = data;
132361b2299dSmrg	/*
13241ab64890Smrg	 * The following hack is used to provide 32 bit long-word
13251ab64890Smrg	 * aligned padding.  The [1] vector is of length 0, 1, 2, or 3,
13261ab64890Smrg	 * whatever is needed.
13271ab64890Smrg	 */
13281ab64890Smrg
13291ab64890Smrg	iov[1].iov_len = -size & 3;
13301ab64890Smrg	iov[1].iov_base = pad;
13311ab64890Smrg	size += iov[1].iov_len;
13321ab64890Smrg#ifdef XTHREADS
13331ab64890Smrg	original_size = size;
13341ab64890Smrg#endif
13351ab64890Smrg	ESET(0);
13361ab64890Smrg	while ((bytes_read = _X11TransReadv (dpy->trans_conn, iov, 2)) != size) {
13371ab64890Smrg
13381ab64890Smrg	    if (bytes_read > 0) {
13391ab64890Smrg		size -= bytes_read;
13401ab64890Smrg		if (iov[0].iov_len < bytes_read) {
13411ab64890Smrg		    int pad_bytes_read = bytes_read - iov[0].iov_len;
13421ab64890Smrg		    iov[1].iov_len -= pad_bytes_read;
13431ab64890Smrg		    iov[1].iov_base =
13441ab64890Smrg			(char *)iov[1].iov_base + pad_bytes_read;
13451ab64890Smrg		    iov[0].iov_len = 0;
13461ab64890Smrg		    }
13471ab64890Smrg	    	else {
13481ab64890Smrg		    iov[0].iov_len -= bytes_read;
13491ab64890Smrg	    	    iov[0].iov_base = (char *)iov[0].iov_base + bytes_read;
13501ab64890Smrg	    	}
13511ab64890Smrg	    }
13521ab64890Smrg	    else if (ETEST()) {
13531ab64890Smrg		_XWaitForReadable(dpy);
13541ab64890Smrg		ESET(0);
13551ab64890Smrg	    }
13561ab64890Smrg#ifdef SUNSYSV
13571ab64890Smrg	    else if (ECHECK(0)) {
13581ab64890Smrg		_XWaitForReadable(dpy);
13591ab64890Smrg	    }
13601ab64890Smrg#endif
13611ab64890Smrg	    else if (bytes_read == 0) {
13621ab64890Smrg		/* Read failed because of end of file! */
13631ab64890Smrg		ESET(EPIPE);
13641ab64890Smrg		_XIOError(dpy);
13651ab64890Smrg		}
136661b2299dSmrg
13671ab64890Smrg	    else  /* bytes_read is less than 0; presumably -1 */ {
13681ab64890Smrg		/* If it's a system call interrupt, it's not an error. */
13691ab64890Smrg		if (!ECHECK(EINTR))
13701ab64890Smrg		    _XIOError(dpy);
13711ab64890Smrg		}
13721ab64890Smrg	    }
13731ab64890Smrg#ifdef XTHREADS
13741ab64890Smrg       if (dpy->lock && dpy->lock->reply_bytes_left > 0)
13751ab64890Smrg       {
13761ab64890Smrg           dpy->lock->reply_bytes_left -= original_size;
13771ab64890Smrg           if (dpy->lock->reply_bytes_left == 0) {
13781ab64890Smrg	       dpy->flags &= ~XlibDisplayReply;
13791ab64890Smrg               UnlockNextReplyReader(dpy);
13801ab64890Smrg	   }
13811ab64890Smrg       }
13821ab64890Smrg#endif /* XTHREADS*/
13831ab64890Smrg}
13841ab64890Smrg
13851ab64890Smrg/*
13861ab64890Smrg * _XSend - Flush the buffer and send the client data. 32 bit word aligned
13871ab64890Smrg * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
13881ab64890Smrg * This routine may have to be reworked if int < long;
13891ab64890Smrg */
13901ab64890Smrgvoid
13911ab64890Smrg_XSend (
13921ab64890Smrg	register Display *dpy,
13931ab64890Smrg	_Xconst char *data,
13941ab64890Smrg	register long size)
13951ab64890Smrg{
13961ab64890Smrg	struct iovec iov[3];
13971ab64890Smrg	static char const pad[3] = {0, 0, 0};
13981ab64890Smrg           /* XText8 and XText16 require that the padding bytes be zero! */
13991ab64890Smrg
14001ab64890Smrg	long skip, dbufsize, padsize, total, todo;
14011ab64890Smrg	_XExtension *ext;
14021ab64890Smrg
14031ab64890Smrg	if (!size || (dpy->flags & XlibDisplayIOError)) return;
14041ab64890Smrg	dbufsize = dpy->bufptr - dpy->buffer;
14051ab64890Smrg#ifdef XTHREADS
14061ab64890Smrg	dpy->flags |= XlibDisplayWriting;
14071ab64890Smrg	/* make sure no one else can put in data */
14081ab64890Smrg	dpy->bufptr = dpy->bufmax;
14091ab64890Smrg#endif
14101ab64890Smrg	padsize = -size & 3;
14111ab64890Smrg	for (ext = dpy->flushes; ext; ext = ext->next_flush) {
14121ab64890Smrg	    (*ext->before_flush)(dpy, &ext->codes, dpy->buffer, dbufsize);
14131ab64890Smrg	    (*ext->before_flush)(dpy, &ext->codes, (char *)data, size);
14141ab64890Smrg	    if (padsize)
14151ab64890Smrg		(*ext->before_flush)(dpy, &ext->codes, pad, padsize);
14161ab64890Smrg	}
14171ab64890Smrg	skip = 0;
14181ab64890Smrg	todo = total = dbufsize + size + padsize;
14191ab64890Smrg
14201ab64890Smrg	/*
14211ab64890Smrg	 * There are 3 pieces that may need to be written out:
14221ab64890Smrg	 *
14231ab64890Smrg	 *     o  whatever is in the display buffer
14241ab64890Smrg	 *     o  the data passed in by the user
14251ab64890Smrg	 *     o  any padding needed to 32bit align the whole mess
14261ab64890Smrg	 *
14271ab64890Smrg	 * This loop looks at all 3 pieces each time through.  It uses skip
14281ab64890Smrg	 * to figure out whether or not a given piece is needed.
14291ab64890Smrg	 */
14301ab64890Smrg	while (total) {
14311ab64890Smrg	    long before = skip;		/* amount of whole thing written */
14321ab64890Smrg	    long remain = todo;		/* amount to try this time, <= total */
14331ab64890Smrg	    int i = 0;
14341ab64890Smrg	    long len;
14351ab64890Smrg
14361ab64890Smrg	    /* You could be very general here and have "in" and "out" iovecs
14371ab64890Smrg	     * and write a loop without using a macro, but what the heck.  This
14381ab64890Smrg	     * translates to:
14391ab64890Smrg	     *
14401ab64890Smrg	     *     how much of this piece is new?
14411ab64890Smrg	     *     if more new then we are trying this time, clamp
14421ab64890Smrg	     *     if nothing new
14431ab64890Smrg	     *         then bump down amount already written, for next piece
14441ab64890Smrg	     *         else put new stuff in iovec, will need all of next piece
14451ab64890Smrg	     *
14461ab64890Smrg	     * Note that todo had better be at least 1 or else we'll end up
14471ab64890Smrg	     * writing 0 iovecs.
14481ab64890Smrg	     */
14491ab64890Smrg#define InsertIOV(pointer, length) \
14501ab64890Smrg	    len = (length) - before; \
14511ab64890Smrg	    if (len > remain) \
14521ab64890Smrg		len = remain; \
14531ab64890Smrg	    if (len <= 0) { \
14541ab64890Smrg		before = (-len); \
14551ab64890Smrg	    } else { \
14561ab64890Smrg		iov[i].iov_len = len; \
14571ab64890Smrg		iov[i].iov_base = (pointer) + before; \
14581ab64890Smrg		i++; \
14591ab64890Smrg		remain -= len; \
14601ab64890Smrg		before = 0; \
14611ab64890Smrg	    }
14621ab64890Smrg
14631ab64890Smrg	    InsertIOV (dpy->buffer, dbufsize)
14641ab64890Smrg	    InsertIOV ((char *)data, size)
14651ab64890Smrg	    InsertIOV ((char *)pad, padsize)
146661b2299dSmrg
14671ab64890Smrg	    ESET(0);
14681ab64890Smrg	    if ((len = _X11TransWritev(dpy->trans_conn, iov, i)) >= 0) {
14691ab64890Smrg		skip += len;
14701ab64890Smrg		total -= len;
14711ab64890Smrg		todo = total;
14721ab64890Smrg	    } else if (ETEST()) {
14731ab64890Smrg		_XWaitForWritable(dpy
14741ab64890Smrg#ifdef XTHREADS
14751ab64890Smrg				  , NULL
14761ab64890Smrg#endif
14771ab64890Smrg				  );
14781ab64890Smrg#ifdef SUNSYSV
14791ab64890Smrg	    } else if (ECHECK(0)) {
14801ab64890Smrg		_XWaitForWritable(dpy
14811ab64890Smrg#ifdef XTHREADS
14821ab64890Smrg				  , NULL
14831ab64890Smrg#endif
14841ab64890Smrg				  );
14851ab64890Smrg#endif
14861ab64890Smrg#ifdef ESZTEST
14871ab64890Smrg	    } else if (ESZTEST()) {
148861b2299dSmrg		if (todo > 1)
14891ab64890Smrg		  todo >>= 1;
14901ab64890Smrg		else {
14911ab64890Smrg		    _XWaitForWritable(dpy
14921ab64890Smrg#ifdef XTHREADS
14931ab64890Smrg				      , NULL
14941ab64890Smrg#endif
14951ab64890Smrg				      );
14961ab64890Smrg		}
14971ab64890Smrg#endif
14981ab64890Smrg	    } else if (!ECHECK(EINTR)) {
14991ab64890Smrg		_XIOError(dpy);
15001ab64890Smrg	    }
15011ab64890Smrg	}
15021ab64890Smrg	dpy->last_req = (char *) & _dummy_request;
15031ab64890Smrg	_XSetSeqSyncFunction(dpy);
15041ab64890Smrg	dpy->bufptr = dpy->buffer;
15051ab64890Smrg#ifdef XTHREADS
15061ab64890Smrg	dpy->flags &= ~XlibDisplayWriting;
15071ab64890Smrg#endif
15081ab64890Smrg	return;
15091ab64890Smrg}
15101ab64890Smrg
15111ab64890Smrgstatic void
15121ab64890Smrg_XGetMiscCode(
15131ab64890Smrg    register Display *dpy)
15141ab64890Smrg{
15151ab64890Smrg    xQueryExtensionReply qrep;
15161ab64890Smrg    register xQueryExtensionReq *qreq;
15171ab64890Smrg    xXCMiscGetVersionReply vrep;
15181ab64890Smrg    register xXCMiscGetVersionReq *vreq;
15191ab64890Smrg
15201ab64890Smrg    if (dpy->xcmisc_opcode)
15211ab64890Smrg	return;
15221ab64890Smrg    GetReq(QueryExtension, qreq);
15231ab64890Smrg    qreq->nbytes = sizeof(XCMiscExtensionName) - 1;
15241ab64890Smrg    qreq->length += (qreq->nbytes+(unsigned)3)>>2;
15251ab64890Smrg    _XSend(dpy, XCMiscExtensionName, (long)qreq->nbytes);
15261ab64890Smrg    if (!_XReply (dpy, (xReply *)&qrep, 0, xTrue))
15271ab64890Smrg	dpy->xcmisc_opcode = -1;
15281ab64890Smrg    else {
15291ab64890Smrg	GetReq(XCMiscGetVersion, vreq);
15301ab64890Smrg	vreq->reqType = qrep.major_opcode;
15311ab64890Smrg	vreq->miscReqType = X_XCMiscGetVersion;
15321ab64890Smrg	vreq->majorVersion = XCMiscMajorVersion;
15331ab64890Smrg	vreq->minorVersion = XCMiscMinorVersion;
15341ab64890Smrg	if (!_XReply (dpy, (xReply *)&vrep, 0, xTrue))
15351ab64890Smrg	    dpy->xcmisc_opcode = -1;
15361ab64890Smrg	else
15371ab64890Smrg	    dpy->xcmisc_opcode = qrep.major_opcode;
15381ab64890Smrg    }
15391ab64890Smrg}
15401ab64890Smrg
154161b2299dSmrgint
15421ab64890Smrg_XIDHandler(
15431ab64890Smrg    register Display *dpy)
15441ab64890Smrg{
15451ab64890Smrg    xXCMiscGetXIDRangeReply grep;
15461ab64890Smrg    register xXCMiscGetXIDRangeReq *greq;
154761b2299dSmrg    int sent_req = 0;
15481ab64890Smrg
15491ab64890Smrg    LockDisplay(dpy);
155061b2299dSmrg    if (dpy->resource_max == dpy->resource_mask + 1) {
155161b2299dSmrg	_XGetMiscCode(dpy);
155261b2299dSmrg	if (dpy->xcmisc_opcode > 0) {
155361b2299dSmrg	    GetReq(XCMiscGetXIDRange, greq);
155461b2299dSmrg	    greq->reqType = dpy->xcmisc_opcode;
155561b2299dSmrg	    greq->miscReqType = X_XCMiscGetXIDRange;
155661b2299dSmrg	    if (_XReply (dpy, (xReply *)&grep, 0, xTrue) && grep.count) {
155761b2299dSmrg		dpy->resource_id = ((grep.start_id - dpy->resource_base) >>
155861b2299dSmrg				    dpy->resource_shift);
155961b2299dSmrg		dpy->resource_max = dpy->resource_id;
156061b2299dSmrg		if (grep.count > 5)
156161b2299dSmrg		    dpy->resource_max += grep.count - 6;
156261b2299dSmrg		dpy->resource_max <<= dpy->resource_shift;
156361b2299dSmrg	    }
156461b2299dSmrg	    sent_req = 1;
15651ab64890Smrg	}
15661ab64890Smrg    }
15671ab64890Smrg    UnlockDisplay(dpy);
156861b2299dSmrg    if (sent_req)
156961b2299dSmrg	SyncHandle();
15701ab64890Smrg    return 0;
15711ab64890Smrg}
15721ab64890Smrg
15731ab64890Smrg/*
15741ab64890Smrg * _XAllocID - resource ID allocation routine.
15751ab64890Smrg */
15761ab64890SmrgXID _XAllocID(
15771ab64890Smrg    register Display *dpy)
15781ab64890Smrg{
15791ab64890Smrg   XID id;
15801ab64890Smrg
15811ab64890Smrg   id = dpy->resource_id << dpy->resource_shift;
15821ab64890Smrg   if (id >= dpy->resource_max) {
158361b2299dSmrg	_XSetPrivSyncFunction(dpy);
15841ab64890Smrg       dpy->resource_max = dpy->resource_mask + 1;
15851ab64890Smrg   }
15861ab64890Smrg   if (id <= dpy->resource_mask) {
15871ab64890Smrg       dpy->resource_id++;
15881ab64890Smrg       return (dpy->resource_base + id);
15891ab64890Smrg   }
15901ab64890Smrg   if (id != 0x10000000) {
15911ab64890Smrg       (void) fprintf(stderr,
15921ab64890Smrg		      "Xlib: resource ID allocation space exhausted!\n");
15931ab64890Smrg       id = 0x10000000;
15941ab64890Smrg       dpy->resource_id = id >> dpy->resource_shift;
15951ab64890Smrg   }
15961ab64890Smrg   return id;
15971ab64890Smrg}
15981ab64890Smrg
15991ab64890Smrg/*
16001ab64890Smrg * _XAllocIDs - multiple resource ID allocation routine.
16011ab64890Smrg */
16021ab64890Smrgvoid _XAllocIDs(
16031ab64890Smrg    register Display *dpy,
16041ab64890Smrg    XID *ids,
16051ab64890Smrg    int count)
16061ab64890Smrg{
16071ab64890Smrg    XID id;
16081ab64890Smrg    int i;
16091ab64890Smrg    xXCMiscGetXIDListReply grep;
16101ab64890Smrg    register xXCMiscGetXIDListReq *greq;
16111ab64890Smrg
16121ab64890Smrg    id = dpy->resource_id << dpy->resource_shift;
16131ab64890Smrg    if (dpy->resource_max <= dpy->resource_mask &&
16141ab64890Smrg	id <= dpy->resource_mask &&
16151ab64890Smrg	(dpy->resource_max - id) > ((count - 1) << dpy->resource_shift)) {
16161ab64890Smrg	id += dpy->resource_base;
16171ab64890Smrg	for (i = 0; i < count; i++) {
16181ab64890Smrg	    ids[i] = id;
16191ab64890Smrg	    id += (1 << dpy->resource_shift);
16201ab64890Smrg	    dpy->resource_id++;
16211ab64890Smrg	}
16221ab64890Smrg	return;
16231ab64890Smrg    }
16241ab64890Smrg    grep.count = 0;
16251ab64890Smrg    _XGetMiscCode(dpy);
16261ab64890Smrg    if (dpy->xcmisc_opcode > 0) {
16271ab64890Smrg	GetReq(XCMiscGetXIDList, greq);
16281ab64890Smrg	greq->reqType = dpy->xcmisc_opcode;
16291ab64890Smrg	greq->miscReqType = X_XCMiscGetXIDList;
16301ab64890Smrg	greq->count = count;
16311ab64890Smrg	if (_XReply(dpy, (xReply *)&grep, 0, xFalse) && grep.count) {
16321ab64890Smrg	    _XRead32(dpy, (long *) ids, 4L * (long) (grep.count));
16331ab64890Smrg	    for (i = 0; i < grep.count; i++) {
16341ab64890Smrg		id = (ids[i] - dpy->resource_base) >> dpy->resource_shift;
16351ab64890Smrg		if (id >= dpy->resource_id)
16361ab64890Smrg		    dpy->resource_id = id;
16371ab64890Smrg	    }
16381ab64890Smrg	    if (id >= dpy->resource_max) {
163961b2299dSmrg		_XSetPrivSyncFunction(dpy);
16401ab64890Smrg		dpy->resource_max = dpy->resource_mask + 1;
16411ab64890Smrg	    }
16421ab64890Smrg	}
16431ab64890Smrg    }
16441ab64890Smrg    for (i = grep.count; i < count; i++)
16451ab64890Smrg	ids[i] = XAllocID(dpy);
16461ab64890Smrg}
16471ab64890Smrg#endif /* !USE_XCB */
16481ab64890Smrg
16491ab64890Smrg/*
16501ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
16511ab64890Smrg * We have three values that will march along, with the following invariant:
16521ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
16531ab64890Smrg * We have to keep
16541ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
16551ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
16561ab64890Smrg * by forcing syncs when we get close.
16571ab64890Smrg */
16581ab64890Smrg
16591ab64890Smrgunsigned long
16601ab64890Smrg_XSetLastRequestRead(
16611ab64890Smrg    register Display *dpy,
16621ab64890Smrg    register xGenericReply *rep)
16631ab64890Smrg{
16641ab64890Smrg    register unsigned long	newseq, lastseq;
16651ab64890Smrg
16661ab64890Smrg    lastseq = dpy->last_request_read;
16671ab64890Smrg    /*
16681ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
16691ab64890Smrg     * to immediately follow another event, except when generated via
16701ab64890Smrg     * SendEvent (hmmm).
16711ab64890Smrg     */
16721ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
16731ab64890Smrg	return(lastseq);
16741ab64890Smrg
16751ab64890Smrg    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
16761ab64890Smrg
16771ab64890Smrg    if (newseq < lastseq) {
16781ab64890Smrg	newseq += 0x10000;
16791ab64890Smrg	if (newseq > dpy->request) {
168061b2299dSmrg	    (void) fprintf (stderr,
16811ab64890Smrg	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
168261b2299dSmrg			    newseq, dpy->request,
16831ab64890Smrg			    (unsigned int) rep->type);
16841ab64890Smrg	    newseq -= 0x10000;
16851ab64890Smrg	}
16861ab64890Smrg    }
16871ab64890Smrg
16881ab64890Smrg    dpy->last_request_read = newseq;
16891ab64890Smrg    return(newseq);
16901ab64890Smrg}
16911ab64890Smrg
16921ab64890Smrg#if !USE_XCB
16931ab64890Smrg/*
16941ab64890Smrg * _XReply - Wait for a reply packet and copy its contents into the
16951ab64890Smrg * specified rep.  Meanwhile we must handle error and event packets that
16961ab64890Smrg * we may encounter.
16971ab64890Smrg */
16981ab64890SmrgStatus
16991ab64890Smrg_XReply (
17001ab64890Smrg    register Display *dpy,
17011ab64890Smrg    register xReply *rep,
17021ab64890Smrg    int extra,		/* number of 32-bit words expected after the reply */
17031ab64890Smrg    Bool discard)	/* should I discard data following "extra" words? */
17041ab64890Smrg{
17051ab64890Smrg    /* Pull out the serial number now, so that (currently illegal) requests
17061ab64890Smrg     * generated by an error handler don't confuse us.
17071ab64890Smrg     */
17081ab64890Smrg    unsigned long cur_request = dpy->request;
17091ab64890Smrg#ifdef XTHREADS
17101ab64890Smrg    struct _XCVList *cvl;
17111ab64890Smrg#endif
17121ab64890Smrg
17131ab64890Smrg    if (dpy->flags & XlibDisplayIOError)
17141ab64890Smrg	return 0;
17151ab64890Smrg
17161ab64890Smrg#ifdef XTHREADS
17171ab64890Smrg    /* create our condition variable and append to list */
17181ab64890Smrg    cvl = QueueReplyReaderLock(dpy);
17191ab64890Smrg    if (cvl) {
17201ab64890Smrg	cvl->buf = rep;
17211ab64890Smrg	if (dpy->lock->reply_awaiters == cvl && !dpy->lock->event_awaiters)
17221ab64890Smrg	    dpy->lock->reply_first = True;
17231ab64890Smrg    }
17241ab64890Smrg
17251ab64890Smrg#ifdef XTHREADS_DEBUG
17261ab64890Smrg    printf("_XReply called in thread %x, adding %x to cvl\n",
17271ab64890Smrg	   XThread_Self(), cvl);
17281ab64890Smrg#endif
17291ab64890Smrg
17301ab64890Smrg    _XFlushInt(dpy, cvl ? cvl->cv : NULL);
17311ab64890Smrg    /* if it is not our turn to read a reply off the wire,
17321ab64890Smrg     * wait til we're at head of list.  if there is an event waiter,
17331ab64890Smrg     * and our reply hasn't been read, they'll be in select and will
17341ab64890Smrg     * hand control back to us next.
17351ab64890Smrg     */
17361ab64890Smrg    if(dpy->lock &&
17371ab64890Smrg       (dpy->lock->reply_awaiters != cvl || !dpy->lock->reply_first)) {
17381ab64890Smrg	ConditionWait(dpy, cvl->cv);
17391ab64890Smrg    }
17401ab64890Smrg    dpy->flags |= XlibDisplayReply;
17411ab64890Smrg#else /* XTHREADS else */
17421ab64890Smrg    _XFlush(dpy);
17431ab64890Smrg#endif
17441ab64890Smrg
17451ab64890Smrg    for (;;) {
17461ab64890Smrg#ifdef XTHREADS
17471ab64890Smrg	/* Did another thread's _XReadEvents get our reply by accident? */
17481ab64890Smrg	if (!dpy->lock || !dpy->lock->reply_was_read)
17491ab64890Smrg#endif
17501ab64890Smrg	    (void) _XRead(dpy, (char *)rep, (long)SIZEOF(xReply));
17511ab64890Smrg#ifdef XTHREADS
17521ab64890Smrg	if (dpy->lock)
17531ab64890Smrg	    dpy->lock->reply_was_read = False;
17541ab64890Smrg#endif
17551ab64890Smrg
17561ab64890Smrg	switch ((int)rep->generic.type) {
17571ab64890Smrg
17581ab64890Smrg	    case X_Reply:
17591ab64890Smrg	        /* Reply received.  Fast update for synchronous replies,
17601ab64890Smrg		 * but deal with multiple outstanding replies.
17611ab64890Smrg		 */
17621ab64890Smrg	        if (rep->generic.sequenceNumber == (cur_request & 0xffff))
17631ab64890Smrg		    dpy->last_request_read = cur_request;
17641ab64890Smrg		else {
17651ab64890Smrg		    int pend = SIZEOF(xReply);
17661ab64890Smrg		    if (_XAsyncReply(dpy, rep, (char *)rep, &pend, False)
17671ab64890Smrg			!= (char *)rep)
17681ab64890Smrg			continue;
17691ab64890Smrg		}
17701ab64890Smrg		if (extra <= rep->generic.length) {
17711ab64890Smrg		    if (extra > 0)
177261b2299dSmrg			/*
17731ab64890Smrg			 * Read the extra data into storage immediately
177461b2299dSmrg			 * following the GenericReply structure.
17751ab64890Smrg			 */
17761ab64890Smrg			(void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)),
17771ab64890Smrg				((long)extra) << 2);
17781ab64890Smrg		    if (discard) {
17791ab64890Smrg			if (extra < rep->generic.length)
17801ab64890Smrg			    _XEatData(dpy, (rep->generic.length - extra) << 2);
17811ab64890Smrg		    }
17821ab64890Smrg#ifdef XTHREADS
17831ab64890Smrg		    if (dpy->lock) {
17841ab64890Smrg			if (discard) {
17851ab64890Smrg			    dpy->lock->reply_bytes_left = 0;
17861ab64890Smrg			} else {
17871ab64890Smrg			    dpy->lock->reply_bytes_left =
17881ab64890Smrg				(rep->generic.length - extra) << 2;
17891ab64890Smrg			}
17901ab64890Smrg			if (dpy->lock->reply_bytes_left == 0) {
17911ab64890Smrg			    dpy->flags &= ~XlibDisplayReply;
17921ab64890Smrg			    UnlockNextReplyReader(dpy);
17931ab64890Smrg			}
17941ab64890Smrg		    } else
17951ab64890Smrg			dpy->flags &= ~XlibDisplayReply;
17961ab64890Smrg#endif
17971ab64890Smrg		    return 1;
17981ab64890Smrg		}
179961b2299dSmrg		/*
18001ab64890Smrg		 *if we get here, then extra > rep->generic.length--meaning we
180161b2299dSmrg		 * read a reply that's shorter than we expected.  This is an
18021ab64890Smrg		 * error,  but we still need to figure out how to handle it...
18031ab64890Smrg		 */
18041ab64890Smrg		(void) _XRead (dpy, (char *) (NEXTPTR(rep,xReply)),
18051ab64890Smrg			((long) rep->generic.length) << 2);
18061ab64890Smrg		dpy->flags &= ~XlibDisplayReply;
18071ab64890Smrg		UnlockNextReplyReader(dpy);
18081ab64890Smrg		_XIOError (dpy);
18091ab64890Smrg		return (0);
18101ab64890Smrg
18111ab64890Smrg    	    case X_Error:
18121ab64890Smrg	    	{
18131ab64890Smrg	        register _XExtension *ext;
18141ab64890Smrg		register Bool ret = False;
18151ab64890Smrg		int ret_code;
18161ab64890Smrg		xError *err = (xError *) rep;
18171ab64890Smrg		unsigned long serial;
18181ab64890Smrg
18191ab64890Smrg		dpy->flags &= ~XlibDisplayReply;
18201ab64890Smrg		serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
18211ab64890Smrg		if (serial == cur_request)
18221ab64890Smrg			/* do not die on "no such font", "can't allocate",
18231ab64890Smrg			   "can't grab" failures */
18241ab64890Smrg			switch ((int)err->errorCode) {
18251ab64890Smrg			case BadName:
18261ab64890Smrg			    switch (err->majorCode) {
18271ab64890Smrg				case X_LookupColor:
18281ab64890Smrg				case X_AllocNamedColor:
18291ab64890Smrg				    UnlockNextReplyReader(dpy);
18301ab64890Smrg				    return(0);
18311ab64890Smrg			    }
18321ab64890Smrg			    break;
18331ab64890Smrg			case BadFont:
18341ab64890Smrg			    if (err->majorCode == X_QueryFont) {
18351ab64890Smrg				UnlockNextReplyReader(dpy);
18361ab64890Smrg				return (0);
18371ab64890Smrg			    }
18381ab64890Smrg			    break;
18391ab64890Smrg			case BadAlloc:
18401ab64890Smrg			case BadAccess:
18411ab64890Smrg			    UnlockNextReplyReader(dpy);
18421ab64890Smrg			    return (0);
18431ab64890Smrg			}
184461b2299dSmrg		/*
18451ab64890Smrg		 * we better see if there is an extension who may
18461ab64890Smrg		 * want to suppress the error.
18471ab64890Smrg		 */
18481ab64890Smrg		for (ext = dpy->ext_procs; !ret && ext; ext = ext->next) {
184961b2299dSmrg		    if (ext->error)
18501ab64890Smrg		       ret = (*ext->error)(dpy, err, &ext->codes, &ret_code);
18511ab64890Smrg		}
18521ab64890Smrg		if (!ret) {
18531ab64890Smrg		    _XError(dpy, err);
18541ab64890Smrg		    ret_code = 0;
18551ab64890Smrg		}
18561ab64890Smrg		if (serial == cur_request) {
18571ab64890Smrg		    UnlockNextReplyReader(dpy);
18581ab64890Smrg		    return(ret_code);
18591ab64890Smrg		}
18601ab64890Smrg
18611ab64890Smrg		} /* case X_Error */
18621ab64890Smrg		break;
18631ab64890Smrg	    default:
18641ab64890Smrg		_XEnq(dpy, (xEvent *) rep);
18651ab64890Smrg#ifdef XTHREADS
18661ab64890Smrg		if (dpy->lock && dpy->lock->event_awaiters)
18671ab64890Smrg		    ConditionSignal(dpy, dpy->lock->event_awaiters->cv);
18681ab64890Smrg#endif
18691ab64890Smrg		break;
18701ab64890Smrg	    }
18711ab64890Smrg	}
187261b2299dSmrg}
18731ab64890Smrg
18741ab64890Smrgstatic char *
18751ab64890Smrg_XAsyncReply(
18761ab64890Smrg    Display *dpy,
18771ab64890Smrg    register xReply *rep,
18781ab64890Smrg    char *buf,
18791ab64890Smrg    register int *lenp,
18801ab64890Smrg    Bool discard)
18811ab64890Smrg{
18821ab64890Smrg    register _XAsyncHandler *async, *next;
18831ab64890Smrg    register int len;
18841ab64890Smrg    register Bool consumed = False;
18851ab64890Smrg    char *nbuf;
18861ab64890Smrg
18871ab64890Smrg    (void) _XSetLastRequestRead(dpy, &rep->generic);
18881ab64890Smrg    len = SIZEOF(xReply) + (rep->generic.length << 2);
18891ab64890Smrg    if (len < SIZEOF(xReply)) {
18901ab64890Smrg	_XIOError (dpy);
18911ab64890Smrg	buf += *lenp;
18921ab64890Smrg	*lenp = 0;
18931ab64890Smrg	return buf;
18941ab64890Smrg    }
189561b2299dSmrg
18961ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
18971ab64890Smrg	next = async->next;
18981ab64890Smrg	if ((consumed = (*async->handler)(dpy, rep, buf, *lenp, async->data)))
18991ab64890Smrg	    break;
19001ab64890Smrg    }
19011ab64890Smrg    if (!consumed) {
19021ab64890Smrg	if (!discard)
19031ab64890Smrg	    return buf;
190461b2299dSmrg	(void) fprintf(stderr,
19051ab64890Smrg		       "Xlib: unexpected async reply (sequence 0x%lx)!\n",
19061ab64890Smrg		       dpy->last_request_read);
19071ab64890Smrg#ifdef XTHREADS
19081ab64890Smrg#ifdef XTHREADS_DEBUG
19091ab64890Smrg	printf("thread %x, unexpected async reply\n", XThread_Self());
19101ab64890Smrg#endif
19111ab64890Smrg#endif
19121ab64890Smrg	if (len > *lenp)
19131ab64890Smrg	    _XEatData(dpy, len - *lenp);
19141ab64890Smrg    }
19151ab64890Smrg    if (len < SIZEOF(xReply))
19161ab64890Smrg    {
19171ab64890Smrg	_XIOError (dpy);
19181ab64890Smrg	buf += *lenp;
19191ab64890Smrg	*lenp = 0;
19201ab64890Smrg	return buf;
19211ab64890Smrg    }
19221ab64890Smrg    if (len >= *lenp) {
19231ab64890Smrg	buf += *lenp;
19241ab64890Smrg	*lenp = 0;
19251ab64890Smrg	return buf;
19261ab64890Smrg    }
19271ab64890Smrg    *lenp -= len;
19281ab64890Smrg    buf += len;
19291ab64890Smrg    len = *lenp;
19301ab64890Smrg    nbuf = buf;
19311ab64890Smrg    while (len > SIZEOF(xReply)) {
19321ab64890Smrg	if (*buf == X_Reply)
19331ab64890Smrg	    return nbuf;
19341ab64890Smrg	buf += SIZEOF(xReply);
19351ab64890Smrg	len -= SIZEOF(xReply);
19361ab64890Smrg    }
19371ab64890Smrg    if (len > 0 && len < SIZEOF(xReply)) {
19381ab64890Smrg	buf = nbuf;
19391ab64890Smrg	len = SIZEOF(xReply) - len;
19401ab64890Smrg	nbuf -= len;
19411ab64890Smrg	memmove(nbuf, buf, *lenp);
19421ab64890Smrg	(void) _XRead(dpy, nbuf + *lenp, (long)len);
19431ab64890Smrg	*lenp += len;
19441ab64890Smrg    }
19451ab64890Smrg    return nbuf;
19461ab64890Smrg}
19471ab64890Smrg#endif /* !USE_XCB */
19481ab64890Smrg
19491ab64890Smrg/*
19501ab64890Smrg * Support for internal connections, such as an IM might use.
19511ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
19521ab64890Smrg */
19531ab64890Smrg
19541ab64890Smrg/* _XRegisterInternalConnection
19551ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
19561ab64890Smrg * include in its select/poll mask must call this function to register the
19571ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
19581ab64890Smrg * will also be called.
19591ab64890Smrg *
19601ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
19611ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
19621ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
19631ab64890Smrg * which will call the associated callback.
19641ab64890Smrg *
19651ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
19661ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
19671ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
19681ab64890Smrg * to be called when fds are registered or unregistered.
19691ab64890Smrg *
19701ab64890Smrg * Returns True if registration succeeded, False if not, typically
19711ab64890Smrg * because could not allocate memory.
19721ab64890Smrg * Assumes Display locked when called.
19731ab64890Smrg */
19741ab64890SmrgStatus
19751ab64890Smrg_XRegisterInternalConnection(
19761ab64890Smrg    Display* dpy,
19771ab64890Smrg    int fd,
19781ab64890Smrg    _XInternalConnectionProc callback,
19791ab64890Smrg    XPointer call_data
19801ab64890Smrg)
19811ab64890Smrg{
19821ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
19831ab64890Smrg    struct _XConnWatchInfo *watchers;
19841ab64890Smrg    XPointer *wd;
19851ab64890Smrg
19861ab64890Smrg    new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
19871ab64890Smrg    if (!new_conni)
19881ab64890Smrg	return 0;
19891ab64890Smrg    new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
19901ab64890Smrg    if (!new_conni->watch_data) {
19911ab64890Smrg	Xfree(new_conni);
19921ab64890Smrg	return 0;
19931ab64890Smrg    }
19941ab64890Smrg    new_conni->fd = fd;
19951ab64890Smrg    new_conni->read_callback = callback;
19961ab64890Smrg    new_conni->call_data = call_data;
19971ab64890Smrg    new_conni->next = NULL;
19981ab64890Smrg    /* link new structure onto end of list */
19991ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
20001ab64890Smrg	;
20011ab64890Smrg    *iptr = new_conni;
20021ab64890Smrg    dpy->im_fd_length++;
20031ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
20041ab64890Smrg
20051ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
20061ab64890Smrg	 watchers;
20071ab64890Smrg	 watchers=watchers->next, wd++) {
20081ab64890Smrg	*wd = NULL;		/* for cleanliness */
20091ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
20101ab64890Smrg    }
20111ab64890Smrg
20121ab64890Smrg    return 1;
20131ab64890Smrg}
20141ab64890Smrg
20151ab64890Smrg/* _XUnregisterInternalConnection
20161ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
20171ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
20181ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
20191ab64890Smrg * will also be called.
20201ab64890Smrg *
20211ab64890Smrg * Assumes Display locked when called.
20221ab64890Smrg */
20231ab64890Smrgvoid
20241ab64890Smrg_XUnregisterInternalConnection(
20251ab64890Smrg    Display* dpy,
20261ab64890Smrg    int fd
20271ab64890Smrg)
20281ab64890Smrg{
20291ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
20301ab64890Smrg    struct _XConnWatchInfo *watch;
20311ab64890Smrg    XPointer *wd;
20321ab64890Smrg
20331ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
20341ab64890Smrg	 prev = &info_list->next) {
20351ab64890Smrg	if (info_list->fd == fd) {
20361ab64890Smrg	    *prev = info_list->next;
20371ab64890Smrg	    dpy->im_fd_length--;
20381ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
20391ab64890Smrg		 watch;
20401ab64890Smrg		 watch=watch->next, wd++) {
20411ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
20421ab64890Smrg	    }
20431ab64890Smrg	    if (info_list->watch_data)
20441ab64890Smrg		Xfree (info_list->watch_data);
20451ab64890Smrg	    Xfree (info_list);
20461ab64890Smrg	    break;
20471ab64890Smrg	}
20481ab64890Smrg    }
20491ab64890Smrg    _XPollfdCacheDel(dpy, fd);
20501ab64890Smrg}
20511ab64890Smrg
20521ab64890Smrg/* XInternalConnectionNumbers
20531ab64890Smrg * Returns an array of fds and an array of corresponding call data.
20541ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
20551ab64890Smrg * will be used instead of this function to discover
20561ab64890Smrg * additional fds to include in the select/poll mask.
20571ab64890Smrg *
20581ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
20591ab64890Smrg * with Xfree;
20601ab64890Smrg */
20611ab64890SmrgStatus
20621ab64890SmrgXInternalConnectionNumbers(
20631ab64890Smrg    Display *dpy,
20641ab64890Smrg    int **fd_return,
20651ab64890Smrg    int *count_return
20661ab64890Smrg)
20671ab64890Smrg{
20681ab64890Smrg    int count;
20691ab64890Smrg    struct _XConnectionInfo *info_list;
20701ab64890Smrg    int *fd_list;
20711ab64890Smrg
20721ab64890Smrg    LockDisplay(dpy);
20731ab64890Smrg    count = 0;
20741ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
20751ab64890Smrg	count++;
20761ab64890Smrg    fd_list = (int*) Xmalloc (count * sizeof(int));
20771ab64890Smrg    if (!fd_list) {
20781ab64890Smrg	UnlockDisplay(dpy);
20791ab64890Smrg	return 0;
20801ab64890Smrg    }
20811ab64890Smrg    count = 0;
20821ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
20831ab64890Smrg	fd_list[count] = info_list->fd;
20841ab64890Smrg	count++;
20851ab64890Smrg    }
20861ab64890Smrg    UnlockDisplay(dpy);
20871ab64890Smrg
20881ab64890Smrg    *fd_return = fd_list;
20891ab64890Smrg    *count_return = count;
20901ab64890Smrg    return 1;
20911ab64890Smrg}
20921ab64890Smrg
20931ab64890Smrgvoid _XProcessInternalConnection(
20941ab64890Smrg    Display *dpy,
20951ab64890Smrg    struct _XConnectionInfo *conn_info)
20961ab64890Smrg{
20971ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
20981ab64890Smrg#if defined(XTHREADS) && !USE_XCB
20991ab64890Smrg    if (dpy->lock) {
21001ab64890Smrg	/* check cache to avoid call to thread_self */
21011ab64890Smrg	if (xthread_have_id(dpy->lock->reading_thread))
21021ab64890Smrg	    dpy->lock->conni_thread = dpy->lock->reading_thread;
21031ab64890Smrg	else
21041ab64890Smrg	    dpy->lock->conni_thread = XThread_Self();
21051ab64890Smrg    }
21061ab64890Smrg#endif /* XTHREADS && !USE_XCB */
21071ab64890Smrg    UnlockDisplay(dpy);
21081ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
21091ab64890Smrg    LockDisplay(dpy);
21101ab64890Smrg#if defined(XTHREADS) && !USE_XCB
21111ab64890Smrg    if (dpy->lock)
21121ab64890Smrg	xthread_clear_id(dpy->lock->conni_thread);
21131ab64890Smrg#endif /* XTHREADS && !USE_XCB */
21141ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
21151ab64890Smrg}
21161ab64890Smrg
21171ab64890Smrg/* XProcessInternalConnection
21181ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
21191ab64890Smrg * for this fd.
21201ab64890Smrg * The Display is NOT locked during the call.
21211ab64890Smrg */
21221ab64890Smrgvoid
21231ab64890SmrgXProcessInternalConnection(
21241ab64890Smrg    Display* dpy,
21251ab64890Smrg    int fd
21261ab64890Smrg)
21271ab64890Smrg{
21281ab64890Smrg    struct _XConnectionInfo *info_list;
21291ab64890Smrg
21301ab64890Smrg    LockDisplay(dpy);
21311ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
21321ab64890Smrg	if (info_list->fd == fd) {
21331ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
21341ab64890Smrg	    break;
21351ab64890Smrg	}
21361ab64890Smrg    }
21371ab64890Smrg    UnlockDisplay(dpy);
21381ab64890Smrg}
21391ab64890Smrg
21401ab64890Smrg/* XAddConnectionWatch
21411ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
21421ab64890Smrg * or _XUnregisterInternalConnection is called.
21431ab64890Smrg * Callbacks are called with the Display locked.
21441ab64890Smrg * If any connections are already registered, the callback is immediately
21451ab64890Smrg * called for each of them.
21461ab64890Smrg */
21471ab64890SmrgStatus
21481ab64890SmrgXAddConnectionWatch(
21491ab64890Smrg    Display* dpy,
21501ab64890Smrg    XConnectionWatchProc callback,
21511ab64890Smrg    XPointer client_data
21521ab64890Smrg)
21531ab64890Smrg{
21541ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
21551ab64890Smrg    struct _XConnectionInfo *info_list;
21561ab64890Smrg    XPointer *wd_array;
21571ab64890Smrg
21581ab64890Smrg    LockDisplay(dpy);
21591ab64890Smrg
21601ab64890Smrg    /* allocate new watch data */
21611ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
21621ab64890Smrg	wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
21631ab64890Smrg					(dpy->watcher_count + 1) *
21641ab64890Smrg					sizeof(XPointer));
21651ab64890Smrg	if (!wd_array) {
21661ab64890Smrg	    UnlockDisplay(dpy);
21671ab64890Smrg	    return 0;
21681ab64890Smrg	}
21691ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
21701ab64890Smrg    }
21711ab64890Smrg
21721ab64890Smrg    new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
21731ab64890Smrg    if (!new_watcher) {
21741ab64890Smrg	UnlockDisplay(dpy);
21751ab64890Smrg	return 0;
21761ab64890Smrg    }
21771ab64890Smrg    new_watcher->fn = callback;
21781ab64890Smrg    new_watcher->client_data = client_data;
21791ab64890Smrg    new_watcher->next = NULL;
21801ab64890Smrg
21811ab64890Smrg    /* link new structure onto end of list */
21821ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
21831ab64890Smrg	;
21841ab64890Smrg    *wptr = new_watcher;
21851ab64890Smrg    dpy->watcher_count++;
21861ab64890Smrg
21871ab64890Smrg    /* call new watcher on all currently registered fds */
21881ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
21891ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
21901ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
21911ab64890Smrg    }
21921ab64890Smrg
21931ab64890Smrg    UnlockDisplay(dpy);
21941ab64890Smrg    return 1;
21951ab64890Smrg}
21961ab64890Smrg
21971ab64890Smrg/* XRemoveConnectionWatch
21981ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
21991ab64890Smrg * Both callback and client_data must match what was passed to
22001ab64890Smrg * XAddConnectionWatch.
220161b2299dSmrg */
22021ab64890Smrgvoid
22031ab64890SmrgXRemoveConnectionWatch(
22041ab64890Smrg    Display* dpy,
22051ab64890Smrg    XConnectionWatchProc callback,
22061ab64890Smrg    XPointer client_data
22071ab64890Smrg)
22081ab64890Smrg{
22091ab64890Smrg    struct _XConnWatchInfo *watch;
22101ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
22111ab64890Smrg    struct _XConnectionInfo *conni;
22121ab64890Smrg    int counter = 0;
22131ab64890Smrg
22141ab64890Smrg    LockDisplay(dpy);
22151ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
22161ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
22171ab64890Smrg	    if (previous)
22181ab64890Smrg		previous->next = watch->next;
22191ab64890Smrg	    else
22201ab64890Smrg		dpy->conn_watchers = watch->next;
22211ab64890Smrg	    Xfree (watch);
22221ab64890Smrg	    dpy->watcher_count--;
22231ab64890Smrg	    /* remove our watch_data for each connection */
22241ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
22251ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
22261ab64890Smrg		/* overlapping */
22271ab64890Smrg		memmove(conni->watch_data+counter,
22281ab64890Smrg			conni->watch_data+counter+1,
22291ab64890Smrg			dpy->watcher_count - counter);
22301ab64890Smrg	    }
22311ab64890Smrg	    break;
22321ab64890Smrg	}
22331ab64890Smrg	previous = watch;
22341ab64890Smrg	counter++;
22351ab64890Smrg    }
22361ab64890Smrg    UnlockDisplay(dpy);
22371ab64890Smrg}
22381ab64890Smrg
22391ab64890Smrg/* end of internal connections support */
22401ab64890Smrg
22411ab64890Smrg
22421ab64890Smrg#if !USE_XCB
22431ab64890Smrg/* Read and discard "n" 8-bit bytes of data */
22441ab64890Smrg
22451ab64890Smrgvoid _XEatData(
22461ab64890Smrg    Display *dpy,
22471ab64890Smrg    register unsigned long n)
22481ab64890Smrg{
22491ab64890Smrg#define SCRATCHSIZE 2048
22501ab64890Smrg    char buf[SCRATCHSIZE];
22511ab64890Smrg
22521ab64890Smrg    while (n > 0) {
22531ab64890Smrg	register long bytes_read = (n > SCRATCHSIZE) ? SCRATCHSIZE : n;
22541ab64890Smrg	(void) _XRead (dpy, buf, bytes_read);
22551ab64890Smrg	n -= bytes_read;
22561ab64890Smrg    }
22571ab64890Smrg#undef SCRATCHSIZE
22581ab64890Smrg}
22591ab64890Smrg#endif /* !USE_XCB */
22601ab64890Smrg
22611ab64890Smrg
22621ab64890Smrg/*
22631ab64890Smrg * _XEnq - Place event packets on the display's queue.
22641ab64890Smrg * note that no squishing of move events in V11, since there
22651ab64890Smrg * is pointer motion hints....
22661ab64890Smrg */
22671ab64890Smrgvoid _XEnq(
22681ab64890Smrg	register Display *dpy,
22691ab64890Smrg	register xEvent *event)
22701ab64890Smrg{
22711ab64890Smrg	register _XQEvent *qelt;
22721ab64890Smrg
22731ab64890Smrg	if ((qelt = dpy->qfree)) {
22741ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
22751ab64890Smrg		dpy->qfree = qelt->next;
22761ab64890Smrg	}
227761b2299dSmrg	else if ((qelt =
22781ab64890Smrg	    (_XQEvent *) Xmalloc((unsigned)sizeof(_XQEvent))) == NULL) {
22791ab64890Smrg		/* Malloc call failed! */
22801ab64890Smrg		ESET(ENOMEM);
22811ab64890Smrg		_XIOError(dpy);
22821ab64890Smrg	}
22831ab64890Smrg	qelt->next = NULL;
22841ab64890Smrg	/* go call through display to find proper event reformatter */
22851ab64890Smrg	if ((*dpy->event_vec[event->u.u.type & 0177])(dpy, &qelt->event, event)) {
22861ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
22871ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
22881ab64890Smrg	    else 		dpy->head = qelt;
228961b2299dSmrg
22901ab64890Smrg	    dpy->tail = qelt;
22911ab64890Smrg	    dpy->qlen++;
22921ab64890Smrg	} else {
22931ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
22941ab64890Smrg	    qelt->next = dpy->qfree;
22951ab64890Smrg	    dpy->qfree = qelt;
22961ab64890Smrg	}
22971ab64890Smrg}
22981ab64890Smrg
22991ab64890Smrg/*
23001ab64890Smrg * _XDeq - Remove event packet from the display's queue.
23011ab64890Smrg */
23021ab64890Smrgvoid _XDeq(
23031ab64890Smrg    register Display *dpy,
23041ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
23051ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
23061ab64890Smrg{
23071ab64890Smrg    if (prev) {
23081ab64890Smrg	if ((prev->next = qelt->next) == NULL)
23091ab64890Smrg	    dpy->tail = prev;
23101ab64890Smrg    } else {
23111ab64890Smrg	/* no prev, so removing first elt */
23121ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
23131ab64890Smrg	    dpy->tail = NULL;
23141ab64890Smrg    }
23151ab64890Smrg    qelt->qserial_num = 0;
23161ab64890Smrg    qelt->next = dpy->qfree;
23171ab64890Smrg    dpy->qfree = qelt;
23181ab64890Smrg    dpy->qlen--;
23191ab64890Smrg}
23201ab64890Smrg
23211ab64890Smrg/*
23221ab64890Smrg * EventToWire in separate file in that often not needed.
23231ab64890Smrg */
23241ab64890Smrg
23251ab64890Smrg/*ARGSUSED*/
23261ab64890SmrgBool
23271ab64890Smrg_XUnknownWireEvent(
23281ab64890Smrg    register Display *dpy,	/* pointer to display structure */
23291ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
23301ab64890Smrg    register xEvent *event)	/* wire protocol event */
23311ab64890Smrg{
23321ab64890Smrg#ifdef notdef
233361b2299dSmrg	(void) fprintf(stderr,
23341ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
23351ab64890Smrg			event->u.u.type, dpy);
23361ab64890Smrg#endif
23371ab64890Smrg	return(False);
23381ab64890Smrg}
23391ab64890Smrg
23401ab64890Smrg/*ARGSUSED*/
23411ab64890SmrgStatus
23421ab64890Smrg_XUnknownNativeEvent(
23431ab64890Smrg    register Display *dpy,	/* pointer to display structure */
23441ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
23451ab64890Smrg    register xEvent *event)	/* wire protocol event */
23461ab64890Smrg{
23471ab64890Smrg#ifdef notdef
234861b2299dSmrg	(void) fprintf(stderr,
23491ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
23501ab64890Smrg			re->type, dpy);
23511ab64890Smrg#endif
23521ab64890Smrg	return(0);
23531ab64890Smrg}
23541ab64890Smrg/*
23551ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
23561ab64890Smrg */
23571ab64890SmrgBool
23581ab64890Smrg_XWireToEvent(
23591ab64890Smrg    register Display *dpy,	/* pointer to display structure */
23601ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
23611ab64890Smrg    register xEvent *event)	/* wire protocol event */
23621ab64890Smrg{
23631ab64890Smrg
23641ab64890Smrg	re->type = event->u.u.type & 0x7f;
23651ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
23661ab64890Smrg					(xGenericReply *)event);
23671ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
23681ab64890Smrg	((XAnyEvent *)re)->display = dpy;
236961b2299dSmrg
23701ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
23711ab64890Smrg		client sends an event rather than the server. */
23721ab64890Smrg
23731ab64890Smrg	switch (event-> u.u.type & 0177) {
23741ab64890Smrg	      case KeyPress:
23751ab64890Smrg	      case KeyRelease:
23761ab64890Smrg	        {
23771ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
23781ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
23791ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
23801ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
23811ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
23821ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
23831ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
23841ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
23851ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
23861ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
23871ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
23881ab64890Smrg			ev->keycode 	= event->u.u.detail;
23891ab64890Smrg		}
23901ab64890Smrg	      	break;
23911ab64890Smrg	      case ButtonPress:
23921ab64890Smrg	      case ButtonRelease:
23931ab64890Smrg	        {
23941ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) re;
23951ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
23961ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
23971ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
23981ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
23991ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
24001ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
24011ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
24021ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
24031ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
24041ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
24051ab64890Smrg			ev->button 	= event->u.u.detail;
24061ab64890Smrg		}
24071ab64890Smrg	        break;
24081ab64890Smrg	      case MotionNotify:
24091ab64890Smrg	        {
24101ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
24111ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
24121ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
24131ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
24141ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
24151ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
24161ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
24171ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
24181ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
24191ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
24201ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
24211ab64890Smrg			ev->is_hint 	= event->u.u.detail;
24221ab64890Smrg		}
24231ab64890Smrg	        break;
24241ab64890Smrg	      case EnterNotify:
24251ab64890Smrg	      case LeaveNotify:
24261ab64890Smrg		{
24271ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
24281ab64890Smrg			ev->root	= event->u.enterLeave.root;
24291ab64890Smrg			ev->window	= event->u.enterLeave.event;
24301ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
24311ab64890Smrg			ev->time	= event->u.enterLeave.time;
24321ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
24331ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
24341ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
24351ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
24361ab64890Smrg			ev->state	= event->u.enterLeave.state;
24371ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
243861b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
24391ab64890Smrg				ELFlagSameScreen) && True;
24401ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
24411ab64890Smrg			  	ELFlagFocus) && True;
24421ab64890Smrg			ev->detail	= event->u.u.detail;
24431ab64890Smrg		}
24441ab64890Smrg		  break;
24451ab64890Smrg	      case FocusIn:
24461ab64890Smrg	      case FocusOut:
24471ab64890Smrg		{
24481ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
24491ab64890Smrg			ev->window 	= event->u.focus.window;
24501ab64890Smrg			ev->mode	= event->u.focus.mode;
24511ab64890Smrg			ev->detail	= event->u.u.detail;
24521ab64890Smrg		}
24531ab64890Smrg		  break;
24541ab64890Smrg	      case KeymapNotify:
24551ab64890Smrg		{
24561ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
24571ab64890Smrg			ev->window	= None;
24581ab64890Smrg			memcpy(&ev->key_vector[1],
24591ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
24601ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
24611ab64890Smrg		}
24621ab64890Smrg		break;
24631ab64890Smrg	      case Expose:
24641ab64890Smrg		{
24651ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
24661ab64890Smrg			ev->window	= event->u.expose.window;
24671ab64890Smrg			ev->x		= event->u.expose.x;
24681ab64890Smrg			ev->y		= event->u.expose.y;
24691ab64890Smrg			ev->width	= event->u.expose.width;
24701ab64890Smrg			ev->height	= event->u.expose.height;
24711ab64890Smrg			ev->count	= event->u.expose.count;
24721ab64890Smrg		}
24731ab64890Smrg		break;
24741ab64890Smrg	      case GraphicsExpose:
24751ab64890Smrg		{
24761ab64890Smrg		    register XGraphicsExposeEvent *ev =
24771ab64890Smrg			(XGraphicsExposeEvent *) re;
24781ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
24791ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
24801ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
24811ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
24821ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
24831ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
24841ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
24851ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
24861ab64890Smrg		}
24871ab64890Smrg		break;
24881ab64890Smrg	      case NoExpose:
24891ab64890Smrg		{
24901ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
24911ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
24921ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
24931ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
24941ab64890Smrg		}
24951ab64890Smrg		break;
24961ab64890Smrg	      case VisibilityNotify:
24971ab64890Smrg		{
24981ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
24991ab64890Smrg		    ev->window		= event->u.visibility.window;
25001ab64890Smrg		    ev->state		= event->u.visibility.state;
25011ab64890Smrg		}
25021ab64890Smrg		break;
25031ab64890Smrg	      case CreateNotify:
25041ab64890Smrg		{
25051ab64890Smrg		    register XCreateWindowEvent *ev =
25061ab64890Smrg			 (XCreateWindowEvent *) re;
25071ab64890Smrg		    ev->window		= event->u.createNotify.window;
25081ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
25091ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
25101ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
25111ab64890Smrg		    ev->width		= event->u.createNotify.width;
25121ab64890Smrg		    ev->height		= event->u.createNotify.height;
25131ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
25141ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
25151ab64890Smrg		}
25161ab64890Smrg		break;
25171ab64890Smrg	      case DestroyNotify:
25181ab64890Smrg		{
25191ab64890Smrg		    register XDestroyWindowEvent *ev =
25201ab64890Smrg				(XDestroyWindowEvent *) re;
25211ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
25221ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
25231ab64890Smrg		}
25241ab64890Smrg		break;
25251ab64890Smrg	      case UnmapNotify:
25261ab64890Smrg		{
25271ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
25281ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
25291ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
25301ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
25311ab64890Smrg		}
25321ab64890Smrg		break;
25331ab64890Smrg	      case MapNotify:
25341ab64890Smrg		{
25351ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
25361ab64890Smrg		    ev->window		= event->u.mapNotify.window;
25371ab64890Smrg		    ev->event		= event->u.mapNotify.event;
25381ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
25391ab64890Smrg		}
25401ab64890Smrg		break;
25411ab64890Smrg	      case MapRequest:
25421ab64890Smrg		{
25431ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
25441ab64890Smrg		    ev->window		= event->u.mapRequest.window;
25451ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
25461ab64890Smrg		}
25471ab64890Smrg		break;
25481ab64890Smrg	      case ReparentNotify:
25491ab64890Smrg		{
25501ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
25511ab64890Smrg		    ev->event		= event->u.reparent.event;
25521ab64890Smrg		    ev->window		= event->u.reparent.window;
25531ab64890Smrg		    ev->parent		= event->u.reparent.parent;
25541ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
25551ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
25561ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
25571ab64890Smrg		}
25581ab64890Smrg		break;
25591ab64890Smrg	      case ConfigureNotify:
25601ab64890Smrg		{
25611ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
25621ab64890Smrg		    ev->event	= event->u.configureNotify.event;
25631ab64890Smrg		    ev->window	= event->u.configureNotify.window;
25641ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
25651ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
25661ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
25671ab64890Smrg		    ev->width	= event->u.configureNotify.width;
25681ab64890Smrg		    ev->height	= event->u.configureNotify.height;
25691ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
25701ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
25711ab64890Smrg		}
25721ab64890Smrg		break;
25731ab64890Smrg	      case ConfigureRequest:
25741ab64890Smrg		{
25751ab64890Smrg		    register XConfigureRequestEvent *ev =
25761ab64890Smrg		        (XConfigureRequestEvent *) re;
25771ab64890Smrg		    ev->window		= event->u.configureRequest.window;
25781ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
25791ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
25801ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
25811ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
25821ab64890Smrg		    ev->width		= event->u.configureRequest.width;
25831ab64890Smrg		    ev->height		= event->u.configureRequest.height;
25841ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
25851ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
25861ab64890Smrg		    ev->detail  	= event->u.u.detail;
25871ab64890Smrg		}
25881ab64890Smrg		break;
25891ab64890Smrg	      case GravityNotify:
25901ab64890Smrg		{
25911ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
25921ab64890Smrg		    ev->window		= event->u.gravity.window;
25931ab64890Smrg		    ev->event		= event->u.gravity.event;
25941ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
25951ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
25961ab64890Smrg		}
25971ab64890Smrg		break;
25981ab64890Smrg	      case ResizeRequest:
25991ab64890Smrg		{
26001ab64890Smrg		    register XResizeRequestEvent *ev =
26011ab64890Smrg			(XResizeRequestEvent *) re;
26021ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
26031ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
26041ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
26051ab64890Smrg		}
26061ab64890Smrg		break;
26071ab64890Smrg	      case CirculateNotify:
26081ab64890Smrg		{
26091ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
26101ab64890Smrg		    ev->window		= event->u.circulate.window;
26111ab64890Smrg		    ev->event		= event->u.circulate.event;
26121ab64890Smrg		    ev->place		= event->u.circulate.place;
26131ab64890Smrg		}
26141ab64890Smrg		break;
26151ab64890Smrg	      case CirculateRequest:
26161ab64890Smrg		{
26171ab64890Smrg		    register XCirculateRequestEvent *ev =
26181ab64890Smrg		        (XCirculateRequestEvent *) re;
26191ab64890Smrg		    ev->window		= event->u.circulate.window;
26201ab64890Smrg		    ev->parent		= event->u.circulate.event;
26211ab64890Smrg		    ev->place		= event->u.circulate.place;
26221ab64890Smrg		}
26231ab64890Smrg		break;
26241ab64890Smrg	      case PropertyNotify:
26251ab64890Smrg		{
26261ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
26271ab64890Smrg		    ev->window		= event->u.property.window;
26281ab64890Smrg		    ev->atom		= event->u.property.atom;
26291ab64890Smrg		    ev->time		= event->u.property.time;
26301ab64890Smrg		    ev->state		= event->u.property.state;
26311ab64890Smrg		}
26321ab64890Smrg		break;
26331ab64890Smrg	      case SelectionClear:
26341ab64890Smrg		{
26351ab64890Smrg		    register XSelectionClearEvent *ev =
26361ab64890Smrg			 (XSelectionClearEvent *) re;
26371ab64890Smrg		    ev->window		= event->u.selectionClear.window;
26381ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
26391ab64890Smrg		    ev->time		= event->u.selectionClear.time;
26401ab64890Smrg		}
26411ab64890Smrg		break;
26421ab64890Smrg	      case SelectionRequest:
26431ab64890Smrg		{
26441ab64890Smrg		    register XSelectionRequestEvent *ev =
26451ab64890Smrg		        (XSelectionRequestEvent *) re;
26461ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
26471ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
26481ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
26491ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
26501ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
26511ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
26521ab64890Smrg		}
26531ab64890Smrg		break;
26541ab64890Smrg	      case SelectionNotify:
26551ab64890Smrg		{
26561ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
26571ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
26581ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
26591ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
26601ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
26611ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
26621ab64890Smrg		}
26631ab64890Smrg		break;
26641ab64890Smrg	      case ColormapNotify:
26651ab64890Smrg		{
26661ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
26671ab64890Smrg		    ev->window		= event->u.colormap.window;
26681ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
26691ab64890Smrg		    ev->new		= event->u.colormap.new;
26701ab64890Smrg		    ev->state		= event->u.colormap.state;
26711ab64890Smrg	        }
26721ab64890Smrg		break;
26731ab64890Smrg	      case ClientMessage:
26741ab64890Smrg		{
26751ab64890Smrg		   register int i;
267661b2299dSmrg		   register XClientMessageEvent *ev
26771ab64890Smrg		   			= (XClientMessageEvent *) re;
26781ab64890Smrg		   ev->window		= event->u.clientMessage.window;
26791ab64890Smrg		   ev->format		= event->u.u.detail;
26801ab64890Smrg		   switch (ev->format) {
268161b2299dSmrg			case 8:
26821ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
268361b2299dSmrg			   for (i = 0; i < 20; i++)
26841ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
26851ab64890Smrg			   break;
26861ab64890Smrg			case 16:
26871ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
26881ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
26891ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
26901ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
26911ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
26921ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
26931ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
26941ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
26951ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
26961ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
26971ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
26981ab64890Smrg			   break;
26991ab64890Smrg			case 32:
27001ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
27011ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
27021ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
27031ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
27041ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
27051ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
27061ab64890Smrg			   break;
27071ab64890Smrg			default: /* XXX should never occur */
27081ab64890Smrg				break;
27091ab64890Smrg		    }
27101ab64890Smrg	        }
27111ab64890Smrg		break;
27121ab64890Smrg	      case MappingNotify:
27131ab64890Smrg		{
27141ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
27151ab64890Smrg		   ev->window		= 0;
27161ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
27171ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
27181ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
27191ab64890Smrg		}
27201ab64890Smrg		break;
27211ab64890Smrg	      default:
27221ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
27231ab64890Smrg	}
27241ab64890Smrg	return(True);
27251ab64890Smrg}
27261ab64890Smrg
27271ab64890Smrg
27281ab64890Smrg/*
272961b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
27301ab64890Smrg * when an X internal system error is encountered.
27311ab64890Smrg */
27321ab64890Smrgint _XDefaultIOError(
27331ab64890Smrg	Display *dpy)
27341ab64890Smrg{
27351ab64890Smrg	if (ECHECK(EPIPE)) {
27361ab64890Smrg	    (void) fprintf (stderr,
27371ab64890Smrg	"X connection to %s broken (explicit kill or server shutdown).\r\n",
27381ab64890Smrg			    DisplayString (dpy));
27391ab64890Smrg	} else {
274061b2299dSmrg	    (void) fprintf (stderr,
27411ab64890Smrg			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
27421ab64890Smrg#ifdef WIN32
27431ab64890Smrg			WSAGetLastError(), strerror(WSAGetLastError()),
27441ab64890Smrg#else
27451ab64890Smrg			errno, strerror (errno),
27461ab64890Smrg#endif
27471ab64890Smrg			DisplayString (dpy));
274861b2299dSmrg	    (void) fprintf (stderr,
27491ab64890Smrg	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
27501ab64890Smrg			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
27511ab64890Smrg			QLength(dpy));
27521ab64890Smrg
27531ab64890Smrg	}
27541ab64890Smrg	exit(1);
27551ab64890Smrg        return(0); /* dummy - function should never return */
27561ab64890Smrg}
27571ab64890Smrg
27581ab64890Smrg
27591ab64890Smrgstatic int _XPrintDefaultError(
27601ab64890Smrg    Display *dpy,
27611ab64890Smrg    XErrorEvent *event,
27621ab64890Smrg    FILE *fp)
27631ab64890Smrg{
27641ab64890Smrg    char buffer[BUFSIZ];
27651ab64890Smrg    char mesg[BUFSIZ];
27661ab64890Smrg    char number[32];
27671ab64890Smrg    const char *mtype = "XlibMessage";
27681ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
27691ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
27701ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
27711ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
27721ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
277361b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
27741ab64890Smrg	mesg, BUFSIZ);
27751ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
27761ab64890Smrg    if (event->request_code < 128) {
27771ab64890Smrg	sprintf(number, "%d", event->request_code);
27781ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
27791ab64890Smrg    } else {
27801ab64890Smrg	for (ext = dpy->ext_procs;
27811ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
27821ab64890Smrg	     ext = ext->next)
27831ab64890Smrg	  ;
27841ab64890Smrg	if (ext)
27851ab64890Smrg	    strcpy(buffer, ext->name);
27861ab64890Smrg	else
27871ab64890Smrg	    buffer[0] = '\0';
27881ab64890Smrg    }
27891ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
27901ab64890Smrg    if (event->request_code >= 128) {
27911ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
27921ab64890Smrg			      mesg, BUFSIZ);
27931ab64890Smrg	fputs("  ", fp);
27941ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
27951ab64890Smrg	if (ext) {
27961ab64890Smrg	    sprintf(mesg, "%s.%d", ext->name, event->minor_code);
27971ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
27981ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
27991ab64890Smrg	}
28001ab64890Smrg	fputs("\n", fp);
28011ab64890Smrg    }
28021ab64890Smrg    if (event->error_code >= 128) {
28031ab64890Smrg	/* kludge, try to find the extension that caused it */
28041ab64890Smrg	buffer[0] = '\0';
28051ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
280661b2299dSmrg	    if (ext->error_string)
28071ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
28081ab64890Smrg				     buffer, BUFSIZ);
28091ab64890Smrg	    if (buffer[0]) {
28101ab64890Smrg		bext = ext;
28111ab64890Smrg		break;
28121ab64890Smrg	    }
28131ab64890Smrg	    if (ext->codes.first_error &&
28141ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
28151ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
28161ab64890Smrg		bext = ext;
281761b2299dSmrg	}
28181ab64890Smrg	if (bext)
28191ab64890Smrg	    sprintf(buffer, "%s.%d", bext->name,
28201ab64890Smrg		    event->error_code - bext->codes.first_error);
28211ab64890Smrg	else
28221ab64890Smrg	    strcpy(buffer, "Value");
28231ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
28241ab64890Smrg	if (mesg[0]) {
28251ab64890Smrg	    fputs("  ", fp);
28261ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
28271ab64890Smrg	    fputs("\n", fp);
28281ab64890Smrg	}
28291ab64890Smrg	/* let extensions try to print the values */
28301ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
28311ab64890Smrg	    if (ext->error_values)
28321ab64890Smrg		(*ext->error_values)(dpy, event, fp);
28331ab64890Smrg	}
28341ab64890Smrg    } else if ((event->error_code == BadWindow) ||
28351ab64890Smrg	       (event->error_code == BadPixmap) ||
28361ab64890Smrg	       (event->error_code == BadCursor) ||
28371ab64890Smrg	       (event->error_code == BadFont) ||
28381ab64890Smrg	       (event->error_code == BadDrawable) ||
28391ab64890Smrg	       (event->error_code == BadColor) ||
28401ab64890Smrg	       (event->error_code == BadGC) ||
28411ab64890Smrg	       (event->error_code == BadIDChoice) ||
28421ab64890Smrg	       (event->error_code == BadValue) ||
28431ab64890Smrg	       (event->error_code == BadAtom)) {
28441ab64890Smrg	if (event->error_code == BadValue)
28451ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
28461ab64890Smrg				  mesg, BUFSIZ);
28471ab64890Smrg	else if (event->error_code == BadAtom)
28481ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
28491ab64890Smrg				  mesg, BUFSIZ);
28501ab64890Smrg	else
28511ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
28521ab64890Smrg				  mesg, BUFSIZ);
28531ab64890Smrg	fputs("  ", fp);
28541ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
28551ab64890Smrg	fputs("\n", fp);
28561ab64890Smrg    }
285761b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
28581ab64890Smrg			  mesg, BUFSIZ);
28591ab64890Smrg    fputs("  ", fp);
28601ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
28611ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
28621ab64890Smrg			  mesg, BUFSIZ);
28631ab64890Smrg    fputs("\n  ", fp);
28641ab64890Smrg    (void) fprintf(fp, mesg, dpy->request);
28651ab64890Smrg    fputs("\n", fp);
28661ab64890Smrg    if (event->error_code == BadImplementation) return 0;
28671ab64890Smrg    return 1;
28681ab64890Smrg}
28691ab64890Smrg
28701ab64890Smrgint _XDefaultError(
28711ab64890Smrg	Display *dpy,
28721ab64890Smrg	XErrorEvent *event)
28731ab64890Smrg{
28741ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
28751ab64890Smrg    exit(1);
28761ab64890Smrg    /*NOTREACHED*/
28771ab64890Smrg}
28781ab64890Smrg
28791ab64890Smrg/*ARGSUSED*/
288061b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
28811ab64890Smrg{
28821ab64890Smrg    return True;
28831ab64890Smrg}
28841ab64890Smrg
28851ab64890Smrg/*
28861ab64890Smrg * _XError - upcall internal or user protocol error handler
28871ab64890Smrg */
28881ab64890Smrgint _XError (
28891ab64890Smrg    Display *dpy,
28901ab64890Smrg    register xError *rep)
28911ab64890Smrg{
289261b2299dSmrg    /*
28931ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
28941ab64890Smrg     * giving it to the user.
28951ab64890Smrg     */
28961ab64890Smrg    XEvent event; /* make it a large event */
28971ab64890Smrg    register _XAsyncHandler *async, *next;
28981ab64890Smrg
28991ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
29001ab64890Smrg
29011ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
29021ab64890Smrg	next = async->next;
29031ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
29041ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
29051ab64890Smrg	    return 0;
29061ab64890Smrg    }
29071ab64890Smrg
29081ab64890Smrg    event.xerror.display = dpy;
29091ab64890Smrg    event.xerror.type = X_Error;
29101ab64890Smrg    event.xerror.resourceid = rep->resourceID;
29111ab64890Smrg    event.xerror.error_code = rep->errorCode;
29121ab64890Smrg    event.xerror.request_code = rep->majorCode;
29131ab64890Smrg    event.xerror.minor_code = rep->minorCode;
29141ab64890Smrg    if (dpy->error_vec &&
29151ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
29161ab64890Smrg	return 0;
29171ab64890Smrg    if (_XErrorFunction != NULL) {
29181ab64890Smrg	int rtn_val;
29191ab64890Smrg#if defined(XTHREADS) && !USE_XCB
29201ab64890Smrg	if (dpy->lock)
29211ab64890Smrg	    (*dpy->lock->user_lock_display)(dpy);
29221ab64890Smrg	UnlockDisplay(dpy);
29231ab64890Smrg#endif /* XTHREADS && !USE_XCB */
29241ab64890Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
29251ab64890Smrg#if defined(XTHREADS) && !USE_XCB
29261ab64890Smrg	LockDisplay(dpy);
29271ab64890Smrg	if (dpy->lock)
29281ab64890Smrg	    (*dpy->lock->user_unlock_display)(dpy);
29291ab64890Smrg#endif /* XTHREADS && !USE_XCB */
29301ab64890Smrg	return rtn_val;
29311ab64890Smrg    } else {
29321ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
29331ab64890Smrg    }
29341ab64890Smrg}
293561b2299dSmrg
29361ab64890Smrg/*
29371ab64890Smrg * _XIOError - call user connection error handler and exit
29381ab64890Smrg */
29391ab64890Smrgint
29401ab64890Smrg_XIOError (
29411ab64890Smrg    Display *dpy)
29421ab64890Smrg{
29431ab64890Smrg    dpy->flags |= XlibDisplayIOError;
29441ab64890Smrg#ifdef WIN32
29451ab64890Smrg    errno = WSAGetLastError();
29461ab64890Smrg#endif
29471ab64890Smrg
29481ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
29491ab64890Smrg     * If this does not hold, then an alternate solution would involve
29501ab64890Smrg     * registering an atexit handler to take over the lock, which would only
29511ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
29521ab64890Smrg#ifdef XTHREADS
29531ab64890Smrg    if (dpy->lock)
29541ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
29551ab64890Smrg#endif
29561ab64890Smrg    UnlockDisplay(dpy);
29571ab64890Smrg
29581ab64890Smrg    if (_XIOErrorFunction != NULL)
29591ab64890Smrg	(*_XIOErrorFunction)(dpy);
29601ab64890Smrg    else
29611ab64890Smrg	_XDefaultIOError(dpy);
29621ab64890Smrg    exit (1);
29631ab64890Smrg    return 0;
29641ab64890Smrg}
29651ab64890Smrg
29661ab64890Smrg
29671ab64890Smrg/*
29681ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
29691ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
29701ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
29711ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
29721ab64890Smrg * is guaranteed to not unlock the display.
29731ab64890Smrg */
29741ab64890Smrgchar *_XAllocScratch(
29751ab64890Smrg	register Display *dpy,
29761ab64890Smrg	unsigned long nbytes)
29771ab64890Smrg{
29781ab64890Smrg	if (nbytes > dpy->scratch_length) {
29791ab64890Smrg	    if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
29801ab64890Smrg	    if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
29811ab64890Smrg		dpy->scratch_length = nbytes;
29821ab64890Smrg	    else dpy->scratch_length = 0;
29831ab64890Smrg	}
29841ab64890Smrg	return (dpy->scratch_buffer);
29851ab64890Smrg}
29861ab64890Smrg
29871ab64890Smrg/*
29881ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
29891ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
29901ab64890Smrg */
29911ab64890Smrgchar *_XAllocTemp(
29921ab64890Smrg    register Display *dpy,
29931ab64890Smrg    unsigned long nbytes)
29941ab64890Smrg{
29951ab64890Smrg    char *buf;
29961ab64890Smrg
29971ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
29981ab64890Smrg    dpy->scratch_buffer = NULL;
29991ab64890Smrg    dpy->scratch_length = 0;
30001ab64890Smrg    return buf;
30011ab64890Smrg}
30021ab64890Smrg
30031ab64890Smrgvoid _XFreeTemp(
30041ab64890Smrg    register Display *dpy,
30051ab64890Smrg    char *buf,
30061ab64890Smrg    unsigned long nbytes)
30071ab64890Smrg{
30081ab64890Smrg    if (dpy->scratch_buffer)
30091ab64890Smrg	Xfree(dpy->scratch_buffer);
30101ab64890Smrg    dpy->scratch_buffer = buf;
30111ab64890Smrg    dpy->scratch_length = nbytes;
30121ab64890Smrg}
30131ab64890Smrg
30141ab64890Smrg/*
30151ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
30161ab64890Smrg */
30171ab64890SmrgVisual *_XVIDtoVisual(
30181ab64890Smrg	Display *dpy,
30191ab64890Smrg	VisualID id)
30201ab64890Smrg{
30211ab64890Smrg	register int i, j, k;
30221ab64890Smrg	register Screen *sp;
30231ab64890Smrg	register Depth *dp;
30241ab64890Smrg	register Visual *vp;
30251ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
30261ab64890Smrg		sp = &dpy->screens[i];
30271ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
30281ab64890Smrg			dp = &sp->depths[j];
30291ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
30301ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
30311ab64890Smrg				vp = &dp->visuals[k];
30321ab64890Smrg				if (vp->visualid == id) return (vp);
30331ab64890Smrg			}
30341ab64890Smrg		}
30351ab64890Smrg	}
30361ab64890Smrg	return (NULL);
30371ab64890Smrg}
30381ab64890Smrg
30391ab64890Smrgint
30401ab64890SmrgXFree (void *data)
30411ab64890Smrg{
30421ab64890Smrg	Xfree (data);
30431ab64890Smrg	return 1;
30441ab64890Smrg}
30451ab64890Smrg
30461ab64890Smrg#ifdef _XNEEDBCOPYFUNC
30471ab64890Smrgvoid _Xbcopy(b1, b2, length)
30481ab64890Smrg    register char *b1, *b2;
30491ab64890Smrg    register length;
30501ab64890Smrg{
30511ab64890Smrg    if (b1 < b2) {
30521ab64890Smrg	b2 += length;
30531ab64890Smrg	b1 += length;
30541ab64890Smrg	while (length--)
30551ab64890Smrg	    *--b2 = *--b1;
30561ab64890Smrg    } else {
30571ab64890Smrg	while (length--)
30581ab64890Smrg	    *b2++ = *b1++;
30591ab64890Smrg    }
30601ab64890Smrg}
30611ab64890Smrg#endif
30621ab64890Smrg
30631ab64890Smrg#ifdef DataRoutineIsProcedure
30641ab64890Smrgvoid Data(
30651ab64890Smrg	Display *dpy,
30661ab64890Smrg	char *data,
30671ab64890Smrg	long len)
30681ab64890Smrg{
30691ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
30701ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
30711ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
30721ab64890Smrg	} else {
30731ab64890Smrg		_XSend(dpy, data, len);
30741ab64890Smrg	}
30751ab64890Smrg}
30761ab64890Smrg#endif /* DataRoutineIsProcedure */
30771ab64890Smrg
30781ab64890Smrg
30791ab64890Smrg#ifdef LONG64
30801ab64890Smrgint
30811ab64890Smrg_XData32(
30821ab64890Smrg    Display *dpy,
30831ab64890Smrg    register long *data,
30841ab64890Smrg    unsigned len)
30851ab64890Smrg{
30861ab64890Smrg    register int *buf;
30871ab64890Smrg    register long i;
30881ab64890Smrg
30891ab64890Smrg    while (len) {
30901ab64890Smrg	buf = (int *)dpy->bufptr;
30911ab64890Smrg	i = dpy->bufmax - (char *)buf;
30921ab64890Smrg	if (!i) {
30931ab64890Smrg	    _XFlush(dpy);
30941ab64890Smrg	    continue;
30951ab64890Smrg	}
30961ab64890Smrg	if (len < i)
30971ab64890Smrg	    i = len;
30981ab64890Smrg	dpy->bufptr = (char *)buf + i;
30991ab64890Smrg	len -= i;
31001ab64890Smrg	i >>= 2;
31011ab64890Smrg	while (--i >= 0)
31021ab64890Smrg	    *buf++ = *data++;
31031ab64890Smrg    }
31041ab64890Smrg    return 0;
31051ab64890Smrg}
31061ab64890Smrg#endif /* LONG64 */
31071ab64890Smrg
31081ab64890Smrg#ifdef WORD64
31091ab64890Smrg
31101ab64890Smrg/*
311161b2299dSmrg * XXX This is a *really* stupid way of doing this.  It should just use
31121ab64890Smrg * dpy->bufptr directly, taking into account where in the word it is.
31131ab64890Smrg */
31141ab64890Smrg
31151ab64890Smrg/*
31161ab64890Smrg * Data16 - Place 16 bit data in the buffer.
31171ab64890Smrg *
31181ab64890Smrg * "dpy" is a pointer to a Display.
31191ab64890Smrg * "data" is a pointer to the data.
31201ab64890Smrg * "len" is the length in bytes of the data.
31211ab64890Smrg */
31221ab64890Smrg
31231ab64890Smrgstatic doData16(
31241ab64890Smrg    register Display *dpy,
31251ab64890Smrg    short *data,
31261ab64890Smrg    unsigned len,
31271ab64890Smrg    char *packbuffer)
31281ab64890Smrg{
31291ab64890Smrg    long *lp,*lpack;
31301ab64890Smrg    long i, nwords,bits;
31311ab64890Smrg    long mask16 = 0x000000000000ffff;
31321ab64890Smrg
31331ab64890Smrg        lp = (long *)data;
31341ab64890Smrg        lpack = (long *)packbuffer;
31351ab64890Smrg
31361ab64890Smrg/*  nwords is the number of 16 bit values to be packed,
31371ab64890Smrg *  the low order 16 bits of each word will be packed
31381ab64890Smrg *  into 64 bit words
31391ab64890Smrg */
31401ab64890Smrg        nwords = len >> 1;
31411ab64890Smrg        bits = 48;
31421ab64890Smrg
31431ab64890Smrg        for(i=0;i<nwords;i++){
31441ab64890Smrg	   if (bits == 48) *lpack = 0;
31451ab64890Smrg           *lpack ^= (*lp & mask16) << bits;
31461ab64890Smrg           bits -= 16 ;
31471ab64890Smrg           lp++;
31481ab64890Smrg           if(bits < 0){
31491ab64890Smrg               lpack++;
31501ab64890Smrg               bits = 48;
31511ab64890Smrg           }
31521ab64890Smrg        }
31531ab64890Smrg        Data(dpy, packbuffer, len);
31541ab64890Smrg}
31551ab64890Smrg
31561ab64890Smrg_XData16 (
31571ab64890Smrg    Display *dpy,
31581ab64890Smrg    short *data,
31591ab64890Smrg    unsigned len)
31601ab64890Smrg{
31611ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
31621ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 1;
31631ab64890Smrg
31641ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
31651ab64890Smrg	doData16 (dpy, data, PACKBUFFERSIZE, packbuffer);
31661ab64890Smrg    }
31671ab64890Smrg    if (len) doData16 (dpy, data, len, packbuffer);
31681ab64890Smrg}
31691ab64890Smrg
31701ab64890Smrg/*
31711ab64890Smrg * Data32 - Place 32 bit data in the buffer.
31721ab64890Smrg *
31731ab64890Smrg * "dpy" is a pointer to a Display.
31741ab64890Smrg * "data" is a pointer to the data.
31751ab64890Smrg * "len" is the length in bytes of the data.
31761ab64890Smrg */
31771ab64890Smrg
31781ab64890Smrgstatic doData32(
31791ab64890Smrg    register Display *dpy
31801ab64890Smrg    long *data,
31811ab64890Smrg    unsigned len,
31821ab64890Smrg    char *packbuffer)
31831ab64890Smrg{
31841ab64890Smrg    long *lp,*lpack;
31851ab64890Smrg    long i,bits,nwords;
31861ab64890Smrg    long mask32 = 0x00000000ffffffff;
31871ab64890Smrg
31881ab64890Smrg        lpack = (long *) packbuffer;
31891ab64890Smrg        lp = data;
31901ab64890Smrg
31911ab64890Smrg/*  nwords is the number of 32 bit values to be packed
31921ab64890Smrg *  the low order 32 bits of each word will be packed
31931ab64890Smrg *  into 64 bit words
31941ab64890Smrg */
31951ab64890Smrg        nwords = len >> 2;
31961ab64890Smrg        bits = 32;
31971ab64890Smrg
31981ab64890Smrg        for(i=0;i<nwords;i++){
31991ab64890Smrg	   if (bits == 32) *lpack = 0;
32001ab64890Smrg           *lpack ^= (*lp & mask32) << bits;
32011ab64890Smrg           bits = bits ^32;
32021ab64890Smrg           lp++;
32031ab64890Smrg           if(bits)
32041ab64890Smrg              lpack++;
32051ab64890Smrg        }
32061ab64890Smrg        Data(dpy, packbuffer, len);
32071ab64890Smrg}
32081ab64890Smrg
32091ab64890Smrgvoid _XData32(
32101ab64890Smrg    Display *dpy,
32111ab64890Smrg    long *data,
321261b2299dSmrg    unsigned len)
32131ab64890Smrg{
32141ab64890Smrg    char packbuffer[PACKBUFFERSIZE];
32151ab64890Smrg    unsigned nunits = PACKBUFFERSIZE >> 2;
32161ab64890Smrg
32171ab64890Smrg    for (; len > PACKBUFFERSIZE; len -= PACKBUFFERSIZE, data += nunits) {
32181ab64890Smrg	doData32 (dpy, data, PACKBUFFERSIZE, packbuffer);
32191ab64890Smrg    }
32201ab64890Smrg    if (len) doData32 (dpy, data, len, packbuffer);
32211ab64890Smrg}
32221ab64890Smrg
32231ab64890Smrg#endif /* WORD64 */
32241ab64890Smrg
32251ab64890Smrg
32261ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
32271ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
32281ab64890Smrg *
32291ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
32301ab64890Smrg *       to have sufficient information for interfacing to the network,
32311ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
32321ab64890Smrg */
32331ab64890Smrg
32342e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
32351ab64890Smrg#define NEED_UTSNAME
32361ab64890Smrg#include <sys/utsname.h>
32371ab64890Smrg#endif
32381ab64890Smrg
32391ab64890Smrg/*
32401ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
32411ab64890Smrg */
32421ab64890Smrgint _XGetHostname (
32431ab64890Smrg    char *buf,
32441ab64890Smrg    int maxlen)
32451ab64890Smrg{
32461ab64890Smrg    int len;
32471ab64890Smrg
32481ab64890Smrg#ifdef NEED_UTSNAME
32491ab64890Smrg    struct utsname name;
32501ab64890Smrg
32511ab64890Smrg    if (maxlen <= 0 || buf == NULL)
32521ab64890Smrg	return 0;
32531ab64890Smrg
32541ab64890Smrg    uname (&name);
32551ab64890Smrg    len = strlen (name.nodename);
32561ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
32571ab64890Smrg    strncpy (buf, name.nodename, len);
32581ab64890Smrg    buf[len] = '\0';
32591ab64890Smrg#else
32601ab64890Smrg    if (maxlen <= 0 || buf == NULL)
32611ab64890Smrg	return 0;
32621ab64890Smrg
32631ab64890Smrg    buf[0] = '\0';
32641ab64890Smrg    (void) gethostname (buf, maxlen);
32651ab64890Smrg    buf [maxlen - 1] = '\0';
32661ab64890Smrg    len = strlen(buf);
32671ab64890Smrg#endif /* NEED_UTSNAME */
32681ab64890Smrg    return len;
32691ab64890Smrg}
32701ab64890Smrg
32711ab64890Smrg
32721ab64890Smrg/*
32731ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
32741ab64890Smrg */
32751ab64890Smrg
327661b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
32771ab64890Smrg{
32781ab64890Smrg    register int i;
32791ab64890Smrg    Window root;
32801ab64890Smrg    int x, y;				/* dummy variables */
32811ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
32821ab64890Smrg
32831ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
32841ab64890Smrg		      &bw, &depth) == False) {
32852e9c7c8cSmrg	return NULL;
32861ab64890Smrg    }
32871ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
32881ab64890Smrg	if (root == RootWindow (dpy, i)) {
32891ab64890Smrg	    return ScreenOfDisplay (dpy, i);
32901ab64890Smrg	}
32911ab64890Smrg    }
32921ab64890Smrg    return NULL;
32931ab64890Smrg}
32941ab64890Smrg
32951ab64890Smrg
32961ab64890Smrg#if defined(WIN32)
32971ab64890Smrg
32981ab64890Smrg/*
32991ab64890Smrg * These functions are intended to be used internally to Xlib only.
33001ab64890Smrg * These functions will always prefix the path with a DOS drive in the
33011ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
33021ab64890Smrg * for use by Xlib function that supply a root-based path to some
33031ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
33041ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
33051ab64890Smrg */
33061ab64890Smrg
33071ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
33081ab64890Smrg    char* path;
33091ab64890Smrg    char* pathbuf;
33101ab64890Smrg    int len_pathbuf;
33111ab64890Smrg    char** pathret;
33121ab64890Smrg{
33131ab64890Smrg    if (access (path, F_OK) == 0) {
33141ab64890Smrg	if (strlen (path) < len_pathbuf)
33151ab64890Smrg	    *pathret = pathbuf;
33161ab64890Smrg	else
33171ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
33181ab64890Smrg	if (*pathret) {
33191ab64890Smrg	    strcpy (*pathret, path);
33201ab64890Smrg	    return 1;
33211ab64890Smrg	}
33221ab64890Smrg    }
33231ab64890Smrg    return 0;
33241ab64890Smrg}
33251ab64890Smrg
33261ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
33271ab64890Smrg    char* path;
33281ab64890Smrg    char* pathbuf;
33291ab64890Smrg    int len_pathbuf;
33301ab64890Smrg    char** pathret;
33311ab64890Smrg{
33321ab64890Smrg    unsigned long drives;
33331ab64890Smrg    int i, len;
33341ab64890Smrg    char* drive;
33351ab64890Smrg    char buf[MAX_PATH];
33361ab64890Smrg    char* bufp;
33371ab64890Smrg
33381ab64890Smrg    /* just try the "raw" name first and see if it works */
33391ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
33401ab64890Smrg	return 1;
33411ab64890Smrg
33421ab64890Smrg    /* try the places set in the environment */
33431ab64890Smrg    drive = getenv ("_XBASEDRIVE");
33441ab64890Smrg#ifdef __UNIXOS2__
33451ab64890Smrg    if (!drive)
33461ab64890Smrg	drive = getenv ("X11ROOT");
33471ab64890Smrg#endif
33481ab64890Smrg    if (!drive)
33491ab64890Smrg	drive = "C:";
33501ab64890Smrg    len = strlen (drive) + strlen (path);
33511ab64890Smrg    if (len < MAX_PATH) bufp = buf;
33521ab64890Smrg    else bufp = Xmalloc (len + 1);
33531ab64890Smrg    strcpy (bufp, drive);
33541ab64890Smrg    strcat (bufp, path);
33551ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
33561ab64890Smrg	if (bufp != buf) Xfree (bufp);
33571ab64890Smrg	return 1;
33581ab64890Smrg    }
33591ab64890Smrg
336061b2299dSmrg#ifndef __UNIXOS2__
33611ab64890Smrg    /* one last place to look */
33621ab64890Smrg    drive = getenv ("HOMEDRIVE");
33631ab64890Smrg    if (drive) {
33641ab64890Smrg	len = strlen (drive) + strlen (path);
33651ab64890Smrg	if (len < MAX_PATH) bufp = buf;
33661ab64890Smrg	else bufp = Xmalloc (len + 1);
33671ab64890Smrg	strcpy (bufp, drive);
33681ab64890Smrg	strcat (bufp, path);
33691ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
33701ab64890Smrg	    if (bufp != buf) Xfree (bufp);
33711ab64890Smrg	    return 1;
33721ab64890Smrg	}
33731ab64890Smrg    }
33741ab64890Smrg
33751ab64890Smrg    /* tried everywhere else, go fishing */
33761ab64890Smrg#define C_DRIVE ('C' - 'A')
33771ab64890Smrg#define Z_DRIVE ('Z' - 'A')
33781ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
33791ab64890Smrg    drives = _getdrives ();
33801ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
33811ab64890Smrg	if ((1 << i) & drives) {
33821ab64890Smrg	    len = 2 + strlen (path);
33831ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
33841ab64890Smrg	    else bufp = Xmalloc (len + 1);
33851ab64890Smrg	    *bufp = 'A' + i;
33861ab64890Smrg	    *(bufp + 1) = ':';
33871ab64890Smrg	    *(bufp + 2) = '\0';
33881ab64890Smrg	    strcat (bufp, path);
33891ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
33901ab64890Smrg		if (bufp != buf) Xfree (bufp);
33911ab64890Smrg		return 1;
33921ab64890Smrg	    }
33931ab64890Smrg	}
33941ab64890Smrg    }
33951ab64890Smrg#endif
33961ab64890Smrg    return 0;
33971ab64890Smrg}
33981ab64890Smrg
33991ab64890Smrgint _XOpenFile(path, flags)
34001ab64890Smrg    _Xconst char* path;
34011ab64890Smrg    int flags;
34021ab64890Smrg{
34031ab64890Smrg    char buf[MAX_PATH];
34041ab64890Smrg    char* bufp = NULL;
34051ab64890Smrg    int ret = -1;
34061ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
34071ab64890Smrg
34081ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
34091ab64890Smrg	ret = open (bufp, flags);
34101ab64890Smrg
34111ab64890Smrg    (void) SetErrorMode (olderror);
34121ab64890Smrg
34131ab64890Smrg    if (bufp != buf) Xfree (bufp);
34141ab64890Smrg
34151ab64890Smrg    return ret;
34161ab64890Smrg}
34171ab64890Smrg
34181ab64890Smrgint _XOpenFileMode(path, flags, mode)
34191ab64890Smrg    _Xconst char* path;
34201ab64890Smrg    int flags;
34211ab64890Smrg    mode_t mode;
34221ab64890Smrg{
34231ab64890Smrg    char buf[MAX_PATH];
34241ab64890Smrg    char* bufp = NULL;
34251ab64890Smrg    int ret = -1;
34261ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
34271ab64890Smrg
34281ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
34291ab64890Smrg	ret = open (bufp, flags, mode);
34301ab64890Smrg
34311ab64890Smrg    (void) SetErrorMode (olderror);
34321ab64890Smrg
34331ab64890Smrg    if (bufp != buf) Xfree (bufp);
34341ab64890Smrg
34351ab64890Smrg    return ret;
34361ab64890Smrg}
34371ab64890Smrg
34381ab64890Smrgvoid* _XFopenFile(path, mode)
34391ab64890Smrg    _Xconst char* path;
34401ab64890Smrg    _Xconst char* mode;
34411ab64890Smrg{
34421ab64890Smrg    char buf[MAX_PATH];
34431ab64890Smrg    char* bufp = NULL;
34441ab64890Smrg    void* ret = NULL;
34451ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
34461ab64890Smrg
34471ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
34481ab64890Smrg	ret = fopen (bufp, mode);
34491ab64890Smrg
34501ab64890Smrg    (void) SetErrorMode (olderror);
34511ab64890Smrg
34521ab64890Smrg    if (bufp != buf) Xfree (bufp);
34531ab64890Smrg
34541ab64890Smrg    return ret;
34551ab64890Smrg}
34561ab64890Smrg
34571ab64890Smrgint _XAccessFile(path)
34581ab64890Smrg    _Xconst char* path;
34591ab64890Smrg{
34601ab64890Smrg    char buf[MAX_PATH];
34611ab64890Smrg    char* bufp;
34621ab64890Smrg    int ret = -1;
34631ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
34641ab64890Smrg
34651ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
34661ab64890Smrg
34671ab64890Smrg    (void) SetErrorMode (olderror);
34681ab64890Smrg
34691ab64890Smrg    if (bufp != buf) Xfree (bufp);
34701ab64890Smrg
34711ab64890Smrg    return ret;
34721ab64890Smrg}
34731ab64890Smrg
34741ab64890Smrg#endif
34751ab64890Smrg
34761ab64890Smrg#ifdef WIN32
34771ab64890Smrg#undef _Xdebug
34781ab64890Smrgint _Xdebug = 0;
34791ab64890Smrgint *_Xdebug_p = &_Xdebug;
34801ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
34811ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
34821ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
34831ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
34841ab64890Smrg    , char * /* file */
34851ab64890Smrg    , int /* line */
34861ab64890Smrg#endif
34871ab64890Smrg        ) = &_XLockMutex_fn;
34881ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
34891ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
34901ab64890Smrg    , char * /* file */
34911ab64890Smrg    , int /* line */
34921ab64890Smrg#endif
34931ab64890Smrg        ) = &_XUnlockMutex_fn;
34941ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
34951ab64890Smrg#endif
3496