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