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