XlibInt.c revision bd8e7fb0
11ab64890Smrg/*
21ab64890Smrg
31ab64890SmrgCopyright 1985, 1986, 1987, 1998  The Open Group
41ab64890Smrg
51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
71ab64890Smrgthe above copyright notice appear in all copies and that both that
81ab64890Smrgcopyright notice and this permission notice appear in supporting
91ab64890Smrgdocumentation.
101ab64890Smrg
111ab64890SmrgThe above copyright notice and this permission notice shall be included
121ab64890Smrgin all copies or substantial portions of the Software.
131ab64890Smrg
141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE.
211ab64890Smrg
221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall
231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or
241ab64890Smrgother dealings in this Software without prior written authorization
251ab64890Smrgfrom The Open Group.
261ab64890Smrg
271ab64890Smrg*/
281ab64890Smrg
291ab64890Smrg/*
301ab64890Smrg *	XlibInt.c - Internal support routines for the C subroutine
311ab64890Smrg *	interface library (Xlib) to the X Window System Protocol V11.0.
321ab64890Smrg */
331ab64890Smrg
341ab64890Smrg#ifdef WIN32
351ab64890Smrg#define _XLIBINT_
361ab64890Smrg#endif
371ab64890Smrg#ifdef HAVE_CONFIG_H
381ab64890Smrg#include <config.h>
391ab64890Smrg#endif
401ab64890Smrg#include "Xlibint.h"
4161b2299dSmrg#include "Xprivate.h"
421ab64890Smrg#include <X11/Xpoll.h>
4361b2299dSmrg#include <assert.h>
441ab64890Smrg#include <stdio.h>
451ab64890Smrg#ifdef WIN32
461ab64890Smrg#include <direct.h>
471ab64890Smrg#endif
481ab64890Smrg
491ab64890Smrg#ifdef XTHREADS
501ab64890Smrg#include "locking.h"
511ab64890Smrg
521ab64890Smrg/* these pointers get initialized by XInitThreads */
531ab64890SmrgLockInfoPtr _Xglobal_lock = NULL;
541ab64890Smrgvoid (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
551ab64890Smrg/* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
561ab64890Smrgvoid (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
571ab64890Smrgvoid (*_XLockMutex_fn)(
581ab64890Smrg    LockInfoPtr /* lock */
591ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
601ab64890Smrg    , char * /* file */
611ab64890Smrg    , int /* line */
621ab64890Smrg#endif
631ab64890Smrg    ) = NULL;
641ab64890Smrgvoid (*_XUnlockMutex_fn)(
651ab64890Smrg    LockInfoPtr /* lock */
661ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
671ab64890Smrg    , char * /* file */
681ab64890Smrg    , int /* line */
691ab64890Smrg#endif
701ab64890Smrg    ) = NULL;
711ab64890Smrgxthread_t (*_Xthread_self_fn)(void) = NULL;
721ab64890Smrg
731ab64890Smrg#define XThread_Self()	((*_Xthread_self_fn)())
741ab64890Smrg
75295fb823Smrg#endif /* XTHREADS */
761ab64890Smrg
771ab64890Smrg#ifdef WIN32
781ab64890Smrg#define ECHECK(err) (WSAGetLastError() == err)
791ab64890Smrg#define ESET(val) WSASetLastError(val)
801ab64890Smrg#else
811ab64890Smrg#ifdef __UNIXOS2__
821ab64890Smrg#define ECHECK(err) (errno == err)
831ab64890Smrg#define ESET(val)
841ab64890Smrg#else
851ab64890Smrg#define ECHECK(err) (errno == err)
861ab64890Smrg#define ESET(val) errno = val
871ab64890Smrg#endif
881ab64890Smrg#endif
891ab64890Smrg
901ab64890Smrg#ifdef __UNIXOS2__
911ab64890Smrg#include <limits.h>
921ab64890Smrg#define MAX_PATH _POSIX_PATH_MAX
931ab64890Smrg#endif
941ab64890Smrg
951ab64890Smrg/*
961ab64890Smrg * The following routines are internal routines used by Xlib for protocol
971ab64890Smrg * packet transmission and reception.
981ab64890Smrg *
991ab64890Smrg * _XIOError(Display *) will be called if any sort of system call error occurs.
1001ab64890Smrg * This is assumed to be a fatal condition, i.e., XIOError should not return.
1011ab64890Smrg *
1021ab64890Smrg * _XError(Display *, xError *) will be called whenever an X_Error event is
1031ab64890Smrg * received.  This is not assumed to be a fatal condition, i.e., it is
1041ab64890Smrg * acceptable for this procedure to return.  However, XError should NOT
1051ab64890Smrg * perform any operations (directly or indirectly) on the DISPLAY.
1061ab64890Smrg *
1071ab64890Smrg * Routines declared with a return type of 'Status' return 0 on failure,
10861b2299dSmrg * and non 0 on success.  Routines with no declared return type don't
1091ab64890Smrg * return anything.  Whenever possible routines that create objects return
1101ab64890Smrg * the object they have created.
1111ab64890Smrg */
1121ab64890Smrg
1131ab64890Smrg#define POLLFD_CACHE_SIZE 5
1141ab64890Smrg
1151ab64890Smrg/* initialize the struct array passed to poll() below */
1161ab64890SmrgBool _XPollfdCacheInit(
1171ab64890Smrg    Display *dpy)
1181ab64890Smrg{
1191ab64890Smrg#ifdef USE_POLL
1201ab64890Smrg    struct pollfd *pfp;
1211ab64890Smrg
122556b6652Smrg    pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
1231ab64890Smrg    if (!pfp)
1241ab64890Smrg	return False;
1251ab64890Smrg    pfp[0].fd = dpy->fd;
1261ab64890Smrg    pfp[0].events = POLLIN;
1271ab64890Smrg
1281ab64890Smrg    dpy->filedes = (XPointer)pfp;
1291ab64890Smrg#endif
1301ab64890Smrg    return True;
1311ab64890Smrg}
1321ab64890Smrg
1331ab64890Smrgvoid _XPollfdCacheAdd(
1341ab64890Smrg    Display *dpy,
1351ab64890Smrg    int fd)
1361ab64890Smrg{
1371ab64890Smrg#ifdef USE_POLL
1381ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1391ab64890Smrg
1401ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1411ab64890Smrg	pfp[dpy->im_fd_length].fd = fd;
1421ab64890Smrg	pfp[dpy->im_fd_length].events = POLLIN;
1431ab64890Smrg    }
1441ab64890Smrg#endif
1451ab64890Smrg}
1461ab64890Smrg
1471ab64890Smrg/* ARGSUSED */
1481ab64890Smrgvoid _XPollfdCacheDel(
1491ab64890Smrg    Display *dpy,
1501ab64890Smrg    int fd)			/* not used */
1511ab64890Smrg{
1521ab64890Smrg#ifdef USE_POLL
1531ab64890Smrg    struct pollfd *pfp = (struct pollfd *)dpy->filedes;
1541ab64890Smrg    struct _XConnectionInfo *conni;
1551ab64890Smrg
1561ab64890Smrg    /* just recalculate whole list */
1571ab64890Smrg    if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
1581ab64890Smrg	int loc = 1;
1591ab64890Smrg	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
1601ab64890Smrg	    pfp[loc].fd = conni->fd;
1611ab64890Smrg	    pfp[loc].events = POLLIN;
1621ab64890Smrg	    loc++;
1631ab64890Smrg	}
1641ab64890Smrg    }
1651ab64890Smrg#endif
1661ab64890Smrg}
1671ab64890Smrg
16861b2299dSmrgstatic int sync_hazard(Display *dpy)
16961b2299dSmrg{
170dac667f7Smrg    /*
171dac667f7Smrg     * "span" and "hazard" need to be signed such that the ">=" comparision
172dac667f7Smrg     * works correctly in the case that hazard is greater than 65525
173dac667f7Smrg     */
174dac667f7Smrg    int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
175dac667f7Smrg    int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
17661b2299dSmrg    return span >= 65535 - hazard - 10;
17761b2299dSmrg}
17861b2299dSmrg
1791ab64890Smrgstatic
18088de56ccSmrgvoid sync_while_locked(Display *dpy)
18188de56ccSmrg{
18288de56ccSmrg#ifdef XTHREADS
18388de56ccSmrg    if (dpy->lock)
18488de56ccSmrg        (*dpy->lock->user_lock_display)(dpy);
18588de56ccSmrg#endif
18688de56ccSmrg    UnlockDisplay(dpy);
18788de56ccSmrg    SyncHandle();
18888de56ccSmrg    InternalLockDisplay(dpy, /* don't skip user locks */ 0);
18988de56ccSmrg#ifdef XTHREADS
19088de56ccSmrg    if (dpy->lock)
19188de56ccSmrg        (*dpy->lock->user_unlock_display)(dpy);
19288de56ccSmrg#endif
19388de56ccSmrg}
19488de56ccSmrg
19588de56ccSmrgvoid _XSeqSyncFunction(
1961ab64890Smrg    register Display *dpy)
1971ab64890Smrg{
1981ab64890Smrg    xGetInputFocusReply rep;
199bd8e7fb0Smrg    _X_UNUSED register xReq *req;
2001ab64890Smrg
201dac667f7Smrg    if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
2021ab64890Smrg	GetEmptyReq(GetInputFocus, req);
2031ab64890Smrg	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
20488de56ccSmrg	sync_while_locked(dpy);
20561b2299dSmrg    } else if (sync_hazard(dpy))
20661b2299dSmrg	_XSetPrivSyncFunction(dpy);
2071ab64890Smrg}
2081ab64890Smrg
20988de56ccSmrg/* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
21061b2299dSmrgstatic int
21161b2299dSmrg_XPrivSyncFunction (Display *dpy)
21261b2299dSmrg{
213e0787e08Smrg#ifdef XTHREADS
21488de56ccSmrg    assert(!dpy->lock_fns);
21588de56ccSmrg#endif
21661b2299dSmrg    assert(dpy->synchandler == _XPrivSyncFunction);
21761b2299dSmrg    assert((dpy->flags & XlibDisplayPrivSync) != 0);
21861b2299dSmrg    dpy->synchandler = dpy->savedsynchandler;
21961b2299dSmrg    dpy->savedsynchandler = NULL;
22061b2299dSmrg    dpy->flags &= ~XlibDisplayPrivSync;
22188de56ccSmrg    if(dpy->synchandler)
22288de56ccSmrg        dpy->synchandler(dpy);
22361b2299dSmrg    _XIDHandler(dpy);
22461b2299dSmrg    _XSeqSyncFunction(dpy);
22561b2299dSmrg    return 0;
22661b2299dSmrg}
22761b2299dSmrg
22861b2299dSmrgvoid _XSetPrivSyncFunction(Display *dpy)
2291ab64890Smrg{
23088de56ccSmrg#ifdef XTHREADS
23188de56ccSmrg    if (dpy->lock_fns)
23288de56ccSmrg        return;
23388de56ccSmrg#endif
23461b2299dSmrg    if (!(dpy->flags & XlibDisplayPrivSync)) {
2351ab64890Smrg	dpy->savedsynchandler = dpy->synchandler;
23661b2299dSmrg	dpy->synchandler = _XPrivSyncFunction;
2371ab64890Smrg	dpy->flags |= XlibDisplayPrivSync;
2381ab64890Smrg    }
2391ab64890Smrg}
2401ab64890Smrg
24161b2299dSmrgvoid _XSetSeqSyncFunction(Display *dpy)
24261b2299dSmrg{
24361b2299dSmrg    if (sync_hazard(dpy))
24461b2299dSmrg	_XSetPrivSyncFunction (dpy);
24561b2299dSmrg}
24661b2299dSmrg
2471ab64890Smrg#ifdef LONG64
2481ab64890Smrgvoid _XRead32(
2491ab64890Smrg    Display *dpy,
2501ab64890Smrg    register long *data,
2511ab64890Smrg    long len)
2521ab64890Smrg{
2531ab64890Smrg    register int *buf;
2541ab64890Smrg    register long i;
2551ab64890Smrg
2561ab64890Smrg    if (len) {
2571ab64890Smrg	(void) _XRead(dpy, (char *)data, len);
2581ab64890Smrg	i = len >> 2;
2591ab64890Smrg	buf = (int *)data + i;
2601ab64890Smrg	data += i;
2611ab64890Smrg	while (--i >= 0)
2621ab64890Smrg	    *--data = *--buf;
2631ab64890Smrg    }
2641ab64890Smrg}
2651ab64890Smrg#endif /* LONG64 */
2661ab64890Smrg
2671ab64890Smrg
2681ab64890Smrg/*
2691ab64890Smrg * The hard part about this is that we only get 16 bits from a reply.
2701ab64890Smrg * We have three values that will march along, with the following invariant:
2711ab64890Smrg *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
2721ab64890Smrg * We have to keep
2731ab64890Smrg *	dpy->request - dpy->last_request_read < 2^16
2741ab64890Smrg * or else we won't know for sure what value to use in events.  We do this
2751ab64890Smrg * by forcing syncs when we get close.
2761ab64890Smrg */
2771ab64890Smrg
2781ab64890Smrgunsigned long
2791ab64890Smrg_XSetLastRequestRead(
2801ab64890Smrg    register Display *dpy,
2811ab64890Smrg    register xGenericReply *rep)
2821ab64890Smrg{
283dac667f7Smrg    register uint64_t	newseq, lastseq;
2841ab64890Smrg
285dac667f7Smrg    lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
2861ab64890Smrg    /*
2871ab64890Smrg     * KeymapNotify has no sequence number, but is always guaranteed
2881ab64890Smrg     * to immediately follow another event, except when generated via
2891ab64890Smrg     * SendEvent (hmmm).
2901ab64890Smrg     */
2911ab64890Smrg    if ((rep->type & 0x7f) == KeymapNotify)
2921ab64890Smrg	return(lastseq);
2931ab64890Smrg
294dac667f7Smrg    newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
2951ab64890Smrg
2961ab64890Smrg    if (newseq < lastseq) {
2971ab64890Smrg	newseq += 0x10000;
298dac667f7Smrg	if (newseq > X_DPY_GET_REQUEST(dpy)) {
29961b2299dSmrg	    (void) fprintf (stderr,
300dac667f7Smrg	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
301dac667f7Smrg			    (unsigned long long)newseq,
302dac667f7Smrg			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
3031ab64890Smrg			    (unsigned int) rep->type);
3041ab64890Smrg	    newseq -= 0x10000;
3051ab64890Smrg	}
3061ab64890Smrg    }
3071ab64890Smrg
308dac667f7Smrg    X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
3091ab64890Smrg    return(newseq);
3101ab64890Smrg}
3111ab64890Smrg
3121ab64890Smrg/*
3131ab64890Smrg * Support for internal connections, such as an IM might use.
3141ab64890Smrg * By Stephen Gildea, X Consortium, September 1993
3151ab64890Smrg */
3161ab64890Smrg
3171ab64890Smrg/* _XRegisterInternalConnection
3181ab64890Smrg * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
3191ab64890Smrg * include in its select/poll mask must call this function to register the
3201ab64890Smrg * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
3211ab64890Smrg * will also be called.
3221ab64890Smrg *
3231ab64890Smrg * Whenever Xlib detects input available on fd, it will call callback
3241ab64890Smrg * with call_data to process it.  If non-Xlib code calls select/poll
3251ab64890Smrg * and detects input available, it must call XProcessInternalConnection,
3261ab64890Smrg * which will call the associated callback.
3271ab64890Smrg *
3281ab64890Smrg * Non-Xlib code can learn about these additional fds by calling
3291ab64890Smrg * XInternalConnectionNumbers or, more typically, by registering
3301ab64890Smrg * a XConnectionWatchProc with XAddConnectionWatch
3311ab64890Smrg * to be called when fds are registered or unregistered.
3321ab64890Smrg *
3331ab64890Smrg * Returns True if registration succeeded, False if not, typically
3341ab64890Smrg * because could not allocate memory.
3351ab64890Smrg * Assumes Display locked when called.
3361ab64890Smrg */
3371ab64890SmrgStatus
3381ab64890Smrg_XRegisterInternalConnection(
3391ab64890Smrg    Display* dpy,
3401ab64890Smrg    int fd,
3411ab64890Smrg    _XInternalConnectionProc callback,
3421ab64890Smrg    XPointer call_data
3431ab64890Smrg)
3441ab64890Smrg{
3451ab64890Smrg    struct _XConnectionInfo *new_conni, **iptr;
3461ab64890Smrg    struct _XConnWatchInfo *watchers;
3471ab64890Smrg    XPointer *wd;
3481ab64890Smrg
349556b6652Smrg    new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
3501ab64890Smrg    if (!new_conni)
3511ab64890Smrg	return 0;
352556b6652Smrg    new_conni->watch_data = Xmalloc(dpy->watcher_count * sizeof(XPointer));
3531ab64890Smrg    if (!new_conni->watch_data) {
3541ab64890Smrg	Xfree(new_conni);
3551ab64890Smrg	return 0;
3561ab64890Smrg    }
3571ab64890Smrg    new_conni->fd = fd;
3581ab64890Smrg    new_conni->read_callback = callback;
3591ab64890Smrg    new_conni->call_data = call_data;
3601ab64890Smrg    new_conni->next = NULL;
3611ab64890Smrg    /* link new structure onto end of list */
3621ab64890Smrg    for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
3631ab64890Smrg	;
3641ab64890Smrg    *iptr = new_conni;
3651ab64890Smrg    dpy->im_fd_length++;
3661ab64890Smrg    _XPollfdCacheAdd(dpy, fd);
3671ab64890Smrg
3681ab64890Smrg    for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
3691ab64890Smrg	 watchers;
3701ab64890Smrg	 watchers=watchers->next, wd++) {
3711ab64890Smrg	*wd = NULL;		/* for cleanliness */
3721ab64890Smrg	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
3731ab64890Smrg    }
3741ab64890Smrg
3751ab64890Smrg    return 1;
3761ab64890Smrg}
3771ab64890Smrg
3781ab64890Smrg/* _XUnregisterInternalConnection
3791ab64890Smrg * Each IM (or Xlib extension) that closes a file descriptor previously
3801ab64890Smrg * registered with _XRegisterInternalConnection must call this function.
3811ab64890Smrg * Any XConnectionWatchProc registered by XAddConnectionWatch
3821ab64890Smrg * will also be called.
3831ab64890Smrg *
3841ab64890Smrg * Assumes Display locked when called.
3851ab64890Smrg */
3861ab64890Smrgvoid
3871ab64890Smrg_XUnregisterInternalConnection(
3881ab64890Smrg    Display* dpy,
3891ab64890Smrg    int fd
3901ab64890Smrg)
3911ab64890Smrg{
3921ab64890Smrg    struct _XConnectionInfo *info_list, **prev;
3931ab64890Smrg    struct _XConnWatchInfo *watch;
3941ab64890Smrg    XPointer *wd;
3951ab64890Smrg
3961ab64890Smrg    for (prev = &dpy->im_fd_info; (info_list = *prev);
3971ab64890Smrg	 prev = &info_list->next) {
3981ab64890Smrg	if (info_list->fd == fd) {
3991ab64890Smrg	    *prev = info_list->next;
4001ab64890Smrg	    dpy->im_fd_length--;
4011ab64890Smrg	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
4021ab64890Smrg		 watch;
4031ab64890Smrg		 watch=watch->next, wd++) {
4041ab64890Smrg		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
4051ab64890Smrg	    }
406cf2acddeSmrg	    Xfree (info_list->watch_data);
4071ab64890Smrg	    Xfree (info_list);
4081ab64890Smrg	    break;
4091ab64890Smrg	}
4101ab64890Smrg    }
4111ab64890Smrg    _XPollfdCacheDel(dpy, fd);
4121ab64890Smrg}
4131ab64890Smrg
4141ab64890Smrg/* XInternalConnectionNumbers
4151ab64890Smrg * Returns an array of fds and an array of corresponding call data.
4161ab64890Smrg * Typically a XConnectionWatchProc registered with XAddConnectionWatch
4171ab64890Smrg * will be used instead of this function to discover
4181ab64890Smrg * additional fds to include in the select/poll mask.
4191ab64890Smrg *
4201ab64890Smrg * The list is allocated with Xmalloc and should be freed by the caller
4211ab64890Smrg * with Xfree;
4221ab64890Smrg */
4231ab64890SmrgStatus
4241ab64890SmrgXInternalConnectionNumbers(
4251ab64890Smrg    Display *dpy,
4261ab64890Smrg    int **fd_return,
4271ab64890Smrg    int *count_return
4281ab64890Smrg)
4291ab64890Smrg{
4301ab64890Smrg    int count;
4311ab64890Smrg    struct _XConnectionInfo *info_list;
4321ab64890Smrg    int *fd_list;
4331ab64890Smrg
4341ab64890Smrg    LockDisplay(dpy);
4351ab64890Smrg    count = 0;
4361ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
4371ab64890Smrg	count++;
438556b6652Smrg    fd_list = Xmalloc (count * sizeof(int));
4391ab64890Smrg    if (!fd_list) {
4401ab64890Smrg	UnlockDisplay(dpy);
4411ab64890Smrg	return 0;
4421ab64890Smrg    }
4431ab64890Smrg    count = 0;
4441ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4451ab64890Smrg	fd_list[count] = info_list->fd;
4461ab64890Smrg	count++;
4471ab64890Smrg    }
4481ab64890Smrg    UnlockDisplay(dpy);
4491ab64890Smrg
4501ab64890Smrg    *fd_return = fd_list;
4511ab64890Smrg    *count_return = count;
4521ab64890Smrg    return 1;
4531ab64890Smrg}
4541ab64890Smrg
4551ab64890Smrgvoid _XProcessInternalConnection(
4561ab64890Smrg    Display *dpy,
4571ab64890Smrg    struct _XConnectionInfo *conn_info)
4581ab64890Smrg{
4591ab64890Smrg    dpy->flags |= XlibDisplayProcConni;
4601ab64890Smrg    UnlockDisplay(dpy);
4611ab64890Smrg    (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
4621ab64890Smrg    LockDisplay(dpy);
4631ab64890Smrg    dpy->flags &= ~XlibDisplayProcConni;
4641ab64890Smrg}
4651ab64890Smrg
4661ab64890Smrg/* XProcessInternalConnection
4671ab64890Smrg * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
4681ab64890Smrg * for this fd.
4691ab64890Smrg * The Display is NOT locked during the call.
4701ab64890Smrg */
4711ab64890Smrgvoid
4721ab64890SmrgXProcessInternalConnection(
4731ab64890Smrg    Display* dpy,
4741ab64890Smrg    int fd
4751ab64890Smrg)
4761ab64890Smrg{
4771ab64890Smrg    struct _XConnectionInfo *info_list;
4781ab64890Smrg
4791ab64890Smrg    LockDisplay(dpy);
4801ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
4811ab64890Smrg	if (info_list->fd == fd) {
4821ab64890Smrg	    _XProcessInternalConnection(dpy, info_list);
4831ab64890Smrg	    break;
4841ab64890Smrg	}
4851ab64890Smrg    }
4861ab64890Smrg    UnlockDisplay(dpy);
4871ab64890Smrg}
4881ab64890Smrg
4891ab64890Smrg/* XAddConnectionWatch
4901ab64890Smrg * Register a callback to be called whenever _XRegisterInternalConnection
4911ab64890Smrg * or _XUnregisterInternalConnection is called.
4921ab64890Smrg * Callbacks are called with the Display locked.
4931ab64890Smrg * If any connections are already registered, the callback is immediately
4941ab64890Smrg * called for each of them.
4951ab64890Smrg */
4961ab64890SmrgStatus
4971ab64890SmrgXAddConnectionWatch(
4981ab64890Smrg    Display* dpy,
4991ab64890Smrg    XConnectionWatchProc callback,
5001ab64890Smrg    XPointer client_data
5011ab64890Smrg)
5021ab64890Smrg{
5031ab64890Smrg    struct _XConnWatchInfo *new_watcher, **wptr;
5041ab64890Smrg    struct _XConnectionInfo *info_list;
5051ab64890Smrg    XPointer *wd_array;
5061ab64890Smrg
5071ab64890Smrg    LockDisplay(dpy);
5081ab64890Smrg
5091ab64890Smrg    /* allocate new watch data */
5101ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
511556b6652Smrg	wd_array = Xrealloc(info_list->watch_data,
512556b6652Smrg			    (dpy->watcher_count + 1) * sizeof(XPointer));
5131ab64890Smrg	if (!wd_array) {
5141ab64890Smrg	    UnlockDisplay(dpy);
5151ab64890Smrg	    return 0;
5161ab64890Smrg	}
517c17aa6b1Smrg	info_list->watch_data = wd_array;
5181ab64890Smrg	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
5191ab64890Smrg    }
5201ab64890Smrg
521556b6652Smrg    new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
5221ab64890Smrg    if (!new_watcher) {
5231ab64890Smrg	UnlockDisplay(dpy);
5241ab64890Smrg	return 0;
5251ab64890Smrg    }
5261ab64890Smrg    new_watcher->fn = callback;
5271ab64890Smrg    new_watcher->client_data = client_data;
5281ab64890Smrg    new_watcher->next = NULL;
5291ab64890Smrg
5301ab64890Smrg    /* link new structure onto end of list */
5311ab64890Smrg    for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
5321ab64890Smrg	;
5331ab64890Smrg    *wptr = new_watcher;
5341ab64890Smrg    dpy->watcher_count++;
5351ab64890Smrg
5361ab64890Smrg    /* call new watcher on all currently registered fds */
5371ab64890Smrg    for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
5381ab64890Smrg	(*callback) (dpy, client_data, info_list->fd, True,
5391ab64890Smrg		     info_list->watch_data + dpy->watcher_count - 1);
5401ab64890Smrg    }
5411ab64890Smrg
5421ab64890Smrg    UnlockDisplay(dpy);
5431ab64890Smrg    return 1;
5441ab64890Smrg}
5451ab64890Smrg
5461ab64890Smrg/* XRemoveConnectionWatch
5471ab64890Smrg * Unregister a callback registered by XAddConnectionWatch.
5481ab64890Smrg * Both callback and client_data must match what was passed to
5491ab64890Smrg * XAddConnectionWatch.
55061b2299dSmrg */
5511ab64890Smrgvoid
5521ab64890SmrgXRemoveConnectionWatch(
5531ab64890Smrg    Display* dpy,
5541ab64890Smrg    XConnectionWatchProc callback,
5551ab64890Smrg    XPointer client_data
5561ab64890Smrg)
5571ab64890Smrg{
5581ab64890Smrg    struct _XConnWatchInfo *watch;
5591ab64890Smrg    struct _XConnWatchInfo *previous = NULL;
5601ab64890Smrg    struct _XConnectionInfo *conni;
5611ab64890Smrg    int counter = 0;
5621ab64890Smrg
5631ab64890Smrg    LockDisplay(dpy);
5641ab64890Smrg    for (watch=dpy->conn_watchers; watch; watch=watch->next) {
5651ab64890Smrg	if (watch->fn == callback  &&  watch->client_data == client_data) {
5661ab64890Smrg	    if (previous)
5671ab64890Smrg		previous->next = watch->next;
5681ab64890Smrg	    else
5691ab64890Smrg		dpy->conn_watchers = watch->next;
5701ab64890Smrg	    Xfree (watch);
5711ab64890Smrg	    dpy->watcher_count--;
5721ab64890Smrg	    /* remove our watch_data for each connection */
5731ab64890Smrg	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
5741ab64890Smrg		/* don't bother realloc'ing; these arrays are small anyway */
5751ab64890Smrg		/* overlapping */
5761ab64890Smrg		memmove(conni->watch_data+counter,
5771ab64890Smrg			conni->watch_data+counter+1,
5781ab64890Smrg			dpy->watcher_count - counter);
5791ab64890Smrg	    }
5801ab64890Smrg	    break;
5811ab64890Smrg	}
5821ab64890Smrg	previous = watch;
5831ab64890Smrg	counter++;
5841ab64890Smrg    }
5851ab64890Smrg    UnlockDisplay(dpy);
5861ab64890Smrg}
5871ab64890Smrg
5881ab64890Smrg/* end of internal connections support */
5891ab64890Smrg
590b4ee4795Smrg/* Cookie jar implementation
591b4ee4795Smrg   dpy->cookiejar is a linked list. _XEnq receives the events but leaves
592b4ee4795Smrg   them in the normal EQ. _XStoreEvent returns the cookie event (minus
593b4ee4795Smrg   data pointer) and adds it to the cookiejar. _XDeq just removes
594b4ee4795Smrg   the entry like any other event but resets the data pointer for
595b4ee4795Smrg   cookie events (to avoid double-free, the memory is re-used by Xlib).
596b4ee4795Smrg
597b4ee4795Smrg   _XFetchEventCookie (called from XGetEventData) removes a cookie from the
598b4ee4795Smrg   jar. _XFreeEventCookies removes all unclaimed cookies from the jar
599b4ee4795Smrg   (called by XNextEvent).
600b4ee4795Smrg
601b4ee4795Smrg   _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
602b4ee4795Smrg   normal EQ.
603b4ee4795Smrg */
604b4ee4795Smrg
605b4ee4795Smrg#include "utlist.h"
606b4ee4795Smrgstruct stored_event {
607b4ee4795Smrg    XGenericEventCookie ev;
608b4ee4795Smrg    struct stored_event *prev;
609b4ee4795Smrg    struct stored_event *next;
610b4ee4795Smrg};
611b4ee4795Smrg
612b4ee4795SmrgBool
613b4ee4795Smrg_XIsEventCookie(Display *dpy, XEvent *ev)
614b4ee4795Smrg{
615b4ee4795Smrg    return (ev->xcookie.type == GenericEvent &&
616b4ee4795Smrg	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
617b4ee4795Smrg}
618b4ee4795Smrg
619b4ee4795Smrg/**
620b4ee4795Smrg * Free all events in the event list.
621b4ee4795Smrg */
622b4ee4795Smrgvoid
623b4ee4795Smrg_XFreeEventCookies(Display *dpy)
624b4ee4795Smrg{
625b4ee4795Smrg    struct stored_event **head, *e, *tmp;
626b4ee4795Smrg
627b4ee4795Smrg    if (!dpy->cookiejar)
628b4ee4795Smrg        return;
629b4ee4795Smrg
630b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
631b4ee4795Smrg
632b4ee4795Smrg    DL_FOREACH_SAFE(*head, e, tmp) {
633b4ee4795Smrg        if (dpy->cookiejar == e)
634b4ee4795Smrg            dpy->cookiejar = NULL;
635c17aa6b1Smrg        XFree(e->ev.data);
636c17aa6b1Smrg        XFree(e);
637b4ee4795Smrg    }
638b4ee4795Smrg}
639b4ee4795Smrg
640b4ee4795Smrg/**
641b4ee4795Smrg * Add an event to the display's event list. This event must be freed on the
642b4ee4795Smrg * next call to XNextEvent().
643b4ee4795Smrg */
644b4ee4795Smrgvoid
645b4ee4795Smrg_XStoreEventCookie(Display *dpy, XEvent *event)
646b4ee4795Smrg{
647b4ee4795Smrg    XGenericEventCookie* cookie = &event->xcookie;
648b4ee4795Smrg    struct stored_event **head, *add;
649b4ee4795Smrg
650b4ee4795Smrg    if (!_XIsEventCookie(dpy, event))
651b4ee4795Smrg        return;
652b4ee4795Smrg
653b4ee4795Smrg    head = (struct stored_event**)(&dpy->cookiejar);
654b4ee4795Smrg
655b4ee4795Smrg    add = Xmalloc(sizeof(struct stored_event));
656b4ee4795Smrg    if (!add) {
657b4ee4795Smrg        ESET(ENOMEM);
658b4ee4795Smrg        _XIOError(dpy);
659b4ee4795Smrg    }
660b4ee4795Smrg    add->ev = *cookie;
661b4ee4795Smrg    DL_APPEND(*head, add);
662b4ee4795Smrg    cookie->data = NULL; /* don't return data yet, must be claimed */
663b4ee4795Smrg}
664b4ee4795Smrg
665b4ee4795Smrg/**
666b4ee4795Smrg * Return the event with the given cookie and remove it from the list.
667b4ee4795Smrg */
668b4ee4795SmrgBool
669b4ee4795Smrg_XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
670b4ee4795Smrg{
671b4ee4795Smrg    Bool ret = False;
672b4ee4795Smrg    struct stored_event **head, *event;
673b4ee4795Smrg    head = (struct stored_event**)&dpy->cookiejar;
674b4ee4795Smrg
675b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)ev))
676b4ee4795Smrg        return ret;
677b4ee4795Smrg
678b4ee4795Smrg    DL_FOREACH(*head, event) {
679b4ee4795Smrg        if (event->ev.cookie == ev->cookie &&
680b4ee4795Smrg            event->ev.extension == ev->extension &&
681b4ee4795Smrg            event->ev.evtype == ev->evtype) {
682b4ee4795Smrg            *ev = event->ev;
683b4ee4795Smrg            DL_DELETE(*head, event);
684b4ee4795Smrg            Xfree(event);
685b4ee4795Smrg            ret = True;
686b4ee4795Smrg            break;
687b4ee4795Smrg        }
688b4ee4795Smrg    }
689b4ee4795Smrg
690b4ee4795Smrg    return ret;
691b4ee4795Smrg}
692b4ee4795Smrg
693b4ee4795SmrgBool
694b4ee4795Smrg_XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
695b4ee4795Smrg{
696b4ee4795Smrg    Bool ret = False;
697b4ee4795Smrg    int extension;
698b4ee4795Smrg
699b4ee4795Smrg    if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
700b4ee4795Smrg        return ret;
701b4ee4795Smrg
702b4ee4795Smrg    extension = in->extension & 0x7F;
703b4ee4795Smrg
704b4ee4795Smrg    if (!dpy->generic_event_copy_vec[extension])
705b4ee4795Smrg        return ret;
706b4ee4795Smrg
707b4ee4795Smrg    ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
708b4ee4795Smrg    out->cookie = ret ? ++dpy->next_cookie  : 0;
709b4ee4795Smrg    return ret;
710b4ee4795Smrg}
711b4ee4795Smrg
7121ab64890Smrg
7131ab64890Smrg/*
7141ab64890Smrg * _XEnq - Place event packets on the display's queue.
7151ab64890Smrg * note that no squishing of move events in V11, since there
7161ab64890Smrg * is pointer motion hints....
7171ab64890Smrg */
7181ab64890Smrgvoid _XEnq(
7191ab64890Smrg	register Display *dpy,
7201ab64890Smrg	register xEvent *event)
7211ab64890Smrg{
7221ab64890Smrg	register _XQEvent *qelt;
723b4ee4795Smrg	int type, extension;
7241ab64890Smrg
7251ab64890Smrg	if ((qelt = dpy->qfree)) {
7261ab64890Smrg		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
7271ab64890Smrg		dpy->qfree = qelt->next;
7281ab64890Smrg	}
729556b6652Smrg	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
7301ab64890Smrg		/* Malloc call failed! */
7311ab64890Smrg		ESET(ENOMEM);
7321ab64890Smrg		_XIOError(dpy);
7331ab64890Smrg	}
7341ab64890Smrg	qelt->next = NULL;
735b4ee4795Smrg
736b4ee4795Smrg	type = event->u.u.type & 0177;
737b4ee4795Smrg	extension = ((xGenericEvent*)event)->extension;
738295fb823Smrg
739295fb823Smrg	qelt->event.type = type;
740556b6652Smrg	/* If an extension has registered a generic_event_vec handler, then
741b4ee4795Smrg	 * it can handle event cookies. Otherwise, proceed with the normal
742b4ee4795Smrg	 * event handlers.
743b4ee4795Smrg	 *
744b4ee4795Smrg	 * If the generic_event_vec is called, qelt->event is a event cookie
745b4ee4795Smrg	 * with the data pointer and the "free" pointer set. Data pointer is
746b4ee4795Smrg	 * some memory allocated by the extension.
747b4ee4795Smrg	 */
748b4ee4795Smrg        if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
749b4ee4795Smrg	    XGenericEventCookie *cookie = &qelt->event.xcookie;
750b4ee4795Smrg	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
751b4ee4795Smrg	    cookie->cookie = ++dpy->next_cookie;
752b4ee4795Smrg
753b4ee4795Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
754b4ee4795Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
755b4ee4795Smrg	    else		dpy->head = qelt;
756b4ee4795Smrg
757b4ee4795Smrg	    dpy->tail = qelt;
758b4ee4795Smrg	    dpy->qlen++;
759b4ee4795Smrg	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
7601ab64890Smrg	    qelt->qserial_num = dpy->next_event_serial_num++;
7611ab64890Smrg	    if (dpy->tail)	dpy->tail->next = qelt;
7621ab64890Smrg	    else 		dpy->head = qelt;
76361b2299dSmrg
7641ab64890Smrg	    dpy->tail = qelt;
7651ab64890Smrg	    dpy->qlen++;
7661ab64890Smrg	} else {
7671ab64890Smrg	    /* ignored, or stashed away for many-to-one compression */
7681ab64890Smrg	    qelt->next = dpy->qfree;
7691ab64890Smrg	    dpy->qfree = qelt;
7701ab64890Smrg	}
7711ab64890Smrg}
7721ab64890Smrg
7731ab64890Smrg/*
7741ab64890Smrg * _XDeq - Remove event packet from the display's queue.
7751ab64890Smrg */
7761ab64890Smrgvoid _XDeq(
7771ab64890Smrg    register Display *dpy,
7781ab64890Smrg    register _XQEvent *prev,	/* element before qelt */
7791ab64890Smrg    register _XQEvent *qelt)	/* element to be unlinked */
7801ab64890Smrg{
7811ab64890Smrg    if (prev) {
7821ab64890Smrg	if ((prev->next = qelt->next) == NULL)
7831ab64890Smrg	    dpy->tail = prev;
7841ab64890Smrg    } else {
7851ab64890Smrg	/* no prev, so removing first elt */
7861ab64890Smrg	if ((dpy->head = qelt->next) == NULL)
7871ab64890Smrg	    dpy->tail = NULL;
7881ab64890Smrg    }
7891ab64890Smrg    qelt->qserial_num = 0;
7901ab64890Smrg    qelt->next = dpy->qfree;
7911ab64890Smrg    dpy->qfree = qelt;
7921ab64890Smrg    dpy->qlen--;
793b4ee4795Smrg
794b4ee4795Smrg    if (_XIsEventCookie(dpy, &qelt->event)) {
795b4ee4795Smrg	XGenericEventCookie* cookie = &qelt->event.xcookie;
796b4ee4795Smrg	/* dpy->qfree is re-used, reset memory to avoid double free on
797b4ee4795Smrg	 * _XFreeDisplayStructure */
798b4ee4795Smrg	cookie->data = NULL;
799b4ee4795Smrg    }
8001ab64890Smrg}
8011ab64890Smrg
8021ab64890Smrg/*
8031ab64890Smrg * EventToWire in separate file in that often not needed.
8041ab64890Smrg */
8051ab64890Smrg
8061ab64890Smrg/*ARGSUSED*/
8071ab64890SmrgBool
8081ab64890Smrg_XUnknownWireEvent(
8091ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8101ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8111ab64890Smrg    register xEvent *event)	/* wire protocol event */
8121ab64890Smrg{
8131ab64890Smrg#ifdef notdef
81461b2299dSmrg	(void) fprintf(stderr,
8151ab64890Smrg	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
8161ab64890Smrg			event->u.u.type, dpy);
8171ab64890Smrg#endif
8181ab64890Smrg	return(False);
8191ab64890Smrg}
8201ab64890Smrg
821b4ee4795SmrgBool
822b4ee4795Smrg_XUnknownWireEventCookie(
823b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
824b4ee4795Smrg    XGenericEventCookie *re,	/* pointer to where event should be reformatted */
825b4ee4795Smrg    xEvent *event)	/* wire protocol event */
826b4ee4795Smrg{
827b4ee4795Smrg#ifdef notdef
828b4ee4795Smrg	fprintf(stderr,
829b4ee4795Smrg	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
830b4ee4795Smrg			((xGenericEvent*)event)->extension, dpy);
831b4ee4795Smrg#endif
832b4ee4795Smrg	return(False);
833b4ee4795Smrg}
834b4ee4795Smrg
835b4ee4795SmrgBool
836b4ee4795Smrg_XUnknownCopyEventCookie(
837b4ee4795Smrg    Display *dpy,	/* pointer to display structure */
838b4ee4795Smrg    XGenericEventCookie *in,	/* source */
839b4ee4795Smrg    XGenericEventCookie *out)	/* destination */
840b4ee4795Smrg{
841b4ee4795Smrg#ifdef notdef
842b4ee4795Smrg	fprintf(stderr,
843b4ee4795Smrg	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
844b4ee4795Smrg			in->extension, dpy);
845b4ee4795Smrg#endif
846b4ee4795Smrg	return(False);
847b4ee4795Smrg}
848b4ee4795Smrg
8491ab64890Smrg/*ARGSUSED*/
8501ab64890SmrgStatus
8511ab64890Smrg_XUnknownNativeEvent(
8521ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8531ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8541ab64890Smrg    register xEvent *event)	/* wire protocol event */
8551ab64890Smrg{
8561ab64890Smrg#ifdef notdef
85761b2299dSmrg	(void) fprintf(stderr,
8581ab64890Smrg 	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
8591ab64890Smrg			re->type, dpy);
8601ab64890Smrg#endif
8611ab64890Smrg	return(0);
8621ab64890Smrg}
8631ab64890Smrg/*
8641ab64890Smrg * reformat a wire event into an XEvent structure of the right type.
8651ab64890Smrg */
8661ab64890SmrgBool
8671ab64890Smrg_XWireToEvent(
8681ab64890Smrg    register Display *dpy,	/* pointer to display structure */
8691ab64890Smrg    register XEvent *re,	/* pointer to where event should be reformatted */
8701ab64890Smrg    register xEvent *event)	/* wire protocol event */
8711ab64890Smrg{
8721ab64890Smrg
8731ab64890Smrg	re->type = event->u.u.type & 0x7f;
8741ab64890Smrg	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
8751ab64890Smrg					(xGenericReply *)event);
8761ab64890Smrg	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
8771ab64890Smrg	((XAnyEvent *)re)->display = dpy;
87861b2299dSmrg
8791ab64890Smrg	/* Ignore the leading bit of the event type since it is set when a
8801ab64890Smrg		client sends an event rather than the server. */
8811ab64890Smrg
8821ab64890Smrg	switch (event-> u.u.type & 0177) {
8831ab64890Smrg	      case KeyPress:
8841ab64890Smrg	      case KeyRelease:
8851ab64890Smrg	        {
8861ab64890Smrg			register XKeyEvent *ev = (XKeyEvent*) re;
8871ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
8881ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
8891ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
8901ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
8911ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
8921ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
8931ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
8941ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
8951ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
8961ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
8971ab64890Smrg			ev->keycode 	= event->u.u.detail;
8981ab64890Smrg		}
8991ab64890Smrg	      	break;
9001ab64890Smrg	      case ButtonPress:
9011ab64890Smrg	      case ButtonRelease:
9021ab64890Smrg	        {
9031ab64890Smrg			register XButtonEvent *ev =  (XButtonEvent *) re;
9041ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9051ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9061ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9071ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9081ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9091ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9101ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9111ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9121ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9131ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9141ab64890Smrg			ev->button 	= event->u.u.detail;
9151ab64890Smrg		}
9161ab64890Smrg	        break;
9171ab64890Smrg	      case MotionNotify:
9181ab64890Smrg	        {
9191ab64890Smrg			register XMotionEvent *ev =   (XMotionEvent *)re;
9201ab64890Smrg			ev->root 	= event->u.keyButtonPointer.root;
9211ab64890Smrg			ev->window 	= event->u.keyButtonPointer.event;
9221ab64890Smrg			ev->subwindow 	= event->u.keyButtonPointer.child;
9231ab64890Smrg			ev->time 	= event->u.keyButtonPointer.time;
9241ab64890Smrg			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
9251ab64890Smrg			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
9261ab64890Smrg			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
9271ab64890Smrg			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
9281ab64890Smrg			ev->state	= event->u.keyButtonPointer.state;
9291ab64890Smrg			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
9301ab64890Smrg			ev->is_hint 	= event->u.u.detail;
9311ab64890Smrg		}
9321ab64890Smrg	        break;
9331ab64890Smrg	      case EnterNotify:
9341ab64890Smrg	      case LeaveNotify:
9351ab64890Smrg		{
9361ab64890Smrg			register XCrossingEvent *ev   = (XCrossingEvent *) re;
9371ab64890Smrg			ev->root	= event->u.enterLeave.root;
9381ab64890Smrg			ev->window	= event->u.enterLeave.event;
9391ab64890Smrg			ev->subwindow	= event->u.enterLeave.child;
9401ab64890Smrg			ev->time	= event->u.enterLeave.time;
9411ab64890Smrg			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
9421ab64890Smrg			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
9431ab64890Smrg			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
9441ab64890Smrg			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
9451ab64890Smrg			ev->state	= event->u.enterLeave.state;
9461ab64890Smrg			ev->mode	= event->u.enterLeave.mode;
94761b2299dSmrg			ev->same_screen = (event->u.enterLeave.flags &
9481ab64890Smrg				ELFlagSameScreen) && True;
9491ab64890Smrg			ev->focus	= (event->u.enterLeave.flags &
9501ab64890Smrg			  	ELFlagFocus) && True;
9511ab64890Smrg			ev->detail	= event->u.u.detail;
9521ab64890Smrg		}
9531ab64890Smrg		  break;
9541ab64890Smrg	      case FocusIn:
9551ab64890Smrg	      case FocusOut:
9561ab64890Smrg		{
9571ab64890Smrg			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
9581ab64890Smrg			ev->window 	= event->u.focus.window;
9591ab64890Smrg			ev->mode	= event->u.focus.mode;
9601ab64890Smrg			ev->detail	= event->u.u.detail;
9611ab64890Smrg		}
9621ab64890Smrg		  break;
9631ab64890Smrg	      case KeymapNotify:
9641ab64890Smrg		{
9651ab64890Smrg			register XKeymapEvent *ev = (XKeymapEvent *) re;
9661ab64890Smrg			ev->window	= None;
9671ab64890Smrg			memcpy(&ev->key_vector[1],
9681ab64890Smrg			       (char *)((xKeymapEvent *) event)->map,
9691ab64890Smrg			       sizeof (((xKeymapEvent *) event)->map));
9701ab64890Smrg		}
9711ab64890Smrg		break;
9721ab64890Smrg	      case Expose:
9731ab64890Smrg		{
9741ab64890Smrg			register XExposeEvent *ev = (XExposeEvent *) re;
9751ab64890Smrg			ev->window	= event->u.expose.window;
9761ab64890Smrg			ev->x		= event->u.expose.x;
9771ab64890Smrg			ev->y		= event->u.expose.y;
9781ab64890Smrg			ev->width	= event->u.expose.width;
9791ab64890Smrg			ev->height	= event->u.expose.height;
9801ab64890Smrg			ev->count	= event->u.expose.count;
9811ab64890Smrg		}
9821ab64890Smrg		break;
9831ab64890Smrg	      case GraphicsExpose:
9841ab64890Smrg		{
9851ab64890Smrg		    register XGraphicsExposeEvent *ev =
9861ab64890Smrg			(XGraphicsExposeEvent *) re;
9871ab64890Smrg		    ev->drawable	= event->u.graphicsExposure.drawable;
9881ab64890Smrg		    ev->x		= event->u.graphicsExposure.x;
9891ab64890Smrg		    ev->y		= event->u.graphicsExposure.y;
9901ab64890Smrg		    ev->width		= event->u.graphicsExposure.width;
9911ab64890Smrg		    ev->height		= event->u.graphicsExposure.height;
9921ab64890Smrg		    ev->count		= event->u.graphicsExposure.count;
9931ab64890Smrg		    ev->major_code	= event->u.graphicsExposure.majorEvent;
9941ab64890Smrg		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
9951ab64890Smrg		}
9961ab64890Smrg		break;
9971ab64890Smrg	      case NoExpose:
9981ab64890Smrg		{
9991ab64890Smrg		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
10001ab64890Smrg		    ev->drawable	= event->u.noExposure.drawable;
10011ab64890Smrg		    ev->major_code	= event->u.noExposure.majorEvent;
10021ab64890Smrg		    ev->minor_code	= event->u.noExposure.minorEvent;
10031ab64890Smrg		}
10041ab64890Smrg		break;
10051ab64890Smrg	      case VisibilityNotify:
10061ab64890Smrg		{
10071ab64890Smrg		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
10081ab64890Smrg		    ev->window		= event->u.visibility.window;
10091ab64890Smrg		    ev->state		= event->u.visibility.state;
10101ab64890Smrg		}
10111ab64890Smrg		break;
10121ab64890Smrg	      case CreateNotify:
10131ab64890Smrg		{
10141ab64890Smrg		    register XCreateWindowEvent *ev =
10151ab64890Smrg			 (XCreateWindowEvent *) re;
10161ab64890Smrg		    ev->window		= event->u.createNotify.window;
10171ab64890Smrg		    ev->parent		= event->u.createNotify.parent;
10181ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
10191ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
10201ab64890Smrg		    ev->width		= event->u.createNotify.width;
10211ab64890Smrg		    ev->height		= event->u.createNotify.height;
10221ab64890Smrg		    ev->border_width	= event->u.createNotify.borderWidth;
10231ab64890Smrg		    ev->override_redirect	= event->u.createNotify.override;
10241ab64890Smrg		}
10251ab64890Smrg		break;
10261ab64890Smrg	      case DestroyNotify:
10271ab64890Smrg		{
10281ab64890Smrg		    register XDestroyWindowEvent *ev =
10291ab64890Smrg				(XDestroyWindowEvent *) re;
10301ab64890Smrg		    ev->window		= event->u.destroyNotify.window;
10311ab64890Smrg		    ev->event		= event->u.destroyNotify.event;
10321ab64890Smrg		}
10331ab64890Smrg		break;
10341ab64890Smrg	      case UnmapNotify:
10351ab64890Smrg		{
10361ab64890Smrg		    register XUnmapEvent *ev = (XUnmapEvent *) re;
10371ab64890Smrg		    ev->window		= event->u.unmapNotify.window;
10381ab64890Smrg		    ev->event		= event->u.unmapNotify.event;
10391ab64890Smrg		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
10401ab64890Smrg		}
10411ab64890Smrg		break;
10421ab64890Smrg	      case MapNotify:
10431ab64890Smrg		{
10441ab64890Smrg		    register XMapEvent *ev = (XMapEvent *) re;
10451ab64890Smrg		    ev->window		= event->u.mapNotify.window;
10461ab64890Smrg		    ev->event		= event->u.mapNotify.event;
10471ab64890Smrg		    ev->override_redirect	= event->u.mapNotify.override;
10481ab64890Smrg		}
10491ab64890Smrg		break;
10501ab64890Smrg	      case MapRequest:
10511ab64890Smrg		{
10521ab64890Smrg		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
10531ab64890Smrg		    ev->window		= event->u.mapRequest.window;
10541ab64890Smrg		    ev->parent		= event->u.mapRequest.parent;
10551ab64890Smrg		}
10561ab64890Smrg		break;
10571ab64890Smrg	      case ReparentNotify:
10581ab64890Smrg		{
10591ab64890Smrg		    register XReparentEvent *ev = (XReparentEvent *) re;
10601ab64890Smrg		    ev->event		= event->u.reparent.event;
10611ab64890Smrg		    ev->window		= event->u.reparent.window;
10621ab64890Smrg		    ev->parent		= event->u.reparent.parent;
10631ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.reparent.x);
10641ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.reparent.y);
10651ab64890Smrg		    ev->override_redirect	= event->u.reparent.override;
10661ab64890Smrg		}
10671ab64890Smrg		break;
10681ab64890Smrg	      case ConfigureNotify:
10691ab64890Smrg		{
10701ab64890Smrg		    register XConfigureEvent *ev = (XConfigureEvent *) re;
10711ab64890Smrg		    ev->event	= event->u.configureNotify.event;
10721ab64890Smrg		    ev->window	= event->u.configureNotify.window;
10731ab64890Smrg		    ev->above	= event->u.configureNotify.aboveSibling;
10741ab64890Smrg		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
10751ab64890Smrg		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
10761ab64890Smrg		    ev->width	= event->u.configureNotify.width;
10771ab64890Smrg		    ev->height	= event->u.configureNotify.height;
10781ab64890Smrg		    ev->border_width  = event->u.configureNotify.borderWidth;
10791ab64890Smrg		    ev->override_redirect = event->u.configureNotify.override;
10801ab64890Smrg		}
10811ab64890Smrg		break;
10821ab64890Smrg	      case ConfigureRequest:
10831ab64890Smrg		{
10841ab64890Smrg		    register XConfigureRequestEvent *ev =
10851ab64890Smrg		        (XConfigureRequestEvent *) re;
10861ab64890Smrg		    ev->window		= event->u.configureRequest.window;
10871ab64890Smrg		    ev->parent		= event->u.configureRequest.parent;
10881ab64890Smrg		    ev->above		= event->u.configureRequest.sibling;
10891ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
10901ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
10911ab64890Smrg		    ev->width		= event->u.configureRequest.width;
10921ab64890Smrg		    ev->height		= event->u.configureRequest.height;
10931ab64890Smrg		    ev->border_width	= event->u.configureRequest.borderWidth;
10941ab64890Smrg		    ev->value_mask	= event->u.configureRequest.valueMask;
10951ab64890Smrg		    ev->detail  	= event->u.u.detail;
10961ab64890Smrg		}
10971ab64890Smrg		break;
10981ab64890Smrg	      case GravityNotify:
10991ab64890Smrg		{
11001ab64890Smrg		    register XGravityEvent *ev = (XGravityEvent *) re;
11011ab64890Smrg		    ev->window		= event->u.gravity.window;
11021ab64890Smrg		    ev->event		= event->u.gravity.event;
11031ab64890Smrg		    ev->x		= cvtINT16toInt(event->u.gravity.x);
11041ab64890Smrg		    ev->y		= cvtINT16toInt(event->u.gravity.y);
11051ab64890Smrg		}
11061ab64890Smrg		break;
11071ab64890Smrg	      case ResizeRequest:
11081ab64890Smrg		{
11091ab64890Smrg		    register XResizeRequestEvent *ev =
11101ab64890Smrg			(XResizeRequestEvent *) re;
11111ab64890Smrg		    ev->window		= event->u.resizeRequest.window;
11121ab64890Smrg		    ev->width		= event->u.resizeRequest.width;
11131ab64890Smrg		    ev->height		= event->u.resizeRequest.height;
11141ab64890Smrg		}
11151ab64890Smrg		break;
11161ab64890Smrg	      case CirculateNotify:
11171ab64890Smrg		{
11181ab64890Smrg		    register XCirculateEvent *ev = (XCirculateEvent *) re;
11191ab64890Smrg		    ev->window		= event->u.circulate.window;
11201ab64890Smrg		    ev->event		= event->u.circulate.event;
11211ab64890Smrg		    ev->place		= event->u.circulate.place;
11221ab64890Smrg		}
11231ab64890Smrg		break;
11241ab64890Smrg	      case CirculateRequest:
11251ab64890Smrg		{
11261ab64890Smrg		    register XCirculateRequestEvent *ev =
11271ab64890Smrg		        (XCirculateRequestEvent *) re;
11281ab64890Smrg		    ev->window		= event->u.circulate.window;
11291ab64890Smrg		    ev->parent		= event->u.circulate.event;
11301ab64890Smrg		    ev->place		= event->u.circulate.place;
11311ab64890Smrg		}
11321ab64890Smrg		break;
11331ab64890Smrg	      case PropertyNotify:
11341ab64890Smrg		{
11351ab64890Smrg		    register XPropertyEvent *ev = (XPropertyEvent *) re;
11361ab64890Smrg		    ev->window		= event->u.property.window;
11371ab64890Smrg		    ev->atom		= event->u.property.atom;
11381ab64890Smrg		    ev->time		= event->u.property.time;
11391ab64890Smrg		    ev->state		= event->u.property.state;
11401ab64890Smrg		}
11411ab64890Smrg		break;
11421ab64890Smrg	      case SelectionClear:
11431ab64890Smrg		{
11441ab64890Smrg		    register XSelectionClearEvent *ev =
11451ab64890Smrg			 (XSelectionClearEvent *) re;
11461ab64890Smrg		    ev->window		= event->u.selectionClear.window;
11471ab64890Smrg		    ev->selection	= event->u.selectionClear.atom;
11481ab64890Smrg		    ev->time		= event->u.selectionClear.time;
11491ab64890Smrg		}
11501ab64890Smrg		break;
11511ab64890Smrg	      case SelectionRequest:
11521ab64890Smrg		{
11531ab64890Smrg		    register XSelectionRequestEvent *ev =
11541ab64890Smrg		        (XSelectionRequestEvent *) re;
11551ab64890Smrg		    ev->owner		= event->u.selectionRequest.owner;
11561ab64890Smrg		    ev->requestor	= event->u.selectionRequest.requestor;
11571ab64890Smrg		    ev->selection	= event->u.selectionRequest.selection;
11581ab64890Smrg		    ev->target		= event->u.selectionRequest.target;
11591ab64890Smrg		    ev->property	= event->u.selectionRequest.property;
11601ab64890Smrg		    ev->time		= event->u.selectionRequest.time;
11611ab64890Smrg		}
11621ab64890Smrg		break;
11631ab64890Smrg	      case SelectionNotify:
11641ab64890Smrg		{
11651ab64890Smrg		    register XSelectionEvent *ev = (XSelectionEvent *) re;
11661ab64890Smrg		    ev->requestor	= event->u.selectionNotify.requestor;
11671ab64890Smrg		    ev->selection	= event->u.selectionNotify.selection;
11681ab64890Smrg		    ev->target		= event->u.selectionNotify.target;
11691ab64890Smrg		    ev->property	= event->u.selectionNotify.property;
11701ab64890Smrg		    ev->time		= event->u.selectionNotify.time;
11711ab64890Smrg		}
11721ab64890Smrg		break;
11731ab64890Smrg	      case ColormapNotify:
11741ab64890Smrg		{
11751ab64890Smrg		    register XColormapEvent *ev = (XColormapEvent *) re;
11761ab64890Smrg		    ev->window		= event->u.colormap.window;
11771ab64890Smrg		    ev->colormap	= event->u.colormap.colormap;
11781ab64890Smrg		    ev->new		= event->u.colormap.new;
11791ab64890Smrg		    ev->state		= event->u.colormap.state;
11801ab64890Smrg	        }
11811ab64890Smrg		break;
11821ab64890Smrg	      case ClientMessage:
11831ab64890Smrg		{
11841ab64890Smrg		   register int i;
118561b2299dSmrg		   register XClientMessageEvent *ev
11861ab64890Smrg		   			= (XClientMessageEvent *) re;
11871ab64890Smrg		   ev->window		= event->u.clientMessage.window;
11881ab64890Smrg		   ev->format		= event->u.u.detail;
11891ab64890Smrg		   switch (ev->format) {
119061b2299dSmrg			case 8:
11911ab64890Smrg			   ev->message_type = event->u.clientMessage.u.b.type;
119261b2299dSmrg			   for (i = 0; i < 20; i++)
11931ab64890Smrg			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
11941ab64890Smrg			   break;
11951ab64890Smrg			case 16:
11961ab64890Smrg			   ev->message_type = event->u.clientMessage.u.s.type;
11971ab64890Smrg			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
11981ab64890Smrg			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
11991ab64890Smrg			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
12001ab64890Smrg			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
12011ab64890Smrg			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
12021ab64890Smrg			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
12031ab64890Smrg			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
12041ab64890Smrg			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
12051ab64890Smrg			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
12061ab64890Smrg			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
12071ab64890Smrg			   break;
12081ab64890Smrg			case 32:
12091ab64890Smrg			   ev->message_type = event->u.clientMessage.u.l.type;
12101ab64890Smrg			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
12111ab64890Smrg			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
12121ab64890Smrg			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
12131ab64890Smrg			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
12141ab64890Smrg			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
12151ab64890Smrg			   break;
12161ab64890Smrg			default: /* XXX should never occur */
12171ab64890Smrg				break;
12181ab64890Smrg		    }
12191ab64890Smrg	        }
12201ab64890Smrg		break;
12211ab64890Smrg	      case MappingNotify:
12221ab64890Smrg		{
12231ab64890Smrg		   register XMappingEvent *ev = (XMappingEvent *)re;
12241ab64890Smrg		   ev->window		= 0;
12251ab64890Smrg		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
12261ab64890Smrg		   ev->request 		= event->u.mappingNotify.request;
12271ab64890Smrg		   ev->count 		= event->u.mappingNotify.count;
12281ab64890Smrg		}
12291ab64890Smrg		break;
12301ab64890Smrg	      default:
12311ab64890Smrg		return(_XUnknownWireEvent(dpy, re, event));
12321ab64890Smrg	}
12331ab64890Smrg	return(True);
12341ab64890Smrg}
12351ab64890Smrg
12361ab64890Smrg
12371ab64890Smrg/*
123861b2299dSmrg * _XDefaultIOError - Default fatal system error reporting routine.  Called
12391ab64890Smrg * when an X internal system error is encountered.
12401ab64890Smrg */
1241bd8e7fb0Smrg_X_NORETURN int _XDefaultIOError(
12421ab64890Smrg	Display *dpy)
12431ab64890Smrg{
12441ab64890Smrg	if (ECHECK(EPIPE)) {
12451ab64890Smrg	    (void) fprintf (stderr,
12461ab64890Smrg	"X connection to %s broken (explicit kill or server shutdown).\r\n",
12471ab64890Smrg			    DisplayString (dpy));
12481ab64890Smrg	} else {
124961b2299dSmrg	    (void) fprintf (stderr,
12501ab64890Smrg			"XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
12511ab64890Smrg#ifdef WIN32
12521ab64890Smrg			WSAGetLastError(), strerror(WSAGetLastError()),
12531ab64890Smrg#else
12541ab64890Smrg			errno, strerror (errno),
12551ab64890Smrg#endif
12561ab64890Smrg			DisplayString (dpy));
125761b2299dSmrg	    (void) fprintf (stderr,
12581ab64890Smrg	 "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
12591ab64890Smrg			NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
12601ab64890Smrg			QLength(dpy));
12611ab64890Smrg
12621ab64890Smrg	}
12631ab64890Smrg	exit(1);
1264dac667f7Smrg	/*NOTREACHED*/
12651ab64890Smrg}
12661ab64890Smrg
12671ab64890Smrg
12681ab64890Smrgstatic int _XPrintDefaultError(
12691ab64890Smrg    Display *dpy,
12701ab64890Smrg    XErrorEvent *event,
12711ab64890Smrg    FILE *fp)
12721ab64890Smrg{
12731ab64890Smrg    char buffer[BUFSIZ];
12741ab64890Smrg    char mesg[BUFSIZ];
12751ab64890Smrg    char number[32];
12761ab64890Smrg    const char *mtype = "XlibMessage";
12771ab64890Smrg    register _XExtension *ext = (_XExtension *)NULL;
12781ab64890Smrg    _XExtension *bext = (_XExtension *)NULL;
12791ab64890Smrg    XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
12801ab64890Smrg    XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
12811ab64890Smrg    (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
128261b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
12831ab64890Smrg	mesg, BUFSIZ);
12841ab64890Smrg    (void) fprintf(fp, mesg, event->request_code);
12851ab64890Smrg    if (event->request_code < 128) {
1286556b6652Smrg	snprintf(number, sizeof(number), "%d", event->request_code);
12871ab64890Smrg	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
12881ab64890Smrg    } else {
12891ab64890Smrg	for (ext = dpy->ext_procs;
12901ab64890Smrg	     ext && (ext->codes.major_opcode != event->request_code);
12911ab64890Smrg	     ext = ext->next)
12921ab64890Smrg	  ;
1293c17aa6b1Smrg	if (ext) {
1294c17aa6b1Smrg	    strncpy(buffer, ext->name, BUFSIZ);
1295c17aa6b1Smrg	    buffer[BUFSIZ - 1] = '\0';
1296c17aa6b1Smrg        } else
12971ab64890Smrg	    buffer[0] = '\0';
12981ab64890Smrg    }
12991ab64890Smrg    (void) fprintf(fp, " (%s)\n", buffer);
13001ab64890Smrg    if (event->request_code >= 128) {
13011ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
13021ab64890Smrg			      mesg, BUFSIZ);
13031ab64890Smrg	fputs("  ", fp);
13041ab64890Smrg	(void) fprintf(fp, mesg, event->minor_code);
13051ab64890Smrg	if (ext) {
1306556b6652Smrg	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
13071ab64890Smrg	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
13081ab64890Smrg	    (void) fprintf(fp, " (%s)", buffer);
13091ab64890Smrg	}
13101ab64890Smrg	fputs("\n", fp);
13111ab64890Smrg    }
13121ab64890Smrg    if (event->error_code >= 128) {
13131ab64890Smrg	/* kludge, try to find the extension that caused it */
13141ab64890Smrg	buffer[0] = '\0';
13151ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
131661b2299dSmrg	    if (ext->error_string)
13171ab64890Smrg		(*ext->error_string)(dpy, event->error_code, &ext->codes,
13181ab64890Smrg				     buffer, BUFSIZ);
13191ab64890Smrg	    if (buffer[0]) {
13201ab64890Smrg		bext = ext;
13211ab64890Smrg		break;
13221ab64890Smrg	    }
13231ab64890Smrg	    if (ext->codes.first_error &&
13241ab64890Smrg		ext->codes.first_error < (int)event->error_code &&
13251ab64890Smrg		(!bext || ext->codes.first_error > bext->codes.first_error))
13261ab64890Smrg		bext = ext;
132761b2299dSmrg	}
13281ab64890Smrg	if (bext)
1329556b6652Smrg	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
1330556b6652Smrg                     event->error_code - bext->codes.first_error);
13311ab64890Smrg	else
13321ab64890Smrg	    strcpy(buffer, "Value");
13331ab64890Smrg	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
13341ab64890Smrg	if (mesg[0]) {
13351ab64890Smrg	    fputs("  ", fp);
13361ab64890Smrg	    (void) fprintf(fp, mesg, event->resourceid);
13371ab64890Smrg	    fputs("\n", fp);
13381ab64890Smrg	}
13391ab64890Smrg	/* let extensions try to print the values */
13401ab64890Smrg	for (ext = dpy->ext_procs; ext; ext = ext->next) {
13411ab64890Smrg	    if (ext->error_values)
13421ab64890Smrg		(*ext->error_values)(dpy, event, fp);
13431ab64890Smrg	}
13441ab64890Smrg    } else if ((event->error_code == BadWindow) ||
13451ab64890Smrg	       (event->error_code == BadPixmap) ||
13461ab64890Smrg	       (event->error_code == BadCursor) ||
13471ab64890Smrg	       (event->error_code == BadFont) ||
13481ab64890Smrg	       (event->error_code == BadDrawable) ||
13491ab64890Smrg	       (event->error_code == BadColor) ||
13501ab64890Smrg	       (event->error_code == BadGC) ||
13511ab64890Smrg	       (event->error_code == BadIDChoice) ||
13521ab64890Smrg	       (event->error_code == BadValue) ||
13531ab64890Smrg	       (event->error_code == BadAtom)) {
13541ab64890Smrg	if (event->error_code == BadValue)
13551ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
13561ab64890Smrg				  mesg, BUFSIZ);
13571ab64890Smrg	else if (event->error_code == BadAtom)
13581ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
13591ab64890Smrg				  mesg, BUFSIZ);
13601ab64890Smrg	else
13611ab64890Smrg	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
13621ab64890Smrg				  mesg, BUFSIZ);
13631ab64890Smrg	fputs("  ", fp);
13641ab64890Smrg	(void) fprintf(fp, mesg, event->resourceid);
13651ab64890Smrg	fputs("\n", fp);
13661ab64890Smrg    }
136761b2299dSmrg    XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
13681ab64890Smrg			  mesg, BUFSIZ);
13691ab64890Smrg    fputs("  ", fp);
13701ab64890Smrg    (void) fprintf(fp, mesg, event->serial);
1371dac667f7Smrg    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
13721ab64890Smrg			  mesg, BUFSIZ);
13731ab64890Smrg    fputs("\n  ", fp);
1374dac667f7Smrg    (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
13751ab64890Smrg    fputs("\n", fp);
13761ab64890Smrg    if (event->error_code == BadImplementation) return 0;
13771ab64890Smrg    return 1;
13781ab64890Smrg}
13791ab64890Smrg
13801ab64890Smrgint _XDefaultError(
13811ab64890Smrg	Display *dpy,
13821ab64890Smrg	XErrorEvent *event)
13831ab64890Smrg{
13841ab64890Smrg    if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
1385bd8e7fb0Smrg
1386bd8e7fb0Smrg    /*
1387bd8e7fb0Smrg     * Store in dpy flags that the client is exiting on an unhandled XError
1388bd8e7fb0Smrg     * (pretend it is an IOError, since the application is dying anyway it
1389bd8e7fb0Smrg     * does not make a difference).
1390bd8e7fb0Smrg     * This is useful for _XReply not to hang if the application makes Xlib
1391bd8e7fb0Smrg     * calls in _fini as part of process termination.
1392bd8e7fb0Smrg     */
1393bd8e7fb0Smrg    dpy->flags |= XlibDisplayIOError;
1394bd8e7fb0Smrg
13951ab64890Smrg    exit(1);
13961ab64890Smrg    /*NOTREACHED*/
13971ab64890Smrg}
13981ab64890Smrg
13991ab64890Smrg/*ARGSUSED*/
140061b2299dSmrgBool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
14011ab64890Smrg{
14021ab64890Smrg    return True;
14031ab64890Smrg}
14041ab64890Smrg
14051ab64890Smrg/*
14061ab64890Smrg * _XError - upcall internal or user protocol error handler
14071ab64890Smrg */
14081ab64890Smrgint _XError (
14091ab64890Smrg    Display *dpy,
14101ab64890Smrg    register xError *rep)
14111ab64890Smrg{
141261b2299dSmrg    /*
14131ab64890Smrg     * X_Error packet encountered!  We need to unpack the error before
14141ab64890Smrg     * giving it to the user.
14151ab64890Smrg     */
14161ab64890Smrg    XEvent event; /* make it a large event */
14171ab64890Smrg    register _XAsyncHandler *async, *next;
14181ab64890Smrg
14191ab64890Smrg    event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
14201ab64890Smrg
14211ab64890Smrg    for (async = dpy->async_handlers; async; async = next) {
14221ab64890Smrg	next = async->next;
14231ab64890Smrg	if ((*async->handler)(dpy, (xReply *)rep,
14241ab64890Smrg			      (char *)rep, SIZEOF(xError), async->data))
14251ab64890Smrg	    return 0;
14261ab64890Smrg    }
14271ab64890Smrg
14281ab64890Smrg    event.xerror.display = dpy;
14291ab64890Smrg    event.xerror.type = X_Error;
14301ab64890Smrg    event.xerror.resourceid = rep->resourceID;
14311ab64890Smrg    event.xerror.error_code = rep->errorCode;
14321ab64890Smrg    event.xerror.request_code = rep->majorCode;
14331ab64890Smrg    event.xerror.minor_code = rep->minorCode;
14341ab64890Smrg    if (dpy->error_vec &&
14351ab64890Smrg	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
14361ab64890Smrg	return 0;
14371ab64890Smrg    if (_XErrorFunction != NULL) {
1438c17aa6b1Smrg	int rtn_val;
1439c17aa6b1Smrg#ifdef XTHREADS
1440c17aa6b1Smrg	if (dpy->lock)
1441c17aa6b1Smrg	    (*dpy->lock->user_lock_display)(dpy);
1442c17aa6b1Smrg	UnlockDisplay(dpy);
1443c17aa6b1Smrg#endif
1444c17aa6b1Smrg	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
1445c17aa6b1Smrg#ifdef XTHREADS
1446c17aa6b1Smrg	LockDisplay(dpy);
1447c17aa6b1Smrg	if (dpy->lock)
1448c17aa6b1Smrg	    (*dpy->lock->user_unlock_display)(dpy);
1449c17aa6b1Smrg#endif
1450c17aa6b1Smrg	return rtn_val;
14511ab64890Smrg    } else {
14521ab64890Smrg	return _XDefaultError(dpy, (XErrorEvent *)&event);
14531ab64890Smrg    }
14541ab64890Smrg}
145561b2299dSmrg
14561ab64890Smrg/*
14571ab64890Smrg * _XIOError - call user connection error handler and exit
14581ab64890Smrg */
14591ab64890Smrgint
14601ab64890Smrg_XIOError (
14611ab64890Smrg    Display *dpy)
14621ab64890Smrg{
14631ab64890Smrg    dpy->flags |= XlibDisplayIOError;
14641ab64890Smrg#ifdef WIN32
14651ab64890Smrg    errno = WSAGetLastError();
14661ab64890Smrg#endif
14671ab64890Smrg
14681ab64890Smrg    /* This assumes that the thread calling exit will call any atexit handlers.
14691ab64890Smrg     * If this does not hold, then an alternate solution would involve
14701ab64890Smrg     * registering an atexit handler to take over the lock, which would only
14711ab64890Smrg     * assume that the same thread calls all the atexit handlers. */
14721ab64890Smrg#ifdef XTHREADS
14731ab64890Smrg    if (dpy->lock)
14741ab64890Smrg	(*dpy->lock->user_lock_display)(dpy);
14751ab64890Smrg#endif
14761ab64890Smrg    UnlockDisplay(dpy);
14771ab64890Smrg
14781ab64890Smrg    if (_XIOErrorFunction != NULL)
14791ab64890Smrg	(*_XIOErrorFunction)(dpy);
14801ab64890Smrg    else
14811ab64890Smrg	_XDefaultIOError(dpy);
14821ab64890Smrg    exit (1);
1483dac667f7Smrg    /*NOTREACHED*/
14841ab64890Smrg}
14851ab64890Smrg
14861ab64890Smrg
14871ab64890Smrg/*
14881ab64890Smrg * This routine can be used to (cheaply) get some memory within a single
14891ab64890Smrg * Xlib routine for scratch space.  A single buffer is reused each time
14901ab64890Smrg * if possible.  To be MT safe, you can only call this between a call to
14911ab64890Smrg * GetReq* and a call to Data* or _XSend*, or in a context when the thread
14921ab64890Smrg * is guaranteed to not unlock the display.
14931ab64890Smrg */
14941ab64890Smrgchar *_XAllocScratch(
14951ab64890Smrg	register Display *dpy,
14961ab64890Smrg	unsigned long nbytes)
14971ab64890Smrg{
14981ab64890Smrg	if (nbytes > dpy->scratch_length) {
1499cf2acddeSmrg	    Xfree (dpy->scratch_buffer);
1500cf2acddeSmrg	    dpy->scratch_buffer = Xmalloc(nbytes);
1501cf2acddeSmrg	    if (dpy->scratch_buffer)
15021ab64890Smrg		dpy->scratch_length = nbytes;
15031ab64890Smrg	    else dpy->scratch_length = 0;
15041ab64890Smrg	}
15051ab64890Smrg	return (dpy->scratch_buffer);
15061ab64890Smrg}
15071ab64890Smrg
15081ab64890Smrg/*
15091ab64890Smrg * Scratch space allocator you can call any time, multiple times, and be
15101ab64890Smrg * MT safe, but you must hand the buffer back with _XFreeTemp.
15111ab64890Smrg */
15121ab64890Smrgchar *_XAllocTemp(
15131ab64890Smrg    register Display *dpy,
15141ab64890Smrg    unsigned long nbytes)
15151ab64890Smrg{
15161ab64890Smrg    char *buf;
15171ab64890Smrg
15181ab64890Smrg    buf = _XAllocScratch(dpy, nbytes);
15191ab64890Smrg    dpy->scratch_buffer = NULL;
15201ab64890Smrg    dpy->scratch_length = 0;
15211ab64890Smrg    return buf;
15221ab64890Smrg}
15231ab64890Smrg
15241ab64890Smrgvoid _XFreeTemp(
15251ab64890Smrg    register Display *dpy,
15261ab64890Smrg    char *buf,
15271ab64890Smrg    unsigned long nbytes)
15281ab64890Smrg{
1529cf2acddeSmrg
1530cf2acddeSmrg    Xfree(dpy->scratch_buffer);
15311ab64890Smrg    dpy->scratch_buffer = buf;
15321ab64890Smrg    dpy->scratch_length = nbytes;
15331ab64890Smrg}
15341ab64890Smrg
15351ab64890Smrg/*
15361ab64890Smrg * Given a visual id, find the visual structure for this id on this display.
15371ab64890Smrg */
15381ab64890SmrgVisual *_XVIDtoVisual(
15391ab64890Smrg	Display *dpy,
15401ab64890Smrg	VisualID id)
15411ab64890Smrg{
15421ab64890Smrg	register int i, j, k;
15431ab64890Smrg	register Screen *sp;
15441ab64890Smrg	register Depth *dp;
15451ab64890Smrg	register Visual *vp;
15461ab64890Smrg	for (i = 0; i < dpy->nscreens; i++) {
15471ab64890Smrg		sp = &dpy->screens[i];
15481ab64890Smrg		for (j = 0; j < sp->ndepths; j++) {
15491ab64890Smrg			dp = &sp->depths[j];
15501ab64890Smrg			/* if nvisuals == 0 then visuals will be NULL */
15511ab64890Smrg			for (k = 0; k < dp->nvisuals; k++) {
15521ab64890Smrg				vp = &dp->visuals[k];
15531ab64890Smrg				if (vp->visualid == id) return (vp);
15541ab64890Smrg			}
15551ab64890Smrg		}
15561ab64890Smrg	}
15571ab64890Smrg	return (NULL);
15581ab64890Smrg}
15591ab64890Smrg
15601ab64890Smrgint
15611ab64890SmrgXFree (void *data)
15621ab64890Smrg{
15631ab64890Smrg	Xfree (data);
15641ab64890Smrg	return 1;
15651ab64890Smrg}
15661ab64890Smrg
15671ab64890Smrg#ifdef _XNEEDBCOPYFUNC
15681ab64890Smrgvoid _Xbcopy(b1, b2, length)
15691ab64890Smrg    register char *b1, *b2;
15701ab64890Smrg    register length;
15711ab64890Smrg{
15721ab64890Smrg    if (b1 < b2) {
15731ab64890Smrg	b2 += length;
15741ab64890Smrg	b1 += length;
15751ab64890Smrg	while (length--)
15761ab64890Smrg	    *--b2 = *--b1;
15771ab64890Smrg    } else {
15781ab64890Smrg	while (length--)
15791ab64890Smrg	    *b2++ = *b1++;
15801ab64890Smrg    }
15811ab64890Smrg}
15821ab64890Smrg#endif
15831ab64890Smrg
15841ab64890Smrg#ifdef DataRoutineIsProcedure
15851ab64890Smrgvoid Data(
15861ab64890Smrg	Display *dpy,
1587556b6652Smrg	_Xconst char *data,
15881ab64890Smrg	long len)
15891ab64890Smrg{
15901ab64890Smrg	if (dpy->bufptr + (len) <= dpy->bufmax) {
15911ab64890Smrg		memcpy(dpy->bufptr, data, (int)len);
15921ab64890Smrg		dpy->bufptr += ((len) + 3) & ~3;
15931ab64890Smrg	} else {
15941ab64890Smrg		_XSend(dpy, data, len);
15951ab64890Smrg	}
15961ab64890Smrg}
15971ab64890Smrg#endif /* DataRoutineIsProcedure */
15981ab64890Smrg
15991ab64890Smrg
16001ab64890Smrg#ifdef LONG64
16011ab64890Smrgint
16021ab64890Smrg_XData32(
16031ab64890Smrg    Display *dpy,
1604556b6652Smrg    register _Xconst long *data,
16051ab64890Smrg    unsigned len)
16061ab64890Smrg{
16071ab64890Smrg    register int *buf;
16081ab64890Smrg    register long i;
16091ab64890Smrg
16101ab64890Smrg    while (len) {
16111ab64890Smrg	buf = (int *)dpy->bufptr;
16121ab64890Smrg	i = dpy->bufmax - (char *)buf;
16131ab64890Smrg	if (!i) {
16141ab64890Smrg	    _XFlush(dpy);
16151ab64890Smrg	    continue;
16161ab64890Smrg	}
16171ab64890Smrg	if (len < i)
16181ab64890Smrg	    i = len;
16191ab64890Smrg	dpy->bufptr = (char *)buf + i;
16201ab64890Smrg	len -= i;
16211ab64890Smrg	i >>= 2;
16221ab64890Smrg	while (--i >= 0)
16231ab64890Smrg	    *buf++ = *data++;
16241ab64890Smrg    }
16251ab64890Smrg    return 0;
16261ab64890Smrg}
16271ab64890Smrg#endif /* LONG64 */
16281ab64890Smrg
16291ab64890Smrg
16301ab64890Smrg
16311ab64890Smrg/* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
16321ab64890Smrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
16331ab64890Smrg *
16341ab64890Smrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
16351ab64890Smrg *       to have sufficient information for interfacing to the network,
16361ab64890Smrg *       and so, you may be better off using gethostname (if it exists).
16371ab64890Smrg */
16381ab64890Smrg
16392e9c7c8cSmrg#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(SVR4)
16401ab64890Smrg#define NEED_UTSNAME
16411ab64890Smrg#include <sys/utsname.h>
164288de56ccSmrg#else
164388de56ccSmrg#ifdef HAVE_UNISTD_H
164488de56ccSmrg#include <unistd.h>
164588de56ccSmrg#endif
16461ab64890Smrg#endif
16471ab64890Smrg
16481ab64890Smrg/*
16491ab64890Smrg * _XGetHostname - similar to gethostname but allows special processing.
16501ab64890Smrg */
16511ab64890Smrgint _XGetHostname (
16521ab64890Smrg    char *buf,
16531ab64890Smrg    int maxlen)
16541ab64890Smrg{
16551ab64890Smrg    int len;
16561ab64890Smrg
16571ab64890Smrg#ifdef NEED_UTSNAME
16581ab64890Smrg    struct utsname name;
16591ab64890Smrg
16601ab64890Smrg    if (maxlen <= 0 || buf == NULL)
16611ab64890Smrg	return 0;
16621ab64890Smrg
16631ab64890Smrg    uname (&name);
16641ab64890Smrg    len = strlen (name.nodename);
16651ab64890Smrg    if (len >= maxlen) len = maxlen - 1;
16661ab64890Smrg    strncpy (buf, name.nodename, len);
16671ab64890Smrg    buf[len] = '\0';
16681ab64890Smrg#else
16691ab64890Smrg    if (maxlen <= 0 || buf == NULL)
16701ab64890Smrg	return 0;
16711ab64890Smrg
16721ab64890Smrg    buf[0] = '\0';
16731ab64890Smrg    (void) gethostname (buf, maxlen);
16741ab64890Smrg    buf [maxlen - 1] = '\0';
16751ab64890Smrg    len = strlen(buf);
16761ab64890Smrg#endif /* NEED_UTSNAME */
16771ab64890Smrg    return len;
16781ab64890Smrg}
16791ab64890Smrg
16801ab64890Smrg
16811ab64890Smrg/*
16821ab64890Smrg * _XScreenOfWindow - get the Screen of a given window
16831ab64890Smrg */
16841ab64890Smrg
168561b2299dSmrgScreen *_XScreenOfWindow(Display *dpy, Window w)
16861ab64890Smrg{
16871ab64890Smrg    register int i;
16881ab64890Smrg    Window root;
16891ab64890Smrg    int x, y;				/* dummy variables */
16901ab64890Smrg    unsigned int width, height, bw, depth;  /* dummy variables */
16911ab64890Smrg
16921ab64890Smrg    if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
16931ab64890Smrg		      &bw, &depth) == False) {
16942e9c7c8cSmrg	return NULL;
16951ab64890Smrg    }
16961ab64890Smrg    for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
16971ab64890Smrg	if (root == RootWindow (dpy, i)) {
16981ab64890Smrg	    return ScreenOfDisplay (dpy, i);
16991ab64890Smrg	}
17001ab64890Smrg    }
17011ab64890Smrg    return NULL;
17021ab64890Smrg}
17031ab64890Smrg
17041ab64890Smrg
1705556b6652Smrg/*
1706556b6652Smrg * WARNING: This implementation's pre-conditions and post-conditions
1707556b6652Smrg * must remain compatible with the old macro-based implementations of
1708556b6652Smrg * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
1709556b6652Smrg * Display structure affected by those macros are part of libX11's
1710556b6652Smrg * ABI.
1711556b6652Smrg */
1712556b6652Smrgvoid *_XGetRequest(Display *dpy, CARD8 type, size_t len)
1713556b6652Smrg{
1714556b6652Smrg    xReq *req;
1715556b6652Smrg
1716556b6652Smrg    if (dpy->bufptr + len > dpy->bufmax)
1717556b6652Smrg	_XFlush(dpy);
1718c555af55Smrg    /* Request still too large, so do not allow it to overflow. */
1719c555af55Smrg    if (dpy->bufptr + len > dpy->bufmax) {
1720c555af55Smrg	fprintf(stderr,
1721c555af55Smrg		"Xlib: request %d length %zd would exceed buffer size.\n",
1722c555af55Smrg		type, len);
1723c555af55Smrg	/* Changes failure condition from overflow to NULL dereference. */
1724c555af55Smrg	return NULL;
1725c555af55Smrg    }
1726556b6652Smrg
1727556b6652Smrg    if (len % 4)
1728556b6652Smrg	fprintf(stderr,
1729556b6652Smrg		"Xlib: request %d length %zd not a multiple of 4.\n",
1730556b6652Smrg		type, len);
1731556b6652Smrg
1732556b6652Smrg    dpy->last_req = dpy->bufptr;
1733556b6652Smrg
1734556b6652Smrg    req = (xReq*)dpy->bufptr;
1735556b6652Smrg    req->reqType = type;
1736556b6652Smrg    req->length = len / 4;
1737556b6652Smrg    dpy->bufptr += len;
1738dac667f7Smrg    X_DPY_REQUEST_INCREMENT(dpy);
1739556b6652Smrg    return req;
1740556b6652Smrg}
1741556b6652Smrg
17421ab64890Smrg#if defined(WIN32)
17431ab64890Smrg
17441ab64890Smrg/*
17451ab64890Smrg * These functions are intended to be used internally to Xlib only.
17461ab64890Smrg * These functions will always prefix the path with a DOS drive in the
17471ab64890Smrg * form "<drive-letter>:". As such, these functions are only suitable
17481ab64890Smrg * for use by Xlib function that supply a root-based path to some
17491ab64890Smrg * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
17501ab64890Smrg * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
17511ab64890Smrg */
17521ab64890Smrg
17531ab64890Smrgstatic int access_file (path, pathbuf, len_pathbuf, pathret)
17541ab64890Smrg    char* path;
17551ab64890Smrg    char* pathbuf;
17561ab64890Smrg    int len_pathbuf;
17571ab64890Smrg    char** pathret;
17581ab64890Smrg{
17591ab64890Smrg    if (access (path, F_OK) == 0) {
17601ab64890Smrg	if (strlen (path) < len_pathbuf)
17611ab64890Smrg	    *pathret = pathbuf;
17621ab64890Smrg	else
17631ab64890Smrg	    *pathret = Xmalloc (strlen (path) + 1);
17641ab64890Smrg	if (*pathret) {
17651ab64890Smrg	    strcpy (*pathret, path);
17661ab64890Smrg	    return 1;
17671ab64890Smrg	}
17681ab64890Smrg    }
17691ab64890Smrg    return 0;
17701ab64890Smrg}
17711ab64890Smrg
17721ab64890Smrgstatic int AccessFile (path, pathbuf, len_pathbuf, pathret)
17731ab64890Smrg    char* path;
17741ab64890Smrg    char* pathbuf;
17751ab64890Smrg    int len_pathbuf;
17761ab64890Smrg    char** pathret;
17771ab64890Smrg{
17781ab64890Smrg    unsigned long drives;
17791ab64890Smrg    int i, len;
17801ab64890Smrg    char* drive;
17811ab64890Smrg    char buf[MAX_PATH];
17821ab64890Smrg    char* bufp;
17831ab64890Smrg
17841ab64890Smrg    /* just try the "raw" name first and see if it works */
17851ab64890Smrg    if (access_file (path, pathbuf, len_pathbuf, pathret))
17861ab64890Smrg	return 1;
17871ab64890Smrg
17881ab64890Smrg    /* try the places set in the environment */
17891ab64890Smrg    drive = getenv ("_XBASEDRIVE");
17901ab64890Smrg#ifdef __UNIXOS2__
17911ab64890Smrg    if (!drive)
17921ab64890Smrg	drive = getenv ("X11ROOT");
17931ab64890Smrg#endif
17941ab64890Smrg    if (!drive)
17951ab64890Smrg	drive = "C:";
17961ab64890Smrg    len = strlen (drive) + strlen (path);
17971ab64890Smrg    if (len < MAX_PATH) bufp = buf;
17981ab64890Smrg    else bufp = Xmalloc (len + 1);
17991ab64890Smrg    strcpy (bufp, drive);
18001ab64890Smrg    strcat (bufp, path);
18011ab64890Smrg    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18021ab64890Smrg	if (bufp != buf) Xfree (bufp);
18031ab64890Smrg	return 1;
18041ab64890Smrg    }
18051ab64890Smrg
180661b2299dSmrg#ifndef __UNIXOS2__
18071ab64890Smrg    /* one last place to look */
18081ab64890Smrg    drive = getenv ("HOMEDRIVE");
18091ab64890Smrg    if (drive) {
18101ab64890Smrg	len = strlen (drive) + strlen (path);
18111ab64890Smrg	if (len < MAX_PATH) bufp = buf;
18121ab64890Smrg	else bufp = Xmalloc (len + 1);
18131ab64890Smrg	strcpy (bufp, drive);
18141ab64890Smrg	strcat (bufp, path);
18151ab64890Smrg	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18161ab64890Smrg	    if (bufp != buf) Xfree (bufp);
18171ab64890Smrg	    return 1;
18181ab64890Smrg	}
18191ab64890Smrg    }
18201ab64890Smrg
18211ab64890Smrg    /* tried everywhere else, go fishing */
18221ab64890Smrg#define C_DRIVE ('C' - 'A')
18231ab64890Smrg#define Z_DRIVE ('Z' - 'A')
18241ab64890Smrg    /* does OS/2 (with or with gcc-emx) have getdrives? */
18251ab64890Smrg    drives = _getdrives ();
18261ab64890Smrg    for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
18271ab64890Smrg	if ((1 << i) & drives) {
18281ab64890Smrg	    len = 2 + strlen (path);
18291ab64890Smrg	    if (len < MAX_PATH) bufp = buf;
18301ab64890Smrg	    else bufp = Xmalloc (len + 1);
18311ab64890Smrg	    *bufp = 'A' + i;
18321ab64890Smrg	    *(bufp + 1) = ':';
18331ab64890Smrg	    *(bufp + 2) = '\0';
18341ab64890Smrg	    strcat (bufp, path);
18351ab64890Smrg	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
18361ab64890Smrg		if (bufp != buf) Xfree (bufp);
18371ab64890Smrg		return 1;
18381ab64890Smrg	    }
18391ab64890Smrg	}
18401ab64890Smrg    }
18411ab64890Smrg#endif
18421ab64890Smrg    return 0;
18431ab64890Smrg}
18441ab64890Smrg
18451ab64890Smrgint _XOpenFile(path, flags)
18461ab64890Smrg    _Xconst char* path;
18471ab64890Smrg    int flags;
18481ab64890Smrg{
18491ab64890Smrg    char buf[MAX_PATH];
18501ab64890Smrg    char* bufp = NULL;
18511ab64890Smrg    int ret = -1;
18521ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
18531ab64890Smrg
18541ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
18551ab64890Smrg	ret = open (bufp, flags);
18561ab64890Smrg
18571ab64890Smrg    (void) SetErrorMode (olderror);
18581ab64890Smrg
18591ab64890Smrg    if (bufp != buf) Xfree (bufp);
18601ab64890Smrg
18611ab64890Smrg    return ret;
18621ab64890Smrg}
18631ab64890Smrg
18641ab64890Smrgint _XOpenFileMode(path, flags, mode)
18651ab64890Smrg    _Xconst char* path;
18661ab64890Smrg    int flags;
18671ab64890Smrg    mode_t mode;
18681ab64890Smrg{
18691ab64890Smrg    char buf[MAX_PATH];
18701ab64890Smrg    char* bufp = NULL;
18711ab64890Smrg    int ret = -1;
18721ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
18731ab64890Smrg
18741ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
18751ab64890Smrg	ret = open (bufp, flags, mode);
18761ab64890Smrg
18771ab64890Smrg    (void) SetErrorMode (olderror);
18781ab64890Smrg
18791ab64890Smrg    if (bufp != buf) Xfree (bufp);
18801ab64890Smrg
18811ab64890Smrg    return ret;
18821ab64890Smrg}
18831ab64890Smrg
18841ab64890Smrgvoid* _XFopenFile(path, mode)
18851ab64890Smrg    _Xconst char* path;
18861ab64890Smrg    _Xconst char* mode;
18871ab64890Smrg{
18881ab64890Smrg    char buf[MAX_PATH];
18891ab64890Smrg    char* bufp = NULL;
18901ab64890Smrg    void* ret = NULL;
18911ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
18921ab64890Smrg
18931ab64890Smrg    if (AccessFile (path, buf, MAX_PATH, &bufp))
18941ab64890Smrg	ret = fopen (bufp, mode);
18951ab64890Smrg
18961ab64890Smrg    (void) SetErrorMode (olderror);
18971ab64890Smrg
18981ab64890Smrg    if (bufp != buf) Xfree (bufp);
18991ab64890Smrg
19001ab64890Smrg    return ret;
19011ab64890Smrg}
19021ab64890Smrg
19031ab64890Smrgint _XAccessFile(path)
19041ab64890Smrg    _Xconst char* path;
19051ab64890Smrg{
19061ab64890Smrg    char buf[MAX_PATH];
19071ab64890Smrg    char* bufp;
19081ab64890Smrg    int ret = -1;
19091ab64890Smrg    UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
19101ab64890Smrg
19111ab64890Smrg    ret = AccessFile (path, buf, MAX_PATH, &bufp);
19121ab64890Smrg
19131ab64890Smrg    (void) SetErrorMode (olderror);
19141ab64890Smrg
19151ab64890Smrg    if (bufp != buf) Xfree (bufp);
19161ab64890Smrg
19171ab64890Smrg    return ret;
19181ab64890Smrg}
19191ab64890Smrg
19201ab64890Smrg#endif
19211ab64890Smrg
19221ab64890Smrg#ifdef WIN32
19231ab64890Smrg#undef _Xdebug
19241ab64890Smrgint _Xdebug = 0;
19251ab64890Smrgint *_Xdebug_p = &_Xdebug;
19261ab64890Smrgvoid (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
19271ab64890Smrgvoid (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
19281ab64890Smrgvoid (**_XLockMutex_fn_p)(LockInfoPtr
19291ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19301ab64890Smrg    , char * /* file */
19311ab64890Smrg    , int /* line */
19321ab64890Smrg#endif
19331ab64890Smrg        ) = &_XLockMutex_fn;
19341ab64890Smrgvoid (**_XUnlockMutex_fn_p)(LockInfoPtr
19351ab64890Smrg#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
19361ab64890Smrg    , char * /* file */
19371ab64890Smrg    , int /* line */
19381ab64890Smrg#endif
19391ab64890Smrg        ) = &_XUnlockMutex_fn;
19401ab64890SmrgLockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
19411ab64890Smrg#endif
1942