XlibInt.c revision e89c59a9
11ab64890Smrg/*
21ab64890Smrg
31ab64890SmrgCopyright 1985, 1986, 1987, 1998  The Open Group
41ab64890Smrg
51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
71ab64890Smrgthe above copyright notice appear in all copies and that both that
81ab64890Smrgcopyright notice and this permission notice appear in supporting
91ab64890Smrgdocumentation.
101ab64890Smrg
111ab64890SmrgThe above copyright notice and this permission notice shall be included
121ab64890Smrgin all copies or substantial portions of the Software.
131ab64890Smrg
141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE.
211ab64890Smrg
221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall
231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or
241ab64890Smrgother dealings in this Software without prior written authorization
251ab64890Smrgfrom The Open Group.
261ab64890Smrg
271ab64890Smrg*/
281ab64890Smrg
291ab64890Smrg/*
301ab64890Smrg *	XlibInt.c - Internal support routines for the C subroutine
311ab64890Smrg *	interface library (Xlib) to the X Window System Protocol V11.0.
321ab64890Smrg */
331ab64890Smrg
341ab64890Smrg#ifdef WIN32
351ab64890Smrg#define _XLIBINT_
361ab64890Smrg#endif
371ab64890Smrg#ifdef HAVE_CONFIG_H
381ab64890Smrg#include <config.h>
391ab64890Smrg#endif
401ab64890Smrg#include "Xlibint.h"
4161b2299dSmrg#include "Xprivate.h"
421ab64890Smrg#include <X11/Xpoll.h>
4361b2299dSmrg#include <assert.h>
441ab64890Smrg#include <stdio.h>
451ab64890Smrg#ifdef WIN32
461ab64890Smrg#include <direct.h>
471ab64890Smrg#endif
481ab64890Smrg
491ab64890Smrg#ifdef XTHREADS
501ab64890Smrg#include "locking.h"
511ab64890Smrg
521ab64890Smrg/* these pointers get initialized by XInitThreads */
531ab64890SmrgLockInfoPtr _Xglobal_lock = NULL;
541ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
551ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
561ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
571ab64890Smrgvoid (*_XLockMutex_fn)(
581ab64890Smrg    LockInfoPtr /* lock */
591ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
601ab64890Smrg    , char * /* file */
611ab64890Smrg    , int /* line */
621ab64890Smrg#endif
631ab64890Smrg    ) = NULL;
641ab64890Smrgvoid (*_XUnlockMutex_fn)(
651ab64890Smrg    LockInfoPtr /* lock */
661ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
671ab64890Smrg    , char * /* file */
681ab64890Smrg    , int /* line */
691ab64890Smrg#endif
701ab64890Smrg    ) = NULL;
711ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL;
721ab64890Smrg
731ab64890Smrg#define XThread_Self()	((*_Xthread_self_fn)())
741ab64890Smrg
75295fb823Smrg#endif /* XTHREADS */
761ab64890Smrg
771ab64890Smrg/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
781ab64890Smrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN
791ab64890Smrg */
801ab64890Smrg#ifdef WIN32
811ab64890Smrg#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
821ab64890Smrg#else
831ab64890Smrg#ifdef __CYGWIN__ /* Cygwin uses ENOBUFS to signal socket is full */
841ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
851ab64890Smrg#else
861ab64890Smrg#if defined(EAGAIN) && defined(EWOULDBLOCK)
871ab64890Smrg#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
881ab64890Smrg#else
891ab64890Smrg#ifdef EAGAIN
901ab64890Smrg#define ETEST() (errno == EAGAIN)
911ab64890Smrg#else
921ab64890Smrg#define ETEST() (errno == EWOULDBLOCK)
931ab64890Smrg#endif /* EAGAIN */
941ab64890Smrg#endif /* EAGAIN && EWOULDBLOCK */
951ab64890Smrg#endif /* __CYGWIN__ */
961ab64890Smrg#endif /* WIN32 */
971ab64890Smrg
981ab64890Smrg#ifdef WIN32
991ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err)
1001ab64890Smrg#define ESET(val) WSASetLastError(val)
1011ab64890Smrg#else
1021ab64890Smrg#ifdef __UNIXOS2__
1031ab64890Smrg#define ECHECK(err) (errno == err)
1041ab64890Smrg#define ESET(val)
1051ab64890Smrg#else
1061ab64890Smrg#define ECHECK(err) (errno == err)
1071ab64890Smrg#define ESET(val) errno = val
1081ab64890Smrg#endif
1091ab64890Smrg#endif
1101ab64890Smrg
1111ab64890Smrg#if defined(LOCALCONN) || defined(LACHMAN)
1121ab64890Smrg#ifdef EMSGSIZE
1131ab64890Smrg#define ESZTEST() (ECHECK(EMSGSIZE) || ECHECK(ERANGE))
1141ab64890Smrg#else
1151ab64890Smrg#define ESZTEST() ECHECK(ERANGE)
1161ab64890Smrg#endif
1171ab64890Smrg#else
1181ab64890Smrg#ifdef EMSGSIZE
1191ab64890Smrg#define ESZTEST() ECHECK(EMSGSIZE)
1201ab64890Smrg#endif
1211ab64890Smrg#endif
1221ab64890Smrg
1231ab64890Smrg#ifdef __UNIXOS2__
1241ab64890Smrg#include <limits.h>
1251ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX
1261ab64890Smrg#endif
1271ab64890Smrg
1281ab64890Smrg/*
1291ab64890Smrg * The following routines are internal routines used by Xlib for protocol
1301ab64890Smrg * packet transmission and reception.
1311ab64890Smrg *
1321ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
1331ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
1341ab64890Smrg *
1351ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
1361ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
1371ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
1381ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
1391ab64890Smrg *
1401ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
14161b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
1421ab64890Smrg * return anything.  Whenever possible routines that create objects return
1431ab64890Smrg * the object they have created.
1441ab64890Smrg */
1451ab64890Smrg
1461ab64890Smrg#define POLLFD_CACHE_SIZE 5
1471ab64890Smrg
1481ab64890Smrg/* initialize the struct array passed to poll() below */
1491ab64890SmrgBool _XPollfdCacheInit(
1501ab64890Smrg    Display *dpy)
1511ab64890Smrg{
1521ab64890Smrg#ifdef USE_POLL
1531ab64890Smrg    struct pollfd *pfp;
1541ab64890Smrg
155556b6652Smrg    pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1561ab64890Smrg    if (!pfp)
1571ab64890Smrg	return False;
1581ab64890Smrg    pfp[0].fd = dpy->fd;
1591ab64890Smrg    pfp[0].events = POLLIN;
1601ab64890Smrg
1611ab64890Smrg    dpy->filedes = (XPointer)pfp;
1621ab64890Smrg#endif
1631ab64890Smrg    return True;
1641ab64890Smrg}
1651ab64890Smrg
1661ab64890Smrgvoid _XPollfdCacheAdd(
1671ab64890Smrg    Display *dpy,
1681ab64890Smrg    int fd)
1691ab64890Smrg{
1701ab64890Smrg#ifdef USE_POLL
1711ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1721ab64890Smrg
1731ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1741ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
1751ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
1761ab64890Smrg    }
1771ab64890Smrg#endif
1781ab64890Smrg}
1791ab64890Smrg
1801ab64890Smrg/* ARGSUSED */
1811ab64890Smrgvoid _XPollfdCacheDel(
1821ab64890Smrg    Display *dpy,
1831ab64890Smrg    int fd)			/* not used */
1841ab64890Smrg{
1851ab64890Smrg#ifdef USE_POLL
1861ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1871ab64890Smrg    struct _XConnectionInfo *conni;
1881ab64890Smrg
1891ab64890Smrg    /* just recalculate whole list */
1901ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1911ab64890Smrg	int loc = 1;
1921ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1931ab64890Smrg	    pfp[loc].fd = conni->fd;
1941ab64890Smrg	    pfp[loc].events = POLLIN;
1951ab64890Smrg	    loc++;
1961ab64890Smrg	}
1971ab64890Smrg    }
1981ab64890Smrg#endif
1991ab64890Smrg}
2001ab64890Smrg
20161b2299dSmrgstatic int sync_hazard(Display *dpy)
20261b2299dSmrg{
20361b2299dSmrg    unsigned long span = dpy->request - dpy->last_request_read;
20461b2299dSmrg    unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
20561b2299dSmrg    return span >= 65535 - hazard - 10;
20661b2299dSmrg}
20761b2299dSmrg
2081ab64890Smrgstatic
20988de56ccSmrgvoid sync_while_locked(Display *dpy)
21088de56ccSmrg{
21188de56ccSmrg#ifdef XTHREADS
21288de56ccSmrg    if (dpy->lock)
21388de56ccSmrg        (*dpy->lock->user_lock_display)(dpy);
21488de56ccSmrg#endif
21588de56ccSmrg    UnlockDisplay(dpy);
21688de56ccSmrg    SyncHandle();
21788de56ccSmrg    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
21888de56ccSmrg#ifdef XTHREADS
21988de56ccSmrg    if (dpy->lock)
22088de56ccSmrg        (*dpy->lock->user_unlock_display)(dpy);
22188de56ccSmrg#endif
22288de56ccSmrg}
22388de56ccSmrg
22488de56ccSmrgvoid _XSeqSyncFunction(
2251ab64890Smrg    register Display *dpy)
2261ab64890Smrg{
2271ab64890Smrg    xGetInputFocusReply rep;
2281ab64890Smrg    register xReq *req;
2291ab64890Smrg
23061b2299dSmrg    if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
2311ab64890Smrg	GetEmptyReq(GetInputFocus, req);
2321ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
23388de56ccSmrg	sync_while_locked(dpy);
23461b2299dSmrg    } else if (sync_hazard(dpy))
23561b2299dSmrg	_XSetPrivSyncFunction(dpy);
2361ab64890Smrg}
2371ab64890Smrg
23888de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
23961b2299dSmrgstatic int
24061b2299dSmrg_XPrivSyncFunction (Display *dpy)
24161b2299dSmrg{
242e0787e08Smrg#ifdef XTHREADS
24388de56ccSmrg    assert(!dpy->lock_fns);
24488de56ccSmrg#endif
24561b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
24661b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
24761b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
24861b2299dSmrg    dpy->savedsynchandler = NULL;
24961b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
25088de56ccSmrg    if(dpy->synchandler)
25188de56ccSmrg        dpy->synchandler(dpy);
25261b2299dSmrg    _XIDHandler(dpy);
25361b2299dSmrg    _XSeqSyncFunction(dpy);
25461b2299dSmrg    return 0;
25561b2299dSmrg}
25661b2299dSmrg
25761b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
2581ab64890Smrg{
25988de56ccSmrg#ifdef XTHREADS
26088de56ccSmrg    if (dpy->lock_fns)
26188de56ccSmrg        return;
26288de56ccSmrg#endif
26361b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
2641ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
26561b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
2661ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
2671ab64890Smrg    }
2681ab64890Smrg}
2691ab64890Smrg
27061b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
27161b2299dSmrg{
27261b2299dSmrg    if (sync_hazard(dpy))
27361b2299dSmrg	_XSetPrivSyncFunction (dpy);
27461b2299dSmrg}
27561b2299dSmrg
2761ab64890Smrg#ifdef LONG64
2771ab64890Smrgvoid _XRead32(
2781ab64890Smrg    Display *dpy,
2791ab64890Smrg    register long *data,
2801ab64890Smrg    long len)
2811ab64890Smrg{
2821ab64890Smrg    register int *buf;
2831ab64890Smrg    register long i;
2841ab64890Smrg
2851ab64890Smrg    if (len) {
2861ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
2871ab64890Smrg	i = len >> 2;
2881ab64890Smrg	buf = (int *)data + i;
2891ab64890Smrg	data += i;
2901ab64890Smrg	while (--i >= 0)
2911ab64890Smrg	    *--data = *--buf;
2921ab64890Smrg    }
2931ab64890Smrg}
2941ab64890Smrg#endif /* LONG64 */
2951ab64890Smrg
2961ab64890Smrg
2971ab64890Smrg/*
2981ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
2991ab64890Smrg * We have three values that will march along, with the following invariant:
3001ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
3011ab64890Smrg * We have to keep
3021ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
3031ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
3041ab64890Smrg * by forcing syncs when we get close.
3051ab64890Smrg */
3061ab64890Smrg
3071ab64890Smrgunsigned long
3081ab64890Smrg_XSetLastRequestRead(
3091ab64890Smrg    register Display *dpy,
3101ab64890Smrg    register xGenericReply *rep)
3111ab64890Smrg{
3121ab64890Smrg    register unsigned long	newseq, lastseq;
3131ab64890Smrg
3141ab64890Smrg    lastseq = dpy->last_request_read;
3151ab64890Smrg    /*
3161ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
3171ab64890Smrg     * to immediately follow another event, except when generated via
3181ab64890Smrg     * SendEvent (hmmm).
3191ab64890Smrg     */
3201ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
3211ab64890Smrg	return(lastseq);
3221ab64890Smrg
3231ab64890Smrg    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
3241ab64890Smrg
3251ab64890Smrg    if (newseq < lastseq) {
3261ab64890Smrg	newseq += 0x10000;
3271ab64890Smrg	if (newseq > dpy->request) {
32861b2299dSmrg	    (void) fprintf (stderr,
3291ab64890Smrg	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
33061b2299dSmrg			    newseq, dpy->request,
3311ab64890Smrg			    (unsigned int) rep->type);
3321ab64890Smrg	    newseq -= 0x10000;
3331ab64890Smrg	}
3341ab64890Smrg    }
3351ab64890Smrg
3361ab64890Smrg    dpy->last_request_read = newseq;
3371ab64890Smrg    return(newseq);
3381ab64890Smrg}
3391ab64890Smrg
3401ab64890Smrg/*
3411ab64890Smrg * Support for internal connections, such as an IM might use.
3421ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
3431ab64890Smrg */
3441ab64890Smrg
3451ab64890Smrg/* _XRegisterInternalConnection
3461ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
3471ab64890Smrg * include in its select/poll mask must call this function to register the
3481ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
3491ab64890Smrg * will also be called.
3501ab64890Smrg *
3511ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
3521ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
3531ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
3541ab64890Smrg * which will call the associated callback.
3551ab64890Smrg *
3561ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
3571ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
3581ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
3591ab64890Smrg * to be called when fds are registered or unregistered.
3601ab64890Smrg *
3611ab64890Smrg * Returns True if registration succeeded, False if not, typically
3621ab64890Smrg * because could not allocate memory.
3631ab64890Smrg * Assumes Display locked when called.
3641ab64890Smrg */
3651ab64890SmrgStatus
3661ab64890Smrg_XRegisterInternalConnection(
3671ab64890Smrg    Display* dpy,
3681ab64890Smrg    int fd,
3691ab64890Smrg    _XInternalConnectionProc callback,
3701ab64890Smrg    XPointer call_data
3711ab64890Smrg)
3721ab64890Smrg{
3731ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
3741ab64890Smrg    struct _XConnWatchInfo *watchers;
3751ab64890Smrg    XPointer *wd;
3761ab64890Smrg
377556b6652Smrg    new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
3781ab64890Smrg    if (!new_conni)
3791ab64890Smrg	return 0;
380556b6652Smrg    new_conni->watch_data = Xmalloc(dpy->watcher_count * sizeof(XPointer));
3811ab64890Smrg    if (!new_conni->watch_data) {
3821ab64890Smrg	Xfree(new_conni);
3831ab64890Smrg	return 0;
3841ab64890Smrg    }
3851ab64890Smrg    new_conni->fd = fd;
3861ab64890Smrg    new_conni->read_callback = callback;
3871ab64890Smrg    new_conni->call_data = call_data;
3881ab64890Smrg    new_conni->next = NULL;
3891ab64890Smrg    /* link new structure onto end of list */
3901ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
3911ab64890Smrg	;
3921ab64890Smrg    *iptr = new_conni;
3931ab64890Smrg    dpy->im_fd_length++;
3941ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
3951ab64890Smrg
3961ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
3971ab64890Smrg	 watchers;
3981ab64890Smrg	 watchers=watchers->next, wd++) {
3991ab64890Smrg	*wd = NULL;		/* for cleanliness */
4001ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
4011ab64890Smrg    }
4021ab64890Smrg
4031ab64890Smrg    return 1;
4041ab64890Smrg}
4051ab64890Smrg
4061ab64890Smrg/* _XUnregisterInternalConnection
4071ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
4081ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
4091ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
4101ab64890Smrg * will also be called.
4111ab64890Smrg *
4121ab64890Smrg * Assumes Display locked when called.
4131ab64890Smrg */
4141ab64890Smrgvoid
4151ab64890Smrg_XUnregisterInternalConnection(
4161ab64890Smrg    Display* dpy,
4171ab64890Smrg    int fd
4181ab64890Smrg)
4191ab64890Smrg{
4201ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
4211ab64890Smrg    struct _XConnWatchInfo *watch;
4221ab64890Smrg    XPointer *wd;
4231ab64890Smrg
4241ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
4251ab64890Smrg	 prev = &info_list->next) {
4261ab64890Smrg	if (info_list->fd == fd) {
4271ab64890Smrg	    *prev = info_list->next;
4281ab64890Smrg	    dpy->im_fd_length--;
4291ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
4301ab64890Smrg		 watch;
4311ab64890Smrg		 watch=watch->next, wd++) {
4321ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
4331ab64890Smrg	    }
4341ab64890Smrg	    if (info_list->watch_data)
4351ab64890Smrg		Xfree (info_list->watch_data);
4361ab64890Smrg	    Xfree (info_list);
4371ab64890Smrg	    break;
4381ab64890Smrg	}
4391ab64890Smrg    }
4401ab64890Smrg    _XPollfdCacheDel(dpy, fd);
4411ab64890Smrg}
4421ab64890Smrg
4431ab64890Smrg/* XInternalConnectionNumbers
4441ab64890Smrg * Returns an array of fds and an array of corresponding call data.
4451ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
4461ab64890Smrg * will be used instead of this function to discover
4471ab64890Smrg * additional fds to include in the select/poll mask.
4481ab64890Smrg *
4491ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
4501ab64890Smrg * with Xfree;
4511ab64890Smrg */
4521ab64890SmrgStatus
4531ab64890SmrgXInternalConnectionNumbers(
4541ab64890Smrg    Display *dpy,
4551ab64890Smrg    int **fd_return,
4561ab64890Smrg    int *count_return
4571ab64890Smrg)
4581ab64890Smrg{
4591ab64890Smrg    int count;
4601ab64890Smrg    struct _XConnectionInfo *info_list;
4611ab64890Smrg    int *fd_list;
4621ab64890Smrg
4631ab64890Smrg    LockDisplay(dpy);
4641ab64890Smrg    count = 0;
4651ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
4661ab64890Smrg	count++;
467556b6652Smrg    fd_list = Xmalloc (count * sizeof(int));
4681ab64890Smrg    if (!fd_list) {
4691ab64890Smrg	UnlockDisplay(dpy);
4701ab64890Smrg	return 0;
4711ab64890Smrg    }
4721ab64890Smrg    count = 0;
4731ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4741ab64890Smrg	fd_list[count] = info_list->fd;
4751ab64890Smrg	count++;
4761ab64890Smrg    }
4771ab64890Smrg    UnlockDisplay(dpy);
4781ab64890Smrg
4791ab64890Smrg    *fd_return = fd_list;
4801ab64890Smrg    *count_return = count;
4811ab64890Smrg    return 1;
4821ab64890Smrg}
4831ab64890Smrg
4841ab64890Smrgvoid _XProcessInternalConnection(
4851ab64890Smrg    Display *dpy,
4861ab64890Smrg    struct _XConnectionInfo *conn_info)
4871ab64890Smrg{
4881ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
4891ab64890Smrg    UnlockDisplay(dpy);
4901ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
4911ab64890Smrg    LockDisplay(dpy);
4921ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
4931ab64890Smrg}
4941ab64890Smrg
4951ab64890Smrg/* XProcessInternalConnection
4961ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
4971ab64890Smrg * for this fd.
4981ab64890Smrg * The Display is NOT locked during the call.
4991ab64890Smrg */
5001ab64890Smrgvoid
5011ab64890SmrgXProcessInternalConnection(
5021ab64890Smrg    Display* dpy,
5031ab64890Smrg    int fd
5041ab64890Smrg)
5051ab64890Smrg{
5061ab64890Smrg    struct _XConnectionInfo *info_list;
5071ab64890Smrg
5081ab64890Smrg    LockDisplay(dpy);
5091ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5101ab64890Smrg	if (info_list->fd == fd) {
5111ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
5121ab64890Smrg	    break;
5131ab64890Smrg	}
5141ab64890Smrg    }
5151ab64890Smrg    UnlockDisplay(dpy);
5161ab64890Smrg}
5171ab64890Smrg
5181ab64890Smrg/* XAddConnectionWatch
5191ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
5201ab64890Smrg * or _XUnregisterInternalConnection is called.
5211ab64890Smrg * Callbacks are called with the Display locked.
5221ab64890Smrg * If any connections are already registered, the callback is immediately
5231ab64890Smrg * called for each of them.
5241ab64890Smrg */
5251ab64890SmrgStatus
5261ab64890SmrgXAddConnectionWatch(
5271ab64890Smrg    Display* dpy,
5281ab64890Smrg    XConnectionWatchProc callback,
5291ab64890Smrg    XPointer client_data
5301ab64890Smrg)
5311ab64890Smrg{
5321ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
5331ab64890Smrg    struct _XConnectionInfo *info_list;
5341ab64890Smrg    XPointer *wd_array;
5351ab64890Smrg
5361ab64890Smrg    LockDisplay(dpy);
5371ab64890Smrg
5381ab64890Smrg    /* allocate new watch data */
5391ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
540556b6652Smrg	wd_array = Xrealloc(info_list->watch_data,
541556b6652Smrg			    (dpy->watcher_count + 1) * sizeof(XPointer));
5421ab64890Smrg	if (!wd_array) {
5431ab64890Smrg	    UnlockDisplay(dpy);
5441ab64890Smrg	    return 0;
5451ab64890Smrg	}
546c17aa6b1Smrg	info_list->watch_data = wd_array;
5471ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
5481ab64890Smrg    }
5491ab64890Smrg
550556b6652Smrg    new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
5511ab64890Smrg    if (!new_watcher) {
5521ab64890Smrg	UnlockDisplay(dpy);
5531ab64890Smrg	return 0;
5541ab64890Smrg    }
5551ab64890Smrg    new_watcher->fn = callback;
5561ab64890Smrg    new_watcher->client_data = client_data;
5571ab64890Smrg    new_watcher->next = NULL;
5581ab64890Smrg
5591ab64890Smrg    /* link new structure onto end of list */
5601ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
5611ab64890Smrg	;
5621ab64890Smrg    *wptr = new_watcher;
5631ab64890Smrg    dpy->watcher_count++;
5641ab64890Smrg
5651ab64890Smrg    /* call new watcher on all currently registered fds */
5661ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5671ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
5681ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
5691ab64890Smrg    }
5701ab64890Smrg
5711ab64890Smrg    UnlockDisplay(dpy);
5721ab64890Smrg    return 1;
5731ab64890Smrg}
5741ab64890Smrg
5751ab64890Smrg/* XRemoveConnectionWatch
5761ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
5771ab64890Smrg * Both callback and client_data must match what was passed to
5781ab64890Smrg * XAddConnectionWatch.
57961b2299dSmrg */
5801ab64890Smrgvoid
5811ab64890SmrgXRemoveConnectionWatch(
5821ab64890Smrg    Display* dpy,
5831ab64890Smrg    XConnectionWatchProc callback,
5841ab64890Smrg    XPointer client_data
5851ab64890Smrg)
5861ab64890Smrg{
5871ab64890Smrg    struct _XConnWatchInfo *watch;
5881ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
5891ab64890Smrg    struct _XConnectionInfo *conni;
5901ab64890Smrg    int counter = 0;
5911ab64890Smrg
5921ab64890Smrg    LockDisplay(dpy);
5931ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
5941ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
5951ab64890Smrg	    if (previous)
5961ab64890Smrg		previous->next = watch->next;
5971ab64890Smrg	    else
5981ab64890Smrg		dpy->conn_watchers = watch->next;
5991ab64890Smrg	    Xfree (watch);
6001ab64890Smrg	    dpy->watcher_count--;
6011ab64890Smrg	    /* remove our watch_data for each connection */
6021ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
6031ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
6041ab64890Smrg		/* overlapping */
6051ab64890Smrg		memmove(conni->watch_data+counter,
6061ab64890Smrg			conni->watch_data+counter+1,
6071ab64890Smrg			dpy->watcher_count - counter);
6081ab64890Smrg	    }
6091ab64890Smrg	    break;
6101ab64890Smrg	}
6111ab64890Smrg	previous = watch;
6121ab64890Smrg	counter++;
6131ab64890Smrg    }
6141ab64890Smrg    UnlockDisplay(dpy);
6151ab64890Smrg}
6161ab64890Smrg
6171ab64890Smrg/* end of internal connections support */
6181ab64890Smrg
619b4ee4795Smrg/* Cookie jar implementation
620b4ee4795Smrg   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
621b4ee4795Smrg   them in the normal EQ. _XStoreEvent returns the cookie event (minus
622b4ee4795Smrg   data pointer) and adds it to the cookiejar. _XDeq just removes
623b4ee4795Smrg   the entry like any other event but resets the data pointer for
624b4ee4795Smrg   cookie events (to avoid double-free, the memory is re-used by Xlib).
625b4ee4795Smrg
626b4ee4795Smrg   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
627b4ee4795Smrg   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
628b4ee4795Smrg   (called by XNextEvent).
629b4ee4795Smrg
630b4ee4795Smrg   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
631b4ee4795Smrg   normal EQ.
632b4ee4795Smrg */
633b4ee4795Smrg
634b4ee4795Smrg#include "utlist.h"
635b4ee4795Smrgstruct stored_event {
636b4ee4795Smrg    XGenericEventCookie ev;
637b4ee4795Smrg    struct stored_event *prev;
638b4ee4795Smrg    struct stored_event *next;
639b4ee4795Smrg};
640b4ee4795Smrg
641b4ee4795SmrgBool
642b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev)
643b4ee4795Smrg{
644b4ee4795Smrg    return (ev->xcookie.type == GenericEvent &&
645b4ee4795Smrg	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
646b4ee4795Smrg}
647b4ee4795Smrg
648b4ee4795Smrg/**
649b4ee4795Smrg * Free all events in the event list.
650b4ee4795Smrg */
651b4ee4795Smrgvoid
652b4ee4795Smrg_XFreeEventCookies(Display *dpy)
653b4ee4795Smrg{
654b4ee4795Smrg    struct stored_event **head, *e, *tmp;
655b4ee4795Smrg
656b4ee4795Smrg    if (!dpy->cookiejar)
657b4ee4795Smrg        return;
658b4ee4795Smrg
659b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
660b4ee4795Smrg
661b4ee4795Smrg    DL_FOREACH_SAFE(*head, e, tmp) {
662b4ee4795Smrg        if (dpy->cookiejar == e)
663b4ee4795Smrg            dpy->cookiejar = NULL;
664c17aa6b1Smrg        XFree(e->ev.data);
665c17aa6b1Smrg        XFree(e);
666b4ee4795Smrg    }
667b4ee4795Smrg}
668b4ee4795Smrg
669b4ee4795Smrg/**
670b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the
671b4ee4795Smrg * next call to XNextEvent().
672b4ee4795Smrg */
673b4ee4795Smrgvoid
674b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event)
675b4ee4795Smrg{
676b4ee4795Smrg    XGenericEventCookie* cookie = &event->xcookie;
677b4ee4795Smrg    struct stored_event **head, *add;
678b4ee4795Smrg
679b4ee4795Smrg    if (!_XIsEventCookie(dpy, event))
680b4ee4795Smrg        return;
681b4ee4795Smrg
682b4ee4795Smrg    head = (struct stored_event**)(&dpy->cookiejar);
683b4ee4795Smrg
684b4ee4795Smrg    add = Xmalloc(sizeof(struct stored_event));
685b4ee4795Smrg    if (!add) {
686b4ee4795Smrg        ESET(ENOMEM);
687b4ee4795Smrg        _XIOError(dpy);
688b4ee4795Smrg    }
689b4ee4795Smrg    add->ev = *cookie;
690b4ee4795Smrg    DL_APPEND(*head, add);
691b4ee4795Smrg    cookie->data = NULL; /* don't return data yet, must be claimed */
692b4ee4795Smrg}
693b4ee4795Smrg
694b4ee4795Smrg/**
695b4ee4795Smrg * Return the event with the given cookie and remove it from the list.
696b4ee4795Smrg */
697b4ee4795SmrgBool
698b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
699b4ee4795Smrg{
700b4ee4795Smrg    Bool ret = False;
701b4ee4795Smrg    struct stored_event **head, *event;
702b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
703b4ee4795Smrg
704b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)ev))
705b4ee4795Smrg        return ret;
706b4ee4795Smrg
707b4ee4795Smrg    DL_FOREACH(*head, event) {
708b4ee4795Smrg        if (event->ev.cookie == ev->cookie &&
709b4ee4795Smrg            event->ev.extension == ev->extension &&
710b4ee4795Smrg            event->ev.evtype == ev->evtype) {
711b4ee4795Smrg            *ev = event->ev;
712b4ee4795Smrg            DL_DELETE(*head, event);
713b4ee4795Smrg            Xfree(event);
714b4ee4795Smrg            ret = True;
715b4ee4795Smrg            break;
716b4ee4795Smrg        }
717b4ee4795Smrg    }
718b4ee4795Smrg
719b4ee4795Smrg    return ret;
720b4ee4795Smrg}
721b4ee4795Smrg
722b4ee4795SmrgBool
723b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
724b4ee4795Smrg{
725b4ee4795Smrg    Bool ret = False;
726b4ee4795Smrg    int extension;
727b4ee4795Smrg
728b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
729b4ee4795Smrg        return ret;
730b4ee4795Smrg
731b4ee4795Smrg    extension = in->extension & 0x7F;
732b4ee4795Smrg
733b4ee4795Smrg    if (!dpy->generic_event_copy_vec[extension])
734b4ee4795Smrg        return ret;
735b4ee4795Smrg
736b4ee4795Smrg    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
737b4ee4795Smrg    out->cookie = ret ? ++dpy->next_cookie  : 0;
738b4ee4795Smrg    return ret;
739b4ee4795Smrg}
740b4ee4795Smrg
7411ab64890Smrg
7421ab64890Smrg/*
7431ab64890Smrg * _XEnq - Place event packets on the display's queue.
7441ab64890Smrg * note that no squishing of move events in V11, since there
7451ab64890Smrg * is pointer motion hints....
7461ab64890Smrg */
7471ab64890Smrgvoid _XEnq(
7481ab64890Smrg	register Display *dpy,
7491ab64890Smrg	register xEvent *event)
7501ab64890Smrg{
7511ab64890Smrg	register _XQEvent *qelt;
752b4ee4795Smrg	int type, extension;
7531ab64890Smrg
7541ab64890Smrg	if ((qelt = dpy->qfree)) {
7551ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
7561ab64890Smrg		dpy->qfree = qelt->next;
7571ab64890Smrg	}
758556b6652Smrg	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
7591ab64890Smrg		/* Malloc call failed! */
7601ab64890Smrg		ESET(ENOMEM);
7611ab64890Smrg		_XIOError(dpy);
7621ab64890Smrg	}
7631ab64890Smrg	qelt->next = NULL;
764b4ee4795Smrg
765b4ee4795Smrg	type = event->u.u.type & 0177;
766b4ee4795Smrg	extension = ((xGenericEvent*)event)->extension;
767295fb823Smrg
768295fb823Smrg	qelt->event.type = type;
769556b6652Smrg	/* If an extension has registered a generic_event_vec handler, then
770b4ee4795Smrg	 * it can handle event cookies. Otherwise, proceed with the normal
771b4ee4795Smrg	 * event handlers.
772b4ee4795Smrg	 *
773b4ee4795Smrg	 * If the generic_event_vec is called, qelt->event is a event cookie
774b4ee4795Smrg	 * with the data pointer and the "free" pointer set. Data pointer is
775b4ee4795Smrg	 * some memory allocated by the extension.
776b4ee4795Smrg	 */
777b4ee4795Smrg        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
778b4ee4795Smrg	    XGenericEventCookie *cookie = &qelt->event.xcookie;
779b4ee4795Smrg	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
780b4ee4795Smrg	    cookie->cookie = ++dpy->next_cookie;
781b4ee4795Smrg
782b4ee4795Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
783b4ee4795Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
784b4ee4795Smrg	    else		dpy->head = qelt;
785b4ee4795Smrg
786b4ee4795Smrg	    dpy->tail = qelt;
787b4ee4795Smrg	    dpy->qlen++;
788b4ee4795Smrg	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
7891ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
7901ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
7911ab64890Smrg	    else 		dpy->head = qelt;
79261b2299dSmrg
7931ab64890Smrg	    dpy->tail = qelt;
7941ab64890Smrg	    dpy->qlen++;
7951ab64890Smrg	} else {
7961ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
7971ab64890Smrg	    qelt->next = dpy->qfree;
7981ab64890Smrg	    dpy->qfree = qelt;
7991ab64890Smrg	}
8001ab64890Smrg}
8011ab64890Smrg
8021ab64890Smrg/*
8031ab64890Smrg * _XDeq - Remove event packet from the display's queue.
8041ab64890Smrg */
8051ab64890Smrgvoid _XDeq(
8061ab64890Smrg    register Display *dpy,
8071ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
8081ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
8091ab64890Smrg{
8101ab64890Smrg    if (prev) {
8111ab64890Smrg	if ((prev->next = qelt->next) == NULL)
8121ab64890Smrg	    dpy->tail = prev;
8131ab64890Smrg    } else {
8141ab64890Smrg	/* no prev, so removing first elt */
8151ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
8161ab64890Smrg	    dpy->tail = NULL;
8171ab64890Smrg    }
8181ab64890Smrg    qelt->qserial_num = 0;
8191ab64890Smrg    qelt->next = dpy->qfree;
8201ab64890Smrg    dpy->qfree = qelt;
8211ab64890Smrg    dpy->qlen--;
822b4ee4795Smrg
823b4ee4795Smrg    if (_XIsEventCookie(dpy, &qelt->event)) {
824b4ee4795Smrg	XGenericEventCookie* cookie = &qelt->event.xcookie;
825b4ee4795Smrg	/* dpy->qfree is re-used, reset memory to avoid double free on
826b4ee4795Smrg	 * _XFreeDisplayStructure */
827b4ee4795Smrg	cookie->data = NULL;
828b4ee4795Smrg    }
8291ab64890Smrg}
8301ab64890Smrg
8311ab64890Smrg/*
8321ab64890Smrg * EventToWire in separate file in that often not needed.
8331ab64890Smrg */
8341ab64890Smrg
8351ab64890Smrg/*ARGSUSED*/
8361ab64890SmrgBool
8371ab64890Smrg_XUnknownWireEvent(
8381ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8391ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8401ab64890Smrg    register xEvent *event)	/* wire protocol event */
8411ab64890Smrg{
8421ab64890Smrg#ifdef notdef
84361b2299dSmrg	(void) fprintf(stderr,
8441ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
8451ab64890Smrg			event->u.u.type, dpy);
8461ab64890Smrg#endif
8471ab64890Smrg	return(False);
8481ab64890Smrg}
8491ab64890Smrg
850b4ee4795SmrgBool
851b4ee4795Smrg_XUnknownWireEventCookie(
852b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
853b4ee4795Smrg    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
854b4ee4795Smrg    xEvent *event)	/* wire protocol event */
855b4ee4795Smrg{
856b4ee4795Smrg#ifdef notdef
857b4ee4795Smrg	fprintf(stderr,
858b4ee4795Smrg	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
859b4ee4795Smrg			((xGenericEvent*)event)->extension, dpy);
860b4ee4795Smrg#endif
861b4ee4795Smrg	return(False);
862b4ee4795Smrg}
863b4ee4795Smrg
864b4ee4795SmrgBool
865b4ee4795Smrg_XUnknownCopyEventCookie(
866b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
867b4ee4795Smrg    XGenericEventCookie *in,	/* source */
868b4ee4795Smrg    XGenericEventCookie *out)	/* destination */
869b4ee4795Smrg{
870b4ee4795Smrg#ifdef notdef
871b4ee4795Smrg	fprintf(stderr,
872b4ee4795Smrg	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
873b4ee4795Smrg			in->extension, dpy);
874b4ee4795Smrg#endif
875b4ee4795Smrg	return(False);
876b4ee4795Smrg}
877b4ee4795Smrg
8781ab64890Smrg/*ARGSUSED*/
8791ab64890SmrgStatus
8801ab64890Smrg_XUnknownNativeEvent(
8811ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8821ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8831ab64890Smrg    register xEvent *event)	/* wire protocol event */
8841ab64890Smrg{
8851ab64890Smrg#ifdef notdef
88661b2299dSmrg	(void) fprintf(stderr,
8871ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
8881ab64890Smrg			re->type, dpy);
8891ab64890Smrg#endif
8901ab64890Smrg	return(0);
8911ab64890Smrg}
8921ab64890Smrg/*
8931ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
8941ab64890Smrg */
8951ab64890SmrgBool
8961ab64890Smrg_XWireToEvent(
8971ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8981ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8991ab64890Smrg    register xEvent *event)	/* wire protocol event */
9001ab64890Smrg{
9011ab64890Smrg
9021ab64890Smrg	re->type = event->u.u.type & 0x7f;
9031ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
9041ab64890Smrg					(xGenericReply *)event);
9051ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
9061ab64890Smrg	((XAnyEvent *)re)->display = dpy;
90761b2299dSmrg
9081ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
9091ab64890Smrg		client sends an event rather than the server. */
9101ab64890Smrg
9111ab64890Smrg	switch (event-> u.u.type & 0177) {
9121ab64890Smrg	      case KeyPress:
9131ab64890Smrg	      case KeyRelease:
9141ab64890Smrg	        {
9151ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
9161ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9171ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9181ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9191ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9201ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9211ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9221ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9231ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9241ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9251ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9261ab64890Smrg			ev->keycode 	= event->u.u.detail;
9271ab64890Smrg		}
9281ab64890Smrg	      	break;
9291ab64890Smrg	      case ButtonPress:
9301ab64890Smrg	      case ButtonRelease:
9311ab64890Smrg	        {
9321ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) re;
9331ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9341ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9351ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9361ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9371ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9381ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9391ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9401ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9411ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9421ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9431ab64890Smrg			ev->button 	= event->u.u.detail;
9441ab64890Smrg		}
9451ab64890Smrg	        break;
9461ab64890Smrg	      case MotionNotify:
9471ab64890Smrg	        {
9481ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
9491ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9501ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9511ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9521ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9531ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9541ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9551ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9561ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9571ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9581ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9591ab64890Smrg			ev->is_hint 	= event->u.u.detail;
9601ab64890Smrg		}
9611ab64890Smrg	        break;
9621ab64890Smrg	      case EnterNotify:
9631ab64890Smrg	      case LeaveNotify:
9641ab64890Smrg		{
9651ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
9661ab64890Smrg			ev->root	= event->u.enterLeave.root;
9671ab64890Smrg			ev->window	= event->u.enterLeave.event;
9681ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
9691ab64890Smrg			ev->time	= event->u.enterLeave.time;
9701ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
9711ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
9721ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
9731ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
9741ab64890Smrg			ev->state	= event->u.enterLeave.state;
9751ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
97661b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
9771ab64890Smrg				ELFlagSameScreen) && True;
9781ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
9791ab64890Smrg			  	ELFlagFocus) && True;
9801ab64890Smrg			ev->detail	= event->u.u.detail;
9811ab64890Smrg		}
9821ab64890Smrg		  break;
9831ab64890Smrg	      case FocusIn:
9841ab64890Smrg	      case FocusOut:
9851ab64890Smrg		{
9861ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
9871ab64890Smrg			ev->window 	= event->u.focus.window;
9881ab64890Smrg			ev->mode	= event->u.focus.mode;
9891ab64890Smrg			ev->detail	= event->u.u.detail;
9901ab64890Smrg		}
9911ab64890Smrg		  break;
9921ab64890Smrg	      case KeymapNotify:
9931ab64890Smrg		{
9941ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
9951ab64890Smrg			ev->window	= None;
9961ab64890Smrg			memcpy(&ev->key_vector[1],
9971ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
9981ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
9991ab64890Smrg		}
10001ab64890Smrg		break;
10011ab64890Smrg	      case Expose:
10021ab64890Smrg		{
10031ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
10041ab64890Smrg			ev->window	= event->u.expose.window;
10051ab64890Smrg			ev->x		= event->u.expose.x;
10061ab64890Smrg			ev->y		= event->u.expose.y;
10071ab64890Smrg			ev->width	= event->u.expose.width;
10081ab64890Smrg			ev->height	= event->u.expose.height;
10091ab64890Smrg			ev->count	= event->u.expose.count;
10101ab64890Smrg		}
10111ab64890Smrg		break;
10121ab64890Smrg	      case GraphicsExpose:
10131ab64890Smrg		{
10141ab64890Smrg		    register XGraphicsExposeEvent *ev =
10151ab64890Smrg			(XGraphicsExposeEvent *) re;
10161ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
10171ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
10181ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
10191ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
10201ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
10211ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
10221ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
10231ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
10241ab64890Smrg		}
10251ab64890Smrg		break;
10261ab64890Smrg	      case NoExpose:
10271ab64890Smrg		{
10281ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
10291ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
10301ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
10311ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
10321ab64890Smrg		}
10331ab64890Smrg		break;
10341ab64890Smrg	      case VisibilityNotify:
10351ab64890Smrg		{
10361ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
10371ab64890Smrg		    ev->window		= event->u.visibility.window;
10381ab64890Smrg		    ev->state		= event->u.visibility.state;
10391ab64890Smrg		}
10401ab64890Smrg		break;
10411ab64890Smrg	      case CreateNotify:
10421ab64890Smrg		{
10431ab64890Smrg		    register XCreateWindowEvent *ev =
10441ab64890Smrg			 (XCreateWindowEvent *) re;
10451ab64890Smrg		    ev->window		= event->u.createNotify.window;
10461ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
10471ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
10481ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
10491ab64890Smrg		    ev->width		= event->u.createNotify.width;
10501ab64890Smrg		    ev->height		= event->u.createNotify.height;
10511ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
10521ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
10531ab64890Smrg		}
10541ab64890Smrg		break;
10551ab64890Smrg	      case DestroyNotify:
10561ab64890Smrg		{
10571ab64890Smrg		    register XDestroyWindowEvent *ev =
10581ab64890Smrg				(XDestroyWindowEvent *) re;
10591ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
10601ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
10611ab64890Smrg		}
10621ab64890Smrg		break;
10631ab64890Smrg	      case UnmapNotify:
10641ab64890Smrg		{
10651ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
10661ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
10671ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
10681ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
10691ab64890Smrg		}
10701ab64890Smrg		break;
10711ab64890Smrg	      case MapNotify:
10721ab64890Smrg		{
10731ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
10741ab64890Smrg		    ev->window		= event->u.mapNotify.window;
10751ab64890Smrg		    ev->event		= event->u.mapNotify.event;
10761ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
10771ab64890Smrg		}
10781ab64890Smrg		break;
10791ab64890Smrg	      case MapRequest:
10801ab64890Smrg		{
10811ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
10821ab64890Smrg		    ev->window		= event->u.mapRequest.window;
10831ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
10841ab64890Smrg		}
10851ab64890Smrg		break;
10861ab64890Smrg	      case ReparentNotify:
10871ab64890Smrg		{
10881ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
10891ab64890Smrg		    ev->event		= event->u.reparent.event;
10901ab64890Smrg		    ev->window		= event->u.reparent.window;
10911ab64890Smrg		    ev->parent		= event->u.reparent.parent;
10921ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
10931ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
10941ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
10951ab64890Smrg		}
10961ab64890Smrg		break;
10971ab64890Smrg	      case ConfigureNotify:
10981ab64890Smrg		{
10991ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
11001ab64890Smrg		    ev->event	= event->u.configureNotify.event;
11011ab64890Smrg		    ev->window	= event->u.configureNotify.window;
11021ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
11031ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
11041ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
11051ab64890Smrg		    ev->width	= event->u.configureNotify.width;
11061ab64890Smrg		    ev->height	= event->u.configureNotify.height;
11071ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
11081ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
11091ab64890Smrg		}
11101ab64890Smrg		break;
11111ab64890Smrg	      case ConfigureRequest:
11121ab64890Smrg		{
11131ab64890Smrg		    register XConfigureRequestEvent *ev =
11141ab64890Smrg		        (XConfigureRequestEvent *) re;
11151ab64890Smrg		    ev->window		= event->u.configureRequest.window;
11161ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
11171ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
11181ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
11191ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
11201ab64890Smrg		    ev->width		= event->u.configureRequest.width;
11211ab64890Smrg		    ev->height		= event->u.configureRequest.height;
11221ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
11231ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
11241ab64890Smrg		    ev->detail  	= event->u.u.detail;
11251ab64890Smrg		}
11261ab64890Smrg		break;
11271ab64890Smrg	      case GravityNotify:
11281ab64890Smrg		{
11291ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
11301ab64890Smrg		    ev->window		= event->u.gravity.window;
11311ab64890Smrg		    ev->event		= event->u.gravity.event;
11321ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
11331ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
11341ab64890Smrg		}
11351ab64890Smrg		break;
11361ab64890Smrg	      case ResizeRequest:
11371ab64890Smrg		{
11381ab64890Smrg		    register XResizeRequestEvent *ev =
11391ab64890Smrg			(XResizeRequestEvent *) re;
11401ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
11411ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
11421ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
11431ab64890Smrg		}
11441ab64890Smrg		break;
11451ab64890Smrg	      case CirculateNotify:
11461ab64890Smrg		{
11471ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
11481ab64890Smrg		    ev->window		= event->u.circulate.window;
11491ab64890Smrg		    ev->event		= event->u.circulate.event;
11501ab64890Smrg		    ev->place		= event->u.circulate.place;
11511ab64890Smrg		}
11521ab64890Smrg		break;
11531ab64890Smrg	      case CirculateRequest:
11541ab64890Smrg		{
11551ab64890Smrg		    register XCirculateRequestEvent *ev =
11561ab64890Smrg		        (XCirculateRequestEvent *) re;
11571ab64890Smrg		    ev->window		= event->u.circulate.window;
11581ab64890Smrg		    ev->parent		= event->u.circulate.event;
11591ab64890Smrg		    ev->place		= event->u.circulate.place;
11601ab64890Smrg		}
11611ab64890Smrg		break;
11621ab64890Smrg	      case PropertyNotify:
11631ab64890Smrg		{
11641ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
11651ab64890Smrg		    ev->window		= event->u.property.window;
11661ab64890Smrg		    ev->atom		= event->u.property.atom;
11671ab64890Smrg		    ev->time		= event->u.property.time;
11681ab64890Smrg		    ev->state		= event->u.property.state;
11691ab64890Smrg		}
11701ab64890Smrg		break;
11711ab64890Smrg	      case SelectionClear:
11721ab64890Smrg		{
11731ab64890Smrg		    register XSelectionClearEvent *ev =
11741ab64890Smrg			 (XSelectionClearEvent *) re;
11751ab64890Smrg		    ev->window		= event->u.selectionClear.window;
11761ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
11771ab64890Smrg		    ev->time		= event->u.selectionClear.time;
11781ab64890Smrg		}
11791ab64890Smrg		break;
11801ab64890Smrg	      case SelectionRequest:
11811ab64890Smrg		{
11821ab64890Smrg		    register XSelectionRequestEvent *ev =
11831ab64890Smrg		        (XSelectionRequestEvent *) re;
11841ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
11851ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
11861ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
11871ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
11881ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
11891ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
11901ab64890Smrg		}
11911ab64890Smrg		break;
11921ab64890Smrg	      case SelectionNotify:
11931ab64890Smrg		{
11941ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
11951ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
11961ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
11971ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
11981ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
11991ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
12001ab64890Smrg		}
12011ab64890Smrg		break;
12021ab64890Smrg	      case ColormapNotify:
12031ab64890Smrg		{
12041ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
12051ab64890Smrg		    ev->window		= event->u.colormap.window;
12061ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
12071ab64890Smrg		    ev->new		= event->u.colormap.new;
12081ab64890Smrg		    ev->state		= event->u.colormap.state;
12091ab64890Smrg	        }
12101ab64890Smrg		break;
12111ab64890Smrg	      case ClientMessage:
12121ab64890Smrg		{
12131ab64890Smrg		   register int i;
121461b2299dSmrg		   register XClientMessageEvent *ev
12151ab64890Smrg		   			= (XClientMessageEvent *) re;
12161ab64890Smrg		   ev->window		= event->u.clientMessage.window;
12171ab64890Smrg		   ev->format		= event->u.u.detail;
12181ab64890Smrg		   switch (ev->format) {
121961b2299dSmrg			case 8:
12201ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
122161b2299dSmrg			   for (i = 0; i < 20; i++)
12221ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
12231ab64890Smrg			   break;
12241ab64890Smrg			case 16:
12251ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
12261ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
12271ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
12281ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
12291ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
12301ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
12311ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
12321ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
12331ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
12341ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
12351ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
12361ab64890Smrg			   break;
12371ab64890Smrg			case 32:
12381ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
12391ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
12401ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
12411ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
12421ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
12431ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
12441ab64890Smrg			   break;
12451ab64890Smrg			default: /* XXX should never occur */
12461ab64890Smrg				break;
12471ab64890Smrg		    }
12481ab64890Smrg	        }
12491ab64890Smrg		break;
12501ab64890Smrg	      case MappingNotify:
12511ab64890Smrg		{
12521ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
12531ab64890Smrg		   ev->window		= 0;
12541ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
12551ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
12561ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
12571ab64890Smrg		}
12581ab64890Smrg		break;
12591ab64890Smrg	      default:
12601ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
12611ab64890Smrg	}
12621ab64890Smrg	return(True);
12631ab64890Smrg}
12641ab64890Smrg
12651ab64890Smrg
12661ab64890Smrg/*
126761b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
12681ab64890Smrg * when an X internal system error is encountered.
12691ab64890Smrg */
12701ab64890Smrgint _XDefaultIOError(
12711ab64890Smrg	Display *dpy)
12721ab64890Smrg{
12731ab64890Smrg	if (ECHECK(EPIPE)) {
12741ab64890Smrg	    (void) fprintf (stderr,
12751ab64890Smrg	"X connection to %s broken (explicit kill or server shutdown).\r\n",
12761ab64890Smrg			    DisplayString (dpy));
12771ab64890Smrg	} else {
127861b2299dSmrg	    (void) fprintf (stderr,
12791ab64890Smrg			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
12801ab64890Smrg#ifdef WIN32
12811ab64890Smrg			WSAGetLastError(), strerror(WSAGetLastError()),
12821ab64890Smrg#else
12831ab64890Smrg			errno, strerror (errno),
12841ab64890Smrg#endif
12851ab64890Smrg			DisplayString (dpy));
128661b2299dSmrg	    (void) fprintf (stderr,
12871ab64890Smrg	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
12881ab64890Smrg			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
12891ab64890Smrg			QLength(dpy));
12901ab64890Smrg
12911ab64890Smrg	}
12921ab64890Smrg	exit(1);
12931ab64890Smrg        return(0); /* dummy - function should never return */
12941ab64890Smrg}
12951ab64890Smrg
12961ab64890Smrg
12971ab64890Smrgstatic int _XPrintDefaultError(
12981ab64890Smrg    Display *dpy,
12991ab64890Smrg    XErrorEvent *event,
13001ab64890Smrg    FILE *fp)
13011ab64890Smrg{
13021ab64890Smrg    char buffer[BUFSIZ];
13031ab64890Smrg    char mesg[BUFSIZ];
13041ab64890Smrg    char number[32];
13051ab64890Smrg    const char *mtype = "XlibMessage";
13061ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
13071ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
13081ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
13091ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
13101ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
131161b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
13121ab64890Smrg	mesg, BUFSIZ);
13131ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
13141ab64890Smrg    if (event->request_code < 128) {
1315556b6652Smrg	snprintf(number, sizeof(number), "%d", event->request_code);
13161ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
13171ab64890Smrg    } else {
13181ab64890Smrg	for (ext = dpy->ext_procs;
13191ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
13201ab64890Smrg	     ext = ext->next)
13211ab64890Smrg	  ;
1322c17aa6b1Smrg	if (ext) {
1323c17aa6b1Smrg	    strncpy(buffer, ext->name, BUFSIZ);
1324c17aa6b1Smrg	    buffer[BUFSIZ - 1] = '\0';
1325c17aa6b1Smrg        } else
13261ab64890Smrg	    buffer[0] = '\0';
13271ab64890Smrg    }
13281ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
13291ab64890Smrg    if (event->request_code >= 128) {
13301ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
13311ab64890Smrg			      mesg, BUFSIZ);
13321ab64890Smrg	fputs("  ", fp);
13331ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
13341ab64890Smrg	if (ext) {
1335556b6652Smrg	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
13361ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
13371ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
13381ab64890Smrg	}
13391ab64890Smrg	fputs("\n", fp);
13401ab64890Smrg    }
13411ab64890Smrg    if (event->error_code >= 128) {
13421ab64890Smrg	/* kludge, try to find the extension that caused it */
13431ab64890Smrg	buffer[0] = '\0';
13441ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
134561b2299dSmrg	    if (ext->error_string)
13461ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
13471ab64890Smrg				     buffer, BUFSIZ);
13481ab64890Smrg	    if (buffer[0]) {
13491ab64890Smrg		bext = ext;
13501ab64890Smrg		break;
13511ab64890Smrg	    }
13521ab64890Smrg	    if (ext->codes.first_error &&
13531ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
13541ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
13551ab64890Smrg		bext = ext;
135661b2299dSmrg	}
13571ab64890Smrg	if (bext)
1358556b6652Smrg	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
1359556b6652Smrg                     event->error_code - bext->codes.first_error);
13601ab64890Smrg	else
13611ab64890Smrg	    strcpy(buffer, "Value");
13621ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
13631ab64890Smrg	if (mesg[0]) {
13641ab64890Smrg	    fputs("  ", fp);
13651ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
13661ab64890Smrg	    fputs("\n", fp);
13671ab64890Smrg	}
13681ab64890Smrg	/* let extensions try to print the values */
13691ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
13701ab64890Smrg	    if (ext->error_values)
13711ab64890Smrg		(*ext->error_values)(dpy, event, fp);
13721ab64890Smrg	}
13731ab64890Smrg    } else if ((event->error_code == BadWindow) ||
13741ab64890Smrg	       (event->error_code == BadPixmap) ||
13751ab64890Smrg	       (event->error_code == BadCursor) ||
13761ab64890Smrg	       (event->error_code == BadFont) ||
13771ab64890Smrg	       (event->error_code == BadDrawable) ||
13781ab64890Smrg	       (event->error_code == BadColor) ||
13791ab64890Smrg	       (event->error_code == BadGC) ||
13801ab64890Smrg	       (event->error_code == BadIDChoice) ||
13811ab64890Smrg	       (event->error_code == BadValue) ||
13821ab64890Smrg	       (event->error_code == BadAtom)) {
13831ab64890Smrg	if (event->error_code == BadValue)
13841ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
13851ab64890Smrg				  mesg, BUFSIZ);
13861ab64890Smrg	else if (event->error_code == BadAtom)
13871ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
13881ab64890Smrg				  mesg, BUFSIZ);
13891ab64890Smrg	else
13901ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
13911ab64890Smrg				  mesg, BUFSIZ);
13921ab64890Smrg	fputs("  ", fp);
13931ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
13941ab64890Smrg	fputs("\n", fp);
13951ab64890Smrg    }
139661b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
13971ab64890Smrg			  mesg, BUFSIZ);
13981ab64890Smrg    fputs("  ", fp);
13991ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
14001ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
14011ab64890Smrg			  mesg, BUFSIZ);
14021ab64890Smrg    fputs("\n  ", fp);
14031ab64890Smrg    (void) fprintf(fp, mesg, dpy->request);
14041ab64890Smrg    fputs("\n", fp);
14051ab64890Smrg    if (event->error_code == BadImplementation) return 0;
14061ab64890Smrg    return 1;
14071ab64890Smrg}
14081ab64890Smrg
14091ab64890Smrgint _XDefaultError(
14101ab64890Smrg	Display *dpy,
14111ab64890Smrg	XErrorEvent *event)
14121ab64890Smrg{
14131ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
14141ab64890Smrg    exit(1);
14151ab64890Smrg    /*NOTREACHED*/
14161ab64890Smrg}
14171ab64890Smrg
14181ab64890Smrg/*ARGSUSED*/
141961b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
14201ab64890Smrg{
14211ab64890Smrg    return True;
14221ab64890Smrg}
14231ab64890Smrg
14241ab64890Smrg/*
14251ab64890Smrg * _XError - upcall internal or user protocol error handler
14261ab64890Smrg */
14271ab64890Smrgint _XError (
14281ab64890Smrg    Display *dpy,
14291ab64890Smrg    register xError *rep)
14301ab64890Smrg{
143161b2299dSmrg    /*
14321ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
14331ab64890Smrg     * giving it to the user.
14341ab64890Smrg     */
14351ab64890Smrg    XEvent event; /* make it a large event */
14361ab64890Smrg    register _XAsyncHandler *async, *next;
14371ab64890Smrg
14381ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
14391ab64890Smrg
14401ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
14411ab64890Smrg	next = async->next;
14421ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
14431ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
14441ab64890Smrg	    return 0;
14451ab64890Smrg    }
14461ab64890Smrg
14471ab64890Smrg    event.xerror.display = dpy;
14481ab64890Smrg    event.xerror.type = X_Error;
14491ab64890Smrg    event.xerror.resourceid = rep->resourceID;
14501ab64890Smrg    event.xerror.error_code = rep->errorCode;
14511ab64890Smrg    event.xerror.request_code = rep->majorCode;
14521ab64890Smrg    event.xerror.minor_code = rep->minorCode;
14531ab64890Smrg    if (dpy->error_vec &&
14541ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
14551ab64890Smrg	return 0;
14561ab64890Smrg    if (_XErrorFunction != NULL) {
1457c17aa6b1Smrg	int rtn_val;
1458c17aa6b1Smrg#ifdef XTHREADS
1459c17aa6b1Smrg	if (dpy->lock)
1460c17aa6b1Smrg	    (*dpy->lock->user_lock_display)(dpy);
1461c17aa6b1Smrg	UnlockDisplay(dpy);
1462c17aa6b1Smrg#endif
1463c17aa6b1Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1464c17aa6b1Smrg#ifdef XTHREADS
1465c17aa6b1Smrg	LockDisplay(dpy);
1466c17aa6b1Smrg	if (dpy->lock)
1467c17aa6b1Smrg	    (*dpy->lock->user_unlock_display)(dpy);
1468c17aa6b1Smrg#endif
1469c17aa6b1Smrg	return rtn_val;
14701ab64890Smrg    } else {
14711ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
14721ab64890Smrg    }
14731ab64890Smrg}
147461b2299dSmrg
14751ab64890Smrg/*
14761ab64890Smrg * _XIOError - call user connection error handler and exit
14771ab64890Smrg */
14781ab64890Smrgint
14791ab64890Smrg_XIOError (
14801ab64890Smrg    Display *dpy)
14811ab64890Smrg{
14821ab64890Smrg    dpy->flags |= XlibDisplayIOError;
14831ab64890Smrg#ifdef WIN32
14841ab64890Smrg    errno = WSAGetLastError();
14851ab64890Smrg#endif
14861ab64890Smrg
14871ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
14881ab64890Smrg     * If this does not hold, then an alternate solution would involve
14891ab64890Smrg     * registering an atexit handler to take over the lock, which would only
14901ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
14911ab64890Smrg#ifdef XTHREADS
14921ab64890Smrg    if (dpy->lock)
14931ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
14941ab64890Smrg#endif
14951ab64890Smrg    UnlockDisplay(dpy);
14961ab64890Smrg
14971ab64890Smrg    if (_XIOErrorFunction != NULL)
14981ab64890Smrg	(*_XIOErrorFunction)(dpy);
14991ab64890Smrg    else
15001ab64890Smrg	_XDefaultIOError(dpy);
15011ab64890Smrg    exit (1);
1502e89c59a9Schristos#ifndef __NetBSD__
15031ab64890Smrg    return 0;
1504e89c59a9Schristos#endif
15051ab64890Smrg}
15061ab64890Smrg
15071ab64890Smrg
15081ab64890Smrg/*
15091ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
15101ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
15111ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
15121ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
15131ab64890Smrg * is guaranteed to not unlock the display.
15141ab64890Smrg */
15151ab64890Smrgchar *_XAllocScratch(
15161ab64890Smrg	register Display *dpy,
15171ab64890Smrg	unsigned long nbytes)
15181ab64890Smrg{
15191ab64890Smrg	if (nbytes > dpy->scratch_length) {
15201ab64890Smrg	    if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
1521556b6652Smrg	    if ((dpy->scratch_buffer = Xmalloc(nbytes)))
15221ab64890Smrg		dpy->scratch_length = nbytes;
15231ab64890Smrg	    else dpy->scratch_length = 0;
15241ab64890Smrg	}
15251ab64890Smrg	return (dpy->scratch_buffer);
15261ab64890Smrg}
15271ab64890Smrg
15281ab64890Smrg/*
15291ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
15301ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
15311ab64890Smrg */
15321ab64890Smrgchar *_XAllocTemp(
15331ab64890Smrg    register Display *dpy,
15341ab64890Smrg    unsigned long nbytes)
15351ab64890Smrg{
15361ab64890Smrg    char *buf;
15371ab64890Smrg
15381ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
15391ab64890Smrg    dpy->scratch_buffer = NULL;
15401ab64890Smrg    dpy->scratch_length = 0;
15411ab64890Smrg    return buf;
15421ab64890Smrg}
15431ab64890Smrg
15441ab64890Smrgvoid _XFreeTemp(
15451ab64890Smrg    register Display *dpy,
15461ab64890Smrg    char *buf,
15471ab64890Smrg    unsigned long nbytes)
15481ab64890Smrg{
15491ab64890Smrg    if (dpy->scratch_buffer)
15501ab64890Smrg	Xfree(dpy->scratch_buffer);
15511ab64890Smrg    dpy->scratch_buffer = buf;
15521ab64890Smrg    dpy->scratch_length = nbytes;
15531ab64890Smrg}
15541ab64890Smrg
15551ab64890Smrg/*
15561ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
15571ab64890Smrg */
15581ab64890SmrgVisual *_XVIDtoVisual(
15591ab64890Smrg	Display *dpy,
15601ab64890Smrg	VisualID id)
15611ab64890Smrg{
15621ab64890Smrg	register int i, j, k;
15631ab64890Smrg	register Screen *sp;
15641ab64890Smrg	register Depth *dp;
15651ab64890Smrg	register Visual *vp;
15661ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
15671ab64890Smrg		sp = &dpy->screens[i];
15681ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
15691ab64890Smrg			dp = &sp->depths[j];
15701ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
15711ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
15721ab64890Smrg				vp = &dp->visuals[k];
15731ab64890Smrg				if (vp->visualid == id) return (vp);
15741ab64890Smrg			}
15751ab64890Smrg		}
15761ab64890Smrg	}
15771ab64890Smrg	return (NULL);
15781ab64890Smrg}
15791ab64890Smrg
15801ab64890Smrgint
15811ab64890SmrgXFree (void *data)
15821ab64890Smrg{
15831ab64890Smrg	Xfree (data);
15841ab64890Smrg	return 1;
15851ab64890Smrg}
15861ab64890Smrg
15871ab64890Smrg#ifdef _XNEEDBCOPYFUNC
15881ab64890Smrgvoid _Xbcopy(b1, b2, length)
15891ab64890Smrg    register char *b1, *b2;
15901ab64890Smrg    register length;
15911ab64890Smrg{
15921ab64890Smrg    if (b1 < b2) {
15931ab64890Smrg	b2 += length;
15941ab64890Smrg	b1 += length;
15951ab64890Smrg	while (length--)
15961ab64890Smrg	    *--b2 = *--b1;
15971ab64890Smrg    } else {
15981ab64890Smrg	while (length--)
15991ab64890Smrg	    *b2++ = *b1++;
16001ab64890Smrg    }
16011ab64890Smrg}
16021ab64890Smrg#endif
16031ab64890Smrg
16041ab64890Smrg#ifdef DataRoutineIsProcedure
16051ab64890Smrgvoid Data(
16061ab64890Smrg	Display *dpy,
1607556b6652Smrg	_Xconst char *data,
16081ab64890Smrg	long len)
16091ab64890Smrg{
16101ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
16111ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
16121ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
16131ab64890Smrg	} else {
16141ab64890Smrg		_XSend(dpy, data, len);
16151ab64890Smrg	}
16161ab64890Smrg}
16171ab64890Smrg#endif /* DataRoutineIsProcedure */
16181ab64890Smrg
16191ab64890Smrg
16201ab64890Smrg#ifdef LONG64
16211ab64890Smrgint
16221ab64890Smrg_XData32(
16231ab64890Smrg    Display *dpy,
1624556b6652Smrg    register _Xconst long *data,
16251ab64890Smrg    unsigned len)
16261ab64890Smrg{
16271ab64890Smrg    register int *buf;
16281ab64890Smrg    register long i;
16291ab64890Smrg
16301ab64890Smrg    while (len) {
16311ab64890Smrg	buf = (int *)dpy->bufptr;
16321ab64890Smrg	i = dpy->bufmax - (char *)buf;
16331ab64890Smrg	if (!i) {
16341ab64890Smrg	    _XFlush(dpy);
16351ab64890Smrg	    continue;
16361ab64890Smrg	}
16371ab64890Smrg	if (len < i)
16381ab64890Smrg	    i = len;
16391ab64890Smrg	dpy->bufptr = (char *)buf + i;
16401ab64890Smrg	len -= i;
16411ab64890Smrg	i >>= 2;
16421ab64890Smrg	while (--i >= 0)
16431ab64890Smrg	    *buf++ = *data++;
16441ab64890Smrg    }
16451ab64890Smrg    return 0;
16461ab64890Smrg}
16471ab64890Smrg#endif /* LONG64 */
16481ab64890Smrg
16491ab64890Smrg
16501ab64890Smrg
16511ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
16521ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
16531ab64890Smrg *
16541ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
16551ab64890Smrg *       to have sufficient information for interfacing to the network,
16561ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
16571ab64890Smrg */
16581ab64890Smrg
16592e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
16601ab64890Smrg#define NEED_UTSNAME
16611ab64890Smrg#include <sys/utsname.h>
166288de56ccSmrg#else
166388de56ccSmrg#ifdef HAVE_UNISTD_H
166488de56ccSmrg#include <unistd.h>
166588de56ccSmrg#endif
16661ab64890Smrg#endif
16671ab64890Smrg
16681ab64890Smrg/*
16691ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
16701ab64890Smrg */
16711ab64890Smrgint _XGetHostname (
16721ab64890Smrg    char *buf,
16731ab64890Smrg    int maxlen)
16741ab64890Smrg{
16751ab64890Smrg    int len;
16761ab64890Smrg
16771ab64890Smrg#ifdef NEED_UTSNAME
16781ab64890Smrg    struct utsname name;
16791ab64890Smrg
16801ab64890Smrg    if (maxlen <= 0 || buf == NULL)
16811ab64890Smrg	return 0;
16821ab64890Smrg
16831ab64890Smrg    uname (&name);
16841ab64890Smrg    len = strlen (name.nodename);
16851ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
16861ab64890Smrg    strncpy (buf, name.nodename, len);
16871ab64890Smrg    buf[len] = '\0';
16881ab64890Smrg#else
16891ab64890Smrg    if (maxlen <= 0 || buf == NULL)
16901ab64890Smrg	return 0;
16911ab64890Smrg
16921ab64890Smrg    buf[0] = '\0';
16931ab64890Smrg    (void) gethostname (buf, maxlen);
16941ab64890Smrg    buf [maxlen - 1] = '\0';
16951ab64890Smrg    len = strlen(buf);
16961ab64890Smrg#endif /* NEED_UTSNAME */
16971ab64890Smrg    return len;
16981ab64890Smrg}
16991ab64890Smrg
17001ab64890Smrg
17011ab64890Smrg/*
17021ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
17031ab64890Smrg */
17041ab64890Smrg
170561b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
17061ab64890Smrg{
17071ab64890Smrg    register int i;
17081ab64890Smrg    Window root;
17091ab64890Smrg    int x, y;				/* dummy variables */
17101ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
17111ab64890Smrg
17121ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
17131ab64890Smrg		      &bw, &depth) == False) {
17142e9c7c8cSmrg	return NULL;
17151ab64890Smrg    }
17161ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
17171ab64890Smrg	if (root == RootWindow (dpy, i)) {
17181ab64890Smrg	    return ScreenOfDisplay (dpy, i);
17191ab64890Smrg	}
17201ab64890Smrg    }
17211ab64890Smrg    return NULL;
17221ab64890Smrg}
17231ab64890Smrg
17241ab64890Smrg
1725556b6652Smrg/*
1726556b6652Smrg * WARNING: This implementation's pre-conditions and post-conditions
1727556b6652Smrg * must remain compatible with the old macro-based implementations of
1728556b6652Smrg * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1729556b6652Smrg * Display structure affected by those macros are part of libX11's
1730556b6652Smrg * ABI.
1731556b6652Smrg */
1732556b6652Smrgvoid *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1733556b6652Smrg{
1734556b6652Smrg    xReq *req;
1735556b6652Smrg
1736556b6652Smrg    if (dpy->bufptr + len > dpy->bufmax)
1737556b6652Smrg	_XFlush(dpy);
1738c555af55Smrg    /* Request still too large, so do not allow it to overflow. */
1739c555af55Smrg    if (dpy->bufptr + len > dpy->bufmax) {
1740c555af55Smrg	fprintf(stderr,
1741c555af55Smrg		"Xlib: request %d length %zd would exceed buffer size.\n",
1742c555af55Smrg		type, len);
1743c555af55Smrg	/* Changes failure condition from overflow to NULL dereference. */
1744c555af55Smrg	return NULL;
1745c555af55Smrg    }
1746556b6652Smrg
1747556b6652Smrg    if (len % 4)
1748556b6652Smrg	fprintf(stderr,
1749556b6652Smrg		"Xlib: request %d length %zd not a multiple of 4.\n",
1750556b6652Smrg		type, len);
1751556b6652Smrg
1752556b6652Smrg    dpy->last_req = dpy->bufptr;
1753556b6652Smrg
1754556b6652Smrg    req = (xReq*)dpy->bufptr;
1755556b6652Smrg    req->reqType = type;
1756556b6652Smrg    req->length = len / 4;
1757556b6652Smrg    dpy->bufptr += len;
1758556b6652Smrg    dpy->request++;
1759556b6652Smrg    return req;
1760556b6652Smrg}
1761556b6652Smrg
17621ab64890Smrg#if defined(WIN32)
17631ab64890Smrg
17641ab64890Smrg/*
17651ab64890Smrg * These functions are intended to be used internally to Xlib only.
17661ab64890Smrg * These functions will always prefix the path with a DOS drive in the
17671ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
17681ab64890Smrg * for use by Xlib function that supply a root-based path to some
17691ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
17701ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
17711ab64890Smrg */
17721ab64890Smrg
17731ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
17741ab64890Smrg    char* path;
17751ab64890Smrg    char* pathbuf;
17761ab64890Smrg    int len_pathbuf;
17771ab64890Smrg    char** pathret;
17781ab64890Smrg{
17791ab64890Smrg    if (access (path, F_OK) == 0) {
17801ab64890Smrg	if (strlen (path) < len_pathbuf)
17811ab64890Smrg	    *pathret = pathbuf;
17821ab64890Smrg	else
17831ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
17841ab64890Smrg	if (*pathret) {
17851ab64890Smrg	    strcpy (*pathret, path);
17861ab64890Smrg	    return 1;
17871ab64890Smrg	}
17881ab64890Smrg    }
17891ab64890Smrg    return 0;
17901ab64890Smrg}
17911ab64890Smrg
17921ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
17931ab64890Smrg    char* path;
17941ab64890Smrg    char* pathbuf;
17951ab64890Smrg    int len_pathbuf;
17961ab64890Smrg    char** pathret;
17971ab64890Smrg{
17981ab64890Smrg    unsigned long drives;
17991ab64890Smrg    int i, len;
18001ab64890Smrg    char* drive;
18011ab64890Smrg    char buf[MAX_PATH];
18021ab64890Smrg    char* bufp;
18031ab64890Smrg
18041ab64890Smrg    /* just try the "raw" name first and see if it works */
18051ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
18061ab64890Smrg	return 1;
18071ab64890Smrg
18081ab64890Smrg    /* try the places set in the environment */
18091ab64890Smrg    drive = getenv ("_XBASEDRIVE");
18101ab64890Smrg#ifdef __UNIXOS2__
18111ab64890Smrg    if (!drive)
18121ab64890Smrg	drive = getenv ("X11ROOT");
18131ab64890Smrg#endif
18141ab64890Smrg    if (!drive)
18151ab64890Smrg	drive = "C:";
18161ab64890Smrg    len = strlen (drive) + strlen (path);
18171ab64890Smrg    if (len < MAX_PATH) bufp = buf;
18181ab64890Smrg    else bufp = Xmalloc (len + 1);
18191ab64890Smrg    strcpy (bufp, drive);
18201ab64890Smrg    strcat (bufp, path);
18211ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18221ab64890Smrg	if (bufp != buf) Xfree (bufp);
18231ab64890Smrg	return 1;
18241ab64890Smrg    }
18251ab64890Smrg
182661b2299dSmrg#ifndef __UNIXOS2__
18271ab64890Smrg    /* one last place to look */
18281ab64890Smrg    drive = getenv ("HOMEDRIVE");
18291ab64890Smrg    if (drive) {
18301ab64890Smrg	len = strlen (drive) + strlen (path);
18311ab64890Smrg	if (len < MAX_PATH) bufp = buf;
18321ab64890Smrg	else bufp = Xmalloc (len + 1);
18331ab64890Smrg	strcpy (bufp, drive);
18341ab64890Smrg	strcat (bufp, path);
18351ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18361ab64890Smrg	    if (bufp != buf) Xfree (bufp);
18371ab64890Smrg	    return 1;
18381ab64890Smrg	}
18391ab64890Smrg    }
18401ab64890Smrg
18411ab64890Smrg    /* tried everywhere else, go fishing */
18421ab64890Smrg#define C_DRIVE ('C' - 'A')
18431ab64890Smrg#define Z_DRIVE ('Z' - 'A')
18441ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
18451ab64890Smrg    drives = _getdrives ();
18461ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
18471ab64890Smrg	if ((1 << i) & drives) {
18481ab64890Smrg	    len = 2 + strlen (path);
18491ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
18501ab64890Smrg	    else bufp = Xmalloc (len + 1);
18511ab64890Smrg	    *bufp = 'A' + i;
18521ab64890Smrg	    *(bufp + 1) = ':';
18531ab64890Smrg	    *(bufp + 2) = '\0';
18541ab64890Smrg	    strcat (bufp, path);
18551ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18561ab64890Smrg		if (bufp != buf) Xfree (bufp);
18571ab64890Smrg		return 1;
18581ab64890Smrg	    }
18591ab64890Smrg	}
18601ab64890Smrg    }
18611ab64890Smrg#endif
18621ab64890Smrg    return 0;
18631ab64890Smrg}
18641ab64890Smrg
18651ab64890Smrgint _XOpenFile(path, flags)
18661ab64890Smrg    _Xconst char* path;
18671ab64890Smrg    int flags;
18681ab64890Smrg{
18691ab64890Smrg    char buf[MAX_PATH];
18701ab64890Smrg    char* bufp = NULL;
18711ab64890Smrg    int ret = -1;
18721ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
18731ab64890Smrg
18741ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
18751ab64890Smrg	ret = open (bufp, flags);
18761ab64890Smrg
18771ab64890Smrg    (void) SetErrorMode (olderror);
18781ab64890Smrg
18791ab64890Smrg    if (bufp != buf) Xfree (bufp);
18801ab64890Smrg
18811ab64890Smrg    return ret;
18821ab64890Smrg}
18831ab64890Smrg
18841ab64890Smrgint _XOpenFileMode(path, flags, mode)
18851ab64890Smrg    _Xconst char* path;
18861ab64890Smrg    int flags;
18871ab64890Smrg    mode_t mode;
18881ab64890Smrg{
18891ab64890Smrg    char buf[MAX_PATH];
18901ab64890Smrg    char* bufp = NULL;
18911ab64890Smrg    int ret = -1;
18921ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
18931ab64890Smrg
18941ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
18951ab64890Smrg	ret = open (bufp, flags, mode);
18961ab64890Smrg
18971ab64890Smrg    (void) SetErrorMode (olderror);
18981ab64890Smrg
18991ab64890Smrg    if (bufp != buf) Xfree (bufp);
19001ab64890Smrg
19011ab64890Smrg    return ret;
19021ab64890Smrg}
19031ab64890Smrg
19041ab64890Smrgvoid* _XFopenFile(path, mode)
19051ab64890Smrg    _Xconst char* path;
19061ab64890Smrg    _Xconst char* mode;
19071ab64890Smrg{
19081ab64890Smrg    char buf[MAX_PATH];
19091ab64890Smrg    char* bufp = NULL;
19101ab64890Smrg    void* ret = NULL;
19111ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19121ab64890Smrg
19131ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19141ab64890Smrg	ret = fopen (bufp, mode);
19151ab64890Smrg
19161ab64890Smrg    (void) SetErrorMode (olderror);
19171ab64890Smrg
19181ab64890Smrg    if (bufp != buf) Xfree (bufp);
19191ab64890Smrg
19201ab64890Smrg    return ret;
19211ab64890Smrg}
19221ab64890Smrg
19231ab64890Smrgint _XAccessFile(path)
19241ab64890Smrg    _Xconst char* path;
19251ab64890Smrg{
19261ab64890Smrg    char buf[MAX_PATH];
19271ab64890Smrg    char* bufp;
19281ab64890Smrg    int ret = -1;
19291ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19301ab64890Smrg
19311ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
19321ab64890Smrg
19331ab64890Smrg    (void) SetErrorMode (olderror);
19341ab64890Smrg
19351ab64890Smrg    if (bufp != buf) Xfree (bufp);
19361ab64890Smrg
19371ab64890Smrg    return ret;
19381ab64890Smrg}
19391ab64890Smrg
19401ab64890Smrg#endif
19411ab64890Smrg
19421ab64890Smrg#ifdef WIN32
19431ab64890Smrg#undef _Xdebug
19441ab64890Smrgint _Xdebug = 0;
19451ab64890Smrgint *_Xdebug_p = &_Xdebug;
19461ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
19471ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
19481ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
19491ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19501ab64890Smrg    , char * /* file */
19511ab64890Smrg    , int /* line */
19521ab64890Smrg#endif
19531ab64890Smrg        ) = &_XLockMutex_fn;
19541ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
19551ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19561ab64890Smrg    , char * /* file */
19571ab64890Smrg    , int /* line */
19581ab64890Smrg#endif
19591ab64890Smrg        ) = &_XUnlockMutex_fn;
19601ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
19611ab64890Smrg#endif
1962