XlibInt.c revision e90f245c
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"
42f2d49d05Smrg#include "reallocarray.h"
431ab64890Smrg#include <X11/Xpoll.h>
4461b2299dSmrg#include <assert.h>
451ab64890Smrg#include <stdio.h>
461ab64890Smrg#ifdef WIN32
471ab64890Smrg#include <direct.h>
481ab64890Smrg#endif
491ab64890Smrg
50f2d49d05Smrg/* Needed for FIONREAD on Solaris */
51f2d49d05Smrg#ifdef HAVE_SYS_FILIO_H
52f2d49d05Smrg#include <sys/filio.h>
53f2d49d05Smrg#endif
54f2d49d05Smrg
55f2d49d05Smrg/* Needed for FIONREAD on Cygwin */
56f2d49d05Smrg#ifdef HAVE_SYS_SOCKET_H
57f2d49d05Smrg#include <sys/socket.h>
58f2d49d05Smrg#endif
59f2d49d05Smrg
60f2d49d05Smrg/* Needed for ioctl() on Solaris */
61f2d49d05Smrg#ifdef HAVE_UNISTD_H
62f2d49d05Smrg#include <unistd.h>
63f2d49d05Smrg#endif
64f2d49d05Smrg
651ab64890Smrg#ifdef XTHREADS
661ab64890Smrg#include "locking.h"
671ab64890Smrg
68f2d49d05Smrg#ifdef HAVE_SYS_IOCTL_H
69f2d49d05Smrg#include <sys/ioctl.h>
70f2d49d05Smrg#endif
71f2d49d05Smrg
721ab64890Smrg/* these pointers get initialized by XInitThreads */
731ab64890SmrgLockInfoPtr _Xglobal_lock = NULL;
741ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
751ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
761ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
771ab64890Smrgvoid (*_XLockMutex_fn)(
781ab64890Smrg    LockInfoPtr /* lock */
791ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
801ab64890Smrg    , char * /* file */
811ab64890Smrg    , int /* line */
821ab64890Smrg#endif
831ab64890Smrg    ) = NULL;
841ab64890Smrgvoid (*_XUnlockMutex_fn)(
851ab64890Smrg    LockInfoPtr /* lock */
861ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
871ab64890Smrg    , char * /* file */
881ab64890Smrg    , int /* line */
891ab64890Smrg#endif
901ab64890Smrg    ) = NULL;
911ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL;
921ab64890Smrg
931ab64890Smrg#define XThread_Self()	((*_Xthread_self_fn)())
941ab64890Smrg
95295fb823Smrg#endif /* XTHREADS */
961ab64890Smrg
971ab64890Smrg#ifdef WIN32
981ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err)
991ab64890Smrg#define ESET(val) WSASetLastError(val)
1001ab64890Smrg#else
1011ab64890Smrg#ifdef __UNIXOS2__
1021ab64890Smrg#define ECHECK(err) (errno == err)
1031ab64890Smrg#define ESET(val)
1041ab64890Smrg#else
1051ab64890Smrg#define ECHECK(err) (errno == err)
1061ab64890Smrg#define ESET(val) errno = val
1071ab64890Smrg#endif
1081ab64890Smrg#endif
1091ab64890Smrg
1101ab64890Smrg#ifdef __UNIXOS2__
1111ab64890Smrg#include <limits.h>
1121ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX
1131ab64890Smrg#endif
1141ab64890Smrg
1151ab64890Smrg/*
1161ab64890Smrg * The following routines are internal routines used by Xlib for protocol
1171ab64890Smrg * packet transmission and reception.
1181ab64890Smrg *
1191ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
1201ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
1211ab64890Smrg *
1221ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
1231ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
1241ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
1251ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
1261ab64890Smrg *
1271ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
12861b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
1291ab64890Smrg * return anything.  Whenever possible routines that create objects return
1301ab64890Smrg * the object they have created.
1311ab64890Smrg */
1321ab64890Smrg
1331ab64890Smrg#define POLLFD_CACHE_SIZE 5
1341ab64890Smrg
1351ab64890Smrg/* initialize the struct array passed to poll() below */
1361ab64890SmrgBool _XPollfdCacheInit(
1371ab64890Smrg    Display *dpy)
1381ab64890Smrg{
1391ab64890Smrg#ifdef USE_POLL
1401ab64890Smrg    struct pollfd *pfp;
1411ab64890Smrg
142556b6652Smrg    pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1431ab64890Smrg    if (!pfp)
1441ab64890Smrg	return False;
1451ab64890Smrg    pfp[0].fd = dpy->fd;
1461ab64890Smrg    pfp[0].events = POLLIN;
1471ab64890Smrg
1481ab64890Smrg    dpy->filedes = (XPointer)pfp;
1491ab64890Smrg#endif
1501ab64890Smrg    return True;
1511ab64890Smrg}
1521ab64890Smrg
1531ab64890Smrgvoid _XPollfdCacheAdd(
1541ab64890Smrg    Display *dpy,
1551ab64890Smrg    int fd)
1561ab64890Smrg{
1571ab64890Smrg#ifdef USE_POLL
1581ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1591ab64890Smrg
1601ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1611ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
1621ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
1631ab64890Smrg    }
1641ab64890Smrg#endif
1651ab64890Smrg}
1661ab64890Smrg
1671ab64890Smrg/* ARGSUSED */
1681ab64890Smrgvoid _XPollfdCacheDel(
1691ab64890Smrg    Display *dpy,
1701ab64890Smrg    int fd)			/* not used */
1711ab64890Smrg{
1721ab64890Smrg#ifdef USE_POLL
1731ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1741ab64890Smrg    struct _XConnectionInfo *conni;
1751ab64890Smrg
1761ab64890Smrg    /* just recalculate whole list */
1771ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1781ab64890Smrg	int loc = 1;
1791ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1801ab64890Smrg	    pfp[loc].fd = conni->fd;
1811ab64890Smrg	    pfp[loc].events = POLLIN;
1821ab64890Smrg	    loc++;
1831ab64890Smrg	}
1841ab64890Smrg    }
1851ab64890Smrg#endif
1861ab64890Smrg}
1871ab64890Smrg
18861b2299dSmrgstatic int sync_hazard(Display *dpy)
18961b2299dSmrg{
190dac667f7Smrg    /*
191e90f245cSmaya     * "span" and "hazard" need to be signed such that the ">=" comparison
192dac667f7Smrg     * works correctly in the case that hazard is greater than 65525
193dac667f7Smrg     */
194dac667f7Smrg    int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
195dac667f7Smrg    int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
19661b2299dSmrg    return span >= 65535 - hazard - 10;
19761b2299dSmrg}
19861b2299dSmrg
1991ab64890Smrgstatic
20088de56ccSmrgvoid sync_while_locked(Display *dpy)
20188de56ccSmrg{
20288de56ccSmrg#ifdef XTHREADS
20388de56ccSmrg    if (dpy->lock)
20488de56ccSmrg        (*dpy->lock->user_lock_display)(dpy);
20588de56ccSmrg#endif
20688de56ccSmrg    UnlockDisplay(dpy);
20788de56ccSmrg    SyncHandle();
20888de56ccSmrg    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
20988de56ccSmrg#ifdef XTHREADS
21088de56ccSmrg    if (dpy->lock)
21188de56ccSmrg        (*dpy->lock->user_unlock_display)(dpy);
21288de56ccSmrg#endif
21388de56ccSmrg}
21488de56ccSmrg
21588de56ccSmrgvoid _XSeqSyncFunction(
2161ab64890Smrg    register Display *dpy)
2171ab64890Smrg{
2181ab64890Smrg    xGetInputFocusReply rep;
219bd8e7fb0Smrg    _X_UNUSED register xReq *req;
2201ab64890Smrg
2210ba404d1Smrg    if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq)) && !dpy->req_seq_syncing) {
2220ba404d1Smrg	dpy->req_seq_syncing = True;
2231ab64890Smrg	GetEmptyReq(GetInputFocus, req);
2241ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
22588de56ccSmrg	sync_while_locked(dpy);
2260ba404d1Smrg	dpy->req_seq_syncing = False;
22761b2299dSmrg    } else if (sync_hazard(dpy))
22861b2299dSmrg	_XSetPrivSyncFunction(dpy);
2291ab64890Smrg}
2301ab64890Smrg
23188de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
23261b2299dSmrgstatic int
23361b2299dSmrg_XPrivSyncFunction (Display *dpy)
23461b2299dSmrg{
235e0787e08Smrg#ifdef XTHREADS
23688de56ccSmrg    assert(!dpy->lock_fns);
23788de56ccSmrg#endif
23861b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
23961b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
24061b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
24161b2299dSmrg    dpy->savedsynchandler = NULL;
24261b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
24388de56ccSmrg    if(dpy->synchandler)
24488de56ccSmrg        dpy->synchandler(dpy);
24561b2299dSmrg    _XIDHandler(dpy);
24661b2299dSmrg    _XSeqSyncFunction(dpy);
24761b2299dSmrg    return 0;
24861b2299dSmrg}
24961b2299dSmrg
25061b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
2511ab64890Smrg{
25288de56ccSmrg#ifdef XTHREADS
25388de56ccSmrg    if (dpy->lock_fns)
25488de56ccSmrg        return;
25588de56ccSmrg#endif
25661b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
2571ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
25861b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
2591ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
2601ab64890Smrg    }
2611ab64890Smrg}
2621ab64890Smrg
26361b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
26461b2299dSmrg{
26561b2299dSmrg    if (sync_hazard(dpy))
26661b2299dSmrg	_XSetPrivSyncFunction (dpy);
26761b2299dSmrg}
26861b2299dSmrg
2691ab64890Smrg#ifdef LONG64
2701ab64890Smrgvoid _XRead32(
2711ab64890Smrg    Display *dpy,
2721ab64890Smrg    register long *data,
2731ab64890Smrg    long len)
2741ab64890Smrg{
2751ab64890Smrg    register int *buf;
2761ab64890Smrg    register long i;
2771ab64890Smrg
2781ab64890Smrg    if (len) {
2791ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
2801ab64890Smrg	i = len >> 2;
2811ab64890Smrg	buf = (int *)data + i;
2821ab64890Smrg	data += i;
2831ab64890Smrg	while (--i >= 0)
2841ab64890Smrg	    *--data = *--buf;
2851ab64890Smrg    }
2861ab64890Smrg}
2871ab64890Smrg#endif /* LONG64 */
2881ab64890Smrg
2891ab64890Smrg
2901ab64890Smrg/*
2911ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
2921ab64890Smrg * We have three values that will march along, with the following invariant:
2931ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
2941ab64890Smrg * We have to keep
2951ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
2961ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
2971ab64890Smrg * by forcing syncs when we get close.
2981ab64890Smrg */
2991ab64890Smrg
3001ab64890Smrgunsigned long
3011ab64890Smrg_XSetLastRequestRead(
3021ab64890Smrg    register Display *dpy,
3031ab64890Smrg    register xGenericReply *rep)
3041ab64890Smrg{
305dac667f7Smrg    register uint64_t	newseq, lastseq;
3061ab64890Smrg
307dac667f7Smrg    lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
3081ab64890Smrg    /*
3091ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
3101ab64890Smrg     * to immediately follow another event, except when generated via
3111ab64890Smrg     * SendEvent (hmmm).
3121ab64890Smrg     */
3131ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
3141ab64890Smrg	return(lastseq);
3151ab64890Smrg
316dac667f7Smrg    newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
3171ab64890Smrg
3181ab64890Smrg    if (newseq < lastseq) {
3191ab64890Smrg	newseq += 0x10000;
320dac667f7Smrg	if (newseq > X_DPY_GET_REQUEST(dpy)) {
32161b2299dSmrg	    (void) fprintf (stderr,
322dac667f7Smrg	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
323dac667f7Smrg			    (unsigned long long)newseq,
324dac667f7Smrg			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
3251ab64890Smrg			    (unsigned int) rep->type);
3261ab64890Smrg	    newseq -= 0x10000;
3271ab64890Smrg	}
3281ab64890Smrg    }
3291ab64890Smrg
330dac667f7Smrg    X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
3311ab64890Smrg    return(newseq);
3321ab64890Smrg}
3331ab64890Smrg
3341ab64890Smrg/*
3351ab64890Smrg * Support for internal connections, such as an IM might use.
3361ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
3371ab64890Smrg */
3381ab64890Smrg
3391ab64890Smrg/* _XRegisterInternalConnection
3401ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
3411ab64890Smrg * include in its select/poll mask must call this function to register the
3421ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
3431ab64890Smrg * will also be called.
3441ab64890Smrg *
3451ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
3461ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
3471ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
3481ab64890Smrg * which will call the associated callback.
3491ab64890Smrg *
3501ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
3511ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
3521ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
3531ab64890Smrg * to be called when fds are registered or unregistered.
3541ab64890Smrg *
3551ab64890Smrg * Returns True if registration succeeded, False if not, typically
3561ab64890Smrg * because could not allocate memory.
3571ab64890Smrg * Assumes Display locked when called.
3581ab64890Smrg */
3591ab64890SmrgStatus
3601ab64890Smrg_XRegisterInternalConnection(
3611ab64890Smrg    Display* dpy,
3621ab64890Smrg    int fd,
3631ab64890Smrg    _XInternalConnectionProc callback,
3641ab64890Smrg    XPointer call_data
3651ab64890Smrg)
3661ab64890Smrg{
3671ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
3681ab64890Smrg    struct _XConnWatchInfo *watchers;
3691ab64890Smrg    XPointer *wd;
3701ab64890Smrg
371556b6652Smrg    new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
3721ab64890Smrg    if (!new_conni)
3731ab64890Smrg	return 0;
374f2d49d05Smrg    new_conni->watch_data = Xmallocarray(dpy->watcher_count, sizeof(XPointer));
3751ab64890Smrg    if (!new_conni->watch_data) {
3761ab64890Smrg	Xfree(new_conni);
3771ab64890Smrg	return 0;
3781ab64890Smrg    }
3791ab64890Smrg    new_conni->fd = fd;
3801ab64890Smrg    new_conni->read_callback = callback;
3811ab64890Smrg    new_conni->call_data = call_data;
3821ab64890Smrg    new_conni->next = NULL;
3831ab64890Smrg    /* link new structure onto end of list */
3841ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
3851ab64890Smrg	;
3861ab64890Smrg    *iptr = new_conni;
3871ab64890Smrg    dpy->im_fd_length++;
3881ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
3891ab64890Smrg
3901ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
3911ab64890Smrg	 watchers;
3921ab64890Smrg	 watchers=watchers->next, wd++) {
3931ab64890Smrg	*wd = NULL;		/* for cleanliness */
3941ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
3951ab64890Smrg    }
3961ab64890Smrg
3971ab64890Smrg    return 1;
3981ab64890Smrg}
3991ab64890Smrg
4001ab64890Smrg/* _XUnregisterInternalConnection
4011ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
4021ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
4031ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
4041ab64890Smrg * will also be called.
4051ab64890Smrg *
4061ab64890Smrg * Assumes Display locked when called.
4071ab64890Smrg */
4081ab64890Smrgvoid
4091ab64890Smrg_XUnregisterInternalConnection(
4101ab64890Smrg    Display* dpy,
4111ab64890Smrg    int fd
4121ab64890Smrg)
4131ab64890Smrg{
4141ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
4151ab64890Smrg    struct _XConnWatchInfo *watch;
4161ab64890Smrg    XPointer *wd;
4171ab64890Smrg
4181ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
4191ab64890Smrg	 prev = &info_list->next) {
4201ab64890Smrg	if (info_list->fd == fd) {
4211ab64890Smrg	    *prev = info_list->next;
4221ab64890Smrg	    dpy->im_fd_length--;
4231ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
4241ab64890Smrg		 watch;
4251ab64890Smrg		 watch=watch->next, wd++) {
4261ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
4271ab64890Smrg	    }
428cf2acddeSmrg	    Xfree (info_list->watch_data);
4291ab64890Smrg	    Xfree (info_list);
4301ab64890Smrg	    break;
4311ab64890Smrg	}
4321ab64890Smrg    }
4331ab64890Smrg    _XPollfdCacheDel(dpy, fd);
4341ab64890Smrg}
4351ab64890Smrg
4361ab64890Smrg/* XInternalConnectionNumbers
4371ab64890Smrg * Returns an array of fds and an array of corresponding call data.
4381ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
4391ab64890Smrg * will be used instead of this function to discover
4401ab64890Smrg * additional fds to include in the select/poll mask.
4411ab64890Smrg *
4421ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
4431ab64890Smrg * with Xfree;
4441ab64890Smrg */
4451ab64890SmrgStatus
4461ab64890SmrgXInternalConnectionNumbers(
4471ab64890Smrg    Display *dpy,
4481ab64890Smrg    int **fd_return,
4491ab64890Smrg    int *count_return
4501ab64890Smrg)
4511ab64890Smrg{
4521ab64890Smrg    int count;
4531ab64890Smrg    struct _XConnectionInfo *info_list;
4541ab64890Smrg    int *fd_list;
4551ab64890Smrg
4561ab64890Smrg    LockDisplay(dpy);
4571ab64890Smrg    count = 0;
4581ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
4591ab64890Smrg	count++;
460f2d49d05Smrg    fd_list = Xmallocarray (count, sizeof(int));
4611ab64890Smrg    if (!fd_list) {
4621ab64890Smrg	UnlockDisplay(dpy);
4631ab64890Smrg	return 0;
4641ab64890Smrg    }
4651ab64890Smrg    count = 0;
4661ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4671ab64890Smrg	fd_list[count] = info_list->fd;
4681ab64890Smrg	count++;
4691ab64890Smrg    }
4701ab64890Smrg    UnlockDisplay(dpy);
4711ab64890Smrg
4721ab64890Smrg    *fd_return = fd_list;
4731ab64890Smrg    *count_return = count;
4741ab64890Smrg    return 1;
4751ab64890Smrg}
4761ab64890Smrg
4771ab64890Smrgvoid _XProcessInternalConnection(
4781ab64890Smrg    Display *dpy,
4791ab64890Smrg    struct _XConnectionInfo *conn_info)
4801ab64890Smrg{
4811ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
4821ab64890Smrg    UnlockDisplay(dpy);
4831ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
4841ab64890Smrg    LockDisplay(dpy);
4851ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
4861ab64890Smrg}
4871ab64890Smrg
4881ab64890Smrg/* XProcessInternalConnection
4891ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
4901ab64890Smrg * for this fd.
4911ab64890Smrg * The Display is NOT locked during the call.
4921ab64890Smrg */
4931ab64890Smrgvoid
4941ab64890SmrgXProcessInternalConnection(
4951ab64890Smrg    Display* dpy,
4961ab64890Smrg    int fd
4971ab64890Smrg)
4981ab64890Smrg{
4991ab64890Smrg    struct _XConnectionInfo *info_list;
5001ab64890Smrg
5011ab64890Smrg    LockDisplay(dpy);
5021ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5031ab64890Smrg	if (info_list->fd == fd) {
5041ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
5051ab64890Smrg	    break;
5061ab64890Smrg	}
5071ab64890Smrg    }
5081ab64890Smrg    UnlockDisplay(dpy);
5091ab64890Smrg}
5101ab64890Smrg
5111ab64890Smrg/* XAddConnectionWatch
5121ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
5131ab64890Smrg * or _XUnregisterInternalConnection is called.
5141ab64890Smrg * Callbacks are called with the Display locked.
5151ab64890Smrg * If any connections are already registered, the callback is immediately
5161ab64890Smrg * called for each of them.
5171ab64890Smrg */
5181ab64890SmrgStatus
5191ab64890SmrgXAddConnectionWatch(
5201ab64890Smrg    Display* dpy,
5211ab64890Smrg    XConnectionWatchProc callback,
5221ab64890Smrg    XPointer client_data
5231ab64890Smrg)
5241ab64890Smrg{
5251ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
5261ab64890Smrg    struct _XConnectionInfo *info_list;
5271ab64890Smrg    XPointer *wd_array;
5281ab64890Smrg
5291ab64890Smrg    LockDisplay(dpy);
5301ab64890Smrg
5311ab64890Smrg    /* allocate new watch data */
5321ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
533f2d49d05Smrg	wd_array = Xreallocarray(info_list->watch_data,
534f2d49d05Smrg                                 dpy->watcher_count + 1, sizeof(XPointer));
5351ab64890Smrg	if (!wd_array) {
5361ab64890Smrg	    UnlockDisplay(dpy);
5371ab64890Smrg	    return 0;
5381ab64890Smrg	}
539c17aa6b1Smrg	info_list->watch_data = wd_array;
5401ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
5411ab64890Smrg    }
5421ab64890Smrg
543556b6652Smrg    new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
5441ab64890Smrg    if (!new_watcher) {
5451ab64890Smrg	UnlockDisplay(dpy);
5461ab64890Smrg	return 0;
5471ab64890Smrg    }
5481ab64890Smrg    new_watcher->fn = callback;
5491ab64890Smrg    new_watcher->client_data = client_data;
5501ab64890Smrg    new_watcher->next = NULL;
5511ab64890Smrg
5521ab64890Smrg    /* link new structure onto end of list */
5531ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
5541ab64890Smrg	;
5551ab64890Smrg    *wptr = new_watcher;
5561ab64890Smrg    dpy->watcher_count++;
5571ab64890Smrg
5581ab64890Smrg    /* call new watcher on all currently registered fds */
5591ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5601ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
5611ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
5621ab64890Smrg    }
5631ab64890Smrg
5641ab64890Smrg    UnlockDisplay(dpy);
5651ab64890Smrg    return 1;
5661ab64890Smrg}
5671ab64890Smrg
5681ab64890Smrg/* XRemoveConnectionWatch
5691ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
5701ab64890Smrg * Both callback and client_data must match what was passed to
5711ab64890Smrg * XAddConnectionWatch.
57261b2299dSmrg */
5731ab64890Smrgvoid
5741ab64890SmrgXRemoveConnectionWatch(
5751ab64890Smrg    Display* dpy,
5761ab64890Smrg    XConnectionWatchProc callback,
5771ab64890Smrg    XPointer client_data
5781ab64890Smrg)
5791ab64890Smrg{
5801ab64890Smrg    struct _XConnWatchInfo *watch;
5811ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
5821ab64890Smrg    struct _XConnectionInfo *conni;
5831ab64890Smrg    int counter = 0;
5841ab64890Smrg
5851ab64890Smrg    LockDisplay(dpy);
5861ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
5871ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
5881ab64890Smrg	    if (previous)
5891ab64890Smrg		previous->next = watch->next;
5901ab64890Smrg	    else
5911ab64890Smrg		dpy->conn_watchers = watch->next;
5921ab64890Smrg	    Xfree (watch);
5931ab64890Smrg	    dpy->watcher_count--;
5941ab64890Smrg	    /* remove our watch_data for each connection */
5951ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
5961ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
5971ab64890Smrg		/* overlapping */
5981ab64890Smrg		memmove(conni->watch_data+counter,
5991ab64890Smrg			conni->watch_data+counter+1,
6001ab64890Smrg			dpy->watcher_count - counter);
6011ab64890Smrg	    }
6021ab64890Smrg	    break;
6031ab64890Smrg	}
6041ab64890Smrg	previous = watch;
6051ab64890Smrg	counter++;
6061ab64890Smrg    }
6071ab64890Smrg    UnlockDisplay(dpy);
6081ab64890Smrg}
6091ab64890Smrg
6101ab64890Smrg/* end of internal connections support */
6111ab64890Smrg
612b4ee4795Smrg/* Cookie jar implementation
613b4ee4795Smrg   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
614b4ee4795Smrg   them in the normal EQ. _XStoreEvent returns the cookie event (minus
615b4ee4795Smrg   data pointer) and adds it to the cookiejar. _XDeq just removes
616b4ee4795Smrg   the entry like any other event but resets the data pointer for
617b4ee4795Smrg   cookie events (to avoid double-free, the memory is re-used by Xlib).
618b4ee4795Smrg
619b4ee4795Smrg   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
620b4ee4795Smrg   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
621b4ee4795Smrg   (called by XNextEvent).
622b4ee4795Smrg
623b4ee4795Smrg   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
624b4ee4795Smrg   normal EQ.
625b4ee4795Smrg */
626b4ee4795Smrg
627b4ee4795Smrg#include "utlist.h"
628b4ee4795Smrgstruct stored_event {
629b4ee4795Smrg    XGenericEventCookie ev;
630b4ee4795Smrg    struct stored_event *prev;
631b4ee4795Smrg    struct stored_event *next;
632b4ee4795Smrg};
633b4ee4795Smrg
634b4ee4795SmrgBool
635b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev)
636b4ee4795Smrg{
637b4ee4795Smrg    return (ev->xcookie.type == GenericEvent &&
638b4ee4795Smrg	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
639b4ee4795Smrg}
640b4ee4795Smrg
641b4ee4795Smrg/**
642b4ee4795Smrg * Free all events in the event list.
643b4ee4795Smrg */
644b4ee4795Smrgvoid
645b4ee4795Smrg_XFreeEventCookies(Display *dpy)
646b4ee4795Smrg{
647b4ee4795Smrg    struct stored_event **head, *e, *tmp;
648b4ee4795Smrg
649b4ee4795Smrg    if (!dpy->cookiejar)
650b4ee4795Smrg        return;
651b4ee4795Smrg
652b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
653b4ee4795Smrg
654b4ee4795Smrg    DL_FOREACH_SAFE(*head, e, tmp) {
655b4ee4795Smrg        if (dpy->cookiejar == e)
656b4ee4795Smrg            dpy->cookiejar = NULL;
657c17aa6b1Smrg        XFree(e->ev.data);
658c17aa6b1Smrg        XFree(e);
659b4ee4795Smrg    }
660b4ee4795Smrg}
661b4ee4795Smrg
662b4ee4795Smrg/**
663b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the
664b4ee4795Smrg * next call to XNextEvent().
665b4ee4795Smrg */
666b4ee4795Smrgvoid
667b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event)
668b4ee4795Smrg{
669b4ee4795Smrg    XGenericEventCookie* cookie = &event->xcookie;
670b4ee4795Smrg    struct stored_event **head, *add;
671b4ee4795Smrg
672b4ee4795Smrg    if (!_XIsEventCookie(dpy, event))
673b4ee4795Smrg        return;
674b4ee4795Smrg
675b4ee4795Smrg    head = (struct stored_event**)(&dpy->cookiejar);
676b4ee4795Smrg
677b4ee4795Smrg    add = Xmalloc(sizeof(struct stored_event));
678b4ee4795Smrg    if (!add) {
679b4ee4795Smrg        ESET(ENOMEM);
680b4ee4795Smrg        _XIOError(dpy);
681b4ee4795Smrg    }
682b4ee4795Smrg    add->ev = *cookie;
683b4ee4795Smrg    DL_APPEND(*head, add);
684b4ee4795Smrg    cookie->data = NULL; /* don't return data yet, must be claimed */
685b4ee4795Smrg}
686b4ee4795Smrg
687b4ee4795Smrg/**
688b4ee4795Smrg * Return the event with the given cookie and remove it from the list.
689b4ee4795Smrg */
690b4ee4795SmrgBool
691b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
692b4ee4795Smrg{
693b4ee4795Smrg    Bool ret = False;
694b4ee4795Smrg    struct stored_event **head, *event;
695b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
696b4ee4795Smrg
697b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)ev))
698b4ee4795Smrg        return ret;
699b4ee4795Smrg
700b4ee4795Smrg    DL_FOREACH(*head, event) {
701b4ee4795Smrg        if (event->ev.cookie == ev->cookie &&
702b4ee4795Smrg            event->ev.extension == ev->extension &&
703b4ee4795Smrg            event->ev.evtype == ev->evtype) {
704b4ee4795Smrg            *ev = event->ev;
705b4ee4795Smrg            DL_DELETE(*head, event);
706b4ee4795Smrg            Xfree(event);
707b4ee4795Smrg            ret = True;
708b4ee4795Smrg            break;
709b4ee4795Smrg        }
710b4ee4795Smrg    }
711b4ee4795Smrg
712b4ee4795Smrg    return ret;
713b4ee4795Smrg}
714b4ee4795Smrg
715b4ee4795SmrgBool
716b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
717b4ee4795Smrg{
718b4ee4795Smrg    Bool ret = False;
719b4ee4795Smrg    int extension;
720b4ee4795Smrg
721b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
722b4ee4795Smrg        return ret;
723b4ee4795Smrg
724b4ee4795Smrg    extension = in->extension & 0x7F;
725b4ee4795Smrg
726b4ee4795Smrg    if (!dpy->generic_event_copy_vec[extension])
727b4ee4795Smrg        return ret;
728b4ee4795Smrg
729b4ee4795Smrg    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
730b4ee4795Smrg    out->cookie = ret ? ++dpy->next_cookie  : 0;
731b4ee4795Smrg    return ret;
732b4ee4795Smrg}
733b4ee4795Smrg
7341ab64890Smrg
7351ab64890Smrg/*
7361ab64890Smrg * _XEnq - Place event packets on the display's queue.
7371ab64890Smrg * note that no squishing of move events in V11, since there
7381ab64890Smrg * is pointer motion hints....
7391ab64890Smrg */
7401ab64890Smrgvoid _XEnq(
7411ab64890Smrg	register Display *dpy,
7421ab64890Smrg	register xEvent *event)
7431ab64890Smrg{
7441ab64890Smrg	register _XQEvent *qelt;
745b4ee4795Smrg	int type, extension;
7461ab64890Smrg
7471ab64890Smrg	if ((qelt = dpy->qfree)) {
7481ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
7491ab64890Smrg		dpy->qfree = qelt->next;
7501ab64890Smrg	}
751556b6652Smrg	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
7521ab64890Smrg		/* Malloc call failed! */
7531ab64890Smrg		ESET(ENOMEM);
7541ab64890Smrg		_XIOError(dpy);
7551ab64890Smrg	}
7561ab64890Smrg	qelt->next = NULL;
757b4ee4795Smrg
758b4ee4795Smrg	type = event->u.u.type & 0177;
759b4ee4795Smrg	extension = ((xGenericEvent*)event)->extension;
760295fb823Smrg
761295fb823Smrg	qelt->event.type = type;
762556b6652Smrg	/* If an extension has registered a generic_event_vec handler, then
763b4ee4795Smrg	 * it can handle event cookies. Otherwise, proceed with the normal
764b4ee4795Smrg	 * event handlers.
765b4ee4795Smrg	 *
766b4ee4795Smrg	 * If the generic_event_vec is called, qelt->event is a event cookie
767b4ee4795Smrg	 * with the data pointer and the "free" pointer set. Data pointer is
768b4ee4795Smrg	 * some memory allocated by the extension.
769b4ee4795Smrg	 */
770b4ee4795Smrg        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
771b4ee4795Smrg	    XGenericEventCookie *cookie = &qelt->event.xcookie;
772b4ee4795Smrg	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
773b4ee4795Smrg	    cookie->cookie = ++dpy->next_cookie;
774b4ee4795Smrg
775b4ee4795Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
776b4ee4795Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
777b4ee4795Smrg	    else		dpy->head = qelt;
778b4ee4795Smrg
779b4ee4795Smrg	    dpy->tail = qelt;
780b4ee4795Smrg	    dpy->qlen++;
781b4ee4795Smrg	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
7821ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
7831ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
7841ab64890Smrg	    else 		dpy->head = qelt;
78561b2299dSmrg
7861ab64890Smrg	    dpy->tail = qelt;
7871ab64890Smrg	    dpy->qlen++;
7881ab64890Smrg	} else {
7891ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
7901ab64890Smrg	    qelt->next = dpy->qfree;
7911ab64890Smrg	    dpy->qfree = qelt;
7921ab64890Smrg	}
7931ab64890Smrg}
7941ab64890Smrg
7951ab64890Smrg/*
7961ab64890Smrg * _XDeq - Remove event packet from the display's queue.
7971ab64890Smrg */
7981ab64890Smrgvoid _XDeq(
7991ab64890Smrg    register Display *dpy,
8001ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
8011ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
8021ab64890Smrg{
8031ab64890Smrg    if (prev) {
8041ab64890Smrg	if ((prev->next = qelt->next) == NULL)
8051ab64890Smrg	    dpy->tail = prev;
8061ab64890Smrg    } else {
8071ab64890Smrg	/* no prev, so removing first elt */
8081ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
8091ab64890Smrg	    dpy->tail = NULL;
8101ab64890Smrg    }
8111ab64890Smrg    qelt->qserial_num = 0;
8121ab64890Smrg    qelt->next = dpy->qfree;
8131ab64890Smrg    dpy->qfree = qelt;
8141ab64890Smrg    dpy->qlen--;
815b4ee4795Smrg
816b4ee4795Smrg    if (_XIsEventCookie(dpy, &qelt->event)) {
817b4ee4795Smrg	XGenericEventCookie* cookie = &qelt->event.xcookie;
818b4ee4795Smrg	/* dpy->qfree is re-used, reset memory to avoid double free on
819b4ee4795Smrg	 * _XFreeDisplayStructure */
820b4ee4795Smrg	cookie->data = NULL;
821b4ee4795Smrg    }
8221ab64890Smrg}
8231ab64890Smrg
8241ab64890Smrg/*
8251ab64890Smrg * EventToWire in separate file in that often not needed.
8261ab64890Smrg */
8271ab64890Smrg
8281ab64890Smrg/*ARGSUSED*/
8291ab64890SmrgBool
8301ab64890Smrg_XUnknownWireEvent(
8311ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8321ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8331ab64890Smrg    register xEvent *event)	/* wire protocol event */
8341ab64890Smrg{
8351ab64890Smrg#ifdef notdef
83661b2299dSmrg	(void) fprintf(stderr,
8371ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
8381ab64890Smrg			event->u.u.type, dpy);
8391ab64890Smrg#endif
8401ab64890Smrg	return(False);
8411ab64890Smrg}
8421ab64890Smrg
843b4ee4795SmrgBool
844b4ee4795Smrg_XUnknownWireEventCookie(
845b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
846b4ee4795Smrg    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
847b4ee4795Smrg    xEvent *event)	/* wire protocol event */
848b4ee4795Smrg{
849b4ee4795Smrg#ifdef notdef
850b4ee4795Smrg	fprintf(stderr,
851b4ee4795Smrg	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
852b4ee4795Smrg			((xGenericEvent*)event)->extension, dpy);
853b4ee4795Smrg#endif
854b4ee4795Smrg	return(False);
855b4ee4795Smrg}
856b4ee4795Smrg
857b4ee4795SmrgBool
858b4ee4795Smrg_XUnknownCopyEventCookie(
859b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
860b4ee4795Smrg    XGenericEventCookie *in,	/* source */
861b4ee4795Smrg    XGenericEventCookie *out)	/* destination */
862b4ee4795Smrg{
863b4ee4795Smrg#ifdef notdef
864b4ee4795Smrg	fprintf(stderr,
865b4ee4795Smrg	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
866b4ee4795Smrg			in->extension, dpy);
867b4ee4795Smrg#endif
868b4ee4795Smrg	return(False);
869b4ee4795Smrg}
870b4ee4795Smrg
8711ab64890Smrg/*ARGSUSED*/
8721ab64890SmrgStatus
8731ab64890Smrg_XUnknownNativeEvent(
8741ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8751ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8761ab64890Smrg    register xEvent *event)	/* wire protocol event */
8771ab64890Smrg{
8781ab64890Smrg#ifdef notdef
87961b2299dSmrg	(void) fprintf(stderr,
8801ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
8811ab64890Smrg			re->type, dpy);
8821ab64890Smrg#endif
8831ab64890Smrg	return(0);
8841ab64890Smrg}
8851ab64890Smrg/*
8861ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
8871ab64890Smrg */
8881ab64890SmrgBool
8891ab64890Smrg_XWireToEvent(
8901ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8911ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8921ab64890Smrg    register xEvent *event)	/* wire protocol event */
8931ab64890Smrg{
8941ab64890Smrg
8951ab64890Smrg	re->type = event->u.u.type & 0x7f;
8961ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
8971ab64890Smrg					(xGenericReply *)event);
8981ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
8991ab64890Smrg	((XAnyEvent *)re)->display = dpy;
90061b2299dSmrg
9011ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
9021ab64890Smrg		client sends an event rather than the server. */
9031ab64890Smrg
9041ab64890Smrg	switch (event-> u.u.type & 0177) {
9051ab64890Smrg	      case KeyPress:
9061ab64890Smrg	      case KeyRelease:
9071ab64890Smrg	        {
9081ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
9091ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9101ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9111ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9121ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9131ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9141ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9151ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9161ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9171ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9181ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9191ab64890Smrg			ev->keycode 	= event->u.u.detail;
9201ab64890Smrg		}
9211ab64890Smrg	      	break;
9221ab64890Smrg	      case ButtonPress:
9231ab64890Smrg	      case ButtonRelease:
9241ab64890Smrg	        {
9251ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) re;
9261ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9271ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9281ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9291ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9301ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9311ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9321ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9331ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9341ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9351ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9361ab64890Smrg			ev->button 	= event->u.u.detail;
9371ab64890Smrg		}
9381ab64890Smrg	        break;
9391ab64890Smrg	      case MotionNotify:
9401ab64890Smrg	        {
9411ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
9421ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9431ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9441ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9451ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9461ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9471ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9481ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9491ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9501ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9511ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9521ab64890Smrg			ev->is_hint 	= event->u.u.detail;
9531ab64890Smrg		}
9541ab64890Smrg	        break;
9551ab64890Smrg	      case EnterNotify:
9561ab64890Smrg	      case LeaveNotify:
9571ab64890Smrg		{
9581ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
9591ab64890Smrg			ev->root	= event->u.enterLeave.root;
9601ab64890Smrg			ev->window	= event->u.enterLeave.event;
9611ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
9621ab64890Smrg			ev->time	= event->u.enterLeave.time;
9631ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
9641ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
9651ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
9661ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
9671ab64890Smrg			ev->state	= event->u.enterLeave.state;
9681ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
96961b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
9701ab64890Smrg				ELFlagSameScreen) && True;
9711ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
9721ab64890Smrg			  	ELFlagFocus) && True;
9731ab64890Smrg			ev->detail	= event->u.u.detail;
9741ab64890Smrg		}
9751ab64890Smrg		  break;
9761ab64890Smrg	      case FocusIn:
9771ab64890Smrg	      case FocusOut:
9781ab64890Smrg		{
9791ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
9801ab64890Smrg			ev->window 	= event->u.focus.window;
9811ab64890Smrg			ev->mode	= event->u.focus.mode;
9821ab64890Smrg			ev->detail	= event->u.u.detail;
9831ab64890Smrg		}
9841ab64890Smrg		  break;
9851ab64890Smrg	      case KeymapNotify:
9861ab64890Smrg		{
9871ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
9881ab64890Smrg			ev->window	= None;
9891ab64890Smrg			memcpy(&ev->key_vector[1],
9901ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
9911ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
9921ab64890Smrg		}
9931ab64890Smrg		break;
9941ab64890Smrg	      case Expose:
9951ab64890Smrg		{
9961ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
9971ab64890Smrg			ev->window	= event->u.expose.window;
9981ab64890Smrg			ev->x		= event->u.expose.x;
9991ab64890Smrg			ev->y		= event->u.expose.y;
10001ab64890Smrg			ev->width	= event->u.expose.width;
10011ab64890Smrg			ev->height	= event->u.expose.height;
10021ab64890Smrg			ev->count	= event->u.expose.count;
10031ab64890Smrg		}
10041ab64890Smrg		break;
10051ab64890Smrg	      case GraphicsExpose:
10061ab64890Smrg		{
10071ab64890Smrg		    register XGraphicsExposeEvent *ev =
10081ab64890Smrg			(XGraphicsExposeEvent *) re;
10091ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
10101ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
10111ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
10121ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
10131ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
10141ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
10151ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
10161ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
10171ab64890Smrg		}
10181ab64890Smrg		break;
10191ab64890Smrg	      case NoExpose:
10201ab64890Smrg		{
10211ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
10221ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
10231ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
10241ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
10251ab64890Smrg		}
10261ab64890Smrg		break;
10271ab64890Smrg	      case VisibilityNotify:
10281ab64890Smrg		{
10291ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
10301ab64890Smrg		    ev->window		= event->u.visibility.window;
10311ab64890Smrg		    ev->state		= event->u.visibility.state;
10321ab64890Smrg		}
10331ab64890Smrg		break;
10341ab64890Smrg	      case CreateNotify:
10351ab64890Smrg		{
10361ab64890Smrg		    register XCreateWindowEvent *ev =
10371ab64890Smrg			 (XCreateWindowEvent *) re;
10381ab64890Smrg		    ev->window		= event->u.createNotify.window;
10391ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
10401ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
10411ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
10421ab64890Smrg		    ev->width		= event->u.createNotify.width;
10431ab64890Smrg		    ev->height		= event->u.createNotify.height;
10441ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
10451ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
10461ab64890Smrg		}
10471ab64890Smrg		break;
10481ab64890Smrg	      case DestroyNotify:
10491ab64890Smrg		{
10501ab64890Smrg		    register XDestroyWindowEvent *ev =
10511ab64890Smrg				(XDestroyWindowEvent *) re;
10521ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
10531ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
10541ab64890Smrg		}
10551ab64890Smrg		break;
10561ab64890Smrg	      case UnmapNotify:
10571ab64890Smrg		{
10581ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
10591ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
10601ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
10611ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
10621ab64890Smrg		}
10631ab64890Smrg		break;
10641ab64890Smrg	      case MapNotify:
10651ab64890Smrg		{
10661ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
10671ab64890Smrg		    ev->window		= event->u.mapNotify.window;
10681ab64890Smrg		    ev->event		= event->u.mapNotify.event;
10691ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
10701ab64890Smrg		}
10711ab64890Smrg		break;
10721ab64890Smrg	      case MapRequest:
10731ab64890Smrg		{
10741ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
10751ab64890Smrg		    ev->window		= event->u.mapRequest.window;
10761ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
10771ab64890Smrg		}
10781ab64890Smrg		break;
10791ab64890Smrg	      case ReparentNotify:
10801ab64890Smrg		{
10811ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
10821ab64890Smrg		    ev->event		= event->u.reparent.event;
10831ab64890Smrg		    ev->window		= event->u.reparent.window;
10841ab64890Smrg		    ev->parent		= event->u.reparent.parent;
10851ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
10861ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
10871ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
10881ab64890Smrg		}
10891ab64890Smrg		break;
10901ab64890Smrg	      case ConfigureNotify:
10911ab64890Smrg		{
10921ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
10931ab64890Smrg		    ev->event	= event->u.configureNotify.event;
10941ab64890Smrg		    ev->window	= event->u.configureNotify.window;
10951ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
10961ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
10971ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
10981ab64890Smrg		    ev->width	= event->u.configureNotify.width;
10991ab64890Smrg		    ev->height	= event->u.configureNotify.height;
11001ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
11011ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
11021ab64890Smrg		}
11031ab64890Smrg		break;
11041ab64890Smrg	      case ConfigureRequest:
11051ab64890Smrg		{
11061ab64890Smrg		    register XConfigureRequestEvent *ev =
11071ab64890Smrg		        (XConfigureRequestEvent *) re;
11081ab64890Smrg		    ev->window		= event->u.configureRequest.window;
11091ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
11101ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
11111ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
11121ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
11131ab64890Smrg		    ev->width		= event->u.configureRequest.width;
11141ab64890Smrg		    ev->height		= event->u.configureRequest.height;
11151ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
11161ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
11171ab64890Smrg		    ev->detail  	= event->u.u.detail;
11181ab64890Smrg		}
11191ab64890Smrg		break;
11201ab64890Smrg	      case GravityNotify:
11211ab64890Smrg		{
11221ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
11231ab64890Smrg		    ev->window		= event->u.gravity.window;
11241ab64890Smrg		    ev->event		= event->u.gravity.event;
11251ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
11261ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
11271ab64890Smrg		}
11281ab64890Smrg		break;
11291ab64890Smrg	      case ResizeRequest:
11301ab64890Smrg		{
11311ab64890Smrg		    register XResizeRequestEvent *ev =
11321ab64890Smrg			(XResizeRequestEvent *) re;
11331ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
11341ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
11351ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
11361ab64890Smrg		}
11371ab64890Smrg		break;
11381ab64890Smrg	      case CirculateNotify:
11391ab64890Smrg		{
11401ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
11411ab64890Smrg		    ev->window		= event->u.circulate.window;
11421ab64890Smrg		    ev->event		= event->u.circulate.event;
11431ab64890Smrg		    ev->place		= event->u.circulate.place;
11441ab64890Smrg		}
11451ab64890Smrg		break;
11461ab64890Smrg	      case CirculateRequest:
11471ab64890Smrg		{
11481ab64890Smrg		    register XCirculateRequestEvent *ev =
11491ab64890Smrg		        (XCirculateRequestEvent *) re;
11501ab64890Smrg		    ev->window		= event->u.circulate.window;
11511ab64890Smrg		    ev->parent		= event->u.circulate.event;
11521ab64890Smrg		    ev->place		= event->u.circulate.place;
11531ab64890Smrg		}
11541ab64890Smrg		break;
11551ab64890Smrg	      case PropertyNotify:
11561ab64890Smrg		{
11571ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
11581ab64890Smrg		    ev->window		= event->u.property.window;
11591ab64890Smrg		    ev->atom		= event->u.property.atom;
11601ab64890Smrg		    ev->time		= event->u.property.time;
11611ab64890Smrg		    ev->state		= event->u.property.state;
11621ab64890Smrg		}
11631ab64890Smrg		break;
11641ab64890Smrg	      case SelectionClear:
11651ab64890Smrg		{
11661ab64890Smrg		    register XSelectionClearEvent *ev =
11671ab64890Smrg			 (XSelectionClearEvent *) re;
11681ab64890Smrg		    ev->window		= event->u.selectionClear.window;
11691ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
11701ab64890Smrg		    ev->time		= event->u.selectionClear.time;
11711ab64890Smrg		}
11721ab64890Smrg		break;
11731ab64890Smrg	      case SelectionRequest:
11741ab64890Smrg		{
11751ab64890Smrg		    register XSelectionRequestEvent *ev =
11761ab64890Smrg		        (XSelectionRequestEvent *) re;
11771ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
11781ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
11791ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
11801ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
11811ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
11821ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
11831ab64890Smrg		}
11841ab64890Smrg		break;
11851ab64890Smrg	      case SelectionNotify:
11861ab64890Smrg		{
11871ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
11881ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
11891ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
11901ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
11911ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
11921ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
11931ab64890Smrg		}
11941ab64890Smrg		break;
11951ab64890Smrg	      case ColormapNotify:
11961ab64890Smrg		{
11971ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
11981ab64890Smrg		    ev->window		= event->u.colormap.window;
11991ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
12001ab64890Smrg		    ev->new		= event->u.colormap.new;
12011ab64890Smrg		    ev->state		= event->u.colormap.state;
12021ab64890Smrg	        }
12031ab64890Smrg		break;
12041ab64890Smrg	      case ClientMessage:
12051ab64890Smrg		{
12061ab64890Smrg		   register int i;
120761b2299dSmrg		   register XClientMessageEvent *ev
12081ab64890Smrg		   			= (XClientMessageEvent *) re;
12091ab64890Smrg		   ev->window		= event->u.clientMessage.window;
12101ab64890Smrg		   ev->format		= event->u.u.detail;
12111ab64890Smrg		   switch (ev->format) {
121261b2299dSmrg			case 8:
12131ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
121461b2299dSmrg			   for (i = 0; i < 20; i++)
12151ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
12161ab64890Smrg			   break;
12171ab64890Smrg			case 16:
12181ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
12191ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
12201ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
12211ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
12221ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
12231ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
12241ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
12251ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
12261ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
12271ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
12281ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
12291ab64890Smrg			   break;
12301ab64890Smrg			case 32:
12311ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
12321ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
12331ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
12341ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
12351ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
12361ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
12371ab64890Smrg			   break;
12381ab64890Smrg			default: /* XXX should never occur */
12391ab64890Smrg				break;
12401ab64890Smrg		    }
12411ab64890Smrg	        }
12421ab64890Smrg		break;
12431ab64890Smrg	      case MappingNotify:
12441ab64890Smrg		{
12451ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
12461ab64890Smrg		   ev->window		= 0;
12471ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
12481ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
12491ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
12501ab64890Smrg		}
12511ab64890Smrg		break;
12521ab64890Smrg	      default:
12531ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
12541ab64890Smrg	}
12551ab64890Smrg	return(True);
12561ab64890Smrg}
12571ab64890Smrg
1258f2d49d05Smrgstatic int
1259f2d49d05SmrgSocketBytesReadable(Display *dpy)
1260f2d49d05Smrg{
1261f2d49d05Smrg    int bytes = 0, last_error;
1262f2d49d05Smrg#ifdef WIN32
1263f2d49d05Smrg    last_error = WSAGetLastError();
1264f2d49d05Smrg    ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
1265f2d49d05Smrg    WSASetLastError(last_error);
1266f2d49d05Smrg#else
1267f2d49d05Smrg    last_error = errno;
1268f2d49d05Smrg    ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
1269f2d49d05Smrg    errno = last_error;
1270f2d49d05Smrg#endif
1271f2d49d05Smrg    return bytes;
1272f2d49d05Smrg}
12731ab64890Smrg
12741ab64890Smrg/*
127561b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
12761ab64890Smrg * when an X internal system error is encountered.
12771ab64890Smrg */
1278bd8e7fb0Smrg_X_NORETURN int _XDefaultIOError(
12791ab64890Smrg	Display *dpy)
12801ab64890Smrg{
1281f2d49d05Smrg	int killed = ECHECK(EPIPE);
1282f2d49d05Smrg
1283f2d49d05Smrg	/*
1284f2d49d05Smrg	 * If the socket was closed on the far end, the final recvmsg in
1285f2d49d05Smrg	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
1286f2d49d05Smrg	 * this to get the more informative error message.
1287f2d49d05Smrg	 */
1288f2d49d05Smrg	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
1289f2d49d05Smrg	    killed = True;
1290f2d49d05Smrg
1291f2d49d05Smrg	if (killed) {
1292f2d49d05Smrg	    fprintf (stderr,
1293f2d49d05Smrg                     "X connection to %s broken (explicit kill or server shutdown).\r\n",
1294f2d49d05Smrg                     DisplayString (dpy));
12951ab64890Smrg	} else {
1296f2d49d05Smrg            fprintf (stderr,
1297f2d49d05Smrg                     "XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
12981ab64890Smrg#ifdef WIN32
1299f2d49d05Smrg                      WSAGetLastError(), strerror(WSAGetLastError()),
13001ab64890Smrg#else
1301f2d49d05Smrg                      errno, strerror (errno),
13021ab64890Smrg#endif
1303f2d49d05Smrg                      DisplayString (dpy));
1304f2d49d05Smrg	    fprintf (stderr,
1305f2d49d05Smrg		     "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
1306f2d49d05Smrg		     NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
1307f2d49d05Smrg		     QLength(dpy));
1308f2d49d05Smrg        }
13091ab64890Smrg
13101ab64890Smrg	exit(1);
1311dac667f7Smrg	/*NOTREACHED*/
13121ab64890Smrg}
13131ab64890Smrg
13141ab64890Smrg
13151ab64890Smrgstatic int _XPrintDefaultError(
13161ab64890Smrg    Display *dpy,
13171ab64890Smrg    XErrorEvent *event,
13181ab64890Smrg    FILE *fp)
13191ab64890Smrg{
13201ab64890Smrg    char buffer[BUFSIZ];
13211ab64890Smrg    char mesg[BUFSIZ];
13221ab64890Smrg    char number[32];
13231ab64890Smrg    const char *mtype = "XlibMessage";
13241ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
13251ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
13261ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
13271ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
13281ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
132961b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
13301ab64890Smrg	mesg, BUFSIZ);
13311ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
13321ab64890Smrg    if (event->request_code < 128) {
1333556b6652Smrg	snprintf(number, sizeof(number), "%d", event->request_code);
13341ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
13351ab64890Smrg    } else {
13361ab64890Smrg	for (ext = dpy->ext_procs;
13371ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
13381ab64890Smrg	     ext = ext->next)
13391ab64890Smrg	  ;
1340c17aa6b1Smrg	if (ext) {
1341c17aa6b1Smrg	    strncpy(buffer, ext->name, BUFSIZ);
1342c17aa6b1Smrg	    buffer[BUFSIZ - 1] = '\0';
1343c17aa6b1Smrg        } else
13441ab64890Smrg	    buffer[0] = '\0';
13451ab64890Smrg    }
13461ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
13471ab64890Smrg    if (event->request_code >= 128) {
13481ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
13491ab64890Smrg			      mesg, BUFSIZ);
13501ab64890Smrg	fputs("  ", fp);
13511ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
13521ab64890Smrg	if (ext) {
1353556b6652Smrg	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
13541ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
13551ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
13561ab64890Smrg	}
13571ab64890Smrg	fputs("\n", fp);
13581ab64890Smrg    }
13591ab64890Smrg    if (event->error_code >= 128) {
13601ab64890Smrg	/* kludge, try to find the extension that caused it */
13611ab64890Smrg	buffer[0] = '\0';
13621ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
136361b2299dSmrg	    if (ext->error_string)
13641ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
13651ab64890Smrg				     buffer, BUFSIZ);
13661ab64890Smrg	    if (buffer[0]) {
13671ab64890Smrg		bext = ext;
13681ab64890Smrg		break;
13691ab64890Smrg	    }
13701ab64890Smrg	    if (ext->codes.first_error &&
13711ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
13721ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
13731ab64890Smrg		bext = ext;
137461b2299dSmrg	}
13751ab64890Smrg	if (bext)
1376556b6652Smrg	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
1377556b6652Smrg                     event->error_code - bext->codes.first_error);
13781ab64890Smrg	else
13791ab64890Smrg	    strcpy(buffer, "Value");
13801ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
13811ab64890Smrg	if (mesg[0]) {
13821ab64890Smrg	    fputs("  ", fp);
13831ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
13841ab64890Smrg	    fputs("\n", fp);
13851ab64890Smrg	}
13861ab64890Smrg	/* let extensions try to print the values */
13871ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
13881ab64890Smrg	    if (ext->error_values)
13891ab64890Smrg		(*ext->error_values)(dpy, event, fp);
13901ab64890Smrg	}
13911ab64890Smrg    } else if ((event->error_code == BadWindow) ||
13921ab64890Smrg	       (event->error_code == BadPixmap) ||
13931ab64890Smrg	       (event->error_code == BadCursor) ||
13941ab64890Smrg	       (event->error_code == BadFont) ||
13951ab64890Smrg	       (event->error_code == BadDrawable) ||
13961ab64890Smrg	       (event->error_code == BadColor) ||
13971ab64890Smrg	       (event->error_code == BadGC) ||
13981ab64890Smrg	       (event->error_code == BadIDChoice) ||
13991ab64890Smrg	       (event->error_code == BadValue) ||
14001ab64890Smrg	       (event->error_code == BadAtom)) {
14011ab64890Smrg	if (event->error_code == BadValue)
14021ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
14031ab64890Smrg				  mesg, BUFSIZ);
14041ab64890Smrg	else if (event->error_code == BadAtom)
14051ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
14061ab64890Smrg				  mesg, BUFSIZ);
14071ab64890Smrg	else
14081ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
14091ab64890Smrg				  mesg, BUFSIZ);
14101ab64890Smrg	fputs("  ", fp);
14111ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
14121ab64890Smrg	fputs("\n", fp);
14131ab64890Smrg    }
141461b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
14151ab64890Smrg			  mesg, BUFSIZ);
14161ab64890Smrg    fputs("  ", fp);
14171ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
1418dac667f7Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
14191ab64890Smrg			  mesg, BUFSIZ);
14201ab64890Smrg    fputs("\n  ", fp);
1421dac667f7Smrg    (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
14221ab64890Smrg    fputs("\n", fp);
14231ab64890Smrg    if (event->error_code == BadImplementation) return 0;
14241ab64890Smrg    return 1;
14251ab64890Smrg}
14261ab64890Smrg
14271ab64890Smrgint _XDefaultError(
14281ab64890Smrg	Display *dpy,
14291ab64890Smrg	XErrorEvent *event)
14301ab64890Smrg{
14311ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
1432bd8e7fb0Smrg
1433bd8e7fb0Smrg    /*
1434bd8e7fb0Smrg     * Store in dpy flags that the client is exiting on an unhandled XError
1435bd8e7fb0Smrg     * (pretend it is an IOError, since the application is dying anyway it
1436bd8e7fb0Smrg     * does not make a difference).
1437bd8e7fb0Smrg     * This is useful for _XReply not to hang if the application makes Xlib
1438bd8e7fb0Smrg     * calls in _fini as part of process termination.
1439bd8e7fb0Smrg     */
1440bd8e7fb0Smrg    dpy->flags |= XlibDisplayIOError;
1441bd8e7fb0Smrg
14421ab64890Smrg    exit(1);
14431ab64890Smrg    /*NOTREACHED*/
14441ab64890Smrg}
14451ab64890Smrg
14461ab64890Smrg/*ARGSUSED*/
144761b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
14481ab64890Smrg{
14491ab64890Smrg    return True;
14501ab64890Smrg}
14511ab64890Smrg
14521ab64890Smrg/*
14531ab64890Smrg * _XError - upcall internal or user protocol error handler
14541ab64890Smrg */
14551ab64890Smrgint _XError (
14561ab64890Smrg    Display *dpy,
14571ab64890Smrg    register xError *rep)
14581ab64890Smrg{
145961b2299dSmrg    /*
14601ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
14611ab64890Smrg     * giving it to the user.
14621ab64890Smrg     */
14631ab64890Smrg    XEvent event; /* make it a large event */
14641ab64890Smrg    register _XAsyncHandler *async, *next;
14651ab64890Smrg
14661ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
14671ab64890Smrg
14681ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
14691ab64890Smrg	next = async->next;
14701ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
14711ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
14721ab64890Smrg	    return 0;
14731ab64890Smrg    }
14741ab64890Smrg
14751ab64890Smrg    event.xerror.display = dpy;
14761ab64890Smrg    event.xerror.type = X_Error;
14771ab64890Smrg    event.xerror.resourceid = rep->resourceID;
14781ab64890Smrg    event.xerror.error_code = rep->errorCode;
14791ab64890Smrg    event.xerror.request_code = rep->majorCode;
14801ab64890Smrg    event.xerror.minor_code = rep->minorCode;
14811ab64890Smrg    if (dpy->error_vec &&
14821ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
14831ab64890Smrg	return 0;
14841ab64890Smrg    if (_XErrorFunction != NULL) {
1485c17aa6b1Smrg	int rtn_val;
1486c17aa6b1Smrg#ifdef XTHREADS
1487c17aa6b1Smrg	if (dpy->lock)
1488c17aa6b1Smrg	    (*dpy->lock->user_lock_display)(dpy);
1489c17aa6b1Smrg	UnlockDisplay(dpy);
1490c17aa6b1Smrg#endif
1491c17aa6b1Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1492c17aa6b1Smrg#ifdef XTHREADS
1493c17aa6b1Smrg	LockDisplay(dpy);
1494c17aa6b1Smrg	if (dpy->lock)
1495c17aa6b1Smrg	    (*dpy->lock->user_unlock_display)(dpy);
1496c17aa6b1Smrg#endif
1497c17aa6b1Smrg	return rtn_val;
14981ab64890Smrg    } else {
14991ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
15001ab64890Smrg    }
15011ab64890Smrg}
150261b2299dSmrg
15031ab64890Smrg/*
15041ab64890Smrg * _XIOError - call user connection error handler and exit
15051ab64890Smrg */
15061ab64890Smrgint
15071ab64890Smrg_XIOError (
15081ab64890Smrg    Display *dpy)
15091ab64890Smrg{
15101ab64890Smrg    dpy->flags |= XlibDisplayIOError;
15111ab64890Smrg#ifdef WIN32
15121ab64890Smrg    errno = WSAGetLastError();
15131ab64890Smrg#endif
15141ab64890Smrg
15151ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
15161ab64890Smrg     * If this does not hold, then an alternate solution would involve
15171ab64890Smrg     * registering an atexit handler to take over the lock, which would only
15181ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
15191ab64890Smrg#ifdef XTHREADS
15201ab64890Smrg    if (dpy->lock)
15211ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
15221ab64890Smrg#endif
15231ab64890Smrg    UnlockDisplay(dpy);
15241ab64890Smrg
15251ab64890Smrg    if (_XIOErrorFunction != NULL)
15261ab64890Smrg	(*_XIOErrorFunction)(dpy);
15271ab64890Smrg    else
15281ab64890Smrg	_XDefaultIOError(dpy);
15291ab64890Smrg    exit (1);
1530dac667f7Smrg    /*NOTREACHED*/
15311ab64890Smrg}
15321ab64890Smrg
15331ab64890Smrg
15341ab64890Smrg/*
15351ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
15361ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
15371ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
15381ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
15391ab64890Smrg * is guaranteed to not unlock the display.
15401ab64890Smrg */
15411ab64890Smrgchar *_XAllocScratch(
15421ab64890Smrg	register Display *dpy,
15431ab64890Smrg	unsigned long nbytes)
15441ab64890Smrg{
15451ab64890Smrg	if (nbytes > dpy->scratch_length) {
1546cf2acddeSmrg	    Xfree (dpy->scratch_buffer);
1547cf2acddeSmrg	    dpy->scratch_buffer = Xmalloc(nbytes);
1548cf2acddeSmrg	    if (dpy->scratch_buffer)
15491ab64890Smrg		dpy->scratch_length = nbytes;
15501ab64890Smrg	    else dpy->scratch_length = 0;
15511ab64890Smrg	}
15521ab64890Smrg	return (dpy->scratch_buffer);
15531ab64890Smrg}
15541ab64890Smrg
15551ab64890Smrg/*
15561ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
15571ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
15581ab64890Smrg */
15591ab64890Smrgchar *_XAllocTemp(
15601ab64890Smrg    register Display *dpy,
15611ab64890Smrg    unsigned long nbytes)
15621ab64890Smrg{
15631ab64890Smrg    char *buf;
15641ab64890Smrg
15651ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
15661ab64890Smrg    dpy->scratch_buffer = NULL;
15671ab64890Smrg    dpy->scratch_length = 0;
15681ab64890Smrg    return buf;
15691ab64890Smrg}
15701ab64890Smrg
15711ab64890Smrgvoid _XFreeTemp(
15721ab64890Smrg    register Display *dpy,
15731ab64890Smrg    char *buf,
15741ab64890Smrg    unsigned long nbytes)
15751ab64890Smrg{
1576cf2acddeSmrg
1577cf2acddeSmrg    Xfree(dpy->scratch_buffer);
15781ab64890Smrg    dpy->scratch_buffer = buf;
15791ab64890Smrg    dpy->scratch_length = nbytes;
15801ab64890Smrg}
15811ab64890Smrg
15821ab64890Smrg/*
15831ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
15841ab64890Smrg */
15851ab64890SmrgVisual *_XVIDtoVisual(
15861ab64890Smrg	Display *dpy,
15871ab64890Smrg	VisualID id)
15881ab64890Smrg{
15891ab64890Smrg	register int i, j, k;
15901ab64890Smrg	register Screen *sp;
15911ab64890Smrg	register Depth *dp;
15921ab64890Smrg	register Visual *vp;
15931ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
15941ab64890Smrg		sp = &dpy->screens[i];
15951ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
15961ab64890Smrg			dp = &sp->depths[j];
15971ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
15981ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
15991ab64890Smrg				vp = &dp->visuals[k];
16001ab64890Smrg				if (vp->visualid == id) return (vp);
16011ab64890Smrg			}
16021ab64890Smrg		}
16031ab64890Smrg	}
16041ab64890Smrg	return (NULL);
16051ab64890Smrg}
16061ab64890Smrg
16071ab64890Smrgint
16081ab64890SmrgXFree (void *data)
16091ab64890Smrg{
16101ab64890Smrg	Xfree (data);
16111ab64890Smrg	return 1;
16121ab64890Smrg}
16131ab64890Smrg
16141ab64890Smrg#ifdef _XNEEDBCOPYFUNC
16151ab64890Smrgvoid _Xbcopy(b1, b2, length)
16161ab64890Smrg    register char *b1, *b2;
16171ab64890Smrg    register length;
16181ab64890Smrg{
16191ab64890Smrg    if (b1 < b2) {
16201ab64890Smrg	b2 += length;
16211ab64890Smrg	b1 += length;
16221ab64890Smrg	while (length--)
16231ab64890Smrg	    *--b2 = *--b1;
16241ab64890Smrg    } else {
16251ab64890Smrg	while (length--)
16261ab64890Smrg	    *b2++ = *b1++;
16271ab64890Smrg    }
16281ab64890Smrg}
16291ab64890Smrg#endif
16301ab64890Smrg
16311ab64890Smrg#ifdef DataRoutineIsProcedure
16321ab64890Smrgvoid Data(
16331ab64890Smrg	Display *dpy,
1634556b6652Smrg	_Xconst char *data,
16351ab64890Smrg	long len)
16361ab64890Smrg{
16371ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
16381ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
16391ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
16401ab64890Smrg	} else {
16411ab64890Smrg		_XSend(dpy, data, len);
16421ab64890Smrg	}
16431ab64890Smrg}
16441ab64890Smrg#endif /* DataRoutineIsProcedure */
16451ab64890Smrg
16461ab64890Smrg
16471ab64890Smrg#ifdef LONG64
16481ab64890Smrgint
16491ab64890Smrg_XData32(
16501ab64890Smrg    Display *dpy,
1651556b6652Smrg    register _Xconst long *data,
16521ab64890Smrg    unsigned len)
16531ab64890Smrg{
16541ab64890Smrg    register int *buf;
16551ab64890Smrg    register long i;
16561ab64890Smrg
16571ab64890Smrg    while (len) {
16581ab64890Smrg	buf = (int *)dpy->bufptr;
16591ab64890Smrg	i = dpy->bufmax - (char *)buf;
16601ab64890Smrg	if (!i) {
16611ab64890Smrg	    _XFlush(dpy);
16621ab64890Smrg	    continue;
16631ab64890Smrg	}
16641ab64890Smrg	if (len < i)
16651ab64890Smrg	    i = len;
16661ab64890Smrg	dpy->bufptr = (char *)buf + i;
16671ab64890Smrg	len -= i;
16681ab64890Smrg	i >>= 2;
16691ab64890Smrg	while (--i >= 0)
16701ab64890Smrg	    *buf++ = *data++;
16711ab64890Smrg    }
16721ab64890Smrg    return 0;
16731ab64890Smrg}
16741ab64890Smrg#endif /* LONG64 */
16751ab64890Smrg
16761ab64890Smrg
16771ab64890Smrg
16781ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
16791ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
16801ab64890Smrg *
16811ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
16821ab64890Smrg *       to have sufficient information for interfacing to the network,
16831ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
16841ab64890Smrg */
16851ab64890Smrg
16862e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
16871ab64890Smrg#define NEED_UTSNAME
16881ab64890Smrg#include <sys/utsname.h>
168988de56ccSmrg#else
169088de56ccSmrg#ifdef HAVE_UNISTD_H
169188de56ccSmrg#include <unistd.h>
169288de56ccSmrg#endif
16931ab64890Smrg#endif
16941ab64890Smrg
16951ab64890Smrg/*
16961ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
16971ab64890Smrg */
16981ab64890Smrgint _XGetHostname (
16991ab64890Smrg    char *buf,
17001ab64890Smrg    int maxlen)
17011ab64890Smrg{
17021ab64890Smrg    int len;
17031ab64890Smrg
17041ab64890Smrg#ifdef NEED_UTSNAME
17051ab64890Smrg    struct utsname name;
17061ab64890Smrg
17071ab64890Smrg    if (maxlen <= 0 || buf == NULL)
17081ab64890Smrg	return 0;
17091ab64890Smrg
17101ab64890Smrg    uname (&name);
1711e90f245cSmaya    len = (int) strlen (name.nodename);
17121ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
1713e90f245cSmaya    strncpy (buf, name.nodename, (size_t) len);
17141ab64890Smrg    buf[len] = '\0';
17151ab64890Smrg#else
17161ab64890Smrg    if (maxlen <= 0 || buf == NULL)
17171ab64890Smrg	return 0;
17181ab64890Smrg
17191ab64890Smrg    buf[0] = '\0';
17201ab64890Smrg    (void) gethostname (buf, maxlen);
17211ab64890Smrg    buf [maxlen - 1] = '\0';
1722e90f245cSmaya    len = (int) strlen(buf);
17231ab64890Smrg#endif /* NEED_UTSNAME */
17241ab64890Smrg    return len;
17251ab64890Smrg}
17261ab64890Smrg
17271ab64890Smrg
17281ab64890Smrg/*
17291ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
17301ab64890Smrg */
17311ab64890Smrg
173261b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
17331ab64890Smrg{
17341ab64890Smrg    register int i;
17351ab64890Smrg    Window root;
17361ab64890Smrg    int x, y;				/* dummy variables */
17371ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
17381ab64890Smrg
17391ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
17401ab64890Smrg		      &bw, &depth) == False) {
17412e9c7c8cSmrg	return NULL;
17421ab64890Smrg    }
17431ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
17441ab64890Smrg	if (root == RootWindow (dpy, i)) {
17451ab64890Smrg	    return ScreenOfDisplay (dpy, i);
17461ab64890Smrg	}
17471ab64890Smrg    }
17481ab64890Smrg    return NULL;
17491ab64890Smrg}
17501ab64890Smrg
17511ab64890Smrg
1752556b6652Smrg/*
1753556b6652Smrg * WARNING: This implementation's pre-conditions and post-conditions
1754556b6652Smrg * must remain compatible with the old macro-based implementations of
1755556b6652Smrg * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1756556b6652Smrg * Display structure affected by those macros are part of libX11's
1757556b6652Smrg * ABI.
1758556b6652Smrg */
1759556b6652Smrgvoid *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1760556b6652Smrg{
1761556b6652Smrg    xReq *req;
1762556b6652Smrg
1763556b6652Smrg    if (dpy->bufptr + len > dpy->bufmax)
1764556b6652Smrg	_XFlush(dpy);
1765c555af55Smrg    /* Request still too large, so do not allow it to overflow. */
1766c555af55Smrg    if (dpy->bufptr + len > dpy->bufmax) {
1767c555af55Smrg	fprintf(stderr,
1768c555af55Smrg		"Xlib: request %d length %zd would exceed buffer size.\n",
1769c555af55Smrg		type, len);
1770c555af55Smrg	/* Changes failure condition from overflow to NULL dereference. */
1771c555af55Smrg	return NULL;
1772c555af55Smrg    }
1773556b6652Smrg
1774556b6652Smrg    if (len % 4)
1775556b6652Smrg	fprintf(stderr,
1776556b6652Smrg		"Xlib: request %d length %zd not a multiple of 4.\n",
1777556b6652Smrg		type, len);
1778556b6652Smrg
1779556b6652Smrg    dpy->last_req = dpy->bufptr;
1780556b6652Smrg
1781556b6652Smrg    req = (xReq*)dpy->bufptr;
1782556b6652Smrg    req->reqType = type;
1783556b6652Smrg    req->length = len / 4;
1784556b6652Smrg    dpy->bufptr += len;
1785dac667f7Smrg    X_DPY_REQUEST_INCREMENT(dpy);
1786556b6652Smrg    return req;
1787556b6652Smrg}
1788556b6652Smrg
17891ab64890Smrg#if defined(WIN32)
17901ab64890Smrg
17911ab64890Smrg/*
17921ab64890Smrg * These functions are intended to be used internally to Xlib only.
17931ab64890Smrg * These functions will always prefix the path with a DOS drive in the
17941ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
17951ab64890Smrg * for use by Xlib function that supply a root-based path to some
17961ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
17971ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
17981ab64890Smrg */
17991ab64890Smrg
18001ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
18011ab64890Smrg    char* path;
18021ab64890Smrg    char* pathbuf;
18031ab64890Smrg    int len_pathbuf;
18041ab64890Smrg    char** pathret;
18051ab64890Smrg{
18061ab64890Smrg    if (access (path, F_OK) == 0) {
18071ab64890Smrg	if (strlen (path) < len_pathbuf)
18081ab64890Smrg	    *pathret = pathbuf;
18091ab64890Smrg	else
18101ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
18111ab64890Smrg	if (*pathret) {
18121ab64890Smrg	    strcpy (*pathret, path);
18131ab64890Smrg	    return 1;
18141ab64890Smrg	}
18151ab64890Smrg    }
18161ab64890Smrg    return 0;
18171ab64890Smrg}
18181ab64890Smrg
18191ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
18201ab64890Smrg    char* path;
18211ab64890Smrg    char* pathbuf;
18221ab64890Smrg    int len_pathbuf;
18231ab64890Smrg    char** pathret;
18241ab64890Smrg{
18251ab64890Smrg    unsigned long drives;
18261ab64890Smrg    int i, len;
18271ab64890Smrg    char* drive;
18281ab64890Smrg    char buf[MAX_PATH];
18291ab64890Smrg    char* bufp;
18301ab64890Smrg
18311ab64890Smrg    /* just try the "raw" name first and see if it works */
18321ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
18331ab64890Smrg	return 1;
18341ab64890Smrg
18351ab64890Smrg    /* try the places set in the environment */
18361ab64890Smrg    drive = getenv ("_XBASEDRIVE");
18371ab64890Smrg#ifdef __UNIXOS2__
18381ab64890Smrg    if (!drive)
18391ab64890Smrg	drive = getenv ("X11ROOT");
18401ab64890Smrg#endif
18411ab64890Smrg    if (!drive)
18421ab64890Smrg	drive = "C:";
18431ab64890Smrg    len = strlen (drive) + strlen (path);
18441ab64890Smrg    if (len < MAX_PATH) bufp = buf;
18451ab64890Smrg    else bufp = Xmalloc (len + 1);
18461ab64890Smrg    strcpy (bufp, drive);
18471ab64890Smrg    strcat (bufp, path);
18481ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18491ab64890Smrg	if (bufp != buf) Xfree (bufp);
18501ab64890Smrg	return 1;
18511ab64890Smrg    }
18521ab64890Smrg
185361b2299dSmrg#ifndef __UNIXOS2__
18541ab64890Smrg    /* one last place to look */
18551ab64890Smrg    drive = getenv ("HOMEDRIVE");
18561ab64890Smrg    if (drive) {
18571ab64890Smrg	len = strlen (drive) + strlen (path);
18581ab64890Smrg	if (len < MAX_PATH) bufp = buf;
18591ab64890Smrg	else bufp = Xmalloc (len + 1);
18601ab64890Smrg	strcpy (bufp, drive);
18611ab64890Smrg	strcat (bufp, path);
18621ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18631ab64890Smrg	    if (bufp != buf) Xfree (bufp);
18641ab64890Smrg	    return 1;
18651ab64890Smrg	}
18661ab64890Smrg    }
18671ab64890Smrg
18681ab64890Smrg    /* tried everywhere else, go fishing */
18691ab64890Smrg#define C_DRIVE ('C' - 'A')
18701ab64890Smrg#define Z_DRIVE ('Z' - 'A')
18711ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
18721ab64890Smrg    drives = _getdrives ();
18731ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
18741ab64890Smrg	if ((1 << i) & drives) {
18751ab64890Smrg	    len = 2 + strlen (path);
18761ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
18771ab64890Smrg	    else bufp = Xmalloc (len + 1);
18781ab64890Smrg	    *bufp = 'A' + i;
18791ab64890Smrg	    *(bufp + 1) = ':';
18801ab64890Smrg	    *(bufp + 2) = '\0';
18811ab64890Smrg	    strcat (bufp, path);
18821ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18831ab64890Smrg		if (bufp != buf) Xfree (bufp);
18841ab64890Smrg		return 1;
18851ab64890Smrg	    }
18861ab64890Smrg	}
18871ab64890Smrg    }
18881ab64890Smrg#endif
18891ab64890Smrg    return 0;
18901ab64890Smrg}
18911ab64890Smrg
18921ab64890Smrgint _XOpenFile(path, flags)
18931ab64890Smrg    _Xconst char* path;
18941ab64890Smrg    int flags;
18951ab64890Smrg{
18961ab64890Smrg    char buf[MAX_PATH];
18971ab64890Smrg    char* bufp = NULL;
18981ab64890Smrg    int ret = -1;
18991ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19001ab64890Smrg
19011ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19021ab64890Smrg	ret = open (bufp, flags);
19031ab64890Smrg
19041ab64890Smrg    (void) SetErrorMode (olderror);
19051ab64890Smrg
19061ab64890Smrg    if (bufp != buf) Xfree (bufp);
19071ab64890Smrg
19081ab64890Smrg    return ret;
19091ab64890Smrg}
19101ab64890Smrg
19111ab64890Smrgint _XOpenFileMode(path, flags, mode)
19121ab64890Smrg    _Xconst char* path;
19131ab64890Smrg    int flags;
19141ab64890Smrg    mode_t mode;
19151ab64890Smrg{
19161ab64890Smrg    char buf[MAX_PATH];
19171ab64890Smrg    char* bufp = NULL;
19181ab64890Smrg    int ret = -1;
19191ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19201ab64890Smrg
19211ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19221ab64890Smrg	ret = open (bufp, flags, mode);
19231ab64890Smrg
19241ab64890Smrg    (void) SetErrorMode (olderror);
19251ab64890Smrg
19261ab64890Smrg    if (bufp != buf) Xfree (bufp);
19271ab64890Smrg
19281ab64890Smrg    return ret;
19291ab64890Smrg}
19301ab64890Smrg
19311ab64890Smrgvoid* _XFopenFile(path, mode)
19321ab64890Smrg    _Xconst char* path;
19331ab64890Smrg    _Xconst char* mode;
19341ab64890Smrg{
19351ab64890Smrg    char buf[MAX_PATH];
19361ab64890Smrg    char* bufp = NULL;
19371ab64890Smrg    void* ret = NULL;
19381ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19391ab64890Smrg
19401ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19411ab64890Smrg	ret = fopen (bufp, mode);
19421ab64890Smrg
19431ab64890Smrg    (void) SetErrorMode (olderror);
19441ab64890Smrg
19451ab64890Smrg    if (bufp != buf) Xfree (bufp);
19461ab64890Smrg
19471ab64890Smrg    return ret;
19481ab64890Smrg}
19491ab64890Smrg
19501ab64890Smrgint _XAccessFile(path)
19511ab64890Smrg    _Xconst char* path;
19521ab64890Smrg{
19531ab64890Smrg    char buf[MAX_PATH];
19541ab64890Smrg    char* bufp;
19551ab64890Smrg    int ret = -1;
19561ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19571ab64890Smrg
19581ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
19591ab64890Smrg
19601ab64890Smrg    (void) SetErrorMode (olderror);
19611ab64890Smrg
19621ab64890Smrg    if (bufp != buf) Xfree (bufp);
19631ab64890Smrg
19641ab64890Smrg    return ret;
19651ab64890Smrg}
19661ab64890Smrg
19671ab64890Smrg#endif
19681ab64890Smrg
19691ab64890Smrg#ifdef WIN32
19701ab64890Smrg#undef _Xdebug
19711ab64890Smrgint _Xdebug = 0;
19721ab64890Smrgint *_Xdebug_p = &_Xdebug;
19731ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
19741ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
19751ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
19761ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19771ab64890Smrg    , char * /* file */
19781ab64890Smrg    , int /* line */
19791ab64890Smrg#endif
19801ab64890Smrg        ) = &_XLockMutex_fn;
19811ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
19821ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19831ab64890Smrg    , char * /* file */
19841ab64890Smrg    , int /* line */
19851ab64890Smrg#endif
19861ab64890Smrg        ) = &_XUnlockMutex_fn;
19871ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
19881ab64890Smrg#endif
1989