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