XlibInt.c revision d5e6aabb
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#define ECHECK(err) (errno == err)
1021ab64890Smrg#define ESET(val) errno = val
1031ab64890Smrg#endif
1041ab64890Smrg
1051ab64890Smrg
1061ab64890Smrg/*
1071ab64890Smrg * The following routines are internal routines used by Xlib for protocol
1081ab64890Smrg * packet transmission and reception.
1091ab64890Smrg *
1101ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
1111ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
1121ab64890Smrg *
1131ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
1141ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
1151ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
1161ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
1171ab64890Smrg *
1181ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
11961b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
1201ab64890Smrg * return anything.  Whenever possible routines that create objects return
1211ab64890Smrg * the object they have created.
1221ab64890Smrg */
1231ab64890Smrg
1241ab64890Smrg#define POLLFD_CACHE_SIZE 5
1251ab64890Smrg
1261ab64890Smrg/* initialize the struct array passed to poll() below */
1271ab64890SmrgBool _XPollfdCacheInit(
1281ab64890Smrg    Display *dpy)
1291ab64890Smrg{
1301ab64890Smrg#ifdef USE_POLL
1311ab64890Smrg    struct pollfd *pfp;
1321ab64890Smrg
133556b6652Smrg    pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1341ab64890Smrg    if (!pfp)
1351ab64890Smrg	return False;
1361ab64890Smrg    pfp[0].fd = dpy->fd;
1371ab64890Smrg    pfp[0].events = POLLIN;
1381ab64890Smrg
1391ab64890Smrg    dpy->filedes = (XPointer)pfp;
1401ab64890Smrg#endif
1411ab64890Smrg    return True;
1421ab64890Smrg}
1431ab64890Smrg
1441ab64890Smrgvoid _XPollfdCacheAdd(
1451ab64890Smrg    Display *dpy,
1461ab64890Smrg    int fd)
1471ab64890Smrg{
1481ab64890Smrg#ifdef USE_POLL
1491ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1501ab64890Smrg
1511ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1521ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
1531ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
1541ab64890Smrg    }
1551ab64890Smrg#endif
1561ab64890Smrg}
1571ab64890Smrg
1581ab64890Smrg/* ARGSUSED */
1591ab64890Smrgvoid _XPollfdCacheDel(
1601ab64890Smrg    Display *dpy,
1611ab64890Smrg    int fd)			/* not used */
1621ab64890Smrg{
1631ab64890Smrg#ifdef USE_POLL
1641ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1651ab64890Smrg    struct _XConnectionInfo *conni;
1661ab64890Smrg
1671ab64890Smrg    /* just recalculate whole list */
1681ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1691ab64890Smrg	int loc = 1;
1701ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1711ab64890Smrg	    pfp[loc].fd = conni->fd;
1721ab64890Smrg	    pfp[loc].events = POLLIN;
1731ab64890Smrg	    loc++;
1741ab64890Smrg	}
1751ab64890Smrg    }
1761ab64890Smrg#endif
1771ab64890Smrg}
1781ab64890Smrg
17961b2299dSmrgstatic int sync_hazard(Display *dpy)
18061b2299dSmrg{
181dac667f7Smrg    /*
182e90f245cSmaya     * "span" and "hazard" need to be signed such that the ">=" comparison
183dac667f7Smrg     * works correctly in the case that hazard is greater than 65525
184dac667f7Smrg     */
185dac667f7Smrg    int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
186dac667f7Smrg    int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
18761b2299dSmrg    return span >= 65535 - hazard - 10;
18861b2299dSmrg}
18961b2299dSmrg
1901ab64890Smrgstatic
19188de56ccSmrgvoid sync_while_locked(Display *dpy)
19288de56ccSmrg{
19388de56ccSmrg#ifdef XTHREADS
19488de56ccSmrg    if (dpy->lock)
19588de56ccSmrg        (*dpy->lock->user_lock_display)(dpy);
19688de56ccSmrg#endif
19788de56ccSmrg    UnlockDisplay(dpy);
19888de56ccSmrg    SyncHandle();
19988de56ccSmrg    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
20088de56ccSmrg#ifdef XTHREADS
20188de56ccSmrg    if (dpy->lock)
20288de56ccSmrg        (*dpy->lock->user_unlock_display)(dpy);
20388de56ccSmrg#endif
20488de56ccSmrg}
20588de56ccSmrg
20688de56ccSmrgvoid _XSeqSyncFunction(
2071ab64890Smrg    register Display *dpy)
2081ab64890Smrg{
2091ab64890Smrg    xGetInputFocusReply rep;
210bd8e7fb0Smrg    _X_UNUSED register xReq *req;
2111ab64890Smrg
21215c3e985Smrg    if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
2131ab64890Smrg	GetEmptyReq(GetInputFocus, req);
2141ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
21588de56ccSmrg	sync_while_locked(dpy);
21661b2299dSmrg    } else if (sync_hazard(dpy))
21761b2299dSmrg	_XSetPrivSyncFunction(dpy);
2181ab64890Smrg}
2191ab64890Smrg
22088de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
22161b2299dSmrgstatic int
22261b2299dSmrg_XPrivSyncFunction (Display *dpy)
22361b2299dSmrg{
224e0787e08Smrg#ifdef XTHREADS
22588de56ccSmrg    assert(!dpy->lock_fns);
22688de56ccSmrg#endif
22761b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
22861b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
22961b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
23061b2299dSmrg    dpy->savedsynchandler = NULL;
23161b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
23288de56ccSmrg    if(dpy->synchandler)
23388de56ccSmrg        dpy->synchandler(dpy);
23461b2299dSmrg    _XIDHandler(dpy);
23561b2299dSmrg    _XSeqSyncFunction(dpy);
23661b2299dSmrg    return 0;
23761b2299dSmrg}
23861b2299dSmrg
23961b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
2401ab64890Smrg{
24188de56ccSmrg#ifdef XTHREADS
24288de56ccSmrg    if (dpy->lock_fns)
24388de56ccSmrg        return;
24488de56ccSmrg#endif
24561b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
2461ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
24761b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
2481ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
2491ab64890Smrg    }
2501ab64890Smrg}
2511ab64890Smrg
25261b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
25361b2299dSmrg{
25461b2299dSmrg    if (sync_hazard(dpy))
25561b2299dSmrg	_XSetPrivSyncFunction (dpy);
25661b2299dSmrg}
25761b2299dSmrg
2581ab64890Smrg#ifdef LONG64
2591ab64890Smrgvoid _XRead32(
2601ab64890Smrg    Display *dpy,
26115c3e985Smrg    long *data,
2621ab64890Smrg    long len)
2631ab64890Smrg{
2641ab64890Smrg    register int *buf;
2651ab64890Smrg    register long i;
2661ab64890Smrg
2671ab64890Smrg    if (len) {
2681ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
2691ab64890Smrg	i = len >> 2;
2701ab64890Smrg	buf = (int *)data + i;
2711ab64890Smrg	data += i;
2721ab64890Smrg	while (--i >= 0)
2731ab64890Smrg	    *--data = *--buf;
2741ab64890Smrg    }
2751ab64890Smrg}
2761ab64890Smrg#endif /* LONG64 */
2771ab64890Smrg
2781ab64890Smrg
2791ab64890Smrg/*
2801ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
2811ab64890Smrg * We have three values that will march along, with the following invariant:
2821ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
2831ab64890Smrg * We have to keep
2841ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
2851ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
2861ab64890Smrg * by forcing syncs when we get close.
2871ab64890Smrg */
2881ab64890Smrg
2891ab64890Smrgunsigned long
2901ab64890Smrg_XSetLastRequestRead(
2911ab64890Smrg    register Display *dpy,
2921ab64890Smrg    register xGenericReply *rep)
2931ab64890Smrg{
294dac667f7Smrg    register uint64_t	newseq, lastseq;
2951ab64890Smrg
296dac667f7Smrg    lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
2971ab64890Smrg    /*
2981ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
2991ab64890Smrg     * to immediately follow another event, except when generated via
3001ab64890Smrg     * SendEvent (hmmm).
3011ab64890Smrg     */
3021ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
3031ab64890Smrg	return(lastseq);
3041ab64890Smrg
305dac667f7Smrg    newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
3061ab64890Smrg
3071ab64890Smrg    if (newseq < lastseq) {
3081ab64890Smrg	newseq += 0x10000;
309dac667f7Smrg	if (newseq > X_DPY_GET_REQUEST(dpy)) {
31061b2299dSmrg	    (void) fprintf (stderr,
311dac667f7Smrg	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
312dac667f7Smrg			    (unsigned long long)newseq,
313dac667f7Smrg			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
3141ab64890Smrg			    (unsigned int) rep->type);
3151ab64890Smrg	    newseq -= 0x10000;
3161ab64890Smrg	}
3171ab64890Smrg    }
3181ab64890Smrg
319dac667f7Smrg    X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
3201ab64890Smrg    return(newseq);
3211ab64890Smrg}
3221ab64890Smrg
3231ab64890Smrg/*
3241ab64890Smrg * Support for internal connections, such as an IM might use.
3251ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
3261ab64890Smrg */
3271ab64890Smrg
3281ab64890Smrg/* _XRegisterInternalConnection
3291ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
3301ab64890Smrg * include in its select/poll mask must call this function to register the
3311ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
3321ab64890Smrg * will also be called.
3331ab64890Smrg *
3341ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
3351ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
3361ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
3371ab64890Smrg * which will call the associated callback.
3381ab64890Smrg *
3391ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
3401ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
3411ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
3421ab64890Smrg * to be called when fds are registered or unregistered.
3431ab64890Smrg *
3441ab64890Smrg * Returns True if registration succeeded, False if not, typically
3451ab64890Smrg * because could not allocate memory.
3461ab64890Smrg * Assumes Display locked when called.
3471ab64890Smrg */
3481ab64890SmrgStatus
3491ab64890Smrg_XRegisterInternalConnection(
3501ab64890Smrg    Display* dpy,
3511ab64890Smrg    int fd,
3521ab64890Smrg    _XInternalConnectionProc callback,
3531ab64890Smrg    XPointer call_data
3541ab64890Smrg)
3551ab64890Smrg{
3561ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
3571ab64890Smrg    struct _XConnWatchInfo *watchers;
3581ab64890Smrg    XPointer *wd;
3591ab64890Smrg
360556b6652Smrg    new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
3611ab64890Smrg    if (!new_conni)
3621ab64890Smrg	return 0;
363f2d49d05Smrg    new_conni->watch_data = Xmallocarray(dpy->watcher_count, sizeof(XPointer));
3641ab64890Smrg    if (!new_conni->watch_data) {
3651ab64890Smrg	Xfree(new_conni);
3661ab64890Smrg	return 0;
3671ab64890Smrg    }
3681ab64890Smrg    new_conni->fd = fd;
3691ab64890Smrg    new_conni->read_callback = callback;
3701ab64890Smrg    new_conni->call_data = call_data;
3711ab64890Smrg    new_conni->next = NULL;
3721ab64890Smrg    /* link new structure onto end of list */
3731ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
3741ab64890Smrg	;
3751ab64890Smrg    *iptr = new_conni;
3761ab64890Smrg    dpy->im_fd_length++;
3771ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
3781ab64890Smrg
3791ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
3801ab64890Smrg	 watchers;
3811ab64890Smrg	 watchers=watchers->next, wd++) {
3821ab64890Smrg	*wd = NULL;		/* for cleanliness */
3831ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
3841ab64890Smrg    }
3851ab64890Smrg
3861ab64890Smrg    return 1;
3871ab64890Smrg}
3881ab64890Smrg
3891ab64890Smrg/* _XUnregisterInternalConnection
3901ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
3911ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
3921ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
3931ab64890Smrg * will also be called.
3941ab64890Smrg *
3951ab64890Smrg * Assumes Display locked when called.
3961ab64890Smrg */
3971ab64890Smrgvoid
3981ab64890Smrg_XUnregisterInternalConnection(
3991ab64890Smrg    Display* dpy,
4001ab64890Smrg    int fd
4011ab64890Smrg)
4021ab64890Smrg{
4031ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
4041ab64890Smrg    struct _XConnWatchInfo *watch;
4051ab64890Smrg    XPointer *wd;
4061ab64890Smrg
4071ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
4081ab64890Smrg	 prev = &info_list->next) {
4091ab64890Smrg	if (info_list->fd == fd) {
4101ab64890Smrg	    *prev = info_list->next;
4111ab64890Smrg	    dpy->im_fd_length--;
4121ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
4131ab64890Smrg		 watch;
4141ab64890Smrg		 watch=watch->next, wd++) {
4151ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
4161ab64890Smrg	    }
417cf2acddeSmrg	    Xfree (info_list->watch_data);
4181ab64890Smrg	    Xfree (info_list);
4191ab64890Smrg	    break;
4201ab64890Smrg	}
4211ab64890Smrg    }
4221ab64890Smrg    _XPollfdCacheDel(dpy, fd);
4231ab64890Smrg}
4241ab64890Smrg
4251ab64890Smrg/* XInternalConnectionNumbers
4261ab64890Smrg * Returns an array of fds and an array of corresponding call data.
4271ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
4281ab64890Smrg * will be used instead of this function to discover
4291ab64890Smrg * additional fds to include in the select/poll mask.
4301ab64890Smrg *
4311ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
4321ab64890Smrg * with Xfree;
4331ab64890Smrg */
4341ab64890SmrgStatus
4351ab64890SmrgXInternalConnectionNumbers(
4361ab64890Smrg    Display *dpy,
4371ab64890Smrg    int **fd_return,
4381ab64890Smrg    int *count_return
4391ab64890Smrg)
4401ab64890Smrg{
4411ab64890Smrg    int count;
4421ab64890Smrg    struct _XConnectionInfo *info_list;
4431ab64890Smrg    int *fd_list;
4441ab64890Smrg
4451ab64890Smrg    LockDisplay(dpy);
4461ab64890Smrg    count = 0;
4471ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
4481ab64890Smrg	count++;
449f2d49d05Smrg    fd_list = Xmallocarray (count, sizeof(int));
4501ab64890Smrg    if (!fd_list) {
4511ab64890Smrg	UnlockDisplay(dpy);
4521ab64890Smrg	return 0;
4531ab64890Smrg    }
4541ab64890Smrg    count = 0;
4551ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4561ab64890Smrg	fd_list[count] = info_list->fd;
4571ab64890Smrg	count++;
4581ab64890Smrg    }
4591ab64890Smrg    UnlockDisplay(dpy);
4601ab64890Smrg
4611ab64890Smrg    *fd_return = fd_list;
4621ab64890Smrg    *count_return = count;
4631ab64890Smrg    return 1;
4641ab64890Smrg}
4651ab64890Smrg
4661ab64890Smrgvoid _XProcessInternalConnection(
4671ab64890Smrg    Display *dpy,
4681ab64890Smrg    struct _XConnectionInfo *conn_info)
4691ab64890Smrg{
4701ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
4711ab64890Smrg    UnlockDisplay(dpy);
4721ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
4731ab64890Smrg    LockDisplay(dpy);
4741ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
4751ab64890Smrg}
4761ab64890Smrg
4771ab64890Smrg/* XProcessInternalConnection
4781ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
4791ab64890Smrg * for this fd.
4801ab64890Smrg * The Display is NOT locked during the call.
4811ab64890Smrg */
4821ab64890Smrgvoid
4831ab64890SmrgXProcessInternalConnection(
4841ab64890Smrg    Display* dpy,
4851ab64890Smrg    int fd
4861ab64890Smrg)
4871ab64890Smrg{
4881ab64890Smrg    struct _XConnectionInfo *info_list;
4891ab64890Smrg
4901ab64890Smrg    LockDisplay(dpy);
4911ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4921ab64890Smrg	if (info_list->fd == fd) {
4931ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
4941ab64890Smrg	    break;
4951ab64890Smrg	}
4961ab64890Smrg    }
4971ab64890Smrg    UnlockDisplay(dpy);
4981ab64890Smrg}
4991ab64890Smrg
5001ab64890Smrg/* XAddConnectionWatch
5011ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
5021ab64890Smrg * or _XUnregisterInternalConnection is called.
5031ab64890Smrg * Callbacks are called with the Display locked.
5041ab64890Smrg * If any connections are already registered, the callback is immediately
5051ab64890Smrg * called for each of them.
5061ab64890Smrg */
5071ab64890SmrgStatus
5081ab64890SmrgXAddConnectionWatch(
5091ab64890Smrg    Display* dpy,
5101ab64890Smrg    XConnectionWatchProc callback,
5111ab64890Smrg    XPointer client_data
5121ab64890Smrg)
5131ab64890Smrg{
5141ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
5151ab64890Smrg    struct _XConnectionInfo *info_list;
5161ab64890Smrg    XPointer *wd_array;
5171ab64890Smrg
5181ab64890Smrg    LockDisplay(dpy);
5191ab64890Smrg
5201ab64890Smrg    /* allocate new watch data */
5211ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
522f2d49d05Smrg	wd_array = Xreallocarray(info_list->watch_data,
523f2d49d05Smrg                                 dpy->watcher_count + 1, sizeof(XPointer));
5241ab64890Smrg	if (!wd_array) {
5251ab64890Smrg	    UnlockDisplay(dpy);
5261ab64890Smrg	    return 0;
5271ab64890Smrg	}
528c17aa6b1Smrg	info_list->watch_data = wd_array;
5291ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
5301ab64890Smrg    }
5311ab64890Smrg
532556b6652Smrg    new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
5331ab64890Smrg    if (!new_watcher) {
5341ab64890Smrg	UnlockDisplay(dpy);
5351ab64890Smrg	return 0;
5361ab64890Smrg    }
5371ab64890Smrg    new_watcher->fn = callback;
5381ab64890Smrg    new_watcher->client_data = client_data;
5391ab64890Smrg    new_watcher->next = NULL;
5401ab64890Smrg
5411ab64890Smrg    /* link new structure onto end of list */
5421ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
5431ab64890Smrg	;
5441ab64890Smrg    *wptr = new_watcher;
5451ab64890Smrg    dpy->watcher_count++;
5461ab64890Smrg
5471ab64890Smrg    /* call new watcher on all currently registered fds */
5481ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5491ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
5501ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
5511ab64890Smrg    }
5521ab64890Smrg
5531ab64890Smrg    UnlockDisplay(dpy);
5541ab64890Smrg    return 1;
5551ab64890Smrg}
5561ab64890Smrg
5571ab64890Smrg/* XRemoveConnectionWatch
5581ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
5591ab64890Smrg * Both callback and client_data must match what was passed to
5601ab64890Smrg * XAddConnectionWatch.
56161b2299dSmrg */
5621ab64890Smrgvoid
5631ab64890SmrgXRemoveConnectionWatch(
5641ab64890Smrg    Display* dpy,
5651ab64890Smrg    XConnectionWatchProc callback,
5661ab64890Smrg    XPointer client_data
5671ab64890Smrg)
5681ab64890Smrg{
5691ab64890Smrg    struct _XConnWatchInfo *watch;
5701ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
5711ab64890Smrg    struct _XConnectionInfo *conni;
5721ab64890Smrg    int counter = 0;
5731ab64890Smrg
5741ab64890Smrg    LockDisplay(dpy);
5751ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
5761ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
5771ab64890Smrg	    if (previous)
5781ab64890Smrg		previous->next = watch->next;
5791ab64890Smrg	    else
5801ab64890Smrg		dpy->conn_watchers = watch->next;
5811ab64890Smrg	    Xfree (watch);
5821ab64890Smrg	    dpy->watcher_count--;
5831ab64890Smrg	    /* remove our watch_data for each connection */
5841ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
5851ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
5861ab64890Smrg		/* overlapping */
5871ab64890Smrg		memmove(conni->watch_data+counter,
5881ab64890Smrg			conni->watch_data+counter+1,
5891ab64890Smrg			dpy->watcher_count - counter);
5901ab64890Smrg	    }
5911ab64890Smrg	    break;
5921ab64890Smrg	}
5931ab64890Smrg	previous = watch;
5941ab64890Smrg	counter++;
5951ab64890Smrg    }
5961ab64890Smrg    UnlockDisplay(dpy);
5971ab64890Smrg}
5981ab64890Smrg
5991ab64890Smrg/* end of internal connections support */
6001ab64890Smrg
601b4ee4795Smrg/* Cookie jar implementation
602b4ee4795Smrg   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
603b4ee4795Smrg   them in the normal EQ. _XStoreEvent returns the cookie event (minus
604b4ee4795Smrg   data pointer) and adds it to the cookiejar. _XDeq just removes
605b4ee4795Smrg   the entry like any other event but resets the data pointer for
606b4ee4795Smrg   cookie events (to avoid double-free, the memory is re-used by Xlib).
607b4ee4795Smrg
608b4ee4795Smrg   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
609b4ee4795Smrg   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
610b4ee4795Smrg   (called by XNextEvent).
611b4ee4795Smrg
612b4ee4795Smrg   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
613b4ee4795Smrg   normal EQ.
614b4ee4795Smrg */
615b4ee4795Smrg
616b4ee4795Smrg#include "utlist.h"
617b4ee4795Smrgstruct stored_event {
618b4ee4795Smrg    XGenericEventCookie ev;
619b4ee4795Smrg    struct stored_event *prev;
620b4ee4795Smrg    struct stored_event *next;
621b4ee4795Smrg};
622b4ee4795Smrg
623b4ee4795SmrgBool
624b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev)
625b4ee4795Smrg{
626b4ee4795Smrg    return (ev->xcookie.type == GenericEvent &&
627b4ee4795Smrg	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
628b4ee4795Smrg}
629b4ee4795Smrg
630b4ee4795Smrg/**
631b4ee4795Smrg * Free all events in the event list.
632b4ee4795Smrg */
633b4ee4795Smrgvoid
634b4ee4795Smrg_XFreeEventCookies(Display *dpy)
635b4ee4795Smrg{
636b4ee4795Smrg    struct stored_event **head, *e, *tmp;
637b4ee4795Smrg
638b4ee4795Smrg    if (!dpy->cookiejar)
639b4ee4795Smrg        return;
640b4ee4795Smrg
641b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
642b4ee4795Smrg
643b4ee4795Smrg    DL_FOREACH_SAFE(*head, e, tmp) {
644c17aa6b1Smrg        XFree(e->ev.data);
645c17aa6b1Smrg        XFree(e);
646b4ee4795Smrg    }
64715c3e985Smrg    dpy->cookiejar = NULL;
648b4ee4795Smrg}
649b4ee4795Smrg
650b4ee4795Smrg/**
651b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the
652b4ee4795Smrg * next call to XNextEvent().
653b4ee4795Smrg */
654b4ee4795Smrgvoid
655b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event)
656b4ee4795Smrg{
657b4ee4795Smrg    XGenericEventCookie* cookie = &event->xcookie;
658b4ee4795Smrg    struct stored_event **head, *add;
659b4ee4795Smrg
660b4ee4795Smrg    if (!_XIsEventCookie(dpy, event))
661b4ee4795Smrg        return;
662b4ee4795Smrg
663b4ee4795Smrg    head = (struct stored_event**)(&dpy->cookiejar);
664b4ee4795Smrg
665b4ee4795Smrg    add = Xmalloc(sizeof(struct stored_event));
666b4ee4795Smrg    if (!add) {
667b4ee4795Smrg        ESET(ENOMEM);
668b4ee4795Smrg        _XIOError(dpy);
66915c3e985Smrg        return;
670b4ee4795Smrg    }
671b4ee4795Smrg    add->ev = *cookie;
672b4ee4795Smrg    DL_APPEND(*head, add);
673b4ee4795Smrg    cookie->data = NULL; /* don't return data yet, must be claimed */
674b4ee4795Smrg}
675b4ee4795Smrg
676b4ee4795Smrg/**
677b4ee4795Smrg * Return the event with the given cookie and remove it from the list.
678b4ee4795Smrg */
679b4ee4795SmrgBool
680b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
681b4ee4795Smrg{
682b4ee4795Smrg    Bool ret = False;
683b4ee4795Smrg    struct stored_event **head, *event;
684b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
685b4ee4795Smrg
686b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)ev))
687b4ee4795Smrg        return ret;
688b4ee4795Smrg
689b4ee4795Smrg    DL_FOREACH(*head, event) {
690b4ee4795Smrg        if (event->ev.cookie == ev->cookie &&
691b4ee4795Smrg            event->ev.extension == ev->extension &&
692b4ee4795Smrg            event->ev.evtype == ev->evtype) {
693b4ee4795Smrg            *ev = event->ev;
694b4ee4795Smrg            DL_DELETE(*head, event);
695b4ee4795Smrg            Xfree(event);
696b4ee4795Smrg            ret = True;
697b4ee4795Smrg            break;
698b4ee4795Smrg        }
699b4ee4795Smrg    }
700b4ee4795Smrg
701b4ee4795Smrg    return ret;
702b4ee4795Smrg}
703b4ee4795Smrg
704b4ee4795SmrgBool
705b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
706b4ee4795Smrg{
707b4ee4795Smrg    Bool ret = False;
708b4ee4795Smrg    int extension;
709b4ee4795Smrg
710b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
711b4ee4795Smrg        return ret;
712b4ee4795Smrg
713b4ee4795Smrg    extension = in->extension & 0x7F;
714b4ee4795Smrg
715b4ee4795Smrg    if (!dpy->generic_event_copy_vec[extension])
716b4ee4795Smrg        return ret;
717b4ee4795Smrg
718b4ee4795Smrg    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
719b4ee4795Smrg    out->cookie = ret ? ++dpy->next_cookie  : 0;
720b4ee4795Smrg    return ret;
721b4ee4795Smrg}
722b4ee4795Smrg
7231ab64890Smrg
7241ab64890Smrg/*
7251ab64890Smrg * _XEnq - Place event packets on the display's queue.
7261ab64890Smrg * note that no squishing of move events in V11, since there
7271ab64890Smrg * is pointer motion hints....
7281ab64890Smrg */
7291ab64890Smrgvoid _XEnq(
7301ab64890Smrg	register Display *dpy,
7311ab64890Smrg	register xEvent *event)
7321ab64890Smrg{
7331ab64890Smrg	register _XQEvent *qelt;
734b4ee4795Smrg	int type, extension;
7351ab64890Smrg
7361ab64890Smrg	if ((qelt = dpy->qfree)) {
7371ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
7381ab64890Smrg		dpy->qfree = qelt->next;
7391ab64890Smrg	}
740556b6652Smrg	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
7411ab64890Smrg		/* Malloc call failed! */
7421ab64890Smrg		ESET(ENOMEM);
7431ab64890Smrg		_XIOError(dpy);
74415c3e985Smrg		return;
7451ab64890Smrg	}
7461ab64890Smrg	qelt->next = NULL;
747b4ee4795Smrg
748b4ee4795Smrg	type = event->u.u.type & 0177;
749b4ee4795Smrg	extension = ((xGenericEvent*)event)->extension;
750295fb823Smrg
751295fb823Smrg	qelt->event.type = type;
752556b6652Smrg	/* If an extension has registered a generic_event_vec handler, then
753b4ee4795Smrg	 * it can handle event cookies. Otherwise, proceed with the normal
754b4ee4795Smrg	 * event handlers.
755b4ee4795Smrg	 *
756b4ee4795Smrg	 * If the generic_event_vec is called, qelt->event is a event cookie
757b4ee4795Smrg	 * with the data pointer and the "free" pointer set. Data pointer is
758b4ee4795Smrg	 * some memory allocated by the extension.
759b4ee4795Smrg	 */
760b4ee4795Smrg        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
761b4ee4795Smrg	    XGenericEventCookie *cookie = &qelt->event.xcookie;
762b4ee4795Smrg	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
763b4ee4795Smrg	    cookie->cookie = ++dpy->next_cookie;
764b4ee4795Smrg
765b4ee4795Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
766b4ee4795Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
767b4ee4795Smrg	    else		dpy->head = qelt;
768b4ee4795Smrg
769b4ee4795Smrg	    dpy->tail = qelt;
770b4ee4795Smrg	    dpy->qlen++;
771b4ee4795Smrg	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
7721ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
7731ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
7741ab64890Smrg	    else 		dpy->head = qelt;
77561b2299dSmrg
7761ab64890Smrg	    dpy->tail = qelt;
7771ab64890Smrg	    dpy->qlen++;
7781ab64890Smrg	} else {
7791ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
7801ab64890Smrg	    qelt->next = dpy->qfree;
7811ab64890Smrg	    dpy->qfree = qelt;
7821ab64890Smrg	}
7831ab64890Smrg}
7841ab64890Smrg
7851ab64890Smrg/*
7861ab64890Smrg * _XDeq - Remove event packet from the display's queue.
7871ab64890Smrg */
7881ab64890Smrgvoid _XDeq(
7891ab64890Smrg    register Display *dpy,
7901ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
7911ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
7921ab64890Smrg{
7931ab64890Smrg    if (prev) {
7941ab64890Smrg	if ((prev->next = qelt->next) == NULL)
7951ab64890Smrg	    dpy->tail = prev;
7961ab64890Smrg    } else {
7971ab64890Smrg	/* no prev, so removing first elt */
7981ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
7991ab64890Smrg	    dpy->tail = NULL;
8001ab64890Smrg    }
8011ab64890Smrg    qelt->qserial_num = 0;
8021ab64890Smrg    qelt->next = dpy->qfree;
8031ab64890Smrg    dpy->qfree = qelt;
8041ab64890Smrg    dpy->qlen--;
805b4ee4795Smrg
806b4ee4795Smrg    if (_XIsEventCookie(dpy, &qelt->event)) {
807b4ee4795Smrg	XGenericEventCookie* cookie = &qelt->event.xcookie;
808b4ee4795Smrg	/* dpy->qfree is re-used, reset memory to avoid double free on
809b4ee4795Smrg	 * _XFreeDisplayStructure */
810b4ee4795Smrg	cookie->data = NULL;
811b4ee4795Smrg    }
8121ab64890Smrg}
8131ab64890Smrg
8141ab64890Smrg/*
8151ab64890Smrg * EventToWire in separate file in that often not needed.
8161ab64890Smrg */
8171ab64890Smrg
8181ab64890Smrg/*ARGSUSED*/
8191ab64890SmrgBool
8201ab64890Smrg_XUnknownWireEvent(
8211ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8221ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8231ab64890Smrg    register xEvent *event)	/* wire protocol event */
8241ab64890Smrg{
8251ab64890Smrg#ifdef notdef
82661b2299dSmrg	(void) fprintf(stderr,
8271ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
8281ab64890Smrg			event->u.u.type, dpy);
8291ab64890Smrg#endif
8301ab64890Smrg	return(False);
8311ab64890Smrg}
8321ab64890Smrg
833b4ee4795SmrgBool
834b4ee4795Smrg_XUnknownWireEventCookie(
835b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
836b4ee4795Smrg    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
837b4ee4795Smrg    xEvent *event)	/* wire protocol event */
838b4ee4795Smrg{
839b4ee4795Smrg#ifdef notdef
840b4ee4795Smrg	fprintf(stderr,
841b4ee4795Smrg	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
842b4ee4795Smrg			((xGenericEvent*)event)->extension, dpy);
843b4ee4795Smrg#endif
844b4ee4795Smrg	return(False);
845b4ee4795Smrg}
846b4ee4795Smrg
847b4ee4795SmrgBool
848b4ee4795Smrg_XUnknownCopyEventCookie(
849b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
850b4ee4795Smrg    XGenericEventCookie *in,	/* source */
851b4ee4795Smrg    XGenericEventCookie *out)	/* destination */
852b4ee4795Smrg{
853b4ee4795Smrg#ifdef notdef
854b4ee4795Smrg	fprintf(stderr,
855b4ee4795Smrg	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
856b4ee4795Smrg			in->extension, dpy);
857b4ee4795Smrg#endif
858b4ee4795Smrg	return(False);
859b4ee4795Smrg}
860b4ee4795Smrg
8611ab64890Smrg/*ARGSUSED*/
8621ab64890SmrgStatus
8631ab64890Smrg_XUnknownNativeEvent(
8641ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8651ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8661ab64890Smrg    register xEvent *event)	/* wire protocol event */
8671ab64890Smrg{
8681ab64890Smrg#ifdef notdef
86961b2299dSmrg	(void) fprintf(stderr,
8701ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
8711ab64890Smrg			re->type, dpy);
8721ab64890Smrg#endif
8731ab64890Smrg	return(0);
8741ab64890Smrg}
8751ab64890Smrg/*
8761ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
8771ab64890Smrg */
8781ab64890SmrgBool
8791ab64890Smrg_XWireToEvent(
8801ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8811ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8821ab64890Smrg    register xEvent *event)	/* wire protocol event */
8831ab64890Smrg{
8841ab64890Smrg
8851ab64890Smrg	re->type = event->u.u.type & 0x7f;
8861ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
8871ab64890Smrg					(xGenericReply *)event);
8881ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
8891ab64890Smrg	((XAnyEvent *)re)->display = dpy;
89061b2299dSmrg
8911ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
8921ab64890Smrg		client sends an event rather than the server. */
8931ab64890Smrg
8941ab64890Smrg	switch (event-> u.u.type & 0177) {
8951ab64890Smrg	      case KeyPress:
8961ab64890Smrg	      case KeyRelease:
8971ab64890Smrg	        {
8981ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
8991ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9001ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9011ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9021ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9031ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9041ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9051ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9061ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9071ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9081ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9091ab64890Smrg			ev->keycode 	= event->u.u.detail;
9101ab64890Smrg		}
9111ab64890Smrg	      	break;
9121ab64890Smrg	      case ButtonPress:
9131ab64890Smrg	      case ButtonRelease:
9141ab64890Smrg	        {
9151ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) 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->button 	= event->u.u.detail;
9271ab64890Smrg		}
9281ab64890Smrg	        break;
9291ab64890Smrg	      case MotionNotify:
9301ab64890Smrg	        {
9311ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
9321ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9331ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9341ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9351ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9361ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9371ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9381ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9391ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9401ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9411ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9421ab64890Smrg			ev->is_hint 	= event->u.u.detail;
9431ab64890Smrg		}
9441ab64890Smrg	        break;
9451ab64890Smrg	      case EnterNotify:
9461ab64890Smrg	      case LeaveNotify:
9471ab64890Smrg		{
9481ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
9491ab64890Smrg			ev->root	= event->u.enterLeave.root;
9501ab64890Smrg			ev->window	= event->u.enterLeave.event;
9511ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
9521ab64890Smrg			ev->time	= event->u.enterLeave.time;
9531ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
9541ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
9551ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
9561ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
9571ab64890Smrg			ev->state	= event->u.enterLeave.state;
9581ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
95961b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
9601ab64890Smrg				ELFlagSameScreen) && True;
9611ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
9621ab64890Smrg			  	ELFlagFocus) && True;
9631ab64890Smrg			ev->detail	= event->u.u.detail;
9641ab64890Smrg		}
9651ab64890Smrg		  break;
9661ab64890Smrg	      case FocusIn:
9671ab64890Smrg	      case FocusOut:
9681ab64890Smrg		{
9691ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
9701ab64890Smrg			ev->window 	= event->u.focus.window;
9711ab64890Smrg			ev->mode	= event->u.focus.mode;
9721ab64890Smrg			ev->detail	= event->u.u.detail;
9731ab64890Smrg		}
9741ab64890Smrg		  break;
9751ab64890Smrg	      case KeymapNotify:
9761ab64890Smrg		{
9771ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
9781ab64890Smrg			ev->window	= None;
9791ab64890Smrg			memcpy(&ev->key_vector[1],
9801ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
9811ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
9821ab64890Smrg		}
9831ab64890Smrg		break;
9841ab64890Smrg	      case Expose:
9851ab64890Smrg		{
9861ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
9871ab64890Smrg			ev->window	= event->u.expose.window;
9881ab64890Smrg			ev->x		= event->u.expose.x;
9891ab64890Smrg			ev->y		= event->u.expose.y;
9901ab64890Smrg			ev->width	= event->u.expose.width;
9911ab64890Smrg			ev->height	= event->u.expose.height;
9921ab64890Smrg			ev->count	= event->u.expose.count;
9931ab64890Smrg		}
9941ab64890Smrg		break;
9951ab64890Smrg	      case GraphicsExpose:
9961ab64890Smrg		{
9971ab64890Smrg		    register XGraphicsExposeEvent *ev =
9981ab64890Smrg			(XGraphicsExposeEvent *) re;
9991ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
10001ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
10011ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
10021ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
10031ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
10041ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
10051ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
10061ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
10071ab64890Smrg		}
10081ab64890Smrg		break;
10091ab64890Smrg	      case NoExpose:
10101ab64890Smrg		{
10111ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
10121ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
10131ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
10141ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
10151ab64890Smrg		}
10161ab64890Smrg		break;
10171ab64890Smrg	      case VisibilityNotify:
10181ab64890Smrg		{
10191ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
10201ab64890Smrg		    ev->window		= event->u.visibility.window;
10211ab64890Smrg		    ev->state		= event->u.visibility.state;
10221ab64890Smrg		}
10231ab64890Smrg		break;
10241ab64890Smrg	      case CreateNotify:
10251ab64890Smrg		{
10261ab64890Smrg		    register XCreateWindowEvent *ev =
10271ab64890Smrg			 (XCreateWindowEvent *) re;
10281ab64890Smrg		    ev->window		= event->u.createNotify.window;
10291ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
10301ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
10311ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
10321ab64890Smrg		    ev->width		= event->u.createNotify.width;
10331ab64890Smrg		    ev->height		= event->u.createNotify.height;
10341ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
10351ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
10361ab64890Smrg		}
10371ab64890Smrg		break;
10381ab64890Smrg	      case DestroyNotify:
10391ab64890Smrg		{
10401ab64890Smrg		    register XDestroyWindowEvent *ev =
10411ab64890Smrg				(XDestroyWindowEvent *) re;
10421ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
10431ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
10441ab64890Smrg		}
10451ab64890Smrg		break;
10461ab64890Smrg	      case UnmapNotify:
10471ab64890Smrg		{
10481ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
10491ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
10501ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
10511ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
10521ab64890Smrg		}
10531ab64890Smrg		break;
10541ab64890Smrg	      case MapNotify:
10551ab64890Smrg		{
10561ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
10571ab64890Smrg		    ev->window		= event->u.mapNotify.window;
10581ab64890Smrg		    ev->event		= event->u.mapNotify.event;
10591ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
10601ab64890Smrg		}
10611ab64890Smrg		break;
10621ab64890Smrg	      case MapRequest:
10631ab64890Smrg		{
10641ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
10651ab64890Smrg		    ev->window		= event->u.mapRequest.window;
10661ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
10671ab64890Smrg		}
10681ab64890Smrg		break;
10691ab64890Smrg	      case ReparentNotify:
10701ab64890Smrg		{
10711ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
10721ab64890Smrg		    ev->event		= event->u.reparent.event;
10731ab64890Smrg		    ev->window		= event->u.reparent.window;
10741ab64890Smrg		    ev->parent		= event->u.reparent.parent;
10751ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
10761ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
10771ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
10781ab64890Smrg		}
10791ab64890Smrg		break;
10801ab64890Smrg	      case ConfigureNotify:
10811ab64890Smrg		{
10821ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
10831ab64890Smrg		    ev->event	= event->u.configureNotify.event;
10841ab64890Smrg		    ev->window	= event->u.configureNotify.window;
10851ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
10861ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
10871ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
10881ab64890Smrg		    ev->width	= event->u.configureNotify.width;
10891ab64890Smrg		    ev->height	= event->u.configureNotify.height;
10901ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
10911ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
10921ab64890Smrg		}
10931ab64890Smrg		break;
10941ab64890Smrg	      case ConfigureRequest:
10951ab64890Smrg		{
10961ab64890Smrg		    register XConfigureRequestEvent *ev =
10971ab64890Smrg		        (XConfigureRequestEvent *) re;
10981ab64890Smrg		    ev->window		= event->u.configureRequest.window;
10991ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
11001ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
11011ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
11021ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
11031ab64890Smrg		    ev->width		= event->u.configureRequest.width;
11041ab64890Smrg		    ev->height		= event->u.configureRequest.height;
11051ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
11061ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
11071ab64890Smrg		    ev->detail  	= event->u.u.detail;
11081ab64890Smrg		}
11091ab64890Smrg		break;
11101ab64890Smrg	      case GravityNotify:
11111ab64890Smrg		{
11121ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
11131ab64890Smrg		    ev->window		= event->u.gravity.window;
11141ab64890Smrg		    ev->event		= event->u.gravity.event;
11151ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
11161ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
11171ab64890Smrg		}
11181ab64890Smrg		break;
11191ab64890Smrg	      case ResizeRequest:
11201ab64890Smrg		{
11211ab64890Smrg		    register XResizeRequestEvent *ev =
11221ab64890Smrg			(XResizeRequestEvent *) re;
11231ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
11241ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
11251ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
11261ab64890Smrg		}
11271ab64890Smrg		break;
11281ab64890Smrg	      case CirculateNotify:
11291ab64890Smrg		{
11301ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
11311ab64890Smrg		    ev->window		= event->u.circulate.window;
11321ab64890Smrg		    ev->event		= event->u.circulate.event;
11331ab64890Smrg		    ev->place		= event->u.circulate.place;
11341ab64890Smrg		}
11351ab64890Smrg		break;
11361ab64890Smrg	      case CirculateRequest:
11371ab64890Smrg		{
11381ab64890Smrg		    register XCirculateRequestEvent *ev =
11391ab64890Smrg		        (XCirculateRequestEvent *) re;
11401ab64890Smrg		    ev->window		= event->u.circulate.window;
11411ab64890Smrg		    ev->parent		= event->u.circulate.event;
11421ab64890Smrg		    ev->place		= event->u.circulate.place;
11431ab64890Smrg		}
11441ab64890Smrg		break;
11451ab64890Smrg	      case PropertyNotify:
11461ab64890Smrg		{
11471ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
11481ab64890Smrg		    ev->window		= event->u.property.window;
11491ab64890Smrg		    ev->atom		= event->u.property.atom;
11501ab64890Smrg		    ev->time		= event->u.property.time;
11511ab64890Smrg		    ev->state		= event->u.property.state;
11521ab64890Smrg		}
11531ab64890Smrg		break;
11541ab64890Smrg	      case SelectionClear:
11551ab64890Smrg		{
11561ab64890Smrg		    register XSelectionClearEvent *ev =
11571ab64890Smrg			 (XSelectionClearEvent *) re;
11581ab64890Smrg		    ev->window		= event->u.selectionClear.window;
11591ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
11601ab64890Smrg		    ev->time		= event->u.selectionClear.time;
11611ab64890Smrg		}
11621ab64890Smrg		break;
11631ab64890Smrg	      case SelectionRequest:
11641ab64890Smrg		{
11651ab64890Smrg		    register XSelectionRequestEvent *ev =
11661ab64890Smrg		        (XSelectionRequestEvent *) re;
11671ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
11681ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
11691ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
11701ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
11711ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
11721ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
11731ab64890Smrg		}
11741ab64890Smrg		break;
11751ab64890Smrg	      case SelectionNotify:
11761ab64890Smrg		{
11771ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
11781ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
11791ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
11801ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
11811ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
11821ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
11831ab64890Smrg		}
11841ab64890Smrg		break;
11851ab64890Smrg	      case ColormapNotify:
11861ab64890Smrg		{
11871ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
11881ab64890Smrg		    ev->window		= event->u.colormap.window;
11891ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
11901ab64890Smrg		    ev->new		= event->u.colormap.new;
11911ab64890Smrg		    ev->state		= event->u.colormap.state;
11921ab64890Smrg	        }
11931ab64890Smrg		break;
11941ab64890Smrg	      case ClientMessage:
11951ab64890Smrg		{
11961ab64890Smrg		   register int i;
119761b2299dSmrg		   register XClientMessageEvent *ev
11981ab64890Smrg		   			= (XClientMessageEvent *) re;
11991ab64890Smrg		   ev->window		= event->u.clientMessage.window;
12001ab64890Smrg		   ev->format		= event->u.u.detail;
12011ab64890Smrg		   switch (ev->format) {
120261b2299dSmrg			case 8:
12031ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
120461b2299dSmrg			   for (i = 0; i < 20; i++)
12051ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
12061ab64890Smrg			   break;
12071ab64890Smrg			case 16:
12081ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
12091ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
12101ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
12111ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
12121ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
12131ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
12141ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
12151ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
12161ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
12171ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
12181ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
12191ab64890Smrg			   break;
12201ab64890Smrg			case 32:
12211ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
12221ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
12231ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
12241ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
12251ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
12261ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
12271ab64890Smrg			   break;
12281ab64890Smrg			default: /* XXX should never occur */
12291ab64890Smrg				break;
12301ab64890Smrg		    }
12311ab64890Smrg	        }
12321ab64890Smrg		break;
12331ab64890Smrg	      case MappingNotify:
12341ab64890Smrg		{
12351ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
12361ab64890Smrg		   ev->window		= 0;
12371ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
12381ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
12391ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
12401ab64890Smrg		}
12411ab64890Smrg		break;
12421ab64890Smrg	      default:
12431ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
12441ab64890Smrg	}
12451ab64890Smrg	return(True);
12461ab64890Smrg}
12471ab64890Smrg
1248f2d49d05Smrgstatic int
1249f2d49d05SmrgSocketBytesReadable(Display *dpy)
1250f2d49d05Smrg{
1251f2d49d05Smrg    int bytes = 0, last_error;
1252f2d49d05Smrg#ifdef WIN32
1253f2d49d05Smrg    last_error = WSAGetLastError();
1254f2d49d05Smrg    ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
1255f2d49d05Smrg    WSASetLastError(last_error);
1256f2d49d05Smrg#else
1257f2d49d05Smrg    last_error = errno;
1258f2d49d05Smrg    ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
1259f2d49d05Smrg    errno = last_error;
1260f2d49d05Smrg#endif
1261f2d49d05Smrg    return bytes;
1262f2d49d05Smrg}
12631ab64890Smrg
126415c3e985Smrg_X_NORETURN void _XDefaultIOErrorExit(
126515c3e985Smrg	Display *dpy,
126615c3e985Smrg	void *user_data)
126715c3e985Smrg{
126815c3e985Smrg    exit(1);
126915c3e985Smrg    /*NOTREACHED*/
127015c3e985Smrg}
127115c3e985Smrg
12721ab64890Smrg/*
127361b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
12741ab64890Smrg * when an X internal system error is encountered.
12751ab64890Smrg */
1276bd8e7fb0Smrg_X_NORETURN int _XDefaultIOError(
12771ab64890Smrg	Display *dpy)
12781ab64890Smrg{
1279f2d49d05Smrg	int killed = ECHECK(EPIPE);
1280f2d49d05Smrg
1281f2d49d05Smrg	/*
1282f2d49d05Smrg	 * If the socket was closed on the far end, the final recvmsg in
1283f2d49d05Smrg	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
1284f2d49d05Smrg	 * this to get the more informative error message.
1285f2d49d05Smrg	 */
1286f2d49d05Smrg	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
1287f2d49d05Smrg	    killed = True;
1288f2d49d05Smrg
1289f2d49d05Smrg	if (killed) {
1290f2d49d05Smrg	    fprintf (stderr,
1291f2d49d05Smrg                     "X connection to %s broken (explicit kill or server shutdown).\r\n",
1292f2d49d05Smrg                     DisplayString (dpy));
12931ab64890Smrg	} else {
1294f2d49d05Smrg            fprintf (stderr,
1295f2d49d05Smrg                     "XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
12961ab64890Smrg#ifdef WIN32
1297f2d49d05Smrg                      WSAGetLastError(), strerror(WSAGetLastError()),
12981ab64890Smrg#else
1299f2d49d05Smrg                      errno, strerror (errno),
13001ab64890Smrg#endif
1301f2d49d05Smrg                      DisplayString (dpy));
1302f2d49d05Smrg	    fprintf (stderr,
1303f2d49d05Smrg		     "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
1304f2d49d05Smrg		     NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
1305f2d49d05Smrg		     QLength(dpy));
1306f2d49d05Smrg        }
13071ab64890Smrg
13081ab64890Smrg	exit(1);
1309dac667f7Smrg	/*NOTREACHED*/
13101ab64890Smrg}
13111ab64890Smrg
13121ab64890Smrg
13131ab64890Smrgstatic int _XPrintDefaultError(
13141ab64890Smrg    Display *dpy,
13151ab64890Smrg    XErrorEvent *event,
13161ab64890Smrg    FILE *fp)
13171ab64890Smrg{
13181ab64890Smrg    char buffer[BUFSIZ];
13191ab64890Smrg    char mesg[BUFSIZ];
13201ab64890Smrg    char number[32];
13211ab64890Smrg    const char *mtype = "XlibMessage";
13221ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
13231ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
13241ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
13251ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
13261ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
132761b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
13281ab64890Smrg	mesg, BUFSIZ);
13291ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
13301ab64890Smrg    if (event->request_code < 128) {
1331556b6652Smrg	snprintf(number, sizeof(number), "%d", event->request_code);
13321ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
13331ab64890Smrg    } else {
13341ab64890Smrg	for (ext = dpy->ext_procs;
13351ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
13361ab64890Smrg	     ext = ext->next)
13371ab64890Smrg	  ;
1338c17aa6b1Smrg	if (ext) {
1339c17aa6b1Smrg	    strncpy(buffer, ext->name, BUFSIZ);
1340c17aa6b1Smrg	    buffer[BUFSIZ - 1] = '\0';
1341c17aa6b1Smrg        } else
13421ab64890Smrg	    buffer[0] = '\0';
13431ab64890Smrg    }
13441ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
13451ab64890Smrg    if (event->request_code >= 128) {
13461ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
13471ab64890Smrg			      mesg, BUFSIZ);
13481ab64890Smrg	fputs("  ", fp);
13491ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
13501ab64890Smrg	if (ext) {
1351556b6652Smrg	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
13521ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
13531ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
13541ab64890Smrg	}
13551ab64890Smrg	fputs("\n", fp);
13561ab64890Smrg    }
13571ab64890Smrg    if (event->error_code >= 128) {
13581ab64890Smrg	/* kludge, try to find the extension that caused it */
13591ab64890Smrg	buffer[0] = '\0';
13601ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
136161b2299dSmrg	    if (ext->error_string)
13621ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
13631ab64890Smrg				     buffer, BUFSIZ);
13641ab64890Smrg	    if (buffer[0]) {
13651ab64890Smrg		bext = ext;
13661ab64890Smrg		break;
13671ab64890Smrg	    }
13681ab64890Smrg	    if (ext->codes.first_error &&
13691ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
13701ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
13711ab64890Smrg		bext = ext;
137261b2299dSmrg	}
13731ab64890Smrg	if (bext)
1374556b6652Smrg	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
1375556b6652Smrg                     event->error_code - bext->codes.first_error);
13761ab64890Smrg	else
13771ab64890Smrg	    strcpy(buffer, "Value");
13781ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
13791ab64890Smrg	if (mesg[0]) {
13801ab64890Smrg	    fputs("  ", fp);
13811ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
13821ab64890Smrg	    fputs("\n", fp);
13831ab64890Smrg	}
13841ab64890Smrg	/* let extensions try to print the values */
13851ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
13861ab64890Smrg	    if (ext->error_values)
13871ab64890Smrg		(*ext->error_values)(dpy, event, fp);
13881ab64890Smrg	}
13891ab64890Smrg    } else if ((event->error_code == BadWindow) ||
13901ab64890Smrg	       (event->error_code == BadPixmap) ||
13911ab64890Smrg	       (event->error_code == BadCursor) ||
13921ab64890Smrg	       (event->error_code == BadFont) ||
13931ab64890Smrg	       (event->error_code == BadDrawable) ||
13941ab64890Smrg	       (event->error_code == BadColor) ||
13951ab64890Smrg	       (event->error_code == BadGC) ||
13961ab64890Smrg	       (event->error_code == BadIDChoice) ||
13971ab64890Smrg	       (event->error_code == BadValue) ||
13981ab64890Smrg	       (event->error_code == BadAtom)) {
13991ab64890Smrg	if (event->error_code == BadValue)
14001ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
14011ab64890Smrg				  mesg, BUFSIZ);
14021ab64890Smrg	else if (event->error_code == BadAtom)
14031ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
14041ab64890Smrg				  mesg, BUFSIZ);
14051ab64890Smrg	else
14061ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
14071ab64890Smrg				  mesg, BUFSIZ);
14081ab64890Smrg	fputs("  ", fp);
14091ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
14101ab64890Smrg	fputs("\n", fp);
14111ab64890Smrg    }
141261b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
14131ab64890Smrg			  mesg, BUFSIZ);
14141ab64890Smrg    fputs("  ", fp);
14151ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
1416dac667f7Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
14171ab64890Smrg			  mesg, BUFSIZ);
14181ab64890Smrg    fputs("\n  ", fp);
1419dac667f7Smrg    (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
14201ab64890Smrg    fputs("\n", fp);
14211ab64890Smrg    if (event->error_code == BadImplementation) return 0;
14221ab64890Smrg    return 1;
14231ab64890Smrg}
14241ab64890Smrg
14251ab64890Smrgint _XDefaultError(
14261ab64890Smrg	Display *dpy,
14271ab64890Smrg	XErrorEvent *event)
14281ab64890Smrg{
14291ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
1430bd8e7fb0Smrg
1431bd8e7fb0Smrg    /*
1432bd8e7fb0Smrg     * Store in dpy flags that the client is exiting on an unhandled XError
1433bd8e7fb0Smrg     * (pretend it is an IOError, since the application is dying anyway it
1434bd8e7fb0Smrg     * does not make a difference).
1435bd8e7fb0Smrg     * This is useful for _XReply not to hang if the application makes Xlib
1436bd8e7fb0Smrg     * calls in _fini as part of process termination.
1437bd8e7fb0Smrg     */
1438bd8e7fb0Smrg    dpy->flags |= XlibDisplayIOError;
1439bd8e7fb0Smrg
14401ab64890Smrg    exit(1);
14411ab64890Smrg    /*NOTREACHED*/
14421ab64890Smrg}
14431ab64890Smrg
14441ab64890Smrg/*ARGSUSED*/
144561b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
14461ab64890Smrg{
14471ab64890Smrg    return True;
14481ab64890Smrg}
14491ab64890Smrg
14501ab64890Smrg/*
14511ab64890Smrg * _XError - upcall internal or user protocol error handler
14521ab64890Smrg */
14531ab64890Smrgint _XError (
14541ab64890Smrg    Display *dpy,
14551ab64890Smrg    register xError *rep)
14561ab64890Smrg{
145761b2299dSmrg    /*
14581ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
14591ab64890Smrg     * giving it to the user.
14601ab64890Smrg     */
14611ab64890Smrg    XEvent event; /* make it a large event */
14621ab64890Smrg    register _XAsyncHandler *async, *next;
14631ab64890Smrg
14641ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
14651ab64890Smrg
14661ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
14671ab64890Smrg	next = async->next;
14681ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
14691ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
14701ab64890Smrg	    return 0;
14711ab64890Smrg    }
14721ab64890Smrg
14731ab64890Smrg    event.xerror.display = dpy;
14741ab64890Smrg    event.xerror.type = X_Error;
14751ab64890Smrg    event.xerror.resourceid = rep->resourceID;
14761ab64890Smrg    event.xerror.error_code = rep->errorCode;
14771ab64890Smrg    event.xerror.request_code = rep->majorCode;
14781ab64890Smrg    event.xerror.minor_code = rep->minorCode;
14791ab64890Smrg    if (dpy->error_vec &&
14801ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
14811ab64890Smrg	return 0;
14821ab64890Smrg    if (_XErrorFunction != NULL) {
1483c17aa6b1Smrg	int rtn_val;
1484c17aa6b1Smrg#ifdef XTHREADS
148515c3e985Smrg	struct _XErrorThreadInfo thread_info = {
148615c3e985Smrg		.error_thread = xthread_self(),
148715c3e985Smrg		.next = dpy->error_threads
148815c3e985Smrg	}, **prev;
148915c3e985Smrg	dpy->error_threads = &thread_info;
1490c17aa6b1Smrg	if (dpy->lock)
1491c17aa6b1Smrg	    (*dpy->lock->user_lock_display)(dpy);
1492c17aa6b1Smrg	UnlockDisplay(dpy);
1493c17aa6b1Smrg#endif
1494c17aa6b1Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1495c17aa6b1Smrg#ifdef XTHREADS
1496c17aa6b1Smrg	LockDisplay(dpy);
1497c17aa6b1Smrg	if (dpy->lock)
1498c17aa6b1Smrg	    (*dpy->lock->user_unlock_display)(dpy);
149915c3e985Smrg
150015c3e985Smrg	/* unlink thread_info from the list */
150115c3e985Smrg	for (prev = &dpy->error_threads; *prev != &thread_info; prev = &(*prev)->next)
150215c3e985Smrg		;
150315c3e985Smrg	*prev = thread_info.next;
1504c17aa6b1Smrg#endif
1505c17aa6b1Smrg	return rtn_val;
15061ab64890Smrg    } else {
15071ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
15081ab64890Smrg    }
15091ab64890Smrg}
151061b2299dSmrg
15111ab64890Smrg/*
15121ab64890Smrg * _XIOError - call user connection error handler and exit
15131ab64890Smrg */
15141ab64890Smrgint
15151ab64890Smrg_XIOError (
15161ab64890Smrg    Display *dpy)
15171ab64890Smrg{
151815c3e985Smrg    XIOErrorExitHandler exit_handler;
151915c3e985Smrg    void *exit_handler_data;
152015c3e985Smrg
15211ab64890Smrg    dpy->flags |= XlibDisplayIOError;
15221ab64890Smrg#ifdef WIN32
15231ab64890Smrg    errno = WSAGetLastError();
15241ab64890Smrg#endif
15251ab64890Smrg
15261ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
15271ab64890Smrg     * If this does not hold, then an alternate solution would involve
15281ab64890Smrg     * registering an atexit handler to take over the lock, which would only
15291ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
15301ab64890Smrg#ifdef XTHREADS
15311ab64890Smrg    if (dpy->lock)
15321ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
15331ab64890Smrg#endif
153415c3e985Smrg    exit_handler = dpy->exit_handler;
153515c3e985Smrg    exit_handler_data = dpy->exit_handler_data;
15361ab64890Smrg    UnlockDisplay(dpy);
15371ab64890Smrg
15381ab64890Smrg    if (_XIOErrorFunction != NULL)
15391ab64890Smrg	(*_XIOErrorFunction)(dpy);
15401ab64890Smrg    else
15411ab64890Smrg	_XDefaultIOError(dpy);
154215c3e985Smrg
154315c3e985Smrg    exit_handler(dpy, exit_handler_data);
154415c3e985Smrg    return 1;
15451ab64890Smrg}
15461ab64890Smrg
15471ab64890Smrg
15481ab64890Smrg/*
15491ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
15501ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
15511ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
15521ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
15531ab64890Smrg * is guaranteed to not unlock the display.
15541ab64890Smrg */
15551ab64890Smrgchar *_XAllocScratch(
15561ab64890Smrg	register Display *dpy,
15571ab64890Smrg	unsigned long nbytes)
15581ab64890Smrg{
15591ab64890Smrg	if (nbytes > dpy->scratch_length) {
1560cf2acddeSmrg	    Xfree (dpy->scratch_buffer);
1561cf2acddeSmrg	    dpy->scratch_buffer = Xmalloc(nbytes);
1562cf2acddeSmrg	    if (dpy->scratch_buffer)
15631ab64890Smrg		dpy->scratch_length = nbytes;
15641ab64890Smrg	    else dpy->scratch_length = 0;
15651ab64890Smrg	}
15661ab64890Smrg	return (dpy->scratch_buffer);
15671ab64890Smrg}
15681ab64890Smrg
15691ab64890Smrg/*
15701ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
15711ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
15721ab64890Smrg */
15731ab64890Smrgchar *_XAllocTemp(
15741ab64890Smrg    register Display *dpy,
15751ab64890Smrg    unsigned long nbytes)
15761ab64890Smrg{
15771ab64890Smrg    char *buf;
15781ab64890Smrg
15791ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
15801ab64890Smrg    dpy->scratch_buffer = NULL;
15811ab64890Smrg    dpy->scratch_length = 0;
15821ab64890Smrg    return buf;
15831ab64890Smrg}
15841ab64890Smrg
15851ab64890Smrgvoid _XFreeTemp(
15861ab64890Smrg    register Display *dpy,
15871ab64890Smrg    char *buf,
15881ab64890Smrg    unsigned long nbytes)
15891ab64890Smrg{
1590cf2acddeSmrg
1591cf2acddeSmrg    Xfree(dpy->scratch_buffer);
15921ab64890Smrg    dpy->scratch_buffer = buf;
15931ab64890Smrg    dpy->scratch_length = nbytes;
15941ab64890Smrg}
15951ab64890Smrg
15961ab64890Smrg/*
15971ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
15981ab64890Smrg */
15991ab64890SmrgVisual *_XVIDtoVisual(
16001ab64890Smrg	Display *dpy,
16011ab64890Smrg	VisualID id)
16021ab64890Smrg{
16031ab64890Smrg	register int i, j, k;
16041ab64890Smrg	register Screen *sp;
16051ab64890Smrg	register Depth *dp;
16061ab64890Smrg	register Visual *vp;
16071ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
16081ab64890Smrg		sp = &dpy->screens[i];
16091ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
16101ab64890Smrg			dp = &sp->depths[j];
16111ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
16121ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
16131ab64890Smrg				vp = &dp->visuals[k];
16141ab64890Smrg				if (vp->visualid == id) return (vp);
16151ab64890Smrg			}
16161ab64890Smrg		}
16171ab64890Smrg	}
16181ab64890Smrg	return (NULL);
16191ab64890Smrg}
16201ab64890Smrg
16211ab64890Smrgint
16221ab64890SmrgXFree (void *data)
16231ab64890Smrg{
16241ab64890Smrg	Xfree (data);
16251ab64890Smrg	return 1;
16261ab64890Smrg}
16271ab64890Smrg
16281ab64890Smrg#ifdef _XNEEDBCOPYFUNC
16291ab64890Smrgvoid _Xbcopy(b1, b2, length)
16301ab64890Smrg    register char *b1, *b2;
16311ab64890Smrg    register length;
16321ab64890Smrg{
16331ab64890Smrg    if (b1 < b2) {
16341ab64890Smrg	b2 += length;
16351ab64890Smrg	b1 += length;
16361ab64890Smrg	while (length--)
16371ab64890Smrg	    *--b2 = *--b1;
16381ab64890Smrg    } else {
16391ab64890Smrg	while (length--)
16401ab64890Smrg	    *b2++ = *b1++;
16411ab64890Smrg    }
16421ab64890Smrg}
16431ab64890Smrg#endif
16441ab64890Smrg
16451ab64890Smrg#ifdef DataRoutineIsProcedure
16461ab64890Smrgvoid Data(
16471ab64890Smrg	Display *dpy,
1648556b6652Smrg	_Xconst char *data,
16491ab64890Smrg	long len)
16501ab64890Smrg{
16511ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
16521ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
16531ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
16541ab64890Smrg	} else {
16551ab64890Smrg		_XSend(dpy, data, len);
16561ab64890Smrg	}
16571ab64890Smrg}
16581ab64890Smrg#endif /* DataRoutineIsProcedure */
16591ab64890Smrg
16601ab64890Smrg
16611ab64890Smrg#ifdef LONG64
16621ab64890Smrgint
16631ab64890Smrg_XData32(
16641ab64890Smrg    Display *dpy,
166515c3e985Smrg    _Xconst long *data,
16661ab64890Smrg    unsigned len)
16671ab64890Smrg{
16681ab64890Smrg    register int *buf;
16691ab64890Smrg    register long i;
16701ab64890Smrg
16711ab64890Smrg    while (len) {
16721ab64890Smrg	buf = (int *)dpy->bufptr;
16731ab64890Smrg	i = dpy->bufmax - (char *)buf;
16741ab64890Smrg	if (!i) {
16751ab64890Smrg	    _XFlush(dpy);
16761ab64890Smrg	    continue;
16771ab64890Smrg	}
16781ab64890Smrg	if (len < i)
16791ab64890Smrg	    i = len;
16801ab64890Smrg	dpy->bufptr = (char *)buf + i;
16811ab64890Smrg	len -= i;
16821ab64890Smrg	i >>= 2;
16831ab64890Smrg	while (--i >= 0)
16841ab64890Smrg	    *buf++ = *data++;
16851ab64890Smrg    }
16861ab64890Smrg    return 0;
16871ab64890Smrg}
16881ab64890Smrg#endif /* LONG64 */
16891ab64890Smrg
16901ab64890Smrg
16911ab64890Smrg
16921ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
16931ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
16941ab64890Smrg *
16951ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
16961ab64890Smrg *       to have sufficient information for interfacing to the network,
16971ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
16981ab64890Smrg */
16991ab64890Smrg
1700c6e579a2Smrg#if defined(_POSIX_SOURCE) || defined(SVR4)
17011ab64890Smrg#define NEED_UTSNAME
17021ab64890Smrg#include <sys/utsname.h>
170388de56ccSmrg#else
170488de56ccSmrg#ifdef HAVE_UNISTD_H
170588de56ccSmrg#include <unistd.h>
170688de56ccSmrg#endif
17071ab64890Smrg#endif
17081ab64890Smrg
17091ab64890Smrg/*
17101ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
17111ab64890Smrg */
17121ab64890Smrgint _XGetHostname (
17131ab64890Smrg    char *buf,
17141ab64890Smrg    int maxlen)
17151ab64890Smrg{
17161ab64890Smrg    int len;
17171ab64890Smrg
17181ab64890Smrg#ifdef NEED_UTSNAME
17191ab64890Smrg    struct utsname name;
17201ab64890Smrg
17211ab64890Smrg    if (maxlen <= 0 || buf == NULL)
17221ab64890Smrg	return 0;
17231ab64890Smrg
17241ab64890Smrg    uname (&name);
1725e90f245cSmaya    len = (int) strlen (name.nodename);
17261ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
1727e90f245cSmaya    strncpy (buf, name.nodename, (size_t) len);
17281ab64890Smrg    buf[len] = '\0';
17291ab64890Smrg#else
17301ab64890Smrg    if (maxlen <= 0 || buf == NULL)
17311ab64890Smrg	return 0;
17321ab64890Smrg
17331ab64890Smrg    buf[0] = '\0';
17341ab64890Smrg    (void) gethostname (buf, maxlen);
17351ab64890Smrg    buf [maxlen - 1] = '\0';
1736e90f245cSmaya    len = (int) strlen(buf);
17371ab64890Smrg#endif /* NEED_UTSNAME */
17381ab64890Smrg    return len;
17391ab64890Smrg}
17401ab64890Smrg
17411ab64890Smrg
17421ab64890Smrg/*
17431ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
17441ab64890Smrg */
17451ab64890Smrg
174661b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
17471ab64890Smrg{
17481ab64890Smrg    register int i;
17491ab64890Smrg    Window root;
17501ab64890Smrg    int x, y;				/* dummy variables */
17511ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
17521ab64890Smrg
17531ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
17541ab64890Smrg		      &bw, &depth) == False) {
17552e9c7c8cSmrg	return NULL;
17561ab64890Smrg    }
17571ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
17581ab64890Smrg	if (root == RootWindow (dpy, i)) {
17591ab64890Smrg	    return ScreenOfDisplay (dpy, i);
17601ab64890Smrg	}
17611ab64890Smrg    }
17621ab64890Smrg    return NULL;
17631ab64890Smrg}
17641ab64890Smrg
17651ab64890Smrg
1766556b6652Smrg/*
1767556b6652Smrg * WARNING: This implementation's pre-conditions and post-conditions
1768556b6652Smrg * must remain compatible with the old macro-based implementations of
1769556b6652Smrg * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1770556b6652Smrg * Display structure affected by those macros are part of libX11's
1771556b6652Smrg * ABI.
1772556b6652Smrg */
1773556b6652Smrgvoid *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1774556b6652Smrg{
1775556b6652Smrg    xReq *req;
1776556b6652Smrg
1777556b6652Smrg    if (dpy->bufptr + len > dpy->bufmax)
1778556b6652Smrg	_XFlush(dpy);
1779c555af55Smrg    /* Request still too large, so do not allow it to overflow. */
1780c555af55Smrg    if (dpy->bufptr + len > dpy->bufmax) {
1781c555af55Smrg	fprintf(stderr,
1782c555af55Smrg		"Xlib: request %d length %zd would exceed buffer size.\n",
1783c555af55Smrg		type, len);
1784c555af55Smrg	/* Changes failure condition from overflow to NULL dereference. */
1785c555af55Smrg	return NULL;
1786c555af55Smrg    }
1787556b6652Smrg
1788556b6652Smrg    if (len % 4)
1789556b6652Smrg	fprintf(stderr,
1790556b6652Smrg		"Xlib: request %d length %zd not a multiple of 4.\n",
1791556b6652Smrg		type, len);
1792556b6652Smrg
1793556b6652Smrg    dpy->last_req = dpy->bufptr;
1794556b6652Smrg
1795556b6652Smrg    req = (xReq*)dpy->bufptr;
1796d5e6aabbSmrg    *req = (xReq) {
1797d5e6aabbSmrg        .reqType = type,
1798d5e6aabbSmrg        .data = 0,
1799d5e6aabbSmrg        .length = len / 4
1800d5e6aabbSmrg    };
1801556b6652Smrg    dpy->bufptr += len;
1802dac667f7Smrg    X_DPY_REQUEST_INCREMENT(dpy);
1803556b6652Smrg    return req;
1804556b6652Smrg}
1805556b6652Smrg
18061ab64890Smrg#if defined(WIN32)
18071ab64890Smrg
18081ab64890Smrg/*
18091ab64890Smrg * These functions are intended to be used internally to Xlib only.
18101ab64890Smrg * These functions will always prefix the path with a DOS drive in the
18111ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
18121ab64890Smrg * for use by Xlib function that supply a root-based path to some
18131ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
18141ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
18151ab64890Smrg */
18161ab64890Smrg
18171ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
18181ab64890Smrg    char* path;
18191ab64890Smrg    char* pathbuf;
18201ab64890Smrg    int len_pathbuf;
18211ab64890Smrg    char** pathret;
18221ab64890Smrg{
18231ab64890Smrg    if (access (path, F_OK) == 0) {
18241ab64890Smrg	if (strlen (path) < len_pathbuf)
18251ab64890Smrg	    *pathret = pathbuf;
18261ab64890Smrg	else
18271ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
18281ab64890Smrg	if (*pathret) {
18291ab64890Smrg	    strcpy (*pathret, path);
18301ab64890Smrg	    return 1;
18311ab64890Smrg	}
18321ab64890Smrg    }
18331ab64890Smrg    return 0;
18341ab64890Smrg}
18351ab64890Smrg
18361ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
18371ab64890Smrg    char* path;
18381ab64890Smrg    char* pathbuf;
18391ab64890Smrg    int len_pathbuf;
18401ab64890Smrg    char** pathret;
18411ab64890Smrg{
18421ab64890Smrg    unsigned long drives;
18431ab64890Smrg    int i, len;
18441ab64890Smrg    char* drive;
18451ab64890Smrg    char buf[MAX_PATH];
18461ab64890Smrg    char* bufp;
18471ab64890Smrg
18481ab64890Smrg    /* just try the "raw" name first and see if it works */
18491ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
18501ab64890Smrg	return 1;
18511ab64890Smrg
18521ab64890Smrg    /* try the places set in the environment */
18531ab64890Smrg    drive = getenv ("_XBASEDRIVE");
18541ab64890Smrg    if (!drive)
18551ab64890Smrg	drive = "C:";
18561ab64890Smrg    len = strlen (drive) + strlen (path);
18571ab64890Smrg    if (len < MAX_PATH) bufp = buf;
18581ab64890Smrg    else bufp = Xmalloc (len + 1);
18591ab64890Smrg    strcpy (bufp, drive);
18601ab64890Smrg    strcat (bufp, path);
18611ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18621ab64890Smrg	if (bufp != buf) Xfree (bufp);
18631ab64890Smrg	return 1;
18641ab64890Smrg    }
18651ab64890Smrg
18661ab64890Smrg    /* one last place to look */
18671ab64890Smrg    drive = getenv ("HOMEDRIVE");
18681ab64890Smrg    if (drive) {
18691ab64890Smrg	len = strlen (drive) + strlen (path);
18701ab64890Smrg	if (len < MAX_PATH) bufp = buf;
18711ab64890Smrg	else bufp = Xmalloc (len + 1);
18721ab64890Smrg	strcpy (bufp, drive);
18731ab64890Smrg	strcat (bufp, path);
18741ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18751ab64890Smrg	    if (bufp != buf) Xfree (bufp);
18761ab64890Smrg	    return 1;
18771ab64890Smrg	}
18781ab64890Smrg    }
18791ab64890Smrg
18801ab64890Smrg    /* tried everywhere else, go fishing */
18811ab64890Smrg#define C_DRIVE ('C' - 'A')
18821ab64890Smrg#define Z_DRIVE ('Z' - 'A')
18831ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
18841ab64890Smrg    drives = _getdrives ();
18851ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
18861ab64890Smrg	if ((1 << i) & drives) {
18871ab64890Smrg	    len = 2 + strlen (path);
18881ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
18891ab64890Smrg	    else bufp = Xmalloc (len + 1);
18901ab64890Smrg	    *bufp = 'A' + i;
18911ab64890Smrg	    *(bufp + 1) = ':';
18921ab64890Smrg	    *(bufp + 2) = '\0';
18931ab64890Smrg	    strcat (bufp, path);
18941ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18951ab64890Smrg		if (bufp != buf) Xfree (bufp);
18961ab64890Smrg		return 1;
18971ab64890Smrg	    }
18981ab64890Smrg	}
18991ab64890Smrg    }
19001ab64890Smrg    return 0;
19011ab64890Smrg}
19021ab64890Smrg
19031ab64890Smrgint _XOpenFile(path, flags)
19041ab64890Smrg    _Xconst char* path;
19051ab64890Smrg    int flags;
19061ab64890Smrg{
19071ab64890Smrg    char buf[MAX_PATH];
19081ab64890Smrg    char* bufp = NULL;
19091ab64890Smrg    int ret = -1;
19101ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19111ab64890Smrg
19121ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19131ab64890Smrg	ret = open (bufp, flags);
19141ab64890Smrg
19151ab64890Smrg    (void) SetErrorMode (olderror);
19161ab64890Smrg
19171ab64890Smrg    if (bufp != buf) Xfree (bufp);
19181ab64890Smrg
19191ab64890Smrg    return ret;
19201ab64890Smrg}
19211ab64890Smrg
19221ab64890Smrgint _XOpenFileMode(path, flags, mode)
19231ab64890Smrg    _Xconst char* path;
19241ab64890Smrg    int flags;
19251ab64890Smrg    mode_t mode;
19261ab64890Smrg{
19271ab64890Smrg    char buf[MAX_PATH];
19281ab64890Smrg    char* bufp = NULL;
19291ab64890Smrg    int ret = -1;
19301ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19311ab64890Smrg
19321ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19331ab64890Smrg	ret = open (bufp, flags, mode);
19341ab64890Smrg
19351ab64890Smrg    (void) SetErrorMode (olderror);
19361ab64890Smrg
19371ab64890Smrg    if (bufp != buf) Xfree (bufp);
19381ab64890Smrg
19391ab64890Smrg    return ret;
19401ab64890Smrg}
19411ab64890Smrg
19421ab64890Smrgvoid* _XFopenFile(path, mode)
19431ab64890Smrg    _Xconst char* path;
19441ab64890Smrg    _Xconst char* mode;
19451ab64890Smrg{
19461ab64890Smrg    char buf[MAX_PATH];
19471ab64890Smrg    char* bufp = NULL;
19481ab64890Smrg    void* ret = NULL;
19491ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19501ab64890Smrg
19511ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
19521ab64890Smrg	ret = fopen (bufp, mode);
19531ab64890Smrg
19541ab64890Smrg    (void) SetErrorMode (olderror);
19551ab64890Smrg
19561ab64890Smrg    if (bufp != buf) Xfree (bufp);
19571ab64890Smrg
19581ab64890Smrg    return ret;
19591ab64890Smrg}
19601ab64890Smrg
19611ab64890Smrgint _XAccessFile(path)
19621ab64890Smrg    _Xconst char* path;
19631ab64890Smrg{
19641ab64890Smrg    char buf[MAX_PATH];
19651ab64890Smrg    char* bufp;
19661ab64890Smrg    int ret = -1;
19671ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19681ab64890Smrg
19691ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
19701ab64890Smrg
19711ab64890Smrg    (void) SetErrorMode (olderror);
19721ab64890Smrg
19731ab64890Smrg    if (bufp != buf) Xfree (bufp);
19741ab64890Smrg
19751ab64890Smrg    return ret;
19761ab64890Smrg}
19771ab64890Smrg
19781ab64890Smrg#endif
19791ab64890Smrg
19801ab64890Smrg#ifdef WIN32
19811ab64890Smrg#undef _Xdebug
19821ab64890Smrgint _Xdebug = 0;
19831ab64890Smrgint *_Xdebug_p = &_Xdebug;
19841ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
19851ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
19861ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
19871ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19881ab64890Smrg    , char * /* file */
19891ab64890Smrg    , int /* line */
19901ab64890Smrg#endif
19911ab64890Smrg        ) = &_XLockMutex_fn;
19921ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
19931ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19941ab64890Smrg    , char * /* file */
19951ab64890Smrg    , int /* line */
19961ab64890Smrg#endif
19971ab64890Smrg        ) = &_XUnlockMutex_fn;
19981ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
19991ab64890Smrg#endif
2000