Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1985, 1986, 1987, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall
     23 not be used in advertising or otherwise to promote the sale, use or
     24 other dealings in this Software without prior written authorization
     25 from The Open Group.
     26 
     27 */
     28 
     29 /*
     30  *	XlibInt.c - Internal support routines for the C subroutine
     31  *	interface library (Xlib) to the X Window System Protocol V11.0.
     32  */
     33 
     34 #ifdef WIN32
     35 #define _XLIBINT_
     36 #endif
     37 #ifdef HAVE_CONFIG_H
     38 #include <config.h>
     39 #endif
     40 #include "Xlibint.h"
     41 #include "Xprivate.h"
     42 #include "reallocarray.h"
     43 #include <X11/Xpoll.h>
     44 #include <assert.h>
     45 #include <stdio.h>
     46 #ifdef WIN32
     47 #include <direct.h>
     48 #endif
     49 
     50 /* Needed for FIONREAD on Solaris */
     51 #ifdef HAVE_SYS_FILIO_H
     52 #include <sys/filio.h>
     53 #endif
     54 
     55 /* Needed for FIONREAD on Cygwin */
     56 #ifdef HAVE_SYS_SOCKET_H
     57 #include <sys/socket.h>
     58 #endif
     59 
     60 /* Needed for ioctl() on Solaris */
     61 #ifdef HAVE_UNISTD_H
     62 #include <unistd.h>
     63 #endif
     64 
     65 #ifdef XTHREADS
     66 #include "locking.h"
     67 
     68 #ifdef HAVE_SYS_IOCTL_H
     69 #include <sys/ioctl.h>
     70 #endif
     71 
     72 /* these pointers get initialized by XInitThreads */
     73 LockInfoPtr _Xglobal_lock = NULL;
     74 void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
     75 /* struct _XCVList *(*_XCreateCVL_fn)() = NULL; */
     76 void (*_XFreeMutex_fn)(LockInfoPtr) = NULL;
     77 void (*_XLockMutex_fn)(
     78     LockInfoPtr /* lock */
     79 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
     80     , char * /* file */
     81     , int /* line */
     82 #endif
     83     ) = NULL;
     84 void (*_XUnlockMutex_fn)(
     85     LockInfoPtr /* lock */
     86 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
     87     , char * /* file */
     88     , int /* line */
     89 #endif
     90     ) = NULL;
     91 xthread_t (*_Xthread_self_fn)(void) = NULL;
     92 
     93 #define XThread_Self()	((*_Xthread_self_fn)())
     94 
     95 #endif /* XTHREADS */
     96 
     97 #ifdef WIN32
     98 #define ECHECK(err) (WSAGetLastError() == err)
     99 #define ESET(val) WSASetLastError(val)
    100 #else
    101 #define ECHECK(err) (errno == err)
    102 #define ESET(val) errno = val
    103 #endif
    104 
    105 
    106 /*
    107  * The following routines are internal routines used by Xlib for protocol
    108  * packet transmission and reception.
    109  *
    110  * _XIOError(Display *) will be called if any sort of system call error occurs.
    111  * This is assumed to be a fatal condition, i.e., XIOError should not return.
    112  *
    113  * _XError(Display *, xError *) will be called whenever an X_Error event is
    114  * received.  This is not assumed to be a fatal condition, i.e., it is
    115  * acceptable for this procedure to return.  However, XError should NOT
    116  * perform any operations (directly or indirectly) on the DISPLAY.
    117  *
    118  * Routines declared with a return type of 'Status' return 0 on failure,
    119  * and non 0 on success.  Routines with no declared return type don't
    120  * return anything.  Whenever possible routines that create objects return
    121  * the object they have created.
    122  */
    123 
    124 #define POLLFD_CACHE_SIZE 5
    125 
    126 /* initialize the struct array passed to poll() below */
    127 Bool _XPollfdCacheInit(
    128     Display *dpy)
    129 {
    130 #ifdef USE_POLL
    131     struct pollfd *pfp;
    132 
    133     pfp = Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
    134     if (!pfp)
    135 	return False;
    136     pfp[0].fd = dpy->fd;
    137     pfp[0].events = POLLIN;
    138 
    139     dpy->filedes = (XPointer)pfp;
    140 #endif
    141     return True;
    142 }
    143 
    144 void _XPollfdCacheAdd(
    145     Display *dpy,
    146     int fd)
    147 {
    148 #ifdef USE_POLL
    149     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
    150 
    151     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
    152 	pfp[dpy->im_fd_length].fd = fd;
    153 	pfp[dpy->im_fd_length].events = POLLIN;
    154     }
    155 #endif
    156 }
    157 
    158 /* ARGSUSED */
    159 void _XPollfdCacheDel(
    160     Display *dpy,
    161     int fd)			/* not used */
    162 {
    163 #ifdef USE_POLL
    164     struct pollfd *pfp = (struct pollfd *)dpy->filedes;
    165     struct _XConnectionInfo *conni;
    166 
    167     /* just recalculate whole list */
    168     if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
    169 	int loc = 1;
    170 	for (conni = dpy->im_fd_info; conni; conni=conni->next) {
    171 	    pfp[loc].fd = conni->fd;
    172 	    pfp[loc].events = POLLIN;
    173 	    loc++;
    174 	}
    175     }
    176 #endif
    177 }
    178 
    179 static int sync_hazard(Display *dpy)
    180 {
    181     /*
    182      * "span" and "hazard" need to be signed such that the ">=" comparison
    183      * works correctly in the case that hazard is greater than 65525
    184      */
    185     int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
    186     int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
    187     return span >= 65535 - hazard - 10;
    188 }
    189 
    190 static
    191 void sync_while_locked(Display *dpy)
    192 {
    193 #ifdef XTHREADS
    194     if (dpy->lock)
    195         (*dpy->lock->user_lock_display)(dpy);
    196 #endif
    197     UnlockDisplay(dpy);
    198     SyncHandle();
    199     InternalLockDisplay(dpy, /* don't skip user locks */ 0);
    200 #ifdef XTHREADS
    201     if (dpy->lock)
    202         (*dpy->lock->user_unlock_display)(dpy);
    203 #endif
    204 }
    205 
    206 void _XSeqSyncFunction(
    207     register Display *dpy)
    208 {
    209     xGetInputFocusReply rep;
    210     _X_UNUSED register xReq *req;
    211 
    212     if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy)) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
    213 	GetEmptyReq(GetInputFocus, req);
    214 	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
    215 	sync_while_locked(dpy);
    216     } else if (sync_hazard(dpy))
    217 	_XSetPrivSyncFunction(dpy);
    218 }
    219 
    220 /* NOTE: only called if !XTHREADS, or when XInitThreads wasn't called. */
    221 static int
    222 _XPrivSyncFunction (Display *dpy)
    223 {
    224 #ifdef XTHREADS
    225     assert(!dpy->lock_fns);
    226 #endif
    227     assert(dpy->synchandler == _XPrivSyncFunction);
    228     assert((dpy->flags & XlibDisplayPrivSync) != 0);
    229     dpy->synchandler = dpy->savedsynchandler;
    230     dpy->savedsynchandler = NULL;
    231     dpy->flags &= ~XlibDisplayPrivSync;
    232     if(dpy->synchandler)
    233         dpy->synchandler(dpy);
    234     _XIDHandler(dpy);
    235     _XSeqSyncFunction(dpy);
    236     return 0;
    237 }
    238 
    239 void _XSetPrivSyncFunction(Display *dpy)
    240 {
    241 #ifdef XTHREADS
    242     if (dpy->lock_fns)
    243         return;
    244 #endif
    245     if (!(dpy->flags & XlibDisplayPrivSync)) {
    246 	dpy->savedsynchandler = dpy->synchandler;
    247 	dpy->synchandler = _XPrivSyncFunction;
    248 	dpy->flags |= XlibDisplayPrivSync;
    249     }
    250 }
    251 
    252 void _XSetSeqSyncFunction(Display *dpy)
    253 {
    254     if (sync_hazard(dpy))
    255 	_XSetPrivSyncFunction (dpy);
    256 }
    257 
    258 #ifdef LONG64
    259 void _XRead32(
    260     Display *dpy,
    261     long *data,
    262     long len)
    263 {
    264     register int *buf;
    265     register long i;
    266 
    267     if (len) {
    268 	(void) _XRead(dpy, (char *)data, len);
    269 	i = len >> 2;
    270 	buf = (int *)data + i;
    271 	data += i;
    272 	while (--i >= 0)
    273 	    *--data = *--buf;
    274     }
    275 }
    276 #endif /* LONG64 */
    277 
    278 
    279 /*
    280  * The hard part about this is that we only get 16 bits from a reply.
    281  * We have three values that will march along, with the following invariant:
    282  *	dpy->last_request_read <= rep->sequenceNumber <= dpy->request
    283  * We have to keep
    284  *	dpy->request - dpy->last_request_read < 2^16
    285  * or else we won't know for sure what value to use in events.  We do this
    286  * by forcing syncs when we get close.
    287  */
    288 
    289 unsigned long
    290 _XSetLastRequestRead(
    291     register Display *dpy,
    292     register xGenericReply *rep)
    293 {
    294     register uint64_t	newseq, lastseq;
    295 
    296     lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
    297     /*
    298      * KeymapNotify has no sequence number, but is always guaranteed
    299      * to immediately follow another event, except when generated via
    300      * SendEvent (hmmm).
    301      */
    302     if ((rep->type & 0x7f) == KeymapNotify)
    303 	return(lastseq);
    304 
    305     newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
    306 
    307     if (newseq < lastseq) {
    308 	newseq += 0x10000;
    309 	if (newseq > X_DPY_GET_REQUEST(dpy)) {
    310 	    (void) fprintf (stderr,
    311 	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
    312 			    (unsigned long long)newseq,
    313 			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
    314 			    (unsigned int) rep->type);
    315 	    newseq -= 0x10000;
    316 	}
    317     }
    318 
    319     X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
    320     return(newseq);
    321 }
    322 
    323 /*
    324  * Support for internal connections, such as an IM might use.
    325  * By Stephen Gildea, X Consortium, September 1993
    326  */
    327 
    328 /* _XRegisterInternalConnection
    329  * Each IM (or Xlib extension) that opens a file descriptor that Xlib should
    330  * include in its select/poll mask must call this function to register the
    331  * fd with Xlib.  Any XConnectionWatchProc registered by XAddConnectionWatch
    332  * will also be called.
    333  *
    334  * Whenever Xlib detects input available on fd, it will call callback
    335  * with call_data to process it.  If non-Xlib code calls select/poll
    336  * and detects input available, it must call XProcessInternalConnection,
    337  * which will call the associated callback.
    338  *
    339  * Non-Xlib code can learn about these additional fds by calling
    340  * XInternalConnectionNumbers or, more typically, by registering
    341  * a XConnectionWatchProc with XAddConnectionWatch
    342  * to be called when fds are registered or unregistered.
    343  *
    344  * Returns True if registration succeeded, False if not, typically
    345  * because could not allocate memory.
    346  * Assumes Display locked when called.
    347  */
    348 Status
    349 _XRegisterInternalConnection(
    350     Display* dpy,
    351     int fd,
    352     _XInternalConnectionProc callback,
    353     XPointer call_data
    354 )
    355 {
    356     struct _XConnectionInfo *new_conni, **iptr;
    357     struct _XConnWatchInfo *watchers;
    358     XPointer *wd;
    359 
    360     new_conni = Xmalloc(sizeof(struct _XConnectionInfo));
    361     if (!new_conni)
    362 	return 0;
    363     new_conni->watch_data = Xmallocarray(dpy->watcher_count, sizeof(XPointer));
    364     if (!new_conni->watch_data) {
    365 	Xfree(new_conni);
    366 	return 0;
    367     }
    368     new_conni->fd = fd;
    369     new_conni->read_callback = callback;
    370     new_conni->call_data = call_data;
    371     new_conni->next = NULL;
    372     /* link new structure onto end of list */
    373     for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
    374 	;
    375     *iptr = new_conni;
    376     dpy->im_fd_length++;
    377     _XPollfdCacheAdd(dpy, fd);
    378 
    379     for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
    380 	 watchers;
    381 	 watchers=watchers->next, wd++) {
    382 	*wd = NULL;		/* for cleanliness */
    383 	(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
    384     }
    385 
    386     return 1;
    387 }
    388 
    389 /* _XUnregisterInternalConnection
    390  * Each IM (or Xlib extension) that closes a file descriptor previously
    391  * registered with _XRegisterInternalConnection must call this function.
    392  * Any XConnectionWatchProc registered by XAddConnectionWatch
    393  * will also be called.
    394  *
    395  * Assumes Display locked when called.
    396  */
    397 void
    398 _XUnregisterInternalConnection(
    399     Display* dpy,
    400     int fd
    401 )
    402 {
    403     struct _XConnectionInfo *info_list, **prev;
    404     struct _XConnWatchInfo *watch;
    405     XPointer *wd;
    406 
    407     for (prev = &dpy->im_fd_info; (info_list = *prev);
    408 	 prev = &info_list->next) {
    409 	if (info_list->fd == fd) {
    410 	    *prev = info_list->next;
    411 	    dpy->im_fd_length--;
    412 	    for (watch=dpy->conn_watchers, wd=info_list->watch_data;
    413 		 watch;
    414 		 watch=watch->next, wd++) {
    415 		(*watch->fn) (dpy, watch->client_data, fd, False, wd);
    416 	    }
    417 	    Xfree (info_list->watch_data);
    418 	    Xfree (info_list);
    419 	    break;
    420 	}
    421     }
    422     _XPollfdCacheDel(dpy, fd);
    423 }
    424 
    425 /* XInternalConnectionNumbers
    426  * Returns an array of fds and an array of corresponding call data.
    427  * Typically a XConnectionWatchProc registered with XAddConnectionWatch
    428  * will be used instead of this function to discover
    429  * additional fds to include in the select/poll mask.
    430  *
    431  * The list is allocated with Xmalloc and should be freed by the caller
    432  * with Xfree;
    433  */
    434 Status
    435 XInternalConnectionNumbers(
    436     Display *dpy,
    437     int **fd_return,
    438     int *count_return
    439 )
    440 {
    441     int count;
    442     struct _XConnectionInfo *info_list;
    443     int *fd_list;
    444 
    445     LockDisplay(dpy);
    446     count = 0;
    447     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
    448 	count++;
    449     fd_list = Xmallocarray (count, sizeof(int));
    450     if (!fd_list) {
    451 	UnlockDisplay(dpy);
    452 	return 0;
    453     }
    454     count = 0;
    455     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
    456 	fd_list[count] = info_list->fd;
    457 	count++;
    458     }
    459     UnlockDisplay(dpy);
    460 
    461     *fd_return = fd_list;
    462     *count_return = count;
    463     return 1;
    464 }
    465 
    466 void _XProcessInternalConnection(
    467     Display *dpy,
    468     struct _XConnectionInfo *conn_info)
    469 {
    470     dpy->flags |= XlibDisplayProcConni;
    471     UnlockDisplay(dpy);
    472     (*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
    473     LockDisplay(dpy);
    474     dpy->flags &= ~XlibDisplayProcConni;
    475 }
    476 
    477 /* XProcessInternalConnection
    478  * Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
    479  * for this fd.
    480  * The Display is NOT locked during the call.
    481  */
    482 void
    483 XProcessInternalConnection(
    484     Display* dpy,
    485     int fd
    486 )
    487 {
    488     struct _XConnectionInfo *info_list;
    489 
    490     LockDisplay(dpy);
    491     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
    492 	if (info_list->fd == fd) {
    493 	    _XProcessInternalConnection(dpy, info_list);
    494 	    break;
    495 	}
    496     }
    497     UnlockDisplay(dpy);
    498 }
    499 
    500 /* XAddConnectionWatch
    501  * Register a callback to be called whenever _XRegisterInternalConnection
    502  * or _XUnregisterInternalConnection is called.
    503  * Callbacks are called with the Display locked.
    504  * If any connections are already registered, the callback is immediately
    505  * called for each of them.
    506  */
    507 Status
    508 XAddConnectionWatch(
    509     Display* dpy,
    510     XConnectionWatchProc callback,
    511     XPointer client_data
    512 )
    513 {
    514     struct _XConnWatchInfo *new_watcher, **wptr;
    515     struct _XConnectionInfo *info_list;
    516     XPointer *wd_array;
    517 
    518     LockDisplay(dpy);
    519 
    520     /* allocate new watch data */
    521     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
    522 	wd_array = Xreallocarray(info_list->watch_data,
    523                                  dpy->watcher_count + 1, sizeof(XPointer));
    524 	if (!wd_array) {
    525 	    UnlockDisplay(dpy);
    526 	    return 0;
    527 	}
    528 	info_list->watch_data = wd_array;
    529 	wd_array[dpy->watcher_count] = NULL;	/* for cleanliness */
    530     }
    531 
    532     new_watcher = Xmalloc(sizeof(struct _XConnWatchInfo));
    533     if (!new_watcher) {
    534 	UnlockDisplay(dpy);
    535 	return 0;
    536     }
    537     new_watcher->fn = callback;
    538     new_watcher->client_data = client_data;
    539     new_watcher->next = NULL;
    540 
    541     /* link new structure onto end of list */
    542     for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
    543 	;
    544     *wptr = new_watcher;
    545     dpy->watcher_count++;
    546 
    547     /* call new watcher on all currently registered fds */
    548     for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
    549 	(*callback) (dpy, client_data, info_list->fd, True,
    550 		     info_list->watch_data + dpy->watcher_count - 1);
    551     }
    552 
    553     UnlockDisplay(dpy);
    554     return 1;
    555 }
    556 
    557 /* XRemoveConnectionWatch
    558  * Unregister a callback registered by XAddConnectionWatch.
    559  * Both callback and client_data must match what was passed to
    560  * XAddConnectionWatch.
    561  */
    562 void
    563 XRemoveConnectionWatch(
    564     Display* dpy,
    565     XConnectionWatchProc callback,
    566     XPointer client_data
    567 )
    568 {
    569     struct _XConnWatchInfo *watch;
    570     struct _XConnWatchInfo *previous = NULL;
    571     struct _XConnectionInfo *conni;
    572     int counter = 0;
    573 
    574     LockDisplay(dpy);
    575     for (watch=dpy->conn_watchers; watch; watch=watch->next) {
    576 	if (watch->fn == callback  &&  watch->client_data == client_data) {
    577 	    if (previous)
    578 		previous->next = watch->next;
    579 	    else
    580 		dpy->conn_watchers = watch->next;
    581 	    Xfree (watch);
    582 	    dpy->watcher_count--;
    583 	    /* remove our watch_data for each connection */
    584 	    for (conni=dpy->im_fd_info; conni; conni=conni->next) {
    585 		/* don't bother realloc'ing; these arrays are small anyway */
    586 		/* overlapping */
    587 		memmove(conni->watch_data+counter,
    588 			conni->watch_data+counter+1,
    589 			dpy->watcher_count - counter);
    590 	    }
    591 	    break;
    592 	}
    593 	previous = watch;
    594 	counter++;
    595     }
    596     UnlockDisplay(dpy);
    597 }
    598 
    599 /* end of internal connections support */
    600 
    601 /* Cookie jar implementation
    602    dpy->cookiejar is a linked list. _XEnq receives the events but leaves
    603    them in the normal EQ. _XStoreEvent returns the cookie event (minus
    604    data pointer) and adds it to the cookiejar. _XDeq just removes
    605    the entry like any other event but resets the data pointer for
    606    cookie events (to avoid double-free, the memory is re-used by Xlib).
    607 
    608    _XFetchEventCookie (called from XGetEventData) removes a cookie from the
    609    jar. _XFreeEventCookies removes all unclaimed cookies from the jar
    610    (called by XNextEvent).
    611 
    612    _XFreeDisplayStructure calls _XFreeEventCookies for each cookie in the
    613    normal EQ.
    614  */
    615 
    616 #include "utlist.h"
    617 struct stored_event {
    618     XGenericEventCookie ev;
    619     struct stored_event *prev;
    620     struct stored_event *next;
    621 };
    622 
    623 Bool
    624 _XIsEventCookie(Display *dpy, XEvent *ev)
    625 {
    626     return (ev->xcookie.type == GenericEvent &&
    627 	    dpy->generic_event_vec[ev->xcookie.extension & 0x7F] != NULL);
    628 }
    629 
    630 /**
    631  * Free all events in the event list.
    632  */
    633 void
    634 _XFreeEventCookies(Display *dpy)
    635 {
    636     struct stored_event **head, *e, *tmp;
    637 
    638     if (!dpy->cookiejar)
    639         return;
    640 
    641     head = (struct stored_event**)&dpy->cookiejar;
    642 
    643     DL_FOREACH_SAFE(*head, e, tmp) {
    644         XFree(e->ev.data);
    645         XFree(e);
    646     }
    647     dpy->cookiejar = NULL;
    648 }
    649 
    650 /**
    651  * Add an event to the display's event list. This event must be freed on the
    652  * next call to XNextEvent().
    653  */
    654 void
    655 _XStoreEventCookie(Display *dpy, XEvent *event)
    656 {
    657     XGenericEventCookie* cookie = &event->xcookie;
    658     struct stored_event **head, *add;
    659 
    660     if (!_XIsEventCookie(dpy, event))
    661         return;
    662 
    663     head = (struct stored_event**)(&dpy->cookiejar);
    664 
    665     add = Xmalloc(sizeof(struct stored_event));
    666     if (!add) {
    667         ESET(ENOMEM);
    668         _XIOError(dpy);
    669         return;
    670     }
    671     add->ev = *cookie;
    672     DL_APPEND(*head, add);
    673     cookie->data = NULL; /* don't return data yet, must be claimed */
    674 }
    675 
    676 /**
    677  * Return the event with the given cookie and remove it from the list.
    678  */
    679 Bool
    680 _XFetchEventCookie(Display *dpy, XGenericEventCookie* ev)
    681 {
    682     Bool ret = False;
    683     struct stored_event **head, *event;
    684     head = (struct stored_event**)&dpy->cookiejar;
    685 
    686     if (!_XIsEventCookie(dpy, (XEvent*)ev))
    687         return ret;
    688 
    689     DL_FOREACH(*head, event) {
    690         if (event->ev.cookie == ev->cookie &&
    691             event->ev.extension == ev->extension &&
    692             event->ev.evtype == ev->evtype) {
    693             *ev = event->ev;
    694             DL_DELETE(*head, event);
    695             Xfree(event);
    696             ret = True;
    697             break;
    698         }
    699     }
    700 
    701     return ret;
    702 }
    703 
    704 Bool
    705 _XCopyEventCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out)
    706 {
    707     Bool ret = False;
    708     int extension;
    709 
    710     if (!_XIsEventCookie(dpy, (XEvent*)in) || !out)
    711         return ret;
    712 
    713     extension = in->extension & 0x7F;
    714 
    715     if (!dpy->generic_event_copy_vec[extension])
    716         return ret;
    717 
    718     ret = ((*dpy->generic_event_copy_vec[extension])(dpy, in, out));
    719     out->cookie = ret ? ++dpy->next_cookie  : 0;
    720     return ret;
    721 }
    722 
    723 
    724 /*
    725  * _XEnq - Place event packets on the display's queue.
    726  * note that no squishing of move events in V11, since there
    727  * is pointer motion hints....
    728  */
    729 void _XEnq(
    730 	register Display *dpy,
    731 	register xEvent *event)
    732 {
    733 	register _XQEvent *qelt;
    734 	int type, extension;
    735 
    736 	if ((qelt = dpy->qfree)) {
    737 		/* If dpy->qfree is non-NULL do this, else malloc a new one. */
    738 		dpy->qfree = qelt->next;
    739 	}
    740 	else if ((qelt = Xmalloc(sizeof(_XQEvent))) == NULL) {
    741 		/* Malloc call failed! */
    742 		ESET(ENOMEM);
    743 		_XIOError(dpy);
    744 		return;
    745 	}
    746 	qelt->next = NULL;
    747 
    748 	type = event->u.u.type & 0177;
    749 	extension = ((xGenericEvent*)event)->extension;
    750 
    751 	qelt->event.type = type;
    752 	/* If an extension has registered a generic_event_vec handler, then
    753 	 * it can handle event cookies. Otherwise, proceed with the normal
    754 	 * event handlers.
    755 	 *
    756 	 * If the generic_event_vec is called, qelt->event is a event cookie
    757 	 * with the data pointer and the "free" pointer set. Data pointer is
    758 	 * some memory allocated by the extension.
    759 	 */
    760         if (type == GenericEvent && dpy->generic_event_vec[extension & 0x7F]) {
    761 	    XGenericEventCookie *cookie = &qelt->event.xcookie;
    762 	    (*dpy->generic_event_vec[extension & 0x7F])(dpy, cookie, event);
    763 	    cookie->cookie = ++dpy->next_cookie;
    764 
    765 	    qelt->qserial_num = dpy->next_event_serial_num++;
    766 	    if (dpy->tail)	dpy->tail->next = qelt;
    767 	    else		dpy->head = qelt;
    768 
    769 	    dpy->tail = qelt;
    770 	    dpy->qlen++;
    771 	} else if ((*dpy->event_vec[type])(dpy, &qelt->event, event)) {
    772 	    qelt->qserial_num = dpy->next_event_serial_num++;
    773 	    if (dpy->tail)	dpy->tail->next = qelt;
    774 	    else 		dpy->head = qelt;
    775 
    776 	    dpy->tail = qelt;
    777 	    dpy->qlen++;
    778 	} else {
    779 	    /* ignored, or stashed away for many-to-one compression */
    780 	    qelt->next = dpy->qfree;
    781 	    dpy->qfree = qelt;
    782 	}
    783 }
    784 
    785 /*
    786  * _XDeq - Remove event packet from the display's queue.
    787  */
    788 void _XDeq(
    789     register Display *dpy,
    790     register _XQEvent *prev,	/* element before qelt */
    791     register _XQEvent *qelt)	/* element to be unlinked */
    792 {
    793     if (prev) {
    794 	if ((prev->next = qelt->next) == NULL)
    795 	    dpy->tail = prev;
    796     } else {
    797 	/* no prev, so removing first elt */
    798 	if ((dpy->head = qelt->next) == NULL)
    799 	    dpy->tail = NULL;
    800     }
    801     qelt->qserial_num = 0;
    802     qelt->next = dpy->qfree;
    803     dpy->qfree = qelt;
    804     dpy->qlen--;
    805 
    806     if (_XIsEventCookie(dpy, &qelt->event)) {
    807 	XGenericEventCookie* cookie = &qelt->event.xcookie;
    808 	/* dpy->qfree is re-used, reset memory to avoid double free on
    809 	 * _XFreeDisplayStructure */
    810 	cookie->data = NULL;
    811     }
    812 }
    813 
    814 /*
    815  * EventToWire in separate file in that often not needed.
    816  */
    817 
    818 /*ARGSUSED*/
    819 Bool
    820 _XUnknownWireEvent(
    821     register Display *dpy,	/* pointer to display structure */
    822     register XEvent *re,	/* pointer to where event should be reformatted */
    823     register xEvent *event)	/* wire protocol event */
    824 {
    825 #ifdef notdef
    826 	(void) fprintf(stderr,
    827 	    "Xlib: unhandled wire event! event number = %d, display = %x\n.",
    828 			event->u.u.type, dpy);
    829 #endif
    830 	return(False);
    831 }
    832 
    833 Bool
    834 _XUnknownWireEventCookie(
    835     Display *dpy,	/* pointer to display structure */
    836     XGenericEventCookie *re,	/* pointer to where event should be reformatted */
    837     xEvent *event)	/* wire protocol event */
    838 {
    839 #ifdef notdef
    840 	fprintf(stderr,
    841 	    "Xlib: unhandled wire cookie event! extension number = %d, display = %x\n.",
    842 			((xGenericEvent*)event)->extension, dpy);
    843 #endif
    844 	return(False);
    845 }
    846 
    847 Bool
    848 _XUnknownCopyEventCookie(
    849     Display *dpy,	/* pointer to display structure */
    850     XGenericEventCookie *in,	/* source */
    851     XGenericEventCookie *out)	/* destination */
    852 {
    853 #ifdef notdef
    854 	fprintf(stderr,
    855 	    "Xlib: unhandled cookie event copy! extension number = %d, display = %x\n.",
    856 			in->extension, dpy);
    857 #endif
    858 	return(False);
    859 }
    860 
    861 /*ARGSUSED*/
    862 Status
    863 _XUnknownNativeEvent(
    864     register Display *dpy,	/* pointer to display structure */
    865     register XEvent *re,	/* pointer to where event should be reformatted */
    866     register xEvent *event)	/* wire protocol event */
    867 {
    868 #ifdef notdef
    869 	(void) fprintf(stderr,
    870  	   "Xlib: unhandled native event! event number = %d, display = %x\n.",
    871 			re->type, dpy);
    872 #endif
    873 	return(0);
    874 }
    875 /*
    876  * reformat a wire event into an XEvent structure of the right type.
    877  */
    878 Bool
    879 _XWireToEvent(
    880     register Display *dpy,	/* pointer to display structure */
    881     register XEvent *re,	/* pointer to where event should be reformatted */
    882     register xEvent *event)	/* wire protocol event */
    883 {
    884 
    885 	re->type = event->u.u.type & 0x7f;
    886 	((XAnyEvent *)re)->serial = _XSetLastRequestRead(dpy,
    887 					(xGenericReply *)event);
    888 	((XAnyEvent *)re)->send_event = ((event->u.u.type & 0x80) != 0);
    889 	((XAnyEvent *)re)->display = dpy;
    890 
    891 	/* Ignore the leading bit of the event type since it is set when a
    892 		client sends an event rather than the server. */
    893 
    894 	switch (event-> u.u.type & 0177) {
    895 	      case KeyPress:
    896 	      case KeyRelease:
    897 	        {
    898 			register XKeyEvent *ev = (XKeyEvent*) re;
    899 			ev->root 	= event->u.keyButtonPointer.root;
    900 			ev->window 	= event->u.keyButtonPointer.event;
    901 			ev->subwindow 	= event->u.keyButtonPointer.child;
    902 			ev->time 	= event->u.keyButtonPointer.time;
    903 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
    904 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
    905 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
    906 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
    907 			ev->state	= event->u.keyButtonPointer.state;
    908 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
    909 			ev->keycode 	= event->u.u.detail;
    910 		}
    911 	      	break;
    912 	      case ButtonPress:
    913 	      case ButtonRelease:
    914 	        {
    915 			register XButtonEvent *ev =  (XButtonEvent *) re;
    916 			ev->root 	= event->u.keyButtonPointer.root;
    917 			ev->window 	= event->u.keyButtonPointer.event;
    918 			ev->subwindow 	= event->u.keyButtonPointer.child;
    919 			ev->time 	= event->u.keyButtonPointer.time;
    920 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
    921 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
    922 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
    923 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
    924 			ev->state	= event->u.keyButtonPointer.state;
    925 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
    926 			ev->button 	= event->u.u.detail;
    927 		}
    928 	        break;
    929 	      case MotionNotify:
    930 	        {
    931 			register XMotionEvent *ev =   (XMotionEvent *)re;
    932 			ev->root 	= event->u.keyButtonPointer.root;
    933 			ev->window 	= event->u.keyButtonPointer.event;
    934 			ev->subwindow 	= event->u.keyButtonPointer.child;
    935 			ev->time 	= event->u.keyButtonPointer.time;
    936 			ev->x 		= cvtINT16toInt(event->u.keyButtonPointer.eventX);
    937 			ev->y 		= cvtINT16toInt(event->u.keyButtonPointer.eventY);
    938 			ev->x_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootX);
    939 			ev->y_root 	= cvtINT16toInt(event->u.keyButtonPointer.rootY);
    940 			ev->state	= event->u.keyButtonPointer.state;
    941 			ev->same_screen	= event->u.keyButtonPointer.sameScreen;
    942 			ev->is_hint 	= event->u.u.detail;
    943 		}
    944 	        break;
    945 	      case EnterNotify:
    946 	      case LeaveNotify:
    947 		{
    948 			register XCrossingEvent *ev   = (XCrossingEvent *) re;
    949 			ev->root	= event->u.enterLeave.root;
    950 			ev->window	= event->u.enterLeave.event;
    951 			ev->subwindow	= event->u.enterLeave.child;
    952 			ev->time	= event->u.enterLeave.time;
    953 			ev->x		= cvtINT16toInt(event->u.enterLeave.eventX);
    954 			ev->y		= cvtINT16toInt(event->u.enterLeave.eventY);
    955 			ev->x_root	= cvtINT16toInt(event->u.enterLeave.rootX);
    956 			ev->y_root	= cvtINT16toInt(event->u.enterLeave.rootY);
    957 			ev->state	= event->u.enterLeave.state;
    958 			ev->mode	= event->u.enterLeave.mode;
    959 			ev->same_screen = (event->u.enterLeave.flags &
    960 				ELFlagSameScreen) && True;
    961 			ev->focus	= (event->u.enterLeave.flags &
    962 			  	ELFlagFocus) && True;
    963 			ev->detail	= event->u.u.detail;
    964 		}
    965 		  break;
    966 	      case FocusIn:
    967 	      case FocusOut:
    968 		{
    969 			register XFocusChangeEvent *ev = (XFocusChangeEvent *) re;
    970 			ev->window 	= event->u.focus.window;
    971 			ev->mode	= event->u.focus.mode;
    972 			ev->detail	= event->u.u.detail;
    973 		}
    974 		  break;
    975 	      case KeymapNotify:
    976 		{
    977 			register XKeymapEvent *ev = (XKeymapEvent *) re;
    978 			ev->window	= None;
    979 			memcpy(&ev->key_vector[1],
    980 			       (char *)((xKeymapEvent *) event)->map,
    981 			       sizeof (((xKeymapEvent *) event)->map));
    982 		}
    983 		break;
    984 	      case Expose:
    985 		{
    986 			register XExposeEvent *ev = (XExposeEvent *) re;
    987 			ev->window	= event->u.expose.window;
    988 			ev->x		= event->u.expose.x;
    989 			ev->y		= event->u.expose.y;
    990 			ev->width	= event->u.expose.width;
    991 			ev->height	= event->u.expose.height;
    992 			ev->count	= event->u.expose.count;
    993 		}
    994 		break;
    995 	      case GraphicsExpose:
    996 		{
    997 		    register XGraphicsExposeEvent *ev =
    998 			(XGraphicsExposeEvent *) re;
    999 		    ev->drawable	= event->u.graphicsExposure.drawable;
   1000 		    ev->x		= event->u.graphicsExposure.x;
   1001 		    ev->y		= event->u.graphicsExposure.y;
   1002 		    ev->width		= event->u.graphicsExposure.width;
   1003 		    ev->height		= event->u.graphicsExposure.height;
   1004 		    ev->count		= event->u.graphicsExposure.count;
   1005 		    ev->major_code	= event->u.graphicsExposure.majorEvent;
   1006 		    ev->minor_code	= event->u.graphicsExposure.minorEvent;
   1007 		}
   1008 		break;
   1009 	      case NoExpose:
   1010 		{
   1011 		    register XNoExposeEvent *ev = (XNoExposeEvent *) re;
   1012 		    ev->drawable	= event->u.noExposure.drawable;
   1013 		    ev->major_code	= event->u.noExposure.majorEvent;
   1014 		    ev->minor_code	= event->u.noExposure.minorEvent;
   1015 		}
   1016 		break;
   1017 	      case VisibilityNotify:
   1018 		{
   1019 		    register XVisibilityEvent *ev = (XVisibilityEvent *) re;
   1020 		    ev->window		= event->u.visibility.window;
   1021 		    ev->state		= event->u.visibility.state;
   1022 		}
   1023 		break;
   1024 	      case CreateNotify:
   1025 		{
   1026 		    register XCreateWindowEvent *ev =
   1027 			 (XCreateWindowEvent *) re;
   1028 		    ev->window		= event->u.createNotify.window;
   1029 		    ev->parent		= event->u.createNotify.parent;
   1030 		    ev->x		= cvtINT16toInt(event->u.createNotify.x);
   1031 		    ev->y		= cvtINT16toInt(event->u.createNotify.y);
   1032 		    ev->width		= event->u.createNotify.width;
   1033 		    ev->height		= event->u.createNotify.height;
   1034 		    ev->border_width	= event->u.createNotify.borderWidth;
   1035 		    ev->override_redirect	= event->u.createNotify.override;
   1036 		}
   1037 		break;
   1038 	      case DestroyNotify:
   1039 		{
   1040 		    register XDestroyWindowEvent *ev =
   1041 				(XDestroyWindowEvent *) re;
   1042 		    ev->window		= event->u.destroyNotify.window;
   1043 		    ev->event		= event->u.destroyNotify.event;
   1044 		}
   1045 		break;
   1046 	      case UnmapNotify:
   1047 		{
   1048 		    register XUnmapEvent *ev = (XUnmapEvent *) re;
   1049 		    ev->window		= event->u.unmapNotify.window;
   1050 		    ev->event		= event->u.unmapNotify.event;
   1051 		    ev->from_configure	= event->u.unmapNotify.fromConfigure;
   1052 		}
   1053 		break;
   1054 	      case MapNotify:
   1055 		{
   1056 		    register XMapEvent *ev = (XMapEvent *) re;
   1057 		    ev->window		= event->u.mapNotify.window;
   1058 		    ev->event		= event->u.mapNotify.event;
   1059 		    ev->override_redirect	= event->u.mapNotify.override;
   1060 		}
   1061 		break;
   1062 	      case MapRequest:
   1063 		{
   1064 		    register XMapRequestEvent *ev = (XMapRequestEvent *) re;
   1065 		    ev->window		= event->u.mapRequest.window;
   1066 		    ev->parent		= event->u.mapRequest.parent;
   1067 		}
   1068 		break;
   1069 	      case ReparentNotify:
   1070 		{
   1071 		    register XReparentEvent *ev = (XReparentEvent *) re;
   1072 		    ev->event		= event->u.reparent.event;
   1073 		    ev->window		= event->u.reparent.window;
   1074 		    ev->parent		= event->u.reparent.parent;
   1075 		    ev->x		= cvtINT16toInt(event->u.reparent.x);
   1076 		    ev->y		= cvtINT16toInt(event->u.reparent.y);
   1077 		    ev->override_redirect	= event->u.reparent.override;
   1078 		}
   1079 		break;
   1080 	      case ConfigureNotify:
   1081 		{
   1082 		    register XConfigureEvent *ev = (XConfigureEvent *) re;
   1083 		    ev->event	= event->u.configureNotify.event;
   1084 		    ev->window	= event->u.configureNotify.window;
   1085 		    ev->above	= event->u.configureNotify.aboveSibling;
   1086 		    ev->x	= cvtINT16toInt(event->u.configureNotify.x);
   1087 		    ev->y	= cvtINT16toInt(event->u.configureNotify.y);
   1088 		    ev->width	= event->u.configureNotify.width;
   1089 		    ev->height	= event->u.configureNotify.height;
   1090 		    ev->border_width  = event->u.configureNotify.borderWidth;
   1091 		    ev->override_redirect = event->u.configureNotify.override;
   1092 		}
   1093 		break;
   1094 	      case ConfigureRequest:
   1095 		{
   1096 		    register XConfigureRequestEvent *ev =
   1097 		        (XConfigureRequestEvent *) re;
   1098 		    ev->window		= event->u.configureRequest.window;
   1099 		    ev->parent		= event->u.configureRequest.parent;
   1100 		    ev->above		= event->u.configureRequest.sibling;
   1101 		    ev->x		= cvtINT16toInt(event->u.configureRequest.x);
   1102 		    ev->y		= cvtINT16toInt(event->u.configureRequest.y);
   1103 		    ev->width		= event->u.configureRequest.width;
   1104 		    ev->height		= event->u.configureRequest.height;
   1105 		    ev->border_width	= event->u.configureRequest.borderWidth;
   1106 		    ev->value_mask	= event->u.configureRequest.valueMask;
   1107 		    ev->detail  	= event->u.u.detail;
   1108 		}
   1109 		break;
   1110 	      case GravityNotify:
   1111 		{
   1112 		    register XGravityEvent *ev = (XGravityEvent *) re;
   1113 		    ev->window		= event->u.gravity.window;
   1114 		    ev->event		= event->u.gravity.event;
   1115 		    ev->x		= cvtINT16toInt(event->u.gravity.x);
   1116 		    ev->y		= cvtINT16toInt(event->u.gravity.y);
   1117 		}
   1118 		break;
   1119 	      case ResizeRequest:
   1120 		{
   1121 		    register XResizeRequestEvent *ev =
   1122 			(XResizeRequestEvent *) re;
   1123 		    ev->window		= event->u.resizeRequest.window;
   1124 		    ev->width		= event->u.resizeRequest.width;
   1125 		    ev->height		= event->u.resizeRequest.height;
   1126 		}
   1127 		break;
   1128 	      case CirculateNotify:
   1129 		{
   1130 		    register XCirculateEvent *ev = (XCirculateEvent *) re;
   1131 		    ev->window		= event->u.circulate.window;
   1132 		    ev->event		= event->u.circulate.event;
   1133 		    ev->place		= event->u.circulate.place;
   1134 		}
   1135 		break;
   1136 	      case CirculateRequest:
   1137 		{
   1138 		    register XCirculateRequestEvent *ev =
   1139 		        (XCirculateRequestEvent *) re;
   1140 		    ev->window		= event->u.circulate.window;
   1141 		    ev->parent		= event->u.circulate.event;
   1142 		    ev->place		= event->u.circulate.place;
   1143 		}
   1144 		break;
   1145 	      case PropertyNotify:
   1146 		{
   1147 		    register XPropertyEvent *ev = (XPropertyEvent *) re;
   1148 		    ev->window		= event->u.property.window;
   1149 		    ev->atom		= event->u.property.atom;
   1150 		    ev->time		= event->u.property.time;
   1151 		    ev->state		= event->u.property.state;
   1152 		}
   1153 		break;
   1154 	      case SelectionClear:
   1155 		{
   1156 		    register XSelectionClearEvent *ev =
   1157 			 (XSelectionClearEvent *) re;
   1158 		    ev->window		= event->u.selectionClear.window;
   1159 		    ev->selection	= event->u.selectionClear.atom;
   1160 		    ev->time		= event->u.selectionClear.time;
   1161 		}
   1162 		break;
   1163 	      case SelectionRequest:
   1164 		{
   1165 		    register XSelectionRequestEvent *ev =
   1166 		        (XSelectionRequestEvent *) re;
   1167 		    ev->owner		= event->u.selectionRequest.owner;
   1168 		    ev->requestor	= event->u.selectionRequest.requestor;
   1169 		    ev->selection	= event->u.selectionRequest.selection;
   1170 		    ev->target		= event->u.selectionRequest.target;
   1171 		    ev->property	= event->u.selectionRequest.property;
   1172 		    ev->time		= event->u.selectionRequest.time;
   1173 		}
   1174 		break;
   1175 	      case SelectionNotify:
   1176 		{
   1177 		    register XSelectionEvent *ev = (XSelectionEvent *) re;
   1178 		    ev->requestor	= event->u.selectionNotify.requestor;
   1179 		    ev->selection	= event->u.selectionNotify.selection;
   1180 		    ev->target		= event->u.selectionNotify.target;
   1181 		    ev->property	= event->u.selectionNotify.property;
   1182 		    ev->time		= event->u.selectionNotify.time;
   1183 		}
   1184 		break;
   1185 	      case ColormapNotify:
   1186 		{
   1187 		    register XColormapEvent *ev = (XColormapEvent *) re;
   1188 		    ev->window		= event->u.colormap.window;
   1189 		    ev->colormap	= event->u.colormap.colormap;
   1190 		    ev->new		= event->u.colormap.new;
   1191 		    ev->state		= event->u.colormap.state;
   1192 	        }
   1193 		break;
   1194 	      case ClientMessage:
   1195 		{
   1196 		   register int i;
   1197 		   register XClientMessageEvent *ev
   1198 		   			= (XClientMessageEvent *) re;
   1199 		   ev->window		= event->u.clientMessage.window;
   1200 		   ev->format		= event->u.u.detail;
   1201 		   switch (ev->format) {
   1202 			case 8:
   1203 			   ev->message_type = event->u.clientMessage.u.b.type;
   1204 			   for (i = 0; i < 20; i++)
   1205 			     ev->data.b[i] = event->u.clientMessage.u.b.bytes[i];
   1206 			   break;
   1207 			case 16:
   1208 			   ev->message_type = event->u.clientMessage.u.s.type;
   1209 			   ev->data.s[0] = cvtINT16toShort(event->u.clientMessage.u.s.shorts0);
   1210 			   ev->data.s[1] = cvtINT16toShort(event->u.clientMessage.u.s.shorts1);
   1211 			   ev->data.s[2] = cvtINT16toShort(event->u.clientMessage.u.s.shorts2);
   1212 			   ev->data.s[3] = cvtINT16toShort(event->u.clientMessage.u.s.shorts3);
   1213 			   ev->data.s[4] = cvtINT16toShort(event->u.clientMessage.u.s.shorts4);
   1214 			   ev->data.s[5] = cvtINT16toShort(event->u.clientMessage.u.s.shorts5);
   1215 			   ev->data.s[6] = cvtINT16toShort(event->u.clientMessage.u.s.shorts6);
   1216 			   ev->data.s[7] = cvtINT16toShort(event->u.clientMessage.u.s.shorts7);
   1217 			   ev->data.s[8] = cvtINT16toShort(event->u.clientMessage.u.s.shorts8);
   1218 			   ev->data.s[9] = cvtINT16toShort(event->u.clientMessage.u.s.shorts9);
   1219 			   break;
   1220 			case 32:
   1221 			   ev->message_type = event->u.clientMessage.u.l.type;
   1222 			   ev->data.l[0] = cvtINT32toLong(event->u.clientMessage.u.l.longs0);
   1223 			   ev->data.l[1] = cvtINT32toLong(event->u.clientMessage.u.l.longs1);
   1224 			   ev->data.l[2] = cvtINT32toLong(event->u.clientMessage.u.l.longs2);
   1225 			   ev->data.l[3] = cvtINT32toLong(event->u.clientMessage.u.l.longs3);
   1226 			   ev->data.l[4] = cvtINT32toLong(event->u.clientMessage.u.l.longs4);
   1227 			   break;
   1228 			default: /* XXX should never occur */
   1229 				break;
   1230 		    }
   1231 	        }
   1232 		break;
   1233 	      case MappingNotify:
   1234 		{
   1235 		   register XMappingEvent *ev = (XMappingEvent *)re;
   1236 		   ev->window		= 0;
   1237 		   ev->first_keycode 	= event->u.mappingNotify.firstKeyCode;
   1238 		   ev->request 		= event->u.mappingNotify.request;
   1239 		   ev->count 		= event->u.mappingNotify.count;
   1240 		}
   1241 		break;
   1242 	      default:
   1243 		return(_XUnknownWireEvent(dpy, re, event));
   1244 	}
   1245 	return(True);
   1246 }
   1247 
   1248 static int
   1249 SocketBytesReadable(Display *dpy)
   1250 {
   1251     int bytes = 0, last_error;
   1252 #ifdef WIN32
   1253     last_error = WSAGetLastError();
   1254     ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
   1255     WSASetLastError(last_error);
   1256 #else
   1257     last_error = errno;
   1258     ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
   1259     errno = last_error;
   1260 #endif
   1261     return bytes;
   1262 }
   1263 
   1264 _X_NORETURN void _XDefaultIOErrorExit(
   1265 	Display *dpy,
   1266 	void *user_data)
   1267 {
   1268     exit(1);
   1269     /*NOTREACHED*/
   1270 }
   1271 
   1272 /*
   1273  * _XDefaultIOError - Default fatal system error reporting routine.  Called
   1274  * when an X internal system error is encountered.
   1275  */
   1276 _X_NORETURN int _XDefaultIOError(
   1277 	Display *dpy)
   1278 {
   1279 	int killed = ECHECK(EPIPE);
   1280 
   1281 	/*
   1282 	 * If the socket was closed on the far end, the final recvmsg in
   1283 	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
   1284 	 * this to get the more informative error message.
   1285 	 */
   1286 	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
   1287 	    killed = True;
   1288 
   1289 	if (killed) {
   1290 	    fprintf (stderr,
   1291                      "X connection to %s broken (explicit kill or server shutdown).\r\n",
   1292                      DisplayString (dpy));
   1293 	} else {
   1294             fprintf (stderr,
   1295                      "XIO:  fatal IO error %d (%s) on X server \"%s\"\r\n",
   1296 #ifdef WIN32
   1297                       WSAGetLastError(), strerror(WSAGetLastError()),
   1298 #else
   1299                       errno, strerror (errno),
   1300 #endif
   1301                       DisplayString (dpy));
   1302 	    fprintf (stderr,
   1303 		     "      after %lu requests (%lu known processed) with %d events remaining.\r\n",
   1304 		     NextRequest(dpy) - 1, LastKnownRequestProcessed(dpy),
   1305 		     QLength(dpy));
   1306         }
   1307 
   1308 	exit(1);
   1309 	/*NOTREACHED*/
   1310 }
   1311 
   1312 
   1313 static int _XPrintDefaultError(
   1314     Display *dpy,
   1315     XErrorEvent *event,
   1316     FILE *fp)
   1317 {
   1318     char buffer[BUFSIZ];
   1319     char mesg[BUFSIZ];
   1320     char number[32];
   1321     const char *mtype = "XlibMessage";
   1322     register _XExtension *ext = (_XExtension *)NULL;
   1323     _XExtension *bext = (_XExtension *)NULL;
   1324     XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
   1325     XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
   1326     (void) fprintf(fp, "%s:  %s\n  ", mesg, buffer);
   1327     XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
   1328 	mesg, BUFSIZ);
   1329     (void) fprintf(fp, mesg, event->request_code);
   1330     if (event->request_code < 128) {
   1331 	snprintf(number, sizeof(number), "%d", event->request_code);
   1332 	XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
   1333     } else {
   1334 	for (ext = dpy->ext_procs;
   1335 	     ext && (ext->codes.major_opcode != event->request_code);
   1336 	     ext = ext->next)
   1337 	  ;
   1338 	if (ext) {
   1339 	    strncpy(buffer, ext->name, BUFSIZ);
   1340 	    buffer[BUFSIZ - 1] = '\0';
   1341         } else
   1342 	    buffer[0] = '\0';
   1343     }
   1344     (void) fprintf(fp, " (%s)\n", buffer);
   1345     if (event->request_code >= 128) {
   1346 	XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
   1347 			      mesg, BUFSIZ);
   1348 	fputs("  ", fp);
   1349 	(void) fprintf(fp, mesg, event->minor_code);
   1350 	if (ext) {
   1351 	    snprintf(mesg, sizeof(mesg), "%s.%d", ext->name, event->minor_code);
   1352 	    XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
   1353 	    (void) fprintf(fp, " (%s)", buffer);
   1354 	}
   1355 	fputs("\n", fp);
   1356     }
   1357     if (event->error_code >= 128) {
   1358 	/* kludge, try to find the extension that caused it */
   1359 	buffer[0] = '\0';
   1360 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
   1361 	    if (ext->error_string)
   1362 		(*ext->error_string)(dpy, event->error_code, &ext->codes,
   1363 				     buffer, BUFSIZ);
   1364 	    if (buffer[0]) {
   1365 		bext = ext;
   1366 		break;
   1367 	    }
   1368 	    if (ext->codes.first_error &&
   1369 		ext->codes.first_error < (int)event->error_code &&
   1370 		(!bext || ext->codes.first_error > bext->codes.first_error))
   1371 		bext = ext;
   1372 	}
   1373 	if (bext)
   1374 	    snprintf(buffer, sizeof(buffer), "%s.%d", bext->name,
   1375                      event->error_code - bext->codes.first_error);
   1376 	else
   1377 	    strcpy(buffer, "Value");
   1378 	XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
   1379 	if (mesg[0]) {
   1380 	    fputs("  ", fp);
   1381 	    (void) fprintf(fp, mesg, event->resourceid);
   1382 	    fputs("\n", fp);
   1383 	}
   1384 	/* let extensions try to print the values */
   1385 	for (ext = dpy->ext_procs; ext; ext = ext->next) {
   1386 	    if (ext->error_values)
   1387 		(*ext->error_values)(dpy, event, fp);
   1388 	}
   1389     } else if ((event->error_code == BadWindow) ||
   1390 	       (event->error_code == BadPixmap) ||
   1391 	       (event->error_code == BadCursor) ||
   1392 	       (event->error_code == BadFont) ||
   1393 	       (event->error_code == BadDrawable) ||
   1394 	       (event->error_code == BadColor) ||
   1395 	       (event->error_code == BadGC) ||
   1396 	       (event->error_code == BadIDChoice) ||
   1397 	       (event->error_code == BadValue) ||
   1398 	       (event->error_code == BadAtom)) {
   1399 	if (event->error_code == BadValue)
   1400 	    XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
   1401 				  mesg, BUFSIZ);
   1402 	else if (event->error_code == BadAtom)
   1403 	    XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
   1404 				  mesg, BUFSIZ);
   1405 	else
   1406 	    XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
   1407 				  mesg, BUFSIZ);
   1408 	fputs("  ", fp);
   1409 	(void) fprintf(fp, mesg, event->resourceid);
   1410 	fputs("\n", fp);
   1411     }
   1412     XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
   1413 			  mesg, BUFSIZ);
   1414     fputs("  ", fp);
   1415     (void) fprintf(fp, mesg, event->serial);
   1416     XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
   1417 			  mesg, BUFSIZ);
   1418     fputs("\n  ", fp);
   1419     (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
   1420     fputs("\n", fp);
   1421     if (event->error_code == BadImplementation) return 0;
   1422     return 1;
   1423 }
   1424 
   1425 int _XDefaultError(
   1426 	Display *dpy,
   1427 	XErrorEvent *event)
   1428 {
   1429     if (_XPrintDefaultError (dpy, event, stderr) == 0) return 0;
   1430 
   1431     /*
   1432      * Store in dpy flags that the client is exiting on an unhandled XError
   1433      * (pretend it is an IOError, since the application is dying anyway it
   1434      * does not make a difference).
   1435      * This is useful for _XReply not to hang if the application makes Xlib
   1436      * calls in _fini as part of process termination.
   1437      */
   1438     dpy->flags |= XlibDisplayIOError;
   1439 
   1440     exit(1);
   1441     /*NOTREACHED*/
   1442 }
   1443 
   1444 /*ARGSUSED*/
   1445 Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
   1446 {
   1447     return True;
   1448 }
   1449 
   1450 /*
   1451  * _XError - upcall internal or user protocol error handler
   1452  */
   1453 int _XError (
   1454     Display *dpy,
   1455     register xError *rep)
   1456 {
   1457     /*
   1458      * X_Error packet encountered!  We need to unpack the error before
   1459      * giving it to the user.
   1460      */
   1461     XEvent event; /* make it a large event */
   1462     register _XAsyncHandler *async, *next;
   1463 
   1464     event.xerror.serial = _XSetLastRequestRead(dpy, (xGenericReply *)rep);
   1465 
   1466     for (async = dpy->async_handlers; async; async = next) {
   1467 	next = async->next;
   1468 	if ((*async->handler)(dpy, (xReply *)rep,
   1469 			      (char *)rep, SIZEOF(xError), async->data))
   1470 	    return 0;
   1471     }
   1472 
   1473     event.xerror.display = dpy;
   1474     event.xerror.type = X_Error;
   1475     event.xerror.resourceid = rep->resourceID;
   1476     event.xerror.error_code = rep->errorCode;
   1477     event.xerror.request_code = rep->majorCode;
   1478     event.xerror.minor_code = rep->minorCode;
   1479     if (dpy->error_vec &&
   1480 	!(*dpy->error_vec[rep->errorCode])(dpy, &event.xerror, rep))
   1481 	return 0;
   1482     if (_XErrorFunction != NULL) {
   1483 	int rtn_val;
   1484 #ifdef XTHREADS
   1485 	struct _XErrorThreadInfo thread_info = {
   1486 		.error_thread = xthread_self(),
   1487 		.next = dpy->error_threads
   1488 	}, **prev;
   1489 	dpy->error_threads = &thread_info;
   1490 	if (dpy->lock)
   1491 	    (*dpy->lock->user_lock_display)(dpy);
   1492 	UnlockDisplay(dpy);
   1493 #endif
   1494 	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
   1495 #ifdef XTHREADS
   1496 	LockDisplay(dpy);
   1497 	if (dpy->lock)
   1498 	    (*dpy->lock->user_unlock_display)(dpy);
   1499 
   1500 	/* unlink thread_info from the list */
   1501 	for (prev = &dpy->error_threads; *prev != &thread_info; prev = &(*prev)->next)
   1502 		;
   1503 	*prev = thread_info.next;
   1504 #endif
   1505 	return rtn_val;
   1506     } else {
   1507 	return _XDefaultError(dpy, (XErrorEvent *)&event);
   1508     }
   1509 }
   1510 
   1511 /*
   1512  * _XIOError - call user connection error handler and exit
   1513  */
   1514 int
   1515 _XIOError (
   1516     Display *dpy)
   1517 {
   1518     XIOErrorExitHandler exit_handler;
   1519     void *exit_handler_data;
   1520 
   1521     dpy->flags |= XlibDisplayIOError;
   1522 #ifdef WIN32
   1523     errno = WSAGetLastError();
   1524 #endif
   1525 
   1526     /* This assumes that the thread calling exit will call any atexit handlers.
   1527      * If this does not hold, then an alternate solution would involve
   1528      * registering an atexit handler to take over the lock, which would only
   1529      * assume that the same thread calls all the atexit handlers. */
   1530 #ifdef XTHREADS
   1531     if (dpy->lock)
   1532 	(*dpy->lock->user_lock_display)(dpy);
   1533 #endif
   1534     exit_handler = dpy->exit_handler;
   1535     exit_handler_data = dpy->exit_handler_data;
   1536     UnlockDisplay(dpy);
   1537 
   1538     if (_XIOErrorFunction != NULL)
   1539 	(*_XIOErrorFunction)(dpy);
   1540     else
   1541 	_XDefaultIOError(dpy);
   1542 
   1543     exit_handler(dpy, exit_handler_data);
   1544     return 1;
   1545 }
   1546 
   1547 
   1548 /*
   1549  * This routine can be used to (cheaply) get some memory within a single
   1550  * Xlib routine for scratch space.  A single buffer is reused each time
   1551  * if possible.  To be MT safe, you can only call this between a call to
   1552  * GetReq* and a call to Data* or _XSend*, or in a context when the thread
   1553  * is guaranteed to not unlock the display.
   1554  */
   1555 char *_XAllocScratch(
   1556 	register Display *dpy,
   1557 	unsigned long nbytes)
   1558 {
   1559 	if (nbytes > dpy->scratch_length) {
   1560 	    Xfree (dpy->scratch_buffer);
   1561 	    dpy->scratch_buffer = Xmalloc(nbytes);
   1562 	    if (dpy->scratch_buffer)
   1563 		dpy->scratch_length = nbytes;
   1564 	    else dpy->scratch_length = 0;
   1565 	}
   1566 	return (dpy->scratch_buffer);
   1567 }
   1568 
   1569 /*
   1570  * Scratch space allocator you can call any time, multiple times, and be
   1571  * MT safe, but you must hand the buffer back with _XFreeTemp.
   1572  */
   1573 char *_XAllocTemp(
   1574     register Display *dpy,
   1575     unsigned long nbytes)
   1576 {
   1577     char *buf;
   1578 
   1579     buf = _XAllocScratch(dpy, nbytes);
   1580     dpy->scratch_buffer = NULL;
   1581     dpy->scratch_length = 0;
   1582     return buf;
   1583 }
   1584 
   1585 void _XFreeTemp(
   1586     register Display *dpy,
   1587     char *buf,
   1588     unsigned long nbytes)
   1589 {
   1590 
   1591     Xfree(dpy->scratch_buffer);
   1592     dpy->scratch_buffer = buf;
   1593     dpy->scratch_length = nbytes;
   1594 }
   1595 
   1596 /*
   1597  * Given a visual id, find the visual structure for this id on this display.
   1598  */
   1599 Visual *_XVIDtoVisual(
   1600 	Display *dpy,
   1601 	VisualID id)
   1602 {
   1603 	register int i, j, k;
   1604 	register Screen *sp;
   1605 	register Depth *dp;
   1606 	register Visual *vp;
   1607 	for (i = 0; i < dpy->nscreens; i++) {
   1608 		sp = &dpy->screens[i];
   1609 		for (j = 0; j < sp->ndepths; j++) {
   1610 			dp = &sp->depths[j];
   1611 			/* if nvisuals == 0 then visuals will be NULL */
   1612 			for (k = 0; k < dp->nvisuals; k++) {
   1613 				vp = &dp->visuals[k];
   1614 				if (vp->visualid == id) return (vp);
   1615 			}
   1616 		}
   1617 	}
   1618 	return (NULL);
   1619 }
   1620 
   1621 int
   1622 XFree (void *data)
   1623 {
   1624 	Xfree (data);
   1625 	return 1;
   1626 }
   1627 
   1628 #ifdef _XNEEDBCOPYFUNC
   1629 void _Xbcopy(b1, b2, length)
   1630     register char *b1, *b2;
   1631     register length;
   1632 {
   1633     if (b1 < b2) {
   1634 	b2 += length;
   1635 	b1 += length;
   1636 	while (length--)
   1637 	    *--b2 = *--b1;
   1638     } else {
   1639 	while (length--)
   1640 	    *b2++ = *b1++;
   1641     }
   1642 }
   1643 #endif
   1644 
   1645 #ifdef DataRoutineIsProcedure
   1646 void Data(
   1647 	Display *dpy,
   1648 	_Xconst char *data,
   1649 	long len)
   1650 {
   1651 	if (dpy->bufptr + (len) <= dpy->bufmax) {
   1652 		memcpy(dpy->bufptr, data, (int)len);
   1653 		dpy->bufptr += ((len) + 3) & ~3;
   1654 	} else {
   1655 		_XSend(dpy, data, len);
   1656 	}
   1657 }
   1658 #endif /* DataRoutineIsProcedure */
   1659 
   1660 
   1661 #ifdef LONG64
   1662 int
   1663 _XData32(
   1664     Display *dpy,
   1665     _Xconst long *data,
   1666     unsigned len)
   1667 {
   1668     register int *buf;
   1669     register long i;
   1670 
   1671     while (len) {
   1672 	buf = (int *)dpy->bufptr;
   1673 	i = dpy->bufmax - (char *)buf;
   1674 	if (!i) {
   1675 	    _XFlush(dpy);
   1676 	    continue;
   1677 	}
   1678 	if (len < i)
   1679 	    i = len;
   1680 	dpy->bufptr = (char *)buf + i;
   1681 	len -= i;
   1682 	i >>= 2;
   1683 	while (--i >= 0)
   1684 	    *buf++ = *data++;
   1685     }
   1686     return 0;
   1687 }
   1688 #endif /* LONG64 */
   1689 
   1690 
   1691 
   1692 /* Make sure this produces the same string as DefineLocal/DefineSelf in xdm.
   1693  * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
   1694  *
   1695  * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
   1696  *       to have sufficient information for interfacing to the network,
   1697  *       and so, you may be better off using gethostname (if it exists).
   1698  */
   1699 
   1700 #if defined(_POSIX_SOURCE) || defined(SVR4)
   1701 #define NEED_UTSNAME
   1702 #include <sys/utsname.h>
   1703 #else
   1704 #ifdef HAVE_UNISTD_H
   1705 #include <unistd.h>
   1706 #endif
   1707 #endif
   1708 
   1709 /*
   1710  * _XGetHostname - similar to gethostname but allows special processing.
   1711  */
   1712 int _XGetHostname (
   1713     char *buf,
   1714     int maxlen)
   1715 {
   1716     int len;
   1717 
   1718 #ifdef NEED_UTSNAME
   1719     struct utsname name;
   1720 
   1721     if (maxlen <= 0 || buf == NULL)
   1722 	return 0;
   1723 
   1724     uname (&name);
   1725     len = (int) strlen (name.nodename);
   1726     if (len >= maxlen) len = maxlen - 1;
   1727     strncpy (buf, name.nodename, (size_t) len);
   1728     buf[len] = '\0';
   1729 #else
   1730     if (maxlen <= 0 || buf == NULL)
   1731 	return 0;
   1732 
   1733     buf[0] = '\0';
   1734     (void) gethostname (buf, maxlen);
   1735     buf [maxlen - 1] = '\0';
   1736     len = (int) strlen(buf);
   1737 #endif /* NEED_UTSNAME */
   1738     return len;
   1739 }
   1740 
   1741 
   1742 /*
   1743  * _XScreenOfWindow - get the Screen of a given window
   1744  */
   1745 
   1746 Screen *_XScreenOfWindow(Display *dpy, Window w)
   1747 {
   1748     register int i;
   1749     Window root;
   1750     int x, y;				/* dummy variables */
   1751     unsigned int width, height, bw, depth;  /* dummy variables */
   1752 
   1753     if (XGetGeometry (dpy, w, &root, &x, &y, &width, &height,
   1754 		      &bw, &depth) == False) {
   1755 	return NULL;
   1756     }
   1757     for (i = 0; i < ScreenCount (dpy); i++) {	/* find root from list */
   1758 	if (root == RootWindow (dpy, i)) {
   1759 	    return ScreenOfDisplay (dpy, i);
   1760 	}
   1761     }
   1762     return NULL;
   1763 }
   1764 
   1765 
   1766 /*
   1767  * WARNING: This implementation's pre-conditions and post-conditions
   1768  * must remain compatible with the old macro-based implementations of
   1769  * GetReq, GetReqExtra, GetResReq, and GetEmptyReq. The portions of the
   1770  * Display structure affected by those macros are part of libX11's
   1771  * ABI.
   1772  */
   1773 void *_XGetRequest(Display *dpy, CARD8 type, size_t len)
   1774 {
   1775     xReq *req;
   1776 
   1777     if (dpy->bufptr + len > dpy->bufmax)
   1778 	_XFlush(dpy);
   1779     /* Request still too large, so do not allow it to overflow. */
   1780     if (dpy->bufptr + len > dpy->bufmax) {
   1781 	fprintf(stderr,
   1782 		"Xlib: request %d length %zd would exceed buffer size.\n",
   1783 		type, len);
   1784 	/* Changes failure condition from overflow to NULL dereference. */
   1785 	return NULL;
   1786     }
   1787 
   1788     if (len % 4)
   1789 	fprintf(stderr,
   1790 		"Xlib: request %d length %zd not a multiple of 4.\n",
   1791 		type, len);
   1792 
   1793     dpy->last_req = dpy->bufptr;
   1794 
   1795     req = (xReq*)dpy->bufptr;
   1796     *req = (xReq) {
   1797         .reqType = type,
   1798         .data = 0,
   1799         .length = len / 4
   1800     };
   1801     dpy->bufptr += len;
   1802     X_DPY_REQUEST_INCREMENT(dpy);
   1803     return req;
   1804 }
   1805 
   1806 #if defined(WIN32)
   1807 
   1808 /*
   1809  * These functions are intended to be used internally to Xlib only.
   1810  * These functions will always prefix the path with a DOS drive in the
   1811  * form "<drive-letter>:". As such, these functions are only suitable
   1812  * for use by Xlib function that supply a root-based path to some
   1813  * particular file, e.g. <ProjectRoot>/lib/X11/locale/locale.dir will
   1814  * be converted to "C:/usr/X11R6.3/lib/X11/locale/locale.dir".
   1815  */
   1816 
   1817 static int access_file (path, pathbuf, len_pathbuf, pathret)
   1818     char* path;
   1819     char* pathbuf;
   1820     int len_pathbuf;
   1821     char** pathret;
   1822 {
   1823     if (access (path, F_OK) == 0) {
   1824 	if (strlen (path) < len_pathbuf)
   1825 	    *pathret = pathbuf;
   1826 	else
   1827 	    *pathret = Xmalloc (strlen (path) + 1);
   1828 	if (*pathret) {
   1829 	    strcpy (*pathret, path);
   1830 	    return 1;
   1831 	}
   1832     }
   1833     return 0;
   1834 }
   1835 
   1836 static int AccessFile (path, pathbuf, len_pathbuf, pathret)
   1837     char* path;
   1838     char* pathbuf;
   1839     int len_pathbuf;
   1840     char** pathret;
   1841 {
   1842     unsigned long drives;
   1843     int i, len;
   1844     char* drive;
   1845     char buf[MAX_PATH];
   1846     char* bufp;
   1847 
   1848     /* just try the "raw" name first and see if it works */
   1849     if (access_file (path, pathbuf, len_pathbuf, pathret))
   1850 	return 1;
   1851 
   1852     /* try the places set in the environment */
   1853     drive = getenv ("_XBASEDRIVE");
   1854     if (!drive)
   1855 	drive = "C:";
   1856     len = strlen (drive) + strlen (path);
   1857     if (len < MAX_PATH) bufp = buf;
   1858     else bufp = Xmalloc (len + 1);
   1859     strcpy (bufp, drive);
   1860     strcat (bufp, path);
   1861     if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1862 	if (bufp != buf) Xfree (bufp);
   1863 	return 1;
   1864     }
   1865 
   1866     /* one last place to look */
   1867     drive = getenv ("HOMEDRIVE");
   1868     if (drive) {
   1869 	len = strlen (drive) + strlen (path);
   1870 	if (len < MAX_PATH) bufp = buf;
   1871 	else bufp = Xmalloc (len + 1);
   1872 	strcpy (bufp, drive);
   1873 	strcat (bufp, path);
   1874 	if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1875 	    if (bufp != buf) Xfree (bufp);
   1876 	    return 1;
   1877 	}
   1878     }
   1879 
   1880     /* tried everywhere else, go fishing */
   1881 #define C_DRIVE ('C' - 'A')
   1882 #define Z_DRIVE ('Z' - 'A')
   1883     /* does OS/2 (with or with gcc-emx) have getdrives? */
   1884     drives = _getdrives ();
   1885     for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
   1886 	if ((1 << i) & drives) {
   1887 	    len = 2 + strlen (path);
   1888 	    if (len < MAX_PATH) bufp = buf;
   1889 	    else bufp = Xmalloc (len + 1);
   1890 	    *bufp = 'A' + i;
   1891 	    *(bufp + 1) = ':';
   1892 	    *(bufp + 2) = '\0';
   1893 	    strcat (bufp, path);
   1894 	    if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
   1895 		if (bufp != buf) Xfree (bufp);
   1896 		return 1;
   1897 	    }
   1898 	}
   1899     }
   1900     return 0;
   1901 }
   1902 
   1903 int _XOpenFile(path, flags)
   1904     _Xconst char* path;
   1905     int flags;
   1906 {
   1907     char buf[MAX_PATH];
   1908     char* bufp = NULL;
   1909     int ret = -1;
   1910     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1911 
   1912     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1913 	ret = open (bufp, flags);
   1914 
   1915     (void) SetErrorMode (olderror);
   1916 
   1917     if (bufp != buf) Xfree (bufp);
   1918 
   1919     return ret;
   1920 }
   1921 
   1922 int _XOpenFileMode(path, flags, mode)
   1923     _Xconst char* path;
   1924     int flags;
   1925     mode_t mode;
   1926 {
   1927     char buf[MAX_PATH];
   1928     char* bufp = NULL;
   1929     int ret = -1;
   1930     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1931 
   1932     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1933 	ret = open (bufp, flags, mode);
   1934 
   1935     (void) SetErrorMode (olderror);
   1936 
   1937     if (bufp != buf) Xfree (bufp);
   1938 
   1939     return ret;
   1940 }
   1941 
   1942 void* _XFopenFile(path, mode)
   1943     _Xconst char* path;
   1944     _Xconst char* mode;
   1945 {
   1946     char buf[MAX_PATH];
   1947     char* bufp = NULL;
   1948     void* ret = NULL;
   1949     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1950 
   1951     if (AccessFile (path, buf, MAX_PATH, &bufp))
   1952 	ret = fopen (bufp, mode);
   1953 
   1954     (void) SetErrorMode (olderror);
   1955 
   1956     if (bufp != buf) Xfree (bufp);
   1957 
   1958     return ret;
   1959 }
   1960 
   1961 int _XAccessFile(path)
   1962     _Xconst char* path;
   1963 {
   1964     char buf[MAX_PATH];
   1965     char* bufp;
   1966     int ret = -1;
   1967     UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
   1968 
   1969     ret = AccessFile (path, buf, MAX_PATH, &bufp);
   1970 
   1971     (void) SetErrorMode (olderror);
   1972 
   1973     if (bufp != buf) Xfree (bufp);
   1974 
   1975     return ret;
   1976 }
   1977 
   1978 #endif
   1979 
   1980 #ifdef WIN32
   1981 #undef _Xdebug
   1982 int _Xdebug = 0;
   1983 int *_Xdebug_p = &_Xdebug;
   1984 void (**_XCreateMutex_fn_p)(LockInfoPtr) = &_XCreateMutex_fn;
   1985 void (**_XFreeMutex_fn_p)(LockInfoPtr) = &_XFreeMutex_fn;
   1986 void (**_XLockMutex_fn_p)(LockInfoPtr
   1987 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
   1988     , char * /* file */
   1989     , int /* line */
   1990 #endif
   1991         ) = &_XLockMutex_fn;
   1992 void (**_XUnlockMutex_fn_p)(LockInfoPtr
   1993 #if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
   1994     , char * /* file */
   1995     , int /* line */
   1996 #endif
   1997         ) = &_XUnlockMutex_fn;
   1998 LockInfoPtr *_Xglobal_lock_p = &_Xglobal_lock;
   1999 #endif
   2000